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