1/*
2 * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "WebPageProxy.h"
28
29#include "AuthenticationChallengeProxy.h"
30#include "AuthenticationDecisionListener.h"
31#include "DataReference.h"
32#include "DownloadProxy.h"
33#include "DrawingAreaProxy.h"
34#include "FindIndicator.h"
35#include "MessageID.h"
36#include "NativeWebKeyboardEvent.h"
37#include "NativeWebMouseEvent.h"
38#include "PageClient.h"
39#include "PrintInfo.h"
40#include "SessionState.h"
41#include "StringPairVector.h"
42#include "TextChecker.h"
43#include "TextCheckerState.h"
44#include "WKContextPrivate.h"
45#include "WebBackForwardList.h"
46#include "WebBackForwardListItem.h"
47#include "WebCertificateInfo.h"
48#include "WebContext.h"
49#include "WebContextMenuProxy.h"
50#include "WebContextUserMessageCoders.h"
51#include "WebCoreArgumentCoders.h"
52#include "WebData.h"
53#include "WebEditCommandProxy.h"
54#include "WebEvent.h"
55#include "WebFormSubmissionListenerProxy.h"
56#include "WebFramePolicyListenerProxy.h"
57#include "WebFullScreenManagerProxy.h"
58#include "WebInspectorProxy.h"
59#include "WebOpenPanelResultListenerProxy.h"
60#include "WebPageCreationParameters.h"
61#include "WebPageGroup.h"
62#include "WebPageGroupData.h"
63#include "WebPageMessages.h"
64#include "WebPopupItem.h"
65#include "WebPopupMenuProxy.h"
66#include "WebPreferences.h"
67#include "WebProcessMessages.h"
68#include "WebProcessProxy.h"
69#include "WebProtectionSpace.h"
70#include "WebSecurityOrigin.h"
71#include "WebURLRequest.h"
72#include <WebCore/DragData.h>
73#include <WebCore/FloatRect.h>
74#include <WebCore/FocusDirection.h>
75#include <WebCore/MIMETypeRegistry.h>
76#include <WebCore/WindowFeatures.h>
77#include <stdio.h>
78
79#if PLATFORM(WIN)
80#include "WebDragSource.h"
81#include <WebCore/BitmapInfo.h>
82#include <WebCore/COMPtr.h>
83#include <WebCore/WCDataObject.h>
84#include <shlobj.h>
85#endif
86
87#ifndef NDEBUG
88#include <wtf/RefCountedLeakCounter.h>
89#endif
90
91// This controls what strategy we use for mouse wheel coalesing.
92#define MERGE_WHEEL_EVENTS 0
93
94#define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, process()->connection())
95
96using namespace WebCore;
97
98namespace WebKit {
99
100WKPageDebugPaintFlags WebPageProxy::s_debugPaintFlags = 0;
101
102#ifndef NDEBUG
103static WTF::RefCountedLeakCounter webPageProxyCounter("WebPageProxy");
104#endif
105
106PassRefPtr<WebPageProxy> WebPageProxy::create(PageClient* pageClient, PassRefPtr<WebProcessProxy> process, WebPageGroup* pageGroup, uint64_t pageID)
107{
108    return adoptRef(new WebPageProxy(pageClient, process, pageGroup, pageID));
109}
110
111WebPageProxy::WebPageProxy(PageClient* pageClient, PassRefPtr<WebProcessProxy> process, WebPageGroup* pageGroup, uint64_t pageID)
112    : m_pageClient(pageClient)
113    , m_process(process)
114    , m_pageGroup(pageGroup)
115    , m_mainFrame(0)
116    , m_userAgent(standardUserAgent())
117    , m_geolocationPermissionRequestManager(this)
118    , m_estimatedProgress(0)
119    , m_isInWindow(m_pageClient->isViewInWindow())
120    , m_isVisible(m_pageClient->isViewVisible())
121    , m_backForwardList(WebBackForwardList::create(this))
122    , m_textZoomFactor(1)
123    , m_pageZoomFactor(1)
124    , m_viewScaleFactor(1)
125    , m_drawsBackground(true)
126    , m_drawsTransparentBackground(false)
127    , m_areMemoryCacheClientCallsEnabled(true)
128    , m_useFixedLayout(false)
129    , m_isValid(true)
130    , m_isClosed(false)
131    , m_isInPrintingMode(false)
132    , m_isPerformingDOMPrintOperation(false)
133    , m_inDecidePolicyForMIMEType(false)
134    , m_syncMimeTypePolicyActionIsValid(false)
135    , m_syncMimeTypePolicyAction(PolicyUse)
136    , m_syncMimeTypePolicyDownloadID(0)
137    , m_inDecidePolicyForNavigationAction(false)
138    , m_syncNavigationActionPolicyActionIsValid(false)
139    , m_syncNavigationActionPolicyAction(PolicyUse)
140    , m_syncNavigationActionPolicyDownloadID(0)
141    , m_processingWheelEvent(false)
142    , m_processingMouseMoveEvent(false)
143    , m_pageID(pageID)
144#if PLATFORM(MAC)
145    , m_isSmartInsertDeleteEnabled(TextChecker::isSmartInsertDeleteEnabled())
146#endif
147    , m_spellDocumentTag(0)
148    , m_hasSpellDocumentTag(false)
149    , m_pendingLearnOrIgnoreWordMessageCount(0)
150    , m_mainFrameHasCustomRepresentation(false)
151    , m_currentDragOperation(DragOperationNone)
152    , m_mainFrameHasHorizontalScrollbar(false)
153    , m_mainFrameHasVerticalScrollbar(false)
154    , m_mainFrameIsPinnedToLeftSide(false)
155    , m_mainFrameIsPinnedToRightSide(false)
156{
157#ifndef NDEBUG
158    webPageProxyCounter.increment();
159#endif
160
161    WebContext::statistics().wkPageCount++;
162
163    m_pageGroup->addPage(this);
164}
165
166WebPageProxy::~WebPageProxy()
167{
168    if (!m_isClosed)
169        close();
170
171    WebContext::statistics().wkPageCount--;
172
173    if (m_hasSpellDocumentTag)
174        TextChecker::closeSpellDocumentWithTag(m_spellDocumentTag);
175
176    m_pageGroup->removePage(this);
177
178#ifndef NDEBUG
179    webPageProxyCounter.decrement();
180#endif
181}
182
183WebProcessProxy* WebPageProxy::process() const
184{
185    return m_process.get();
186}
187
188bool WebPageProxy::isValid()
189{
190    // A page that has been explicitly closed is never valid.
191    if (m_isClosed)
192        return false;
193
194    return m_isValid;
195}
196
197void WebPageProxy::setDrawingArea(PassOwnPtr<DrawingAreaProxy> drawingArea)
198{
199    if (drawingArea == m_drawingArea)
200        return;
201
202    m_drawingArea = drawingArea;
203}
204
205void WebPageProxy::initializeLoaderClient(const WKPageLoaderClient* loadClient)
206{
207    m_loaderClient.initialize(loadClient);
208}
209
210void WebPageProxy::initializePolicyClient(const WKPagePolicyClient* policyClient)
211{
212    m_policyClient.initialize(policyClient);
213}
214
215void WebPageProxy::initializeFormClient(const WKPageFormClient* formClient)
216{
217    m_formClient.initialize(formClient);
218}
219
220void WebPageProxy::initializeResourceLoadClient(const WKPageResourceLoadClient* client)
221{
222    m_resourceLoadClient.initialize(client);
223}
224
225void WebPageProxy::initializeUIClient(const WKPageUIClient* client)
226{
227    if (!isValid())
228        return;
229
230    m_uiClient.initialize(client);
231
232    process()->send(Messages::WebPage::SetCanRunBeforeUnloadConfirmPanel(m_uiClient.canRunBeforeUnloadConfirmPanel()), m_pageID);
233    process()->send(Messages::WebPage::SetCanRunModal(m_uiClient.canRunModal()), m_pageID);
234}
235
236void WebPageProxy::initializeFindClient(const WKPageFindClient* client)
237{
238    m_findClient.initialize(client);
239}
240
241void WebPageProxy::initializeContextMenuClient(const WKPageContextMenuClient* client)
242{
243    m_contextMenuClient.initialize(client);
244}
245
246void WebPageProxy::reattachToWebProcess()
247{
248    ASSERT(!isValid());
249
250    m_isValid = true;
251
252    m_process = m_process->context()->relaunchProcessIfNecessary();
253    process()->addExistingWebPage(this, m_pageID);
254
255    initializeWebPage();
256
257    m_pageClient->didRelaunchProcess();
258}
259
260void WebPageProxy::reattachToWebProcessWithItem(WebBackForwardListItem* item)
261{
262    if (item && item != m_backForwardList->currentItem())
263        m_backForwardList->goToItem(item);
264
265    reattachToWebProcess();
266
267    if (!item)
268        return;
269
270    SandboxExtension::Handle sandboxExtensionHandle;
271    initializeSandboxExtensionHandle(KURL(KURL(), item->url()), sandboxExtensionHandle);
272    process()->send(Messages::WebPage::GoToBackForwardItem(item->itemID(), sandboxExtensionHandle), m_pageID);
273}
274
275void WebPageProxy::initializeWebPage()
276{
277    ASSERT(isValid());
278
279    BackForwardListItemVector items = m_backForwardList->entries();
280    for (size_t i = 0; i < items.size(); ++i)
281        process()->registerNewWebBackForwardListItem(items[i].get());
282
283    m_drawingArea = m_pageClient->createDrawingAreaProxy();
284    ASSERT(m_drawingArea);
285
286    process()->send(Messages::WebProcess::CreateWebPage(m_pageID, creationParameters()), 0);
287}
288
289void WebPageProxy::close()
290{
291    if (!isValid())
292        return;
293
294    m_isClosed = true;
295
296    m_backForwardList->pageClosed();
297    m_pageClient->pageClosed();
298
299    process()->disconnectFramesFromPage(this);
300    m_mainFrame = 0;
301
302#if ENABLE(INSPECTOR)
303    if (m_inspector) {
304        m_inspector->invalidate();
305        m_inspector = 0;
306    }
307#endif
308
309#if ENABLE(FULLSCREEN_API)
310    if (m_fullScreenManager) {
311        m_fullScreenManager->invalidate();
312        m_fullScreenManager = 0;
313    }
314#endif
315
316    if (m_openPanelResultListener) {
317        m_openPanelResultListener->invalidate();
318        m_openPanelResultListener = 0;
319    }
320
321    m_geolocationPermissionRequestManager.invalidateRequests();
322
323    m_toolTip = String();
324
325    m_mainFrameHasHorizontalScrollbar = false;
326    m_mainFrameHasVerticalScrollbar = false;
327
328    m_mainFrameIsPinnedToLeftSide = false;
329    m_mainFrameIsPinnedToRightSide = false;
330
331    invalidateCallbackMap(m_voidCallbacks);
332    invalidateCallbackMap(m_dataCallbacks);
333    invalidateCallbackMap(m_stringCallbacks);
334    m_loadDependentStringCallbackIDs.clear();
335    invalidateCallbackMap(m_scriptValueCallbacks);
336    invalidateCallbackMap(m_computedPagesCallbacks);
337
338    Vector<WebEditCommandProxy*> editCommandVector;
339    copyToVector(m_editCommandSet, editCommandVector);
340    m_editCommandSet.clear();
341    for (size_t i = 0, size = editCommandVector.size(); i < size; ++i)
342        editCommandVector[i]->invalidate();
343
344    m_activePopupMenu = 0;
345
346    m_estimatedProgress = 0.0;
347
348    m_loaderClient.initialize(0);
349    m_policyClient.initialize(0);
350    m_uiClient.initialize(0);
351
352    m_drawingArea.clear();
353
354    process()->send(Messages::WebPage::Close(), m_pageID);
355    process()->removeWebPage(m_pageID);
356}
357
358bool WebPageProxy::tryClose()
359{
360    if (!isValid())
361        return true;
362
363    process()->send(Messages::WebPage::TryClose(), m_pageID);
364    return false;
365}
366
367void WebPageProxy::initializeSandboxExtensionHandle(const KURL& url, SandboxExtension::Handle& sandboxExtensionHandle)
368{
369    if (!url.isLocalFile())
370        return;
371
372    // Don't give the inspector full access to the file system.
373    if (WebInspectorProxy::isInspectorPage(this))
374        return;
375
376    SandboxExtension::createHandle("/", SandboxExtension::ReadOnly, sandboxExtensionHandle);
377}
378
379void WebPageProxy::loadURL(const String& url)
380{
381    setPendingAPIRequestURL(url);
382
383    if (!isValid())
384        reattachToWebProcess();
385
386    SandboxExtension::Handle sandboxExtensionHandle;
387    initializeSandboxExtensionHandle(KURL(KURL(), url), sandboxExtensionHandle);
388    process()->send(Messages::WebPage::LoadURL(url, sandboxExtensionHandle), m_pageID);
389}
390
391void WebPageProxy::loadURLRequest(WebURLRequest* urlRequest)
392{
393    setPendingAPIRequestURL(urlRequest->resourceRequest().url());
394
395    if (!isValid())
396        reattachToWebProcess();
397
398    SandboxExtension::Handle sandboxExtensionHandle;
399    initializeSandboxExtensionHandle(urlRequest->resourceRequest().url(), sandboxExtensionHandle);
400    process()->send(Messages::WebPage::LoadURLRequest(urlRequest->resourceRequest(), sandboxExtensionHandle), m_pageID);
401}
402
403void WebPageProxy::loadHTMLString(const String& htmlString, const String& baseURL)
404{
405    if (!isValid())
406        reattachToWebProcess();
407
408    process()->send(Messages::WebPage::LoadHTMLString(htmlString, baseURL), m_pageID);
409}
410
411void WebPageProxy::loadAlternateHTMLString(const String& htmlString, const String& baseURL, const String& unreachableURL)
412{
413    if (!isValid())
414        reattachToWebProcess();
415
416    if (m_mainFrame)
417        m_mainFrame->setUnreachableURL(unreachableURL);
418
419    process()->send(Messages::WebPage::LoadAlternateHTMLString(htmlString, baseURL, unreachableURL), m_pageID);
420}
421
422void WebPageProxy::loadPlainTextString(const String& string)
423{
424    if (!isValid())
425        reattachToWebProcess();
426
427    process()->send(Messages::WebPage::LoadPlainTextString(string), m_pageID);
428}
429
430void WebPageProxy::stopLoading()
431{
432    if (!isValid())
433        return;
434    process()->send(Messages::WebPage::StopLoading(), m_pageID);
435}
436
437void WebPageProxy::reload(bool reloadFromOrigin)
438{
439    if (m_backForwardList->currentItem())
440        setPendingAPIRequestURL(m_backForwardList->currentItem()->url());
441
442    if (!isValid()) {
443        reattachToWebProcessWithItem(m_backForwardList->currentItem());
444        return;
445    }
446
447    process()->send(Messages::WebPage::Reload(reloadFromOrigin), m_pageID);
448}
449
450void WebPageProxy::goForward()
451{
452    if (isValid() && !canGoForward())
453        return;
454
455    WebBackForwardListItem* forwardItem = m_backForwardList->forwardItem();
456    if (forwardItem)
457        setPendingAPIRequestURL(forwardItem->url());
458
459    if (!isValid()) {
460        reattachToWebProcessWithItem(forwardItem);
461        return;
462    }
463
464    SandboxExtension::Handle sandboxExtensionHandle;
465    initializeSandboxExtensionHandle(KURL(KURL(), forwardItem->url()), sandboxExtensionHandle);
466    process()->send(Messages::WebPage::GoForward(forwardItem->itemID(), sandboxExtensionHandle), m_pageID);
467}
468
469bool WebPageProxy::canGoForward() const
470{
471    return m_backForwardList->forwardItem();
472}
473
474void WebPageProxy::goBack()
475{
476    if (isValid() && !canGoBack())
477        return;
478
479    WebBackForwardListItem* backItem = m_backForwardList->backItem();
480    if (backItem)
481        setPendingAPIRequestURL(backItem->url());
482
483    if (!isValid()) {
484        reattachToWebProcessWithItem(backItem);
485        return;
486    }
487
488    SandboxExtension::Handle sandboxExtensionHandle;
489    initializeSandboxExtensionHandle(KURL(KURL(), backItem->url()), sandboxExtensionHandle);
490    process()->send(Messages::WebPage::GoBack(backItem->itemID(), sandboxExtensionHandle), m_pageID);
491}
492
493bool WebPageProxy::canGoBack() const
494{
495    return m_backForwardList->backItem();
496}
497
498void WebPageProxy::goToBackForwardItem(WebBackForwardListItem* item)
499{
500    if (!isValid()) {
501        reattachToWebProcessWithItem(item);
502        return;
503    }
504
505    setPendingAPIRequestURL(item->url());
506
507    SandboxExtension::Handle sandboxExtensionHandle;
508    initializeSandboxExtensionHandle(KURL(KURL(), item->url()), sandboxExtensionHandle);
509    process()->send(Messages::WebPage::GoToBackForwardItem(item->itemID(), sandboxExtensionHandle), m_pageID);
510}
511
512void WebPageProxy::didChangeBackForwardList(WebBackForwardListItem* added, Vector<RefPtr<APIObject> >* removed)
513{
514    m_loaderClient.didChangeBackForwardList(this, added, removed);
515}
516
517void WebPageProxy::shouldGoToBackForwardListItem(uint64_t itemID, bool& shouldGoToBackForwardItem)
518{
519    WebBackForwardListItem* item = process()->webBackForwardItem(itemID);
520    shouldGoToBackForwardItem = item && m_loaderClient.shouldGoToBackForwardListItem(this, item);
521}
522
523bool WebPageProxy::canShowMIMEType(const String& mimeType) const
524{
525    if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
526        return true;
527
528    if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
529        return true;
530
531    if (mimeType.startsWith("text/", false))
532        return !MIMETypeRegistry::isUnsupportedTextMIMEType(mimeType);
533
534    String newMimeType = mimeType;
535    PluginInfoStore::Plugin plugin = m_process->context()->pluginInfoStore()->findPlugin(newMimeType, KURL());
536    if (!plugin.path.isNull())
537        return true;
538
539    return false;
540}
541
542void WebPageProxy::setDrawsBackground(bool drawsBackground)
543{
544    if (m_drawsBackground == drawsBackground)
545        return;
546
547    m_drawsBackground = drawsBackground;
548
549    if (isValid())
550        process()->send(Messages::WebPage::SetDrawsBackground(drawsBackground), m_pageID);
551}
552
553void WebPageProxy::setDrawsTransparentBackground(bool drawsTransparentBackground)
554{
555    if (m_drawsTransparentBackground == drawsTransparentBackground)
556        return;
557
558    m_drawsTransparentBackground = drawsTransparentBackground;
559
560    if (isValid())
561        process()->send(Messages::WebPage::SetDrawsTransparentBackground(drawsTransparentBackground), m_pageID);
562}
563
564void WebPageProxy::viewWillStartLiveResize()
565{
566    if (!isValid())
567        return;
568    process()->send(Messages::WebPage::ViewWillStartLiveResize(), m_pageID);
569}
570
571void WebPageProxy::viewWillEndLiveResize()
572{
573    if (!isValid())
574        return;
575    process()->send(Messages::WebPage::ViewWillEndLiveResize(), m_pageID);
576}
577
578void WebPageProxy::setViewNeedsDisplay(const IntRect& rect)
579{
580    m_pageClient->setViewNeedsDisplay(rect);
581}
582
583void WebPageProxy::displayView()
584{
585    m_pageClient->displayView();
586}
587
588void WebPageProxy::scrollView(const IntRect& scrollRect, const IntSize& scrollOffset)
589{
590    m_pageClient->scrollView(scrollRect, scrollOffset);
591}
592
593void WebPageProxy::viewStateDidChange(ViewStateFlags flags)
594{
595    if (!isValid())
596        return;
597
598    if (flags & ViewIsFocused)
599        process()->send(Messages::WebPage::SetFocused(m_pageClient->isViewFocused()), m_pageID);
600
601    if (flags & ViewWindowIsActive)
602        process()->send(Messages::WebPage::SetActive(m_pageClient->isViewWindowActive()), m_pageID);
603
604    if (flags & ViewIsVisible) {
605        bool isVisible = m_pageClient->isViewVisible();
606        if (isVisible != m_isVisible) {
607            m_isVisible = isVisible;
608            m_drawingArea->visibilityDidChange();
609            m_drawingArea->setPageIsVisible(isVisible);
610        }
611    }
612
613    if (flags & ViewIsInWindow) {
614        bool isInWindow = m_pageClient->isViewInWindow();
615        if (m_isInWindow != isInWindow) {
616            m_isInWindow = isInWindow;
617            process()->send(Messages::WebPage::SetIsInWindow(isInWindow), m_pageID);
618        }
619    }
620
621    if (flags & (ViewWindowIsActive | ViewIsVisible))
622        m_drawingArea->setBackingStoreIsDiscardable(!m_pageClient->isViewWindowActive() || !isViewVisible());
623}
624
625IntSize WebPageProxy::viewSize() const
626{
627    return m_pageClient->viewSize();
628}
629
630void WebPageProxy::setInitialFocus(bool forward)
631{
632    if (!isValid())
633        return;
634    process()->send(Messages::WebPage::SetInitialFocus(forward), m_pageID);
635}
636
637void WebPageProxy::setWindowResizerSize(const IntSize& windowResizerSize)
638{
639    if (!isValid())
640        return;
641    process()->send(Messages::WebPage::SetWindowResizerSize(windowResizerSize), m_pageID);
642}
643
644void WebPageProxy::validateCommand(const String& commandName, PassRefPtr<ValidateCommandCallback> callback)
645{
646    if (!isValid()) {
647        callback->invalidate();
648        return;
649    }
650
651    uint64_t callbackID = callback->callbackID();
652    m_validateCommandCallbacks.set(callbackID, callback.get());
653    process()->send(Messages::WebPage::ValidateCommand(commandName, callbackID), m_pageID);
654}
655
656void WebPageProxy::executeEditCommand(const String& commandName)
657{
658    if (!isValid())
659        return;
660
661    process()->send(Messages::WebPage::ExecuteEditCommand(commandName), m_pageID);
662}
663
664#if PLATFORM(WIN)
665WebCore::IntRect WebPageProxy::firstRectForCharacterInSelectedRange(int characterPosition)
666{
667    IntRect resultRect;
668    process()->sendSync(Messages::WebPage::FirstRectForCharacterInSelectedRange(characterPosition), Messages::WebPage::FirstRectForCharacterInSelectedRange::Reply(resultRect), m_pageID);
669    return resultRect;
670}
671
672String WebPageProxy::getSelectedText()
673{
674    String text;
675    process()->sendSync(Messages::WebPage::GetSelectedText(), Messages::WebPage::GetSelectedText::Reply(text), m_pageID);
676    return text;
677}
678
679bool WebPageProxy::gestureWillBegin(const IntPoint& point)
680{
681    bool canBeginPanning = false;
682    process()->sendSync(Messages::WebPage::GestureWillBegin(point), Messages::WebPage::GestureWillBegin::Reply(canBeginPanning), m_pageID);
683    return canBeginPanning;
684}
685
686void WebPageProxy::gestureDidScroll(const IntSize& size)
687{
688    process()->send(Messages::WebPage::GestureDidScroll(size), m_pageID);
689}
690
691void WebPageProxy::gestureDidEnd()
692{
693    process()->send(Messages::WebPage::GestureDidEnd(), m_pageID);
694}
695
696void WebPageProxy::setGestureReachedScrollingLimit(bool limitReached)
697{
698    m_pageClient->setGestureReachedScrollingLimit(limitReached);
699}
700#endif
701
702#if ENABLE(TILED_BACKING_STORE)
703void WebPageProxy::setActualVisibleContentRect(const IntRect& rect)
704{
705    if (!isValid())
706        return;
707
708    process()->send(Messages::WebPage::SetActualVisibleContentRect(rect), m_pageID);
709}
710#endif
711
712void WebPageProxy::dragEntered(WebCore::DragData* dragData, const String& dragStorageName)
713{
714    SandboxExtension::Handle sandboxExtensionHandle;
715    performDragControllerAction(DragControllerActionEntered, dragData, dragStorageName, sandboxExtensionHandle);
716}
717
718void WebPageProxy::dragUpdated(WebCore::DragData* dragData, const String& dragStorageName)
719{
720    SandboxExtension::Handle sandboxExtensionHandle;
721    performDragControllerAction(DragControllerActionUpdated, dragData, dragStorageName, sandboxExtensionHandle);
722}
723
724void WebPageProxy::dragExited(WebCore::DragData* dragData, const String& dragStorageName)
725{
726    SandboxExtension::Handle sandboxExtensionHandle;
727    performDragControllerAction(DragControllerActionExited, dragData, dragStorageName, sandboxExtensionHandle);
728}
729
730void WebPageProxy::performDrag(WebCore::DragData* dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle)
731{
732    performDragControllerAction(DragControllerActionPerformDrag, dragData, dragStorageName, sandboxExtensionHandle);
733}
734
735void WebPageProxy::performDragControllerAction(DragControllerAction action, WebCore::DragData* dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle)
736{
737    if (!isValid())
738        return;
739#if PLATFORM(WIN)
740    // FIXME: We should pass the drag data map only on DragEnter.
741    process()->send(Messages::WebPage::PerformDragControllerAction(action, dragData->clientPosition(), dragData->globalPosition(),
742        dragData->draggingSourceOperationMask(), dragData->dragDataMap(), dragData->flags()), m_pageID);
743#else
744    process()->send(Messages::WebPage::PerformDragControllerAction(action, dragData->clientPosition(), dragData->globalPosition(), dragData->draggingSourceOperationMask(), dragStorageName, dragData->flags(), sandboxExtensionHandle), m_pageID);
745#endif
746}
747
748void WebPageProxy::didPerformDragControllerAction(uint64_t resultOperation)
749{
750    m_currentDragOperation = static_cast<DragOperation>(resultOperation);
751}
752
753#if PLATFORM(WIN)
754
755void WebPageProxy::startDragDrop(const IntPoint& imageOrigin, const IntPoint& dragPoint, uint64_t okEffect,
756    const HashMap<UINT, Vector<String> >& dataMap, const IntSize& dragImageSize, const SharedMemory::Handle& dragImageHandle, bool isLinkDrag)
757{
758    COMPtr<WCDataObject> dataObject;
759    WCDataObject::createInstance(&dataObject, dataMap);
760
761    RefPtr<SharedMemory> memoryBuffer = SharedMemory::create(dragImageHandle, SharedMemory::ReadOnly);
762    if (!memoryBuffer)
763        return;
764
765    RefPtr<WebDragSource> source = WebDragSource::createInstance();
766    if (!source)
767        return;
768
769    COMPtr<IDragSourceHelper> helper;
770    if (FAILED(::CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, IID_IDragSourceHelper, reinterpret_cast<LPVOID*>(&helper))))
771        return;
772
773    BitmapInfo bitmapInfo = BitmapInfo::create(dragImageSize);
774    void* bits;
775    OwnPtr<HBITMAP> hbmp(::CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &bits, 0, 0));
776    memcpy(bits, memoryBuffer->data(), memoryBuffer->size());
777
778    SHDRAGIMAGE sdi;
779    sdi.sizeDragImage.cx = bitmapInfo.bmiHeader.biWidth;
780    sdi.sizeDragImage.cy = bitmapInfo.bmiHeader.biHeight;
781    sdi.crColorKey = 0xffffffff;
782    sdi.hbmpDragImage = hbmp.leakPtr();
783    sdi.ptOffset.x = dragPoint.x() - imageOrigin.x();
784    sdi.ptOffset.y = dragPoint.y() - imageOrigin.y();
785    if (isLinkDrag)
786        sdi.ptOffset.y = bitmapInfo.bmiHeader.biHeight - sdi.ptOffset.y;
787
788    helper->InitializeFromBitmap(&sdi, dataObject.get());
789
790    DWORD effect = DROPEFFECT_NONE;
791
792    DragOperation operation = DragOperationNone;
793    if (::DoDragDrop(dataObject.get(), source.get(), okEffect, &effect) == DRAGDROP_S_DROP) {
794        if (effect & DROPEFFECT_COPY)
795            operation = DragOperationCopy;
796        else if (effect & DROPEFFECT_LINK)
797            operation = DragOperationLink;
798        else if (effect & DROPEFFECT_MOVE)
799            operation = DragOperationMove;
800    }
801    POINT globalPoint;
802    ::GetCursorPos(&globalPoint);
803    POINT localPoint = globalPoint;
804    ::ScreenToClient(m_pageClient->nativeWindow(), &localPoint);
805
806    dragEnded(localPoint, globalPoint, operation);
807}
808#endif
809
810void WebPageProxy::dragEnded(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition, uint64_t operation)
811{
812    if (!isValid())
813        return;
814    process()->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID);
815}
816
817void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event)
818{
819    if (!isValid())
820        return;
821
822    // NOTE: This does not start the responsiveness timer because mouse move should not indicate interaction.
823    if (event.type() != WebEvent::MouseMove)
824        process()->responsivenessTimer()->start();
825    else {
826        if (m_processingMouseMoveEvent) {
827            m_nextMouseMoveEvent = adoptPtr(new NativeWebMouseEvent(event));
828            return;
829        }
830
831        m_processingMouseMoveEvent = true;
832    }
833
834    // <https://bugs.webkit.org/show_bug.cgi?id=57904> We need to keep track of the mouse down event in the case where we
835    // display a popup menu for select elements. When the user changes the selected item,
836    // we fake a mouse up event by using this stored down event. This event gets cleared
837    // when the mouse up message is received from WebProcess.
838    if (event.type() == WebEvent::MouseDown)
839        m_currentlyProcessedMouseDownEvent = adoptPtr(new NativeWebMouseEvent(event));
840
841    process()->send(Messages::WebPage::MouseEvent(event), m_pageID);
842}
843
844static PassOwnPtr<WebWheelEvent> coalesceWheelEvents(WebWheelEvent* oldNextWheelEvent, const WebWheelEvent& newWheelEvent)
845{
846#if MERGE_WHEEL_EVENTS
847    // Merge model: Combine wheel event deltas (and wheel ticks) into a single wheel event.
848    if (!oldNextWheelEvent)
849        return adoptPtr(new WebWheelEvent(newWheelEvent));
850
851    if (oldNextWheelEvent->position() != newWheelEvent.position() || oldNextWheelEvent->modifiers() != newWheelEvent.modifiers() || oldNextWheelEvent->granularity() != newWheelEvent.granularity())
852        return adoptPtr(new WebWheelEvent(newWheelEvent));
853
854    FloatSize mergedDelta = oldNextWheelEvent->delta() + newWheelEvent.delta();
855    FloatSize mergedWheelTicks = oldNextWheelEvent->wheelTicks() + newWheelEvent.wheelTicks();
856
857    return adoptPtr(new WebWheelEvent(WebEvent::Wheel, newWheelEvent.position(), newWheelEvent.globalPosition(), mergedDelta, mergedWheelTicks, newWheelEvent.granularity(), newWheelEvent.modifiers(), newWheelEvent.timestamp()));
858#else
859    // Simple model: Just keep the last event, dropping all interim events.
860    return adoptPtr(new WebWheelEvent(newWheelEvent));
861#endif
862}
863
864void WebPageProxy::handleWheelEvent(const WebWheelEvent& event)
865{
866    if (!isValid())
867        return;
868
869    if (m_processingWheelEvent) {
870        m_nextWheelEvent = coalesceWheelEvents(m_nextWheelEvent.get(), event);
871        return;
872    }
873
874    process()->responsivenessTimer()->start();
875    process()->send(Messages::WebPage::WheelEvent(event), m_pageID);
876    m_processingWheelEvent = true;
877}
878
879void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
880{
881    if (!isValid())
882        return;
883
884    m_keyEventQueue.append(event);
885
886    process()->responsivenessTimer()->start();
887    process()->send(Messages::WebPage::KeyEvent(event), m_pageID);
888}
889
890#if ENABLE(GESTURE_EVENTS)
891void WebPageProxy::handleGestureEvent(const WebGestureEvent& event)
892{
893    if (!isValid())
894        return;
895
896    process()->responsivenessTimer()->start();
897    process()->send(Messages::WebPage::GestureEvent(event), m_pageID);
898}
899#endif
900
901#if ENABLE(TOUCH_EVENTS)
902void WebPageProxy::handleTouchEvent(const WebTouchEvent& event)
903{
904    if (!isValid())
905        return;
906    process()->send(Messages::WebPage::TouchEvent(event), m_pageID);
907}
908#endif
909
910void WebPageProxy::scrollBy(ScrollDirection direction, ScrollGranularity granularity)
911{
912    if (!isValid())
913        return;
914
915    process()->send(Messages::WebPage::ScrollBy(direction, granularity), m_pageID);
916}
917
918void WebPageProxy::receivedPolicyDecision(PolicyAction action, WebFrameProxy* frame, uint64_t listenerID)
919{
920    if (!isValid())
921        return;
922
923    uint64_t downloadID = 0;
924    if (action == PolicyDownload) {
925        // Create a download proxy.
926        downloadID = m_process->context()->createDownloadProxy()->downloadID();
927    }
928
929    // If we received a policy decision while in decidePolicyForMIMEType the decision will
930    // be sent back to the web process by decidePolicyForMIMEType.
931    if (m_inDecidePolicyForMIMEType) {
932        m_syncMimeTypePolicyActionIsValid = true;
933        m_syncMimeTypePolicyAction = action;
934        m_syncMimeTypePolicyDownloadID = downloadID;
935        return;
936    }
937
938    // If we received a policy decision while in decidePolicyForNavigationAction the decision will
939    // be sent back to the web process by decidePolicyForNavigationAction.
940    if (m_inDecidePolicyForNavigationAction) {
941        m_syncNavigationActionPolicyActionIsValid = true;
942        m_syncNavigationActionPolicyAction = action;
943        m_syncNavigationActionPolicyDownloadID = downloadID;
944        return;
945    }
946
947    process()->send(Messages::WebPage::DidReceivePolicyDecision(frame->frameID(), listenerID, action, downloadID), m_pageID);
948}
949
950String WebPageProxy::pageTitle() const
951{
952    // Return the null string if there is no main frame (e.g. nothing has been loaded in the page yet, WebProcess has
953    // crashed, page has been closed).
954    if (!m_mainFrame)
955        return String();
956
957    return m_mainFrame->title();
958}
959
960void WebPageProxy::setUserAgent(const String& userAgent)
961{
962    if (m_userAgent == userAgent)
963        return;
964    m_userAgent = userAgent;
965
966    if (!isValid())
967        return;
968    process()->send(Messages::WebPage::SetUserAgent(m_userAgent), m_pageID);
969}
970
971void WebPageProxy::setApplicationNameForUserAgent(const String& applicationName)
972{
973    if (m_applicationNameForUserAgent == applicationName)
974        return;
975
976    m_applicationNameForUserAgent = applicationName;
977    if (!m_customUserAgent.isEmpty())
978        return;
979
980    setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
981}
982
983void WebPageProxy::setCustomUserAgent(const String& customUserAgent)
984{
985    if (m_customUserAgent == customUserAgent)
986        return;
987
988    m_customUserAgent = customUserAgent;
989
990    if (m_customUserAgent.isEmpty()) {
991        setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
992        return;
993    }
994
995    setUserAgent(m_customUserAgent);
996}
997
998bool WebPageProxy::supportsTextEncoding() const
999{
1000    return !m_mainFrameHasCustomRepresentation && m_mainFrame && !m_mainFrame->isDisplayingStandaloneImageDocument();
1001}
1002
1003void WebPageProxy::setCustomTextEncodingName(const String& encodingName)
1004{
1005    if (m_customTextEncodingName == encodingName)
1006        return;
1007    m_customTextEncodingName = encodingName;
1008
1009    if (!isValid())
1010        return;
1011    process()->send(Messages::WebPage::SetCustomTextEncodingName(encodingName), m_pageID);
1012}
1013
1014void WebPageProxy::terminateProcess()
1015{
1016    if (!isValid())
1017        return;
1018
1019    process()->terminate();
1020}
1021
1022#if !USE(CF) || defined(BUILDING_QT__)
1023PassRefPtr<WebData> WebPageProxy::sessionStateData(WebPageProxySessionStateFilterCallback, void* context) const
1024{
1025    // FIXME: Return session state data for saving Page state.
1026    return 0;
1027}
1028
1029void WebPageProxy::restoreFromSessionStateData(WebData*)
1030{
1031    // FIXME: Restore the Page from the passed in session state data.
1032}
1033#endif
1034
1035bool WebPageProxy::supportsTextZoom() const
1036{
1037    if (m_mainFrameHasCustomRepresentation)
1038        return false;
1039
1040    // FIXME: This should also return false for standalone media and plug-in documents.
1041    if (!m_mainFrame || m_mainFrame->isDisplayingStandaloneImageDocument())
1042        return false;
1043
1044    return true;
1045}
1046
1047void WebPageProxy::setTextZoomFactor(double zoomFactor)
1048{
1049    if (!isValid())
1050        return;
1051
1052    if (m_mainFrameHasCustomRepresentation)
1053        return;
1054
1055    if (m_textZoomFactor == zoomFactor)
1056        return;
1057
1058    m_textZoomFactor = zoomFactor;
1059    process()->send(Messages::WebPage::SetTextZoomFactor(m_textZoomFactor), m_pageID);
1060}
1061
1062double WebPageProxy::pageZoomFactor() const
1063{
1064    return m_mainFrameHasCustomRepresentation ? m_pageClient->customRepresentationZoomFactor() : m_pageZoomFactor;
1065}
1066
1067void WebPageProxy::setPageZoomFactor(double zoomFactor)
1068{
1069    if (!isValid())
1070        return;
1071
1072    if (m_mainFrameHasCustomRepresentation) {
1073        m_pageClient->setCustomRepresentationZoomFactor(zoomFactor);
1074        return;
1075    }
1076
1077    if (m_pageZoomFactor == zoomFactor)
1078        return;
1079
1080    m_pageZoomFactor = zoomFactor;
1081    process()->send(Messages::WebPage::SetPageZoomFactor(m_pageZoomFactor), m_pageID);
1082}
1083
1084void WebPageProxy::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
1085{
1086    if (!isValid())
1087        return;
1088
1089    if (m_mainFrameHasCustomRepresentation) {
1090        m_pageClient->setCustomRepresentationZoomFactor(pageZoomFactor);
1091        return;
1092    }
1093
1094    if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
1095        return;
1096
1097    m_pageZoomFactor = pageZoomFactor;
1098    m_textZoomFactor = textZoomFactor;
1099    process()->send(Messages::WebPage::SetPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor), m_pageID);
1100}
1101
1102void WebPageProxy::scaleWebView(double scale, const IntPoint& origin)
1103{
1104    if (!isValid())
1105        return;
1106
1107    process()->send(Messages::WebPage::ScaleWebView(scale, origin), m_pageID);
1108}
1109
1110void WebPageProxy::setUseFixedLayout(bool fixed)
1111{
1112    if (!isValid())
1113        return;
1114
1115    if (fixed == m_useFixedLayout)
1116        return;
1117
1118    m_useFixedLayout = fixed;
1119    if (!fixed)
1120        m_fixedLayoutSize = IntSize();
1121    process()->send(Messages::WebPage::SetUseFixedLayout(fixed), m_pageID);
1122}
1123
1124void WebPageProxy::setFixedLayoutSize(const IntSize& size)
1125{
1126    if (!isValid())
1127        return;
1128
1129    if (size == m_fixedLayoutSize)
1130        return;
1131
1132    m_fixedLayoutSize = size;
1133    process()->send(Messages::WebPage::SetFixedLayoutSize(size), m_pageID);
1134}
1135
1136void WebPageProxy::viewScaleFactorDidChange(double scaleFactor)
1137{
1138    m_viewScaleFactor = scaleFactor;
1139}
1140
1141void WebPageProxy::setMemoryCacheClientCallsEnabled(bool memoryCacheClientCallsEnabled)
1142{
1143    if (!isValid())
1144        return;
1145
1146    if (m_areMemoryCacheClientCallsEnabled == memoryCacheClientCallsEnabled)
1147        return;
1148
1149    m_areMemoryCacheClientCallsEnabled = memoryCacheClientCallsEnabled;
1150    process()->send(Messages::WebPage::SetMemoryCacheMessagesEnabled(memoryCacheClientCallsEnabled), m_pageID);
1151}
1152
1153void WebPageProxy::findString(const String& string, FindOptions options, unsigned maxMatchCount)
1154{
1155    if (m_mainFrameHasCustomRepresentation)
1156        m_pageClient->findStringInCustomRepresentation(string, options, maxMatchCount);
1157    else
1158        process()->send(Messages::WebPage::FindString(string, options, maxMatchCount), m_pageID);
1159}
1160
1161void WebPageProxy::hideFindUI()
1162{
1163    process()->send(Messages::WebPage::HideFindUI(), m_pageID);
1164}
1165
1166void WebPageProxy::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
1167{
1168    if (m_mainFrameHasCustomRepresentation) {
1169        m_pageClient->countStringMatchesInCustomRepresentation(string, options, maxMatchCount);
1170        return;
1171    }
1172
1173    if (!isValid())
1174        return;
1175
1176    process()->send(Messages::WebPage::CountStringMatches(string, options, maxMatchCount), m_pageID);
1177}
1178
1179void WebPageProxy::runJavaScriptInMainFrame(const String& script, PassRefPtr<ScriptValueCallback> prpCallback)
1180{
1181    RefPtr<ScriptValueCallback> callback = prpCallback;
1182    if (!isValid()) {
1183        callback->invalidate();
1184        return;
1185    }
1186
1187    uint64_t callbackID = callback->callbackID();
1188    m_scriptValueCallbacks.set(callbackID, callback.get());
1189    process()->send(Messages::WebPage::RunJavaScriptInMainFrame(script, callbackID), m_pageID);
1190}
1191
1192void WebPageProxy::getRenderTreeExternalRepresentation(PassRefPtr<StringCallback> prpCallback)
1193{
1194    RefPtr<StringCallback> callback = prpCallback;
1195    if (!isValid()) {
1196        callback->invalidate();
1197        return;
1198    }
1199
1200    uint64_t callbackID = callback->callbackID();
1201    m_stringCallbacks.set(callbackID, callback.get());
1202    process()->send(Messages::WebPage::GetRenderTreeExternalRepresentation(callbackID), m_pageID);
1203}
1204
1205void WebPageProxy::getSourceForFrame(WebFrameProxy* frame, PassRefPtr<StringCallback> prpCallback)
1206{
1207    RefPtr<StringCallback> callback = prpCallback;
1208    if (!isValid()) {
1209        callback->invalidate();
1210        return;
1211    }
1212
1213    uint64_t callbackID = callback->callbackID();
1214    m_loadDependentStringCallbackIDs.add(callbackID);
1215    m_stringCallbacks.set(callbackID, callback.get());
1216    process()->send(Messages::WebPage::GetSourceForFrame(frame->frameID(), callbackID), m_pageID);
1217}
1218
1219void WebPageProxy::getContentsAsString(PassRefPtr<StringCallback> prpCallback)
1220{
1221    RefPtr<StringCallback> callback = prpCallback;
1222    if (!isValid()) {
1223        callback->invalidate();
1224        return;
1225    }
1226
1227    uint64_t callbackID = callback->callbackID();
1228    m_loadDependentStringCallbackIDs.add(callbackID);
1229    m_stringCallbacks.set(callbackID, callback.get());
1230    process()->send(Messages::WebPage::GetContentsAsString(callbackID), m_pageID);
1231}
1232
1233void WebPageProxy::getSelectionOrContentsAsString(PassRefPtr<StringCallback> prpCallback)
1234{
1235    RefPtr<StringCallback> callback = prpCallback;
1236    if (!isValid()) {
1237        callback->invalidate();
1238        return;
1239    }
1240
1241    uint64_t callbackID = callback->callbackID();
1242    m_stringCallbacks.set(callbackID, callback.get());
1243    process()->send(Messages::WebPage::GetSelectionOrContentsAsString(callbackID), m_pageID);
1244}
1245
1246void WebPageProxy::getMainResourceDataOfFrame(WebFrameProxy* frame, PassRefPtr<DataCallback> prpCallback)
1247{
1248    RefPtr<DataCallback> callback = prpCallback;
1249    if (!isValid()) {
1250        callback->invalidate();
1251        return;
1252    }
1253
1254    uint64_t callbackID = callback->callbackID();
1255    m_dataCallbacks.set(callbackID, callback.get());
1256    process()->send(Messages::WebPage::GetMainResourceDataOfFrame(frame->frameID(), callbackID), m_pageID);
1257}
1258
1259void WebPageProxy::getResourceDataFromFrame(WebFrameProxy* frame, WebURL* resourceURL, PassRefPtr<DataCallback> prpCallback)
1260{
1261    RefPtr<DataCallback> callback = prpCallback;
1262    if (!isValid()) {
1263        callback->invalidate();
1264        return;
1265    }
1266
1267    uint64_t callbackID = callback->callbackID();
1268    m_dataCallbacks.set(callbackID, callback.get());
1269    process()->send(Messages::WebPage::GetResourceDataFromFrame(frame->frameID(), resourceURL->string(), callbackID), m_pageID);
1270}
1271
1272void WebPageProxy::getWebArchiveOfFrame(WebFrameProxy* frame, PassRefPtr<DataCallback> prpCallback)
1273{
1274    RefPtr<DataCallback> callback = prpCallback;
1275    if (!isValid()) {
1276        callback->invalidate();
1277        return;
1278    }
1279
1280    uint64_t callbackID = callback->callbackID();
1281    m_dataCallbacks.set(callbackID, callback.get());
1282    process()->send(Messages::WebPage::GetWebArchiveOfFrame(frame->frameID(), callbackID), m_pageID);
1283}
1284
1285void WebPageProxy::forceRepaint(PassRefPtr<VoidCallback> prpCallback)
1286{
1287    RefPtr<VoidCallback> callback = prpCallback;
1288    if (!isValid()) {
1289        callback->invalidate();
1290        return;
1291    }
1292
1293    uint64_t callbackID = callback->callbackID();
1294    m_voidCallbacks.set(callbackID, callback.get());
1295    process()->send(Messages::WebPage::ForceRepaint(callbackID), m_pageID);
1296}
1297
1298void WebPageProxy::preferencesDidChange()
1299{
1300    if (!isValid())
1301        return;
1302
1303    // FIXME: It probably makes more sense to send individual preference changes.
1304    // However, WebKitTestRunner depends on getting a preference change notification
1305    // even if nothing changed in UI process, so that overrides get removed.
1306
1307    // Preferences need to be updated during synchronous printing to make "print backgrounds" preference work when toggled from a print dialog checkbox.
1308    process()->send(Messages::WebPage::PreferencesDidChange(pageGroup()->preferences()->store()), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0);
1309}
1310
1311#if ENABLE(TILED_BACKING_STORE)
1312void WebPageProxy::setResizesToContentsUsingLayoutSize(const WebCore::IntSize& targetLayoutSize)
1313{
1314    process()->send(Messages::WebPage::SetResizesToContentsUsingLayoutSize(targetLayoutSize), m_pageID);
1315}
1316#endif
1317
1318void WebPageProxy::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
1319{
1320#if PLATFORM(MAC) || PLATFORM(WIN)
1321    if (messageID.is<CoreIPC::MessageClassDrawingAreaProxy>()) {
1322        m_drawingArea->didReceiveDrawingAreaProxyMessage(connection, messageID, arguments);
1323        return;
1324    }
1325#endif
1326
1327    if (messageID.is<CoreIPC::MessageClassDrawingAreaProxyLegacy>()) {
1328        m_drawingArea->didReceiveMessage(connection, messageID, arguments);
1329        return;
1330    }
1331
1332#if ENABLE(INSPECTOR)
1333    if (messageID.is<CoreIPC::MessageClassWebInspectorProxy>()) {
1334        if (WebInspectorProxy* inspector = this->inspector())
1335            inspector->didReceiveWebInspectorProxyMessage(connection, messageID, arguments);
1336        return;
1337    }
1338#endif
1339
1340#if ENABLE(FULLSCREEN_API)
1341    if (messageID.is<CoreIPC::MessageClassWebFullScreenManagerProxy>()) {
1342        fullScreenManager()->didReceiveMessage(connection, messageID, arguments);
1343        return;
1344    }
1345#endif
1346
1347    didReceiveWebPageProxyMessage(connection, messageID, arguments);
1348}
1349
1350void WebPageProxy::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, CoreIPC::ArgumentEncoder* reply)
1351{
1352#if ENABLE(INSPECTOR)
1353    if (messageID.is<CoreIPC::MessageClassWebInspectorProxy>()) {
1354        if (WebInspectorProxy* inspector = this->inspector())
1355            inspector->didReceiveSyncWebInspectorProxyMessage(connection, messageID, arguments, reply);
1356        return;
1357    }
1358#endif
1359
1360#if ENABLE(FULLSCREEN_API)
1361    if (messageID.is<CoreIPC::MessageClassWebFullScreenManagerProxy>()) {
1362        fullScreenManager()->didReceiveSyncMessage(connection, messageID, arguments, reply);
1363        return;
1364    }
1365#endif
1366
1367    // FIXME: Do something with reply.
1368    didReceiveSyncWebPageProxyMessage(connection, messageID, arguments, reply);
1369}
1370
1371void WebPageProxy::didCreateMainFrame(uint64_t frameID)
1372{
1373    MESSAGE_CHECK(!m_mainFrame);
1374    MESSAGE_CHECK(process()->canCreateFrame(frameID));
1375
1376    m_mainFrame = WebFrameProxy::create(this, frameID);
1377
1378    // Add the frame to the process wide map.
1379    process()->frameCreated(frameID, m_mainFrame.get());
1380}
1381
1382void WebPageProxy::didCreateSubframe(uint64_t frameID, uint64_t parentFrameID)
1383{
1384    MESSAGE_CHECK(m_mainFrame);
1385
1386    WebFrameProxy* parentFrame = process()->webFrame(parentFrameID);
1387    MESSAGE_CHECK(parentFrame);
1388    MESSAGE_CHECK(parentFrame->isDescendantOf(m_mainFrame.get()));
1389
1390    MESSAGE_CHECK(process()->canCreateFrame(frameID));
1391
1392    RefPtr<WebFrameProxy> subFrame = WebFrameProxy::create(this, frameID);
1393
1394    // Add the frame to the process wide map.
1395    process()->frameCreated(frameID, subFrame.get());
1396
1397    // Insert the frame into the frame hierarchy.
1398    parentFrame->appendChild(subFrame.get());
1399}
1400
1401static bool isDisconnectedFrame(WebFrameProxy* frame)
1402{
1403    return !frame->page() || !frame->page()->mainFrame() || !frame->isDescendantOf(frame->page()->mainFrame());
1404}
1405
1406void WebPageProxy::didSaveFrameToPageCache(uint64_t frameID)
1407{
1408    MESSAGE_CHECK(m_mainFrame);
1409
1410    WebFrameProxy* subframe = process()->webFrame(frameID);
1411    MESSAGE_CHECK(subframe);
1412
1413    if (isDisconnectedFrame(subframe))
1414        return;
1415
1416    MESSAGE_CHECK(subframe->isDescendantOf(m_mainFrame.get()));
1417
1418    subframe->didRemoveFromHierarchy();
1419}
1420
1421void WebPageProxy::didRestoreFrameFromPageCache(uint64_t frameID, uint64_t parentFrameID)
1422{
1423    MESSAGE_CHECK(m_mainFrame);
1424
1425    WebFrameProxy* subframe = process()->webFrame(frameID);
1426    MESSAGE_CHECK(subframe);
1427    MESSAGE_CHECK(!subframe->parentFrame());
1428    MESSAGE_CHECK(subframe->page() == m_mainFrame->page());
1429
1430    WebFrameProxy* parentFrame = process()->webFrame(parentFrameID);
1431    MESSAGE_CHECK(parentFrame);
1432    MESSAGE_CHECK(parentFrame->isDescendantOf(m_mainFrame.get()));
1433
1434    // Insert the frame into the frame hierarchy.
1435    parentFrame->appendChild(subframe);
1436}
1437
1438
1439// Always start progress at initialProgressValue. This helps provide feedback as
1440// soon as a load starts.
1441
1442static const double initialProgressValue = 0.1;
1443
1444double WebPageProxy::estimatedProgress() const
1445{
1446    if (!pendingAPIRequestURL().isNull())
1447        return initialProgressValue;
1448    return m_estimatedProgress;
1449}
1450
1451void WebPageProxy::didStartProgress()
1452{
1453    m_estimatedProgress = initialProgressValue;
1454
1455    m_loaderClient.didStartProgress(this);
1456}
1457
1458void WebPageProxy::didChangeProgress(double value)
1459{
1460    m_estimatedProgress = value;
1461
1462    m_loaderClient.didChangeProgress(this);
1463}
1464
1465void WebPageProxy::didFinishProgress()
1466{
1467    m_estimatedProgress = 1.0;
1468
1469    m_loaderClient.didFinishProgress(this);
1470}
1471
1472void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, const String& url, const String& unreachableURL, CoreIPC::ArgumentDecoder* arguments)
1473{
1474    clearPendingAPIRequestURL();
1475
1476    RefPtr<APIObject> userData;
1477    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1478    if (!arguments->decode(messageDecoder))
1479        return;
1480
1481    WebFrameProxy* frame = process()->webFrame(frameID);
1482    MESSAGE_CHECK(frame);
1483
1484    frame->setUnreachableURL(unreachableURL);
1485
1486    frame->didStartProvisionalLoad(url);
1487    m_loaderClient.didStartProvisionalLoadForFrame(this, frame, userData.get());
1488}
1489
1490void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, const String& url, CoreIPC::ArgumentDecoder* arguments)
1491{
1492    RefPtr<APIObject> userData;
1493    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1494    if (!arguments->decode(messageDecoder))
1495        return;
1496
1497    WebFrameProxy* frame = process()->webFrame(frameID);
1498    MESSAGE_CHECK(frame);
1499
1500    frame->didReceiveServerRedirectForProvisionalLoad(url);
1501
1502    m_loaderClient.didReceiveServerRedirectForProvisionalLoadForFrame(this, frame, userData.get());
1503}
1504
1505void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const ResourceError& error, CoreIPC::ArgumentDecoder* arguments)
1506{
1507    RefPtr<APIObject> userData;
1508    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1509    if (!arguments->decode(messageDecoder))
1510        return;
1511
1512    WebFrameProxy* frame = process()->webFrame(frameID);
1513    MESSAGE_CHECK(frame);
1514
1515    frame->didFailProvisionalLoad();
1516
1517    m_loaderClient.didFailProvisionalLoadWithErrorForFrame(this, frame, error, userData.get());
1518}
1519
1520void WebPageProxy::clearLoadDependentCallbacks()
1521{
1522    Vector<uint64_t> callbackIDsCopy;
1523    copyToVector(m_loadDependentStringCallbackIDs, callbackIDsCopy);
1524    m_loadDependentStringCallbackIDs.clear();
1525
1526    for (size_t i = 0; i < callbackIDsCopy.size(); ++i) {
1527        RefPtr<StringCallback> callback = m_stringCallbacks.take(callbackIDsCopy[i]);
1528        if (callback)
1529            callback->invalidate();
1530    }
1531}
1532
1533void WebPageProxy::didCommitLoadForFrame(uint64_t frameID, const String& mimeType, bool frameHasCustomRepresentation, const PlatformCertificateInfo& certificateInfo, CoreIPC::ArgumentDecoder* arguments)
1534{
1535    RefPtr<APIObject> userData;
1536    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1537    if (!arguments->decode(messageDecoder))
1538        return;
1539
1540#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD)
1541    dismissCorrectionPanel(ReasonForDismissingCorrectionPanelIgnored);
1542    m_pageClient->dismissDictionaryLookupPanel();
1543#endif
1544
1545    WebFrameProxy* frame = process()->webFrame(frameID);
1546    MESSAGE_CHECK(frame);
1547
1548    clearLoadDependentCallbacks();
1549
1550    frame->didCommitLoad(mimeType, certificateInfo);
1551
1552    if (frame->isMainFrame()) {
1553        m_mainFrameHasCustomRepresentation = frameHasCustomRepresentation;
1554        m_pageClient->didCommitLoadForMainFrame(frameHasCustomRepresentation);
1555    }
1556
1557    m_loaderClient.didCommitLoadForFrame(this, frame, userData.get());
1558}
1559
1560void WebPageProxy::didFinishDocumentLoadForFrame(uint64_t frameID, CoreIPC::ArgumentDecoder* arguments)
1561{
1562    RefPtr<APIObject> userData;
1563    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1564    if (!arguments->decode(messageDecoder))
1565        return;
1566
1567    WebFrameProxy* frame = process()->webFrame(frameID);
1568    MESSAGE_CHECK(frame);
1569
1570    m_loaderClient.didFinishDocumentLoadForFrame(this, frame, userData.get());
1571}
1572
1573void WebPageProxy::didFinishLoadForFrame(uint64_t frameID, CoreIPC::ArgumentDecoder* arguments)
1574{
1575    RefPtr<APIObject> userData;
1576    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1577    if (!arguments->decode(messageDecoder))
1578        return;
1579
1580    WebFrameProxy* frame = process()->webFrame(frameID);
1581    MESSAGE_CHECK(frame);
1582
1583    frame->didFinishLoad();
1584
1585    m_loaderClient.didFinishLoadForFrame(this, frame, userData.get());
1586}
1587
1588void WebPageProxy::didFailLoadForFrame(uint64_t frameID, const ResourceError& error, CoreIPC::ArgumentDecoder* arguments)
1589{
1590    RefPtr<APIObject> userData;
1591    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1592    if (!arguments->decode(messageDecoder))
1593        return;
1594
1595    WebFrameProxy* frame = process()->webFrame(frameID);
1596    MESSAGE_CHECK(frame);
1597
1598    clearLoadDependentCallbacks();
1599
1600    frame->didFailLoad();
1601
1602    m_loaderClient.didFailLoadWithErrorForFrame(this, frame, error, userData.get());
1603}
1604
1605void WebPageProxy::didSameDocumentNavigationForFrame(uint64_t frameID, uint32_t opaqueSameDocumentNavigationType, const String& url, CoreIPC::ArgumentDecoder* arguments)
1606{
1607    RefPtr<APIObject> userData;
1608    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1609    if (!arguments->decode(messageDecoder))
1610        return;
1611
1612    WebFrameProxy* frame = process()->webFrame(frameID);
1613    MESSAGE_CHECK(frame);
1614
1615    frame->didSameDocumentNavigation(url);
1616
1617    m_loaderClient.didSameDocumentNavigationForFrame(this, frame, static_cast<SameDocumentNavigationType>(opaqueSameDocumentNavigationType), userData.get());
1618}
1619
1620void WebPageProxy::didReceiveTitleForFrame(uint64_t frameID, const String& title, CoreIPC::ArgumentDecoder* arguments)
1621{
1622    RefPtr<APIObject> userData;
1623    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1624    if (!arguments->decode(messageDecoder))
1625        return;
1626
1627    WebFrameProxy* frame = process()->webFrame(frameID);
1628    MESSAGE_CHECK(frame);
1629
1630    frame->didChangeTitle(title);
1631
1632    m_loaderClient.didReceiveTitleForFrame(this, title, frame, userData.get());
1633}
1634
1635void WebPageProxy::didFirstLayoutForFrame(uint64_t frameID, CoreIPC::ArgumentDecoder* arguments)
1636{
1637    RefPtr<APIObject> userData;
1638    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1639    if (!arguments->decode(messageDecoder))
1640        return;
1641
1642    WebFrameProxy* frame = process()->webFrame(frameID);
1643    MESSAGE_CHECK(frame);
1644
1645    m_loaderClient.didFirstLayoutForFrame(this, frame, userData.get());
1646}
1647
1648void WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame(uint64_t frameID, CoreIPC::ArgumentDecoder* arguments)
1649{
1650    RefPtr<APIObject> userData;
1651    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1652    if (!arguments->decode(messageDecoder))
1653        return;
1654
1655    WebFrameProxy* frame = process()->webFrame(frameID);
1656    MESSAGE_CHECK(frame);
1657
1658    m_loaderClient.didFirstVisuallyNonEmptyLayoutForFrame(this, frame, userData.get());
1659}
1660
1661void WebPageProxy::didRemoveFrameFromHierarchy(uint64_t frameID, CoreIPC::ArgumentDecoder* arguments)
1662{
1663    RefPtr<APIObject> userData;
1664    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1665    if (!arguments->decode(messageDecoder))
1666        return;
1667
1668    WebFrameProxy* frame = process()->webFrame(frameID);
1669    MESSAGE_CHECK(frame);
1670
1671    frame->didRemoveFromHierarchy();
1672
1673    m_loaderClient.didRemoveFrameFromHierarchy(this, frame, userData.get());
1674}
1675
1676void WebPageProxy::didDisplayInsecureContentForFrame(uint64_t frameID, CoreIPC::ArgumentDecoder* arguments)
1677{
1678    RefPtr<APIObject> userData;
1679    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1680    if (!arguments->decode(messageDecoder))
1681        return;
1682
1683    WebFrameProxy* frame = process()->webFrame(frameID);
1684    MESSAGE_CHECK(frame);
1685
1686    m_loaderClient.didDisplayInsecureContentForFrame(this, frame, userData.get());
1687}
1688
1689void WebPageProxy::didRunInsecureContentForFrame(uint64_t frameID, CoreIPC::ArgumentDecoder* arguments)
1690{
1691    RefPtr<APIObject> userData;
1692    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1693    if (!arguments->decode(messageDecoder))
1694        return;
1695
1696    WebFrameProxy* frame = process()->webFrame(frameID);
1697    MESSAGE_CHECK(frame);
1698
1699    m_loaderClient.didRunInsecureContentForFrame(this, frame, userData.get());
1700}
1701
1702void WebPageProxy::frameDidBecomeFrameSet(uint64_t frameID, bool value)
1703{
1704    WebFrameProxy* frame = process()->webFrame(frameID);
1705    MESSAGE_CHECK(frame);
1706
1707    frame->setIsFrameSet(value);
1708    if (frame->isMainFrame())
1709        m_frameSetLargestFrame = value ? m_mainFrame : 0;
1710}
1711
1712// PolicyClient
1713void WebPageProxy::decidePolicyForNavigationAction(uint64_t frameID, uint32_t opaqueNavigationType, uint32_t opaqueModifiers, int32_t opaqueMouseButton, const ResourceRequest& request, uint64_t listenerID, CoreIPC::ArgumentDecoder* arguments, bool& receivedPolicyAction, uint64_t& policyAction, uint64_t& downloadID)
1714{
1715    RefPtr<APIObject> userData;
1716    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1717    if (!arguments->decode(messageDecoder))
1718        return;
1719
1720    if (request.url() != pendingAPIRequestURL())
1721        clearPendingAPIRequestURL();
1722
1723    WebFrameProxy* frame = process()->webFrame(frameID);
1724    MESSAGE_CHECK(frame);
1725
1726    NavigationType navigationType = static_cast<NavigationType>(opaqueNavigationType);
1727    WebEvent::Modifiers modifiers = static_cast<WebEvent::Modifiers>(opaqueModifiers);
1728    WebMouseEvent::Button mouseButton = static_cast<WebMouseEvent::Button>(opaqueMouseButton);
1729
1730    RefPtr<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
1731
1732    ASSERT(!m_inDecidePolicyForNavigationAction);
1733
1734    m_inDecidePolicyForNavigationAction = true;
1735    m_syncNavigationActionPolicyActionIsValid = false;
1736
1737    if (!m_policyClient.decidePolicyForNavigationAction(this, frame, navigationType, modifiers, mouseButton, request, listener.get(), userData.get()))
1738        listener->use();
1739
1740    m_inDecidePolicyForNavigationAction = false;
1741
1742    // Check if we received a policy decision already. If we did, we can just pass it back.
1743    receivedPolicyAction = m_syncNavigationActionPolicyActionIsValid;
1744    if (m_syncNavigationActionPolicyActionIsValid) {
1745        policyAction = m_syncNavigationActionPolicyAction;
1746        downloadID = m_syncNavigationActionPolicyDownloadID;
1747    }
1748}
1749
1750void WebPageProxy::decidePolicyForNewWindowAction(uint64_t frameID, uint32_t opaqueNavigationType, uint32_t opaqueModifiers, int32_t opaqueMouseButton, const ResourceRequest& request, const String& frameName, uint64_t listenerID, CoreIPC::ArgumentDecoder* arguments)
1751{
1752    RefPtr<APIObject> userData;
1753    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1754    if (!arguments->decode(messageDecoder))
1755        return;
1756
1757    WebFrameProxy* frame = process()->webFrame(frameID);
1758    MESSAGE_CHECK(frame);
1759
1760    NavigationType navigationType = static_cast<NavigationType>(opaqueNavigationType);
1761    WebEvent::Modifiers modifiers = static_cast<WebEvent::Modifiers>(opaqueModifiers);
1762    WebMouseEvent::Button mouseButton = static_cast<WebMouseEvent::Button>(opaqueMouseButton);
1763
1764    RefPtr<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
1765    if (!m_policyClient.decidePolicyForNewWindowAction(this, frame, navigationType, modifiers, mouseButton, request, frameName, listener.get(), userData.get()))
1766        listener->use();
1767}
1768
1769void WebPageProxy::decidePolicyForResponse(uint64_t frameID, const ResourceResponse& response, const ResourceRequest& request, uint64_t listenerID, CoreIPC::ArgumentDecoder* arguments, bool& receivedPolicyAction, uint64_t& policyAction, uint64_t& downloadID)
1770{
1771    RefPtr<APIObject> userData;
1772    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1773    if (!arguments->decode(messageDecoder))
1774        return;
1775
1776    WebFrameProxy* frame = process()->webFrame(frameID);
1777    MESSAGE_CHECK(frame);
1778
1779    RefPtr<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
1780
1781    ASSERT(!m_inDecidePolicyForMIMEType);
1782
1783    m_inDecidePolicyForMIMEType = true;
1784    m_syncMimeTypePolicyActionIsValid = false;
1785
1786    if (!m_policyClient.decidePolicyForResponse(this, frame, response, request, listener.get(), userData.get()))
1787        listener->use();
1788
1789    m_inDecidePolicyForMIMEType = false;
1790
1791    // Check if we received a policy decision already. If we did, we can just pass it back.
1792    receivedPolicyAction = m_syncMimeTypePolicyActionIsValid;
1793    if (m_syncMimeTypePolicyActionIsValid) {
1794        policyAction = m_syncMimeTypePolicyAction;
1795        downloadID = m_syncMimeTypePolicyDownloadID;
1796    }
1797}
1798
1799void WebPageProxy::unableToImplementPolicy(uint64_t frameID, const WebCore::ResourceError& error, CoreIPC::ArgumentDecoder* arguments)
1800{
1801    RefPtr<APIObject> userData;
1802    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1803    if (!arguments->decode(messageDecoder))
1804        return;
1805
1806    WebFrameProxy* frame = process()->webFrame(frameID);
1807    MESSAGE_CHECK(frame);
1808
1809    m_policyClient.unableToImplementPolicy(this, frame, error, userData.get());
1810}
1811
1812// FormClient
1813
1814void WebPageProxy::willSubmitForm(uint64_t frameID, uint64_t sourceFrameID, const StringPairVector& textFieldValues, uint64_t listenerID, CoreIPC::ArgumentDecoder* arguments)
1815{
1816    RefPtr<APIObject> userData;
1817    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1818    if (!arguments->decode(messageDecoder))
1819        return;
1820
1821    WebFrameProxy* frame = process()->webFrame(frameID);
1822    MESSAGE_CHECK(frame);
1823
1824    WebFrameProxy* sourceFrame = process()->webFrame(sourceFrameID);
1825    MESSAGE_CHECK(sourceFrame);
1826
1827    RefPtr<WebFormSubmissionListenerProxy> listener = frame->setUpFormSubmissionListenerProxy(listenerID);
1828    if (!m_formClient.willSubmitForm(this, frame, sourceFrame, textFieldValues.stringPairVector(), userData.get(), listener.get()))
1829        listener->continueSubmission();
1830}
1831
1832// ResourceLoad Client
1833
1834void WebPageProxy::didInitiateLoadForResource(uint64_t frameID, uint64_t resourceIdentifier, const ResourceRequest& request, bool pageIsProvisionallyLoading)
1835{
1836    WebFrameProxy* frame = process()->webFrame(frameID);
1837    MESSAGE_CHECK(frame);
1838
1839    m_resourceLoadClient.didInitiateLoadForResource(this, frame, resourceIdentifier, request, pageIsProvisionallyLoading);
1840}
1841
1842void WebPageProxy::didSendRequestForResource(uint64_t frameID, uint64_t resourceIdentifier, const ResourceRequest& request, const ResourceResponse& redirectResponse)
1843{
1844    WebFrameProxy* frame = process()->webFrame(frameID);
1845    MESSAGE_CHECK(frame);
1846
1847    m_resourceLoadClient.didSendRequestForResource(this, frame, resourceIdentifier, request, redirectResponse);
1848}
1849
1850void WebPageProxy::didReceiveResponseForResource(uint64_t frameID, uint64_t resourceIdentifier, const ResourceResponse& response)
1851{
1852    WebFrameProxy* frame = process()->webFrame(frameID);
1853    MESSAGE_CHECK(frame);
1854
1855    m_resourceLoadClient.didReceiveResponseForResource(this, frame, resourceIdentifier, response);
1856}
1857
1858void WebPageProxy::didReceiveContentLengthForResource(uint64_t frameID, uint64_t resourceIdentifier, uint64_t contentLength)
1859{
1860    WebFrameProxy* frame = process()->webFrame(frameID);
1861    MESSAGE_CHECK(frame);
1862
1863    m_resourceLoadClient.didReceiveContentLengthForResource(this, frame, resourceIdentifier, contentLength);
1864}
1865
1866void WebPageProxy::didFinishLoadForResource(uint64_t frameID, uint64_t resourceIdentifier)
1867{
1868    WebFrameProxy* frame = process()->webFrame(frameID);
1869    MESSAGE_CHECK(frame);
1870
1871    m_resourceLoadClient.didFinishLoadForResource(this, frame, resourceIdentifier);
1872}
1873
1874void WebPageProxy::didFailLoadForResource(uint64_t frameID, uint64_t resourceIdentifier, const ResourceError& error)
1875{
1876    WebFrameProxy* frame = process()->webFrame(frameID);
1877    MESSAGE_CHECK(frame);
1878
1879    m_resourceLoadClient.didFailLoadForResource(this, frame, resourceIdentifier, error);
1880}
1881
1882// UIClient
1883
1884void WebPageProxy::createNewPage(const WindowFeatures& windowFeatures, uint32_t opaqueModifiers, int32_t opaqueMouseButton, uint64_t& newPageID, WebPageCreationParameters& newPageParameters)
1885{
1886    RefPtr<WebPageProxy> newPage = m_uiClient.createNewPage(this, windowFeatures, static_cast<WebEvent::Modifiers>(opaqueModifiers), static_cast<WebMouseEvent::Button>(opaqueMouseButton));
1887    if (newPage) {
1888        newPageID = newPage->pageID();
1889        newPageParameters = newPage->creationParameters();
1890    } else
1891        newPageID = 0;
1892}
1893
1894void WebPageProxy::showPage()
1895{
1896    m_uiClient.showPage(this);
1897}
1898
1899void WebPageProxy::closePage()
1900{
1901    m_uiClient.close(this);
1902}
1903
1904void WebPageProxy::runJavaScriptAlert(uint64_t frameID, const String& message)
1905{
1906    WebFrameProxy* frame = process()->webFrame(frameID);
1907    MESSAGE_CHECK(frame);
1908
1909    // Since runJavaScriptAlert() can spin a nested run loop we need to turn off the responsiveness timer.
1910    process()->responsivenessTimer()->stop();
1911
1912    m_uiClient.runJavaScriptAlert(this, message, frame);
1913}
1914
1915void WebPageProxy::runJavaScriptConfirm(uint64_t frameID, const String& message, bool& result)
1916{
1917    WebFrameProxy* frame = process()->webFrame(frameID);
1918    MESSAGE_CHECK(frame);
1919
1920    // Since runJavaScriptConfirm() can spin a nested run loop we need to turn off the responsiveness timer.
1921    process()->responsivenessTimer()->stop();
1922
1923    result = m_uiClient.runJavaScriptConfirm(this, message, frame);
1924}
1925
1926void WebPageProxy::runJavaScriptPrompt(uint64_t frameID, const String& message, const String& defaultValue, String& result)
1927{
1928    WebFrameProxy* frame = process()->webFrame(frameID);
1929    MESSAGE_CHECK(frame);
1930
1931    // Since runJavaScriptPrompt() can spin a nested run loop we need to turn off the responsiveness timer.
1932    process()->responsivenessTimer()->stop();
1933
1934    result = m_uiClient.runJavaScriptPrompt(this, message, defaultValue, frame);
1935}
1936
1937void WebPageProxy::setStatusText(const String& text)
1938{
1939    m_uiClient.setStatusText(this, text);
1940}
1941
1942void WebPageProxy::mouseDidMoveOverElement(uint32_t opaqueModifiers, CoreIPC::ArgumentDecoder* arguments)
1943{
1944    RefPtr<APIObject> userData;
1945    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
1946    if (!arguments->decode(messageDecoder))
1947        return;
1948
1949    WebEvent::Modifiers modifiers = static_cast<WebEvent::Modifiers>(opaqueModifiers);
1950
1951    m_uiClient.mouseDidMoveOverElement(this, modifiers, userData.get());
1952}
1953
1954void WebPageProxy::missingPluginButtonClicked(const String& mimeType, const String& url, const String& pluginsPageURL)
1955{
1956    m_uiClient.missingPluginButtonClicked(this, mimeType, url, pluginsPageURL);
1957}
1958
1959void WebPageProxy::setToolbarsAreVisible(bool toolbarsAreVisible)
1960{
1961    m_uiClient.setToolbarsAreVisible(this, toolbarsAreVisible);
1962}
1963
1964void WebPageProxy::getToolbarsAreVisible(bool& toolbarsAreVisible)
1965{
1966    toolbarsAreVisible = m_uiClient.toolbarsAreVisible(this);
1967}
1968
1969void WebPageProxy::setMenuBarIsVisible(bool menuBarIsVisible)
1970{
1971    m_uiClient.setMenuBarIsVisible(this, menuBarIsVisible);
1972}
1973
1974void WebPageProxy::getMenuBarIsVisible(bool& menuBarIsVisible)
1975{
1976    menuBarIsVisible = m_uiClient.menuBarIsVisible(this);
1977}
1978
1979void WebPageProxy::setStatusBarIsVisible(bool statusBarIsVisible)
1980{
1981    m_uiClient.setStatusBarIsVisible(this, statusBarIsVisible);
1982}
1983
1984void WebPageProxy::getStatusBarIsVisible(bool& statusBarIsVisible)
1985{
1986    statusBarIsVisible = m_uiClient.statusBarIsVisible(this);
1987}
1988
1989void WebPageProxy::setIsResizable(bool isResizable)
1990{
1991    m_uiClient.setIsResizable(this, isResizable);
1992}
1993
1994void WebPageProxy::getIsResizable(bool& isResizable)
1995{
1996    isResizable = m_uiClient.isResizable(this);
1997}
1998
1999void WebPageProxy::setWindowFrame(const FloatRect& newWindowFrame)
2000{
2001    m_uiClient.setWindowFrame(this, m_pageClient->convertToDeviceSpace(newWindowFrame));
2002}
2003
2004void WebPageProxy::getWindowFrame(FloatRect& newWindowFrame)
2005{
2006    newWindowFrame = m_pageClient->convertToUserSpace(m_uiClient.windowFrame(this));
2007}
2008
2009void WebPageProxy::windowToScreen(const IntRect& viewRect, IntRect& result)
2010{
2011    result = m_pageClient->windowToScreen(viewRect);
2012}
2013
2014void WebPageProxy::runBeforeUnloadConfirmPanel(const String& message, uint64_t frameID, bool& shouldClose)
2015{
2016    WebFrameProxy* frame = process()->webFrame(frameID);
2017    MESSAGE_CHECK(frame);
2018
2019    shouldClose = m_uiClient.runBeforeUnloadConfirmPanel(this, message, frame);
2020}
2021
2022#if ENABLE(TILED_BACKING_STORE)
2023void WebPageProxy::pageDidRequestScroll(const IntPoint& point)
2024{
2025    m_pageClient->pageDidRequestScroll(point);
2026}
2027#endif
2028
2029void WebPageProxy::didChangeViewportData(const ViewportArguments& args)
2030{
2031    m_pageClient->setViewportArguments(args);
2032}
2033
2034void WebPageProxy::pageDidScroll()
2035{
2036    m_uiClient.pageDidScroll(this);
2037}
2038
2039void WebPageProxy::runOpenPanel(uint64_t frameID, const WebOpenPanelParameters::Data& data)
2040{
2041    if (m_openPanelResultListener) {
2042        m_openPanelResultListener->invalidate();
2043        m_openPanelResultListener = 0;
2044    }
2045
2046    WebFrameProxy* frame = process()->webFrame(frameID);
2047    MESSAGE_CHECK(frame);
2048
2049    m_openPanelResultListener = WebOpenPanelResultListenerProxy::create(this);
2050
2051    if (!m_uiClient.runOpenPanel(this, frame, data, m_openPanelResultListener.get()))
2052        didCancelForOpenPanel();
2053}
2054
2055void WebPageProxy::printFrame(uint64_t frameID)
2056{
2057    ASSERT(!m_isPerformingDOMPrintOperation);
2058    m_isPerformingDOMPrintOperation = true;
2059
2060    WebFrameProxy* frame = process()->webFrame(frameID);
2061    MESSAGE_CHECK(frame);
2062
2063    m_uiClient.printFrame(this, frame);
2064
2065    m_isPerformingDOMPrintOperation = false;
2066}
2067
2068#if PLATFORM(QT)
2069void WebPageProxy::didChangeContentsSize(const WebCore::IntSize& size)
2070{
2071    m_pageClient->didChangeContentsSize(size);
2072}
2073
2074void WebPageProxy::didFindZoomableArea(const WebCore::IntRect& area)
2075{
2076    m_pageClient->didFindZoomableArea(area);
2077}
2078
2079void WebPageProxy::findZoomableAreaForPoint(const WebCore::IntPoint& point)
2080{
2081    if (!isValid())
2082        return;
2083
2084    process()->send(Messages::WebPage::FindZoomableAreaForPoint(point), m_pageID);
2085}
2086#endif
2087
2088void WebPageProxy::didDraw()
2089{
2090    m_uiClient.didDraw(this);
2091}
2092
2093// Inspector
2094
2095#if ENABLE(INSPECTOR)
2096
2097WebInspectorProxy* WebPageProxy::inspector()
2098{
2099    if (isClosed() || !isValid())
2100        return 0;
2101    if (!m_inspector)
2102        m_inspector = WebInspectorProxy::create(this);
2103    return m_inspector.get();
2104}
2105
2106#endif
2107
2108#if ENABLE(FULLSCREEN_API)
2109WebFullScreenManagerProxy* WebPageProxy::fullScreenManager()
2110{
2111    if (!m_fullScreenManager)
2112        m_fullScreenManager = WebFullScreenManagerProxy::create(this);
2113    return m_fullScreenManager.get();
2114}
2115#endif
2116
2117// BackForwardList
2118
2119void WebPageProxy::backForwardAddItem(uint64_t itemID)
2120{
2121    m_backForwardList->addItem(process()->webBackForwardItem(itemID));
2122}
2123
2124void WebPageProxy::backForwardGoToItem(uint64_t itemID)
2125{
2126    m_backForwardList->goToItem(process()->webBackForwardItem(itemID));
2127}
2128
2129void WebPageProxy::backForwardItemAtIndex(int32_t index, uint64_t& itemID)
2130{
2131    WebBackForwardListItem* item = m_backForwardList->itemAtIndex(index);
2132    itemID = item ? item->itemID() : 0;
2133}
2134
2135void WebPageProxy::backForwardBackListCount(int32_t& count)
2136{
2137    count = m_backForwardList->backListCount();
2138}
2139
2140void WebPageProxy::backForwardForwardListCount(int32_t& count)
2141{
2142    count = m_backForwardList->forwardListCount();
2143}
2144
2145void WebPageProxy::editorStateChanged(const EditorState& editorState)
2146{
2147#if PLATFORM(MAC)
2148    bool couldChangeSecureInputState = m_editorState.isInPasswordField != editorState.isInPasswordField || m_editorState.selectionIsNone;
2149#endif
2150
2151    m_editorState = editorState;
2152
2153#if PLATFORM(MAC)
2154    // This is a temporary state. Flipping secure input state too quickly can expose race conditions.
2155    if (editorState.selectionIsNone)
2156        return;
2157
2158    if (couldChangeSecureInputState)
2159        m_pageClient->updateSecureInputState();
2160#endif
2161}
2162
2163#if PLATFORM(WIN)
2164void WebPageProxy::didChangeCompositionSelection(bool hasComposition)
2165{
2166    m_pageClient->compositionSelectionChanged(hasComposition);
2167}
2168
2169void WebPageProxy::confirmComposition(const String& compositionString)
2170{
2171    process()->send(Messages::WebPage::ConfirmComposition(compositionString), m_pageID);
2172}
2173
2174void WebPageProxy::setComposition(const String& compositionString, Vector<WebCore::CompositionUnderline>& underlines, int cursorPosition)
2175{
2176    process()->send(Messages::WebPage::SetComposition(compositionString, underlines, cursorPosition), m_pageID);
2177}
2178#endif
2179
2180// Undo management
2181
2182void WebPageProxy::registerEditCommandForUndo(uint64_t commandID, uint32_t editAction)
2183{
2184    registerEditCommand(WebEditCommandProxy::create(commandID, static_cast<EditAction>(editAction), this), Undo);
2185}
2186
2187void WebPageProxy::canUndoRedo(uint32_t action, bool& result)
2188{
2189    result = m_pageClient->canUndoRedo(static_cast<UndoOrRedo>(action));
2190}
2191
2192void WebPageProxy::executeUndoRedo(uint32_t action, bool& result)
2193{
2194    m_pageClient->executeUndoRedo(static_cast<UndoOrRedo>(action));
2195    result = true;
2196}
2197
2198void WebPageProxy::clearAllEditCommands()
2199{
2200    m_pageClient->clearAllEditCommands();
2201}
2202
2203void WebPageProxy::didCountStringMatches(const String& string, uint32_t matchCount)
2204{
2205    m_findClient.didCountStringMatches(this, string, matchCount);
2206}
2207
2208void WebPageProxy::setFindIndicator(const FloatRect& selectionRectInWindowCoordinates, const Vector<FloatRect>& textRectsInSelectionRectCoordinates, const ShareableBitmap::Handle& contentImageHandle, bool fadeOut)
2209{
2210    RefPtr<FindIndicator> findIndicator = FindIndicator::create(selectionRectInWindowCoordinates, textRectsInSelectionRectCoordinates, contentImageHandle);
2211    m_pageClient->setFindIndicator(findIndicator.release(), fadeOut);
2212}
2213
2214void WebPageProxy::didFindString(const String& string, uint32_t matchCount)
2215{
2216    m_findClient.didFindString(this, string, matchCount);
2217}
2218
2219void WebPageProxy::didFailToFindString(const String& string)
2220{
2221    m_findClient.didFailToFindString(this, string);
2222}
2223
2224void WebPageProxy::valueChangedForPopupMenu(WebPopupMenuProxy*, int32_t newSelectedIndex)
2225{
2226    process()->send(Messages::WebPage::DidChangeSelectedIndexForActivePopupMenu(newSelectedIndex), m_pageID);
2227}
2228
2229void WebPageProxy::setTextFromItemForPopupMenu(WebPopupMenuProxy*, int32_t index)
2230{
2231    process()->send(Messages::WebPage::SetTextForActivePopupMenu(index), m_pageID);
2232}
2233
2234NativeWebMouseEvent* WebPageProxy::currentlyProcessedMouseDownEvent()
2235{
2236    return m_currentlyProcessedMouseDownEvent.get();
2237}
2238
2239void WebPageProxy::showPopupMenu(const IntRect& rect, uint64_t textDirection, const Vector<WebPopupItem>& items, int32_t selectedIndex, const PlatformPopupMenuData& data)
2240{
2241    if (m_activePopupMenu) {
2242        m_activePopupMenu->hidePopupMenu();
2243        m_activePopupMenu->invalidate();
2244        m_activePopupMenu = 0;
2245    }
2246
2247    m_activePopupMenu = m_pageClient->createPopupMenuProxy(this);
2248
2249    // Since showPopupMenu() can spin a nested run loop we need to turn off the responsiveness timer.
2250    process()->responsivenessTimer()->stop();
2251
2252    RefPtr<WebPopupMenuProxy> protectedActivePopupMenu = m_activePopupMenu;
2253
2254    protectedActivePopupMenu->showPopupMenu(rect, static_cast<TextDirection>(textDirection), m_viewScaleFactor, items, data, selectedIndex);
2255    protectedActivePopupMenu->invalidate();
2256    protectedActivePopupMenu = 0;
2257}
2258
2259void WebPageProxy::hidePopupMenu()
2260{
2261    if (!m_activePopupMenu)
2262        return;
2263
2264    m_activePopupMenu->hidePopupMenu();
2265    m_activePopupMenu->invalidate();
2266    m_activePopupMenu = 0;
2267}
2268
2269void WebPageProxy::showContextMenu(const IntPoint& menuLocation, const ContextMenuState& contextMenuState, const Vector<WebContextMenuItemData>& proposedItems, CoreIPC::ArgumentDecoder* arguments)
2270{
2271    internalShowContextMenu(menuLocation, contextMenuState, proposedItems, arguments);
2272
2273    // No matter the result of internalShowContextMenu, always notify the WebProcess that the menu is hidden so it starts handling mouse events again.
2274    process()->send(Messages::WebPage::ContextMenuHidden(), m_pageID);
2275}
2276
2277void WebPageProxy::internalShowContextMenu(const IntPoint& menuLocation, const ContextMenuState& contextMenuState, const Vector<WebContextMenuItemData>& proposedItems, CoreIPC::ArgumentDecoder* arguments)
2278{
2279    RefPtr<APIObject> userData;
2280    WebContextUserMessageDecoder messageDecoder(userData, m_process->context());
2281    if (!arguments->decode(messageDecoder))
2282        return;
2283
2284    m_activeContextMenuState = contextMenuState;
2285
2286    if (m_activeContextMenu) {
2287        m_activeContextMenu->hideContextMenu();
2288        m_activeContextMenu = 0;
2289    }
2290
2291    m_activeContextMenu = m_pageClient->createContextMenuProxy(this);
2292
2293    // Since showContextMenu() can spin a nested run loop we need to turn off the responsiveness timer.
2294    process()->responsivenessTimer()->stop();
2295
2296    // Give the PageContextMenuClient one last swipe at changing the menu.
2297    Vector<WebContextMenuItemData> items;
2298    if (!m_contextMenuClient.getContextMenuFromProposedMenu(this, proposedItems, items, userData.get()))
2299        m_activeContextMenu->showContextMenu(menuLocation, proposedItems);
2300    else
2301        m_activeContextMenu->showContextMenu(menuLocation, items);
2302}
2303
2304void WebPageProxy::contextMenuItemSelected(const WebContextMenuItemData& item)
2305{
2306    // Application custom items don't need to round-trip through to WebCore in the WebProcess.
2307    if (item.action() >= ContextMenuItemBaseApplicationTag) {
2308        m_contextMenuClient.customContextMenuItemSelected(this, item);
2309        return;
2310    }
2311
2312#if PLATFORM(MAC)
2313    if (item.action() == ContextMenuItemTagSmartCopyPaste) {
2314        setSmartInsertDeleteEnabled(!isSmartInsertDeleteEnabled());
2315        return;
2316    }
2317    if (item.action() == ContextMenuItemTagSmartQuotes) {
2318        TextChecker::setAutomaticQuoteSubstitutionEnabled(!TextChecker::state().isAutomaticQuoteSubstitutionEnabled);
2319        process()->updateTextCheckerState();
2320        return;
2321    }
2322    if (item.action() == ContextMenuItemTagSmartDashes) {
2323        TextChecker::setAutomaticDashSubstitutionEnabled(!TextChecker::state().isAutomaticDashSubstitutionEnabled);
2324        process()->updateTextCheckerState();
2325        return;
2326    }
2327    if (item.action() == ContextMenuItemTagSmartLinks) {
2328        TextChecker::setAutomaticLinkDetectionEnabled(!TextChecker::state().isAutomaticLinkDetectionEnabled);
2329        process()->updateTextCheckerState();
2330        return;
2331    }
2332    if (item.action() == ContextMenuItemTagTextReplacement) {
2333        TextChecker::setAutomaticTextReplacementEnabled(!TextChecker::state().isAutomaticTextReplacementEnabled);
2334        process()->updateTextCheckerState();
2335        return;
2336    }
2337    if (item.action() == ContextMenuItemTagCorrectSpellingAutomatically) {
2338        TextChecker::setAutomaticSpellingCorrectionEnabled(!TextChecker::state().isAutomaticSpellingCorrectionEnabled);
2339        process()->updateTextCheckerState();
2340        return;
2341    }
2342    if (item.action() == ContextMenuItemTagShowSubstitutions) {
2343        TextChecker::toggleSubstitutionsPanelIsShowing();
2344        return;
2345    }
2346#endif
2347    if (item.action() == ContextMenuItemTagDownloadImageToDisk) {
2348        m_process->context()->download(this, KURL(KURL(), m_activeContextMenuState.absoluteImageURLString));
2349        return;
2350    }
2351    if (item.action() == ContextMenuItemTagDownloadLinkToDisk) {
2352        m_process->context()->download(this, KURL(KURL(), m_activeContextMenuState.absoluteLinkURLString));
2353        return;
2354    }
2355    if (item.action() == ContextMenuItemTagCheckSpellingWhileTyping) {
2356        TextChecker::setContinuousSpellCheckingEnabled(!TextChecker::state().isContinuousSpellCheckingEnabled);
2357        process()->updateTextCheckerState();
2358        return;
2359    }
2360    if (item.action() == ContextMenuItemTagCheckGrammarWithSpelling) {
2361        TextChecker::setGrammarCheckingEnabled(!TextChecker::state().isGrammarCheckingEnabled);
2362        process()->updateTextCheckerState();
2363        return;
2364    }
2365    if (item.action() == ContextMenuItemTagShowSpellingPanel) {
2366        if (!TextChecker::spellingUIIsShowing())
2367            advanceToNextMisspelling(true);
2368        TextChecker::toggleSpellingUIIsShowing();
2369        return;
2370    }
2371    if (item.action() == ContextMenuItemTagLearnSpelling || item.action() == ContextMenuItemTagIgnoreSpelling)
2372        ++m_pendingLearnOrIgnoreWordMessageCount;
2373
2374    process()->send(Messages::WebPage::DidSelectItemFromActiveContextMenu(item), m_pageID);
2375}
2376
2377void WebPageProxy::didChooseFilesForOpenPanel(const Vector<String>& fileURLs)
2378{
2379    if (!isValid())
2380        return;
2381
2382#if ENABLE(WEB_PROCESS_SANDBOX)
2383    // FIXME: The sandbox extensions should be sent with the DidChooseFilesForOpenPanel message. This
2384    // is gated on a way of passing SandboxExtension::Handles in a Vector.
2385    for (size_t i = 0; i < fileURLs.size(); ++i) {
2386        SandboxExtension::Handle sandboxExtensionHandle;
2387        SandboxExtension::createHandle(fileURLs[i], SandboxExtension::ReadOnly, sandboxExtensionHandle);
2388        process()->send(Messages::WebPage::ExtendSandboxForFileFromOpenPanel(sandboxExtensionHandle), m_pageID);
2389    }
2390#endif
2391
2392    process()->send(Messages::WebPage::DidChooseFilesForOpenPanel(fileURLs), m_pageID);
2393
2394    m_openPanelResultListener->invalidate();
2395    m_openPanelResultListener = 0;
2396}
2397
2398void WebPageProxy::didCancelForOpenPanel()
2399{
2400    if (!isValid())
2401        return;
2402
2403    process()->send(Messages::WebPage::DidCancelForOpenPanel(), m_pageID);
2404
2405    m_openPanelResultListener->invalidate();
2406    m_openPanelResultListener = 0;
2407}
2408
2409void WebPageProxy::advanceToNextMisspelling(bool startBeforeSelection) const
2410{
2411    process()->send(Messages::WebPage::AdvanceToNextMisspelling(startBeforeSelection), m_pageID);
2412}
2413
2414void WebPageProxy::changeSpellingToWord(const String& word) const
2415{
2416    if (word.isEmpty())
2417        return;
2418
2419    process()->send(Messages::WebPage::ChangeSpellingToWord(word), m_pageID);
2420}
2421
2422void WebPageProxy::registerEditCommand(PassRefPtr<WebEditCommandProxy> commandProxy, UndoOrRedo undoOrRedo)
2423{
2424    m_pageClient->registerEditCommand(commandProxy, undoOrRedo);
2425}
2426
2427void WebPageProxy::addEditCommand(WebEditCommandProxy* command)
2428{
2429    m_editCommandSet.add(command);
2430}
2431
2432void WebPageProxy::removeEditCommand(WebEditCommandProxy* command)
2433{
2434    m_editCommandSet.remove(command);
2435
2436    if (!isValid())
2437        return;
2438    process()->send(Messages::WebPage::DidRemoveEditCommand(command->commandID()), m_pageID);
2439}
2440
2441bool WebPageProxy::isValidEditCommand(WebEditCommandProxy* command)
2442{
2443    return m_editCommandSet.find(command) != m_editCommandSet.end();
2444}
2445
2446int64_t WebPageProxy::spellDocumentTag()
2447{
2448    if (!m_hasSpellDocumentTag) {
2449        m_spellDocumentTag = TextChecker::uniqueSpellDocumentTag(this);
2450        m_hasSpellDocumentTag = true;
2451    }
2452
2453    return m_spellDocumentTag;
2454}
2455
2456#if USE(UNIFIED_TEXT_CHECKING)
2457
2458void WebPageProxy::checkTextOfParagraph(const String& text, uint64_t checkingTypes, Vector<TextCheckingResult>& results)
2459{
2460    results = TextChecker::checkTextOfParagraph(spellDocumentTag(), text.characters(), text.length(), checkingTypes);
2461}
2462
2463#endif
2464
2465void WebPageProxy::checkSpellingOfString(const String& text, int32_t& misspellingLocation, int32_t& misspellingLength)
2466{
2467    TextChecker::checkSpellingOfString(spellDocumentTag(), text.characters(), text.length(), misspellingLocation, misspellingLength);
2468}
2469
2470void WebPageProxy::checkGrammarOfString(const String& text, Vector<WebCore::GrammarDetail>& grammarDetails, int32_t& badGrammarLocation, int32_t& badGrammarLength)
2471{
2472    TextChecker::checkGrammarOfString(spellDocumentTag(), text.characters(), text.length(), grammarDetails, badGrammarLocation, badGrammarLength);
2473}
2474
2475void WebPageProxy::spellingUIIsShowing(bool& isShowing)
2476{
2477    isShowing = TextChecker::spellingUIIsShowing();
2478}
2479
2480void WebPageProxy::updateSpellingUIWithMisspelledWord(const String& misspelledWord)
2481{
2482    TextChecker::updateSpellingUIWithMisspelledWord(spellDocumentTag(), misspelledWord);
2483}
2484
2485void WebPageProxy::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail)
2486{
2487    TextChecker::updateSpellingUIWithGrammarString(spellDocumentTag(), badGrammarPhrase, grammarDetail);
2488}
2489
2490void WebPageProxy::getGuessesForWord(const String& word, const String& context, Vector<String>& guesses)
2491{
2492    TextChecker::getGuessesForWord(spellDocumentTag(), word, context, guesses);
2493}
2494
2495void WebPageProxy::learnWord(const String& word)
2496{
2497    MESSAGE_CHECK(m_pendingLearnOrIgnoreWordMessageCount);
2498    --m_pendingLearnOrIgnoreWordMessageCount;
2499
2500    TextChecker::learnWord(spellDocumentTag(), word);
2501}
2502
2503void WebPageProxy::ignoreWord(const String& word)
2504{
2505    MESSAGE_CHECK(m_pendingLearnOrIgnoreWordMessageCount);
2506    --m_pendingLearnOrIgnoreWordMessageCount;
2507
2508    TextChecker::ignoreWord(spellDocumentTag(), word);
2509}
2510
2511// Other
2512
2513void WebPageProxy::setFocus(bool focused)
2514{
2515    if (focused)
2516        m_uiClient.focus(this);
2517    else
2518        m_uiClient.unfocus(this);
2519}
2520
2521void WebPageProxy::takeFocus(uint32_t direction)
2522{
2523    m_uiClient.takeFocus(this, (static_cast<FocusDirection>(direction) == FocusDirectionForward) ? kWKFocusDirectionForward : kWKFocusDirectionBackward);
2524}
2525
2526void WebPageProxy::setToolTip(const String& toolTip)
2527{
2528    String oldToolTip = m_toolTip;
2529    m_toolTip = toolTip;
2530    m_pageClient->toolTipChanged(oldToolTip, m_toolTip);
2531}
2532
2533void WebPageProxy::setCursor(const WebCore::Cursor& cursor)
2534{
2535    m_pageClient->setCursor(cursor);
2536}
2537
2538void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
2539{
2540    WebEvent::Type type = static_cast<WebEvent::Type>(opaqueType);
2541
2542    switch (type) {
2543    case WebEvent::NoType:
2544    case WebEvent::MouseMove:
2545        break;
2546
2547    case WebEvent::MouseDown:
2548    case WebEvent::MouseUp:
2549    case WebEvent::Wheel:
2550    case WebEvent::KeyDown:
2551    case WebEvent::KeyUp:
2552    case WebEvent::RawKeyDown:
2553    case WebEvent::Char:
2554#if ENABLE(GESTURE_EVENTS)
2555    case WebEvent::GestureScrollBegin:
2556    case WebEvent::GestureScrollEnd:
2557#endif
2558        process()->responsivenessTimer()->stop();
2559        break;
2560    }
2561
2562    switch (type) {
2563    case WebEvent::NoType:
2564        break;
2565    case WebEvent::MouseMove:
2566        m_processingMouseMoveEvent = false;
2567        if (m_nextMouseMoveEvent) {
2568            handleMouseEvent(*m_nextMouseMoveEvent);
2569            m_nextMouseMoveEvent = nullptr;
2570        }
2571        break;
2572    case WebEvent::MouseDown:
2573#if ENABLE(GESTURE_EVENTS)
2574    case WebEvent::GestureScrollBegin:
2575    case WebEvent::GestureScrollEnd:
2576#endif
2577        break;
2578    case WebEvent::MouseUp:
2579        m_currentlyProcessedMouseDownEvent = nullptr;
2580        break;
2581
2582    case WebEvent::Wheel: {
2583        m_processingWheelEvent = false;
2584        if (m_nextWheelEvent) {
2585            handleWheelEvent(*m_nextWheelEvent);
2586            m_nextWheelEvent = nullptr;
2587        }
2588        break;
2589    }
2590
2591    case WebEvent::KeyDown:
2592    case WebEvent::KeyUp:
2593    case WebEvent::RawKeyDown:
2594    case WebEvent::Char: {
2595        NativeWebKeyboardEvent event = m_keyEventQueue.first();
2596        MESSAGE_CHECK(type == event.type());
2597
2598        m_keyEventQueue.removeFirst();
2599
2600        m_pageClient->doneWithKeyEvent(event, handled);
2601
2602        if (handled)
2603            break;
2604
2605        if (m_uiClient.implementsDidNotHandleKeyEvent())
2606            m_uiClient.didNotHandleKeyEvent(this, event);
2607#if PLATFORM(WIN)
2608        else
2609            ::TranslateMessage(event.nativeEvent());
2610#endif
2611        break;
2612    }
2613    }
2614}
2615
2616void WebPageProxy::voidCallback(uint64_t callbackID)
2617{
2618    RefPtr<VoidCallback> callback = m_voidCallbacks.take(callbackID);
2619    if (!callback) {
2620        // FIXME: Log error or assert.
2621        return;
2622    }
2623
2624    callback->performCallback();
2625}
2626
2627void WebPageProxy::dataCallback(const CoreIPC::DataReference& dataReference, uint64_t callbackID)
2628{
2629    RefPtr<DataCallback> callback = m_dataCallbacks.take(callbackID);
2630    if (!callback) {
2631        // FIXME: Log error or assert.
2632        return;
2633    }
2634
2635    callback->performCallbackWithReturnValue(WebData::create(dataReference.data(), dataReference.size()).get());
2636}
2637
2638void WebPageProxy::stringCallback(const String& resultString, uint64_t callbackID)
2639{
2640    RefPtr<StringCallback> callback = m_stringCallbacks.take(callbackID);
2641    if (!callback) {
2642        // FIXME: Log error or assert.
2643        // this can validly happen if a load invalidated the callback, though
2644        return;
2645    }
2646
2647    m_loadDependentStringCallbackIDs.remove(callbackID);
2648
2649    callback->performCallbackWithReturnValue(resultString.impl());
2650}
2651
2652void WebPageProxy::scriptValueCallback(const CoreIPC::DataReference& dataReference, uint64_t callbackID)
2653{
2654    RefPtr<ScriptValueCallback> callback = m_scriptValueCallbacks.take(callbackID);
2655    if (!callback) {
2656        // FIXME: Log error or assert.
2657        return;
2658    }
2659
2660    Vector<uint8_t> data;
2661    data.reserveInitialCapacity(dataReference.size());
2662    data.append(dataReference.data(), dataReference.size());
2663
2664    callback->performCallbackWithReturnValue(data.size() ? WebSerializedScriptValue::adopt(data).get() : 0);
2665}
2666
2667void WebPageProxy::computedPagesCallback(const Vector<WebCore::IntRect>& pageRects, double totalScaleFactorForPrinting, uint64_t callbackID)
2668{
2669    RefPtr<ComputedPagesCallback> callback = m_computedPagesCallbacks.take(callbackID);
2670    if (!callback) {
2671        // FIXME: Log error or assert.
2672        return;
2673    }
2674
2675    callback->performCallbackWithReturnValue(pageRects, totalScaleFactorForPrinting);
2676}
2677
2678void WebPageProxy::validateCommandCallback(const String& commandName, bool isEnabled, int state, uint64_t callbackID)
2679{
2680    RefPtr<ValidateCommandCallback> callback = m_validateCommandCallbacks.take(callbackID);
2681    if (!callback) {
2682        // FIXME: Log error or assert.
2683        return;
2684    }
2685
2686    callback->performCallbackWithReturnValue(commandName.impl(), isEnabled, state);
2687}
2688
2689void WebPageProxy::focusedFrameChanged(uint64_t frameID)
2690{
2691    if (!frameID) {
2692        m_focusedFrame = 0;
2693        return;
2694    }
2695
2696    WebFrameProxy* frame = process()->webFrame(frameID);
2697    MESSAGE_CHECK(frame);
2698
2699    m_focusedFrame = frame;
2700}
2701
2702void WebPageProxy::frameSetLargestFrameChanged(uint64_t frameID)
2703{
2704    if (!frameID) {
2705        m_frameSetLargestFrame = 0;
2706        return;
2707    }
2708
2709    WebFrameProxy* frame = process()->webFrame(frameID);
2710    MESSAGE_CHECK(frame);
2711
2712    m_frameSetLargestFrame = frame;
2713}
2714
2715void WebPageProxy::processDidBecomeUnresponsive()
2716{
2717    m_loaderClient.processDidBecomeUnresponsive(this);
2718}
2719
2720void WebPageProxy::processDidBecomeResponsive()
2721{
2722    m_loaderClient.processDidBecomeResponsive(this);
2723}
2724
2725void WebPageProxy::processDidCrash()
2726{
2727    ASSERT(m_pageClient);
2728
2729    m_isValid = false;
2730
2731    m_mainFrame = nullptr;
2732    m_drawingArea = nullptr;
2733
2734#if ENABLE(INSPECTOR)
2735    if (m_inspector) {
2736        m_inspector->invalidate();
2737        m_inspector = nullptr;
2738    }
2739#endif
2740
2741#if ENABLE(FULLSCREEN_API)
2742    if (m_fullScreenManager) {
2743        m_fullScreenManager->invalidate();
2744        m_fullScreenManager = nullptr;
2745    }
2746#endif
2747
2748    if (m_openPanelResultListener) {
2749        m_openPanelResultListener->invalidate();
2750        m_openPanelResultListener = nullptr;
2751    }
2752
2753    m_geolocationPermissionRequestManager.invalidateRequests();
2754
2755    m_toolTip = String();
2756
2757    m_mainFrameHasHorizontalScrollbar = false;
2758    m_mainFrameHasVerticalScrollbar = false;
2759
2760    m_mainFrameIsPinnedToLeftSide = false;
2761    m_mainFrameIsPinnedToRightSide = false;
2762
2763    invalidateCallbackMap(m_voidCallbacks);
2764    invalidateCallbackMap(m_dataCallbacks);
2765    invalidateCallbackMap(m_stringCallbacks);
2766    m_loadDependentStringCallbackIDs.clear();
2767    invalidateCallbackMap(m_scriptValueCallbacks);
2768    invalidateCallbackMap(m_computedPagesCallbacks);
2769    invalidateCallbackMap(m_validateCommandCallbacks);
2770
2771    Vector<WebEditCommandProxy*> editCommandVector;
2772    copyToVector(m_editCommandSet, editCommandVector);
2773    m_editCommandSet.clear();
2774    for (size_t i = 0, size = editCommandVector.size(); i < size; ++i)
2775        editCommandVector[i]->invalidate();
2776    m_pageClient->clearAllEditCommands();
2777
2778    m_activePopupMenu = 0;
2779
2780    m_estimatedProgress = 0.0;
2781
2782    m_pendingLearnOrIgnoreWordMessageCount = 0;
2783
2784    m_pageClient->processDidCrash();
2785    m_loaderClient.processDidCrash(this);
2786
2787    // Can't expect DidReceiveEvent notifications from a crashed web process.
2788    m_keyEventQueue.clear();
2789    m_nextWheelEvent = nullptr;
2790    m_nextMouseMoveEvent = nullptr;
2791    m_currentlyProcessedMouseDownEvent = nullptr;
2792
2793#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD)
2794    dismissCorrectionPanel(ReasonForDismissingCorrectionPanelIgnored);
2795    m_pageClient->dismissDictionaryLookupPanel();
2796#endif
2797}
2798
2799WebPageCreationParameters WebPageProxy::creationParameters() const
2800{
2801    WebPageCreationParameters parameters;
2802
2803    parameters.viewSize = m_pageClient->viewSize();
2804    parameters.isActive = m_pageClient->isViewWindowActive();
2805    parameters.isFocused = m_pageClient->isViewFocused();
2806    parameters.isVisible = m_pageClient->isViewVisible();
2807    parameters.isInWindow = m_pageClient->isViewInWindow();
2808    parameters.drawingAreaType = m_drawingArea->type();
2809    parameters.store = m_pageGroup->preferences()->store();
2810    parameters.pageGroupData = m_pageGroup->data();
2811    parameters.drawsBackground = m_drawsBackground;
2812    parameters.drawsTransparentBackground = m_drawsTransparentBackground;
2813    parameters.areMemoryCacheClientCallsEnabled = m_areMemoryCacheClientCallsEnabled;
2814    parameters.useFixedLayout = m_useFixedLayout;
2815    parameters.fixedLayoutSize = m_fixedLayoutSize;
2816    parameters.userAgent = userAgent();
2817    parameters.sessionState = SessionState(m_backForwardList->entries(), m_backForwardList->currentIndex());
2818    parameters.highestUsedBackForwardItemID = WebBackForwardListItem::highedUsedItemID();
2819    parameters.canRunBeforeUnloadConfirmPanel = m_uiClient.canRunBeforeUnloadConfirmPanel();
2820    parameters.canRunModal = m_uiClient.canRunModal();
2821    parameters.userSpaceScaleFactor = m_pageClient->userSpaceScaleFactor();
2822
2823#if PLATFORM(MAC)
2824    parameters.isSmartInsertDeleteEnabled = m_isSmartInsertDeleteEnabled;
2825#endif
2826
2827#if PLATFORM(WIN)
2828    parameters.nativeWindow = m_pageClient->nativeWindow();
2829#endif
2830
2831    return parameters;
2832}
2833
2834#if USE(ACCELERATED_COMPOSITING)
2835void WebPageProxy::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
2836{
2837    m_pageClient->enterAcceleratedCompositingMode(layerTreeContext);
2838}
2839
2840void WebPageProxy::exitAcceleratedCompositingMode()
2841{
2842    m_pageClient->exitAcceleratedCompositingMode();
2843}
2844#endif // USE(ACCELERATED_COMPOSITING)
2845
2846void WebPageProxy::backForwardClear()
2847{
2848    m_backForwardList->clear();
2849}
2850
2851void WebPageProxy::canAuthenticateAgainstProtectionSpaceInFrame(uint64_t frameID, const WebCore::ProtectionSpace& coreProtectionSpace, bool& canAuthenticate)
2852{
2853    WebFrameProxy* frame = process()->webFrame(frameID);
2854    MESSAGE_CHECK(frame);
2855
2856    RefPtr<WebProtectionSpace> protectionSpace = WebProtectionSpace::create(coreProtectionSpace);
2857
2858    canAuthenticate = m_loaderClient.canAuthenticateAgainstProtectionSpaceInFrame(this, frame, protectionSpace.get());
2859}
2860
2861void WebPageProxy::didReceiveAuthenticationChallenge(uint64_t frameID, const WebCore::AuthenticationChallenge& coreChallenge, uint64_t challengeID)
2862{
2863    WebFrameProxy* frame = process()->webFrame(frameID);
2864    MESSAGE_CHECK(frame);
2865
2866    RefPtr<AuthenticationChallengeProxy> authenticationChallenge = AuthenticationChallengeProxy::create(coreChallenge, challengeID, process());
2867
2868    m_loaderClient.didReceiveAuthenticationChallengeInFrame(this, frame, authenticationChallenge.get());
2869}
2870
2871void WebPageProxy::exceededDatabaseQuota(uint64_t frameID, const String& originIdentifier, const String& databaseName, const String& displayName, uint64_t currentQuota, uint64_t currentUsage, uint64_t expectedUsage, uint64_t& newQuota)
2872{
2873    WebFrameProxy* frame = process()->webFrame(frameID);
2874    MESSAGE_CHECK(frame);
2875
2876    RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::create(originIdentifier);
2877
2878    newQuota = m_uiClient.exceededDatabaseQuota(this, frame, origin.get(), databaseName, displayName, currentQuota, currentUsage, expectedUsage);
2879}
2880
2881void WebPageProxy::requestGeolocationPermissionForFrame(uint64_t geolocationID, uint64_t frameID, String originIdentifier)
2882{
2883    WebFrameProxy* frame = process()->webFrame(frameID);
2884    MESSAGE_CHECK(frame);
2885
2886    RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::create(originIdentifier);
2887    RefPtr<GeolocationPermissionRequestProxy> request = m_geolocationPermissionRequestManager.createRequest(geolocationID);
2888
2889    if (!m_uiClient.decidePolicyForGeolocationPermissionRequest(this, frame, origin.get(), request.get()))
2890        request->deny();
2891}
2892
2893float WebPageProxy::headerHeight(WebFrameProxy* frame)
2894{
2895    return m_uiClient.headerHeight(this, frame);
2896}
2897
2898float WebPageProxy::footerHeight(WebFrameProxy* frame)
2899{
2900    return m_uiClient.footerHeight(this, frame);
2901}
2902
2903void WebPageProxy::drawHeader(WebFrameProxy* frame, const FloatRect& rect)
2904{
2905    m_uiClient.drawHeader(this, frame, rect);
2906}
2907
2908void WebPageProxy::drawFooter(WebFrameProxy* frame, const FloatRect& rect)
2909{
2910    m_uiClient.drawFooter(this, frame, rect);
2911}
2912
2913void WebPageProxy::didCompleteRubberBandForMainFrame(const IntSize& initialOverhang)
2914{
2915    m_uiClient.didCompleteRubberBandForMainFrame(this, initialOverhang);
2916}
2917
2918void WebPageProxy::didChangeScrollbarsForMainFrame(bool hasHorizontalScrollbar, bool hasVerticalScrollbar)
2919{
2920    m_mainFrameHasHorizontalScrollbar = hasHorizontalScrollbar;
2921    m_mainFrameHasVerticalScrollbar = hasVerticalScrollbar;
2922
2923    m_pageClient->didChangeScrollbarsForMainFrame();
2924}
2925
2926void WebPageProxy::didChangeScrollOffsetPinningForMainFrame(bool pinnedToLeftSide, bool pinnedToRightSide)
2927{
2928    m_mainFrameIsPinnedToLeftSide = pinnedToLeftSide;
2929    m_mainFrameIsPinnedToRightSide = pinnedToRightSide;
2930}
2931
2932void WebPageProxy::didFinishLoadingDataForCustomRepresentation(const String& suggestedFilename, const CoreIPC::DataReference& dataReference)
2933{
2934    m_pageClient->didFinishLoadingDataForCustomRepresentation(suggestedFilename, dataReference);
2935}
2936
2937void WebPageProxy::backForwardRemovedItem(uint64_t itemID)
2938{
2939    process()->send(Messages::WebPage::DidRemoveBackForwardItem(itemID), m_pageID);
2940}
2941
2942void WebPageProxy::beginPrinting(WebFrameProxy* frame, const PrintInfo& printInfo)
2943{
2944    if (m_isInPrintingMode)
2945        return;
2946
2947    m_isInPrintingMode = true;
2948    process()->send(Messages::WebPage::BeginPrinting(frame->frameID(), printInfo), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0);
2949}
2950
2951void WebPageProxy::endPrinting()
2952{
2953    if (!m_isInPrintingMode)
2954        return;
2955
2956    m_isInPrintingMode = false;
2957    process()->send(Messages::WebPage::EndPrinting(), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0);
2958}
2959
2960void WebPageProxy::computePagesForPrinting(WebFrameProxy* frame, const PrintInfo& printInfo, PassRefPtr<ComputedPagesCallback> prpCallback)
2961{
2962    RefPtr<ComputedPagesCallback> callback = prpCallback;
2963    if (!isValid()) {
2964        callback->invalidate();
2965        return;
2966    }
2967
2968    uint64_t callbackID = callback->callbackID();
2969    m_computedPagesCallbacks.set(callbackID, callback.get());
2970    m_isInPrintingMode = true;
2971    process()->send(Messages::WebPage::ComputePagesForPrinting(frame->frameID(), printInfo, callbackID), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0);
2972}
2973
2974#if PLATFORM(MAC) || PLATFORM(WIN)
2975void WebPageProxy::drawRectToPDF(WebFrameProxy* frame, const IntRect& rect, PassRefPtr<DataCallback> prpCallback)
2976{
2977    RefPtr<DataCallback> callback = prpCallback;
2978    if (!isValid()) {
2979        callback->invalidate();
2980        return;
2981    }
2982
2983    uint64_t callbackID = callback->callbackID();
2984    m_dataCallbacks.set(callbackID, callback.get());
2985    process()->send(Messages::WebPage::DrawRectToPDF(frame->frameID(), rect, callbackID), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0);
2986}
2987
2988void WebPageProxy::drawPagesToPDF(WebFrameProxy* frame, uint32_t first, uint32_t count, PassRefPtr<DataCallback> prpCallback)
2989{
2990    RefPtr<DataCallback> callback = prpCallback;
2991    if (!isValid()) {
2992        callback->invalidate();
2993        return;
2994    }
2995
2996    uint64_t callbackID = callback->callbackID();
2997    m_dataCallbacks.set(callbackID, callback.get());
2998    process()->send(Messages::WebPage::DrawPagesToPDF(frame->frameID(), first, count, callbackID), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0);
2999}
3000#endif
3001
3002void WebPageProxy::flashBackingStoreUpdates(const Vector<IntRect>& updateRects)
3003{
3004    m_pageClient->flashBackingStoreUpdates(updateRects);
3005}
3006
3007Color WebPageProxy::viewUpdatesFlashColor()
3008{
3009    return Color(0, 200, 255);
3010}
3011
3012Color WebPageProxy::backingStoreUpdatesFlashColor()
3013{
3014    return Color(200, 0, 255);
3015}
3016
3017void WebPageProxy::saveDataToFileInDownloadsFolder(const String& suggestedFilename, const String& mimeType, const String& originatingURLString, WebData* data)
3018{
3019    m_uiClient.saveDataToFileInDownloadsFolder(this, suggestedFilename, mimeType, originatingURLString, data);
3020}
3021
3022void WebPageProxy::linkClicked(const String& url, const WebMouseEvent& event)
3023{
3024    process()->send(Messages::WebPage::LinkClicked(url, event), m_pageID, 0);
3025}
3026
3027#if PLATFORM(MAC)
3028
3029void WebPageProxy::substitutionsPanelIsShowing(bool& isShowing)
3030{
3031    isShowing = TextChecker::substitutionsPanelIsShowing();
3032}
3033
3034#if !defined(BUILDING_ON_SNOW_LEOPARD)
3035void WebPageProxy::showCorrectionPanel(int32_t panelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
3036{
3037    m_pageClient->showCorrectionPanel((WebCore::CorrectionPanelInfo::PanelType)panelType, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings);
3038}
3039
3040void WebPageProxy::dismissCorrectionPanel(int32_t reason)
3041{
3042    m_pageClient->dismissCorrectionPanel((WebCore::ReasonForDismissingCorrectionPanel)reason);
3043}
3044
3045void WebPageProxy::dismissCorrectionPanelSoon(int32_t reason, String& result)
3046{
3047    result = m_pageClient->dismissCorrectionPanelSoon((WebCore::ReasonForDismissingCorrectionPanel)reason);
3048}
3049
3050void WebPageProxy::recordAutocorrectionResponse(int32_t responseType, const String& replacedString, const String& replacementString)
3051{
3052    m_pageClient->recordAutocorrectionResponse((WebCore::EditorClient::AutocorrectionResponseType)responseType, replacedString, replacementString);
3053}
3054#endif // !defined(BUILDING_ON_SNOW_LEOPARD)
3055
3056void WebPageProxy::handleCorrectionPanelResult(const String& result)
3057{
3058#if !defined(BUILDING_ON_SNOW_LEOPARD)
3059    if (!isClosed())
3060        process()->send(Messages::WebPage::HandleCorrectionPanelResult(result), m_pageID, 0);
3061#endif
3062}
3063#endif // PLATFORM(MAC)
3064
3065} // namespace WebKit
3066