1/*
2 * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
3 * Copyright (C) 2012 Intel Corporation. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "WebPageProxy.h"
29
30#include "AuthenticationChallengeProxy.h"
31#include "AuthenticationDecisionListener.h"
32#include "DataReference.h"
33#include "DownloadProxy.h"
34#include "DrawingAreaProxy.h"
35#include "DrawingAreaProxyMessages.h"
36#include "EventDispatcherMessages.h"
37#include "FindIndicator.h"
38#include "ImmutableArray.h"
39#include "Logging.h"
40#include "NativeWebKeyboardEvent.h"
41#include "NativeWebMouseEvent.h"
42#include "NativeWebWheelEvent.h"
43#include "NotificationPermissionRequest.h"
44#include "NotificationPermissionRequestManager.h"
45#include "PageClient.h"
46#include "PluginInformation.h"
47#include "PluginProcessManager.h"
48#include "PrintInfo.h"
49#include "SessionState.h"
50#include "TextChecker.h"
51#include "TextCheckerState.h"
52#include "WKContextPrivate.h"
53#include "WebBackForwardList.h"
54#include "WebBackForwardListItem.h"
55#include "WebCertificateInfo.h"
56#include "WebColorPickerResultListenerProxy.h"
57#include "WebContext.h"
58#include "WebContextMenuProxy.h"
59#include "WebContextUserMessageCoders.h"
60#include "WebCoreArgumentCoders.h"
61#include "WebData.h"
62#include "WebEditCommandProxy.h"
63#include "WebEvent.h"
64#include "WebFormSubmissionListenerProxy.h"
65#include "WebFramePolicyListenerProxy.h"
66#include "WebFullScreenManagerProxy.h"
67#include "WebFullScreenManagerProxyMessages.h"
68#include "WebInspectorProxy.h"
69#include "WebInspectorProxyMessages.h"
70#include "WebNotificationManagerProxy.h"
71#include "WebOpenPanelResultListenerProxy.h"
72#include "WebPageCreationParameters.h"
73#include "WebPageGroup.h"
74#include "WebPageGroupData.h"
75#include "WebPageMessages.h"
76#include "WebPageProxyMessages.h"
77#include "WebPopupItem.h"
78#include "WebPopupMenuProxy.h"
79#include "WebPreferences.h"
80#include "WebProcessMessages.h"
81#include "WebProcessProxy.h"
82#include "WebProtectionSpace.h"
83#include "WebSecurityOrigin.h"
84#include "WebURLRequest.h"
85#include <WebCore/DragController.h>
86#include <WebCore/DragData.h>
87#include <WebCore/DragSession.h>
88#include <WebCore/FloatRect.h>
89#include <WebCore/FocusDirection.h>
90#include <WebCore/MIMETypeRegistry.h>
91#include <WebCore/RenderEmbeddedObject.h>
92#include <WebCore/TextCheckerClient.h>
93#include <WebCore/WindowFeatures.h>
94#include <stdio.h>
95
96#if USE(COORDINATED_GRAPHICS)
97#include "CoordinatedLayerTreeHostProxyMessages.h"
98#endif
99
100#if PLATFORM(QT)
101#include "ArgumentCodersQt.h"
102#endif
103
104#if PLATFORM(GTK)
105#include "ArgumentCodersGtk.h"
106#endif
107
108#if USE(SOUP)
109#include "WebSoupRequestManagerProxy.h"
110#endif
111
112#if ENABLE(VIBRATION)
113#include "WebVibrationProxy.h"
114#endif
115
116#ifndef NDEBUG
117#include <wtf/RefCountedLeakCounter.h>
118#endif
119
120// This controls what strategy we use for mouse wheel coalescing.
121#define MERGE_WHEEL_EVENTS 1
122
123#define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, m_process->connection())
124#define MESSAGE_CHECK_URL(url) MESSAGE_CHECK_BASE(m_process->checkURLReceivedFromWebProcess(url), m_process->connection())
125
126using namespace WebCore;
127
128// Represents the number of wheel events we can hold in the queue before we start pushing them preemptively.
129static const unsigned wheelEventQueueSizeThreshold = 10;
130
131namespace WebKit {
132
133WKPageDebugPaintFlags WebPageProxy::s_debugPaintFlags = 0;
134
135DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageProxyCounter, ("WebPageProxy"));
136
137class ExceededDatabaseQuotaRecords {
138    WTF_MAKE_NONCOPYABLE(ExceededDatabaseQuotaRecords); WTF_MAKE_FAST_ALLOCATED;
139public:
140    struct Record {
141        uint64_t frameID;
142        String originIdentifier;
143        String databaseName;
144        String displayName;
145        uint64_t currentQuota;
146        uint64_t currentOriginUsage;
147        uint64_t currentDatabaseUsage;
148        uint64_t expectedUsage;
149        RefPtr<Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply> reply;
150    };
151
152    static ExceededDatabaseQuotaRecords& shared();
153
154    PassOwnPtr<Record> createRecord(uint64_t frameID, String originIdentifier,
155        String databaseName, String displayName, uint64_t currentQuota,
156        uint64_t currentOriginUsage, uint64_t currentDatabaseUsage, uint64_t expectedUsage,
157        PassRefPtr<Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply>);
158
159    void add(PassOwnPtr<Record>);
160    bool areBeingProcessed() const { return m_currentRecord; }
161    Record* next();
162
163private:
164    ExceededDatabaseQuotaRecords() { }
165    ~ExceededDatabaseQuotaRecords() { }
166
167    Deque<OwnPtr<Record>> m_records;
168    OwnPtr<Record> m_currentRecord;
169};
170
171ExceededDatabaseQuotaRecords& ExceededDatabaseQuotaRecords::shared()
172{
173    DEFINE_STATIC_LOCAL(ExceededDatabaseQuotaRecords, records, ());
174    return records;
175}
176
177PassOwnPtr<ExceededDatabaseQuotaRecords::Record> ExceededDatabaseQuotaRecords::createRecord(
178    uint64_t frameID, String originIdentifier, String databaseName, String displayName,
179    uint64_t currentQuota, uint64_t currentOriginUsage, uint64_t currentDatabaseUsage,
180    uint64_t expectedUsage, PassRefPtr<Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply> reply)
181{
182    OwnPtr<Record> record = adoptPtr(new Record);
183    record->frameID = frameID;
184    record->originIdentifier = originIdentifier;
185    record->databaseName = databaseName;
186    record->displayName = displayName;
187    record->currentQuota = currentQuota;
188    record->currentOriginUsage = currentOriginUsage;
189    record->currentDatabaseUsage = currentDatabaseUsage;
190    record->expectedUsage = expectedUsage;
191    record->reply = reply;
192    return record.release();
193}
194
195void ExceededDatabaseQuotaRecords::add(PassOwnPtr<ExceededDatabaseQuotaRecords::Record> record)
196{
197    m_records.append(record);
198}
199
200ExceededDatabaseQuotaRecords::Record* ExceededDatabaseQuotaRecords::next()
201{
202    m_currentRecord.clear();
203    if (!m_records.isEmpty())
204        m_currentRecord = m_records.takeFirst();
205    return m_currentRecord.get();
206}
207
208#if !LOG_DISABLED
209static const char* webKeyboardEventTypeString(WebEvent::Type type)
210{
211    switch (type) {
212    case WebEvent::KeyDown:
213        return "KeyDown";
214
215    case WebEvent::KeyUp:
216        return "KeyUp";
217
218    case WebEvent::RawKeyDown:
219        return "RawKeyDown";
220
221    case WebEvent::Char:
222        return "Char";
223
224    default:
225        ASSERT_NOT_REACHED();
226        return "<unknown>";
227    }
228}
229#endif // !LOG_DISABLED
230
231PassRefPtr<WebPageProxy> WebPageProxy::create(PageClient* pageClient, PassRefPtr<WebProcessProxy> process, WebPageGroup* pageGroup, uint64_t pageID)
232{
233    return adoptRef(new WebPageProxy(pageClient, process, pageGroup, pageID));
234}
235
236WebPageProxy::WebPageProxy(PageClient* pageClient, PassRefPtr<WebProcessProxy> process, WebPageGroup* pageGroup, uint64_t pageID)
237    : m_pageClient(pageClient)
238    , m_process(process)
239    , m_pageGroup(pageGroup)
240    , m_mainFrame(0)
241    , m_userAgent(standardUserAgent())
242    , m_geolocationPermissionRequestManager(this)
243    , m_notificationPermissionRequestManager(this)
244    , m_estimatedProgress(0)
245    , m_isInWindow(m_pageClient->isViewInWindow())
246    , m_isVisible(m_pageClient->isViewVisible())
247    , m_backForwardList(WebBackForwardList::create(this))
248    , m_loadStateAtProcessExit(WebFrameProxy::LoadStateFinished)
249    , m_temporarilyClosedComposition(false)
250    , m_textZoomFactor(1)
251    , m_pageZoomFactor(1)
252    , m_pageScaleFactor(1)
253    , m_intrinsicDeviceScaleFactor(1)
254    , m_customDeviceScaleFactor(0)
255#if HAVE(LAYER_HOSTING_IN_WINDOW_SERVER)
256    , m_layerHostingMode(LayerHostingModeInWindowServer)
257#else
258    , m_layerHostingMode(LayerHostingModeDefault)
259#endif
260    , m_drawsBackground(true)
261    , m_drawsTransparentBackground(false)
262    , m_areMemoryCacheClientCallsEnabled(true)
263    , m_useFixedLayout(false)
264    , m_suppressScrollbarAnimations(false)
265    , m_paginationMode(Pagination::Unpaginated)
266    , m_paginationBehavesLikeColumns(false)
267    , m_pageLength(0)
268    , m_gapBetweenPages(0)
269    , m_isValid(true)
270    , m_isClosed(false)
271    , m_canRunModal(false)
272    , m_isInPrintingMode(false)
273    , m_isPerformingDOMPrintOperation(false)
274    , m_inDecidePolicyForResponseSync(false)
275    , m_decidePolicyForResponseRequest(0)
276    , m_syncMimeTypePolicyActionIsValid(false)
277    , m_syncMimeTypePolicyAction(PolicyUse)
278    , m_syncMimeTypePolicyDownloadID(0)
279    , m_inDecidePolicyForNavigationAction(false)
280    , m_syncNavigationActionPolicyActionIsValid(false)
281    , m_syncNavigationActionPolicyAction(PolicyUse)
282    , m_syncNavigationActionPolicyDownloadID(0)
283    , m_processingMouseMoveEvent(false)
284#if ENABLE(TOUCH_EVENTS)
285    , m_needTouchEvents(false)
286#endif
287    , m_pageID(pageID)
288    , m_isPageSuspended(false)
289#if PLATFORM(MAC)
290    , m_isSmartInsertDeleteEnabled(TextChecker::isSmartInsertDeleteEnabled())
291#endif
292    , m_spellDocumentTag(0)
293    , m_hasSpellDocumentTag(false)
294    , m_pendingLearnOrIgnoreWordMessageCount(0)
295    , m_mainFrameHasCustomRepresentation(false)
296    , m_mainFrameHasHorizontalScrollbar(false)
297    , m_mainFrameHasVerticalScrollbar(false)
298    , m_canShortCircuitHorizontalWheelEvents(true)
299    , m_mainFrameIsPinnedToLeftSide(false)
300    , m_mainFrameIsPinnedToRightSide(false)
301    , m_mainFrameIsPinnedToTopSide(false)
302    , m_mainFrameIsPinnedToBottomSide(false)
303    , m_rubberBandsAtBottom(false)
304    , m_rubberBandsAtTop(false)
305    , m_mainFrameInViewSourceMode(false)
306    , m_pageCount(0)
307    , m_renderTreeSize(0)
308    , m_shouldSendEventsSynchronously(false)
309    , m_suppressVisibilityUpdates(false)
310    , m_autoSizingShouldExpandToViewHeight(false)
311    , m_mediaVolume(1)
312    , m_mayStartMediaWhenInWindow(true)
313    , m_waitingForDidUpdateInWindowState(false)
314#if PLATFORM(MAC)
315    , m_exposedRectChangedTimer(this, &WebPageProxy::exposedRectChangedTimerFired)
316    , m_clipsToExposedRect(false)
317    , m_lastSentClipsToExposedRect(false)
318#endif
319#if ENABLE(PAGE_VISIBILITY_API)
320    , m_visibilityState(PageVisibilityStateVisible)
321#endif
322    , m_scrollPinningBehavior(DoNotPin)
323{
324#if ENABLE(PAGE_VISIBILITY_API)
325    if (!m_isVisible)
326        m_visibilityState = PageVisibilityStateHidden;
327#endif
328#ifndef NDEBUG
329    webPageProxyCounter.increment();
330#endif
331
332    WebContext::statistics().wkPageCount++;
333
334    m_pageGroup->addPage(this);
335
336#if ENABLE(INSPECTOR)
337    m_inspector = WebInspectorProxy::create(this);
338#endif
339#if ENABLE(FULLSCREEN_API)
340    m_fullScreenManager = WebFullScreenManagerProxy::create(this);
341#endif
342#if ENABLE(VIBRATION)
343    m_vibration = WebVibrationProxy::create(this);
344#endif
345#if ENABLE(THREADED_SCROLLING)
346    m_rubberBandsAtBottom = true;
347    m_rubberBandsAtTop = true;
348#endif
349
350    m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, this);
351
352    // FIXME: If we ever expose the session storage size as a preference, we need to pass it here.
353    m_process->context()->storageManager().createSessionStorageNamespace(m_pageID, m_process->isValid() ? m_process->connection() : 0, std::numeric_limits<unsigned>::max());
354}
355
356WebPageProxy::~WebPageProxy()
357{
358    if (!m_isClosed)
359        close();
360
361    WebContext::statistics().wkPageCount--;
362
363    if (m_hasSpellDocumentTag)
364        TextChecker::closeSpellDocumentWithTag(m_spellDocumentTag);
365
366    m_pageGroup->removePage(this);
367
368#ifndef NDEBUG
369    webPageProxyCounter.decrement();
370#endif
371}
372
373WebProcessProxy* WebPageProxy::process() const
374{
375    return m_process.get();
376}
377
378PlatformProcessIdentifier WebPageProxy::processIdentifier() const
379{
380    if (m_isClosed)
381        return 0;
382
383    return m_process->processIdentifier();
384}
385
386bool WebPageProxy::isValid() const
387{
388    // A page that has been explicitly closed is never valid.
389    if (m_isClosed)
390        return false;
391
392    return m_isValid;
393}
394
395PassRefPtr<ImmutableArray> WebPageProxy::relatedPages() const
396{
397    // pages() returns a list of pages in WebProcess, so this page may or may not be among them - a client can use a reference to WebPageProxy after the page has closed.
398    Vector<WebPageProxy*> pages = m_process->pages();
399
400    Vector<RefPtr<APIObject>> result;
401    result.reserveCapacity(pages.size());
402    for (size_t i = 0; i < pages.size(); ++i) {
403        if (pages[i] != this)
404            result.append(pages[i]);
405    }
406
407    return ImmutableArray::adopt(result);
408}
409
410void WebPageProxy::initializeLoaderClient(const WKPageLoaderClient* loadClient)
411{
412    m_loaderClient.initialize(loadClient);
413
414    if (!loadClient)
415        return;
416
417    // It would be nice to get rid of this code and transition all clients to using didLayout instead of
418    // didFirstLayoutInFrame and didFirstVisuallyNonEmptyLayoutInFrame. In the meantime, this is required
419    // for backwards compatibility.
420    WebCore::LayoutMilestones milestones = 0;
421    if (loadClient->didFirstLayoutForFrame)
422        milestones |= WebCore::DidFirstLayout;
423    if (loadClient->didFirstVisuallyNonEmptyLayoutForFrame)
424        milestones |= WebCore::DidFirstVisuallyNonEmptyLayout;
425    if (loadClient->didNewFirstVisuallyNonEmptyLayout)
426        milestones |= WebCore::DidHitRelevantRepaintedObjectsAreaThreshold;
427
428    if (milestones)
429        m_process->send(Messages::WebPage::ListenForLayoutMilestones(milestones), m_pageID);
430
431    m_process->send(Messages::WebPage::SetWillGoToBackForwardItemCallbackEnabled(loadClient->version > 0), m_pageID);
432}
433
434void WebPageProxy::initializePolicyClient(const WKPagePolicyClient* policyClient)
435{
436    m_policyClient.initialize(policyClient);
437}
438
439void WebPageProxy::initializeFormClient(const WKPageFormClient* formClient)
440{
441    m_formClient.initialize(formClient);
442}
443
444void WebPageProxy::initializeUIClient(const WKPageUIClient* client)
445{
446    if (!isValid())
447        return;
448
449    m_uiClient.initialize(client);
450
451    m_process->send(Messages::WebPage::SetCanRunBeforeUnloadConfirmPanel(m_uiClient.canRunBeforeUnloadConfirmPanel()), m_pageID);
452    setCanRunModal(m_uiClient.canRunModal());
453}
454
455void WebPageProxy::initializeFindClient(const WKPageFindClient* client)
456{
457    m_findClient.initialize(client);
458}
459
460void WebPageProxy::initializeFindMatchesClient(const WKPageFindMatchesClient* client)
461{
462    m_findMatchesClient.initialize(client);
463}
464
465#if ENABLE(CONTEXT_MENUS)
466void WebPageProxy::initializeContextMenuClient(const WKPageContextMenuClient* client)
467{
468    m_contextMenuClient.initialize(client);
469}
470#endif
471
472void WebPageProxy::reattachToWebProcess()
473{
474    ASSERT(!isValid());
475    ASSERT(m_process);
476    ASSERT(!m_process->isValid());
477    ASSERT(!m_process->isLaunching());
478
479    m_isValid = true;
480
481    if (m_process->context()->processModel() == ProcessModelSharedSecondaryProcess)
482        m_process = m_process->context()->ensureSharedWebProcess();
483    else
484        m_process = m_process->context()->createNewWebProcessRespectingProcessCountLimit();
485    m_process->addExistingWebPage(this, m_pageID);
486    m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, this);
487
488#if ENABLE(INSPECTOR)
489    m_inspector = WebInspectorProxy::create(this);
490#endif
491#if ENABLE(FULLSCREEN_API)
492    m_fullScreenManager = WebFullScreenManagerProxy::create(this);
493#endif
494
495    initializeWebPage();
496
497    m_pageClient->didRelaunchProcess();
498    m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
499}
500
501void WebPageProxy::reattachToWebProcessWithItem(WebBackForwardListItem* item)
502{
503    if (item && item != m_backForwardList->currentItem())
504        m_backForwardList->goToItem(item);
505
506    reattachToWebProcess();
507
508    if (!item)
509        return;
510
511    m_process->send(Messages::WebPage::GoToBackForwardItem(item->itemID()), m_pageID);
512    m_process->responsivenessTimer()->start();
513}
514
515void WebPageProxy::initializeWebPage()
516{
517    ASSERT(isValid());
518
519    BackForwardListItemVector items = m_backForwardList->entries();
520    for (size_t i = 0; i < items.size(); ++i)
521        m_process->registerNewWebBackForwardListItem(items[i].get());
522
523    m_drawingArea = m_pageClient->createDrawingAreaProxy();
524    ASSERT(m_drawingArea);
525
526#if ENABLE(INSPECTOR_SERVER)
527    if (m_pageGroup->preferences()->developerExtrasEnabled())
528        inspector()->enableRemoteInspection();
529#endif
530
531    m_process->send(Messages::WebProcess::CreateWebPage(m_pageID, creationParameters()), 0);
532
533#if ENABLE(PAGE_VISIBILITY_API)
534    m_process->send(Messages::WebPage::SetVisibilityState(m_visibilityState, /* isInitialState */ true), m_pageID);
535#elif ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
536    m_process->send(Messages::WebPage::SetVisibilityState(m_isVisible ? PageVisibilityStateVisible : PageVisibilityStateHidden, /* isInitialState */ true), m_pageID);
537#endif
538
539#if PLATFORM(MAC)
540    m_process->send(Messages::WebPage::SetSmartInsertDeleteEnabled(m_isSmartInsertDeleteEnabled), m_pageID);
541#endif
542}
543
544void WebPageProxy::close()
545{
546    if (!isValid())
547        return;
548
549    m_isClosed = true;
550
551    m_backForwardList->pageClosed();
552    m_pageClient->pageClosed();
553
554    m_process->disconnectFramesFromPage(this);
555    m_mainFrame = 0;
556
557#if ENABLE(INSPECTOR)
558    if (m_inspector) {
559        m_inspector->invalidate();
560        m_inspector = 0;
561    }
562#endif
563
564#if ENABLE(FULLSCREEN_API)
565    if (m_fullScreenManager) {
566        m_fullScreenManager->invalidate();
567        m_fullScreenManager = 0;
568    }
569#endif
570
571#if ENABLE(VIBRATION)
572    m_vibration->invalidate();
573#endif
574
575    if (m_openPanelResultListener) {
576        m_openPanelResultListener->invalidate();
577        m_openPanelResultListener = 0;
578    }
579
580#if ENABLE(INPUT_TYPE_COLOR)
581    if (m_colorChooser) {
582        m_colorChooser->invalidate();
583        m_colorChooser = nullptr;
584    }
585
586    if (m_colorPickerResultListener) {
587        m_colorPickerResultListener->invalidate();
588        m_colorPickerResultListener = nullptr;
589    }
590#endif
591
592#if ENABLE(GEOLOCATION)
593    m_geolocationPermissionRequestManager.invalidateRequests();
594#endif
595
596    m_notificationPermissionRequestManager.invalidateRequests();
597    m_process->context()->supplement<WebNotificationManagerProxy>()->clearNotifications(this);
598
599    m_toolTip = String();
600
601    m_mainFrameHasHorizontalScrollbar = false;
602    m_mainFrameHasVerticalScrollbar = false;
603
604    m_mainFrameIsPinnedToLeftSide = false;
605    m_mainFrameIsPinnedToRightSide = false;
606    m_mainFrameIsPinnedToTopSide = false;
607    m_mainFrameIsPinnedToBottomSide = false;
608
609    m_visibleScrollerThumbRect = IntRect();
610
611    invalidateCallbackMap(m_voidCallbacks);
612    invalidateCallbackMap(m_dataCallbacks);
613    invalidateCallbackMap(m_imageCallbacks);
614    invalidateCallbackMap(m_stringCallbacks);
615    m_loadDependentStringCallbackIDs.clear();
616    invalidateCallbackMap(m_scriptValueCallbacks);
617    invalidateCallbackMap(m_computedPagesCallbacks);
618#if PLATFORM(GTK)
619    invalidateCallbackMap(m_printFinishedCallbacks);
620#endif
621
622    Vector<WebEditCommandProxy*> editCommandVector;
623    copyToVector(m_editCommandSet, editCommandVector);
624    m_editCommandSet.clear();
625    for (size_t i = 0, size = editCommandVector.size(); i < size; ++i)
626        editCommandVector[i]->invalidate();
627
628    m_activePopupMenu = 0;
629
630    m_estimatedProgress = 0.0;
631
632    m_loaderClient.initialize(0);
633    m_policyClient.initialize(0);
634    m_uiClient.initialize(0);
635#if PLATFORM(EFL)
636    m_uiPopupMenuClient.initialize(0);
637#endif
638
639    m_drawingArea = nullptr;
640
641#if PLATFORM(MAC)
642    m_exposedRectChangedTimer.stop();
643#endif
644
645    m_process->send(Messages::WebPage::Close(), m_pageID);
646    m_process->removeWebPage(m_pageID);
647    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
648    m_process->context()->storageManager().destroySessionStorageNamespace(m_pageID);
649}
650
651bool WebPageProxy::tryClose()
652{
653    if (!isValid())
654        return true;
655
656    m_process->send(Messages::WebPage::TryClose(), m_pageID);
657    m_process->responsivenessTimer()->start();
658    return false;
659}
660
661bool WebPageProxy::maybeInitializeSandboxExtensionHandle(const KURL& url, SandboxExtension::Handle& sandboxExtensionHandle)
662{
663    if (!url.isLocalFile())
664        return false;
665
666    if (m_process->hasAssumedReadAccessToURL(url))
667        return false;
668
669#if ENABLE(INSPECTOR)
670    // Inspector resources are in a directory with assumed access.
671    ASSERT_WITH_SECURITY_IMPLICATION(!WebInspectorProxy::isInspectorPage(this));
672#endif
673
674    SandboxExtension::createHandle("/", SandboxExtension::ReadOnly, sandboxExtensionHandle);
675    return true;
676}
677
678void WebPageProxy::loadURL(const String& url, APIObject* userData)
679{
680    setPendingAPIRequestURL(url);
681
682    if (!isValid())
683        reattachToWebProcess();
684
685    SandboxExtension::Handle sandboxExtensionHandle;
686    bool createdExtension = maybeInitializeSandboxExtensionHandle(KURL(KURL(), url), sandboxExtensionHandle);
687    if (createdExtension)
688        m_process->willAcquireUniversalFileReadSandboxExtension();
689    m_process->send(Messages::WebPage::LoadURL(url, sandboxExtensionHandle, WebContextUserMessageEncoder(userData)), m_pageID);
690    m_process->responsivenessTimer()->start();
691}
692
693void WebPageProxy::loadURLRequest(WebURLRequest* urlRequest, APIObject* userData)
694{
695    setPendingAPIRequestURL(urlRequest->resourceRequest().url());
696
697    if (!isValid())
698        reattachToWebProcess();
699
700    SandboxExtension::Handle sandboxExtensionHandle;
701    bool createdExtension = maybeInitializeSandboxExtensionHandle(urlRequest->resourceRequest().url(), sandboxExtensionHandle);
702    if (createdExtension)
703        m_process->willAcquireUniversalFileReadSandboxExtension();
704    m_process->send(Messages::WebPage::LoadURLRequest(urlRequest->resourceRequest(), sandboxExtensionHandle, WebContextUserMessageEncoder(userData)), m_pageID);
705    m_process->responsivenessTimer()->start();
706}
707
708void WebPageProxy::loadFile(const String& fileURLString, const String& resourceDirectoryURLString, APIObject* userData)
709{
710    if (!isValid())
711        reattachToWebProcess();
712
713    KURL fileURL = KURL(KURL(), fileURLString);
714    if (!fileURL.isLocalFile())
715        return;
716
717    KURL resourceDirectoryURL;
718    if (resourceDirectoryURLString.isNull())
719        resourceDirectoryURL = KURL(ParsedURLString, ASCIILiteral("file:///"));
720    else {
721        resourceDirectoryURL = KURL(KURL(), resourceDirectoryURLString);
722        if (!resourceDirectoryURL.isLocalFile())
723            return;
724    }
725
726    String resourceDirectoryPath = resourceDirectoryURL.fileSystemPath();
727
728    SandboxExtension::Handle sandboxExtensionHandle;
729    SandboxExtension::createHandle(resourceDirectoryPath, SandboxExtension::ReadOnly, sandboxExtensionHandle);
730    m_process->assumeReadAccessToBaseURL(resourceDirectoryURL);
731    m_process->send(Messages::WebPage::LoadURL(fileURL, sandboxExtensionHandle, WebContextUserMessageEncoder(userData)), m_pageID);
732    m_process->responsivenessTimer()->start();
733}
734
735void WebPageProxy::loadData(WebData* data, const String& MIMEType, const String& encoding, const String& baseURL, APIObject* userData)
736{
737    if (!isValid())
738        reattachToWebProcess();
739
740    m_process->assumeReadAccessToBaseURL(baseURL);
741    m_process->send(Messages::WebPage::LoadData(data->dataReference(), MIMEType, encoding, baseURL, WebContextUserMessageEncoder(userData)), m_pageID);
742    m_process->responsivenessTimer()->start();
743}
744
745void WebPageProxy::loadHTMLString(const String& htmlString, const String& baseURL, APIObject* userData)
746{
747    if (!isValid())
748        reattachToWebProcess();
749
750    m_process->assumeReadAccessToBaseURL(baseURL);
751    m_process->send(Messages::WebPage::LoadHTMLString(htmlString, baseURL, WebContextUserMessageEncoder(userData)), m_pageID);
752    m_process->responsivenessTimer()->start();
753}
754
755void WebPageProxy::loadAlternateHTMLString(const String& htmlString, const String& baseURL, const String& unreachableURL, APIObject* userData)
756{
757    if (!isValid())
758        reattachToWebProcess();
759
760    if (m_mainFrame)
761        m_mainFrame->setUnreachableURL(unreachableURL);
762
763    m_process->assumeReadAccessToBaseURL(baseURL);
764    m_process->send(Messages::WebPage::LoadAlternateHTMLString(htmlString, baseURL, unreachableURL, WebContextUserMessageEncoder(userData)), m_pageID);
765    m_process->responsivenessTimer()->start();
766}
767
768void WebPageProxy::loadPlainTextString(const String& string, APIObject* userData)
769{
770    if (!isValid())
771        reattachToWebProcess();
772
773    m_process->send(Messages::WebPage::LoadPlainTextString(string, WebContextUserMessageEncoder(userData)), m_pageID);
774    m_process->responsivenessTimer()->start();
775}
776
777void WebPageProxy::loadWebArchiveData(const WebData* webArchiveData, APIObject* userData)
778{
779    if (!isValid())
780        reattachToWebProcess();
781
782    m_process->send(Messages::WebPage::LoadWebArchiveData(webArchiveData->dataReference(), WebContextUserMessageEncoder(userData)), m_pageID);
783    m_process->responsivenessTimer()->start();
784}
785
786void WebPageProxy::stopLoading()
787{
788    if (!isValid())
789        return;
790
791    m_process->send(Messages::WebPage::StopLoading(), m_pageID);
792    m_process->responsivenessTimer()->start();
793}
794
795void WebPageProxy::reload(bool reloadFromOrigin)
796{
797    SandboxExtension::Handle sandboxExtensionHandle;
798
799    if (m_backForwardList->currentItem()) {
800        String url = m_backForwardList->currentItem()->url();
801        setPendingAPIRequestURL(url);
802
803        // We may not have an extension yet if back/forward list was reinstated after a WebProcess crash or a browser relaunch
804        bool createdExtension = maybeInitializeSandboxExtensionHandle(KURL(KURL(), url), sandboxExtensionHandle);
805        if (createdExtension)
806            m_process->willAcquireUniversalFileReadSandboxExtension();
807    }
808
809    if (!isValid()) {
810        reattachToWebProcessWithItem(m_backForwardList->currentItem());
811        return;
812    }
813
814    m_process->send(Messages::WebPage::Reload(reloadFromOrigin, sandboxExtensionHandle), m_pageID);
815    m_process->responsivenessTimer()->start();
816}
817
818void WebPageProxy::goForward()
819{
820    if (isValid() && !canGoForward())
821        return;
822
823    WebBackForwardListItem* forwardItem = m_backForwardList->forwardItem();
824    if (!forwardItem)
825        return;
826
827    setPendingAPIRequestURL(forwardItem->url());
828
829    if (!isValid()) {
830        reattachToWebProcessWithItem(forwardItem);
831        return;
832    }
833
834    m_process->send(Messages::WebPage::GoForward(forwardItem->itemID()), m_pageID);
835    m_process->responsivenessTimer()->start();
836}
837
838bool WebPageProxy::canGoForward() const
839{
840    return m_backForwardList->forwardItem();
841}
842
843void WebPageProxy::goBack()
844{
845    if (isValid() && !canGoBack())
846        return;
847
848    WebBackForwardListItem* backItem = m_backForwardList->backItem();
849    if (!backItem)
850        return;
851
852    setPendingAPIRequestURL(backItem->url());
853
854    if (!isValid()) {
855        reattachToWebProcessWithItem(backItem);
856        return;
857    }
858
859    m_process->send(Messages::WebPage::GoBack(backItem->itemID()), m_pageID);
860    m_process->responsivenessTimer()->start();
861}
862
863bool WebPageProxy::canGoBack() const
864{
865    return m_backForwardList->backItem();
866}
867
868void WebPageProxy::goToBackForwardItem(WebBackForwardListItem* item)
869{
870    if (!isValid()) {
871        reattachToWebProcessWithItem(item);
872        return;
873    }
874
875    setPendingAPIRequestURL(item->url());
876
877    m_process->send(Messages::WebPage::GoToBackForwardItem(item->itemID()), m_pageID);
878    m_process->responsivenessTimer()->start();
879}
880
881void WebPageProxy::tryRestoreScrollPosition()
882{
883    if (!isValid())
884        return;
885
886    m_process->send(Messages::WebPage::TryRestoreScrollPosition(), m_pageID);
887}
888
889void WebPageProxy::didChangeBackForwardList(WebBackForwardListItem* added, Vector<RefPtr<APIObject>>* removed)
890{
891    m_loaderClient.didChangeBackForwardList(this, added, removed);
892}
893
894void WebPageProxy::shouldGoToBackForwardListItem(uint64_t itemID, bool& shouldGoToBackForwardItem)
895{
896    WebBackForwardListItem* item = m_process->webBackForwardItem(itemID);
897    shouldGoToBackForwardItem = item && m_loaderClient.shouldGoToBackForwardListItem(this, item);
898}
899
900void WebPageProxy::willGoToBackForwardListItem(uint64_t itemID, CoreIPC::MessageDecoder& decoder)
901{
902    RefPtr<APIObject> userData;
903    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
904    if (!decoder.decode(messageDecoder))
905        return;
906
907    if (WebBackForwardListItem* item = m_process->webBackForwardItem(itemID))
908        m_loaderClient.willGoToBackForwardListItem(this, item, userData.get());
909}
910
911String WebPageProxy::activeURL() const
912{
913    // If there is a currently pending url, it is the active URL,
914    // even when there's no main frame yet, as it might be the
915    // first API request.
916    if (!m_pendingAPIRequestURL.isNull())
917        return m_pendingAPIRequestURL;
918
919    if (!m_mainFrame)
920        return String();
921
922    if (!m_mainFrame->unreachableURL().isEmpty())
923        return m_mainFrame->unreachableURL();
924
925    switch (m_mainFrame->loadState()) {
926    case WebFrameProxy::LoadStateProvisional:
927        return m_mainFrame->provisionalURL();
928    case WebFrameProxy::LoadStateCommitted:
929    case WebFrameProxy::LoadStateFinished:
930        return m_mainFrame->url();
931    }
932
933    ASSERT_NOT_REACHED();
934    return String();
935}
936
937String WebPageProxy::provisionalURL() const
938{
939    if (!m_mainFrame)
940        return String();
941    return m_mainFrame->provisionalURL();
942}
943
944String WebPageProxy::committedURL() const
945{
946    if (!m_mainFrame)
947        return String();
948
949    return m_mainFrame->url();
950}
951
952bool WebPageProxy::canShowMIMEType(const String& mimeType) const
953{
954    if (MIMETypeRegistry::canShowMIMEType(mimeType))
955        return true;
956
957#if ENABLE(NETSCAPE_PLUGIN_API)
958    String newMimeType = mimeType;
959    PluginModuleInfo plugin = m_process->context()->pluginInfoStore().findPlugin(newMimeType, KURL());
960    if (!plugin.path.isNull() && m_pageGroup->preferences()->pluginsEnabled())
961        return true;
962#endif // ENABLE(NETSCAPE_PLUGIN_API)
963
964#if PLATFORM(MAC)
965    // On Mac, we can show PDFs.
966    if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType) && !WebContext::omitPDFSupport())
967        return true;
968#endif // PLATFORM(MAC)
969
970    return false;
971}
972
973void WebPageProxy::setDrawsBackground(bool drawsBackground)
974{
975    if (m_drawsBackground == drawsBackground)
976        return;
977
978    m_drawsBackground = drawsBackground;
979
980    if (isValid())
981        m_process->send(Messages::WebPage::SetDrawsBackground(drawsBackground), m_pageID);
982}
983
984void WebPageProxy::setDrawsTransparentBackground(bool drawsTransparentBackground)
985{
986    if (m_drawsTransparentBackground == drawsTransparentBackground)
987        return;
988
989    m_drawsTransparentBackground = drawsTransparentBackground;
990
991    if (isValid())
992        m_process->send(Messages::WebPage::SetDrawsTransparentBackground(drawsTransparentBackground), m_pageID);
993}
994
995void WebPageProxy::setUnderlayColor(const Color& color)
996{
997    if (m_underlayColor == color)
998        return;
999
1000    m_underlayColor = color;
1001
1002    if (isValid())
1003        m_process->send(Messages::WebPage::SetUnderlayColor(color), m_pageID);
1004}
1005
1006void WebPageProxy::viewWillStartLiveResize()
1007{
1008    if (!isValid())
1009        return;
1010    m_process->send(Messages::WebPage::ViewWillStartLiveResize(), m_pageID);
1011}
1012
1013void WebPageProxy::viewWillEndLiveResize()
1014{
1015    if (!isValid())
1016        return;
1017    m_process->send(Messages::WebPage::ViewWillEndLiveResize(), m_pageID);
1018}
1019
1020void WebPageProxy::setViewNeedsDisplay(const IntRect& rect)
1021{
1022    m_pageClient->setViewNeedsDisplay(rect);
1023}
1024
1025void WebPageProxy::displayView()
1026{
1027    m_pageClient->displayView();
1028}
1029
1030bool WebPageProxy::canScrollView()
1031{
1032    return m_pageClient->canScrollView();
1033}
1034
1035void WebPageProxy::scrollView(const IntRect& scrollRect, const IntSize& scrollOffset)
1036{
1037    m_pageClient->scrollView(scrollRect, scrollOffset);
1038}
1039
1040void WebPageProxy::viewInWindowStateDidChange(WantsReplyOrNot wantsReply)
1041{
1042    if (!isValid())
1043        return;
1044
1045    bool isInWindow = m_pageClient->isViewInWindow();
1046    if (m_isInWindow != isInWindow) {
1047        m_isInWindow = isInWindow;
1048        m_process->send(Messages::WebPage::SetIsInWindow(isInWindow, wantsReply == WantsReplyOrNot::DoesWantReply), m_pageID);
1049    }
1050
1051    if (isInWindow) {
1052        LayerHostingMode layerHostingMode = m_pageClient->viewLayerHostingMode();
1053        if (m_layerHostingMode != layerHostingMode) {
1054            m_layerHostingMode = layerHostingMode;
1055            m_drawingArea->layerHostingModeDidChange();
1056        }
1057    }
1058}
1059
1060void WebPageProxy::viewStateDidChange(ViewStateFlags flags)
1061{
1062    if (!isValid())
1063        return;
1064
1065    if (flags & ViewIsFocused)
1066        m_process->send(Messages::WebPage::SetFocused(m_pageClient->isViewFocused()), m_pageID);
1067
1068    if (flags & ViewWindowIsActive)
1069        m_process->send(Messages::WebPage::SetActive(m_pageClient->isViewWindowActive()), m_pageID);
1070
1071    if (flags & ViewIsVisible) {
1072        bool isVisible = m_pageClient->isViewVisible();
1073        if (isVisible != m_isVisible) {
1074            m_isVisible = isVisible;
1075            m_process->pageVisibilityChanged(this);
1076            m_drawingArea->visibilityDidChange();
1077
1078            if (!m_isVisible) {
1079                // If we've started the responsiveness timer as part of telling the web process to update the backing store
1080                // state, it might not send back a reply (since it won't paint anything if the web page is hidden) so we
1081                // stop the unresponsiveness timer here.
1082                m_process->responsivenessTimer()->stop();
1083            }
1084
1085#if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING) && !ENABLE(PAGE_VISIBILITY_API)
1086            PageVisibilityState visibilityState = m_isVisible ? PageVisibilityStateVisible : PageVisibilityStateHidden;
1087            m_process->send(Messages::WebPage::SetVisibilityState(visibilityState, false), m_pageID);
1088#endif
1089        }
1090    }
1091
1092    if (flags & ViewIsInWindow)
1093        viewInWindowStateDidChange();
1094
1095#if ENABLE(PAGE_VISIBILITY_API)
1096    PageVisibilityState visibilityState = PageVisibilityStateHidden;
1097
1098    if (m_isVisible)
1099        visibilityState = PageVisibilityStateVisible;
1100
1101    if (visibilityState != m_visibilityState) {
1102        m_visibilityState = visibilityState;
1103        m_process->send(Messages::WebPage::SetVisibilityState(visibilityState, false), m_pageID);
1104    }
1105#endif
1106
1107    updateBackingStoreDiscardableState();
1108}
1109
1110void WebPageProxy::waitForDidUpdateInWindowState()
1111{
1112    // If we have previously timed out with no response from the WebProcess, don't block the UIProcess again until it starts responding.
1113    if (m_waitingForDidUpdateInWindowState)
1114        return;
1115
1116    if (!isValid())
1117        return;
1118
1119    m_waitingForDidUpdateInWindowState = true;
1120
1121    if (!m_process->isLaunching()) {
1122        const double inWindowStateUpdateTimeout = 0.25;
1123        m_process->connection()->waitForAndDispatchImmediately<Messages::WebPageProxy::DidUpdateInWindowState>(m_pageID, inWindowStateUpdateTimeout);
1124    }
1125}
1126
1127IntSize WebPageProxy::viewSize() const
1128{
1129    return m_pageClient->viewSize();
1130}
1131
1132void WebPageProxy::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& keyboardEvent)
1133{
1134    if (!isValid())
1135        return;
1136    m_process->send(Messages::WebPage::SetInitialFocus(forward, isKeyboardEventValid, keyboardEvent), m_pageID);
1137}
1138
1139void WebPageProxy::setWindowResizerSize(const IntSize& windowResizerSize)
1140{
1141    if (!isValid())
1142        return;
1143    m_process->send(Messages::WebPage::SetWindowResizerSize(windowResizerSize), m_pageID);
1144}
1145
1146void WebPageProxy::clearSelection()
1147{
1148    if (!isValid())
1149        return;
1150    m_process->send(Messages::WebPage::ClearSelection(), m_pageID);
1151}
1152
1153void WebPageProxy::validateCommand(const String& commandName, PassRefPtr<ValidateCommandCallback> callback)
1154{
1155    if (!isValid()) {
1156        callback->invalidate();
1157        return;
1158    }
1159
1160    uint64_t callbackID = callback->callbackID();
1161    m_validateCommandCallbacks.set(callbackID, callback.get());
1162    m_process->send(Messages::WebPage::ValidateCommand(commandName, callbackID), m_pageID);
1163}
1164
1165void WebPageProxy::setMaintainsInactiveSelection(bool newValue)
1166{
1167    m_maintainsInactiveSelection = newValue;
1168}
1169
1170void WebPageProxy::executeEditCommand(const String& commandName)
1171{
1172    if (!isValid())
1173        return;
1174
1175    DEFINE_STATIC_LOCAL(String, ignoreSpellingCommandName, (ASCIILiteral("ignoreSpelling")));
1176    if (commandName == ignoreSpellingCommandName)
1177        ++m_pendingLearnOrIgnoreWordMessageCount;
1178
1179    m_process->send(Messages::WebPage::ExecuteEditCommand(commandName), m_pageID);
1180}
1181
1182#if USE(TILED_BACKING_STORE)
1183void WebPageProxy::commitPageTransitionViewport()
1184{
1185    if (!isValid())
1186        return;
1187
1188    process()->send(Messages::WebPage::CommitPageTransitionViewport(), m_pageID);
1189}
1190#endif
1191
1192#if ENABLE(DRAG_SUPPORT)
1193void WebPageProxy::dragEntered(DragData* dragData, const String& dragStorageName)
1194{
1195    SandboxExtension::Handle sandboxExtensionHandle;
1196    SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray;
1197    performDragControllerAction(DragControllerActionEntered, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray);
1198}
1199
1200void WebPageProxy::dragUpdated(DragData* dragData, const String& dragStorageName)
1201{
1202    SandboxExtension::Handle sandboxExtensionHandle;
1203    SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray;
1204    performDragControllerAction(DragControllerActionUpdated, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray);
1205}
1206
1207void WebPageProxy::dragExited(DragData* dragData, const String& dragStorageName)
1208{
1209    SandboxExtension::Handle sandboxExtensionHandle;
1210    SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray;
1211    performDragControllerAction(DragControllerActionExited, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray);
1212}
1213
1214void WebPageProxy::performDrag(DragData* dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle, const SandboxExtension::HandleArray& sandboxExtensionsForUpload)
1215{
1216    performDragControllerAction(DragControllerActionPerformDrag, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionsForUpload);
1217}
1218
1219void WebPageProxy::performDragControllerAction(DragControllerAction action, DragData* dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle, const SandboxExtension::HandleArray& sandboxExtensionsForUpload)
1220{
1221    if (!isValid())
1222        return;
1223#if PLATFORM(QT) || PLATFORM(GTK)
1224    m_process->send(Messages::WebPage::PerformDragControllerAction(action, *dragData), m_pageID);
1225#else
1226    m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData->clientPosition(), dragData->globalPosition(), dragData->draggingSourceOperationMask(), dragStorageName, dragData->flags(), sandboxExtensionHandle, sandboxExtensionsForUpload), m_pageID);
1227#endif
1228}
1229
1230void WebPageProxy::didPerformDragControllerAction(WebCore::DragSession dragSession)
1231{
1232    m_currentDragSession = dragSession;
1233}
1234
1235#if PLATFORM(QT) || PLATFORM(GTK)
1236void WebPageProxy::startDrag(const DragData& dragData, const ShareableBitmap::Handle& dragImageHandle)
1237{
1238    RefPtr<ShareableBitmap> dragImage = 0;
1239    if (!dragImageHandle.isNull()) {
1240        dragImage = ShareableBitmap::create(dragImageHandle);
1241        if (!dragImage)
1242            return;
1243    }
1244
1245    m_pageClient->startDrag(dragData, dragImage.release());
1246}
1247#endif
1248
1249void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& globalPosition, uint64_t operation)
1250{
1251    if (!isValid())
1252        return;
1253    m_process->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID);
1254}
1255#endif // ENABLE(DRAG_SUPPORT)
1256
1257void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event)
1258{
1259    if (!isValid())
1260        return;
1261
1262    // NOTE: This does not start the responsiveness timer because mouse move should not indicate interaction.
1263    if (event.type() != WebEvent::MouseMove)
1264        m_process->responsivenessTimer()->start();
1265    else {
1266        if (m_processingMouseMoveEvent) {
1267            m_nextMouseMoveEvent = adoptPtr(new NativeWebMouseEvent(event));
1268            return;
1269        }
1270
1271        m_processingMouseMoveEvent = true;
1272    }
1273
1274    // <https://bugs.webkit.org/show_bug.cgi?id=57904> We need to keep track of the mouse down event in the case where we
1275    // display a popup menu for select elements. When the user changes the selected item,
1276    // we fake a mouse up event by using this stored down event. This event gets cleared
1277    // when the mouse up message is received from WebProcess.
1278    if (event.type() == WebEvent::MouseDown)
1279        m_currentlyProcessedMouseDownEvent = adoptPtr(new NativeWebMouseEvent(event));
1280
1281    if (m_shouldSendEventsSynchronously) {
1282        bool handled = false;
1283        m_process->sendSync(Messages::WebPage::MouseEventSyncForTesting(event), Messages::WebPage::MouseEventSyncForTesting::Reply(handled), m_pageID);
1284        didReceiveEvent(event.type(), handled);
1285    } else
1286        m_process->send(Messages::WebPage::MouseEvent(event), m_pageID);
1287}
1288
1289#if MERGE_WHEEL_EVENTS
1290static bool canCoalesce(const WebWheelEvent& a, const WebWheelEvent& b)
1291{
1292    if (a.position() != b.position())
1293        return false;
1294    if (a.globalPosition() != b.globalPosition())
1295        return false;
1296    if (a.modifiers() != b.modifiers())
1297        return false;
1298    if (a.granularity() != b.granularity())
1299        return false;
1300#if PLATFORM(MAC)
1301    if (a.phase() != b.phase())
1302        return false;
1303    if (a.momentumPhase() != b.momentumPhase())
1304        return false;
1305    if (a.hasPreciseScrollingDeltas() != b.hasPreciseScrollingDeltas())
1306        return false;
1307#endif
1308
1309    return true;
1310}
1311
1312static WebWheelEvent coalesce(const WebWheelEvent& a, const WebWheelEvent& b)
1313{
1314    ASSERT(canCoalesce(a, b));
1315
1316    FloatSize mergedDelta = a.delta() + b.delta();
1317    FloatSize mergedWheelTicks = a.wheelTicks() + b.wheelTicks();
1318
1319#if PLATFORM(MAC)
1320    FloatSize mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta();
1321
1322    return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.directionInvertedFromDevice(), b.phase(), b.momentumPhase(), b.hasPreciseScrollingDeltas(), b.scrollCount(), mergedUnacceleratedScrollingDelta, b.modifiers(), b.timestamp());
1323#else
1324    return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp());
1325#endif
1326}
1327#endif // MERGE_WHEEL_EVENTS
1328
1329static WebWheelEvent coalescedWheelEvent(Deque<NativeWebWheelEvent>& queue, Vector<NativeWebWheelEvent>& coalescedEvents)
1330{
1331    ASSERT(!queue.isEmpty());
1332    ASSERT(coalescedEvents.isEmpty());
1333
1334#if MERGE_WHEEL_EVENTS
1335    NativeWebWheelEvent firstEvent = queue.takeFirst();
1336    coalescedEvents.append(firstEvent);
1337
1338    WebWheelEvent event = firstEvent;
1339    while (!queue.isEmpty() && canCoalesce(event, queue.first())) {
1340        NativeWebWheelEvent firstEvent = queue.takeFirst();
1341        coalescedEvents.append(firstEvent);
1342        event = coalesce(event, firstEvent);
1343    }
1344
1345    return event;
1346#else
1347    while (!queue.isEmpty())
1348        coalescedEvents.append(queue.takeFirst());
1349    return coalescedEvents.last();
1350#endif
1351}
1352
1353void WebPageProxy::handleWheelEvent(const NativeWebWheelEvent& event)
1354{
1355    if (!isValid())
1356        return;
1357
1358    if (!m_currentlyProcessedWheelEvents.isEmpty()) {
1359        m_wheelEventQueue.append(event);
1360        if (m_wheelEventQueue.size() < wheelEventQueueSizeThreshold)
1361            return;
1362        // The queue has too many wheel events, so push a new event.
1363    }
1364
1365    if (!m_wheelEventQueue.isEmpty()) {
1366        processNextQueuedWheelEvent();
1367        return;
1368    }
1369
1370    OwnPtr<Vector<NativeWebWheelEvent>> coalescedWheelEvent = adoptPtr(new Vector<NativeWebWheelEvent>);
1371    coalescedWheelEvent->append(event);
1372    m_currentlyProcessedWheelEvents.append(coalescedWheelEvent.release());
1373    sendWheelEvent(event);
1374}
1375
1376void WebPageProxy::processNextQueuedWheelEvent()
1377{
1378    OwnPtr<Vector<NativeWebWheelEvent>> nextCoalescedEvent = adoptPtr(new Vector<NativeWebWheelEvent>);
1379    WebWheelEvent nextWheelEvent = coalescedWheelEvent(m_wheelEventQueue, *nextCoalescedEvent.get());
1380    m_currentlyProcessedWheelEvents.append(nextCoalescedEvent.release());
1381    sendWheelEvent(nextWheelEvent);
1382}
1383
1384void WebPageProxy::sendWheelEvent(const WebWheelEvent& event)
1385{
1386    m_process->responsivenessTimer()->start();
1387
1388    if (m_shouldSendEventsSynchronously) {
1389        bool handled = false;
1390        m_process->sendSync(Messages::WebPage::WheelEventSyncForTesting(event), Messages::WebPage::WheelEventSyncForTesting::Reply(handled), m_pageID);
1391        didReceiveEvent(event.type(), handled);
1392        return;
1393    }
1394
1395    m_process->send(Messages::EventDispatcher::WheelEvent(m_pageID, event, canGoBack(), canGoForward()), 0);
1396}
1397
1398void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
1399{
1400    if (!isValid())
1401        return;
1402
1403    LOG(KeyHandling, "WebPageProxy::handleKeyboardEvent: %s", webKeyboardEventTypeString(event.type()));
1404
1405    m_keyEventQueue.append(event);
1406
1407    m_process->responsivenessTimer()->start();
1408    if (m_shouldSendEventsSynchronously) {
1409        bool handled = false;
1410        m_process->sendSync(Messages::WebPage::KeyEventSyncForTesting(event), Messages::WebPage::KeyEventSyncForTesting::Reply(handled), m_pageID);
1411        didReceiveEvent(event.type(), handled);
1412    } else if (m_keyEventQueue.size() == 1) // Otherwise, sent from DidReceiveEvent message handler.
1413        m_process->send(Messages::WebPage::KeyEvent(event), m_pageID);
1414}
1415
1416#if ENABLE(NETSCAPE_PLUGIN_API)
1417void WebPageProxy::findPlugin(const String& mimeType, uint32_t processType, const String& urlString, const String& frameURLString, const String& pageURLString, bool allowOnlyApplicationPlugins, uint64_t& pluginProcessToken, String& newMimeType, uint32_t& pluginLoadPolicy, String& unavailabilityDescription)
1418{
1419    MESSAGE_CHECK_URL(urlString);
1420
1421    newMimeType = mimeType.lower();
1422    pluginLoadPolicy = PluginModuleLoadNormally;
1423
1424    PluginData::AllowedPluginTypes allowedPluginTypes = allowOnlyApplicationPlugins ? PluginData::OnlyApplicationPlugins : PluginData::AllPlugins;
1425    PluginModuleInfo plugin = m_process->context()->pluginInfoStore().findPlugin(newMimeType, KURL(KURL(), urlString), allowedPluginTypes);
1426    if (!plugin.path) {
1427        pluginProcessToken = 0;
1428        return;
1429    }
1430
1431    pluginLoadPolicy = PluginInfoStore::defaultLoadPolicyForPlugin(plugin);
1432
1433#if PLATFORM(MAC)
1434    RefPtr<ImmutableDictionary> pluginInformation = createPluginInformationDictionary(plugin, frameURLString, String(), pageURLString, String(), String());
1435    pluginLoadPolicy = m_loaderClient.pluginLoadPolicy(this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), unavailabilityDescription);
1436#else
1437    UNUSED_PARAM(frameURLString);
1438    UNUSED_PARAM(pageURLString);
1439#endif
1440
1441    PluginProcessSandboxPolicy pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
1442    switch (pluginLoadPolicy) {
1443    case PluginModuleLoadNormally:
1444        pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
1445        break;
1446    case PluginModuleLoadUnsandboxed:
1447        pluginProcessSandboxPolicy = PluginProcessSandboxPolicyUnsandboxed;
1448        break;
1449
1450    case PluginModuleBlocked:
1451        pluginProcessToken = 0;
1452        return;
1453    }
1454
1455    pluginProcessToken = PluginProcessManager::shared().pluginProcessToken(plugin, static_cast<PluginProcessType>(processType), pluginProcessSandboxPolicy);
1456}
1457
1458#endif // ENABLE(NETSCAPE_PLUGIN_API)
1459
1460#if ENABLE(GESTURE_EVENTS)
1461void WebPageProxy::handleGestureEvent(const WebGestureEvent& event)
1462{
1463    if (!isValid())
1464        return;
1465
1466    m_gestureEventQueue.append(event);
1467
1468    m_process->responsivenessTimer()->start();
1469    m_process->send(Messages::EventDispatcher::GestureEvent(m_pageID, event), 0);
1470}
1471#endif
1472
1473#if ENABLE(TOUCH_EVENTS)
1474#if PLATFORM(QT)
1475void WebPageProxy::handlePotentialActivation(const IntPoint& touchPoint, const IntSize& touchArea)
1476{
1477    m_process->send(Messages::WebPage::HighlightPotentialActivation(touchPoint, touchArea), m_pageID);
1478}
1479#endif
1480
1481void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
1482{
1483    if (!isValid())
1484        return;
1485
1486    // If the page is suspended, which should be the case during panning, pinching
1487    // and animation on the page itself (kinetic scrolling, tap to zoom) etc, then
1488    // we do not send any of the events to the page even if is has listeners.
1489    if (m_needTouchEvents && !m_isPageSuspended) {
1490        m_touchEventQueue.append(event);
1491        m_process->responsivenessTimer()->start();
1492        if (m_shouldSendEventsSynchronously) {
1493            bool handled = false;
1494            m_process->sendSync(Messages::WebPage::TouchEventSyncForTesting(event), Messages::WebPage::TouchEventSyncForTesting::Reply(handled), m_pageID);
1495            didReceiveEvent(event.type(), handled);
1496        } else
1497            m_process->send(Messages::WebPage::TouchEvent(event), m_pageID);
1498    } else {
1499        if (m_touchEventQueue.isEmpty()) {
1500            bool isEventHandled = false;
1501            m_pageClient->doneWithTouchEvent(event, isEventHandled);
1502        } else {
1503            // We attach the incoming events to the newest queued event so that all
1504            // the events are delivered in the correct order when the event is dequed.
1505            QueuedTouchEvents& lastEvent = m_touchEventQueue.last();
1506            lastEvent.deferredTouchEvents.append(event);
1507        }
1508    }
1509}
1510#endif
1511
1512void WebPageProxy::scrollBy(ScrollDirection direction, ScrollGranularity granularity)
1513{
1514    if (!isValid())
1515        return;
1516
1517    m_process->send(Messages::WebPage::ScrollBy(direction, granularity), m_pageID);
1518}
1519
1520void WebPageProxy::centerSelectionInVisibleArea()
1521{
1522    if (!isValid())
1523        return;
1524
1525    m_process->send(Messages::WebPage::CenterSelectionInVisibleArea(), m_pageID);
1526}
1527
1528void WebPageProxy::receivedPolicyDecision(PolicyAction action, WebFrameProxy* frame, uint64_t listenerID)
1529{
1530    if (!isValid())
1531        return;
1532
1533    if (action == PolicyIgnore)
1534        clearPendingAPIRequestURL();
1535
1536    uint64_t downloadID = 0;
1537    if (action == PolicyDownload) {
1538        // Create a download proxy.
1539        DownloadProxy* download = m_process->context()->createDownloadProxy();
1540        downloadID = download->downloadID();
1541#if PLATFORM(QT) || PLATFORM(EFL) || PLATFORM(GTK)
1542        // Our design does not suppport downloads without a WebPage.
1543        handleDownloadRequest(download);
1544#endif
1545    }
1546
1547    // If we received a policy decision while in decidePolicyForResponse the decision will
1548    // be sent back to the web process by decidePolicyForResponse.
1549    if (m_inDecidePolicyForResponseSync) {
1550        m_syncMimeTypePolicyActionIsValid = true;
1551        m_syncMimeTypePolicyAction = action;
1552        m_syncMimeTypePolicyDownloadID = downloadID;
1553        return;
1554    }
1555
1556    // If we received a policy decision while in decidePolicyForNavigationAction the decision will
1557    // be sent back to the web process by decidePolicyForNavigationAction.
1558    if (m_inDecidePolicyForNavigationAction) {
1559        m_syncNavigationActionPolicyActionIsValid = true;
1560        m_syncNavigationActionPolicyAction = action;
1561        m_syncNavigationActionPolicyDownloadID = downloadID;
1562        return;
1563    }
1564
1565    m_process->send(Messages::WebPage::DidReceivePolicyDecision(frame->frameID(), listenerID, action, downloadID), m_pageID);
1566}
1567
1568String WebPageProxy::pageTitle() const
1569{
1570    // Return the null string if there is no main frame (e.g. nothing has been loaded in the page yet, WebProcess has
1571    // crashed, page has been closed).
1572    if (!m_mainFrame)
1573        return String();
1574
1575    return m_mainFrame->title();
1576}
1577
1578void WebPageProxy::setUserAgent(const String& userAgent)
1579{
1580    if (m_userAgent == userAgent)
1581        return;
1582    m_userAgent = userAgent;
1583
1584    if (!isValid())
1585        return;
1586    m_process->send(Messages::WebPage::SetUserAgent(m_userAgent), m_pageID);
1587}
1588
1589void WebPageProxy::setApplicationNameForUserAgent(const String& applicationName)
1590{
1591    if (m_applicationNameForUserAgent == applicationName)
1592        return;
1593
1594    m_applicationNameForUserAgent = applicationName;
1595    if (!m_customUserAgent.isEmpty())
1596        return;
1597
1598    setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
1599}
1600
1601void WebPageProxy::setCustomUserAgent(const String& customUserAgent)
1602{
1603    if (m_customUserAgent == customUserAgent)
1604        return;
1605
1606    m_customUserAgent = customUserAgent;
1607
1608    if (m_customUserAgent.isEmpty()) {
1609        setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
1610        return;
1611    }
1612
1613    setUserAgent(m_customUserAgent);
1614}
1615
1616void WebPageProxy::resumeActiveDOMObjectsAndAnimations()
1617{
1618    if (!isValid() || !m_isPageSuspended)
1619        return;
1620
1621    m_isPageSuspended = false;
1622
1623    m_process->send(Messages::WebPage::ResumeActiveDOMObjectsAndAnimations(), m_pageID);
1624}
1625
1626void WebPageProxy::suspendActiveDOMObjectsAndAnimations()
1627{
1628    if (!isValid() || m_isPageSuspended)
1629        return;
1630
1631    m_isPageSuspended = true;
1632
1633    m_process->send(Messages::WebPage::SuspendActiveDOMObjectsAndAnimations(), m_pageID);
1634}
1635
1636bool WebPageProxy::supportsTextEncoding() const
1637{
1638    return !m_mainFrameHasCustomRepresentation && m_mainFrame && !m_mainFrame->isDisplayingStandaloneImageDocument();
1639}
1640
1641void WebPageProxy::setCustomTextEncodingName(const String& encodingName)
1642{
1643    if (m_customTextEncodingName == encodingName)
1644        return;
1645    m_customTextEncodingName = encodingName;
1646
1647    if (!isValid())
1648        return;
1649    m_process->send(Messages::WebPage::SetCustomTextEncodingName(encodingName), m_pageID);
1650}
1651
1652void WebPageProxy::terminateProcess()
1653{
1654    // NOTE: This uses a check of m_isValid rather than calling isValid() since
1655    // we want this to run even for pages being closed or that already closed.
1656    if (!m_isValid)
1657        return;
1658
1659    m_process->requestTermination();
1660    resetStateAfterProcessExited();
1661}
1662
1663#if !USE(CF) || defined(BUILDING_QT__)
1664PassRefPtr<WebData> WebPageProxy::sessionStateData(WebPageProxySessionStateFilterCallback, void* /*context*/) const
1665{
1666    // FIXME: Return session state data for saving Page state.
1667    return 0;
1668}
1669
1670void WebPageProxy::restoreFromSessionStateData(WebData*)
1671{
1672    // FIXME: Restore the Page from the passed in session state data.
1673}
1674#endif
1675
1676bool WebPageProxy::supportsTextZoom() const
1677{
1678    if (m_mainFrameHasCustomRepresentation)
1679        return false;
1680
1681    // FIXME: This should also return false for standalone media and plug-in documents.
1682    if (!m_mainFrame || m_mainFrame->isDisplayingStandaloneImageDocument())
1683        return false;
1684
1685    return true;
1686}
1687
1688void WebPageProxy::setTextZoomFactor(double zoomFactor)
1689{
1690    if (!isValid())
1691        return;
1692
1693    if (m_mainFrameHasCustomRepresentation)
1694        return;
1695
1696    if (m_textZoomFactor == zoomFactor)
1697        return;
1698
1699    m_textZoomFactor = zoomFactor;
1700    m_process->send(Messages::WebPage::SetTextZoomFactor(m_textZoomFactor), m_pageID);
1701}
1702
1703double WebPageProxy::pageZoomFactor() const
1704{
1705    return m_mainFrameHasCustomRepresentation ? m_pageClient->customRepresentationZoomFactor() : m_pageZoomFactor;
1706}
1707
1708void WebPageProxy::setPageZoomFactor(double zoomFactor)
1709{
1710    if (!isValid())
1711        return;
1712
1713    if (m_mainFrameHasCustomRepresentation) {
1714        m_pageClient->setCustomRepresentationZoomFactor(zoomFactor);
1715        return;
1716    }
1717
1718    if (m_pageZoomFactor == zoomFactor)
1719        return;
1720
1721    m_pageZoomFactor = zoomFactor;
1722    m_process->send(Messages::WebPage::SetPageZoomFactor(m_pageZoomFactor), m_pageID);
1723}
1724
1725void WebPageProxy::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
1726{
1727    if (!isValid())
1728        return;
1729
1730    if (m_mainFrameHasCustomRepresentation) {
1731        m_pageClient->setCustomRepresentationZoomFactor(pageZoomFactor);
1732        return;
1733    }
1734
1735    if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
1736        return;
1737
1738    m_pageZoomFactor = pageZoomFactor;
1739    m_textZoomFactor = textZoomFactor;
1740    m_process->send(Messages::WebPage::SetPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor), m_pageID);
1741}
1742
1743void WebPageProxy::scalePage(double scale, const IntPoint& origin)
1744{
1745    if (!isValid())
1746        return;
1747
1748    m_process->send(Messages::WebPage::ScalePage(scale, origin), m_pageID);
1749}
1750
1751void WebPageProxy::setIntrinsicDeviceScaleFactor(float scaleFactor)
1752{
1753    if (m_intrinsicDeviceScaleFactor == scaleFactor)
1754        return;
1755
1756    m_intrinsicDeviceScaleFactor = scaleFactor;
1757
1758    if (m_drawingArea)
1759        m_drawingArea->deviceScaleFactorDidChange();
1760}
1761
1762void WebPageProxy::windowScreenDidChange(PlatformDisplayID displayID)
1763{
1764    if (!isValid())
1765        return;
1766
1767    m_process->send(Messages::WebPage::WindowScreenDidChange(displayID), m_pageID);
1768}
1769
1770float WebPageProxy::deviceScaleFactor() const
1771{
1772    if (m_customDeviceScaleFactor)
1773        return m_customDeviceScaleFactor;
1774    return m_intrinsicDeviceScaleFactor;
1775}
1776
1777void WebPageProxy::setCustomDeviceScaleFactor(float customScaleFactor)
1778{
1779    if (!isValid())
1780        return;
1781
1782    if (m_customDeviceScaleFactor == customScaleFactor)
1783        return;
1784
1785    float oldScaleFactor = deviceScaleFactor();
1786
1787    m_customDeviceScaleFactor = customScaleFactor;
1788
1789    if (deviceScaleFactor() != oldScaleFactor)
1790        m_drawingArea->deviceScaleFactorDidChange();
1791}
1792
1793void WebPageProxy::setUseFixedLayout(bool fixed)
1794{
1795    if (!isValid())
1796        return;
1797
1798    // This check is fine as the value is initialized in the web
1799    // process as part of the creation parameters.
1800    if (fixed == m_useFixedLayout)
1801        return;
1802
1803    m_useFixedLayout = fixed;
1804    if (!fixed)
1805        m_fixedLayoutSize = IntSize();
1806    m_process->send(Messages::WebPage::SetUseFixedLayout(fixed), m_pageID);
1807}
1808
1809void WebPageProxy::setFixedLayoutSize(const IntSize& size)
1810{
1811    if (!isValid())
1812        return;
1813
1814    if (size == m_fixedLayoutSize)
1815        return;
1816
1817    m_fixedLayoutSize = size;
1818    m_process->send(Messages::WebPage::SetFixedLayoutSize(size), m_pageID);
1819}
1820
1821void WebPageProxy::listenForLayoutMilestones(WebCore::LayoutMilestones milestones)
1822{
1823    if (!isValid())
1824        return;
1825
1826    m_process->send(Messages::WebPage::ListenForLayoutMilestones(milestones), m_pageID);
1827}
1828
1829void WebPageProxy::setVisibilityState(WebCore::PageVisibilityState visibilityState, bool isInitialState)
1830{
1831    if (!isValid())
1832        return;
1833
1834#if ENABLE(PAGE_VISIBILITY_API)
1835    if (visibilityState != m_visibilityState || isInitialState) {
1836        m_visibilityState = visibilityState;
1837        m_process->send(Messages::WebPage::SetVisibilityState(visibilityState, isInitialState), m_pageID);
1838    }
1839#endif
1840}
1841
1842void WebPageProxy::setSuppressScrollbarAnimations(bool suppressAnimations)
1843{
1844    if (!isValid())
1845        return;
1846
1847    if (suppressAnimations == m_suppressScrollbarAnimations)
1848        return;
1849
1850    m_suppressScrollbarAnimations = suppressAnimations;
1851    m_process->send(Messages::WebPage::SetSuppressScrollbarAnimations(suppressAnimations), m_pageID);
1852}
1853
1854void WebPageProxy::setRubberBandsAtBottom(bool rubberBandsAtBottom)
1855{
1856    if (rubberBandsAtBottom == m_rubberBandsAtBottom)
1857        return;
1858
1859    m_rubberBandsAtBottom = rubberBandsAtBottom;
1860
1861    if (!isValid())
1862        return;
1863
1864    m_process->send(Messages::WebPage::SetRubberBandsAtBottom(rubberBandsAtBottom), m_pageID);
1865}
1866
1867void WebPageProxy::setRubberBandsAtTop(bool rubberBandsAtTop)
1868{
1869    if (rubberBandsAtTop == m_rubberBandsAtTop)
1870        return;
1871
1872    m_rubberBandsAtTop = rubberBandsAtTop;
1873
1874    if (!isValid())
1875        return;
1876
1877    m_process->send(Messages::WebPage::SetRubberBandsAtTop(rubberBandsAtTop), m_pageID);
1878}
1879
1880void WebPageProxy::setPaginationMode(WebCore::Pagination::Mode mode)
1881{
1882    if (mode == m_paginationMode)
1883        return;
1884
1885    m_paginationMode = mode;
1886
1887    if (!isValid())
1888        return;
1889    m_process->send(Messages::WebPage::SetPaginationMode(mode), m_pageID);
1890}
1891
1892void WebPageProxy::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
1893{
1894    if (behavesLikeColumns == m_paginationBehavesLikeColumns)
1895        return;
1896
1897    m_paginationBehavesLikeColumns = behavesLikeColumns;
1898
1899    if (!isValid())
1900        return;
1901    m_process->send(Messages::WebPage::SetPaginationBehavesLikeColumns(behavesLikeColumns), m_pageID);
1902}
1903
1904void WebPageProxy::setPageLength(double pageLength)
1905{
1906    if (pageLength == m_pageLength)
1907        return;
1908
1909    m_pageLength = pageLength;
1910
1911    if (!isValid())
1912        return;
1913    m_process->send(Messages::WebPage::SetPageLength(pageLength), m_pageID);
1914}
1915
1916void WebPageProxy::setGapBetweenPages(double gap)
1917{
1918    if (gap == m_gapBetweenPages)
1919        return;
1920
1921    m_gapBetweenPages = gap;
1922
1923    if (!isValid())
1924        return;
1925    m_process->send(Messages::WebPage::SetGapBetweenPages(gap), m_pageID);
1926}
1927
1928void WebPageProxy::pageScaleFactorDidChange(double scaleFactor)
1929{
1930    m_pageScaleFactor = scaleFactor;
1931}
1932
1933void WebPageProxy::pageZoomFactorDidChange(double zoomFactor)
1934{
1935    m_pageZoomFactor = zoomFactor;
1936}
1937
1938void WebPageProxy::setMemoryCacheClientCallsEnabled(bool memoryCacheClientCallsEnabled)
1939{
1940    if (!isValid())
1941        return;
1942
1943    if (m_areMemoryCacheClientCallsEnabled == memoryCacheClientCallsEnabled)
1944        return;
1945
1946    m_areMemoryCacheClientCallsEnabled = memoryCacheClientCallsEnabled;
1947    m_process->send(Messages::WebPage::SetMemoryCacheMessagesEnabled(memoryCacheClientCallsEnabled), m_pageID);
1948}
1949
1950void WebPageProxy::findStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
1951{
1952    if (string.isEmpty()) {
1953        didFindStringMatches(string, Vector<Vector<WebCore::IntRect>> (), 0);
1954        return;
1955    }
1956
1957    m_process->send(Messages::WebPage::FindStringMatches(string, options, maxMatchCount), m_pageID);
1958}
1959
1960void WebPageProxy::findString(const String& string, FindOptions options, unsigned maxMatchCount)
1961{
1962    if (m_mainFrameHasCustomRepresentation)
1963        m_pageClient->findStringInCustomRepresentation(string, options, maxMatchCount);
1964    else
1965        m_process->send(Messages::WebPage::FindString(string, options, maxMatchCount), m_pageID);
1966}
1967
1968void WebPageProxy::getImageForFindMatch(int32_t matchIndex)
1969{
1970    m_process->send(Messages::WebPage::GetImageForFindMatch(matchIndex), m_pageID);
1971}
1972
1973void WebPageProxy::selectFindMatch(int32_t matchIndex)
1974{
1975    m_process->send(Messages::WebPage::SelectFindMatch(matchIndex), m_pageID);
1976}
1977
1978void WebPageProxy::hideFindUI()
1979{
1980    m_process->send(Messages::WebPage::HideFindUI(), m_pageID);
1981}
1982
1983void WebPageProxy::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
1984{
1985    if (m_mainFrameHasCustomRepresentation) {
1986        m_pageClient->countStringMatchesInCustomRepresentation(string, options, maxMatchCount);
1987        return;
1988    }
1989
1990    if (!isValid())
1991        return;
1992
1993    m_process->send(Messages::WebPage::CountStringMatches(string, options, maxMatchCount), m_pageID);
1994}
1995
1996void WebPageProxy::runJavaScriptInMainFrame(const String& script, PassRefPtr<ScriptValueCallback> prpCallback)
1997{
1998    RefPtr<ScriptValueCallback> callback = prpCallback;
1999    if (!isValid()) {
2000        callback->invalidate();
2001        return;
2002    }
2003
2004    uint64_t callbackID = callback->callbackID();
2005    m_scriptValueCallbacks.set(callbackID, callback.get());
2006    m_process->send(Messages::WebPage::RunJavaScriptInMainFrame(script, callbackID), m_pageID);
2007}
2008
2009void WebPageProxy::getRenderTreeExternalRepresentation(PassRefPtr<StringCallback> prpCallback)
2010{
2011    RefPtr<StringCallback> callback = prpCallback;
2012    if (!isValid()) {
2013        callback->invalidate();
2014        return;
2015    }
2016
2017    uint64_t callbackID = callback->callbackID();
2018    m_stringCallbacks.set(callbackID, callback.get());
2019    m_process->send(Messages::WebPage::GetRenderTreeExternalRepresentation(callbackID), m_pageID);
2020}
2021
2022void WebPageProxy::getSourceForFrame(WebFrameProxy* frame, PassRefPtr<StringCallback> prpCallback)
2023{
2024    RefPtr<StringCallback> callback = prpCallback;
2025    if (!isValid()) {
2026        callback->invalidate();
2027        return;
2028    }
2029
2030    uint64_t callbackID = callback->callbackID();
2031    m_loadDependentStringCallbackIDs.add(callbackID);
2032    m_stringCallbacks.set(callbackID, callback.get());
2033    m_process->send(Messages::WebPage::GetSourceForFrame(frame->frameID(), callbackID), m_pageID);
2034}
2035
2036void WebPageProxy::getContentsAsString(PassRefPtr<StringCallback> prpCallback)
2037{
2038    RefPtr<StringCallback> callback = prpCallback;
2039    if (!isValid()) {
2040        callback->invalidate();
2041        return;
2042    }
2043
2044    uint64_t callbackID = callback->callbackID();
2045    m_loadDependentStringCallbackIDs.add(callbackID);
2046    m_stringCallbacks.set(callbackID, callback.get());
2047    m_process->send(Messages::WebPage::GetContentsAsString(callbackID), m_pageID);
2048}
2049
2050#if ENABLE(MHTML)
2051void WebPageProxy::getContentsAsMHTMLData(PassRefPtr<DataCallback> prpCallback, bool useBinaryEncoding)
2052{
2053    RefPtr<DataCallback> callback = prpCallback;
2054    if (!isValid()) {
2055        callback->invalidate();
2056        return;
2057    }
2058
2059    uint64_t callbackID = callback->callbackID();
2060    m_dataCallbacks.set(callbackID, callback.get());
2061    m_process->send(Messages::WebPage::GetContentsAsMHTMLData(callbackID, useBinaryEncoding), m_pageID);
2062}
2063#endif
2064
2065void WebPageProxy::getSelectionOrContentsAsString(PassRefPtr<StringCallback> prpCallback)
2066{
2067    RefPtr<StringCallback> callback = prpCallback;
2068    if (!isValid()) {
2069        callback->invalidate();
2070        return;
2071    }
2072
2073    uint64_t callbackID = callback->callbackID();
2074    m_stringCallbacks.set(callbackID, callback.get());
2075    m_process->send(Messages::WebPage::GetSelectionOrContentsAsString(callbackID), m_pageID);
2076}
2077
2078void WebPageProxy::getSelectionAsWebArchiveData(PassRefPtr<DataCallback> prpCallback)
2079{
2080    RefPtr<DataCallback> callback = prpCallback;
2081    if (!isValid()) {
2082        callback->invalidate();
2083        return;
2084    }
2085
2086    uint64_t callbackID = callback->callbackID();
2087    m_dataCallbacks.set(callbackID, callback.get());
2088    m_process->send(Messages::WebPage::GetSelectionAsWebArchiveData(callbackID), m_pageID);
2089}
2090
2091void WebPageProxy::getMainResourceDataOfFrame(WebFrameProxy* frame, PassRefPtr<DataCallback> prpCallback)
2092{
2093    RefPtr<DataCallback> callback = prpCallback;
2094    if (!isValid()) {
2095        callback->invalidate();
2096        return;
2097    }
2098
2099    uint64_t callbackID = callback->callbackID();
2100    m_dataCallbacks.set(callbackID, callback.get());
2101    m_process->send(Messages::WebPage::GetMainResourceDataOfFrame(frame->frameID(), callbackID), m_pageID);
2102}
2103
2104void WebPageProxy::getResourceDataFromFrame(WebFrameProxy* frame, WebURL* resourceURL, PassRefPtr<DataCallback> prpCallback)
2105{
2106    RefPtr<DataCallback> callback = prpCallback;
2107    if (!isValid()) {
2108        callback->invalidate();
2109        return;
2110    }
2111
2112    uint64_t callbackID = callback->callbackID();
2113    m_dataCallbacks.set(callbackID, callback.get());
2114    m_process->send(Messages::WebPage::GetResourceDataFromFrame(frame->frameID(), resourceURL->string(), callbackID), m_pageID);
2115}
2116
2117void WebPageProxy::getWebArchiveOfFrame(WebFrameProxy* frame, PassRefPtr<DataCallback> prpCallback)
2118{
2119    RefPtr<DataCallback> callback = prpCallback;
2120    if (!isValid()) {
2121        callback->invalidate();
2122        return;
2123    }
2124
2125    uint64_t callbackID = callback->callbackID();
2126    m_dataCallbacks.set(callbackID, callback.get());
2127    m_process->send(Messages::WebPage::GetWebArchiveOfFrame(frame->frameID(), callbackID), m_pageID);
2128}
2129
2130void WebPageProxy::forceRepaint(PassRefPtr<VoidCallback> prpCallback)
2131{
2132    RefPtr<VoidCallback> callback = prpCallback;
2133    if (!isValid()) {
2134        callback->invalidate();
2135        return;
2136    }
2137
2138    uint64_t callbackID = callback->callbackID();
2139    m_voidCallbacks.set(callbackID, callback.get());
2140    m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
2141    m_process->send(Messages::WebPage::ForceRepaint(callbackID), m_pageID);
2142}
2143
2144void WebPageProxy::preferencesDidChange()
2145{
2146    if (!isValid())
2147        return;
2148
2149#if ENABLE(INSPECTOR_SERVER)
2150    if (m_pageGroup->preferences()->developerExtrasEnabled())
2151        inspector()->enableRemoteInspection();
2152#endif
2153
2154    m_process->pagePreferencesChanged(this);
2155
2156    m_pageClient->preferencesDidChange();
2157
2158    // FIXME: It probably makes more sense to send individual preference changes.
2159    // However, WebKitTestRunner depends on getting a preference change notification
2160    // even if nothing changed in UI process, so that overrides get removed.
2161
2162    // Preferences need to be updated during synchronous printing to make "print backgrounds" preference work when toggled from a print dialog checkbox.
2163    m_process->send(Messages::WebPage::PreferencesDidChange(pageGroup()->preferences()->store()), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0);
2164}
2165
2166void WebPageProxy::didCreateMainFrame(uint64_t frameID)
2167{
2168    MESSAGE_CHECK(!m_mainFrame);
2169    MESSAGE_CHECK(m_process->canCreateFrame(frameID));
2170
2171    m_mainFrame = WebFrameProxy::create(this, frameID);
2172
2173    // Add the frame to the process wide map.
2174    m_process->frameCreated(frameID, m_mainFrame.get());
2175}
2176
2177void WebPageProxy::didCreateSubframe(uint64_t frameID)
2178{
2179    MESSAGE_CHECK(m_mainFrame);
2180    MESSAGE_CHECK(m_process->canCreateFrame(frameID));
2181
2182    RefPtr<WebFrameProxy> subFrame = WebFrameProxy::create(this, frameID);
2183
2184    // Add the frame to the process wide map.
2185    m_process->frameCreated(frameID, subFrame.get());
2186}
2187
2188// Always start progress at initialProgressValue. This helps provide feedback as
2189// soon as a load starts.
2190
2191static const double initialProgressValue = 0.1;
2192
2193double WebPageProxy::estimatedProgress() const
2194{
2195    if (!pendingAPIRequestURL().isNull())
2196        return initialProgressValue;
2197    return m_estimatedProgress;
2198}
2199
2200void WebPageProxy::didStartProgress()
2201{
2202    m_estimatedProgress = initialProgressValue;
2203
2204    m_loaderClient.didStartProgress(this);
2205}
2206
2207void WebPageProxy::didChangeProgress(double value)
2208{
2209    m_estimatedProgress = value;
2210
2211    m_loaderClient.didChangeProgress(this);
2212}
2213
2214void WebPageProxy::didFinishProgress()
2215{
2216    m_estimatedProgress = 1.0;
2217
2218    m_loaderClient.didFinishProgress(this);
2219}
2220
2221void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, const String& url, const String& unreachableURL, CoreIPC::MessageDecoder& decoder)
2222{
2223    clearPendingAPIRequestURL();
2224
2225    RefPtr<APIObject> userData;
2226    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2227    if (!decoder.decode(messageDecoder))
2228        return;
2229
2230    WebFrameProxy* frame = m_process->webFrame(frameID);
2231    MESSAGE_CHECK(frame);
2232    MESSAGE_CHECK_URL(url);
2233
2234    frame->setUnreachableURL(unreachableURL);
2235
2236    frame->didStartProvisionalLoad(url);
2237    m_loaderClient.didStartProvisionalLoadForFrame(this, frame, userData.get());
2238}
2239
2240void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, const String& url, CoreIPC::MessageDecoder& decoder)
2241{
2242    RefPtr<APIObject> userData;
2243    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2244    if (!decoder.decode(messageDecoder))
2245        return;
2246
2247    WebFrameProxy* frame = m_process->webFrame(frameID);
2248    MESSAGE_CHECK(frame);
2249    MESSAGE_CHECK_URL(url);
2250
2251    frame->didReceiveServerRedirectForProvisionalLoad(url);
2252
2253    m_loaderClient.didReceiveServerRedirectForProvisionalLoadForFrame(this, frame, userData.get());
2254}
2255
2256void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const ResourceError& error, CoreIPC::MessageDecoder& decoder)
2257{
2258    RefPtr<APIObject> userData;
2259    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2260    if (!decoder.decode(messageDecoder))
2261        return;
2262
2263    WebFrameProxy* frame = m_process->webFrame(frameID);
2264    MESSAGE_CHECK(frame);
2265
2266    frame->didFailProvisionalLoad();
2267
2268    m_loaderClient.didFailProvisionalLoadWithErrorForFrame(this, frame, error, userData.get());
2269}
2270
2271void WebPageProxy::clearLoadDependentCallbacks()
2272{
2273    Vector<uint64_t> callbackIDsCopy;
2274    copyToVector(m_loadDependentStringCallbackIDs, callbackIDsCopy);
2275    m_loadDependentStringCallbackIDs.clear();
2276
2277    for (size_t i = 0; i < callbackIDsCopy.size(); ++i) {
2278        RefPtr<StringCallback> callback = m_stringCallbacks.take(callbackIDsCopy[i]);
2279        if (callback)
2280            callback->invalidate();
2281    }
2282}
2283
2284void WebPageProxy::didCommitLoadForFrame(uint64_t frameID, const String& mimeType, bool frameHasCustomRepresentation, uint32_t opaqueFrameLoadType, const PlatformCertificateInfo& certificateInfo, CoreIPC::MessageDecoder& decoder)
2285{
2286    RefPtr<APIObject> userData;
2287    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2288    if (!decoder.decode(messageDecoder))
2289        return;
2290
2291    WebFrameProxy* frame = m_process->webFrame(frameID);
2292    MESSAGE_CHECK(frame);
2293
2294#if PLATFORM(MAC)
2295    // FIXME (bug 59111): didCommitLoadForFrame comes too late when restoring a page from b/f cache, making us disable secure event mode in password fields.
2296    // FIXME: A load going on in one frame shouldn't affect text editing in other frames on the page.
2297    m_pageClient->resetSecureInputState();
2298    dismissCorrectionPanel(ReasonForDismissingAlternativeTextIgnored);
2299    m_pageClient->dismissDictionaryLookupPanel();
2300#endif
2301
2302    clearLoadDependentCallbacks();
2303
2304    frame->didCommitLoad(mimeType, certificateInfo);
2305
2306    if (frame->isMainFrame()) {
2307        m_mainFrameHasCustomRepresentation = frameHasCustomRepresentation;
2308
2309        if (m_mainFrameHasCustomRepresentation) {
2310            // Always assume that the main frame is pinned here, since the custom representation view will handle
2311            // any wheel events and dispatch them to the WKView when necessary.
2312            m_mainFrameIsPinnedToLeftSide = true;
2313            m_mainFrameIsPinnedToRightSide = true;
2314            m_mainFrameIsPinnedToTopSide = true;
2315            m_mainFrameIsPinnedToBottomSide = true;
2316        }
2317        m_pageClient->didCommitLoadForMainFrame(frameHasCustomRepresentation);
2318    }
2319
2320    // Even if WebPage has the default pageScaleFactor (and therefore doesn't reset it),
2321    // WebPageProxy's cache of the value can get out of sync (e.g. in the case where a
2322    // plugin is handling page scaling itself) so we should reset it to the default
2323    // for standard main frame loads.
2324    if (frame->isMainFrame() && static_cast<FrameLoadType>(opaqueFrameLoadType) == FrameLoadTypeStandard)
2325        m_pageScaleFactor = 1;
2326
2327    m_loaderClient.didCommitLoadForFrame(this, frame, userData.get());
2328}
2329
2330void WebPageProxy::didFinishDocumentLoadForFrame(uint64_t frameID, CoreIPC::MessageDecoder& decoder)
2331{
2332    RefPtr<APIObject> userData;
2333    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2334    if (!decoder.decode(messageDecoder))
2335        return;
2336
2337    WebFrameProxy* frame = m_process->webFrame(frameID);
2338    MESSAGE_CHECK(frame);
2339
2340    m_loaderClient.didFinishDocumentLoadForFrame(this, frame, userData.get());
2341}
2342
2343void WebPageProxy::didFinishLoadForFrame(uint64_t frameID, CoreIPC::MessageDecoder& decoder)
2344{
2345    RefPtr<APIObject> userData;
2346    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2347    if (!decoder.decode(messageDecoder))
2348        return;
2349
2350    WebFrameProxy* frame = m_process->webFrame(frameID);
2351    MESSAGE_CHECK(frame);
2352
2353    frame->didFinishLoad();
2354
2355    m_loaderClient.didFinishLoadForFrame(this, frame, userData.get());
2356}
2357
2358void WebPageProxy::didFailLoadForFrame(uint64_t frameID, const ResourceError& error, CoreIPC::MessageDecoder& decoder)
2359{
2360    RefPtr<APIObject> userData;
2361    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2362    if (!decoder.decode(messageDecoder))
2363        return;
2364
2365    WebFrameProxy* frame = m_process->webFrame(frameID);
2366    MESSAGE_CHECK(frame);
2367
2368    clearLoadDependentCallbacks();
2369
2370    frame->didFailLoad();
2371
2372    m_loaderClient.didFailLoadWithErrorForFrame(this, frame, error, userData.get());
2373}
2374
2375void WebPageProxy::didSameDocumentNavigationForFrame(uint64_t frameID, uint32_t opaqueSameDocumentNavigationType, const String& url, CoreIPC::MessageDecoder& decoder)
2376{
2377    RefPtr<APIObject> userData;
2378    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2379    if (!decoder.decode(messageDecoder))
2380        return;
2381
2382    WebFrameProxy* frame = m_process->webFrame(frameID);
2383    MESSAGE_CHECK(frame);
2384    MESSAGE_CHECK_URL(url);
2385
2386    clearPendingAPIRequestURL();
2387    frame->didSameDocumentNavigation(url);
2388
2389    m_loaderClient.didSameDocumentNavigationForFrame(this, frame, static_cast<SameDocumentNavigationType>(opaqueSameDocumentNavigationType), userData.get());
2390}
2391
2392void WebPageProxy::didReceiveTitleForFrame(uint64_t frameID, const String& title, CoreIPC::MessageDecoder& decoder)
2393{
2394    RefPtr<APIObject> userData;
2395    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2396    if (!decoder.decode(messageDecoder))
2397        return;
2398
2399    WebFrameProxy* frame = m_process->webFrame(frameID);
2400    MESSAGE_CHECK(frame);
2401
2402    frame->didChangeTitle(title);
2403
2404    m_loaderClient.didReceiveTitleForFrame(this, title, frame, userData.get());
2405}
2406
2407void WebPageProxy::didFirstLayoutForFrame(uint64_t frameID, CoreIPC::MessageDecoder& decoder)
2408{
2409    RefPtr<APIObject> userData;
2410    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2411    if (!decoder.decode(messageDecoder))
2412        return;
2413
2414    WebFrameProxy* frame = m_process->webFrame(frameID);
2415    MESSAGE_CHECK(frame);
2416
2417    m_loaderClient.didFirstLayoutForFrame(this, frame, userData.get());
2418}
2419
2420void WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame(uint64_t frameID, CoreIPC::MessageDecoder& decoder)
2421{
2422    RefPtr<APIObject> userData;
2423    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2424    if (!decoder.decode(messageDecoder))
2425        return;
2426
2427    WebFrameProxy* frame = m_process->webFrame(frameID);
2428    MESSAGE_CHECK(frame);
2429
2430    m_loaderClient.didFirstVisuallyNonEmptyLayoutForFrame(this, frame, userData.get());
2431}
2432
2433void WebPageProxy::didNewFirstVisuallyNonEmptyLayout(CoreIPC::MessageDecoder& decoder)
2434{
2435    RefPtr<APIObject> userData;
2436    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2437    if (!decoder.decode(messageDecoder))
2438        return;
2439
2440    m_loaderClient.didNewFirstVisuallyNonEmptyLayout(this, userData.get());
2441}
2442
2443void WebPageProxy::didLayout(uint32_t layoutMilestones, CoreIPC::MessageDecoder& decoder)
2444{
2445    RefPtr<APIObject> userData;
2446    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2447    if (!decoder.decode(messageDecoder))
2448        return;
2449
2450    m_loaderClient.didLayout(this, static_cast<LayoutMilestones>(layoutMilestones), userData.get());
2451}
2452
2453void WebPageProxy::didRemoveFrameFromHierarchy(uint64_t frameID, CoreIPC::MessageDecoder& decoder)
2454{
2455    RefPtr<APIObject> userData;
2456    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2457    if (!decoder.decode(messageDecoder))
2458        return;
2459
2460    WebFrameProxy* frame = m_process->webFrame(frameID);
2461    MESSAGE_CHECK(frame);
2462
2463    m_loaderClient.didRemoveFrameFromHierarchy(this, frame, userData.get());
2464}
2465
2466void WebPageProxy::didDisplayInsecureContentForFrame(uint64_t frameID, CoreIPC::MessageDecoder& decoder)
2467{
2468    RefPtr<APIObject> userData;
2469    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2470    if (!decoder.decode(messageDecoder))
2471        return;
2472
2473    WebFrameProxy* frame = m_process->webFrame(frameID);
2474    MESSAGE_CHECK(frame);
2475
2476    m_loaderClient.didDisplayInsecureContentForFrame(this, frame, userData.get());
2477}
2478
2479void WebPageProxy::didRunInsecureContentForFrame(uint64_t frameID, CoreIPC::MessageDecoder& decoder)
2480{
2481    RefPtr<APIObject> userData;
2482    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2483    if (!decoder.decode(messageDecoder))
2484        return;
2485
2486    WebFrameProxy* frame = m_process->webFrame(frameID);
2487    MESSAGE_CHECK(frame);
2488
2489    m_loaderClient.didRunInsecureContentForFrame(this, frame, userData.get());
2490}
2491
2492void WebPageProxy::didDetectXSSForFrame(uint64_t frameID, CoreIPC::MessageDecoder& decoder)
2493{
2494    RefPtr<APIObject> userData;
2495    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2496    if (!decoder.decode(messageDecoder))
2497        return;
2498
2499    WebFrameProxy* frame = m_process->webFrame(frameID);
2500    MESSAGE_CHECK(frame);
2501
2502    m_loaderClient.didDetectXSSForFrame(this, frame, userData.get());
2503}
2504
2505void WebPageProxy::frameDidBecomeFrameSet(uint64_t frameID, bool value)
2506{
2507    WebFrameProxy* frame = m_process->webFrame(frameID);
2508    MESSAGE_CHECK(frame);
2509
2510    frame->setIsFrameSet(value);
2511    if (frame->isMainFrame())
2512        m_frameSetLargestFrame = value ? m_mainFrame : 0;
2513}
2514
2515// PolicyClient
2516void WebPageProxy::decidePolicyForNavigationAction(uint64_t frameID, uint32_t opaqueNavigationType, uint32_t opaqueModifiers, int32_t opaqueMouseButton, const ResourceRequest& request, uint64_t listenerID, CoreIPC::MessageDecoder& decoder, bool& receivedPolicyAction, uint64_t& policyAction, uint64_t& downloadID)
2517{
2518    RefPtr<APIObject> userData;
2519    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2520    if (!decoder.decode(messageDecoder))
2521        return;
2522
2523    if (request.url() != pendingAPIRequestURL())
2524        clearPendingAPIRequestURL();
2525
2526    WebFrameProxy* frame = m_process->webFrame(frameID);
2527    MESSAGE_CHECK(frame);
2528    MESSAGE_CHECK_URL(request.url());
2529
2530    NavigationType navigationType = static_cast<NavigationType>(opaqueNavigationType);
2531    WebEvent::Modifiers modifiers = static_cast<WebEvent::Modifiers>(opaqueModifiers);
2532    WebMouseEvent::Button mouseButton = static_cast<WebMouseEvent::Button>(opaqueMouseButton);
2533
2534    RefPtr<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
2535
2536    ASSERT(!m_inDecidePolicyForNavigationAction);
2537
2538    m_inDecidePolicyForNavigationAction = true;
2539    m_syncNavigationActionPolicyActionIsValid = false;
2540
2541    if (!m_policyClient.decidePolicyForNavigationAction(this, frame, navigationType, modifiers, mouseButton, request, listener.get(), userData.get()))
2542        listener->use();
2543
2544    m_inDecidePolicyForNavigationAction = false;
2545
2546    // Check if we received a policy decision already. If we did, we can just pass it back.
2547    receivedPolicyAction = m_syncNavigationActionPolicyActionIsValid;
2548    if (m_syncNavigationActionPolicyActionIsValid) {
2549        policyAction = m_syncNavigationActionPolicyAction;
2550        downloadID = m_syncNavigationActionPolicyDownloadID;
2551    }
2552}
2553
2554void WebPageProxy::decidePolicyForNewWindowAction(uint64_t frameID, uint32_t opaqueNavigationType, uint32_t opaqueModifiers, int32_t opaqueMouseButton, const ResourceRequest& request, const String& frameName, uint64_t listenerID, CoreIPC::MessageDecoder& decoder)
2555{
2556    RefPtr<APIObject> userData;
2557    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2558    if (!decoder.decode(messageDecoder))
2559        return;
2560
2561    WebFrameProxy* frame = m_process->webFrame(frameID);
2562    MESSAGE_CHECK(frame);
2563    MESSAGE_CHECK_URL(request.url());
2564
2565    NavigationType navigationType = static_cast<NavigationType>(opaqueNavigationType);
2566    WebEvent::Modifiers modifiers = static_cast<WebEvent::Modifiers>(opaqueModifiers);
2567    WebMouseEvent::Button mouseButton = static_cast<WebMouseEvent::Button>(opaqueMouseButton);
2568
2569    RefPtr<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
2570    if (!m_policyClient.decidePolicyForNewWindowAction(this, frame, navigationType, modifiers, mouseButton, request, frameName, listener.get(), userData.get()))
2571        listener->use();
2572}
2573
2574void WebPageProxy::decidePolicyForResponse(uint64_t frameID, const ResourceResponse& response, const ResourceRequest& request, uint64_t listenerID, CoreIPC::MessageDecoder& decoder)
2575{
2576    RefPtr<APIObject> userData;
2577    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2578    if (!decoder.decode(messageDecoder))
2579        return;
2580
2581    WebFrameProxy* frame = m_process->webFrame(frameID);
2582    MESSAGE_CHECK(frame);
2583    MESSAGE_CHECK_URL(request.url());
2584    MESSAGE_CHECK_URL(response.url());
2585
2586    RefPtr<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
2587
2588    if (!m_policyClient.decidePolicyForResponse(this, frame, response, request, listener.get(), userData.get()))
2589        listener->use();
2590}
2591
2592void WebPageProxy::decidePolicyForResponseSync(uint64_t frameID, const ResourceResponse& response, const ResourceRequest& request, uint64_t listenerID, CoreIPC::MessageDecoder& decoder, bool& receivedPolicyAction, uint64_t& policyAction, uint64_t& downloadID)
2593{
2594    ASSERT(!m_inDecidePolicyForResponseSync);
2595
2596    m_inDecidePolicyForResponseSync = true;
2597    m_decidePolicyForResponseRequest = &request;
2598    m_syncMimeTypePolicyActionIsValid = false;
2599
2600    decidePolicyForResponse(frameID, response, request, listenerID, decoder);
2601
2602    m_inDecidePolicyForResponseSync = false;
2603    m_decidePolicyForResponseRequest = 0;
2604
2605    // Check if we received a policy decision already. If we did, we can just pass it back.
2606    receivedPolicyAction = m_syncMimeTypePolicyActionIsValid;
2607    if (m_syncMimeTypePolicyActionIsValid) {
2608        policyAction = m_syncMimeTypePolicyAction;
2609        downloadID = m_syncMimeTypePolicyDownloadID;
2610    }
2611}
2612
2613void WebPageProxy::unableToImplementPolicy(uint64_t frameID, const ResourceError& error, CoreIPC::MessageDecoder& decoder)
2614{
2615    RefPtr<APIObject> userData;
2616    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2617    if (!decoder.decode(messageDecoder))
2618        return;
2619
2620    WebFrameProxy* frame = m_process->webFrame(frameID);
2621    MESSAGE_CHECK(frame);
2622
2623    m_policyClient.unableToImplementPolicy(this, frame, error, userData.get());
2624}
2625
2626// FormClient
2627
2628void WebPageProxy::willSubmitForm(uint64_t frameID, uint64_t sourceFrameID, const Vector<std::pair<String, String>>& textFieldValues, uint64_t listenerID, CoreIPC::MessageDecoder& decoder)
2629{
2630    RefPtr<APIObject> userData;
2631    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2632    if (!decoder.decode(messageDecoder))
2633        return;
2634
2635    WebFrameProxy* frame = m_process->webFrame(frameID);
2636    MESSAGE_CHECK(frame);
2637
2638    WebFrameProxy* sourceFrame = m_process->webFrame(sourceFrameID);
2639    MESSAGE_CHECK(sourceFrame);
2640
2641    RefPtr<WebFormSubmissionListenerProxy> listener = frame->setUpFormSubmissionListenerProxy(listenerID);
2642    if (!m_formClient.willSubmitForm(this, frame, sourceFrame, textFieldValues, userData.get(), listener.get()))
2643        listener->continueSubmission();
2644}
2645
2646// UIClient
2647
2648void WebPageProxy::createNewPage(const ResourceRequest& request, const WindowFeatures& windowFeatures, uint32_t opaqueModifiers, int32_t opaqueMouseButton, uint64_t& newPageID, WebPageCreationParameters& newPageParameters)
2649{
2650    RefPtr<WebPageProxy> newPage = m_uiClient.createNewPage(this, request, windowFeatures, static_cast<WebEvent::Modifiers>(opaqueModifiers), static_cast<WebMouseEvent::Button>(opaqueMouseButton));
2651    if (!newPage) {
2652        newPageID = 0;
2653        return;
2654    }
2655
2656    newPageID = newPage->pageID();
2657    newPageParameters = newPage->creationParameters();
2658    process()->context()->storageManager().cloneSessionStorageNamespace(m_pageID, newPage->pageID());
2659}
2660
2661void WebPageProxy::showPage()
2662{
2663    m_uiClient.showPage(this);
2664}
2665
2666void WebPageProxy::closePage(bool stopResponsivenessTimer)
2667{
2668    if (stopResponsivenessTimer)
2669        m_process->responsivenessTimer()->stop();
2670
2671    m_pageClient->clearAllEditCommands();
2672    m_uiClient.close(this);
2673}
2674
2675void WebPageProxy::runJavaScriptAlert(uint64_t frameID, const String& message)
2676{
2677    WebFrameProxy* frame = m_process->webFrame(frameID);
2678    MESSAGE_CHECK(frame);
2679
2680    // Since runJavaScriptAlert() can spin a nested run loop we need to turn off the responsiveness timer.
2681    m_process->responsivenessTimer()->stop();
2682
2683    m_uiClient.runJavaScriptAlert(this, message, frame);
2684}
2685
2686void WebPageProxy::runJavaScriptConfirm(uint64_t frameID, const String& message, bool& result)
2687{
2688    WebFrameProxy* frame = m_process->webFrame(frameID);
2689    MESSAGE_CHECK(frame);
2690
2691    // Since runJavaScriptConfirm() can spin a nested run loop we need to turn off the responsiveness timer.
2692    m_process->responsivenessTimer()->stop();
2693
2694    result = m_uiClient.runJavaScriptConfirm(this, message, frame);
2695}
2696
2697void WebPageProxy::runJavaScriptPrompt(uint64_t frameID, const String& message, const String& defaultValue, String& result)
2698{
2699    WebFrameProxy* frame = m_process->webFrame(frameID);
2700    MESSAGE_CHECK(frame);
2701
2702    // Since runJavaScriptPrompt() can spin a nested run loop we need to turn off the responsiveness timer.
2703    m_process->responsivenessTimer()->stop();
2704
2705    result = m_uiClient.runJavaScriptPrompt(this, message, defaultValue, frame);
2706}
2707
2708void WebPageProxy::shouldInterruptJavaScript(bool& result)
2709{
2710    // Since shouldInterruptJavaScript() can spin a nested run loop we need to turn off the responsiveness timer.
2711    m_process->responsivenessTimer()->stop();
2712
2713    result = m_uiClient.shouldInterruptJavaScript(this);
2714}
2715
2716void WebPageProxy::setStatusText(const String& text)
2717{
2718    m_uiClient.setStatusText(this, text);
2719}
2720
2721void WebPageProxy::mouseDidMoveOverElement(const WebHitTestResult::Data& hitTestResultData, uint32_t opaqueModifiers, CoreIPC::MessageDecoder& decoder)
2722{
2723    RefPtr<APIObject> userData;
2724    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
2725    if (!decoder.decode(messageDecoder))
2726        return;
2727
2728    WebEvent::Modifiers modifiers = static_cast<WebEvent::Modifiers>(opaqueModifiers);
2729
2730    m_uiClient.mouseDidMoveOverElement(this, hitTestResultData, modifiers, userData.get());
2731}
2732
2733void WebPageProxy::connectionWillOpen(CoreIPC::Connection* connection)
2734{
2735    ASSERT(connection == m_process->connection());
2736
2737    m_process->context()->storageManager().setAllowedSessionStorageNamespaceConnection(m_pageID, connection);
2738}
2739
2740void WebPageProxy::connectionWillClose(CoreIPC::Connection* connection)
2741{
2742    ASSERT_UNUSED(connection, connection == m_process->connection());
2743
2744    m_process->context()->storageManager().setAllowedSessionStorageNamespaceConnection(m_pageID, 0);
2745}
2746
2747void WebPageProxy::unavailablePluginButtonClicked(uint32_t opaquePluginUnavailabilityReason, const String& mimeType, const String& pluginURLString, const String& pluginspageAttributeURLString, const String& frameURLString, const String& pageURLString)
2748{
2749    MESSAGE_CHECK_URL(pluginURLString);
2750    MESSAGE_CHECK_URL(pluginspageAttributeURLString);
2751    MESSAGE_CHECK_URL(frameURLString);
2752    MESSAGE_CHECK_URL(pageURLString);
2753
2754    RefPtr<ImmutableDictionary> pluginInformation;
2755#if ENABLE(NETSCAPE_PLUGIN_API)
2756    String newMimeType = mimeType;
2757    PluginModuleInfo plugin = m_process->context()->pluginInfoStore().findPlugin(newMimeType, KURL(KURL(), pluginURLString));
2758    pluginInformation = createPluginInformationDictionary(plugin, frameURLString, mimeType, pageURLString, pluginspageAttributeURLString, pluginURLString);
2759#endif
2760
2761    WKPluginUnavailabilityReason pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginMissing;
2762    switch (static_cast<RenderEmbeddedObject::PluginUnavailabilityReason>(opaquePluginUnavailabilityReason)) {
2763    case RenderEmbeddedObject::PluginMissing:
2764        pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginMissing;
2765        break;
2766    case RenderEmbeddedObject::InsecurePluginVersion:
2767        pluginUnavailabilityReason = kWKPluginUnavailabilityReasonInsecurePluginVersion;
2768        break;
2769    case RenderEmbeddedObject::PluginCrashed:
2770        pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginCrashed;
2771        break;
2772    case RenderEmbeddedObject::PluginBlockedByContentSecurityPolicy:
2773        ASSERT_NOT_REACHED();
2774    }
2775
2776    m_uiClient.unavailablePluginButtonClicked(this, pluginUnavailabilityReason, pluginInformation.get());
2777}
2778
2779void WebPageProxy::setToolbarsAreVisible(bool toolbarsAreVisible)
2780{
2781    m_uiClient.setToolbarsAreVisible(this, toolbarsAreVisible);
2782}
2783
2784void WebPageProxy::getToolbarsAreVisible(bool& toolbarsAreVisible)
2785{
2786    toolbarsAreVisible = m_uiClient.toolbarsAreVisible(this);
2787}
2788
2789void WebPageProxy::setMenuBarIsVisible(bool menuBarIsVisible)
2790{
2791    m_uiClient.setMenuBarIsVisible(this, menuBarIsVisible);
2792}
2793
2794void WebPageProxy::getMenuBarIsVisible(bool& menuBarIsVisible)
2795{
2796    menuBarIsVisible = m_uiClient.menuBarIsVisible(this);
2797}
2798
2799void WebPageProxy::setStatusBarIsVisible(bool statusBarIsVisible)
2800{
2801    m_uiClient.setStatusBarIsVisible(this, statusBarIsVisible);
2802}
2803
2804void WebPageProxy::getStatusBarIsVisible(bool& statusBarIsVisible)
2805{
2806    statusBarIsVisible = m_uiClient.statusBarIsVisible(this);
2807}
2808
2809void WebPageProxy::setIsResizable(bool isResizable)
2810{
2811    m_uiClient.setIsResizable(this, isResizable);
2812}
2813
2814void WebPageProxy::getIsResizable(bool& isResizable)
2815{
2816    isResizable = m_uiClient.isResizable(this);
2817}
2818
2819void WebPageProxy::setWindowFrame(const FloatRect& newWindowFrame)
2820{
2821    m_uiClient.setWindowFrame(this, m_pageClient->convertToDeviceSpace(newWindowFrame));
2822}
2823
2824void WebPageProxy::getWindowFrame(FloatRect& newWindowFrame)
2825{
2826    newWindowFrame = m_pageClient->convertToUserSpace(m_uiClient.windowFrame(this));
2827}
2828
2829void WebPageProxy::screenToWindow(const IntPoint& screenPoint, IntPoint& windowPoint)
2830{
2831    windowPoint = m_pageClient->screenToWindow(screenPoint);
2832}
2833
2834void WebPageProxy::windowToScreen(const IntRect& viewRect, IntRect& result)
2835{
2836    result = m_pageClient->windowToScreen(viewRect);
2837}
2838
2839void WebPageProxy::runBeforeUnloadConfirmPanel(const String& message, uint64_t frameID, bool& shouldClose)
2840{
2841    WebFrameProxy* frame = m_process->webFrame(frameID);
2842    MESSAGE_CHECK(frame);
2843
2844    // Since runBeforeUnloadConfirmPanel() can spin a nested run loop we need to turn off the responsiveness timer.
2845    m_process->responsivenessTimer()->stop();
2846
2847    shouldClose = m_uiClient.runBeforeUnloadConfirmPanel(this, message, frame);
2848}
2849
2850#if USE(TILED_BACKING_STORE)
2851void WebPageProxy::pageDidRequestScroll(const IntPoint& point)
2852{
2853    m_pageClient->pageDidRequestScroll(point);
2854}
2855
2856void WebPageProxy::pageTransitionViewportReady()
2857{
2858    m_pageClient->pageTransitionViewportReady();
2859}
2860
2861void WebPageProxy::didRenderFrame(const WebCore::IntSize& contentsSize, const WebCore::IntRect& coveredRect)
2862{
2863    m_pageClient->didRenderFrame(contentsSize, coveredRect);
2864}
2865
2866#endif
2867
2868void WebPageProxy::didChangeViewportProperties(const ViewportAttributes& attr)
2869{
2870    m_pageClient->didChangeViewportProperties(attr);
2871}
2872
2873void WebPageProxy::pageDidScroll()
2874{
2875    m_uiClient.pageDidScroll(this);
2876#if PLATFORM(MAC)
2877    dismissCorrectionPanel(ReasonForDismissingAlternativeTextIgnored);
2878#endif
2879}
2880
2881void WebPageProxy::runOpenPanel(uint64_t frameID, const FileChooserSettings& settings)
2882{
2883    if (m_openPanelResultListener) {
2884        m_openPanelResultListener->invalidate();
2885        m_openPanelResultListener = 0;
2886    }
2887
2888    WebFrameProxy* frame = m_process->webFrame(frameID);
2889    MESSAGE_CHECK(frame);
2890
2891    RefPtr<WebOpenPanelParameters> parameters = WebOpenPanelParameters::create(settings);
2892    m_openPanelResultListener = WebOpenPanelResultListenerProxy::create(this);
2893
2894    // Since runOpenPanel() can spin a nested run loop we need to turn off the responsiveness timer.
2895    m_process->responsivenessTimer()->stop();
2896
2897    if (!m_uiClient.runOpenPanel(this, frame, parameters.get(), m_openPanelResultListener.get()))
2898        didCancelForOpenPanel();
2899}
2900
2901void WebPageProxy::printFrame(uint64_t frameID)
2902{
2903    ASSERT(!m_isPerformingDOMPrintOperation);
2904    m_isPerformingDOMPrintOperation = true;
2905
2906    WebFrameProxy* frame = m_process->webFrame(frameID);
2907    MESSAGE_CHECK(frame);
2908
2909    m_uiClient.printFrame(this, frame);
2910
2911    endPrinting(); // Send a message synchronously while m_isPerformingDOMPrintOperation is still true.
2912    m_isPerformingDOMPrintOperation = false;
2913}
2914
2915void WebPageProxy::printMainFrame()
2916{
2917    printFrame(m_mainFrame->frameID());
2918}
2919
2920void WebPageProxy::setMediaVolume(float volume)
2921{
2922    if (volume == m_mediaVolume)
2923        return;
2924
2925    m_mediaVolume = volume;
2926
2927    if (!isValid())
2928        return;
2929
2930    m_process->send(Messages::WebPage::SetMediaVolume(volume), m_pageID);
2931}
2932
2933void WebPageProxy::setMayStartMediaWhenInWindow(bool mayStartMedia)
2934{
2935    if (mayStartMedia == m_mayStartMediaWhenInWindow)
2936        return;
2937
2938    m_mayStartMediaWhenInWindow = mayStartMedia;
2939
2940    if (!isValid())
2941        return;
2942
2943    process()->send(Messages::WebPage::SetMayStartMediaWhenInWindow(mayStartMedia), m_pageID);
2944}
2945
2946#if PLATFORM(QT) || PLATFORM(EFL) || PLATFORM(GTK)
2947void WebPageProxy::handleDownloadRequest(DownloadProxy* download)
2948{
2949    m_pageClient->handleDownloadRequest(download);
2950}
2951#endif // PLATFORM(QT) || PLATFORM(EFL) || PLATFORM(GTK)
2952
2953#if PLATFORM(QT) || PLATFORM(EFL)
2954void WebPageProxy::didChangeContentsSize(const IntSize& size)
2955{
2956    m_pageClient->didChangeContentsSize(size);
2957}
2958#endif
2959
2960#if ENABLE(TOUCH_EVENTS)
2961void WebPageProxy::needTouchEvents(bool needTouchEvents)
2962{
2963    m_needTouchEvents = needTouchEvents;
2964}
2965#endif
2966
2967#if ENABLE(INPUT_TYPE_COLOR)
2968void WebPageProxy::showColorChooser(const WebCore::Color& initialColor, const IntRect& elementRect)
2969{
2970    ASSERT(!m_colorChooser);
2971
2972    if (m_colorPickerResultListener) {
2973        m_colorPickerResultListener->invalidate();
2974        m_colorPickerResultListener = nullptr;
2975    }
2976
2977    m_colorPickerResultListener = WebColorPickerResultListenerProxy::create(this);
2978    m_colorChooser = WebColorChooserProxy::create(this);
2979
2980    if (m_uiClient.showColorPicker(this, initialColor.serialized(), m_colorPickerResultListener.get()))
2981        return;
2982
2983    m_colorChooser = m_pageClient->createColorChooserProxy(this, initialColor, elementRect);
2984    if (!m_colorChooser)
2985        didEndColorChooser();
2986}
2987
2988void WebPageProxy::setColorChooserColor(const WebCore::Color& color)
2989{
2990    ASSERT(m_colorChooser);
2991
2992    m_colorChooser->setSelectedColor(color);
2993}
2994
2995void WebPageProxy::endColorChooser()
2996{
2997    ASSERT(m_colorChooser);
2998
2999    m_colorChooser->endChooser();
3000}
3001
3002void WebPageProxy::didChooseColor(const WebCore::Color& color)
3003{
3004    if (!isValid())
3005        return;
3006
3007    m_process->send(Messages::WebPage::DidChooseColor(color), m_pageID);
3008}
3009
3010void WebPageProxy::didEndColorChooser()
3011{
3012    if (!isValid())
3013        return;
3014
3015    if (m_colorChooser) {
3016        m_colorChooser->invalidate();
3017        m_colorChooser = nullptr;
3018    }
3019
3020    m_process->send(Messages::WebPage::DidEndColorChooser(), m_pageID);
3021
3022    m_colorPickerResultListener->invalidate();
3023    m_colorPickerResultListener = nullptr;
3024
3025    m_uiClient.hideColorPicker(this);
3026}
3027#endif
3028
3029void WebPageProxy::didDraw()
3030{
3031    m_uiClient.didDraw(this);
3032}
3033
3034// Inspector
3035
3036#if ENABLE(INSPECTOR)
3037
3038WebInspectorProxy* WebPageProxy::inspector()
3039{
3040    if (isClosed() || !isValid())
3041        return 0;
3042    return m_inspector.get();
3043}
3044
3045#endif
3046
3047#if ENABLE(FULLSCREEN_API)
3048WebFullScreenManagerProxy* WebPageProxy::fullScreenManager()
3049{
3050    return m_fullScreenManager.get();
3051}
3052#endif
3053
3054// BackForwardList
3055
3056void WebPageProxy::backForwardAddItem(uint64_t itemID)
3057{
3058    m_backForwardList->addItem(m_process->webBackForwardItem(itemID));
3059}
3060
3061void WebPageProxy::backForwardGoToItem(uint64_t itemID, SandboxExtension::Handle& sandboxExtensionHandle)
3062{
3063    WebBackForwardListItem* item = m_process->webBackForwardItem(itemID);
3064    if (!item)
3065        return;
3066
3067    bool createdExtension = maybeInitializeSandboxExtensionHandle(KURL(KURL(), item->url()), sandboxExtensionHandle);
3068    if (createdExtension)
3069        m_process->willAcquireUniversalFileReadSandboxExtension();
3070    m_backForwardList->goToItem(item);
3071}
3072
3073void WebPageProxy::backForwardItemAtIndex(int32_t index, uint64_t& itemID)
3074{
3075    WebBackForwardListItem* item = m_backForwardList->itemAtIndex(index);
3076    itemID = item ? item->itemID() : 0;
3077}
3078
3079void WebPageProxy::backForwardBackListCount(int32_t& count)
3080{
3081    count = m_backForwardList->backListCount();
3082}
3083
3084void WebPageProxy::backForwardForwardListCount(int32_t& count)
3085{
3086    count = m_backForwardList->forwardListCount();
3087}
3088
3089void WebPageProxy::editorStateChanged(const EditorState& editorState)
3090{
3091#if PLATFORM(MAC)
3092    bool couldChangeSecureInputState = m_editorState.isInPasswordField != editorState.isInPasswordField || m_editorState.selectionIsNone;
3093    bool closedComposition = !editorState.shouldIgnoreCompositionSelectionChange && !editorState.hasComposition && (m_editorState.hasComposition || m_temporarilyClosedComposition);
3094    m_temporarilyClosedComposition = editorState.shouldIgnoreCompositionSelectionChange && (m_temporarilyClosedComposition || m_editorState.hasComposition) && !editorState.hasComposition;
3095#endif
3096
3097    m_editorState = editorState;
3098
3099#if PLATFORM(MAC)
3100    // Selection being none is a temporary state when editing. Flipping secure input state too quickly was causing trouble (not fully understood).
3101    if (couldChangeSecureInputState && !editorState.selectionIsNone)
3102        m_pageClient->updateSecureInputState();
3103
3104    if (editorState.shouldIgnoreCompositionSelectionChange)
3105        return;
3106
3107    if (closedComposition)
3108        m_pageClient->notifyInputContextAboutDiscardedComposition();
3109    if (editorState.hasComposition) {
3110        // Abandon the current inline input session if selection changed for any other reason but an input method changing the composition.
3111        // FIXME: This logic should be in WebCore, no need to round-trip to UI process to cancel the composition.
3112        cancelComposition();
3113        m_pageClient->notifyInputContextAboutDiscardedComposition();
3114    }
3115#elif PLATFORM(QT) || PLATFORM(EFL) || PLATFORM(GTK)
3116    m_pageClient->updateTextInputState();
3117#endif
3118}
3119
3120// Undo management
3121
3122void WebPageProxy::registerEditCommandForUndo(uint64_t commandID, uint32_t editAction)
3123{
3124    registerEditCommand(WebEditCommandProxy::create(commandID, static_cast<EditAction>(editAction), this), Undo);
3125}
3126
3127void WebPageProxy::canUndoRedo(uint32_t action, bool& result)
3128{
3129    result = m_pageClient->canUndoRedo(static_cast<UndoOrRedo>(action));
3130}
3131
3132void WebPageProxy::executeUndoRedo(uint32_t action, bool& result)
3133{
3134    m_pageClient->executeUndoRedo(static_cast<UndoOrRedo>(action));
3135    result = true;
3136}
3137
3138void WebPageProxy::clearAllEditCommands()
3139{
3140    m_pageClient->clearAllEditCommands();
3141}
3142
3143void WebPageProxy::didCountStringMatches(const String& string, uint32_t matchCount)
3144{
3145    m_findClient.didCountStringMatches(this, string, matchCount);
3146}
3147
3148void WebPageProxy::didGetImageForFindMatch(const ShareableBitmap::Handle& contentImageHandle, uint32_t matchIndex)
3149{
3150    m_findMatchesClient.didGetImageForMatchResult(this, WebImage::create(ShareableBitmap::create(contentImageHandle)).get(), matchIndex);
3151}
3152
3153void WebPageProxy::setFindIndicator(const FloatRect& selectionRectInWindowCoordinates, const Vector<FloatRect>& textRectsInSelectionRectCoordinates, float contentImageScaleFactor, const ShareableBitmap::Handle& contentImageHandle, bool fadeOut, bool animate)
3154{
3155    RefPtr<FindIndicator> findIndicator = FindIndicator::create(selectionRectInWindowCoordinates, textRectsInSelectionRectCoordinates, contentImageScaleFactor, contentImageHandle);
3156    m_pageClient->setFindIndicator(findIndicator.release(), fadeOut, animate);
3157}
3158
3159void WebPageProxy::didFindString(const String& string, uint32_t matchCount)
3160{
3161    m_findClient.didFindString(this, string, matchCount);
3162}
3163
3164void WebPageProxy::didFindStringMatches(const String& string, Vector<Vector<WebCore::IntRect>> matchRects, int32_t firstIndexAfterSelection)
3165{
3166    Vector<RefPtr<APIObject>> matches;
3167    matches.reserveInitialCapacity(matchRects.size());
3168
3169    for (size_t i = 0; i < matchRects.size(); ++i) {
3170        const Vector<WebCore::IntRect>& rects = matchRects[i];
3171        size_t numRects = matchRects[i].size();
3172        Vector<RefPtr<APIObject>> apiRects;
3173        apiRects.reserveInitialCapacity(numRects);
3174
3175        for (size_t i = 0; i < numRects; ++i)
3176            apiRects.uncheckedAppend(WebRect::create(toAPI(rects[i])));
3177        matches.uncheckedAppend(ImmutableArray::adopt(apiRects));
3178    }
3179    m_findMatchesClient.didFindStringMatches(this, string, ImmutableArray::adopt(matches).get(), firstIndexAfterSelection);
3180}
3181
3182void WebPageProxy::didFailToFindString(const String& string)
3183{
3184    m_findClient.didFailToFindString(this, string);
3185}
3186
3187void WebPageProxy::valueChangedForPopupMenu(WebPopupMenuProxy*, int32_t newSelectedIndex)
3188{
3189    m_process->send(Messages::WebPage::DidChangeSelectedIndexForActivePopupMenu(newSelectedIndex), m_pageID);
3190}
3191
3192void WebPageProxy::setTextFromItemForPopupMenu(WebPopupMenuProxy*, int32_t index)
3193{
3194    m_process->send(Messages::WebPage::SetTextForActivePopupMenu(index), m_pageID);
3195}
3196
3197NativeWebMouseEvent* WebPageProxy::currentlyProcessedMouseDownEvent()
3198{
3199    return m_currentlyProcessedMouseDownEvent.get();
3200}
3201
3202void WebPageProxy::postMessageToInjectedBundle(const String& messageName, APIObject* messageBody)
3203{
3204    process()->send(Messages::WebPage::PostInjectedBundleMessage(messageName, WebContextUserMessageEncoder(messageBody)), m_pageID);
3205}
3206
3207#if PLATFORM(GTK)
3208void WebPageProxy::failedToShowPopupMenu()
3209{
3210    m_process->send(Messages::WebPage::FailedToShowPopupMenu(), m_pageID);
3211}
3212#endif
3213
3214void WebPageProxy::showPopupMenu(const IntRect& rect, uint64_t textDirection, const Vector<WebPopupItem>& items, int32_t selectedIndex, const PlatformPopupMenuData& data)
3215{
3216    if (m_activePopupMenu) {
3217#if PLATFORM(EFL)
3218        m_uiPopupMenuClient.hidePopupMenu(this);
3219#else
3220        m_activePopupMenu->hidePopupMenu();
3221#endif
3222        m_activePopupMenu->invalidate();
3223        m_activePopupMenu = 0;
3224    }
3225
3226    m_activePopupMenu = m_pageClient->createPopupMenuProxy(this);
3227
3228    if (!m_activePopupMenu)
3229        return;
3230
3231    // Since showPopupMenu() can spin a nested run loop we need to turn off the responsiveness timer.
3232    m_process->responsivenessTimer()->stop();
3233
3234#if PLATFORM(EFL)
3235    UNUSED_PARAM(data);
3236    m_uiPopupMenuClient.showPopupMenu(this, m_activePopupMenu.get(), rect, static_cast<TextDirection>(textDirection), m_pageScaleFactor, items, selectedIndex);
3237#else
3238    RefPtr<WebPopupMenuProxy> protectedActivePopupMenu = m_activePopupMenu;
3239
3240    protectedActivePopupMenu->showPopupMenu(rect, static_cast<TextDirection>(textDirection), m_pageScaleFactor, items, data, selectedIndex);
3241
3242    // Since Qt and Efl doesn't use a nested mainloop to show the popup and get the answer, we need to keep the client pointer valid.
3243#if !PLATFORM(QT)
3244    protectedActivePopupMenu->invalidate();
3245#endif
3246    protectedActivePopupMenu = 0;
3247#endif
3248}
3249
3250void WebPageProxy::hidePopupMenu()
3251{
3252    if (!m_activePopupMenu)
3253        return;
3254
3255#if PLATFORM(EFL)
3256    m_uiPopupMenuClient.hidePopupMenu(this);
3257#else
3258    m_activePopupMenu->hidePopupMenu();
3259#endif
3260    m_activePopupMenu->invalidate();
3261    m_activePopupMenu = 0;
3262}
3263
3264#if ENABLE(CONTEXT_MENUS)
3265void WebPageProxy::showContextMenu(const IntPoint& menuLocation, const WebHitTestResult::Data& hitTestResultData, const Vector<WebContextMenuItemData>& proposedItems, CoreIPC::MessageDecoder& decoder)
3266{
3267    internalShowContextMenu(menuLocation, hitTestResultData, proposedItems, decoder);
3268
3269    // No matter the result of internalShowContextMenu, always notify the WebProcess that the menu is hidden so it starts handling mouse events again.
3270    m_process->send(Messages::WebPage::ContextMenuHidden(), m_pageID);
3271}
3272
3273void WebPageProxy::internalShowContextMenu(const IntPoint& menuLocation, const WebHitTestResult::Data& hitTestResultData, const Vector<WebContextMenuItemData>& proposedItems, CoreIPC::MessageDecoder& decoder)
3274{
3275    RefPtr<APIObject> userData;
3276    WebContextUserMessageDecoder messageDecoder(userData, m_process.get());
3277    if (!decoder.decode(messageDecoder))
3278        return;
3279
3280    m_activeContextMenuHitTestResultData = hitTestResultData;
3281
3282    if (!m_contextMenuClient.hideContextMenu(this) && m_activeContextMenu) {
3283        m_activeContextMenu->hideContextMenu();
3284        m_activeContextMenu = 0;
3285    }
3286
3287    m_activeContextMenu = m_pageClient->createContextMenuProxy(this);
3288    if (!m_activeContextMenu)
3289        return;
3290
3291    // Since showContextMenu() can spin a nested run loop we need to turn off the responsiveness timer.
3292    m_process->responsivenessTimer()->stop();
3293
3294    // Give the PageContextMenuClient one last swipe at changing the menu.
3295    Vector<WebContextMenuItemData> items;
3296    if (!m_contextMenuClient.getContextMenuFromProposedMenu(this, proposedItems, items, hitTestResultData, userData.get())) {
3297        if (!m_contextMenuClient.showContextMenu(this, menuLocation, proposedItems))
3298            m_activeContextMenu->showContextMenu(menuLocation, proposedItems);
3299    } else if (!m_contextMenuClient.showContextMenu(this, menuLocation, items))
3300        m_activeContextMenu->showContextMenu(menuLocation, items);
3301
3302    m_contextMenuClient.contextMenuDismissed(this);
3303}
3304
3305void WebPageProxy::contextMenuItemSelected(const WebContextMenuItemData& item)
3306{
3307    // Application custom items don't need to round-trip through to WebCore in the WebProcess.
3308    if (item.action() >= ContextMenuItemBaseApplicationTag) {
3309        m_contextMenuClient.customContextMenuItemSelected(this, item);
3310        return;
3311    }
3312
3313#if PLATFORM(MAC)
3314    if (item.action() == ContextMenuItemTagSmartCopyPaste) {
3315        setSmartInsertDeleteEnabled(!isSmartInsertDeleteEnabled());
3316        return;
3317    }
3318    if (item.action() == ContextMenuItemTagSmartQuotes) {
3319        TextChecker::setAutomaticQuoteSubstitutionEnabled(!TextChecker::state().isAutomaticQuoteSubstitutionEnabled);
3320        m_process->updateTextCheckerState();
3321        return;
3322    }
3323    if (item.action() == ContextMenuItemTagSmartDashes) {
3324        TextChecker::setAutomaticDashSubstitutionEnabled(!TextChecker::state().isAutomaticDashSubstitutionEnabled);
3325        m_process->updateTextCheckerState();
3326        return;
3327    }
3328    if (item.action() == ContextMenuItemTagSmartLinks) {
3329        TextChecker::setAutomaticLinkDetectionEnabled(!TextChecker::state().isAutomaticLinkDetectionEnabled);
3330        m_process->updateTextCheckerState();
3331        return;
3332    }
3333    if (item.action() == ContextMenuItemTagTextReplacement) {
3334        TextChecker::setAutomaticTextReplacementEnabled(!TextChecker::state().isAutomaticTextReplacementEnabled);
3335        m_process->updateTextCheckerState();
3336        return;
3337    }
3338    if (item.action() == ContextMenuItemTagCorrectSpellingAutomatically) {
3339        TextChecker::setAutomaticSpellingCorrectionEnabled(!TextChecker::state().isAutomaticSpellingCorrectionEnabled);
3340        m_process->updateTextCheckerState();
3341        return;
3342    }
3343    if (item.action() == ContextMenuItemTagShowSubstitutions) {
3344        TextChecker::toggleSubstitutionsPanelIsShowing();
3345        return;
3346    }
3347#endif
3348    if (item.action() == ContextMenuItemTagDownloadImageToDisk) {
3349        m_process->context()->download(this, KURL(KURL(), m_activeContextMenuHitTestResultData.absoluteImageURL));
3350        return;
3351    }
3352    if (item.action() == ContextMenuItemTagDownloadLinkToDisk) {
3353        m_process->context()->download(this, KURL(KURL(), m_activeContextMenuHitTestResultData.absoluteLinkURL));
3354        return;
3355    }
3356    if (item.action() == ContextMenuItemTagDownloadMediaToDisk) {
3357        m_process->context()->download(this, KURL(KURL(), m_activeContextMenuHitTestResultData.absoluteMediaURL));
3358        return;
3359    }
3360    if (item.action() == ContextMenuItemTagCheckSpellingWhileTyping) {
3361        TextChecker::setContinuousSpellCheckingEnabled(!TextChecker::state().isContinuousSpellCheckingEnabled);
3362        m_process->updateTextCheckerState();
3363        return;
3364    }
3365    if (item.action() == ContextMenuItemTagCheckGrammarWithSpelling) {
3366        TextChecker::setGrammarCheckingEnabled(!TextChecker::state().isGrammarCheckingEnabled);
3367        m_process->updateTextCheckerState();
3368        return;
3369    }
3370    if (item.action() == ContextMenuItemTagShowSpellingPanel) {
3371        if (!TextChecker::spellingUIIsShowing())
3372            advanceToNextMisspelling(true);
3373        TextChecker::toggleSpellingUIIsShowing();
3374        return;
3375    }
3376    if (item.action() == ContextMenuItemTagLearnSpelling || item.action() == ContextMenuItemTagIgnoreSpelling)
3377        ++m_pendingLearnOrIgnoreWordMessageCount;
3378
3379    m_process->send(Messages::WebPage::DidSelectItemFromActiveContextMenu(item), m_pageID);
3380}
3381#endif // ENABLE(CONTEXT_MENUS)
3382
3383void WebPageProxy::didChooseFilesForOpenPanel(const Vector<String>& fileURLs)
3384{
3385    if (!isValid())
3386        return;
3387
3388#if ENABLE(WEB_PROCESS_SANDBOX)
3389    // FIXME: The sandbox extensions should be sent with the DidChooseFilesForOpenPanel message. This
3390    // is gated on a way of passing SandboxExtension::Handles in a Vector.
3391    for (size_t i = 0; i < fileURLs.size(); ++i) {
3392        SandboxExtension::Handle sandboxExtensionHandle;
3393        SandboxExtension::createHandle(fileURLs[i], SandboxExtension::ReadOnly, sandboxExtensionHandle);
3394        m_process->send(Messages::WebPage::ExtendSandboxForFileFromOpenPanel(sandboxExtensionHandle), m_pageID);
3395    }
3396#endif
3397
3398    m_process->send(Messages::WebPage::DidChooseFilesForOpenPanel(fileURLs), m_pageID);
3399
3400    m_openPanelResultListener->invalidate();
3401    m_openPanelResultListener = 0;
3402}
3403
3404void WebPageProxy::didCancelForOpenPanel()
3405{
3406    if (!isValid())
3407        return;
3408
3409    m_process->send(Messages::WebPage::DidCancelForOpenPanel(), m_pageID);
3410
3411    m_openPanelResultListener->invalidate();
3412    m_openPanelResultListener = 0;
3413}
3414
3415void WebPageProxy::advanceToNextMisspelling(bool startBeforeSelection) const
3416{
3417    m_process->send(Messages::WebPage::AdvanceToNextMisspelling(startBeforeSelection), m_pageID);
3418}
3419
3420void WebPageProxy::changeSpellingToWord(const String& word) const
3421{
3422    if (word.isEmpty())
3423        return;
3424
3425    m_process->send(Messages::WebPage::ChangeSpellingToWord(word), m_pageID);
3426}
3427
3428void WebPageProxy::registerEditCommand(PassRefPtr<WebEditCommandProxy> commandProxy, UndoOrRedo undoOrRedo)
3429{
3430    m_pageClient->registerEditCommand(commandProxy, undoOrRedo);
3431}
3432
3433void WebPageProxy::addEditCommand(WebEditCommandProxy* command)
3434{
3435    m_editCommandSet.add(command);
3436}
3437
3438void WebPageProxy::removeEditCommand(WebEditCommandProxy* command)
3439{
3440    m_editCommandSet.remove(command);
3441
3442    if (!isValid())
3443        return;
3444    m_process->send(Messages::WebPage::DidRemoveEditCommand(command->commandID()), m_pageID);
3445}
3446
3447bool WebPageProxy::isValidEditCommand(WebEditCommandProxy* command)
3448{
3449    return m_editCommandSet.find(command) != m_editCommandSet.end();
3450}
3451
3452int64_t WebPageProxy::spellDocumentTag()
3453{
3454    if (!m_hasSpellDocumentTag) {
3455        m_spellDocumentTag = TextChecker::uniqueSpellDocumentTag(this);
3456        m_hasSpellDocumentTag = true;
3457    }
3458
3459    return m_spellDocumentTag;
3460}
3461
3462#if USE(UNIFIED_TEXT_CHECKING)
3463void WebPageProxy::checkTextOfParagraph(const String& text, uint64_t checkingTypes, Vector<TextCheckingResult>& results)
3464{
3465    results = TextChecker::checkTextOfParagraph(spellDocumentTag(), text.characters(), text.length(), checkingTypes);
3466}
3467#endif
3468
3469void WebPageProxy::checkSpellingOfString(const String& text, int32_t& misspellingLocation, int32_t& misspellingLength)
3470{
3471    TextChecker::checkSpellingOfString(spellDocumentTag(), text.characters(), text.length(), misspellingLocation, misspellingLength);
3472}
3473
3474void WebPageProxy::checkGrammarOfString(const String& text, Vector<GrammarDetail>& grammarDetails, int32_t& badGrammarLocation, int32_t& badGrammarLength)
3475{
3476    TextChecker::checkGrammarOfString(spellDocumentTag(), text.characters(), text.length(), grammarDetails, badGrammarLocation, badGrammarLength);
3477}
3478
3479void WebPageProxy::spellingUIIsShowing(bool& isShowing)
3480{
3481    isShowing = TextChecker::spellingUIIsShowing();
3482}
3483
3484void WebPageProxy::updateSpellingUIWithMisspelledWord(const String& misspelledWord)
3485{
3486    TextChecker::updateSpellingUIWithMisspelledWord(spellDocumentTag(), misspelledWord);
3487}
3488
3489void WebPageProxy::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail)
3490{
3491    TextChecker::updateSpellingUIWithGrammarString(spellDocumentTag(), badGrammarPhrase, grammarDetail);
3492}
3493
3494void WebPageProxy::getGuessesForWord(const String& word, const String& context, Vector<String>& guesses)
3495{
3496    TextChecker::getGuessesForWord(spellDocumentTag(), word, context, guesses);
3497}
3498
3499void WebPageProxy::learnWord(const String& word)
3500{
3501    MESSAGE_CHECK(m_pendingLearnOrIgnoreWordMessageCount);
3502    --m_pendingLearnOrIgnoreWordMessageCount;
3503
3504    TextChecker::learnWord(spellDocumentTag(), word);
3505}
3506
3507void WebPageProxy::ignoreWord(const String& word)
3508{
3509    MESSAGE_CHECK(m_pendingLearnOrIgnoreWordMessageCount);
3510    --m_pendingLearnOrIgnoreWordMessageCount;
3511
3512    TextChecker::ignoreWord(spellDocumentTag(), word);
3513}
3514
3515void WebPageProxy::requestCheckingOfString(uint64_t requestID, const TextCheckingRequestData& request)
3516{
3517    TextChecker::requestCheckingOfString(TextCheckerCompletion::create(requestID, request, this));
3518}
3519
3520void WebPageProxy::didFinishCheckingText(uint64_t requestID, const Vector<WebCore::TextCheckingResult>& result) const
3521{
3522    m_process->send(Messages::WebPage::DidFinishCheckingText(requestID, result), m_pageID);
3523}
3524
3525void WebPageProxy::didCancelCheckingText(uint64_t requestID) const
3526{
3527    m_process->send(Messages::WebPage::DidCancelCheckingText(requestID), m_pageID);
3528}
3529// Other
3530
3531void WebPageProxy::setFocus(bool focused)
3532{
3533    if (focused)
3534        m_uiClient.focus(this);
3535    else
3536        m_uiClient.unfocus(this);
3537}
3538
3539void WebPageProxy::takeFocus(uint32_t direction)
3540{
3541    m_uiClient.takeFocus(this, (static_cast<FocusDirection>(direction) == FocusDirectionForward) ? kWKFocusDirectionForward : kWKFocusDirectionBackward);
3542}
3543
3544void WebPageProxy::setToolTip(const String& toolTip)
3545{
3546    String oldToolTip = m_toolTip;
3547    m_toolTip = toolTip;
3548    m_pageClient->toolTipChanged(oldToolTip, m_toolTip);
3549}
3550
3551void WebPageProxy::setCursor(const WebCore::Cursor& cursor)
3552{
3553    // The Web process may have asked to change the cursor when the view was in an active window, but
3554    // if it is no longer in a window or the window is not active, then the cursor should not change.
3555    if (m_pageClient->isViewWindowActive())
3556        m_pageClient->setCursor(cursor);
3557}
3558
3559void WebPageProxy::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves)
3560{
3561    m_pageClient->setCursorHiddenUntilMouseMoves(hiddenUntilMouseMoves);
3562}
3563
3564void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
3565{
3566    WebEvent::Type type = static_cast<WebEvent::Type>(opaqueType);
3567
3568    switch (type) {
3569    case WebEvent::NoType:
3570    case WebEvent::MouseMove:
3571        break;
3572
3573    case WebEvent::MouseDown:
3574    case WebEvent::MouseUp:
3575    case WebEvent::Wheel:
3576    case WebEvent::KeyDown:
3577    case WebEvent::KeyUp:
3578    case WebEvent::RawKeyDown:
3579    case WebEvent::Char:
3580#if ENABLE(GESTURE_EVENTS)
3581    case WebEvent::GestureScrollBegin:
3582    case WebEvent::GestureScrollEnd:
3583    case WebEvent::GestureSingleTap:
3584#endif
3585#if ENABLE(TOUCH_EVENTS)
3586    case WebEvent::TouchStart:
3587    case WebEvent::TouchMove:
3588    case WebEvent::TouchEnd:
3589    case WebEvent::TouchCancel:
3590#endif
3591        m_process->responsivenessTimer()->stop();
3592        break;
3593    }
3594
3595    switch (type) {
3596    case WebEvent::NoType:
3597        break;
3598    case WebEvent::MouseMove:
3599        m_processingMouseMoveEvent = false;
3600        if (m_nextMouseMoveEvent) {
3601            handleMouseEvent(*m_nextMouseMoveEvent);
3602            m_nextMouseMoveEvent = nullptr;
3603        }
3604        break;
3605    case WebEvent::MouseDown:
3606        break;
3607#if ENABLE(GESTURE_EVENTS)
3608    case WebEvent::GestureScrollBegin:
3609    case WebEvent::GestureScrollEnd:
3610    case WebEvent::GestureSingleTap: {
3611        WebGestureEvent event = m_gestureEventQueue.first();
3612        MESSAGE_CHECK(type == event.type());
3613
3614        m_gestureEventQueue.removeFirst();
3615        m_pageClient->doneWithGestureEvent(event, handled);
3616        break;
3617    }
3618#endif
3619    case WebEvent::MouseUp:
3620        m_currentlyProcessedMouseDownEvent = nullptr;
3621        break;
3622
3623    case WebEvent::Wheel: {
3624        MESSAGE_CHECK(!m_currentlyProcessedWheelEvents.isEmpty());
3625
3626        OwnPtr<Vector<NativeWebWheelEvent>> oldestCoalescedEvent = m_currentlyProcessedWheelEvents.takeFirst();
3627
3628        // FIXME: Dispatch additional events to the didNotHandleWheelEvent client function.
3629        if (!handled && m_uiClient.implementsDidNotHandleWheelEvent())
3630            m_uiClient.didNotHandleWheelEvent(this, oldestCoalescedEvent->last());
3631
3632        if (!m_wheelEventQueue.isEmpty())
3633            processNextQueuedWheelEvent();
3634        break;
3635    }
3636
3637    case WebEvent::KeyDown:
3638    case WebEvent::KeyUp:
3639    case WebEvent::RawKeyDown:
3640    case WebEvent::Char: {
3641        LOG(KeyHandling, "WebPageProxy::didReceiveEvent: %s", webKeyboardEventTypeString(type));
3642
3643        MESSAGE_CHECK(!m_keyEventQueue.isEmpty());
3644        NativeWebKeyboardEvent event = m_keyEventQueue.takeFirst();
3645
3646        MESSAGE_CHECK(type == event.type());
3647
3648        if (!m_keyEventQueue.isEmpty())
3649            m_process->send(Messages::WebPage::KeyEvent(m_keyEventQueue.first()), m_pageID);
3650
3651        m_pageClient->doneWithKeyEvent(event, handled);
3652        if (handled)
3653            break;
3654
3655        if (m_uiClient.implementsDidNotHandleKeyEvent())
3656            m_uiClient.didNotHandleKeyEvent(this, event);
3657        break;
3658    }
3659#if ENABLE(TOUCH_EVENTS)
3660    case WebEvent::TouchStart:
3661    case WebEvent::TouchMove:
3662    case WebEvent::TouchEnd:
3663    case WebEvent::TouchCancel: {
3664        MESSAGE_CHECK(!m_touchEventQueue.isEmpty());
3665        QueuedTouchEvents queuedEvents = m_touchEventQueue.takeFirst();
3666
3667        MESSAGE_CHECK(type == queuedEvents.forwardedEvent.type());
3668
3669        m_pageClient->doneWithTouchEvent(queuedEvents.forwardedEvent, handled);
3670        for (size_t i = 0; i < queuedEvents.deferredTouchEvents.size(); ++i) {
3671            bool isEventHandled = false;
3672            m_pageClient->doneWithTouchEvent(queuedEvents.deferredTouchEvents.at(i), isEventHandled);
3673        }
3674        break;
3675    }
3676#endif
3677    }
3678}
3679
3680void WebPageProxy::stopResponsivenessTimer()
3681{
3682    m_process->responsivenessTimer()->stop();
3683}
3684
3685void WebPageProxy::voidCallback(uint64_t callbackID)
3686{
3687    RefPtr<VoidCallback> callback = m_voidCallbacks.take(callbackID);
3688    if (!callback) {
3689        // FIXME: Log error or assert.
3690        return;
3691    }
3692
3693    callback->performCallback();
3694}
3695
3696void WebPageProxy::dataCallback(const CoreIPC::DataReference& dataReference, uint64_t callbackID)
3697{
3698    RefPtr<DataCallback> callback = m_dataCallbacks.take(callbackID);
3699    if (!callback) {
3700        // FIXME: Log error or assert.
3701        return;
3702    }
3703
3704    callback->performCallbackWithReturnValue(WebData::create(dataReference.data(), dataReference.size()).get());
3705}
3706
3707void WebPageProxy::imageCallback(const ShareableBitmap::Handle& bitmapHandle, uint64_t callbackID)
3708{
3709    RefPtr<ImageCallback> callback = m_imageCallbacks.take(callbackID);
3710    if (!callback) {
3711        // FIXME: Log error or assert.
3712        return;
3713    }
3714
3715    callback->performCallbackWithReturnValue(bitmapHandle);
3716}
3717
3718void WebPageProxy::stringCallback(const String& resultString, uint64_t callbackID)
3719{
3720    RefPtr<StringCallback> callback = m_stringCallbacks.take(callbackID);
3721    if (!callback) {
3722        // FIXME: Log error or assert.
3723        // this can validly happen if a load invalidated the callback, though
3724        return;
3725    }
3726
3727    m_loadDependentStringCallbackIDs.remove(callbackID);
3728
3729    callback->performCallbackWithReturnValue(resultString.impl());
3730}
3731
3732void WebPageProxy::scriptValueCallback(const CoreIPC::DataReference& dataReference, uint64_t callbackID)
3733{
3734    RefPtr<ScriptValueCallback> callback = m_scriptValueCallbacks.take(callbackID);
3735    if (!callback) {
3736        // FIXME: Log error or assert.
3737        return;
3738    }
3739
3740    Vector<uint8_t> data;
3741    data.reserveInitialCapacity(dataReference.size());
3742    data.append(dataReference.data(), dataReference.size());
3743
3744    callback->performCallbackWithReturnValue(data.size() ? WebSerializedScriptValue::adopt(data).get() : 0);
3745}
3746
3747void WebPageProxy::computedPagesCallback(const Vector<IntRect>& pageRects, double totalScaleFactorForPrinting, uint64_t callbackID)
3748{
3749    RefPtr<ComputedPagesCallback> callback = m_computedPagesCallbacks.take(callbackID);
3750    if (!callback) {
3751        // FIXME: Log error or assert.
3752        return;
3753    }
3754
3755    callback->performCallbackWithReturnValue(pageRects, totalScaleFactorForPrinting);
3756}
3757
3758void WebPageProxy::validateCommandCallback(const String& commandName, bool isEnabled, int state, uint64_t callbackID)
3759{
3760    RefPtr<ValidateCommandCallback> callback = m_validateCommandCallbacks.take(callbackID);
3761    if (!callback) {
3762        // FIXME: Log error or assert.
3763        return;
3764    }
3765
3766    callback->performCallbackWithReturnValue(commandName.impl(), isEnabled, state);
3767}
3768
3769#if PLATFORM(GTK)
3770void WebPageProxy::printFinishedCallback(const ResourceError& printError, uint64_t callbackID)
3771{
3772    RefPtr<PrintFinishedCallback> callback = m_printFinishedCallbacks.take(callbackID);
3773    if (!callback) {
3774        // FIXME: Log error or assert.
3775        return;
3776    }
3777
3778    RefPtr<WebError> error = WebError::create(printError);
3779    callback->performCallbackWithReturnValue(error.get());
3780}
3781#endif
3782
3783void WebPageProxy::focusedFrameChanged(uint64_t frameID)
3784{
3785    if (!frameID) {
3786        m_focusedFrame = 0;
3787        return;
3788    }
3789
3790    WebFrameProxy* frame = m_process->webFrame(frameID);
3791    MESSAGE_CHECK(frame);
3792
3793    m_focusedFrame = frame;
3794}
3795
3796void WebPageProxy::frameSetLargestFrameChanged(uint64_t frameID)
3797{
3798    if (!frameID) {
3799        m_frameSetLargestFrame = 0;
3800        return;
3801    }
3802
3803    WebFrameProxy* frame = m_process->webFrame(frameID);
3804    MESSAGE_CHECK(frame);
3805
3806    m_frameSetLargestFrame = frame;
3807}
3808
3809void WebPageProxy::processDidBecomeUnresponsive()
3810{
3811    if (!isValid())
3812        return;
3813
3814    updateBackingStoreDiscardableState();
3815
3816    m_loaderClient.processDidBecomeUnresponsive(this);
3817}
3818
3819void WebPageProxy::interactionOccurredWhileProcessUnresponsive()
3820{
3821    if (!isValid())
3822        return;
3823
3824    m_loaderClient.interactionOccurredWhileProcessUnresponsive(this);
3825}
3826
3827void WebPageProxy::processDidBecomeResponsive()
3828{
3829    if (!isValid())
3830        return;
3831
3832    updateBackingStoreDiscardableState();
3833
3834    m_loaderClient.processDidBecomeResponsive(this);
3835}
3836
3837void WebPageProxy::processDidCrash()
3838{
3839    ASSERT(m_isValid);
3840
3841    resetStateAfterProcessExited();
3842
3843    m_pageClient->processDidCrash();
3844    m_loaderClient.processDidCrash(this);
3845}
3846
3847void WebPageProxy::resetStateAfterProcessExited()
3848{
3849    if (!isValid())
3850        return;
3851
3852    ASSERT(m_pageClient);
3853    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
3854
3855    m_isValid = false;
3856    m_isPageSuspended = false;
3857    m_waitingForDidUpdateInWindowState = false;
3858
3859    if (m_mainFrame) {
3860        m_urlAtProcessExit = m_mainFrame->url();
3861        m_loadStateAtProcessExit = m_mainFrame->loadState();
3862    }
3863
3864    m_mainFrame = nullptr;
3865    m_drawingArea = nullptr;
3866
3867#if ENABLE(INSPECTOR)
3868    m_inspector->invalidate();
3869    m_inspector = nullptr;
3870#endif
3871
3872#if ENABLE(FULLSCREEN_API)
3873    m_fullScreenManager->invalidate();
3874    m_fullScreenManager = nullptr;
3875#endif
3876
3877#if ENABLE(VIBRATION)
3878    m_vibration->invalidate();
3879#endif
3880
3881    if (m_openPanelResultListener) {
3882        m_openPanelResultListener->invalidate();
3883        m_openPanelResultListener = nullptr;
3884    }
3885
3886#if ENABLE(INPUT_TYPE_COLOR)
3887    if (m_colorChooser) {
3888        m_colorChooser->invalidate();
3889        m_colorChooser = nullptr;
3890    }
3891
3892    if (m_colorPickerResultListener) {
3893        m_colorPickerResultListener->invalidate();
3894        m_colorPickerResultListener = nullptr;
3895    }
3896#endif
3897
3898#if ENABLE(GEOLOCATION)
3899    m_geolocationPermissionRequestManager.invalidateRequests();
3900#endif
3901
3902    m_notificationPermissionRequestManager.invalidateRequests();
3903
3904    m_toolTip = String();
3905
3906    m_mainFrameHasHorizontalScrollbar = false;
3907    m_mainFrameHasVerticalScrollbar = false;
3908
3909    m_mainFrameIsPinnedToLeftSide = false;
3910    m_mainFrameIsPinnedToRightSide = false;
3911    m_mainFrameIsPinnedToTopSide = false;
3912    m_mainFrameIsPinnedToBottomSide = false;
3913
3914    m_visibleScrollerThumbRect = IntRect();
3915
3916    invalidateCallbackMap(m_voidCallbacks);
3917    invalidateCallbackMap(m_dataCallbacks);
3918    invalidateCallbackMap(m_stringCallbacks);
3919    m_loadDependentStringCallbackIDs.clear();
3920    invalidateCallbackMap(m_scriptValueCallbacks);
3921    invalidateCallbackMap(m_computedPagesCallbacks);
3922    invalidateCallbackMap(m_validateCommandCallbacks);
3923#if PLATFORM(GTK)
3924    invalidateCallbackMap(m_printFinishedCallbacks);
3925#endif
3926
3927    Vector<WebEditCommandProxy*> editCommandVector;
3928    copyToVector(m_editCommandSet, editCommandVector);
3929    m_editCommandSet.clear();
3930    for (size_t i = 0, size = editCommandVector.size(); i < size; ++i)
3931        editCommandVector[i]->invalidate();
3932    m_pageClient->clearAllEditCommands();
3933
3934    m_activePopupMenu = 0;
3935
3936    m_estimatedProgress = 0.0;
3937
3938    m_pendingLearnOrIgnoreWordMessageCount = 0;
3939
3940    // If the call out to the loader client didn't cause the web process to be relaunched,
3941    // we'll call setNeedsDisplay on the view so that we won't have the old contents showing.
3942    // If the call did cause the web process to be relaunched, we'll keep the old page contents showing
3943    // until the new web process has painted its contents.
3944    setViewNeedsDisplay(IntRect(IntPoint(), viewSize()));
3945
3946    // Can't expect DidReceiveEvent notifications from a crashed web process.
3947#if ENABLE(GESTURE_EVENTS)
3948    m_gestureEventQueue.clear();
3949#endif
3950    m_keyEventQueue.clear();
3951    m_wheelEventQueue.clear();
3952    m_currentlyProcessedWheelEvents.clear();
3953
3954    m_nextMouseMoveEvent = nullptr;
3955    m_currentlyProcessedMouseDownEvent = nullptr;
3956
3957    m_processingMouseMoveEvent = false;
3958
3959#if ENABLE(TOUCH_EVENTS)
3960    m_needTouchEvents = false;
3961    m_touchEventQueue.clear();
3962#endif
3963
3964    // FIXME: Reset m_editorState.
3965    // FIXME: Notify input methods about abandoned composition.
3966    m_temporarilyClosedComposition = false;
3967
3968#if PLATFORM(MAC)
3969    dismissCorrectionPanel(ReasonForDismissingAlternativeTextIgnored);
3970    m_pageClient->dismissDictionaryLookupPanel();
3971#endif
3972}
3973
3974WebPageCreationParameters WebPageProxy::creationParameters() const
3975{
3976    WebPageCreationParameters parameters;
3977
3978    parameters.viewSize = m_pageClient->viewSize();
3979    parameters.isActive = m_pageClient->isViewWindowActive();
3980    parameters.isFocused = m_pageClient->isViewFocused();
3981    parameters.isVisible = m_pageClient->isViewVisible();
3982    parameters.isInWindow = m_pageClient->isViewInWindow();
3983    parameters.drawingAreaType = m_drawingArea->type();
3984    parameters.store = m_pageGroup->preferences()->store();
3985    parameters.pageGroupData = m_pageGroup->data();
3986    parameters.drawsBackground = m_drawsBackground;
3987    parameters.drawsTransparentBackground = m_drawsTransparentBackground;
3988    parameters.underlayColor = m_underlayColor;
3989    parameters.areMemoryCacheClientCallsEnabled = m_areMemoryCacheClientCallsEnabled;
3990    parameters.useFixedLayout = m_useFixedLayout;
3991    parameters.fixedLayoutSize = m_fixedLayoutSize;
3992    parameters.suppressScrollbarAnimations = m_suppressScrollbarAnimations;
3993    parameters.paginationMode = m_paginationMode;
3994    parameters.paginationBehavesLikeColumns = m_paginationBehavesLikeColumns;
3995    parameters.pageLength = m_pageLength;
3996    parameters.gapBetweenPages = m_gapBetweenPages;
3997    parameters.userAgent = userAgent();
3998    parameters.sessionState = SessionState(m_backForwardList->entries(), m_backForwardList->currentIndex());
3999    parameters.highestUsedBackForwardItemID = WebBackForwardListItem::highedUsedItemID();
4000    parameters.canRunBeforeUnloadConfirmPanel = m_uiClient.canRunBeforeUnloadConfirmPanel();
4001    parameters.canRunModal = m_canRunModal;
4002    parameters.deviceScaleFactor = deviceScaleFactor();
4003    parameters.mediaVolume = m_mediaVolume;
4004    parameters.mayStartMediaWhenInWindow = m_mayStartMediaWhenInWindow;
4005    parameters.minimumLayoutSize = m_minimumLayoutSize;
4006    parameters.autoSizingShouldExpandToViewHeight = m_autoSizingShouldExpandToViewHeight;
4007    parameters.scrollPinningBehavior = m_scrollPinningBehavior;
4008
4009#if PLATFORM(MAC)
4010    parameters.layerHostingMode = m_layerHostingMode;
4011    parameters.colorSpace = m_pageClient->colorSpace();
4012#endif
4013
4014    return parameters;
4015}
4016
4017#if USE(ACCELERATED_COMPOSITING)
4018void WebPageProxy::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
4019{
4020    m_pageClient->enterAcceleratedCompositingMode(layerTreeContext);
4021}
4022
4023void WebPageProxy::exitAcceleratedCompositingMode()
4024{
4025    m_pageClient->exitAcceleratedCompositingMode();
4026}
4027
4028void WebPageProxy::updateAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
4029{
4030    m_pageClient->updateAcceleratedCompositingMode(layerTreeContext);
4031}
4032#endif // USE(ACCELERATED_COMPOSITING)
4033
4034void WebPageProxy::backForwardClear()
4035{
4036    m_backForwardList->clear();
4037}
4038
4039void WebPageProxy::canAuthenticateAgainstProtectionSpaceInFrame(uint64_t frameID, const ProtectionSpace& coreProtectionSpace, bool& canAuthenticate)
4040{
4041    WebFrameProxy* frame = m_process->webFrame(frameID);
4042    MESSAGE_CHECK(frame);
4043
4044    RefPtr<WebProtectionSpace> protectionSpace = WebProtectionSpace::create(coreProtectionSpace);
4045
4046    canAuthenticate = m_loaderClient.canAuthenticateAgainstProtectionSpaceInFrame(this, frame, protectionSpace.get());
4047}
4048
4049void WebPageProxy::didReceiveAuthenticationChallenge(uint64_t frameID, const AuthenticationChallenge& coreChallenge, uint64_t challengeID)
4050{
4051    didReceiveAuthenticationChallengeProxy(frameID, AuthenticationChallengeProxy::create(coreChallenge, challengeID, m_process->connection()));
4052}
4053
4054void WebPageProxy::didReceiveAuthenticationChallengeProxy(uint64_t frameID, PassRefPtr<AuthenticationChallengeProxy> prpAuthenticationChallenge)
4055{
4056    ASSERT(prpAuthenticationChallenge);
4057
4058    WebFrameProxy* frame = m_process->webFrame(frameID);
4059    MESSAGE_CHECK(frame);
4060
4061    RefPtr<AuthenticationChallengeProxy> authenticationChallenge = prpAuthenticationChallenge;
4062    m_loaderClient.didReceiveAuthenticationChallengeInFrame(this, frame, authenticationChallenge.get());
4063}
4064
4065void WebPageProxy::exceededDatabaseQuota(uint64_t frameID, const String& originIdentifier, const String& databaseName, const String& displayName, uint64_t currentQuota, uint64_t currentOriginUsage, uint64_t currentDatabaseUsage, uint64_t expectedUsage, PassRefPtr<Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply> reply)
4066{
4067    ExceededDatabaseQuotaRecords& records = ExceededDatabaseQuotaRecords::shared();
4068    OwnPtr<ExceededDatabaseQuotaRecords::Record> newRecord =  records.createRecord(frameID,
4069        originIdentifier, databaseName, displayName, currentQuota, currentOriginUsage,
4070        currentDatabaseUsage, expectedUsage, reply);
4071    records.add(newRecord.release());
4072
4073    if (records.areBeingProcessed())
4074        return;
4075
4076    ExceededDatabaseQuotaRecords::Record* record = records.next();
4077    while (record) {
4078        WebFrameProxy* frame = m_process->webFrame(record->frameID);
4079        MESSAGE_CHECK(frame);
4080
4081        RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::createFromDatabaseIdentifier(record->originIdentifier);
4082
4083        uint64_t newQuota = m_uiClient.exceededDatabaseQuota(this, frame, origin.get(),
4084            record->databaseName, record->displayName, record->currentQuota,
4085            record->currentOriginUsage, record->currentDatabaseUsage, record->expectedUsage);
4086
4087        record->reply->send(newQuota);
4088        record = records.next();
4089    }
4090}
4091
4092void WebPageProxy::requestGeolocationPermissionForFrame(uint64_t geolocationID, uint64_t frameID, String originIdentifier)
4093{
4094    WebFrameProxy* frame = m_process->webFrame(frameID);
4095    MESSAGE_CHECK(frame);
4096
4097    // FIXME: Geolocation should probably be using toString() as its string representation instead of databaseIdentifier().
4098    RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::createFromDatabaseIdentifier(originIdentifier);
4099    RefPtr<GeolocationPermissionRequestProxy> request = m_geolocationPermissionRequestManager.createRequest(geolocationID);
4100
4101    if (!m_uiClient.decidePolicyForGeolocationPermissionRequest(this, frame, origin.get(), request.get()))
4102        request->deny();
4103}
4104
4105void WebPageProxy::requestNotificationPermission(uint64_t requestID, const String& originString)
4106{
4107    if (!isRequestIDValid(requestID))
4108        return;
4109
4110    RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::createFromString(originString);
4111    RefPtr<NotificationPermissionRequest> request = m_notificationPermissionRequestManager.createRequest(requestID);
4112
4113    if (!m_uiClient.decidePolicyForNotificationPermissionRequest(this, origin.get(), request.get()))
4114        request->deny();
4115}
4116
4117void WebPageProxy::showNotification(const String& title, const String& body, const String& iconURL, const String& tag, const String& lang, const String& dir, const String& originString, uint64_t notificationID)
4118{
4119    m_process->context()->supplement<WebNotificationManagerProxy>()->show(this, title, body, iconURL, tag, lang, dir, originString, notificationID);
4120}
4121
4122void WebPageProxy::cancelNotification(uint64_t notificationID)
4123{
4124    m_process->context()->supplement<WebNotificationManagerProxy>()->cancel(this, notificationID);
4125}
4126
4127void WebPageProxy::clearNotifications(const Vector<uint64_t>& notificationIDs)
4128{
4129    m_process->context()->supplement<WebNotificationManagerProxy>()->clearNotifications(this, notificationIDs);
4130}
4131
4132void WebPageProxy::didDestroyNotification(uint64_t notificationID)
4133{
4134    m_process->context()->supplement<WebNotificationManagerProxy>()->didDestroyNotification(this, notificationID);
4135}
4136
4137float WebPageProxy::headerHeight(WebFrameProxy* frame)
4138{
4139    if (frame->isDisplayingPDFDocument())
4140        return 0;
4141    return m_uiClient.headerHeight(this, frame);
4142}
4143
4144float WebPageProxy::footerHeight(WebFrameProxy* frame)
4145{
4146    if (frame->isDisplayingPDFDocument())
4147        return 0;
4148    return m_uiClient.footerHeight(this, frame);
4149}
4150
4151void WebPageProxy::drawHeader(WebFrameProxy* frame, const FloatRect& rect)
4152{
4153    if (frame->isDisplayingPDFDocument())
4154        return;
4155    m_uiClient.drawHeader(this, frame, rect);
4156}
4157
4158void WebPageProxy::drawFooter(WebFrameProxy* frame, const FloatRect& rect)
4159{
4160    if (frame->isDisplayingPDFDocument())
4161        return;
4162    m_uiClient.drawFooter(this, frame, rect);
4163}
4164
4165void WebPageProxy::runModal()
4166{
4167    // Since runModal() can (and probably will) spin a nested run loop we need to turn off the responsiveness timer.
4168    m_process->responsivenessTimer()->stop();
4169
4170    // Our Connection's run loop might have more messages waiting to be handled after this RunModal message.
4171    // To make sure they are handled inside of the the nested modal run loop we must first signal the Connection's
4172    // run loop so we're guaranteed that it has a chance to wake up.
4173    // See http://webkit.org/b/89590 for more discussion.
4174    m_process->connection()->wakeUpRunLoop();
4175
4176    m_uiClient.runModal(this);
4177}
4178
4179void WebPageProxy::notifyScrollerThumbIsVisibleInRect(const IntRect& scrollerThumb)
4180{
4181    m_visibleScrollerThumbRect = scrollerThumb;
4182}
4183
4184void WebPageProxy::recommendedScrollbarStyleDidChange(int32_t newStyle)
4185{
4186#if PLATFORM(MAC)
4187    m_pageClient->recommendedScrollbarStyleDidChange(newStyle);
4188#else
4189    UNUSED_PARAM(newStyle);
4190#endif
4191}
4192
4193void WebPageProxy::didChangeScrollbarsForMainFrame(bool hasHorizontalScrollbar, bool hasVerticalScrollbar)
4194{
4195    m_mainFrameHasHorizontalScrollbar = hasHorizontalScrollbar;
4196    m_mainFrameHasVerticalScrollbar = hasVerticalScrollbar;
4197}
4198
4199void WebPageProxy::didChangeScrollOffsetPinningForMainFrame(bool pinnedToLeftSide, bool pinnedToRightSide, bool pinnedToTopSide, bool pinnedToBottomSide)
4200{
4201    m_mainFrameIsPinnedToLeftSide = pinnedToLeftSide;
4202    m_mainFrameIsPinnedToRightSide = pinnedToRightSide;
4203    m_mainFrameIsPinnedToTopSide = pinnedToTopSide;
4204    m_mainFrameIsPinnedToBottomSide = pinnedToBottomSide;
4205}
4206
4207void WebPageProxy::didChangePageCount(unsigned pageCount)
4208{
4209    m_pageCount = pageCount;
4210}
4211
4212void WebPageProxy::didFailToInitializePlugin(const String& mimeType, const String& frameURLString, const String& pageURLString)
4213{
4214    m_loaderClient.didFailToInitializePlugin(this, createPluginInformationDictionary(mimeType, frameURLString, pageURLString).get());
4215}
4216
4217void WebPageProxy::didBlockInsecurePluginVersion(const String& mimeType, const String& pluginURLString, const String& frameURLString, const String& pageURLString, bool replacementObscured)
4218{
4219    RefPtr<ImmutableDictionary> pluginInformation;
4220
4221#if PLATFORM(MAC) && ENABLE(NETSCAPE_PLUGIN_API)
4222    String newMimeType = mimeType;
4223    PluginModuleInfo plugin = m_process->context()->pluginInfoStore().findPlugin(newMimeType, KURL(KURL(), pluginURLString));
4224    pluginInformation = createPluginInformationDictionary(plugin, frameURLString, mimeType, pageURLString, String(), String(), replacementObscured);
4225#else
4226    UNUSED_PARAM(pluginURLString);
4227#endif
4228
4229    m_loaderClient.didBlockInsecurePluginVersion(this, pluginInformation.get());
4230}
4231
4232bool WebPageProxy::willHandleHorizontalScrollEvents() const
4233{
4234    return !m_canShortCircuitHorizontalWheelEvents;
4235}
4236
4237void WebPageProxy::didFinishLoadingDataForCustomRepresentation(const String& suggestedFilename, const CoreIPC::DataReference& dataReference)
4238{
4239    m_pageClient->didFinishLoadingDataForCustomRepresentation(suggestedFilename, dataReference);
4240}
4241
4242void WebPageProxy::backForwardRemovedItem(uint64_t itemID)
4243{
4244    m_process->send(Messages::WebPage::DidRemoveBackForwardItem(itemID), m_pageID);
4245}
4246
4247void WebPageProxy::setCanRunModal(bool canRunModal)
4248{
4249    if (!isValid())
4250        return;
4251
4252    // It's only possible to change the state for a WebPage which
4253    // already qualifies for running modal child web pages, otherwise
4254    // there's no other possibility than not allowing it.
4255    m_canRunModal = m_uiClient.canRunModal() && canRunModal;
4256    m_process->send(Messages::WebPage::SetCanRunModal(m_canRunModal), m_pageID);
4257}
4258
4259bool WebPageProxy::canRunModal()
4260{
4261    return isValid() ? m_canRunModal : false;
4262}
4263
4264void WebPageProxy::beginPrinting(WebFrameProxy* frame, const PrintInfo& printInfo)
4265{
4266    if (m_isInPrintingMode)
4267        return;
4268
4269    m_isInPrintingMode = true;
4270    m_process->send(Messages::WebPage::BeginPrinting(frame->frameID(), printInfo), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0);
4271}
4272
4273void WebPageProxy::endPrinting()
4274{
4275    if (!m_isInPrintingMode)
4276        return;
4277
4278    m_isInPrintingMode = false;
4279    m_process->send(Messages::WebPage::EndPrinting(), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0);
4280}
4281
4282void WebPageProxy::computePagesForPrinting(WebFrameProxy* frame, const PrintInfo& printInfo, PassRefPtr<ComputedPagesCallback> prpCallback)
4283{
4284    RefPtr<ComputedPagesCallback> callback = prpCallback;
4285    if (!isValid()) {
4286        callback->invalidate();
4287        return;
4288    }
4289
4290    uint64_t callbackID = callback->callbackID();
4291    m_computedPagesCallbacks.set(callbackID, callback.get());
4292    m_isInPrintingMode = true;
4293    m_process->send(Messages::WebPage::ComputePagesForPrinting(frame->frameID(), printInfo, callbackID), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0);
4294}
4295
4296#if PLATFORM(MAC)
4297void WebPageProxy::drawRectToImage(WebFrameProxy* frame, const PrintInfo& printInfo, const IntRect& rect, const WebCore::IntSize& imageSize, PassRefPtr<ImageCallback> prpCallback)
4298{
4299    RefPtr<ImageCallback> callback = prpCallback;
4300    if (!isValid()) {
4301        callback->invalidate();
4302        return;
4303    }
4304
4305    uint64_t callbackID = callback->callbackID();
4306    m_imageCallbacks.set(callbackID, callback.get());
4307    m_process->send(Messages::WebPage::DrawRectToImage(frame->frameID(), printInfo, rect, imageSize, callbackID), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0);
4308}
4309
4310void WebPageProxy::drawPagesToPDF(WebFrameProxy* frame, const PrintInfo& printInfo, uint32_t first, uint32_t count, PassRefPtr<DataCallback> prpCallback)
4311{
4312    RefPtr<DataCallback> callback = prpCallback;
4313    if (!isValid()) {
4314        callback->invalidate();
4315        return;
4316    }
4317
4318    uint64_t callbackID = callback->callbackID();
4319    m_dataCallbacks.set(callbackID, callback.get());
4320    m_process->send(Messages::WebPage::DrawPagesToPDF(frame->frameID(), printInfo, first, count, callbackID), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0);
4321}
4322#elif PLATFORM(GTK)
4323void WebPageProxy::drawPagesForPrinting(WebFrameProxy* frame, const PrintInfo& printInfo, PassRefPtr<PrintFinishedCallback> didPrintCallback)
4324{
4325    RefPtr<PrintFinishedCallback> callback = didPrintCallback;
4326    if (!isValid()) {
4327        callback->invalidate();
4328        return;
4329    }
4330
4331    uint64_t callbackID = callback->callbackID();
4332    m_printFinishedCallbacks.set(callbackID, callback.get());
4333    m_isInPrintingMode = true;
4334    m_process->send(Messages::WebPage::DrawPagesForPrinting(frame->frameID(), printInfo, callbackID), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0);
4335}
4336#endif
4337
4338void WebPageProxy::flashBackingStoreUpdates(const Vector<IntRect>& updateRects)
4339{
4340    m_pageClient->flashBackingStoreUpdates(updateRects);
4341}
4342
4343void WebPageProxy::updateBackingStoreDiscardableState()
4344{
4345    ASSERT(isValid());
4346
4347    bool isDiscardable;
4348
4349    if (!m_process->responsivenessTimer()->isResponsive())
4350        isDiscardable = false;
4351    else
4352        isDiscardable = !m_pageClient->isViewWindowActive() || !isViewVisible();
4353
4354    m_drawingArea->setBackingStoreIsDiscardable(isDiscardable);
4355}
4356
4357Color WebPageProxy::viewUpdatesFlashColor()
4358{
4359    return Color(0, 200, 255);
4360}
4361
4362Color WebPageProxy::backingStoreUpdatesFlashColor()
4363{
4364    return Color(200, 0, 255);
4365}
4366
4367void WebPageProxy::saveDataToFileInDownloadsFolder(const String& suggestedFilename, const String& mimeType, const String& originatingURLString, WebData* data)
4368{
4369    m_uiClient.saveDataToFileInDownloadsFolder(this, suggestedFilename, mimeType, originatingURLString, data);
4370}
4371
4372void WebPageProxy::savePDFToFileInDownloadsFolder(const String& suggestedFilename, const String& originatingURLString, const CoreIPC::DataReference& data)
4373{
4374    if (!suggestedFilename.endsWith(".pdf", false))
4375        return;
4376
4377    RefPtr<WebData> webData = WebData::create(data.data(), data.size());
4378
4379    saveDataToFileInDownloadsFolder(suggestedFilename, "application/pdf", originatingURLString, webData.get());
4380}
4381
4382void WebPageProxy::linkClicked(const String& url, const WebMouseEvent& event)
4383{
4384    m_process->send(Messages::WebPage::LinkClicked(url, event), m_pageID, 0);
4385}
4386
4387void WebPageProxy::setMinimumLayoutSize(const IntSize& minimumLayoutSize)
4388{
4389    if (m_minimumLayoutSize == minimumLayoutSize)
4390        return;
4391
4392    m_minimumLayoutSize = minimumLayoutSize;
4393
4394    if (!isValid())
4395        return;
4396
4397    m_process->send(Messages::WebPage::SetMinimumLayoutSize(minimumLayoutSize), m_pageID, 0);
4398    m_drawingArea->minimumLayoutSizeDidChange();
4399
4400#if PLATFORM(MAC)
4401    if (m_minimumLayoutSize.width() <= 0)
4402        intrinsicContentSizeDidChange(IntSize(-1, -1));
4403#endif
4404}
4405
4406void WebPageProxy::setAutoSizingShouldExpandToViewHeight(bool shouldExpand)
4407{
4408    if (m_autoSizingShouldExpandToViewHeight == shouldExpand)
4409        return;
4410
4411    m_autoSizingShouldExpandToViewHeight = shouldExpand;
4412
4413    if (!isValid())
4414        return;
4415
4416    m_process->send(Messages::WebPage::SetAutoSizingShouldExpandToViewHeight(shouldExpand), m_pageID, 0);
4417}
4418
4419#if PLATFORM(MAC)
4420
4421void WebPageProxy::substitutionsPanelIsShowing(bool& isShowing)
4422{
4423    isShowing = TextChecker::substitutionsPanelIsShowing();
4424}
4425
4426void WebPageProxy::showCorrectionPanel(int32_t panelType, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
4427{
4428    m_pageClient->showCorrectionPanel((AlternativeTextType)panelType, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings);
4429}
4430
4431void WebPageProxy::dismissCorrectionPanel(int32_t reason)
4432{
4433    m_pageClient->dismissCorrectionPanel((ReasonForDismissingAlternativeText)reason);
4434}
4435
4436void WebPageProxy::dismissCorrectionPanelSoon(int32_t reason, String& result)
4437{
4438    result = m_pageClient->dismissCorrectionPanelSoon((ReasonForDismissingAlternativeText)reason);
4439}
4440
4441void WebPageProxy::recordAutocorrectionResponse(int32_t responseType, const String& replacedString, const String& replacementString)
4442{
4443    m_pageClient->recordAutocorrectionResponse((AutocorrectionResponseType)responseType, replacedString, replacementString);
4444}
4445
4446void WebPageProxy::handleAlternativeTextUIResult(const String& result)
4447{
4448    if (!isClosed())
4449        m_process->send(Messages::WebPage::HandleAlternativeTextUIResult(result), m_pageID, 0);
4450}
4451
4452#if USE(DICTATION_ALTERNATIVES)
4453void WebPageProxy::showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext)
4454{
4455    m_pageClient->showDictationAlternativeUI(boundingBoxOfDictatedText, dictationContext);
4456}
4457
4458void WebPageProxy::removeDictationAlternatives(uint64_t dictationContext)
4459{
4460    m_pageClient->removeDictationAlternatives(dictationContext);
4461}
4462
4463void WebPageProxy::dictationAlternatives(uint64_t dictationContext, Vector<String>& result)
4464{
4465    result = m_pageClient->dictationAlternatives(dictationContext);
4466}
4467#endif
4468
4469#endif // PLATFORM(MAC)
4470
4471#if USE(SOUP)
4472void WebPageProxy::didReceiveURIRequest(String uriString, uint64_t requestID)
4473{
4474    m_process->context()->supplement<WebSoupRequestManagerProxy>()->didReceiveURIRequest(uriString, this, requestID);
4475}
4476#endif
4477
4478#if PLATFORM(QT) || PLATFORM(GTK)
4479void WebPageProxy::setComposition(const String& text, Vector<CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd)
4480{
4481    // FIXME: We need to find out how to proper handle the crashes case.
4482    if (!isValid())
4483        return;
4484
4485    process()->send(Messages::WebPage::SetComposition(text, underlines, selectionStart, selectionEnd, replacementRangeStart, replacementRangeEnd), m_pageID);
4486}
4487
4488void WebPageProxy::confirmComposition(const String& compositionString, int64_t selectionStart, int64_t selectionLength)
4489{
4490    if (!isValid())
4491        return;
4492
4493    process()->send(Messages::WebPage::ConfirmComposition(compositionString, selectionStart, selectionLength), m_pageID);
4494}
4495
4496void WebPageProxy::cancelComposition()
4497{
4498    if (!isValid())
4499        return;
4500
4501    process()->send(Messages::WebPage::CancelComposition(), m_pageID);
4502}
4503#endif // PLATFORM(QT) || PLATFORM(GTK)
4504
4505void WebPageProxy::setMainFrameInViewSourceMode(bool mainFrameInViewSourceMode)
4506{
4507    if (m_mainFrameInViewSourceMode == mainFrameInViewSourceMode)
4508        return;
4509
4510    m_mainFrameInViewSourceMode = mainFrameInViewSourceMode;
4511
4512    if (isValid())
4513        m_process->send(Messages::WebPage::SetMainFrameInViewSourceMode(mainFrameInViewSourceMode), m_pageID);
4514}
4515
4516void WebPageProxy::didSaveToPageCache()
4517{
4518    m_process->didSaveToPageCache();
4519}
4520
4521void WebPageProxy::setScrollPinningBehavior(ScrollPinningBehavior pinning)
4522{
4523    if (m_scrollPinningBehavior == pinning)
4524        return;
4525
4526    m_scrollPinningBehavior = pinning;
4527
4528    if (isValid())
4529        m_process->send(Messages::WebPage::SetScrollPinningBehavior(pinning), m_pageID);
4530}
4531
4532} // namespace WebKit
4533