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