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