Implement contentInset for Mac WebKit2
[WebKit-https.git] / Source / WebKit2 / UIProcess / WebPageProxy.cpp
1 /*
2  * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
3  * Copyright (C) 2012 Intel Corporation. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "WebPageProxy.h"
29
30 #include "APIArray.h"
31 #include "APILoaderClient.h"
32 #include "APIPolicyClient.h"
33 #include "APIUIClient.h"
34 #include "APIURLRequest.h"
35 #include "AuthenticationChallengeProxy.h"
36 #include "AuthenticationDecisionListener.h"
37 #include "DataReference.h"
38 #include "DownloadProxy.h"
39 #include "DrawingAreaProxy.h"
40 #include "DrawingAreaProxyMessages.h"
41 #include "EventDispatcherMessages.h"
42 #include "FindIndicator.h"
43 #include "Logging.h"
44 #include "NativeWebKeyboardEvent.h"
45 #include "NativeWebMouseEvent.h"
46 #include "NativeWebWheelEvent.h"
47 #include "NavigationActionData.h"
48 #include "NotificationPermissionRequest.h"
49 #include "NotificationPermissionRequestManager.h"
50 #include "PageClient.h"
51 #include "PluginInformation.h"
52 #include "PluginProcessManager.h"
53 #include "PrintInfo.h"
54 #include "SessionState.h"
55 #include "TextChecker.h"
56 #include "TextCheckerState.h"
57 #include "WKContextPrivate.h"
58 #include "WebBackForwardList.h"
59 #include "WebBackForwardListItem.h"
60 #include "WebCertificateInfo.h"
61 #include "WebContext.h"
62 #include "WebContextMenuProxy.h"
63 #include "WebContextUserMessageCoders.h"
64 #include "WebCoreArgumentCoders.h"
65 #include "WebEditCommandProxy.h"
66 #include "WebEvent.h"
67 #include "WebEventConversion.h"
68 #include "WebFormSubmissionListenerProxy.h"
69 #include "WebFramePolicyListenerProxy.h"
70 #include "WebFullScreenManagerProxy.h"
71 #include "WebFullScreenManagerProxyMessages.h"
72 #include "WebInspectorProxy.h"
73 #include "WebInspectorProxyMessages.h"
74 #include "WebNotificationManagerProxy.h"
75 #include "WebOpenPanelParameters.h"
76 #include "WebOpenPanelResultListenerProxy.h"
77 #include "WebPageCreationParameters.h"
78 #include "WebPageGroup.h"
79 #include "WebPageGroupData.h"
80 #include "WebPageMessages.h"
81 #include "WebPageProxyMessages.h"
82 #include "WebPopupItem.h"
83 #include "WebPopupMenuProxy.h"
84 #include "WebPreferences.h"
85 #include "WebProcessMessages.h"
86 #include "WebProcessProxy.h"
87 #include "WebProtectionSpace.h"
88 #include "WebSecurityOrigin.h"
89 #include <WebCore/DragController.h>
90 #include <WebCore/DragData.h>
91 #include <WebCore/DragSession.h>
92 #include <WebCore/FloatRect.h>
93 #include <WebCore/FocusDirection.h>
94 #include <WebCore/MIMETypeRegistry.h>
95 #include <WebCore/RenderEmbeddedObject.h>
96 #include <WebCore/SerializedCryptoKeyWrap.h>
97 #include <WebCore/TextCheckerClient.h>
98 #include <WebCore/WindowFeatures.h>
99 #include <stdio.h>
100 #include <wtf/NeverDestroyed.h>
101 #include <wtf/text/StringView.h>
102
103 #if ENABLE(ASYNC_SCROLLING)
104 #include "RemoteScrollingCoordinatorProxy.h"
105 #endif
106
107 #if USE(COORDINATED_GRAPHICS)
108 #include "CoordinatedLayerTreeHostProxyMessages.h"
109 #endif
110
111 #if PLATFORM(GTK)
112 #include "ArgumentCodersGtk.h"
113 #endif
114
115 #if USE(SOUP) && !ENABLE(CUSTOM_PROTOCOLS)
116 #include "WebSoupRequestManagerProxy.h"
117 #endif
118
119 #if ENABLE(VIBRATION)
120 #include "WebVibrationProxy.h"
121 #endif
122
123 #ifndef NDEBUG
124 #include <wtf/RefCountedLeakCounter.h>
125 #endif
126
127 #if ENABLE(NETWORK_PROCESS)
128 #include "NetworkProcessMessages.h"
129 #endif
130
131 #if PLATFORM(COCOA)
132 #include "ViewSnapshotStore.h"
133 #endif
134
135 #if PLATFORM(IOS)
136 #include "WebVideoFullscreenManagerProxy.h"
137 #include "WebVideoFullscreenManagerProxyMessages.h"
138 #endif
139
140 // This controls what strategy we use for mouse wheel coalescing.
141 #define MERGE_WHEEL_EVENTS 1
142
143 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, m_process->connection())
144 #define MESSAGE_CHECK_URL(url) MESSAGE_CHECK_BASE(m_process->checkURLReceivedFromWebProcess(url), m_process->connection())
145
146 using namespace WebCore;
147
148 // Represents the number of wheel events we can hold in the queue before we start pushing them preemptively.
149 static const unsigned wheelEventQueueSizeThreshold = 10;
150
151 namespace WebKit {
152
153 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageProxyCounter, ("WebPageProxy"));
154
155 class ExceededDatabaseQuotaRecords {
156     WTF_MAKE_NONCOPYABLE(ExceededDatabaseQuotaRecords); WTF_MAKE_FAST_ALLOCATED;
157     friend class NeverDestroyed<ExceededDatabaseQuotaRecords>;
158 public:
159     struct Record {
160         uint64_t frameID;
161         String originIdentifier;
162         String databaseName;
163         String displayName;
164         uint64_t currentQuota;
165         uint64_t currentOriginUsage;
166         uint64_t currentDatabaseUsage;
167         uint64_t expectedUsage;
168         RefPtr<Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply> reply;
169     };
170
171     static ExceededDatabaseQuotaRecords& shared();
172
173     PassOwnPtr<Record> createRecord(uint64_t frameID, String originIdentifier,
174         String databaseName, String displayName, uint64_t currentQuota,
175         uint64_t currentOriginUsage, uint64_t currentDatabaseUsage, uint64_t expectedUsage, 
176         PassRefPtr<Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply>);
177
178     void add(PassOwnPtr<Record>);
179     bool areBeingProcessed() const { return m_currentRecord; }
180     Record* next();
181
182 private:
183     ExceededDatabaseQuotaRecords() { }
184     ~ExceededDatabaseQuotaRecords() { }
185
186     Deque<OwnPtr<Record>> m_records;
187     OwnPtr<Record> m_currentRecord;
188 };
189
190 ExceededDatabaseQuotaRecords& ExceededDatabaseQuotaRecords::shared()
191 {
192     static NeverDestroyed<ExceededDatabaseQuotaRecords> records;
193     return records;
194 }
195
196 PassOwnPtr<ExceededDatabaseQuotaRecords::Record> ExceededDatabaseQuotaRecords::createRecord(
197     uint64_t frameID, String originIdentifier, String databaseName, String displayName,
198     uint64_t currentQuota, uint64_t currentOriginUsage, uint64_t currentDatabaseUsage,
199     uint64_t expectedUsage, PassRefPtr<Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply> reply)
200 {
201     OwnPtr<Record> record = adoptPtr(new Record);
202     record->frameID = frameID;
203     record->originIdentifier = originIdentifier;
204     record->databaseName = databaseName;
205     record->displayName = displayName;
206     record->currentQuota = currentQuota;
207     record->currentOriginUsage = currentOriginUsage;
208     record->currentDatabaseUsage = currentDatabaseUsage;
209     record->expectedUsage = expectedUsage;
210     record->reply = reply;
211     return record.release();
212 }
213
214 void ExceededDatabaseQuotaRecords::add(PassOwnPtr<ExceededDatabaseQuotaRecords::Record> record)
215 {
216     m_records.append(record);
217 }
218
219 ExceededDatabaseQuotaRecords::Record* ExceededDatabaseQuotaRecords::next()
220 {
221     m_currentRecord.clear();
222     if (!m_records.isEmpty())
223         m_currentRecord = m_records.takeFirst();
224     return m_currentRecord.get();
225 }
226
227 #if !LOG_DISABLED
228 static const char* webKeyboardEventTypeString(WebEvent::Type type)
229 {
230     switch (type) {
231     case WebEvent::KeyDown:
232         return "KeyDown";
233     
234     case WebEvent::KeyUp:
235         return "KeyUp";
236     
237     case WebEvent::RawKeyDown:
238         return "RawKeyDown";
239     
240     case WebEvent::Char:
241         return "Char";
242     
243     default:
244         ASSERT_NOT_REACHED();
245         return "<unknown>";
246     }
247 }
248 #endif // !LOG_DISABLED
249
250 PassRefPtr<WebPageProxy> WebPageProxy::create(PageClient& pageClient, WebProcessProxy& process, uint64_t pageID, const WebPageConfiguration& configuration)
251 {
252     return adoptRef(new WebPageProxy(pageClient, process, pageID, configuration));
253 }
254
255 WebPageProxy::WebPageProxy(PageClient& pageClient, WebProcessProxy& process, uint64_t pageID, const WebPageConfiguration& configuration)
256     : m_pageClient(pageClient)
257     , m_loaderClient(std::make_unique<API::LoaderClient>())
258     , m_policyClient(std::make_unique<API::PolicyClient>())
259     , m_uiClient(std::make_unique<API::UIClient>())
260     , m_process(process)
261     , m_pageGroup(*configuration.pageGroup)
262     , m_preferences(*configuration.preferences)
263     , m_visitedLinkProvider(*configuration.visitedLinkProvider)
264     , m_mainFrame(nullptr)
265     , m_userAgent(standardUserAgent())
266     , m_geolocationPermissionRequestManager(*this)
267     , m_notificationPermissionRequestManager(*this)
268     , m_viewState(ViewState::NoFlags)
269     , m_backForwardList(WebBackForwardList::create(*this))
270     , m_loadStateAtProcessExit(FrameLoadState::State::Finished)
271     , m_temporarilyClosedComposition(false)
272     , m_textZoomFactor(1)
273     , m_pageZoomFactor(1)
274     , m_pageScaleFactor(1)
275     , m_intrinsicDeviceScaleFactor(1)
276     , m_customDeviceScaleFactor(0)
277     , m_topContentInset(0)
278     , m_layerHostingMode(LayerHostingMode::InProcess)
279     , m_drawsBackground(true)
280     , m_drawsTransparentBackground(false)
281     , m_areMemoryCacheClientCallsEnabled(true)
282     , m_useFixedLayout(false)
283     , m_suppressScrollbarAnimations(false)
284     , m_paginationMode(Pagination::Unpaginated)
285     , m_paginationBehavesLikeColumns(false)
286     , m_pageLength(0)
287     , m_gapBetweenPages(0)
288     , m_isValid(true)
289     , m_isClosed(false)
290     , m_canRunModal(false)
291     , m_isInPrintingMode(false)
292     , m_isPerformingDOMPrintOperation(false)
293     , m_inDecidePolicyForResponseSync(false)
294     , m_decidePolicyForResponseRequest(0)
295     , m_syncMimeTypePolicyActionIsValid(false)
296     , m_syncMimeTypePolicyAction(PolicyUse)
297     , m_syncMimeTypePolicyDownloadID(0)
298     , m_inDecidePolicyForNavigationAction(false)
299     , m_syncNavigationActionPolicyActionIsValid(false)
300     , m_syncNavigationActionPolicyAction(PolicyUse)
301     , m_syncNavigationActionPolicyDownloadID(0)
302     , m_processingMouseMoveEvent(false)
303 #if ENABLE(TOUCH_EVENTS)
304     , m_isTrackingTouchEvents(false)
305 #endif
306     , m_pageID(pageID)
307     , m_session(*configuration.session)
308     , m_isPageSuspended(false)
309 #if ENABLE(REMOTE_INSPECTOR)
310     , m_allowsRemoteInspection(true)
311 #endif
312 #if PLATFORM(COCOA)
313     , m_isSmartInsertDeleteEnabled(TextChecker::isSmartInsertDeleteEnabled())
314 #endif
315     , m_spellDocumentTag(0)
316     , m_hasSpellDocumentTag(false)
317     , m_pendingLearnOrIgnoreWordMessageCount(0)
318     , m_mainFrameHasCustomContentProvider(false)
319     , m_delegatesScrolling(false)
320     , m_mainFrameHasHorizontalScrollbar(false)
321     , m_mainFrameHasVerticalScrollbar(false)
322     , m_canShortCircuitHorizontalWheelEvents(true)
323     , m_mainFrameIsPinnedToLeftSide(false)
324     , m_mainFrameIsPinnedToRightSide(false)
325     , m_mainFrameIsPinnedToTopSide(false)
326     , m_mainFrameIsPinnedToBottomSide(false)
327     , m_shouldUseImplicitRubberBandControl(false)
328     , m_rubberBandsAtLeft(true)
329     , m_rubberBandsAtRight(true)
330     , m_rubberBandsAtTop(true)
331     , m_rubberBandsAtBottom(true)
332     , m_backgroundExtendsBeyondPage(false)
333     , m_shouldRecordNavigationSnapshots(false)
334     , m_pageCount(0)
335     , m_renderTreeSize(0)
336     , m_shouldSendEventsSynchronously(false)
337     , m_suppressVisibilityUpdates(false)
338     , m_autoSizingShouldExpandToViewHeight(false)
339     , m_mediaVolume(1)
340     , m_mayStartMediaWhenInWindow(true)
341     , m_waitingForDidUpdateViewState(false)
342     , m_scrollPinningBehavior(DoNotPin)
343     , m_navigationID(0)
344 {
345     if (m_process->state() == WebProcessProxy::State::Running)
346         m_visitedLinkProvider->addProcess(m_process.get());
347
348     updateViewState();
349
350 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
351     m_layerHostingMode = m_viewState & ViewState::IsInWindow ? m_pageClient.viewLayerHostingMode() : LayerHostingMode::OutOfProcess;
352 #endif
353
354     platformInitialize();
355
356 #ifndef NDEBUG
357     webPageProxyCounter.increment();
358 #endif
359
360     WebContext::statistics().wkPageCount++;
361
362     m_preferences->addPage(*this);
363     m_pageGroup->addPage(this);
364
365 #if ENABLE(INSPECTOR)
366     m_inspector = WebInspectorProxy::create(this);
367 #endif
368 #if ENABLE(FULLSCREEN_API)
369     m_fullScreenManager = WebFullScreenManagerProxy::create(*this, m_pageClient.fullScreenManagerProxyClient());
370 #endif
371 #if PLATFORM(IOS)
372     m_videoFullscreenManager = WebVideoFullscreenManagerProxy::create(*this);
373 #endif
374 #if ENABLE(VIBRATION)
375     m_vibration = WebVibrationProxy::create(this);
376 #endif
377
378     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
379
380     // FIXME: If we ever expose the session storage size as a preference, we need to pass it here.
381     IPC::Connection* connection = m_process->state() == WebProcessProxy::State::Running ? m_process->connection() : nullptr;
382     m_process->context().storageManager().createSessionStorageNamespace(m_pageID, connection, std::numeric_limits<unsigned>::max());
383     setSession(*configuration.session);
384 }
385
386 WebPageProxy::~WebPageProxy()
387 {
388     if (!m_isClosed)
389         close();
390
391     WebContext::statistics().wkPageCount--;
392
393     if (m_hasSpellDocumentTag)
394         TextChecker::closeSpellDocumentWithTag(m_spellDocumentTag);
395
396     m_preferences->removePage(*this);
397     m_pageGroup->removePage(this);
398
399 #ifndef NDEBUG
400     webPageProxyCounter.decrement();
401 #endif
402 }
403
404 PlatformProcessIdentifier WebPageProxy::processIdentifier() const
405 {
406     if (m_isClosed)
407         return 0;
408
409     return m_process->processIdentifier();
410 }
411
412 bool WebPageProxy::isValid() const
413 {
414     // A page that has been explicitly closed is never valid.
415     if (m_isClosed)
416         return false;
417
418     return m_isValid;
419 }
420
421 void WebPageProxy::setPreferences(WebPreferences& preferences)
422 {
423     if (&preferences == &m_preferences.get())
424         return;
425
426     m_preferences->removePage(*this);
427     m_preferences = preferences;
428     m_preferences->addPage(*this);
429
430     preferencesDidChange();
431 }
432
433 void WebPageProxy::setLoaderClient(std::unique_ptr<API::LoaderClient> loaderClient)
434 {
435     if (!loaderClient) {
436         m_loaderClient = std::make_unique<API::LoaderClient>();
437         return;
438     }
439
440     m_loaderClient = std::move(loaderClient);
441 }
442
443 void WebPageProxy::setPolicyClient(std::unique_ptr<API::PolicyClient> policyClient)
444 {
445     if (!policyClient) {
446         m_policyClient = std::make_unique<API::PolicyClient>();
447         return;
448     }
449
450     m_policyClient = std::move(policyClient);
451 }
452
453 void WebPageProxy::initializeFormClient(const WKPageFormClientBase* formClient)
454 {
455     m_formClient.initialize(formClient);
456 }
457
458 void WebPageProxy::setUIClient(std::unique_ptr<API::UIClient> uiClient)
459 {
460     if (!uiClient) {
461         m_uiClient = std::make_unique<API::UIClient>();
462         return;
463     }
464
465     m_uiClient = std::move(uiClient);
466
467     if (!isValid())
468         return;
469
470     m_process->send(Messages::WebPage::SetCanRunBeforeUnloadConfirmPanel(m_uiClient->canRunBeforeUnloadConfirmPanel()), m_pageID);
471     setCanRunModal(m_uiClient->canRunModal());
472 }
473
474 void WebPageProxy::initializeFindClient(const WKPageFindClientBase* client)
475 {
476     m_findClient.initialize(client);
477 }
478
479 void WebPageProxy::initializeFindMatchesClient(const WKPageFindMatchesClientBase* client)
480 {
481     m_findMatchesClient.initialize(client);
482 }
483
484 #if ENABLE(CONTEXT_MENUS)
485 void WebPageProxy::initializeContextMenuClient(const WKPageContextMenuClientBase* client)
486 {
487     m_contextMenuClient.initialize(client);
488 }
489 #endif
490
491 void WebPageProxy::reattachToWebProcess()
492 {
493     ASSERT(!isValid());
494     ASSERT(m_process->state() == WebProcessProxy::State::Terminated);
495
496     updateViewState();
497
498     m_isValid = true;
499
500     if (m_process->context().processModel() == ProcessModelSharedSecondaryProcess)
501         m_process = m_process->context().ensureSharedWebProcess();
502     else
503         m_process = m_process->context().createNewWebProcessRespectingProcessCountLimit();
504     m_process->addExistingWebPage(this, m_pageID);
505     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
506
507 #if ENABLE(INSPECTOR)
508     m_inspector = WebInspectorProxy::create(this);
509 #endif
510 #if ENABLE(FULLSCREEN_API)
511     m_fullScreenManager = WebFullScreenManagerProxy::create(*this, m_pageClient.fullScreenManagerProxyClient());
512 #endif
513
514     initializeWebPage();
515
516     m_pageClient.didRelaunchProcess();
517     m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
518 }
519
520 void WebPageProxy::reattachToWebProcessWithItem(WebBackForwardListItem* item)
521 {
522     if (item && item != m_backForwardList->currentItem())
523         m_backForwardList->goToItem(item);
524     
525     reattachToWebProcess();
526
527     if (!item)
528         return;
529
530     m_process->send(Messages::WebPage::GoToBackForwardItem(item->itemID()), m_pageID);
531     m_process->responsivenessTimer()->start();
532 }
533
534 void WebPageProxy::setSession(API::Session& session)
535 {
536     m_session = session;
537     m_process->send(Messages::WebPage::SetSessionID(session.getID()), m_pageID);
538
539 #if ENABLE(NETWORK_PROCESS)
540     if (session.isEphemeral())
541         m_process->context().sendToNetworkingProcess(Messages::NetworkProcess::EnsurePrivateBrowsingSession(session.getID()));
542 #endif
543 }
544
545 void WebPageProxy::initializeWebPage()
546 {
547     ASSERT(isValid());
548
549     BackForwardListItemVector items = m_backForwardList->entries();
550     for (size_t i = 0; i < items.size(); ++i)
551         m_process->registerNewWebBackForwardListItem(items[i].get());
552
553     m_drawingArea = m_pageClient.createDrawingAreaProxy();
554     ASSERT(m_drawingArea);
555
556 #if ENABLE(ASYNC_SCROLLING)
557     if (m_drawingArea->type() == DrawingAreaTypeRemoteLayerTree)
558         m_scrollingCoordinatorProxy = std::make_unique<RemoteScrollingCoordinatorProxy>(*this);
559 #endif
560
561 #if ENABLE(INSPECTOR_SERVER)
562     if (pageGroup().preferences().developerExtrasEnabled())
563         inspector()->enableRemoteInspection();
564 #endif
565
566     process().send(Messages::WebProcess::CreateWebPage(m_pageID, creationParameters()), 0);
567
568 #if PLATFORM(COCOA)
569     send(Messages::WebPage::SetSmartInsertDeleteEnabled(m_isSmartInsertDeleteEnabled));
570 #endif
571 }
572
573 bool WebPageProxy::isProcessSuppressible() const
574 {
575     return (m_viewState & ViewState::IsVisuallyIdle) && m_preferences->pageVisibilityBasedProcessSuppressionEnabled();
576 }
577
578 void WebPageProxy::close()
579 {
580     if (!isValid())
581         return;
582
583     m_isClosed = true;
584
585     if (m_process->state() == WebProcessProxy::State::Running)
586         m_visitedLinkProvider->removeProcess(m_process.get());
587
588     m_backForwardList->pageClosed();
589     m_pageClient.pageClosed();
590
591     m_process->disconnectFramesFromPage(this);
592
593     resetState();
594
595     m_loaderClient = std::make_unique<API::LoaderClient>();
596     m_policyClient = std::make_unique<API::PolicyClient>();
597     m_formClient.initialize(0);
598     m_uiClient = std::make_unique<API::UIClient>();
599 #if PLATFORM(EFL)
600     m_uiPopupMenuClient.initialize(0);
601 #endif
602     m_findClient.initialize(0);
603     m_findMatchesClient.initialize(0);
604 #if ENABLE(CONTEXT_MENUS)
605     m_contextMenuClient.initialize(0);
606 #endif
607
608     m_process->send(Messages::WebPage::Close(), m_pageID);
609     m_process->removeWebPage(m_pageID);
610     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
611     m_process->context().storageManager().destroySessionStorageNamespace(m_pageID);
612     m_process->context().supplement<WebNotificationManagerProxy>()->clearNotifications(this);
613 }
614
615 bool WebPageProxy::tryClose()
616 {
617     if (!isValid())
618         return true;
619
620     m_process->send(Messages::WebPage::TryClose(), m_pageID);
621     m_process->responsivenessTimer()->start();
622     return false;
623 }
624
625 bool WebPageProxy::maybeInitializeSandboxExtensionHandle(const URL& url, SandboxExtension::Handle& sandboxExtensionHandle)
626 {
627     if (!url.isLocalFile())
628         return false;
629
630 #if ENABLE(INSPECTOR)
631     // Don't give the inspector full access to the file system.
632     if (WebInspectorProxy::isInspectorPage(*this))
633         return false;
634 #endif
635
636     SandboxExtension::createHandle("/", SandboxExtension::ReadOnly, sandboxExtensionHandle);
637     return true;
638 }
639
640 uint64_t WebPageProxy::loadRequest(const ResourceRequest& request, API::Object* userData)
641 {
642     uint64_t navigationID = generateNavigationID();
643
644     auto transaction = m_pageLoadState.transaction();
645
646     m_pageLoadState.setPendingAPIRequestURL(transaction, request.url());
647
648     if (!isValid())
649         reattachToWebProcess();
650
651     SandboxExtension::Handle sandboxExtensionHandle;
652     bool createdExtension = maybeInitializeSandboxExtensionHandle(request.url(), sandboxExtensionHandle);
653     if (createdExtension)
654         m_process->willAcquireUniversalFileReadSandboxExtension();
655     m_process->send(Messages::WebPage::LoadRequest(navigationID, request, sandboxExtensionHandle, WebContextUserMessageEncoder(userData, process())), m_pageID);
656     m_process->responsivenessTimer()->start();
657
658     return navigationID;
659 }
660
661 void WebPageProxy::loadFile(const String& fileURLString, const String& resourceDirectoryURLString, API::Object* userData)
662 {
663     if (!isValid())
664         reattachToWebProcess();
665
666     URL fileURL = URL(URL(), fileURLString);
667     if (!fileURL.isLocalFile())
668         return;
669
670     URL resourceDirectoryURL;
671     if (resourceDirectoryURLString.isNull())
672         resourceDirectoryURL = URL(ParsedURLString, ASCIILiteral("file:///"));
673     else {
674         resourceDirectoryURL = URL(URL(), resourceDirectoryURLString);
675         if (!resourceDirectoryURL.isLocalFile())
676             return;
677     }
678
679     String resourceDirectoryPath = resourceDirectoryURL.fileSystemPath();
680
681     SandboxExtension::Handle sandboxExtensionHandle;
682     SandboxExtension::createHandle(resourceDirectoryPath, SandboxExtension::ReadOnly, sandboxExtensionHandle);
683     m_process->assumeReadAccessToBaseURL(resourceDirectoryURL);
684     m_process->send(Messages::WebPage::LoadRequest(generateNavigationID(), fileURL, sandboxExtensionHandle, WebContextUserMessageEncoder(userData, process())), m_pageID);
685     m_process->responsivenessTimer()->start();
686 }
687
688 void WebPageProxy::loadData(API::Data* data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData)
689 {
690     if (!isValid())
691         reattachToWebProcess();
692
693     m_process->assumeReadAccessToBaseURL(baseURL);
694     m_process->send(Messages::WebPage::LoadData(data->dataReference(), MIMEType, encoding, baseURL, WebContextUserMessageEncoder(userData, process())), m_pageID);
695     m_process->responsivenessTimer()->start();
696 }
697
698 void WebPageProxy::loadHTMLString(const String& htmlString, const String& baseURL, API::Object* userData)
699 {
700     if (!isValid())
701         reattachToWebProcess();
702
703     m_process->assumeReadAccessToBaseURL(baseURL);
704     m_process->send(Messages::WebPage::LoadHTMLString(htmlString, baseURL, WebContextUserMessageEncoder(userData, process())), m_pageID);
705     m_process->responsivenessTimer()->start();
706 }
707
708 void WebPageProxy::loadAlternateHTMLString(const String& htmlString, const String& baseURL, const String& unreachableURL, API::Object* userData)
709 {
710     if (!isValid())
711         reattachToWebProcess();
712
713     auto transaction = m_pageLoadState.transaction();
714
715     m_pageLoadState.setUnreachableURL(transaction, unreachableURL);
716
717     if (m_mainFrame)
718         m_mainFrame->setUnreachableURL(unreachableURL);
719
720     m_process->assumeReadAccessToBaseURL(baseURL);
721     m_process->send(Messages::WebPage::LoadAlternateHTMLString(htmlString, baseURL, unreachableURL, WebContextUserMessageEncoder(userData, process())), m_pageID);
722     m_process->responsivenessTimer()->start();
723 }
724
725 void WebPageProxy::loadPlainTextString(const String& string, API::Object* userData)
726 {
727     if (!isValid())
728         reattachToWebProcess();
729
730     m_process->send(Messages::WebPage::LoadPlainTextString(string, WebContextUserMessageEncoder(userData, process())), m_pageID);
731     m_process->responsivenessTimer()->start();
732 }
733
734 void WebPageProxy::loadWebArchiveData(API::Data* webArchiveData, API::Object* userData)
735 {
736     if (!isValid())
737         reattachToWebProcess();
738
739     m_process->send(Messages::WebPage::LoadWebArchiveData(webArchiveData->dataReference(), WebContextUserMessageEncoder(userData, process())), m_pageID);
740     m_process->responsivenessTimer()->start();
741 }
742
743 void WebPageProxy::stopLoading()
744 {
745     if (!isValid())
746         return;
747
748     m_process->send(Messages::WebPage::StopLoading(), m_pageID);
749     m_process->responsivenessTimer()->start();
750 }
751
752 void WebPageProxy::reload(bool reloadFromOrigin)
753 {
754     SandboxExtension::Handle sandboxExtensionHandle;
755
756     if (m_backForwardList->currentItem()) {
757         String url = m_backForwardList->currentItem()->url();
758         auto transaction = m_pageLoadState.transaction();
759         m_pageLoadState.setPendingAPIRequestURL(transaction, url);
760
761         // We may not have an extension yet if back/forward list was reinstated after a WebProcess crash or a browser relaunch
762         bool createdExtension = maybeInitializeSandboxExtensionHandle(URL(URL(), url), sandboxExtensionHandle);
763         if (createdExtension)
764             m_process->willAcquireUniversalFileReadSandboxExtension();
765     }
766
767     if (!isValid()) {
768         reattachToWebProcessWithItem(m_backForwardList->currentItem());
769         return;
770     }
771
772     m_process->send(Messages::WebPage::Reload(generateNavigationID(), reloadFromOrigin, sandboxExtensionHandle), m_pageID);
773     m_process->responsivenessTimer()->start();
774 }
775
776 void WebPageProxy::recordNavigationSnapshot()
777 {
778     if (!m_shouldRecordNavigationSnapshots)
779         return;
780
781 #if PLATFORM(COCOA)
782     ViewSnapshotStore::shared().recordSnapshot(*this);
783 #endif
784 }
785
786 void WebPageProxy::goForward()
787 {
788     WebBackForwardListItem* forwardItem = m_backForwardList->forwardItem();
789     if (!forwardItem)
790         return;
791
792     recordNavigationSnapshot();
793
794     auto transaction = m_pageLoadState.transaction();
795
796     m_pageLoadState.setPendingAPIRequestURL(transaction, forwardItem->url());
797
798     if (!isValid()) {
799         reattachToWebProcessWithItem(forwardItem);
800         return;
801     }
802
803     m_process->send(Messages::WebPage::GoForward(forwardItem->itemID()), m_pageID);
804     m_process->responsivenessTimer()->start();
805 }
806
807 void WebPageProxy::goBack()
808 {
809     WebBackForwardListItem* backItem = m_backForwardList->backItem();
810     if (!backItem)
811         return;
812
813     recordNavigationSnapshot();
814
815     auto transaction = m_pageLoadState.transaction();
816
817     m_pageLoadState.setPendingAPIRequestURL(transaction, backItem->url());
818
819     if (!isValid()) {
820         reattachToWebProcessWithItem(backItem);
821         return;
822     }
823
824     m_process->send(Messages::WebPage::GoBack(backItem->itemID()), m_pageID);
825     m_process->responsivenessTimer()->start();
826 }
827
828 void WebPageProxy::goToBackForwardItem(WebBackForwardListItem* item)
829 {
830     if (!isValid()) {
831         reattachToWebProcessWithItem(item);
832         return;
833     }
834
835     recordNavigationSnapshot();
836     
837     auto transaction = m_pageLoadState.transaction();
838
839     m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
840
841     m_process->send(Messages::WebPage::GoToBackForwardItem(item->itemID()), m_pageID);
842     m_process->responsivenessTimer()->start();
843 }
844
845 void WebPageProxy::tryRestoreScrollPosition()
846 {
847     if (!isValid())
848         return;
849
850     m_process->send(Messages::WebPage::TryRestoreScrollPosition(), m_pageID);
851 }
852
853 void WebPageProxy::didChangeBackForwardList(WebBackForwardListItem* added, Vector<RefPtr<WebBackForwardListItem>> removed)
854 {
855     m_loaderClient->didChangeBackForwardList(this, added, std::move(removed));
856
857 #if PLATFORM(MAC)
858     m_pageClient.clearCustomSwipeViews();
859 #endif
860 }
861
862 void WebPageProxy::willGoToBackForwardListItem(uint64_t itemID, IPC::MessageDecoder& decoder)
863 {
864     RefPtr<API::Object> userData;
865     WebContextUserMessageDecoder messageDecoder(userData, process());
866     if (!decoder.decode(messageDecoder))
867         return;
868
869     if (WebBackForwardListItem* item = m_process->webBackForwardItem(itemID))
870         m_loaderClient->willGoToBackForwardListItem(this, item, userData.get());
871 }
872
873 bool WebPageProxy::canShowMIMEType(const String& mimeType)
874 {
875     if (MIMETypeRegistry::canShowMIMEType(mimeType))
876         return true;
877
878 #if ENABLE(NETSCAPE_PLUGIN_API)
879     String newMimeType = mimeType;
880     PluginModuleInfo plugin = m_process->context().pluginInfoStore().findPlugin(newMimeType, URL());
881     if (!plugin.path.isNull() && m_preferences->pluginsEnabled())
882         return true;
883 #endif // ENABLE(NETSCAPE_PLUGIN_API)
884
885 #if PLATFORM(COCOA)
886     // On Mac, we can show PDFs.
887     if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType) && !WebContext::omitPDFSupport())
888         return true;
889 #endif // PLATFORM(COCOA)
890
891     return false;
892 }
893
894 #if ENABLE(REMOTE_INSPECTOR)
895 void WebPageProxy::setAllowsRemoteInspection(bool allow)
896 {
897     if (m_allowsRemoteInspection == allow)
898         return;
899
900     m_allowsRemoteInspection = allow;
901
902     if (isValid())
903         m_process->send(Messages::WebPage::SetAllowsRemoteInspection(allow), m_pageID);
904 }
905 #endif
906
907 void WebPageProxy::setDrawsBackground(bool drawsBackground)
908 {
909     if (m_drawsBackground == drawsBackground)
910         return;
911
912     m_drawsBackground = drawsBackground;
913
914     if (isValid())
915         m_process->send(Messages::WebPage::SetDrawsBackground(drawsBackground), m_pageID);
916 }
917
918 void WebPageProxy::setDrawsTransparentBackground(bool drawsTransparentBackground)
919 {
920     if (m_drawsTransparentBackground == drawsTransparentBackground)
921         return;
922
923     m_drawsTransparentBackground = drawsTransparentBackground;
924
925     if (isValid())
926         m_process->send(Messages::WebPage::SetDrawsTransparentBackground(drawsTransparentBackground), m_pageID);
927 }
928
929 void WebPageProxy::setTopContentInset(float contentInset)
930 {
931     if (m_topContentInset == contentInset)
932         return;
933
934     m_topContentInset = contentInset;
935
936     if (isValid())
937         m_process->send(Messages::WebPage::SetTopContentInset(contentInset), m_pageID);
938 }
939
940 void WebPageProxy::setUnderlayColor(const Color& color)
941 {
942     if (m_underlayColor == color)
943         return;
944
945     m_underlayColor = color;
946
947     if (isValid())
948         m_process->send(Messages::WebPage::SetUnderlayColor(color), m_pageID);
949 }
950
951 void WebPageProxy::viewWillStartLiveResize()
952 {
953     if (!isValid())
954         return;
955 #if ENABLE(INPUT_TYPE_COLOR_POPOVER)
956     if (m_colorPicker)
957         endColorPicker();
958 #endif
959     m_process->send(Messages::WebPage::ViewWillStartLiveResize(), m_pageID);
960 }
961
962 void WebPageProxy::viewWillEndLiveResize()
963 {
964     if (!isValid())
965         return;
966     m_process->send(Messages::WebPage::ViewWillEndLiveResize(), m_pageID);
967 }
968
969 void WebPageProxy::setViewNeedsDisplay(const IntRect& rect)
970 {
971     m_pageClient.setViewNeedsDisplay(rect);
972 }
973
974 void WebPageProxy::displayView()
975 {
976     m_pageClient.displayView();
977 }
978
979 bool WebPageProxy::canScrollView()
980 {
981     return m_pageClient.canScrollView();
982 }
983
984 void WebPageProxy::scrollView(const IntRect& scrollRect, const IntSize& scrollOffset)
985 {
986     m_pageClient.scrollView(scrollRect, scrollOffset);
987 }
988
989 void WebPageProxy::updateViewState(ViewState::Flags flagsToUpdate)
990 {
991     m_viewState &= ~flagsToUpdate;
992     if (flagsToUpdate & ViewState::IsFocused && m_pageClient.isViewFocused())
993         m_viewState |= ViewState::IsFocused;
994     if (flagsToUpdate & ViewState::WindowIsActive && m_pageClient.isViewWindowActive())
995         m_viewState |= ViewState::WindowIsActive;
996     if (flagsToUpdate & ViewState::IsVisible && m_pageClient.isViewVisible())
997         m_viewState |= ViewState::IsVisible;
998     if (flagsToUpdate & ViewState::IsVisibleOrOccluded && m_pageClient.isViewVisibleOrOccluded())
999         m_viewState |= ViewState::IsVisibleOrOccluded;
1000     if (flagsToUpdate & ViewState::IsInWindow && m_pageClient.isViewInWindow())
1001         m_viewState |= ViewState::IsInWindow;
1002     if (flagsToUpdate & ViewState::IsVisuallyIdle && m_pageClient.isVisuallyIdle())
1003         m_viewState |= ViewState::IsVisuallyIdle;
1004 }
1005
1006 void WebPageProxy::viewStateDidChange(ViewState::Flags mayHaveChanged, WantsReplyOrNot wantsReply)
1007 {
1008     if (!isValid())
1009         return;
1010
1011     // If the visibility state may have changed, then so may the visually idle & occluded agnostic state.
1012     if (mayHaveChanged & ViewState::IsVisible)
1013         mayHaveChanged |= ViewState::IsVisibleOrOccluded | ViewState::IsVisuallyIdle;
1014
1015     // Record the prior view state, update the flags that may have changed,
1016     // and check which flags have actually changed.
1017     ViewState::Flags previousViewState = m_viewState;
1018     updateViewState(mayHaveChanged);
1019     ViewState::Flags changed = m_viewState ^ previousViewState;
1020
1021     if (changed)
1022         m_process->send(Messages::WebPage::SetViewState(m_viewState, wantsReply == WantsReplyOrNot::DoesWantReply), m_pageID);
1023
1024     if (changed & ViewState::IsVisuallyIdle)
1025         m_process->pageSuppressibilityChanged(this);
1026
1027     // If we've started the responsiveness timer as part of telling the web process to update the backing store
1028     // state, it might not send back a reply (since it won't paint anything if the web page is hidden) so we
1029     // stop the unresponsiveness timer here.
1030     if ((changed & ViewState::IsVisible) && !isViewVisible())
1031         m_process->responsivenessTimer()->stop();
1032
1033     if ((mayHaveChanged & ViewState::IsInWindow) && (m_viewState & ViewState::IsInWindow)) {
1034         LayerHostingMode layerHostingMode = m_pageClient.viewLayerHostingMode();
1035         if (m_layerHostingMode != layerHostingMode) {
1036             m_layerHostingMode = layerHostingMode;
1037             m_process->send(Messages::WebPage::SetLayerHostingMode(static_cast<unsigned>(layerHostingMode)), m_pageID);
1038         }
1039     }
1040
1041 #if ENABLE(INPUT_TYPE_COLOR_POPOVER)
1042     if ((mayHaveChanged & ViewState::IsInWindow) && !(m_viewState & ViewState::IsInWindow)) {
1043         // When leaving the current page, close the popover color well.
1044         if (m_colorPicker)
1045             endColorPicker();
1046     }
1047 #endif
1048
1049     if (changed & ViewState::IsInWindow)
1050         process().updateProcessState();
1051
1052     updateBackingStoreDiscardableState();
1053 }
1054
1055 void WebPageProxy::waitForDidUpdateViewState()
1056 {
1057     // If we have previously timed out with no response from the WebProcess, don't block the UIProcess again until it starts responding.
1058     if (m_waitingForDidUpdateViewState)
1059         return;
1060
1061     if (!isValid())
1062         return;
1063
1064     m_waitingForDidUpdateViewState = true;
1065
1066     if (m_process->state() != WebProcessProxy::State::Launching) {
1067         auto viewStateUpdateTimeout = std::chrono::milliseconds(250);
1068         m_process->connection()->waitForAndDispatchImmediately<Messages::WebPageProxy::DidUpdateViewState>(m_pageID, viewStateUpdateTimeout);
1069     }
1070 }
1071
1072 IntSize WebPageProxy::viewSize() const
1073 {
1074     return m_pageClient.viewSize();
1075 }
1076
1077 void WebPageProxy::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& keyboardEvent)
1078 {
1079     if (!isValid())
1080         return;
1081     m_process->send(Messages::WebPage::SetInitialFocus(forward, isKeyboardEventValid, keyboardEvent), m_pageID);
1082 }
1083
1084 void WebPageProxy::setWindowResizerSize(const IntSize& windowResizerSize)
1085 {
1086     if (!isValid())
1087         return;
1088     m_process->send(Messages::WebPage::SetWindowResizerSize(windowResizerSize), m_pageID);
1089 }
1090     
1091 void WebPageProxy::clearSelection()
1092 {
1093     if (!isValid())
1094         return;
1095     m_process->send(Messages::WebPage::ClearSelection(), m_pageID);
1096 }
1097
1098 void WebPageProxy::validateCommand(const String& commandName, PassRefPtr<ValidateCommandCallback> callback)
1099 {
1100     if (!isValid()) {
1101         callback->invalidate();
1102         return;
1103     }
1104
1105     uint64_t callbackID = callback->callbackID();
1106     m_validateCommandCallbacks.set(callbackID, callback);
1107     m_process->send(Messages::WebPage::ValidateCommand(commandName, callbackID), m_pageID);
1108 }
1109
1110 void WebPageProxy::setMaintainsInactiveSelection(bool newValue)
1111 {
1112     m_maintainsInactiveSelection = newValue;
1113 }
1114     
1115 void WebPageProxy::executeEditCommand(const String& commandName)
1116 {
1117     static NeverDestroyed<String> ignoreSpellingCommandName(ASCIILiteral("ignoreSpelling"));
1118
1119     if (!isValid())
1120         return;
1121
1122     if (commandName == ignoreSpellingCommandName)
1123         ++m_pendingLearnOrIgnoreWordMessageCount;
1124
1125     m_process->send(Messages::WebPage::ExecuteEditCommand(commandName), m_pageID);
1126 }
1127     
1128 #if USE(TILED_BACKING_STORE)
1129 void WebPageProxy::commitPageTransitionViewport()
1130 {
1131     if (!isValid())
1132         return;
1133
1134     process().send(Messages::WebPage::CommitPageTransitionViewport(), m_pageID);
1135 }
1136 #endif
1137
1138 #if ENABLE(DRAG_SUPPORT)
1139 void WebPageProxy::dragEntered(DragData& dragData, const String& dragStorageName)
1140 {
1141     SandboxExtension::Handle sandboxExtensionHandle;
1142     SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray;
1143     performDragControllerAction(DragControllerActionEntered, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray);
1144 }
1145
1146 void WebPageProxy::dragUpdated(DragData& dragData, const String& dragStorageName)
1147 {
1148     SandboxExtension::Handle sandboxExtensionHandle;
1149     SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray;
1150     performDragControllerAction(DragControllerActionUpdated, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray);
1151 }
1152
1153 void WebPageProxy::dragExited(DragData& dragData, const String& dragStorageName)
1154 {
1155     SandboxExtension::Handle sandboxExtensionHandle;
1156     SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray;
1157     performDragControllerAction(DragControllerActionExited, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray);
1158 }
1159
1160 void WebPageProxy::performDrag(DragData& dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle, const SandboxExtension::HandleArray& sandboxExtensionsForUpload)
1161 {
1162     performDragControllerAction(DragControllerActionPerformDrag, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionsForUpload);
1163 }
1164
1165 void WebPageProxy::performDragControllerAction(DragControllerAction action, DragData& dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle, const SandboxExtension::HandleArray& sandboxExtensionsForUpload)
1166 {
1167     if (!isValid())
1168         return;
1169 #if PLATFORM(GTK)
1170     UNUSED_PARAM(dragStorageName);
1171     UNUSED_PARAM(sandboxExtensionHandle);
1172     UNUSED_PARAM(sandboxExtensionsForUpload);
1173     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData), m_pageID);
1174 #else
1175     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData.clientPosition(), dragData.globalPosition(), dragData.draggingSourceOperationMask(), dragStorageName, dragData.flags(), sandboxExtensionHandle, sandboxExtensionsForUpload), m_pageID);
1176 #endif
1177 }
1178
1179 void WebPageProxy::didPerformDragControllerAction(WebCore::DragSession dragSession)
1180 {
1181     m_currentDragSession = dragSession;
1182 }
1183
1184 #if PLATFORM(GTK)
1185 void WebPageProxy::startDrag(const DragData& dragData, const ShareableBitmap::Handle& dragImageHandle)
1186 {
1187     RefPtr<ShareableBitmap> dragImage = 0;
1188     if (!dragImageHandle.isNull()) {
1189         dragImage = ShareableBitmap::create(dragImageHandle);
1190         if (!dragImage)
1191             return;
1192     }
1193
1194     m_pageClient.startDrag(dragData, dragImage.release());
1195 }
1196 #endif
1197
1198 void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& globalPosition, uint64_t operation)
1199 {
1200     if (!isValid())
1201         return;
1202     m_process->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID);
1203 }
1204 #endif // ENABLE(DRAG_SUPPORT)
1205
1206 void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event)
1207 {
1208     if (!isValid())
1209         return;
1210
1211     // NOTE: This does not start the responsiveness timer because mouse move should not indicate interaction.
1212     if (event.type() != WebEvent::MouseMove)
1213         m_process->responsivenessTimer()->start();
1214     else {
1215         if (m_processingMouseMoveEvent) {
1216             m_nextMouseMoveEvent = adoptPtr(new NativeWebMouseEvent(event));
1217             return;
1218         }
1219
1220         m_processingMouseMoveEvent = true;
1221     }
1222
1223     // <https://bugs.webkit.org/show_bug.cgi?id=57904> We need to keep track of the mouse down event in the case where we
1224     // display a popup menu for select elements. When the user changes the selected item,
1225     // we fake a mouse up event by using this stored down event. This event gets cleared
1226     // when the mouse up message is received from WebProcess.
1227     if (event.type() == WebEvent::MouseDown)
1228         m_currentlyProcessedMouseDownEvent = adoptPtr(new NativeWebMouseEvent(event));
1229
1230     if (m_shouldSendEventsSynchronously) {
1231         bool handled = false;
1232         m_process->sendSync(Messages::WebPage::MouseEventSyncForTesting(event), Messages::WebPage::MouseEventSyncForTesting::Reply(handled), m_pageID);
1233         didReceiveEvent(event.type(), handled);
1234     } else
1235         m_process->send(Messages::WebPage::MouseEvent(event), m_pageID);
1236 }
1237
1238 #if MERGE_WHEEL_EVENTS
1239 static bool canCoalesce(const WebWheelEvent& a, const WebWheelEvent& b)
1240 {
1241     if (a.position() != b.position())
1242         return false;
1243     if (a.globalPosition() != b.globalPosition())
1244         return false;
1245     if (a.modifiers() != b.modifiers())
1246         return false;
1247     if (a.granularity() != b.granularity())
1248         return false;
1249 #if PLATFORM(COCOA)
1250     if (a.phase() != b.phase())
1251         return false;
1252     if (a.momentumPhase() != b.momentumPhase())
1253         return false;
1254     if (a.hasPreciseScrollingDeltas() != b.hasPreciseScrollingDeltas())
1255         return false;
1256 #endif
1257
1258     return true;
1259 }
1260
1261 static WebWheelEvent coalesce(const WebWheelEvent& a, const WebWheelEvent& b)
1262 {
1263     ASSERT(canCoalesce(a, b));
1264
1265     FloatSize mergedDelta = a.delta() + b.delta();
1266     FloatSize mergedWheelTicks = a.wheelTicks() + b.wheelTicks();
1267
1268 #if PLATFORM(COCOA)
1269     FloatSize mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta();
1270
1271     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());
1272 #else
1273     return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp());
1274 #endif
1275 }
1276 #endif // MERGE_WHEEL_EVENTS
1277
1278 static WebWheelEvent coalescedWheelEvent(Deque<NativeWebWheelEvent>& queue, Vector<NativeWebWheelEvent>& coalescedEvents)
1279 {
1280     ASSERT(!queue.isEmpty());
1281     ASSERT(coalescedEvents.isEmpty());
1282
1283 #if MERGE_WHEEL_EVENTS
1284     NativeWebWheelEvent firstEvent = queue.takeFirst();
1285     coalescedEvents.append(firstEvent);
1286
1287     WebWheelEvent event = firstEvent;
1288     while (!queue.isEmpty() && canCoalesce(event, queue.first())) {
1289         NativeWebWheelEvent firstEvent = queue.takeFirst();
1290         coalescedEvents.append(firstEvent);
1291         event = coalesce(event, firstEvent);
1292     }
1293
1294     return event;
1295 #else
1296     while (!queue.isEmpty())
1297         coalescedEvents.append(queue.takeFirst());
1298     return coalescedEvents.last();
1299 #endif
1300 }
1301
1302 void WebPageProxy::handleWheelEvent(const NativeWebWheelEvent& event)
1303 {
1304 #if ENABLE(ASYNC_SCROLLING)
1305     if (m_scrollingCoordinatorProxy && m_scrollingCoordinatorProxy->handleWheelEvent(platform(event)))
1306         return;
1307 #endif
1308
1309     if (!isValid())
1310         return;
1311
1312     if (!m_currentlyProcessedWheelEvents.isEmpty()) {
1313         m_wheelEventQueue.append(event);
1314         if (m_wheelEventQueue.size() < wheelEventQueueSizeThreshold)
1315             return;
1316         // The queue has too many wheel events, so push a new event.
1317     }
1318
1319     if (!m_wheelEventQueue.isEmpty()) {
1320         processNextQueuedWheelEvent();
1321         return;
1322     }
1323
1324     OwnPtr<Vector<NativeWebWheelEvent>> coalescedWheelEvent = adoptPtr(new Vector<NativeWebWheelEvent>);
1325     coalescedWheelEvent->append(event);
1326     m_currentlyProcessedWheelEvents.append(coalescedWheelEvent.release());
1327     sendWheelEvent(event);
1328 }
1329
1330 void WebPageProxy::processNextQueuedWheelEvent()
1331 {
1332     OwnPtr<Vector<NativeWebWheelEvent>> nextCoalescedEvent = adoptPtr(new Vector<NativeWebWheelEvent>);
1333     WebWheelEvent nextWheelEvent = coalescedWheelEvent(m_wheelEventQueue, *nextCoalescedEvent.get());
1334     m_currentlyProcessedWheelEvents.append(nextCoalescedEvent.release());
1335     sendWheelEvent(nextWheelEvent);
1336 }
1337
1338 void WebPageProxy::sendWheelEvent(const WebWheelEvent& event)
1339 {
1340     m_process->responsivenessTimer()->start();
1341
1342     if (m_shouldSendEventsSynchronously) {
1343         bool handled = false;
1344         m_process->sendSync(Messages::WebPage::WheelEventSyncForTesting(event), Messages::WebPage::WheelEventSyncForTesting::Reply(handled), m_pageID);
1345         didReceiveEvent(event.type(), handled);
1346         return;
1347     }
1348
1349     m_process->send(
1350         Messages::EventDispatcher::WheelEvent(
1351             m_pageID,
1352             event,
1353             shouldUseImplicitRubberBandControl() ? !m_backForwardList->backItem() : rubberBandsAtLeft(),
1354             shouldUseImplicitRubberBandControl() ? !m_backForwardList->forwardItem() : rubberBandsAtRight(),
1355             rubberBandsAtTop(),
1356             rubberBandsAtBottom()
1357         ), 0);
1358 }
1359
1360 void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
1361 {
1362     if (!isValid())
1363         return;
1364     
1365     LOG(KeyHandling, "WebPageProxy::handleKeyboardEvent: %s", webKeyboardEventTypeString(event.type()));
1366
1367     m_keyEventQueue.append(event);
1368
1369     m_process->responsivenessTimer()->start();
1370     if (m_shouldSendEventsSynchronously) {
1371         bool handled = false;
1372         m_process->sendSync(Messages::WebPage::KeyEventSyncForTesting(event), Messages::WebPage::KeyEventSyncForTesting::Reply(handled), m_pageID);
1373         didReceiveEvent(event.type(), handled);
1374     } else if (m_keyEventQueue.size() == 1) // Otherwise, sent from DidReceiveEvent message handler.
1375         m_process->send(Messages::WebPage::KeyEvent(event), m_pageID);
1376 }
1377
1378 uint64_t WebPageProxy::generateNavigationID()
1379 {
1380     return ++m_navigationID;
1381 }
1382
1383 #if ENABLE(NETSCAPE_PLUGIN_API)
1384 void 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)
1385 {
1386     MESSAGE_CHECK_URL(urlString);
1387
1388     newMimeType = mimeType.lower();
1389     pluginLoadPolicy = PluginModuleLoadNormally;
1390
1391     PluginData::AllowedPluginTypes allowedPluginTypes = allowOnlyApplicationPlugins ? PluginData::OnlyApplicationPlugins : PluginData::AllPlugins;
1392     PluginModuleInfo plugin = m_process->context().pluginInfoStore().findPlugin(newMimeType, URL(URL(), urlString), allowedPluginTypes);
1393     if (!plugin.path) {
1394         pluginProcessToken = 0;
1395         return;
1396     }
1397
1398     pluginLoadPolicy = PluginInfoStore::defaultLoadPolicyForPlugin(plugin);
1399
1400 #if PLATFORM(COCOA)
1401     RefPtr<ImmutableDictionary> pluginInformation = createPluginInformationDictionary(plugin, frameURLString, String(), pageURLString, String(), String());
1402     pluginLoadPolicy = m_loaderClient->pluginLoadPolicy(this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), unavailabilityDescription);
1403 #else
1404     UNUSED_PARAM(frameURLString);
1405     UNUSED_PARAM(pageURLString);
1406     UNUSED_PARAM(unavailabilityDescription);
1407 #endif
1408
1409     PluginProcessSandboxPolicy pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
1410     switch (pluginLoadPolicy) {
1411     case PluginModuleLoadNormally:
1412         pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
1413         break;
1414     case PluginModuleLoadUnsandboxed:
1415         pluginProcessSandboxPolicy = PluginProcessSandboxPolicyUnsandboxed;
1416         break;
1417
1418     case PluginModuleBlocked:
1419         pluginProcessToken = 0;
1420         return;
1421     }
1422
1423     pluginProcessToken = PluginProcessManager::shared().pluginProcessToken(plugin, static_cast<PluginProcessType>(processType), pluginProcessSandboxPolicy);
1424 }
1425
1426 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1427
1428 #if ENABLE(TOUCH_EVENTS)
1429
1430 bool WebPageProxy::shouldStartTrackingTouchEvents(const WebTouchEvent& touchStartEvent) const
1431 {
1432 #if ENABLE(ASYNC_SCROLLING)
1433     for (auto& touchPoint : touchStartEvent.touchPoints()) {
1434         if (m_scrollingCoordinatorProxy->isPointInNonFastScrollableRegion(touchPoint.location()))
1435             return true;
1436     }
1437
1438     return false;
1439 #else
1440     UNUSED_PARAM(touchStartEvent);
1441 #endif // ENABLE(ASYNC_SCROLLING)
1442     return true;
1443 }
1444
1445 void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
1446 {
1447     if (!isValid())
1448         return;
1449
1450     if (event.type() == WebEvent::TouchStart)
1451         m_isTrackingTouchEvents = shouldStartTrackingTouchEvents(event);
1452
1453     if (!m_isTrackingTouchEvents)
1454         return;
1455
1456     // If the page is suspended, which should be the case during panning, pinching
1457     // and animation on the page itself (kinetic scrolling, tap to zoom) etc, then
1458     // we do not send any of the events to the page even if is has listeners.
1459     if (!m_isPageSuspended) {
1460         m_touchEventQueue.append(event);
1461         m_process->responsivenessTimer()->start();
1462         if (m_shouldSendEventsSynchronously) {
1463             bool handled = false;
1464             m_process->sendSync(Messages::WebPage::TouchEventSyncForTesting(event), Messages::WebPage::TouchEventSyncForTesting::Reply(handled), m_pageID);
1465             didReceiveEvent(event.type(), handled);
1466         } else
1467             m_process->send(Messages::WebPage::TouchEvent(event), m_pageID);
1468     } else {
1469         if (m_touchEventQueue.isEmpty()) {
1470             bool isEventHandled = false;
1471             m_pageClient.doneWithTouchEvent(event, isEventHandled);
1472         } else {
1473             // We attach the incoming events to the newest queued event so that all
1474             // the events are delivered in the correct order when the event is dequed.
1475             QueuedTouchEvents& lastEvent = m_touchEventQueue.last();
1476             lastEvent.deferredTouchEvents.append(event);
1477         }
1478     }
1479
1480     if (event.type() == WebEvent::TouchEnd || event.type() == WebEvent::TouchCancel)
1481         m_isTrackingTouchEvents = false;
1482 }
1483 #endif // ENABLE(TOUCH_EVENTS)
1484
1485 void WebPageProxy::scrollBy(ScrollDirection direction, ScrollGranularity granularity)
1486 {
1487     if (!isValid())
1488         return;
1489
1490     m_process->send(Messages::WebPage::ScrollBy(direction, granularity), m_pageID);
1491 }
1492
1493 void WebPageProxy::centerSelectionInVisibleArea()
1494 {
1495     if (!isValid())
1496         return;
1497
1498     m_process->send(Messages::WebPage::CenterSelectionInVisibleArea(), m_pageID);
1499 }
1500
1501 void WebPageProxy::receivedPolicyDecision(PolicyAction action, WebFrameProxy* frame, uint64_t listenerID)
1502 {
1503     if (!isValid())
1504         return;
1505
1506     auto transaction = m_pageLoadState.transaction();
1507
1508     if (action == PolicyIgnore)
1509         m_pageLoadState.clearPendingAPIRequestURL(transaction);
1510
1511     uint64_t downloadID = 0;
1512     if (action == PolicyDownload) {
1513         // Create a download proxy.
1514         DownloadProxy* download = m_process->context().createDownloadProxy();
1515         downloadID = download->downloadID();
1516 #if PLATFORM(EFL) || PLATFORM(GTK)
1517         // Our design does not suppport downloads without a WebPage.
1518         handleDownloadRequest(download);
1519 #endif
1520     }
1521
1522     // If we received a policy decision while in decidePolicyForResponse the decision will
1523     // be sent back to the web process by decidePolicyForResponse.
1524     if (m_inDecidePolicyForResponseSync) {
1525         m_syncMimeTypePolicyActionIsValid = true;
1526         m_syncMimeTypePolicyAction = action;
1527         m_syncMimeTypePolicyDownloadID = downloadID;
1528         return;
1529     }
1530
1531     // If we received a policy decision while in decidePolicyForNavigationAction the decision will 
1532     // be sent back to the web process by decidePolicyForNavigationAction. 
1533     if (m_inDecidePolicyForNavigationAction) {
1534         m_syncNavigationActionPolicyActionIsValid = true;
1535         m_syncNavigationActionPolicyAction = action;
1536         m_syncNavigationActionPolicyDownloadID = downloadID;
1537         return;
1538     }
1539     
1540     m_process->send(Messages::WebPage::DidReceivePolicyDecision(frame->frameID(), listenerID, action, downloadID), m_pageID);
1541 }
1542
1543 void WebPageProxy::setUserAgent(const String& userAgent)
1544 {
1545     if (m_userAgent == userAgent)
1546         return;
1547     m_userAgent = userAgent;
1548
1549     if (!isValid())
1550         return;
1551     m_process->send(Messages::WebPage::SetUserAgent(m_userAgent), m_pageID);
1552 }
1553
1554 void WebPageProxy::setApplicationNameForUserAgent(const String& applicationName)
1555 {
1556     if (m_applicationNameForUserAgent == applicationName)
1557         return;
1558
1559     m_applicationNameForUserAgent = applicationName;
1560     if (!m_customUserAgent.isEmpty())
1561         return;
1562
1563     setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
1564 }
1565
1566 void WebPageProxy::setCustomUserAgent(const String& customUserAgent)
1567 {
1568     if (m_customUserAgent == customUserAgent)
1569         return;
1570
1571     m_customUserAgent = customUserAgent;
1572
1573     if (m_customUserAgent.isEmpty()) {
1574         setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
1575         return;
1576     }
1577
1578     setUserAgent(m_customUserAgent);
1579 }
1580
1581 void WebPageProxy::resumeActiveDOMObjectsAndAnimations()
1582 {
1583     if (!isValid() || !m_isPageSuspended)
1584         return;
1585
1586     m_isPageSuspended = false;
1587
1588     m_process->send(Messages::WebPage::ResumeActiveDOMObjectsAndAnimations(), m_pageID);
1589 }
1590
1591 void WebPageProxy::suspendActiveDOMObjectsAndAnimations()
1592 {
1593     if (!isValid() || m_isPageSuspended)
1594         return;
1595
1596     m_isPageSuspended = true;
1597
1598     m_process->send(Messages::WebPage::SuspendActiveDOMObjectsAndAnimations(), m_pageID);
1599 }
1600
1601 bool WebPageProxy::supportsTextEncoding() const
1602 {
1603     // FIXME (118840): We should probably only support this for text documents, not all non-image documents.
1604     return m_mainFrame && !m_mainFrame->isDisplayingStandaloneImageDocument();
1605 }
1606
1607 void WebPageProxy::setCustomTextEncodingName(const String& encodingName)
1608 {
1609     if (m_customTextEncodingName == encodingName)
1610         return;
1611     m_customTextEncodingName = encodingName;
1612
1613     if (!isValid())
1614         return;
1615     m_process->send(Messages::WebPage::SetCustomTextEncodingName(encodingName), m_pageID);
1616 }
1617
1618 void WebPageProxy::terminateProcess()
1619 {
1620     // NOTE: This uses a check of m_isValid rather than calling isValid() since
1621     // we want this to run even for pages being closed or that already closed.
1622     if (!m_isValid)
1623         return;
1624
1625     m_process->requestTermination();
1626     resetStateAfterProcessExited();
1627 }
1628
1629 #if !USE(CF)
1630 PassRefPtr<API::Data> WebPageProxy::sessionStateData(WebPageProxySessionStateFilterCallback, void* /*context*/) const
1631 {
1632     // FIXME: Return session state data for saving Page state.
1633     return 0;
1634 }
1635
1636 void WebPageProxy::restoreFromSessionStateData(API::Data*)
1637 {
1638     // FIXME: Restore the Page from the passed in session state data.
1639 }
1640 #endif
1641
1642 bool WebPageProxy::supportsTextZoom() const
1643 {
1644     // FIXME (118840): This should also return false for standalone media and plug-in documents.
1645     if (!m_mainFrame || m_mainFrame->isDisplayingStandaloneImageDocument())
1646         return false;
1647
1648     return true;
1649 }
1650  
1651 void WebPageProxy::setTextZoomFactor(double zoomFactor)
1652 {
1653     if (!isValid())
1654         return;
1655
1656     if (m_textZoomFactor == zoomFactor)
1657         return;
1658
1659     m_textZoomFactor = zoomFactor;
1660     m_process->send(Messages::WebPage::SetTextZoomFactor(m_textZoomFactor), m_pageID); 
1661 }
1662
1663 void WebPageProxy::setPageZoomFactor(double zoomFactor)
1664 {
1665     if (!isValid())
1666         return;
1667
1668     if (m_pageZoomFactor == zoomFactor)
1669         return;
1670
1671     m_pageZoomFactor = zoomFactor;
1672     m_process->send(Messages::WebPage::SetPageZoomFactor(m_pageZoomFactor), m_pageID); 
1673 }
1674
1675 void WebPageProxy::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
1676 {
1677     if (!isValid())
1678         return;
1679
1680     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
1681         return;
1682
1683     m_pageZoomFactor = pageZoomFactor;
1684     m_textZoomFactor = textZoomFactor;
1685     m_process->send(Messages::WebPage::SetPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor), m_pageID); 
1686 }
1687
1688 void WebPageProxy::scalePage(double scale, const IntPoint& origin)
1689 {
1690     if (!isValid())
1691         return;
1692
1693     m_pageScaleFactor = scale;
1694     m_process->send(Messages::WebPage::ScalePage(scale, origin), m_pageID);
1695 }
1696
1697 void WebPageProxy::setIntrinsicDeviceScaleFactor(float scaleFactor)
1698 {
1699     if (m_intrinsicDeviceScaleFactor == scaleFactor)
1700         return;
1701
1702     m_intrinsicDeviceScaleFactor = scaleFactor;
1703
1704     if (m_drawingArea)
1705         m_drawingArea->deviceScaleFactorDidChange();
1706 }
1707
1708 void WebPageProxy::windowScreenDidChange(PlatformDisplayID displayID)
1709 {
1710     if (!isValid())
1711         return;
1712
1713     m_process->send(Messages::WebPage::WindowScreenDidChange(displayID), m_pageID);
1714 }
1715
1716 float WebPageProxy::deviceScaleFactor() const
1717 {
1718     if (m_customDeviceScaleFactor)
1719         return m_customDeviceScaleFactor;
1720     return m_intrinsicDeviceScaleFactor;
1721 }
1722
1723 void WebPageProxy::setCustomDeviceScaleFactor(float customScaleFactor)
1724 {
1725     if (!isValid())
1726         return;
1727
1728     if (m_customDeviceScaleFactor == customScaleFactor)
1729         return;
1730
1731     float oldScaleFactor = deviceScaleFactor();
1732
1733     m_customDeviceScaleFactor = customScaleFactor;
1734
1735     if (deviceScaleFactor() != oldScaleFactor)
1736         m_drawingArea->deviceScaleFactorDidChange();
1737 }
1738
1739 void WebPageProxy::setUseFixedLayout(bool fixed)
1740 {
1741     if (!isValid())
1742         return;
1743
1744     // This check is fine as the value is initialized in the web
1745     // process as part of the creation parameters.
1746     if (fixed == m_useFixedLayout)
1747         return;
1748
1749     m_useFixedLayout = fixed;
1750     if (!fixed)
1751         m_fixedLayoutSize = IntSize();
1752     m_process->send(Messages::WebPage::SetUseFixedLayout(fixed), m_pageID);
1753 }
1754
1755 void WebPageProxy::setFixedLayoutSize(const IntSize& size)
1756 {
1757     if (!isValid())
1758         return;
1759
1760     if (size == m_fixedLayoutSize)
1761         return;
1762
1763     m_fixedLayoutSize = size;
1764     m_process->send(Messages::WebPage::SetFixedLayoutSize(size), m_pageID);
1765 }
1766
1767 void WebPageProxy::listenForLayoutMilestones(WebCore::LayoutMilestones milestones)
1768 {
1769     if (!isValid())
1770         return;
1771
1772     m_process->send(Messages::WebPage::ListenForLayoutMilestones(milestones), m_pageID);
1773 }
1774
1775 void WebPageProxy::setSuppressScrollbarAnimations(bool suppressAnimations)
1776 {
1777     if (!isValid())
1778         return;
1779
1780     if (suppressAnimations == m_suppressScrollbarAnimations)
1781         return;
1782
1783     m_suppressScrollbarAnimations = suppressAnimations;
1784     m_process->send(Messages::WebPage::SetSuppressScrollbarAnimations(suppressAnimations), m_pageID);
1785 }
1786
1787 bool WebPageProxy::rubberBandsAtLeft() const
1788 {
1789     return m_rubberBandsAtLeft;
1790 }
1791
1792 void WebPageProxy::setRubberBandsAtLeft(bool rubberBandsAtLeft)
1793 {
1794     m_rubberBandsAtLeft = rubberBandsAtLeft;
1795 }
1796
1797 bool WebPageProxy::rubberBandsAtRight() const
1798 {
1799     return m_rubberBandsAtRight;
1800 }
1801
1802 void WebPageProxy::setRubberBandsAtRight(bool rubberBandsAtRight)
1803 {
1804     m_rubberBandsAtRight = rubberBandsAtRight;
1805 }
1806
1807 bool WebPageProxy::rubberBandsAtTop() const
1808 {
1809     return m_rubberBandsAtTop;
1810 }
1811
1812 void WebPageProxy::setRubberBandsAtTop(bool rubberBandsAtTop)
1813 {
1814     m_rubberBandsAtTop = rubberBandsAtTop;
1815 }
1816
1817 bool WebPageProxy::rubberBandsAtBottom() const
1818 {
1819     return m_rubberBandsAtBottom;
1820 }
1821
1822 void WebPageProxy::setRubberBandsAtBottom(bool rubberBandsAtBottom)
1823 {
1824     m_rubberBandsAtBottom = rubberBandsAtBottom;
1825 }
1826
1827 void WebPageProxy::setBackgroundExtendsBeyondPage(bool backgroundExtendsBeyondPage)
1828 {
1829     if (backgroundExtendsBeyondPage == m_backgroundExtendsBeyondPage)
1830         return;
1831
1832     m_backgroundExtendsBeyondPage = backgroundExtendsBeyondPage;
1833
1834     if (!isValid())
1835         return;
1836     m_process->send(Messages::WebPage::SetBackgroundExtendsBeyondPage(backgroundExtendsBeyondPage), m_pageID);
1837 }
1838
1839 bool WebPageProxy::backgroundExtendsBeyondPage() const
1840 {
1841     return m_backgroundExtendsBeyondPage;
1842 }
1843
1844 void WebPageProxy::setPaginationMode(WebCore::Pagination::Mode mode)
1845 {
1846     if (mode == m_paginationMode)
1847         return;
1848
1849     m_paginationMode = mode;
1850
1851     if (!isValid())
1852         return;
1853     m_process->send(Messages::WebPage::SetPaginationMode(mode), m_pageID);
1854 }
1855
1856 void WebPageProxy::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
1857 {
1858     if (behavesLikeColumns == m_paginationBehavesLikeColumns)
1859         return;
1860
1861     m_paginationBehavesLikeColumns = behavesLikeColumns;
1862
1863     if (!isValid())
1864         return;
1865     m_process->send(Messages::WebPage::SetPaginationBehavesLikeColumns(behavesLikeColumns), m_pageID);
1866 }
1867
1868 void WebPageProxy::setPageLength(double pageLength)
1869 {
1870     if (pageLength == m_pageLength)
1871         return;
1872
1873     m_pageLength = pageLength;
1874
1875     if (!isValid())
1876         return;
1877     m_process->send(Messages::WebPage::SetPageLength(pageLength), m_pageID);
1878 }
1879
1880 void WebPageProxy::setGapBetweenPages(double gap)
1881 {
1882     if (gap == m_gapBetweenPages)
1883         return;
1884
1885     m_gapBetweenPages = gap;
1886
1887     if (!isValid())
1888         return;
1889     m_process->send(Messages::WebPage::SetGapBetweenPages(gap), m_pageID);
1890 }
1891
1892 void WebPageProxy::pageScaleFactorDidChange(double scaleFactor)
1893 {
1894     m_pageScaleFactor = scaleFactor;
1895 }
1896
1897 void WebPageProxy::pageZoomFactorDidChange(double zoomFactor)
1898 {
1899     m_pageZoomFactor = zoomFactor;
1900 }
1901
1902 void WebPageProxy::setMemoryCacheClientCallsEnabled(bool memoryCacheClientCallsEnabled)
1903 {
1904     if (!isValid())
1905         return;
1906
1907     if (m_areMemoryCacheClientCallsEnabled == memoryCacheClientCallsEnabled)
1908         return;
1909
1910     m_areMemoryCacheClientCallsEnabled = memoryCacheClientCallsEnabled;
1911     m_process->send(Messages::WebPage::SetMemoryCacheMessagesEnabled(memoryCacheClientCallsEnabled), m_pageID);
1912 }
1913
1914 void WebPageProxy::findStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
1915 {
1916     if (string.isEmpty()) {
1917         didFindStringMatches(string, Vector<Vector<WebCore::IntRect>> (), 0);
1918         return;
1919     }
1920
1921     m_process->send(Messages::WebPage::FindStringMatches(string, options, maxMatchCount), m_pageID);
1922 }
1923
1924 void WebPageProxy::findString(const String& string, FindOptions options, unsigned maxMatchCount)
1925 {
1926     m_process->send(Messages::WebPage::FindString(string, options, maxMatchCount), m_pageID);
1927 }
1928
1929 void WebPageProxy::getImageForFindMatch(int32_t matchIndex)
1930 {
1931     m_process->send(Messages::WebPage::GetImageForFindMatch(matchIndex), m_pageID);
1932 }
1933
1934 void WebPageProxy::selectFindMatch(int32_t matchIndex)
1935 {
1936     m_process->send(Messages::WebPage::SelectFindMatch(matchIndex), m_pageID);
1937 }
1938
1939 void WebPageProxy::hideFindUI()
1940 {
1941     m_process->send(Messages::WebPage::HideFindUI(), m_pageID);
1942 }
1943
1944 void WebPageProxy::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
1945 {
1946     if (!isValid())
1947         return;
1948
1949     m_process->send(Messages::WebPage::CountStringMatches(string, options, maxMatchCount), m_pageID);
1950 }
1951
1952 void WebPageProxy::runJavaScriptInMainFrame(const String& script, PassRefPtr<ScriptValueCallback> prpCallback)
1953 {
1954     RefPtr<ScriptValueCallback> callback = prpCallback;
1955     if (!isValid()) {
1956         callback->invalidate();
1957         return;
1958     }
1959
1960     uint64_t callbackID = callback->callbackID();
1961     m_scriptValueCallbacks.set(callbackID, callback);
1962     m_process->send(Messages::WebPage::RunJavaScriptInMainFrame(script, callbackID), m_pageID);
1963 }
1964
1965 void WebPageProxy::getRenderTreeExternalRepresentation(PassRefPtr<StringCallback> prpCallback)
1966 {
1967     RefPtr<StringCallback> callback = prpCallback;
1968     if (!isValid()) {
1969         callback->invalidate();
1970         return;
1971     }
1972     
1973     uint64_t callbackID = callback->callbackID();
1974     m_stringCallbacks.set(callbackID, callback);
1975     m_process->send(Messages::WebPage::GetRenderTreeExternalRepresentation(callbackID), m_pageID);
1976 }
1977
1978 void WebPageProxy::getSourceForFrame(WebFrameProxy* frame, PassRefPtr<StringCallback> prpCallback)
1979 {
1980     RefPtr<StringCallback> callback = prpCallback;
1981     if (!isValid()) {
1982         callback->invalidate();
1983         return;
1984     }
1985     
1986     uint64_t callbackID = callback->callbackID();
1987     m_loadDependentStringCallbackIDs.add(callbackID);
1988     m_stringCallbacks.set(callbackID, callback);
1989     m_process->send(Messages::WebPage::GetSourceForFrame(frame->frameID(), callbackID), m_pageID);
1990 }
1991
1992 void WebPageProxy::getContentsAsString(PassRefPtr<StringCallback> prpCallback)
1993 {
1994     RefPtr<StringCallback> callback = prpCallback;
1995     if (!isValid()) {
1996         callback->invalidate();
1997         return;
1998     }
1999     
2000     uint64_t callbackID = callback->callbackID();
2001     m_loadDependentStringCallbackIDs.add(callbackID);
2002     m_stringCallbacks.set(callbackID, callback);
2003     m_process->send(Messages::WebPage::GetContentsAsString(callbackID), m_pageID);
2004 }
2005
2006 void WebPageProxy::getBytecodeProfile(PassRefPtr<StringCallback> prpCallback)
2007 {
2008     RefPtr<StringCallback> callback = prpCallback;
2009     if (!isValid()) {
2010         callback->invalidate();
2011         return;
2012     }
2013     
2014     uint64_t callbackID = callback->callbackID();
2015     m_loadDependentStringCallbackIDs.add(callbackID);
2016     m_stringCallbacks.set(callbackID, callback);
2017     m_process->send(Messages::WebPage::GetBytecodeProfile(callbackID), m_pageID);
2018 }
2019     
2020 #if ENABLE(MHTML)
2021 void WebPageProxy::getContentsAsMHTMLData(PassRefPtr<DataCallback> prpCallback, bool useBinaryEncoding)
2022 {
2023     RefPtr<DataCallback> callback = prpCallback;
2024     if (!isValid()) {
2025         callback->invalidate();
2026         return;
2027     }
2028
2029     uint64_t callbackID = callback->callbackID();
2030     m_dataCallbacks.set(callbackID, callback);
2031     m_process->send(Messages::WebPage::GetContentsAsMHTMLData(callbackID, useBinaryEncoding), m_pageID);
2032 }
2033 #endif
2034
2035 void WebPageProxy::getSelectionOrContentsAsString(PassRefPtr<StringCallback> prpCallback)
2036 {
2037     RefPtr<StringCallback> callback = prpCallback;
2038     if (!isValid()) {
2039         callback->invalidate();
2040         return;
2041     }
2042     
2043     uint64_t callbackID = callback->callbackID();
2044     m_stringCallbacks.set(callbackID, callback);
2045     m_process->send(Messages::WebPage::GetSelectionOrContentsAsString(callbackID), m_pageID);
2046 }
2047
2048 void WebPageProxy::getSelectionAsWebArchiveData(PassRefPtr<DataCallback> prpCallback)
2049 {
2050     RefPtr<DataCallback> callback = prpCallback;
2051     if (!isValid()) {
2052         callback->invalidate();
2053         return;
2054     }
2055     
2056     uint64_t callbackID = callback->callbackID();
2057     m_dataCallbacks.set(callbackID, callback);
2058     m_process->send(Messages::WebPage::GetSelectionAsWebArchiveData(callbackID), m_pageID);
2059 }
2060
2061 void WebPageProxy::getMainResourceDataOfFrame(WebFrameProxy* frame, PassRefPtr<DataCallback> prpCallback)
2062 {
2063     RefPtr<DataCallback> callback = prpCallback;
2064     if (!isValid()) {
2065         callback->invalidate();
2066         return;
2067     }
2068     
2069     uint64_t callbackID = callback->callbackID();
2070     m_dataCallbacks.set(callbackID, callback);
2071     m_process->send(Messages::WebPage::GetMainResourceDataOfFrame(frame->frameID(), callbackID), m_pageID);
2072 }
2073
2074 void WebPageProxy::getResourceDataFromFrame(WebFrameProxy* frame, API::URL* resourceURL, PassRefPtr<DataCallback> prpCallback)
2075 {
2076     RefPtr<DataCallback> callback = prpCallback;
2077     if (!isValid()) {
2078         callback->invalidate();
2079         return;
2080     }
2081     
2082     uint64_t callbackID = callback->callbackID();
2083     m_dataCallbacks.set(callbackID, callback);
2084     m_process->send(Messages::WebPage::GetResourceDataFromFrame(frame->frameID(), resourceURL->string(), callbackID), m_pageID);
2085 }
2086
2087 void WebPageProxy::getWebArchiveOfFrame(WebFrameProxy* frame, PassRefPtr<DataCallback> prpCallback)
2088 {
2089     RefPtr<DataCallback> callback = prpCallback;
2090     if (!isValid()) {
2091         callback->invalidate();
2092         return;
2093     }
2094     
2095     uint64_t callbackID = callback->callbackID();
2096     m_dataCallbacks.set(callbackID, callback);
2097     m_process->send(Messages::WebPage::GetWebArchiveOfFrame(frame->frameID(), callbackID), m_pageID);
2098 }
2099
2100 void WebPageProxy::forceRepaint(PassRefPtr<VoidCallback> prpCallback)
2101 {
2102     RefPtr<VoidCallback> callback = prpCallback;
2103     if (!isValid()) {
2104         callback->invalidate();
2105         return;
2106     }
2107
2108     uint64_t callbackID = callback->callbackID();
2109     m_voidCallbacks.set(callbackID, callback);
2110     m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
2111     m_process->send(Messages::WebPage::ForceRepaint(callbackID), m_pageID); 
2112 }
2113
2114 void WebPageProxy::preferencesDidChange()
2115 {
2116     if (!isValid())
2117         return;
2118
2119 #if ENABLE(INSPECTOR_SERVER)
2120     if (m_preferences->developerExtrasEnabled())
2121         inspector()->enableRemoteInspection();
2122 #endif
2123
2124     m_process->pagePreferencesChanged(this);
2125
2126     m_pageClient.preferencesDidChange();
2127
2128     // FIXME: It probably makes more sense to send individual preference changes.
2129     // However, WebKitTestRunner depends on getting a preference change notification
2130     // even if nothing changed in UI process, so that overrides get removed.
2131
2132     // Preferences need to be updated during synchronous printing to make "print backgrounds" preference work when toggled from a print dialog checkbox.
2133     m_process->send(Messages::WebPage::PreferencesDidChange(m_preferences->store()), m_pageID, m_isPerformingDOMPrintOperation ? IPC::DispatchMessageEvenWhenWaitingForSyncReply : 0);
2134 }
2135
2136 void WebPageProxy::didCreateMainFrame(uint64_t frameID)
2137 {
2138     MESSAGE_CHECK(!m_mainFrame);
2139     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
2140
2141     m_mainFrame = WebFrameProxy::create(this, frameID);
2142
2143     // Add the frame to the process wide map.
2144     m_process->frameCreated(frameID, m_mainFrame.get());
2145 }
2146
2147 void WebPageProxy::didCreateSubframe(uint64_t frameID)
2148 {
2149     MESSAGE_CHECK(m_mainFrame);
2150     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
2151     
2152     RefPtr<WebFrameProxy> subFrame = WebFrameProxy::create(this, frameID);
2153
2154     // Add the frame to the process wide map.
2155     m_process->frameCreated(frameID, subFrame.get());
2156 }
2157
2158 double WebPageProxy::estimatedProgress() const
2159 {
2160     return m_pageLoadState.estimatedProgress();
2161 }
2162
2163 void WebPageProxy::didStartProgress()
2164 {
2165     auto transaction = m_pageLoadState.transaction();
2166     m_pageLoadState.didStartProgress(transaction);
2167
2168     m_pageLoadState.commitChanges();
2169     m_loaderClient->didStartProgress(this);
2170 }
2171
2172 void WebPageProxy::didChangeProgress(double value)
2173 {
2174     auto transaction = m_pageLoadState.transaction();
2175     m_pageLoadState.didChangeProgress(transaction, value);
2176
2177     m_pageLoadState.commitChanges();
2178     m_loaderClient->didChangeProgress(this);
2179 }
2180
2181 void WebPageProxy::didFinishProgress()
2182 {
2183     auto transaction = m_pageLoadState.transaction();
2184     m_pageLoadState.didFinishProgress(transaction);
2185
2186     m_pageLoadState.commitChanges();
2187     m_loaderClient->didFinishProgress(this);
2188 }
2189
2190 void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& url, const String& unreachableURL, IPC::MessageDecoder& decoder)
2191 {
2192     auto transaction = m_pageLoadState.transaction();
2193
2194     m_pageLoadState.clearPendingAPIRequestURL(transaction);
2195
2196     RefPtr<API::Object> userData;
2197     WebContextUserMessageDecoder messageDecoder(userData, process());
2198     if (!decoder.decode(messageDecoder))
2199         return;
2200
2201     WebFrameProxy* frame = m_process->webFrame(frameID);
2202     MESSAGE_CHECK(frame);
2203     MESSAGE_CHECK_URL(url);
2204
2205     if (frame->isMainFrame()) {
2206         recordNavigationSnapshot();
2207         m_pageLoadState.didStartProvisionalLoad(transaction, url, unreachableURL);
2208     }
2209
2210     frame->setUnreachableURL(unreachableURL);
2211     frame->didStartProvisionalLoad(url);
2212
2213     m_pageLoadState.commitChanges();
2214     m_loaderClient->didStartProvisionalLoadForFrame(this, frame, navigationID, userData.get());
2215 }
2216
2217 void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& url, IPC::MessageDecoder& decoder)
2218 {
2219     RefPtr<API::Object> userData;
2220     WebContextUserMessageDecoder messageDecoder(userData, process());
2221     if (!decoder.decode(messageDecoder))
2222         return;
2223
2224     WebFrameProxy* frame = m_process->webFrame(frameID);
2225     MESSAGE_CHECK(frame);
2226     MESSAGE_CHECK_URL(url);
2227
2228     auto transaction = m_pageLoadState.transaction();
2229
2230     if (frame->isMainFrame())
2231         m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, url);
2232
2233     frame->didReceiveServerRedirectForProvisionalLoad(url);
2234
2235     m_pageLoadState.commitChanges();
2236     m_loaderClient->didReceiveServerRedirectForProvisionalLoadForFrame(this, frame, navigationID, userData.get());
2237 }
2238
2239 void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, const ResourceError& error, IPC::MessageDecoder& decoder)
2240 {
2241     RefPtr<API::Object> userData;
2242     WebContextUserMessageDecoder messageDecoder(userData, process());
2243     if (!decoder.decode(messageDecoder))
2244         return;
2245
2246     WebFrameProxy* frame = m_process->webFrame(frameID);
2247     MESSAGE_CHECK(frame);
2248
2249     auto transaction = m_pageLoadState.transaction();
2250
2251     if (frame->isMainFrame())
2252         m_pageLoadState.didFailProvisionalLoad(transaction);
2253
2254     frame->didFailProvisionalLoad();
2255
2256     m_pageLoadState.commitChanges();
2257     m_loaderClient->didFailProvisionalLoadWithErrorForFrame(this, frame, navigationID, error, userData.get());
2258 }
2259
2260 void WebPageProxy::clearLoadDependentCallbacks()
2261 {
2262     Vector<uint64_t> callbackIDsCopy;
2263     copyToVector(m_loadDependentStringCallbackIDs, callbackIDsCopy);
2264     m_loadDependentStringCallbackIDs.clear();
2265
2266     for (size_t i = 0; i < callbackIDsCopy.size(); ++i) {
2267         RefPtr<StringCallback> callback = m_stringCallbacks.take(callbackIDsCopy[i]);
2268         if (callback)
2269             callback->invalidate();
2270     }
2271 }
2272
2273 void WebPageProxy::didCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t opaqueFrameLoadType, const WebCore::CertificateInfo& certificateInfo, IPC::MessageDecoder& decoder)
2274 {
2275     RefPtr<API::Object> userData;
2276     WebContextUserMessageDecoder messageDecoder(userData, process());
2277     if (!decoder.decode(messageDecoder))
2278         return;
2279
2280     WebFrameProxy* frame = m_process->webFrame(frameID);
2281     MESSAGE_CHECK(frame);
2282
2283     auto transaction = m_pageLoadState.transaction();
2284
2285     if (frame->isMainFrame())
2286         m_pageLoadState.didCommitLoad(transaction);
2287
2288 #if USE(APPKIT)
2289     // FIXME (bug 59111): didCommitLoadForFrame comes too late when restoring a page from b/f cache, making us disable secure event mode in password fields.
2290     // FIXME: A load going on in one frame shouldn't affect text editing in other frames on the page.
2291     m_pageClient.resetSecureInputState();
2292     dismissCorrectionPanel(ReasonForDismissingAlternativeTextIgnored);
2293     m_pageClient.dismissDictionaryLookupPanel();
2294 #endif
2295
2296     clearLoadDependentCallbacks();
2297
2298     frame->didCommitLoad(mimeType, certificateInfo);
2299
2300     if (frame->isMainFrame()) {
2301         m_mainFrameHasCustomContentProvider = frameHasCustomContentProvider;
2302
2303         if (m_mainFrameHasCustomContentProvider) {
2304             // Always assume that the main frame is pinned here, since the custom representation view will handle
2305             // any wheel events and dispatch them to the WKView when necessary.
2306             m_mainFrameIsPinnedToLeftSide = true;
2307             m_mainFrameIsPinnedToRightSide = true;
2308             m_mainFrameIsPinnedToTopSide = true;
2309             m_mainFrameIsPinnedToBottomSide = true;
2310         }
2311         m_pageClient.didCommitLoadForMainFrame(mimeType, frameHasCustomContentProvider);
2312     }
2313
2314     // Even if WebPage has the default pageScaleFactor (and therefore doesn't reset it),
2315     // WebPageProxy's cache of the value can get out of sync (e.g. in the case where a
2316     // plugin is handling page scaling itself) so we should reset it to the default
2317     // for standard main frame loads.
2318     if (frame->isMainFrame() && static_cast<FrameLoadType>(opaqueFrameLoadType) == FrameLoadTypeStandard)
2319         m_pageScaleFactor = 1;
2320
2321     m_pageLoadState.commitChanges();
2322     m_loaderClient->didCommitLoadForFrame(this, frame, navigationID, userData.get());
2323 }
2324
2325 void WebPageProxy::didFinishDocumentLoadForFrame(uint64_t frameID, IPC::MessageDecoder& decoder)
2326 {
2327     RefPtr<API::Object> userData;
2328     WebContextUserMessageDecoder messageDecoder(userData, process());
2329     if (!decoder.decode(messageDecoder))
2330         return;
2331
2332     WebFrameProxy* frame = m_process->webFrame(frameID);
2333     MESSAGE_CHECK(frame);
2334
2335     m_loaderClient->didFinishDocumentLoadForFrame(this, frame, userData.get());
2336 }
2337
2338 void WebPageProxy::didFinishLoadForFrame(uint64_t frameID, uint64_t navigationID, IPC::MessageDecoder& decoder)
2339 {
2340     RefPtr<API::Object> userData;
2341     WebContextUserMessageDecoder messageDecoder(userData, process());
2342     if (!decoder.decode(messageDecoder))
2343         return;
2344
2345     WebFrameProxy* frame = m_process->webFrame(frameID);
2346     MESSAGE_CHECK(frame);
2347
2348     auto transaction = m_pageLoadState.transaction();
2349
2350     if (frame->isMainFrame())
2351         m_pageLoadState.didFinishLoad(transaction);
2352
2353     frame->didFinishLoad();
2354
2355     m_pageLoadState.commitChanges();
2356     m_loaderClient->didFinishLoadForFrame(this, frame, navigationID, userData.get());
2357 }
2358
2359 void WebPageProxy::didFailLoadForFrame(uint64_t frameID, uint64_t navigationID, const ResourceError& error, IPC::MessageDecoder& decoder)
2360 {
2361     RefPtr<API::Object> userData;
2362     WebContextUserMessageDecoder messageDecoder(userData, process());
2363     if (!decoder.decode(messageDecoder))
2364         return;
2365
2366     WebFrameProxy* frame = m_process->webFrame(frameID);
2367     MESSAGE_CHECK(frame);
2368
2369     clearLoadDependentCallbacks();
2370
2371     auto transaction = m_pageLoadState.transaction();
2372
2373     if (frame->isMainFrame())
2374         m_pageLoadState.didFailLoad(transaction);
2375
2376     frame->didFailLoad();
2377
2378     m_pageLoadState.commitChanges();
2379     m_loaderClient->didFailLoadWithErrorForFrame(this, frame, navigationID, error, userData.get());
2380 }
2381
2382 void WebPageProxy::didSameDocumentNavigationForFrame(uint64_t frameID, uint32_t opaqueSameDocumentNavigationType, const String& url, IPC::MessageDecoder& decoder)
2383 {
2384     RefPtr<API::Object> userData;
2385     WebContextUserMessageDecoder messageDecoder(userData, process());
2386     if (!decoder.decode(messageDecoder))
2387         return;
2388
2389     WebFrameProxy* frame = m_process->webFrame(frameID);
2390     MESSAGE_CHECK(frame);
2391     MESSAGE_CHECK_URL(url);
2392
2393     auto transaction = m_pageLoadState.transaction();
2394
2395     if (frame->isMainFrame())
2396         m_pageLoadState.didSameDocumentNavigation(transaction, url);
2397
2398     m_pageLoadState.clearPendingAPIRequestURL(transaction);
2399     frame->didSameDocumentNavigation(url);
2400
2401     m_pageLoadState.commitChanges();
2402     m_loaderClient->didSameDocumentNavigationForFrame(this, frame, static_cast<SameDocumentNavigationType>(opaqueSameDocumentNavigationType), userData.get());
2403 }
2404
2405 void WebPageProxy::didReceiveTitleForFrame(uint64_t frameID, const String& title, IPC::MessageDecoder& decoder)
2406 {
2407     RefPtr<API::Object> userData;
2408     WebContextUserMessageDecoder messageDecoder(userData, process());
2409     if (!decoder.decode(messageDecoder))
2410         return;
2411
2412     WebFrameProxy* frame = m_process->webFrame(frameID);
2413     MESSAGE_CHECK(frame);
2414
2415     auto transaction = m_pageLoadState.transaction();
2416
2417     if (frame->isMainFrame())
2418         m_pageLoadState.setTitle(transaction, title);
2419
2420     frame->didChangeTitle(title);
2421     
2422     m_pageLoadState.commitChanges();
2423     m_loaderClient->didReceiveTitleForFrame(this, title, frame, userData.get());
2424 }
2425
2426 void WebPageProxy::didFirstLayoutForFrame(uint64_t frameID, IPC::MessageDecoder& decoder)
2427 {
2428     RefPtr<API::Object> userData;
2429     WebContextUserMessageDecoder messageDecoder(userData, process());
2430     if (!decoder.decode(messageDecoder))
2431         return;
2432
2433     WebFrameProxy* frame = m_process->webFrame(frameID);
2434     MESSAGE_CHECK(frame);
2435
2436     m_loaderClient->didFirstLayoutForFrame(this, frame, userData.get());
2437 }
2438
2439 void WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame(uint64_t frameID, IPC::MessageDecoder& decoder)
2440 {
2441     RefPtr<API::Object> userData;
2442     WebContextUserMessageDecoder messageDecoder(userData, process());
2443     if (!decoder.decode(messageDecoder))
2444         return;
2445
2446     WebFrameProxy* frame = m_process->webFrame(frameID);
2447     MESSAGE_CHECK(frame);
2448
2449     m_loaderClient->didFirstVisuallyNonEmptyLayoutForFrame(this, frame, userData.get());
2450 }
2451
2452 void WebPageProxy::didLayout(uint32_t layoutMilestones, IPC::MessageDecoder& decoder)
2453 {
2454     RefPtr<API::Object> userData;
2455     WebContextUserMessageDecoder messageDecoder(userData, process());
2456     if (!decoder.decode(messageDecoder))
2457         return;
2458
2459     m_loaderClient->didLayout(this, static_cast<LayoutMilestones>(layoutMilestones), userData.get());
2460 }
2461
2462 void WebPageProxy::didRemoveFrameFromHierarchy(uint64_t frameID, IPC::MessageDecoder& decoder)
2463 {
2464     RefPtr<API::Object> userData;
2465     WebContextUserMessageDecoder messageDecoder(userData, process());
2466     if (!decoder.decode(messageDecoder))
2467         return;
2468
2469     WebFrameProxy* frame = m_process->webFrame(frameID);
2470     MESSAGE_CHECK(frame);
2471
2472     m_loaderClient->didRemoveFrameFromHierarchy(this, frame, userData.get());
2473 }
2474
2475 void WebPageProxy::didDisplayInsecureContentForFrame(uint64_t frameID, IPC::MessageDecoder& decoder)
2476 {
2477     RefPtr<API::Object> userData;
2478     WebContextUserMessageDecoder messageDecoder(userData, process());
2479     if (!decoder.decode(messageDecoder))
2480         return;
2481
2482     WebFrameProxy* frame = m_process->webFrame(frameID);
2483     MESSAGE_CHECK(frame);
2484
2485     auto transaction = m_pageLoadState.transaction();
2486     m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
2487
2488     m_pageLoadState.commitChanges();
2489     m_loaderClient->didDisplayInsecureContentForFrame(this, frame, userData.get());
2490 }
2491
2492 void WebPageProxy::didRunInsecureContentForFrame(uint64_t frameID, IPC::MessageDecoder& decoder)
2493 {
2494     RefPtr<API::Object> userData;
2495     WebContextUserMessageDecoder messageDecoder(userData, process());
2496     if (!decoder.decode(messageDecoder))
2497         return;
2498
2499     WebFrameProxy* frame = m_process->webFrame(frameID);
2500     MESSAGE_CHECK(frame);
2501
2502     auto transaction = m_pageLoadState.transaction();
2503     m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
2504
2505     m_pageLoadState.commitChanges();
2506     m_loaderClient->didRunInsecureContentForFrame(this, frame, userData.get());
2507 }
2508
2509 void WebPageProxy::didDetectXSSForFrame(uint64_t frameID, IPC::MessageDecoder& decoder)
2510 {
2511     RefPtr<API::Object> userData;
2512     WebContextUserMessageDecoder messageDecoder(userData, process());
2513     if (!decoder.decode(messageDecoder))
2514         return;
2515
2516     WebFrameProxy* frame = m_process->webFrame(frameID);
2517     MESSAGE_CHECK(frame);
2518
2519     m_loaderClient->didDetectXSSForFrame(this, frame, userData.get());
2520 }
2521
2522 void WebPageProxy::frameDidBecomeFrameSet(uint64_t frameID, bool value)
2523 {
2524     WebFrameProxy* frame = m_process->webFrame(frameID);
2525     MESSAGE_CHECK(frame);
2526
2527     frame->setIsFrameSet(value);
2528     if (frame->isMainFrame())
2529         m_frameSetLargestFrame = value ? m_mainFrame : 0;
2530 }
2531
2532 void WebPageProxy::decidePolicyForNavigationAction(uint64_t frameID, const NavigationActionData& navigationActionData, uint64_t originatingFrameID, const WebCore::ResourceRequest& originalRequest, const ResourceRequest& request, uint64_t listenerID, IPC::MessageDecoder& decoder, bool& receivedPolicyAction, uint64_t& policyAction, uint64_t& downloadID)
2533 {
2534     RefPtr<API::Object> userData;
2535     WebContextUserMessageDecoder messageDecoder(userData, process());
2536     if (!decoder.decode(messageDecoder))
2537         return;
2538
2539     auto transaction = m_pageLoadState.transaction();
2540
2541     if (request.url() != m_pageLoadState.pendingAPIRequestURL())
2542         m_pageLoadState.clearPendingAPIRequestURL(transaction);
2543
2544     WebFrameProxy* frame = m_process->webFrame(frameID);
2545     MESSAGE_CHECK(frame);
2546     MESSAGE_CHECK_URL(request.url());
2547     MESSAGE_CHECK_URL(originalRequest.url());
2548
2549     WebFrameProxy* originatingFrame = m_process->webFrame(originatingFrameID);
2550     
2551     RefPtr<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
2552
2553     ASSERT(!m_inDecidePolicyForNavigationAction);
2554
2555     m_inDecidePolicyForNavigationAction = true;
2556     m_syncNavigationActionPolicyActionIsValid = false;
2557
2558     m_policyClient->decidePolicyForNavigationAction(this, frame, navigationActionData, originatingFrame, originalRequest, request, std::move(listener), userData.get());
2559
2560     m_inDecidePolicyForNavigationAction = false;
2561
2562     // Check if we received a policy decision already. If we did, we can just pass it back.
2563     receivedPolicyAction = m_syncNavigationActionPolicyActionIsValid;
2564     if (m_syncNavigationActionPolicyActionIsValid) {
2565         policyAction = m_syncNavigationActionPolicyAction;
2566         downloadID = m_syncNavigationActionPolicyDownloadID;
2567     }
2568 }
2569
2570 void WebPageProxy::decidePolicyForNewWindowAction(uint64_t frameID, const NavigationActionData& navigationActionData, const ResourceRequest& request, const String& frameName, uint64_t listenerID, IPC::MessageDecoder& decoder)
2571 {
2572     RefPtr<API::Object> userData;
2573     WebContextUserMessageDecoder messageDecoder(userData, process());
2574     if (!decoder.decode(messageDecoder))
2575         return;
2576
2577     WebFrameProxy* frame = m_process->webFrame(frameID);
2578     MESSAGE_CHECK(frame);
2579     MESSAGE_CHECK_URL(request.url());
2580
2581     RefPtr<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
2582
2583     m_policyClient->decidePolicyForNewWindowAction(this, frame, navigationActionData, request, frameName, std::move(listener), userData.get());
2584 }
2585
2586 void WebPageProxy::decidePolicyForResponse(uint64_t frameID, const ResourceResponse& response, const ResourceRequest& request, bool canShowMIMEType, uint64_t listenerID, IPC::MessageDecoder& decoder)
2587 {
2588     RefPtr<API::Object> userData;
2589     WebContextUserMessageDecoder messageDecoder(userData, process());
2590     if (!decoder.decode(messageDecoder))
2591         return;
2592
2593     WebFrameProxy* frame = m_process->webFrame(frameID);
2594     MESSAGE_CHECK(frame);
2595     MESSAGE_CHECK_URL(request.url());
2596     MESSAGE_CHECK_URL(response.url());
2597
2598     RefPtr<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
2599
2600     m_policyClient->decidePolicyForResponse(this, frame, response, request, canShowMIMEType, std::move(listener), userData.get());
2601 }
2602
2603 void WebPageProxy::decidePolicyForResponseSync(uint64_t frameID, const ResourceResponse& response, const ResourceRequest& request, bool canShowMIMEType, uint64_t listenerID, IPC::MessageDecoder& decoder, bool& receivedPolicyAction, uint64_t& policyAction, uint64_t& downloadID)
2604 {
2605     ASSERT(!m_inDecidePolicyForResponseSync);
2606
2607     m_inDecidePolicyForResponseSync = true;
2608     m_decidePolicyForResponseRequest = &request;
2609     m_syncMimeTypePolicyActionIsValid = false;
2610
2611     decidePolicyForResponse(frameID, response, request, canShowMIMEType, listenerID, decoder);
2612
2613     m_inDecidePolicyForResponseSync = false;
2614     m_decidePolicyForResponseRequest = 0;
2615
2616     // Check if we received a policy decision already. If we did, we can just pass it back.
2617     receivedPolicyAction = m_syncMimeTypePolicyActionIsValid;
2618     if (m_syncMimeTypePolicyActionIsValid) {
2619         policyAction = m_syncMimeTypePolicyAction;
2620         downloadID = m_syncMimeTypePolicyDownloadID;
2621     }
2622 }
2623
2624 void WebPageProxy::unableToImplementPolicy(uint64_t frameID, const ResourceError& error, IPC::MessageDecoder& decoder)
2625 {
2626     RefPtr<API::Object> userData;
2627     WebContextUserMessageDecoder messageDecoder(userData, process());
2628     if (!decoder.decode(messageDecoder))
2629         return;
2630     
2631     WebFrameProxy* frame = m_process->webFrame(frameID);
2632     MESSAGE_CHECK(frame);
2633
2634     m_policyClient->unableToImplementPolicy(this, frame, error, userData.get());
2635 }
2636
2637 // FormClient
2638
2639 void WebPageProxy::willSubmitForm(uint64_t frameID, uint64_t sourceFrameID, const Vector<std::pair<String, String>>& textFieldValues, uint64_t listenerID, IPC::MessageDecoder& decoder)
2640 {
2641     RefPtr<API::Object> userData;
2642     WebContextUserMessageDecoder messageDecoder(userData, process());
2643     if (!decoder.decode(messageDecoder))
2644         return;
2645
2646     WebFrameProxy* frame = m_process->webFrame(frameID);
2647     MESSAGE_CHECK(frame);
2648
2649     WebFrameProxy* sourceFrame = m_process->webFrame(sourceFrameID);
2650     MESSAGE_CHECK(sourceFrame);
2651
2652     RefPtr<WebFormSubmissionListenerProxy> listener = frame->setUpFormSubmissionListenerProxy(listenerID);
2653     if (!m_formClient.willSubmitForm(this, frame, sourceFrame, textFieldValues, userData.get(), listener.get()))
2654         listener->continueSubmission();
2655 }
2656
2657 // UIClient
2658
2659 void WebPageProxy::createNewPage(const ResourceRequest& request, const WindowFeatures& windowFeatures, uint32_t opaqueModifiers, int32_t opaqueMouseButton, uint64_t& newPageID, WebPageCreationParameters& newPageParameters)
2660 {
2661     RefPtr<WebPageProxy> newPage = m_uiClient->createNewPage(this, request, windowFeatures, static_cast<WebEvent::Modifiers>(opaqueModifiers), static_cast<WebMouseEvent::Button>(opaqueMouseButton));
2662     if (!newPage) {
2663         newPageID = 0;
2664         return;
2665     }
2666
2667     newPageID = newPage->pageID();
2668     newPageParameters = newPage->creationParameters();
2669     process().context().storageManager().cloneSessionStorageNamespace(m_pageID, newPage->pageID());
2670 }
2671     
2672 void WebPageProxy::showPage()
2673 {
2674     m_uiClient->showPage(this);
2675 }
2676
2677 void WebPageProxy::closePage(bool stopResponsivenessTimer)
2678 {
2679     if (stopResponsivenessTimer)
2680         m_process->responsivenessTimer()->stop();
2681
2682     m_pageClient.clearAllEditCommands();
2683     m_uiClient->close(this);
2684 }
2685
2686 void WebPageProxy::runJavaScriptAlert(uint64_t frameID, const String& message, RefPtr<Messages::WebPageProxy::RunJavaScriptAlert::DelayedReply> reply)
2687 {
2688     WebFrameProxy* frame = m_process->webFrame(frameID);
2689     MESSAGE_CHECK(frame);
2690
2691     // Since runJavaScriptAlert() can spin a nested run loop we need to turn off the responsiveness timer.
2692     m_process->responsivenessTimer()->stop();
2693
2694     m_uiClient->runJavaScriptAlert(this, message, frame, [reply]{ reply->send(); });
2695 }
2696
2697 void WebPageProxy::runJavaScriptConfirm(uint64_t frameID, const String& message, RefPtr<Messages::WebPageProxy::RunJavaScriptConfirm::DelayedReply> reply)
2698 {
2699     WebFrameProxy* frame = m_process->webFrame(frameID);
2700     MESSAGE_CHECK(frame);
2701
2702     // Since runJavaScriptConfirm() can spin a nested run loop we need to turn off the responsiveness timer.
2703     m_process->responsivenessTimer()->stop();
2704
2705     m_uiClient->runJavaScriptConfirm(this, message, frame, [reply](bool result) { reply->send(result); });
2706 }
2707
2708 void WebPageProxy::runJavaScriptPrompt(uint64_t frameID, const String& message, const String& defaultValue, RefPtr<Messages::WebPageProxy::RunJavaScriptPrompt::DelayedReply> reply)
2709 {
2710     WebFrameProxy* frame = m_process->webFrame(frameID);
2711     MESSAGE_CHECK(frame);
2712
2713     // Since runJavaScriptPrompt() can spin a nested run loop we need to turn off the responsiveness timer.
2714     m_process->responsivenessTimer()->stop();
2715
2716     m_uiClient->runJavaScriptPrompt(this, message, defaultValue, frame, [reply](const String& result) { reply->send(result); });
2717 }
2718
2719 void WebPageProxy::shouldInterruptJavaScript(bool& result)
2720 {
2721     // Since shouldInterruptJavaScript() can spin a nested run loop we need to turn off the responsiveness timer.
2722     m_process->responsivenessTimer()->stop();
2723
2724     result = m_uiClient->shouldInterruptJavaScript(this);
2725 }
2726
2727 void WebPageProxy::setStatusText(const String& text)
2728 {
2729     m_uiClient->setStatusText(this, text);
2730 }
2731
2732 void WebPageProxy::mouseDidMoveOverElement(const WebHitTestResult::Data& hitTestResultData, uint32_t opaqueModifiers, IPC::MessageDecoder& decoder)
2733 {
2734     RefPtr<API::Object> userData;
2735     WebContextUserMessageDecoder messageDecoder(userData, process());
2736     if (!decoder.decode(messageDecoder))
2737         return;
2738
2739     WebEvent::Modifiers modifiers = static_cast<WebEvent::Modifiers>(opaqueModifiers);
2740
2741     m_uiClient->mouseDidMoveOverElement(this, hitTestResultData, modifiers, userData.get());
2742 }
2743
2744 void WebPageProxy::connectionWillOpen(IPC::Connection* connection)
2745 {
2746     ASSERT(connection == m_process->connection());
2747
2748     m_visitedLinkProvider->addProcess(m_process.get());
2749
2750     m_process->context().storageManager().setAllowedSessionStorageNamespaceConnection(m_pageID, connection);
2751 }
2752
2753 void WebPageProxy::connectionWillClose(IPC::Connection* connection)
2754 {
2755     ASSERT_UNUSED(connection, connection == m_process->connection());
2756
2757     m_process->context().storageManager().setAllowedSessionStorageNamespaceConnection(m_pageID, 0);
2758 }
2759
2760 #if ENABLE(NETSCAPE_PLUGIN_API)
2761 void WebPageProxy::unavailablePluginButtonClicked(uint32_t opaquePluginUnavailabilityReason, const String& mimeType, const String& pluginURLString, const String& pluginspageAttributeURLString, const String& frameURLString, const String& pageURLString)
2762 {
2763     MESSAGE_CHECK_URL(pluginURLString);
2764     MESSAGE_CHECK_URL(pluginspageAttributeURLString);
2765     MESSAGE_CHECK_URL(frameURLString);
2766     MESSAGE_CHECK_URL(pageURLString);
2767
2768     RefPtr<ImmutableDictionary> pluginInformation;
2769     String newMimeType = mimeType;
2770     PluginModuleInfo plugin = m_process->context().pluginInfoStore().findPlugin(newMimeType, URL(URL(), pluginURLString));
2771     pluginInformation = createPluginInformationDictionary(plugin, frameURLString, mimeType, pageURLString, pluginspageAttributeURLString, pluginURLString);
2772
2773     WKPluginUnavailabilityReason pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginMissing;
2774     switch (static_cast<RenderEmbeddedObject::PluginUnavailabilityReason>(opaquePluginUnavailabilityReason)) {
2775     case RenderEmbeddedObject::PluginMissing:
2776         pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginMissing;
2777         break;
2778     case RenderEmbeddedObject::InsecurePluginVersion:
2779         pluginUnavailabilityReason = kWKPluginUnavailabilityReasonInsecurePluginVersion;
2780         break;
2781     case RenderEmbeddedObject::PluginCrashed:
2782         pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginCrashed;
2783         break;
2784     case RenderEmbeddedObject::PluginBlockedByContentSecurityPolicy:
2785         ASSERT_NOT_REACHED();
2786     }
2787
2788     m_uiClient->unavailablePluginButtonClicked(this, pluginUnavailabilityReason, pluginInformation.get());
2789 }
2790 #endif // ENABLE(NETSCAPE_PLUGIN_API)
2791
2792 #if ENABLE(WEBGL)
2793 void WebPageProxy::webGLPolicyForURL(const String& url, uint32_t& loadPolicy)
2794 {
2795     loadPolicy = static_cast<uint32_t>(m_loaderClient->webGLLoadPolicy(this, url));
2796 }
2797
2798 void WebPageProxy::resolveWebGLPolicyForURL(const String& url, uint32_t& loadPolicy)
2799 {
2800     loadPolicy = static_cast<uint32_t>(m_loaderClient->resolveWebGLLoadPolicy(this, url));
2801 }
2802 #endif // ENABLE(WEBGL)
2803
2804 void WebPageProxy::setToolbarsAreVisible(bool toolbarsAreVisible)
2805 {
2806     m_uiClient->setToolbarsAreVisible(this, toolbarsAreVisible);
2807 }
2808
2809 void WebPageProxy::getToolbarsAreVisible(bool& toolbarsAreVisible)
2810 {
2811     toolbarsAreVisible = m_uiClient->toolbarsAreVisible(this);
2812 }
2813
2814 void WebPageProxy::setMenuBarIsVisible(bool menuBarIsVisible)
2815 {
2816     m_uiClient->setMenuBarIsVisible(this, menuBarIsVisible);
2817 }
2818
2819 void WebPageProxy::getMenuBarIsVisible(bool& menuBarIsVisible)
2820 {
2821     menuBarIsVisible = m_uiClient->menuBarIsVisible(this);
2822 }
2823
2824 void WebPageProxy::setStatusBarIsVisible(bool statusBarIsVisible)
2825 {
2826     m_uiClient->setStatusBarIsVisible(this, statusBarIsVisible);
2827 }
2828
2829 void WebPageProxy::getStatusBarIsVisible(bool& statusBarIsVisible)
2830 {
2831     statusBarIsVisible = m_uiClient->statusBarIsVisible(this);
2832 }
2833
2834 void WebPageProxy::setIsResizable(bool isResizable)
2835 {
2836     m_uiClient->setIsResizable(this, isResizable);
2837 }
2838
2839 void WebPageProxy::getIsResizable(bool& isResizable)
2840 {
2841     isResizable = m_uiClient->isResizable(this);
2842 }
2843
2844 void WebPageProxy::setWindowFrame(const FloatRect& newWindowFrame)
2845 {
2846     m_uiClient->setWindowFrame(this, m_pageClient.convertToDeviceSpace(newWindowFrame));
2847 }
2848
2849 void WebPageProxy::getWindowFrame(FloatRect& newWindowFrame)
2850 {
2851     newWindowFrame = m_pageClient.convertToUserSpace(m_uiClient->windowFrame(this));
2852 }
2853     
2854 void WebPageProxy::screenToRootView(const IntPoint& screenPoint, IntPoint& windowPoint)
2855 {
2856     windowPoint = m_pageClient.screenToRootView(screenPoint);
2857 }
2858     
2859 void WebPageProxy::rootViewToScreen(const IntRect& viewRect, IntRect& result)
2860 {
2861     result = m_pageClient.rootViewToScreen(viewRect);
2862 }
2863     
2864 void WebPageProxy::runBeforeUnloadConfirmPanel(const String& message, uint64_t frameID, bool& shouldClose)
2865 {
2866     WebFrameProxy* frame = m_process->webFrame(frameID);
2867     MESSAGE_CHECK(frame);
2868
2869     // Since runBeforeUnloadConfirmPanel() can spin a nested run loop we need to turn off the responsiveness timer.
2870     m_process->responsivenessTimer()->stop();
2871
2872     shouldClose = m_uiClient->runBeforeUnloadConfirmPanel(this, message, frame);
2873 }
2874
2875 #if USE(TILED_BACKING_STORE)
2876 void WebPageProxy::pageDidRequestScroll(const IntPoint& point)
2877 {
2878     m_pageClient.pageDidRequestScroll(point);
2879 }
2880
2881 void WebPageProxy::pageTransitionViewportReady()
2882 {
2883     m_pageClient.pageTransitionViewportReady();
2884 }
2885
2886 void WebPageProxy::didRenderFrame(const WebCore::IntSize& contentsSize, const WebCore::IntRect& coveredRect)
2887 {
2888     m_pageClient.didRenderFrame(contentsSize, coveredRect);
2889 }
2890
2891 #endif
2892
2893 void WebPageProxy::didChangeViewportProperties(const ViewportAttributes& attr)
2894 {
2895     m_pageClient.didChangeViewportProperties(attr);
2896 }
2897
2898 void WebPageProxy::pageDidScroll()
2899 {
2900     m_uiClient->pageDidScroll(this);
2901 #if PLATFORM(MAC)
2902     dismissCorrectionPanel(ReasonForDismissingAlternativeTextIgnored);
2903 #endif
2904 }
2905
2906 void WebPageProxy::runOpenPanel(uint64_t frameID, const FileChooserSettings& settings)
2907 {
2908     if (m_openPanelResultListener) {
2909         m_openPanelResultListener->invalidate();
2910         m_openPanelResultListener = 0;
2911     }
2912
2913     WebFrameProxy* frame = m_process->webFrame(frameID);
2914     MESSAGE_CHECK(frame);
2915
2916     RefPtr<WebOpenPanelParameters> parameters = WebOpenPanelParameters::create(settings);
2917     m_openPanelResultListener = WebOpenPanelResultListenerProxy::create(this);
2918
2919     // Since runOpenPanel() can spin a nested run loop we need to turn off the responsiveness timer.
2920     m_process->responsivenessTimer()->stop();
2921
2922     if (!m_uiClient->runOpenPanel(this, frame, parameters.get(), m_openPanelResultListener.get()))
2923         didCancelForOpenPanel();
2924 }
2925
2926 void WebPageProxy::printFrame(uint64_t frameID)
2927 {
2928     ASSERT(!m_isPerformingDOMPrintOperation);
2929     m_isPerformingDOMPrintOperation = true;
2930
2931     WebFrameProxy* frame = m_process->webFrame(frameID);
2932     MESSAGE_CHECK(frame);
2933
2934     m_uiClient->printFrame(this, frame);
2935
2936     endPrinting(); // Send a message synchronously while m_isPerformingDOMPrintOperation is still true.
2937     m_isPerformingDOMPrintOperation = false;
2938 }
2939
2940 void WebPageProxy::printMainFrame()
2941 {
2942     printFrame(m_mainFrame->frameID());
2943 }
2944
2945 void WebPageProxy::setMediaVolume(float volume)
2946 {
2947     if (volume == m_mediaVolume)
2948         return;
2949     
2950     m_mediaVolume = volume;
2951     
2952     if (!isValid())
2953         return;
2954     
2955     m_process->send(Messages::WebPage::SetMediaVolume(volume), m_pageID);    
2956 }
2957
2958 void WebPageProxy::setMayStartMediaWhenInWindow(bool mayStartMedia)
2959 {
2960     if (mayStartMedia == m_mayStartMediaWhenInWindow)
2961         return;
2962
2963     m_mayStartMediaWhenInWindow = mayStartMedia;
2964
2965     if (!isValid())
2966         return;
2967
2968     process().send(Messages::WebPage::SetMayStartMediaWhenInWindow(mayStartMedia), m_pageID);
2969 }
2970
2971 #if PLATFORM(EFL) || PLATFORM(GTK)
2972 void WebPageProxy::handleDownloadRequest(DownloadProxy* download)
2973 {
2974     m_pageClient.handleDownloadRequest(download);
2975 }
2976 #endif // PLATFORM(EFL) || PLATFORM(GTK)
2977
2978 #if PLATFORM(EFL)
2979 void WebPageProxy::didChangeContentSize(const IntSize& size)
2980 {
2981     m_pageClient.didChangeContentSize(size);
2982 }
2983 #endif
2984
2985 #if ENABLE(INPUT_TYPE_COLOR)
2986 void WebPageProxy::showColorPicker(const WebCore::Color& initialColor, const IntRect& elementRect)
2987 {
2988 #if ENABLE(INPUT_TYPE_COLOR_POPOVER)
2989     // A new popover color well needs to be created (and the previous one destroyed) for
2990     // each activation of a color element.
2991     m_colorPicker = 0;
2992 #endif
2993     if (!m_colorPicker)
2994         m_colorPicker = m_pageClient.createColorPicker(this, initialColor, elementRect);
2995     m_colorPicker->showColorPicker(initialColor);
2996 }
2997
2998 void WebPageProxy::setColorPickerColor(const WebCore::Color& color)
2999 {
3000     ASSERT(m_colorPicker);
3001
3002     m_colorPicker->setSelectedColor(color);
3003 }
3004
3005 void WebPageProxy::endColorPicker()
3006 {
3007     ASSERT(m_colorPicker);
3008
3009     m_colorPicker->endPicker();
3010 }
3011
3012 void WebPageProxy::didChooseColor(const WebCore::Color& color)
3013 {
3014     if (!isValid())
3015         return;
3016
3017     m_process->send(Messages::WebPage::DidChooseColor(color), m_pageID);
3018 }
3019
3020 void WebPageProxy::didEndColorPicker()
3021 {
3022     if (!isValid())
3023         return;
3024
3025     if (m_colorPicker) {
3026         m_colorPicker->invalidate();
3027         m_colorPicker = nullptr;
3028     }
3029
3030     m_process->send(Messages::WebPage::DidEndColorPicker(), m_pageID);
3031 }
3032 #endif
3033
3034 void WebPageProxy::didDraw()
3035 {
3036     m_uiClient->didDraw(this);
3037 }
3038
3039 // Inspector
3040
3041 #if ENABLE(INSPECTOR)
3042
3043 WebInspectorProxy* WebPageProxy::inspector()
3044 {
3045     if (isClosed() || !isValid())
3046         return 0;
3047     return m_inspector.get();
3048 }
3049
3050 #endif
3051
3052 #if ENABLE(FULLSCREEN_API)
3053 WebFullScreenManagerProxy* WebPageProxy::fullScreenManager()
3054 {
3055     return m_fullScreenManager.get();
3056 }
3057 #endif
3058     
3059 #if PLATFORM(IOS)
3060 RefPtr<WebVideoFullscreenManagerProxy> WebPageProxy::videoFullscreenManager()
3061 {
3062     return m_videoFullscreenManager;
3063 }
3064 #endif
3065
3066 // BackForwardList
3067
3068 void WebPageProxy::backForwardAddItem(uint64_t itemID)
3069 {
3070     m_backForwardList->addItem(m_process->webBackForwardItem(itemID));
3071 }
3072
3073 void WebPageProxy::backForwardGoToItem(uint64_t itemID, SandboxExtension::Handle& sandboxExtensionHandle)
3074 {
3075     WebBackForwardListItem* item = m_process->webBackForwardItem(itemID);
3076     if (!item)
3077         return;
3078
3079     bool createdExtension = maybeInitializeSandboxExtensionHandle(URL(URL(), item->url()), sandboxExtensionHandle);
3080     if (createdExtension)
3081         m_process->willAcquireUniversalFileReadSandboxExtension();
3082     m_backForwardList->goToItem(item);
3083 }
3084
3085 void WebPageProxy::backForwardItemAtIndex(int32_t index, uint64_t& itemID)
3086 {
3087     WebBackForwardListItem* item = m_backForwardList->itemAtIndex(index);
3088     itemID = item ? item->itemID() : 0;
3089 }
3090
3091 void WebPageProxy::backForwardBackListCount(int32_t& count)
3092 {
3093     count = m_backForwardList->backListCount();
3094 }
3095
3096 void WebPageProxy::backForwardForwardListCount(int32_t& count)
3097 {
3098     count = m_backForwardList->forwardListCount();
3099 }
3100
3101 void WebPageProxy::editorStateChanged(const EditorState& editorState)
3102 {
3103 #if PLATFORM(COCOA)
3104     bool couldChangeSecureInputState = m_editorState.isInPasswordField != editorState.isInPasswordField || m_editorState.selectionIsNone;
3105     bool closedComposition = !editorState.shouldIgnoreCompositionSelectionChange && !editorState.hasComposition && (m_editorState.hasComposition || m_temporarilyClosedComposition);
3106     m_temporarilyClosedComposition = editorState.shouldIgnoreCompositionSelectionChange && (m_temporarilyClosedComposition || m_editorState.hasComposition) && !editorState.hasComposition;
3107 #endif
3108
3109     m_editorState = editorState;
3110
3111 #if PLATFORM(COCOA)
3112     // Selection being none is a temporary state when editing. Flipping secure input state too quickly was causing trouble (not fully understood).
3113     if (couldChangeSecureInputState && !editorState.selectionIsNone)
3114         m_pageClient.updateSecureInputState();
3115
3116     if (editorState.shouldIgnoreCompositionSelectionChange)
3117         return;
3118
3119     if (closedComposition)
3120         m_pageClient.notifyInputContextAboutDiscardedComposition();
3121     if (editorState.hasComposition) {
3122         // Abandon the current inline input session if selection changed for any other reason but an input method changing the composition.
3123         // FIXME: This logic should be in WebCore, no need to round-trip to UI process to cancel the composition.
3124         cancelComposition();
3125         m_pageClient.notifyInputContextAboutDiscardedComposition();
3126     }
3127 #if PLATFORM(IOS)
3128     else {
3129         // We need to notify the client on iOS to make sure the selection is redrawn.
3130         notifyRevealedSelection();
3131     }
3132 #endif
3133 #elif PLATFORM(EFL) || PLATFORM(GTK)
3134     m_pageClient.updateTextInputState();
3135 #endif
3136 }
3137
3138 // Undo management
3139
3140 void WebPageProxy::registerEditCommandForUndo(uint64_t commandID, uint32_t editAction)
3141 {
3142     registerEditCommand(WebEditCommandProxy::create(commandID, static_cast<EditAction>(editAction), this), Undo);
3143 }
3144
3145 void WebPageProxy::canUndoRedo(uint32_t action, bool& result)
3146 {
3147     result = m_pageClient.canUndoRedo(static_cast<UndoOrRedo>(action));
3148 }
3149
3150 void WebPageProxy::executeUndoRedo(uint32_t action, bool& result)
3151 {
3152     m_pageClient.executeUndoRedo(static_cast<UndoOrRedo>(action));
3153     result = true;
3154 }
3155
3156 void WebPageProxy::clearAllEditCommands()
3157 {
3158     m_pageClient.clearAllEditCommands();
3159 }
3160
3161 void WebPageProxy::didCountStringMatches(const String& string, uint32_t matchCount)
3162 {
3163     m_findClient.didCountStringMatches(this, string, matchCount);
3164 }
3165
3166 void WebPageProxy::didGetImageForFindMatch(const ShareableBitmap::Handle& contentImageHandle, uint32_t matchIndex)
3167 {
3168     m_findMatchesClient.didGetImageForMatchResult(this, WebImage::create(ShareableBitmap::create(contentImageHandle)).get(), matchIndex);
3169 }
3170
3171 void WebPageProxy::setFindIndicator(const FloatRect& selectionRectInWindowCoordinates, const Vector<FloatRect>& textRectsInSelectionRectCoordinates, float contentImageScaleFactor, const ShareableBitmap::Handle& contentImageHandle, bool fadeOut, bool animate)
3172 {
3173     RefPtr<FindIndicator> findIndicator = FindIndicator::create(selectionRectInWindowCoordinates, textRectsInSelectionRectCoordinates, contentImageScaleFactor, contentImageHandle);
3174     m_pageClient.setFindIndicator(findIndicator.release(), fadeOut, animate);
3175 }
3176
3177 void WebPageProxy::didFindString(const String& string, uint32_t matchCount)
3178 {
3179     m_findClient.didFindString(this, string, matchCount);
3180 }
3181
3182 void WebPageProxy::didFindStringMatches(const String& string, Vector<Vector<WebCore::IntRect>> matchRects, int32_t firstIndexAfterSelection)
3183 {
3184     Vector<RefPtr<API::Object>> matches;
3185     matches.reserveInitialCapacity(matchRects.size());
3186
3187     for (const auto& rects : matchRects) {
3188         Vector<RefPtr<API::Object>> apiRects;
3189         apiRects.reserveInitialCapacity(rects.size());
3190
3191         for (const auto& rect : rects)
3192             apiRects.uncheckedAppend(API::Rect::create(toAPI(rect)));
3193
3194         matches.uncheckedAppend(API::Array::create(std::move(apiRects)));
3195     }
3196
3197     m_findMatchesClient.didFindStringMatches(this, string, API::Array::create(std::move(matches)).get(), firstIndexAfterSelection);
3198 }
3199
3200 void WebPageProxy::didFailToFindString(const String& string)
3201 {
3202     m_findClient.didFailToFindString(this, string);
3203 }
3204
3205 bool WebPageProxy::sendMessage(std::unique_ptr<IPC::MessageEncoder> encoder, unsigned messageSendFlags)
3206 {
3207     return m_process->sendMessage(std::move(encoder), messageSendFlags);
3208 }
3209
3210 IPC::Connection* WebPageProxy::messageSenderConnection()
3211 {
3212     return m_process->connection();
3213 }
3214
3215 uint64_t WebPageProxy::messageSenderDestinationID()
3216 {
3217     return m_pageID;
3218 }
3219
3220 void WebPageProxy::valueChangedForPopupMenu(WebPopupMenuProxy*, int32_t newSelectedIndex)
3221 {
3222     m_process->send(Messages::WebPage::DidChangeSelectedIndexForActivePopupMenu(newSelectedIndex), m_pageID);
3223 }
3224
3225 void WebPageProxy::setTextFromItemForPopupMenu(WebPopupMenuProxy*, int32_t index)
3226 {
3227     m_process->send(Messages::WebPage::SetTextForActivePopupMenu(index), m_pageID);
3228 }
3229
3230 NativeWebMouseEvent* WebPageProxy::currentlyProcessedMouseDownEvent()
3231 {
3232     return m_currentlyProcessedMouseDownEvent.get();
3233 }
3234
3235 void WebPageProxy::postMessageToInjectedBundle(const String& messageName, API::Object* messageBody)
3236 {
3237     process().send(Messages::WebPage::PostInjectedBundleMessage(messageName, WebContextUserMessageEncoder(messageBody, process())), m_pageID);
3238 }
3239
3240 #if PLATFORM(GTK)
3241 void WebPageProxy::failedToShowPopupMenu()
3242 {
3243     m_process->send(Messages::WebPage::FailedToShowPopupMenu(), m_pageID);
3244 }
3245 #endif
3246
3247 void WebPageProxy::showPopupMenu(const IntRect& rect, uint64_t textDirection, const Vector<WebPopupItem>& items, int32_t selectedIndex, const PlatformPopupMenuData& data)
3248 {
3249     if (m_activePopupMenu) {
3250 #if PLATFORM(EFL)
3251         m_uiPopupMenuClient.hidePopupMenu(this);
3252 #else
3253         m_activePopupMenu->hidePopupMenu();
3254 #endif
3255         m_activePopupMenu->invalidate();
3256         m_activePopupMenu = 0;
3257     }
3258
3259     m_activePopupMenu = m_pageClient.createPopupMenuProxy(this);
3260
3261     if (!m_activePopupMenu)
3262         return;
3263
3264     // Since showPopupMenu() can spin a nested run loop we need to turn off the responsiveness timer.
3265     m_process->responsivenessTimer()->stop();
3266
3267 #if PLATFORM(EFL)
3268     UNUSED_PARAM(data);
3269     m_uiPopupMenuClient.showPopupMenu(this, m_activePopupMenu.get(), rect, static_cast<TextDirection>(textDirection), m_pageScaleFactor, items, selectedIndex);
3270 #else
3271     RefPtr<WebPopupMenuProxy> protectedActivePopupMenu = m_activePopupMenu;
3272
3273     protectedActivePopupMenu->showPopupMenu(rect, static_cast<TextDirection>(textDirection), m_pageScaleFactor, items, data, selectedIndex);
3274
3275     // Since Efl doesn't use a nested mainloop to show the popup and get the answer, we need to keep the client pointer valid.
3276     // FIXME: The above comment doesn't make any sense since this code is compiled out for EFL.
3277     protectedActivePopupMenu->invalidate();
3278     protectedActivePopupMenu = 0;
3279 #endif
3280 }
3281
3282 void WebPageProxy::hidePopupMenu()
3283 {
3284     if (!m_activePopupMenu)
3285         return;
3286
3287 #if PLATFORM(EFL)
3288     m_uiPopupMenuClient.hidePopupMenu(this);
3289 #else
3290     m_activePopupMenu->hidePopupMenu();
3291 #endif
3292     m_activePopupMenu->invalidate();
3293     m_activePopupMenu = 0;
3294 }
3295
3296 #if ENABLE(CONTEXT_MENUS)
3297 void WebPageProxy::showContextMenu(const IntPoint& menuLocation, const ContextMenuContextData& contextMenuContextData, const Vector<WebContextMenuItemData>& proposedItems, IPC::MessageDecoder& decoder)
3298 {
3299     internalShowContextMenu(menuLocation, contextMenuContextData, proposedItems, decoder);
3300     
3301     // No matter the result of internalShowContextMenu, always notify the WebProcess that the menu is hidden so it starts handling mouse events again.
3302     m_process->send(Messages::WebPage::ContextMenuHidden(), m_pageID);
3303 }
3304
3305 void WebPageProxy::internalShowContextMenu(const IntPoint& menuLocation, const ContextMenuContextData& contextMenuContextData, const Vector<WebContextMenuItemData>& proposedItems, IPC::MessageDecoder& decoder)
3306 {
3307     RefPtr<API::Object> userData;
3308     WebContextUserMessageDecoder messageDecoder(userData, process());
3309     if (!decoder.decode(messageDecoder))
3310         return;
3311
3312     m_activeContextMenuContextData = contextMenuContextData;
3313
3314     if (!m_contextMenuClient.hideContextMenu(this) && m_activeContextMenu) {
3315         m_activeContextMenu->hideContextMenu();
3316         m_activeContextMenu = 0;
3317     }
3318
3319     m_activeContextMenu = m_pageClient.createContextMenuProxy(this);
3320     if (!m_activeContextMenu)
3321         return;
3322
3323     // Since showContextMenu() can spin a nested run loop we need to turn off the responsiveness timer.
3324     m_process->responsivenessTimer()->stop();
3325
3326     // Unless this is an image control, give the PageContextMenuClient one last swipe at changing the menu.
3327     Vector<WebContextMenuItemData> items;
3328     bool useProposedItems = true;
3329     bool askClientToChangeMenu = true;
3330 #if ENABLE(IMAGE_CONTROLS)
3331     if (!contextMenuContextData.controlledImageHandle().isNull())
3332         askClientToChangeMenu = false;
3333 #endif
3334
3335     if (askClientToChangeMenu && m_contextMenuClient.getContextMenuFromProposedMenu(this, proposedItems, items, contextMenuContextData.webHitTestResultData(), userData.get()))
3336         useProposedItems = false;
3337     
3338     const Vector<WebContextMenuItemData>& itemsToShow = useProposedItems ? proposedItems : items;
3339     if (!m_contextMenuClient.showContextMenu(this, menuLocation, itemsToShow))
3340         m_activeContextMenu->showContextMenu(menuLocation, itemsToShow, contextMenuContextData);
3341
3342     m_contextMenuClient.contextMenuDismissed(this);
3343 }
3344
3345 #if ENABLE(IMAGE_CONTROLS)
3346 void WebPageProxy::replaceControlledImage(PassRefPtr<ShareableBitmap> newBitmap)
3347 {
3348     RefPtr<ShareableBitmap> bitmap = newBitmap;
3349     ShareableBitmap::Handle bitmapHandle;
3350     bitmap->createHandle(bitmapHandle);
3351     m_process->send(Messages::WebPage::ReplaceControlledImage(bitmapHandle), m_pageID);
3352 }
3353 #endif
3354
3355 void WebPageProxy::contextMenuItemSelected(const WebContextMenuItemData& item)
3356 {
3357     // Application custom items don't need to round-trip through to WebCore in the WebProcess.
3358     if (item.action() >= ContextMenuItemBaseApplicationTag) {
3359         m_contextMenuClient.customContextMenuItemSelected(this, item);
3360         return;
3361     }
3362
3363 #if PLATFORM(COCOA)
3364     if (item.action() == ContextMenuItemTagSmartCopyPaste) {
3365         setSmartInsertDeleteEnabled(!isSmartInsertDeleteEnabled());
3366         return;
3367     }
3368     if (item.action() == ContextMenuItemTagSmartQuotes) {
3369         TextChecker::setAutomaticQuoteSubstitutionEnabled(!TextChecker::state().isAutomaticQuoteSubstitutionEnabled);
3370         m_process->updateTextCheckerState();
3371         return;
3372     }
3373     if (item.action() == ContextMenuItemTagSmartDashes) {
3374         TextChecker::setAutomaticDashSubstitutionEnabled(!TextChecker::state().isAutomaticDashSubstitutionEnabled);
3375         m_process->updateTextCheckerState();
3376         return;
3377     }
3378     if (item.action() == ContextMenuItemTagSmartLinks) {
3379         TextChecker::setAutomaticLinkDetectionEnabled(!TextChecker::state().isAutomaticLinkDetectionEnabled);
3380         m_process->updateTextCheckerState();
3381         return;
3382     }
3383     if (item.action() == ContextMenuItemTagTextReplacement) {
3384         TextChecker::setAutomaticTextReplacementEnabled(!TextChecker::state().isAutomaticTextReplacementEnabled);
3385         m_process->updateTextCheckerState();
3386         return;
3387     }
3388     if (item.action() == ContextMenuItemTagCorrectSpellingAutomatically) {
3389         TextChecker::setAutomaticSpellingCorrectionEnabled(!TextChecker::state().isAutomaticSpellingCorrectionEnabled);
3390         m_process->updateTextCheckerState();
3391         return;        
3392     }
3393     if (item.action() == ContextMenuItemTagShowSubstitutions) {
3394         TextChecker::toggleSubstitutionsPanelIsShowing();
3395         return;
3396     }
3397 #endif
3398     if (item.action() == ContextMenuItemTagDownloadImageToDisk) {
3399         m_process->context().download(this, URL(URL(), m_activeContextMenuContextData.webHitTestResultData().absoluteImageURL));
3400         return;    
3401     }
3402     if (item.action() == ContextMenuItemTagDownloadLinkToDisk) {
3403         m_process->context().download(this, URL(URL(), m_activeContextMenuContextData.webHitTestResultData().absoluteLinkURL));
3404         return;
3405     }
3406     if (item.action() == ContextMenuItemTagDownloadMediaToDisk) {
3407         m_process->context().download(this, URL(URL(), m_activeContextMenuContextData.webHitTestResultData().absoluteMediaURL));
3408         return;
3409     }
3410     if (item.action() == ContextMenuItemTagCheckSpellingWhileTyping) {
3411         TextChecker::setContinuousSpellCheckingEnabled(!TextChecker::state().isContinuousSpellCheckingEnabled);
3412         m_process->updateTextCheckerState();
3413         return;
3414     }
3415     if (item.action() == ContextMenuItemTagCheckGrammarWithSpelling) {
3416         TextChecker::setGrammarCheckingEnabled(!TextChecker::state().isGrammarCheckingEnabled);
3417         m_process->updateTextCheckerState();
3418         return;
3419     }
3420     if (item.action() == ContextMenuItemTagShowSpellingPanel) {
3421         if (!TextChecker::spellingUIIsShowing())
3422             advanceToNextMisspelling(true);
3423         TextChecker::toggleSpellingUIIsShowing();
3424         return;
3425     }
3426     if (item.action() == ContextMenuItemTagLearnSpelling || item.action() == ContextMenuItemTagIgnoreSpelling)
3427         ++m_pendingLearnOrIgnoreWordMessageCount;
3428
3429     m_process->send(Messages::WebPage::DidSelectItemFromActiveContextMenu(item), m_pageID);
3430 }
3431 #endif // ENABLE(CONTEXT_MENUS)
3432
3433 void WebPageProxy::didChooseFilesForOpenPanel(const Vector<String>& fileURLs)
3434 {
3435     if (!isValid())
3436         return;
3437
3438 #if ENABLE(WEB_PROCESS_SANDBOX)
3439     // FIXME: The sandbox extensions should be sent with the DidChooseFilesForOpenPanel message. This
3440     // is gated on a way of passing SandboxExtension::Handles in a Vector.
3441     for (size_t i = 0; i < fileURLs.size(); ++i) {
3442         SandboxExtension::Handle sandboxExtensionHandle;
3443         SandboxExtension::createHandle(fileURLs[i], SandboxExtension::ReadOnly, sandboxExtensionHandle);
3444         m_process->send(Messages::WebPage::ExtendSandboxForFileFromOpenPanel(sandboxExtensionHandle), m_pageID);
3445     }
3446 #endif
3447
3448     m_process->send(Messages::WebPage::DidChooseFilesForOpenPanel(fileURLs), m_pageID);
3449
3450     m_openPanelResultListener->invalidate();
3451     m_openPanelResultListener = 0;
3452 }
3453
3454 void WebPageProxy::didCancelForOpenPanel()
3455 {
3456     if (!isValid())
3457         return;
3458
3459     m_process->send(Messages::WebPage::DidCancelForOpenPanel(), m_pageID);
3460     
3461     m_openPanelResultListener->invalidate();
3462     m_openPanelResultListener = 0;
3463 }
3464
3465 void WebPageProxy::advanceToNextMisspelling(bool startBeforeSelection)
3466 {
3467     m_process->send(Messages::WebPage::AdvanceToNextMisspelling(startBeforeSelection), m_pageID);
3468 }
3469
3470 void WebPageProxy::changeSpellingToWord(const String& word)
3471 {
3472     if (word.isEmpty())
3473         return;
3474
3475     m_process->send(Messages::WebPage::ChangeSpellingToWord(word), m_pageID);
3476 }
3477
3478 void WebPageProxy::registerEditCommand(PassRefPtr<WebEditCommandProxy> commandProxy, UndoOrRedo undoOrRedo)
3479 {
3480     m_pageClient.registerEditCommand(commandProxy, undoOrRedo);
3481 }
3482
3483 void WebPageProxy::addEditCommand(WebEditCommandProxy* command)
3484 {
3485     m_editCommandSet.add(command);
3486 }
3487
3488 void WebPageProxy::removeEditCommand(WebEditCommandProxy* command)
3489 {
3490     m_editCommandSet.remove(command);
3491
3492     if (!isValid())
3493         return;
3494     m_process->send(Messages::WebPage::DidRemoveEditCommand(command->commandID()), m_pageID);
3495 }
3496
3497 bool WebPageProxy::isValidEditCommand(WebEditCommandProxy* command)
3498 {
3499     return m_editCommandSet.find(command) != m_editCommandSet.end();
3500 }
3501
3502 int64_t WebPageProxy::spellDocumentTag()
3503 {
3504     if (!m_hasSpellDocumentTag) {
3505         m_spellDocumentTag = TextChecker::uniqueSpellDocumentTag(this);
3506         m_hasSpellDocumentTag = true;
3507     }
3508
3509     return m_spellDocumentTag;
3510 }
3511
3512 #if USE(UNIFIED_TEXT_CHECKING)
3513 void WebPageProxy::checkTextOfParagraph(const String& text, uint64_t checkingTypes, Vector<TextCheckingResult>& results)
3514 {
3515     results = TextChecker::checkTextOfParagraph(spellDocumentTag(), text, checkingTypes);
3516 }
3517 #endif
3518
3519 void WebPageProxy::checkSpellingOfString(const String& text, int32_t& misspellingLocation, int32_t& misspellingLength)
3520 {
3521     TextChecker::checkSpellingOfString(spellDocumentTag(), text, misspellingLocation, misspellingLength);
3522 }
3523
3524 void WebPageProxy::checkGrammarOfString(const String& text, Vector<GrammarDetail>& grammarDetails, int32_t& badGrammarLocation, int32_t& badGrammarLength)
3525 {
3526     TextChecker::checkGrammarOfString(spellDocumentTag(), text, grammarDetails, badGrammarLocation, badGrammarLength);
3527 }
3528
3529 void WebPageProxy::spellingUIIsShowing(bool& isShowing)
3530 {
3531     isShowing = TextChecker::spellingUIIsShowing();
3532 }
3533
3534 void WebPageProxy::updateSpellingUIWithMisspelledWord(const String& misspelledWord)
3535 {
3536     TextChecker::updateSpellingUIWithMisspelledWord(spellDocumentTag(), misspelledWord);
3537 }
3538
3539 void WebPageProxy::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail)
3540 {
3541     TextChecker::updateSpellingUIWithGrammarString(spellDocumentTag(), badGrammarPhrase, grammarDetail);
3542 }
3543
3544 void WebPageProxy::getGuessesForWord(const String& word, const String& context, Vector<String>& guesses)
3545 {
3546     TextChecker::getGuessesForWord(spellDocumentTag(), word, context, guesses);
3547 }
3548
3549 void WebPageProxy::learnWord(const String& word)
3550 {
3551     MESSAGE_CHECK(m_pendingLearnOrIgnoreWordMessageCount);
3552     --m_pendingLearnOrIgnoreWordMessageCount;
3553
3554     TextChecker::learnWord(spellDocumentTag(), word);
3555 }
3556
3557 void WebPageProxy::ignoreWord(const String& word)
3558 {
3559     MESSAGE_CHECK(m_pendingLearnOrIgnoreWordMessageCount);
3560     --m_pendingLearnOrIgnoreWordMessageCount;
3561
3562     TextChecker::ignoreWord(spellDocumentTag(), word);
3563 }
3564
3565 void WebPageProxy::requestCheckingOfString(uint64_t requestID, const TextCheckingRequestData& request)
3566 {
3567     TextChecker::requestCheckingOfString(TextCheckerCompletion::create(requestID, request, this));
3568 }
3569
3570 void WebPageProxy::didFinishCheckingText(uint64_t requestID, const Vector<WebCore::TextCheckingResult>& result)
3571 {
3572     m_process->send(Messages::WebPage::DidFinishCheckingText(requestID, result), m_pageID);
3573 }
3574
3575 void WebPageProxy::didCancelCheckingText(uint64_t requestID)
3576 {
3577     m_process->send(Messages::WebPage::DidCancelCheckingText(requestID), m_pageID);
3578 }
3579 // Other
3580
3581 void WebPageProxy::setFocus(bool focused)
3582 {
3583     if (focused)
3584         m_uiClient->focus(this);
3585     else
3586         m_uiClient->unfocus(this);
3587 }
3588
3589 void WebPageProxy::takeFocus(uint32_t direction)
3590 {
3591     m_uiClient->takeFocus(this, (static_cast<FocusDirection>(direction) == FocusDirectionForward) ? kWKFocusDirectionForward : kWKFocusDirectionBackward);
3592 }
3593
3594 void WebPageProxy::setToolTip(const String& toolTip)
3595 {
3596     String oldToolTip = m_toolTip;
3597     m_toolTip = toolTip;
3598     m_pageClient.toolTipChanged(oldToolTip, m_toolTip);
3599 }
3600
3601 void WebPageProxy::setCursor(const WebCore::Cursor& cursor)
3602 {
3603     // The Web process may have asked to change the cursor when the view was in an active window, but
3604     // if it is no longer in a window or the window is not active, then the cursor should not change.
3605     if (m_pageClient.isViewWindowActive())
3606         m_pageClient.setCursor(cursor);
3607 }
3608
3609 void WebPageProxy::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves)
3610 {
3611     m_pageClient.setCursorHiddenUntilMouseMoves(hiddenUntilMouseMoves);
3612 }
3613
3614 void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
3615 {
3616     WebEvent::Type type = static_cast<WebEvent::Type>(opaqueType);
3617
3618     switch (type) {
3619     case WebEvent::NoType:
3620     case WebEvent::MouseMove:
3621         break;
3622
3623     case WebEvent::MouseDown:
3624     case WebEvent::MouseUp:
3625     case WebEvent::Wheel:
3626     case WebEvent::KeyDown:
3627     case WebEvent::KeyUp:
3628     case WebEvent::RawKeyDown:
3629     case WebEvent::Char:
3630 #if ENABLE(TOUCH_EVENTS)
3631     case WebEvent::TouchStart:
3632     case WebEvent::TouchMove:
3633     case WebEvent::TouchEnd:
3634     case WebEvent::TouchCancel:
3635 #endif
3636         m_process->responsivenessTimer()->stop();
3637         break;
3638     }
3639
3640     switch (type) {