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