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