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 "WebPage.h"
28
29#include "Arguments.h"
30#include "DataReference.h"
31#include "DecoderAdapter.h"
32#include "DrawingArea.h"
33#include "InjectedBundle.h"
34#include "InjectedBundleBackForwardList.h"
35#include "LayerTreeHost.h"
36#include "MessageID.h"
37#include "NetscapePlugin.h"
38#include "PageOverlay.h"
39#include "PluginProxy.h"
40#include "PluginView.h"
41#include "PrintInfo.h"
42#include "RunLoop.h"
43#include "SessionState.h"
44#include "ShareableBitmap.h"
45#include "WebBackForwardList.h"
46#include "WebBackForwardListItem.h"
47#include "WebBackForwardListProxy.h"
48#include "WebChromeClient.h"
49#include "WebContextMenu.h"
50#include "WebContextMenuClient.h"
51#include "WebContextMessages.h"
52#include "WebCoreArgumentCoders.h"
53#include "WebDragClient.h"
54#include "WebEditorClient.h"
55#include "WebEvent.h"
56#include "WebEventConversion.h"
57#include "WebFrame.h"
58#include "WebFullScreenManager.h"
59#include "WebGeolocationClient.h"
60#include "WebImage.h"
61#include "WebInspector.h"
62#include "WebInspectorClient.h"
63#include "WebOpenPanelResultListener.h"
64#include "WebPageCreationParameters.h"
65#include "WebPageGroupProxy.h"
66#include "WebPageProxyMessages.h"
67#include "WebPopupMenu.h"
68#include "WebPreferencesStore.h"
69#include "WebProcess.h"
70#include "WebProcessProxyMessages.h"
71#include <JavaScriptCore/APICast.h>
72#include <WebCore/AbstractDatabase.h>
73#include <WebCore/ArchiveResource.h>
74#include <WebCore/Chrome.h>
75#include <WebCore/ContextMenuController.h>
76#include <WebCore/DocumentFragment.h>
77#include <WebCore/DocumentLoader.h>
78#include <WebCore/DocumentMarkerController.h>
79#include <WebCore/DragController.h>
80#include <WebCore/DragData.h>
81#include <WebCore/EditingBehavior.h>
82#include <WebCore/EventHandler.h>
83#include <WebCore/FocusController.h>
84#include <WebCore/FormState.h>
85#include <WebCore/Frame.h>
86#include <WebCore/FrameLoadRequest.h>
87#include <WebCore/FrameLoaderTypes.h>
88#include <WebCore/FrameView.h>
89#include <WebCore/HTMLFormElement.h>
90#include <WebCore/HistoryItem.h>
91#include <WebCore/KeyboardEvent.h>
92#include <WebCore/MouseEvent.h>
93#include <WebCore/Page.h>
94#include <WebCore/PlatformKeyboardEvent.h>
95#include <WebCore/PrintContext.h>
96#include <WebCore/RenderLayer.h>
97#include <WebCore/RenderTreeAsText.h>
98#include <WebCore/RenderView.h>
99#include <WebCore/ReplaceSelectionCommand.h>
100#include <WebCore/ResourceRequest.h>
101#include <WebCore/SchemeRegistry.h>
102#include <WebCore/SerializedScriptValue.h>
103#include <WebCore/Settings.h>
104#include <WebCore/SharedBuffer.h>
105#include <WebCore/SubstituteData.h>
106#include <WebCore/TextIterator.h>
107#include <WebCore/markup.h>
108#include <runtime/JSLock.h>
109#include <runtime/JSValue.h>
110
111#include <WebCore/Range.h>
112#include <WebCore/VisiblePosition.h>
113
114#if PLATFORM(MAC) || PLATFORM(WIN)
115#include <WebCore/LegacyWebArchive.h>
116#endif
117
118#if ENABLE(PLUGIN_PROCESS)
119#if PLATFORM(MAC)
120#include "MachPort.h"
121#endif
122#endif
123
124#if PLATFORM(QT)
125#include "HitTestResult.h"
126#endif
127
128#ifndef NDEBUG
129#include <wtf/RefCountedLeakCounter.h>
130#endif
131
132using namespace JSC;
133using namespace WebCore;
134
135namespace WebKit {
136
137#ifndef NDEBUG
138static WTF::RefCountedLeakCounter webPageCounter("WebPage");
139#endif
140
141PassRefPtr<WebPage> WebPage::create(uint64_t pageID, const WebPageCreationParameters& parameters)
142{
143    RefPtr<WebPage> page = adoptRef(new WebPage(pageID, parameters));
144
145    if (page->pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())
146        WebProcess::shared().injectedBundle()->didCreatePage(page.get());
147
148    return page.release();
149}
150
151WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
152    : m_viewSize(parameters.viewSize)
153    , m_drawsBackground(true)
154    , m_drawsTransparentBackground(false)
155    , m_isInRedo(false)
156    , m_isClosed(false)
157    , m_tabToLinks(false)
158#if PLATFORM(MAC)
159    , m_windowIsVisible(false)
160    , m_isSmartInsertDeleteEnabled(parameters.isSmartInsertDeleteEnabled)
161    , m_keyboardEventBeingInterpreted(0)
162#elif PLATFORM(WIN)
163    , m_nativeWindow(parameters.nativeWindow)
164#endif
165    , m_findController(this)
166    , m_geolocationPermissionRequestManager(this)
167    , m_pageID(pageID)
168    , m_canRunBeforeUnloadConfirmPanel(parameters.canRunBeforeUnloadConfirmPanel)
169    , m_canRunModal(parameters.canRunModal)
170    , m_isRunningModal(false)
171    , m_userSpaceScaleFactor(parameters.userSpaceScaleFactor)
172    , m_cachedMainFrameIsPinnedToLeftSide(false)
173    , m_cachedMainFrameIsPinnedToRightSide(false)
174    , m_isShowingContextMenu(false)
175#if PLATFORM(WIN)
176    , m_gestureReachedScrollingLimit(false)
177#endif
178{
179    ASSERT(m_pageID);
180
181    Page::PageClients pageClients;
182    pageClients.chromeClient = new WebChromeClient(this);
183    pageClients.contextMenuClient = new WebContextMenuClient(this);
184    pageClients.editorClient = new WebEditorClient(this);
185    pageClients.dragClient = new WebDragClient(this);
186    pageClients.backForwardClient = WebBackForwardListProxy::create(this);
187#if ENABLE(CLIENT_BASED_GEOLOCATION)
188    pageClients.geolocationClient = new WebGeolocationClient(this);
189#endif
190#if ENABLE(INSPECTOR)
191    pageClients.inspectorClient = new WebInspectorClient(this);
192#endif
193    m_page = adoptPtr(new Page(pageClients));
194
195    // Qt does not yet call setIsInWindow. Until it does, just leave
196    // this line out so plug-ins and video will work. Eventually all platforms
197    // should call setIsInWindow and this comment and #if should be removed,
198    // leaving behind the setCanStartMedia call.
199#if !PLATFORM(QT)
200    m_page->setCanStartMedia(false);
201#endif
202
203    updatePreferences(parameters.store);
204
205    m_pageGroup = WebProcess::shared().webPageGroup(parameters.pageGroupData);
206    m_page->setGroupName(m_pageGroup->identifier());
207
208    platformInitialize();
209    Settings::setDefaultMinDOMTimerInterval(0.004);
210
211    m_drawingArea = DrawingArea::create(this, parameters);
212    m_mainFrame = WebFrame::createMainFrame(this);
213
214    setDrawsBackground(parameters.drawsBackground);
215    setDrawsTransparentBackground(parameters.drawsTransparentBackground);
216
217    setMemoryCacheMessagesEnabled(parameters.areMemoryCacheClientCallsEnabled);
218
219    setActive(parameters.isActive);
220    setFocused(parameters.isFocused);
221    setIsInWindow(parameters.isInWindow);
222
223    m_userAgent = parameters.userAgent;
224
225    WebBackForwardListProxy::setHighestItemIDFromUIProcess(parameters.highestUsedBackForwardItemID);
226
227    if (!parameters.sessionState.isEmpty())
228        restoreSession(parameters.sessionState);
229
230#ifndef NDEBUG
231    webPageCounter.increment();
232#endif
233}
234
235WebPage::~WebPage()
236{
237    if (m_backForwardList)
238        m_backForwardList->detach();
239
240    ASSERT(!m_page);
241
242    m_sandboxExtensionTracker.invalidate();
243
244#if PLATFORM(MAC)
245    ASSERT(m_pluginViews.isEmpty());
246#endif
247
248#ifndef NDEBUG
249    webPageCounter.decrement();
250#endif
251}
252
253void WebPage::dummy(bool&)
254{
255}
256
257CoreIPC::Connection* WebPage::connection() const
258{
259    return WebProcess::shared().connection();
260}
261
262void WebPage::initializeInjectedBundleContextMenuClient(WKBundlePageContextMenuClient* client)
263{
264    m_contextMenuClient.initialize(client);
265}
266
267void WebPage::initializeInjectedBundleEditorClient(WKBundlePageEditorClient* client)
268{
269    m_editorClient.initialize(client);
270}
271
272void WebPage::initializeInjectedBundleFormClient(WKBundlePageFormClient* client)
273{
274    m_formClient.initialize(client);
275}
276
277void WebPage::initializeInjectedBundleLoaderClient(WKBundlePageLoaderClient* client)
278{
279    m_loaderClient.initialize(client);
280}
281
282void WebPage::initializeInjectedBundlePolicyClient(WKBundlePagePolicyClient* client)
283{
284    m_policyClient.initialize(client);
285}
286
287void WebPage::initializeInjectedBundleResourceLoadClient(WKBundlePageResourceLoadClient* client)
288{
289    m_resourceLoadClient.initialize(client);
290}
291
292void WebPage::initializeInjectedBundleUIClient(WKBundlePageUIClient* client)
293{
294    m_uiClient.initialize(client);
295}
296
297#if ENABLE(FULLSCREEN_API)
298void WebPage::initializeInjectedBundleFullScreenClient(WKBundlePageFullScreenClient* client)
299{
300    m_fullScreenClient.initialize(client);
301}
302#endif
303
304PassRefPtr<Plugin> WebPage::createPlugin(const Plugin::Parameters& parameters)
305{
306    String pluginPath;
307
308    if (!WebProcess::shared().connection()->sendSync(
309            Messages::WebContext::GetPluginPath(parameters.mimeType, parameters.url.string()),
310            Messages::WebContext::GetPluginPath::Reply(pluginPath), 0)) {
311        return 0;
312    }
313
314    if (pluginPath.isNull())
315        return 0;
316
317#if ENABLE(PLUGIN_PROCESS)
318    return PluginProxy::create(pluginPath);
319#else
320    return NetscapePlugin::create(NetscapePluginModule::getOrCreate(pluginPath));
321#endif
322}
323
324EditorState WebPage::editorState() const
325{
326    Frame* frame = m_page->focusController()->focusedOrMainFrame();
327    ASSERT(frame);
328
329    EditorState result;
330    result.selectionIsNone = frame->selection()->isNone();
331    result.selectionIsRange = frame->selection()->isRange();
332    result.isContentEditable = frame->selection()->isContentEditable();
333    result.isContentRichlyEditable = frame->selection()->isContentRichlyEditable();
334    result.isInPasswordField = frame->selection()->isInPasswordField();
335    result.hasComposition = frame->editor()->hasComposition();
336
337    return result;
338}
339
340String WebPage::renderTreeExternalRepresentation() const
341{
342    return externalRepresentation(m_mainFrame->coreFrame(), RenderAsTextBehaviorNormal);
343}
344
345void WebPage::executeEditingCommand(const String& commandName, const String& argument)
346{
347    Frame* frame = m_page->focusController()->focusedOrMainFrame();
348    if (!frame)
349        return;
350    frame->editor()->command(commandName).execute(argument);
351}
352
353bool WebPage::isEditingCommandEnabled(const String& commandName)
354{
355    Frame* frame = m_page->focusController()->focusedOrMainFrame();
356    if (!frame)
357        return false;
358
359    Editor::Command command = frame->editor()->command(commandName);
360    return command.isSupported() && command.isEnabled();
361}
362
363void WebPage::clearMainFrameName()
364{
365    mainFrame()->coreFrame()->tree()->clearName();
366}
367
368#if USE(ACCELERATED_COMPOSITING)
369void WebPage::enterAcceleratedCompositingMode(GraphicsLayer* layer)
370{
371    m_drawingArea->setRootCompositingLayer(layer);
372}
373
374void WebPage::exitAcceleratedCompositingMode()
375{
376    m_drawingArea->setRootCompositingLayer(0);
377}
378#endif
379
380void WebPage::close()
381{
382    if (m_isClosed)
383        return;
384
385    m_isClosed = true;
386
387    if (pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())
388        WebProcess::shared().injectedBundle()->willDestroyPage(this);
389
390#if ENABLE(INSPECTOR)
391    m_inspector = 0;
392#endif
393#if ENABLE(FULLSCREEN_API)
394    m_fullScreenManager = 0;
395#endif
396
397    if (m_activePopupMenu) {
398        m_activePopupMenu->disconnectFromPage();
399        m_activePopupMenu = 0;
400    }
401
402    if (m_activeOpenPanelResultListener) {
403        m_activeOpenPanelResultListener->disconnectFromPage();
404        m_activeOpenPanelResultListener = 0;
405    }
406
407    m_sandboxExtensionTracker.invalidate();
408
409    m_printContext = nullptr;
410
411    m_mainFrame->coreFrame()->loader()->detachFromParent();
412    m_page.clear();
413
414    m_drawingArea.clear();
415
416    bool isRunningModal = m_isRunningModal;
417    m_isRunningModal = false;
418
419    // The WebPage can be destroyed by this call.
420    WebProcess::shared().removeWebPage(m_pageID);
421
422    if (isRunningModal)
423        WebProcess::shared().runLoop()->stop();
424}
425
426void WebPage::tryClose()
427{
428    if (!m_mainFrame->coreFrame()->loader()->shouldClose())
429        return;
430
431    sendClose();
432}
433
434void WebPage::sendClose()
435{
436    send(Messages::WebPageProxy::ClosePage());
437}
438
439void WebPage::loadURL(const String& url, const SandboxExtension::Handle& sandboxExtensionHandle)
440{
441    loadURLRequest(ResourceRequest(KURL(KURL(), url)), sandboxExtensionHandle);
442}
443
444void WebPage::loadURLRequest(const ResourceRequest& request, const SandboxExtension::Handle& sandboxExtensionHandle)
445{
446    m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
447    m_mainFrame->coreFrame()->loader()->load(request, false);
448}
449
450void WebPage::loadData(PassRefPtr<SharedBuffer> sharedBuffer, const String& MIMEType, const String& encodingName, const KURL& baseURL, const KURL& unreachableURL)
451{
452    ResourceRequest request(baseURL);
453    SubstituteData substituteData(sharedBuffer, MIMEType, encodingName, unreachableURL);
454    m_mainFrame->coreFrame()->loader()->load(request, substituteData, false);
455}
456
457void WebPage::loadHTMLString(const String& htmlString, const String& baseURLString)
458{
459    RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar));
460    KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString);
461    loadData(sharedBuffer, "text/html", "utf-16", baseURL, KURL());
462}
463
464void WebPage::loadAlternateHTMLString(const String& htmlString, const String& baseURLString, const String& unreachableURLString)
465{
466    RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar));
467    KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString);
468    KURL unreachableURL = unreachableURLString.isEmpty() ? KURL() : KURL(KURL(), unreachableURLString);
469    loadData(sharedBuffer, "text/html", "utf-16", baseURL, unreachableURL);
470}
471
472void WebPage::loadPlainTextString(const String& string)
473{
474    RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(string.characters()), string.length() * sizeof(UChar));
475    loadData(sharedBuffer, "text/plain", "utf-16", blankURL(), KURL());
476}
477
478void WebPage::linkClicked(const String& url, const WebMouseEvent& event)
479{
480    Frame* frame = m_page->mainFrame();
481    if (!frame)
482        return;
483
484    RefPtr<Event> coreEvent;
485    if (event.type() != WebEvent::NoType)
486        coreEvent = MouseEvent::create(eventNames().clickEvent, frame->document()->defaultView(), platform(event), 0, 0);
487
488    frame->loader()->loadFrameRequest(FrameLoadRequest(frame->document()->securityOrigin(), ResourceRequest(url)),
489        false, false, coreEvent.get(), 0, SendReferrer);
490}
491
492void WebPage::stopLoadingFrame(uint64_t frameID)
493{
494    WebFrame* frame = WebProcess::shared().webFrame(frameID);
495    if (!frame)
496        return;
497
498    frame->coreFrame()->loader()->stopForUserCancel();
499}
500
501void WebPage::stopLoading()
502{
503    m_mainFrame->coreFrame()->loader()->stopForUserCancel();
504}
505
506void WebPage::setDefersLoading(bool defersLoading)
507{
508    m_page->setDefersLoading(defersLoading);
509}
510
511void WebPage::reload(bool reloadFromOrigin)
512{
513    m_mainFrame->coreFrame()->loader()->reload(reloadFromOrigin);
514}
515
516void WebPage::goForward(uint64_t backForwardItemID, const SandboxExtension::Handle& sandboxExtensionHandle)
517{
518    HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
519    ASSERT(item);
520    if (!item)
521        return;
522
523    m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
524    m_page->goToItem(item, FrameLoadTypeForward);
525}
526
527void WebPage::goBack(uint64_t backForwardItemID, const SandboxExtension::Handle& sandboxExtensionHandle)
528{
529    HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
530    ASSERT(item);
531    if (!item)
532        return;
533
534    m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
535    m_page->goToItem(item, FrameLoadTypeBack);
536}
537
538void WebPage::goToBackForwardItem(uint64_t backForwardItemID, const SandboxExtension::Handle& sandboxExtensionHandle)
539{
540    HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
541    ASSERT(item);
542    if (!item)
543        return;
544
545    m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
546    m_page->goToItem(item, FrameLoadTypeIndexedBackForward);
547}
548
549void WebPage::layoutIfNeeded()
550{
551    if (m_mainFrame->coreFrame()->view())
552        m_mainFrame->coreFrame()->view()->updateLayoutAndStyleIfNeededRecursive();
553}
554
555void WebPage::setSize(const WebCore::IntSize& viewSize)
556{
557#if ENABLE(TILED_BACKING_STORE)
558    // If we are resizing to content ignore external attempts.
559    if (!m_resizesToContentsLayoutSize.isEmpty())
560        return;
561#endif
562
563    if (m_viewSize == viewSize)
564        return;
565
566    Frame* frame = m_page->mainFrame();
567
568    frame->view()->resize(viewSize);
569    frame->view()->setNeedsLayout();
570    m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), viewSize));
571
572    m_viewSize = viewSize;
573}
574
575#if ENABLE(TILED_BACKING_STORE)
576void WebPage::setActualVisibleContentRect(const IntRect& rect)
577{
578    Frame* frame = m_page->mainFrame();
579
580    frame->view()->setActualVisibleContentRect(rect);
581}
582
583void WebPage::setResizesToContentsUsingLayoutSize(const IntSize& targetLayoutSize)
584{
585    if (m_resizesToContentsLayoutSize == targetLayoutSize)
586        return;
587
588    m_resizesToContentsLayoutSize = targetLayoutSize;
589
590    Frame* frame = m_page->mainFrame();
591    if (m_resizesToContentsLayoutSize.isEmpty()) {
592        frame->view()->setDelegatesScrolling(false);
593        frame->view()->setUseFixedLayout(false);
594        frame->view()->setPaintsEntireContents(false);
595    } else {
596        frame->view()->setDelegatesScrolling(true);
597        frame->view()->setUseFixedLayout(true);
598        frame->view()->setPaintsEntireContents(true);
599        frame->view()->setFixedLayoutSize(m_resizesToContentsLayoutSize);
600    }
601    frame->view()->forceLayout();
602}
603
604void WebPage::resizeToContentsIfNeeded()
605{
606    if (m_resizesToContentsLayoutSize.isEmpty())
607        return;
608
609    Frame* frame = m_page->mainFrame();
610
611    IntSize contentSize = frame->view()->contentsSize();
612    if (contentSize == m_viewSize)
613        return;
614
615    m_viewSize = contentSize;
616    frame->view()->resize(m_viewSize);
617    frame->view()->setNeedsLayout();
618}
619#endif
620
621void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset)
622{
623    Frame* frame = m_page->mainFrame();
624
625    IntPoint scrollPosition = frame->view()->scrollPosition();
626    IntPoint maximumScrollPosition = frame->view()->maximumScrollPosition();
627
628    // If the current scroll position in a direction is the max scroll position
629    // we don't want to scroll at all.
630    IntSize newScrollOffset;
631    if (scrollPosition.x() < maximumScrollPosition.x())
632        newScrollOffset.setWidth(scrollOffset.width());
633    if (scrollPosition.y() < maximumScrollPosition.y())
634        newScrollOffset.setHeight(scrollOffset.height());
635
636    if (newScrollOffset.isZero())
637        return;
638
639    frame->view()->setScrollPosition(frame->view()->scrollPosition() + newScrollOffset);
640}
641
642void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect)
643{
644    graphicsContext.save();
645    graphicsContext.clip(rect);
646    m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect);
647    graphicsContext.restore();
648}
649
650void WebPage::drawPageOverlay(GraphicsContext& graphicsContext, const IntRect& rect)
651{
652    ASSERT(m_pageOverlay);
653
654    graphicsContext.save();
655    graphicsContext.clip(rect);
656    m_pageOverlay->drawRect(graphicsContext, rect);
657    graphicsContext.restore();
658}
659
660double WebPage::textZoomFactor() const
661{
662    Frame* frame = m_mainFrame->coreFrame();
663    if (!frame)
664        return 1;
665    return frame->textZoomFactor();
666}
667
668void WebPage::setTextZoomFactor(double zoomFactor)
669{
670    Frame* frame = m_mainFrame->coreFrame();
671    if (!frame)
672        return;
673    frame->setTextZoomFactor(static_cast<float>(zoomFactor));
674}
675
676double WebPage::pageZoomFactor() const
677{
678    Frame* frame = m_mainFrame->coreFrame();
679    if (!frame)
680        return 1;
681    return frame->pageZoomFactor();
682}
683
684void WebPage::setPageZoomFactor(double zoomFactor)
685{
686    Frame* frame = m_mainFrame->coreFrame();
687    if (!frame)
688        return;
689    frame->setPageZoomFactor(static_cast<float>(zoomFactor));
690}
691
692void WebPage::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
693{
694    Frame* frame = m_mainFrame->coreFrame();
695    if (!frame)
696        return;
697    return frame->setPageAndTextZoomFactors(static_cast<float>(pageZoomFactor), static_cast<float>(textZoomFactor));
698}
699
700void WebPage::scaleWebView(double scale, const IntPoint& origin)
701{
702    Frame* frame = m_mainFrame->coreFrame();
703    if (!frame)
704        return;
705    frame->scalePage(scale, origin);
706
707    send(Messages::WebPageProxy::ViewScaleFactorDidChange(scale));
708}
709
710double WebPage::viewScaleFactor() const
711{
712    Frame* frame = m_mainFrame->coreFrame();
713    if (!frame)
714        return 1;
715    return frame->pageScaleFactor();
716}
717
718void WebPage::setUseFixedLayout(bool fixed)
719{
720    Frame* frame = m_mainFrame->coreFrame();
721    if (!frame)
722        return;
723
724    FrameView* view = frame->view();
725    if (!view)
726        return;
727
728    view->setUseFixedLayout(fixed);
729    if (!fixed)
730        view->setFixedLayoutSize(IntSize());
731}
732
733void WebPage::setFixedLayoutSize(const IntSize& size)
734{
735    Frame* frame = m_mainFrame->coreFrame();
736    if (!frame)
737        return;
738
739    FrameView* view = frame->view();
740    if (!view)
741        return;
742
743    view->setFixedLayoutSize(size);
744    view->forceLayout();
745}
746
747void WebPage::installPageOverlay(PassRefPtr<PageOverlay> pageOverlay)
748{
749    bool shouldFadeIn = true;
750
751    if (m_pageOverlay) {
752        m_pageOverlay->setPage(0);
753
754        if (pageOverlay) {
755            // We're installing a page overlay when a page overlay is already active.
756            // In this case we don't want to fade in the new overlay.
757            shouldFadeIn = false;
758        }
759    }
760
761    m_pageOverlay = pageOverlay;
762    m_pageOverlay->setPage(this);
763
764    if (shouldFadeIn)
765        m_pageOverlay->startFadeInAnimation();
766
767    m_drawingArea->didInstallPageOverlay();
768    m_pageOverlay->setNeedsDisplay();
769}
770
771void WebPage::uninstallPageOverlay(PageOverlay* pageOverlay, bool fadeOut)
772{
773    if (pageOverlay != m_pageOverlay)
774        return;
775
776    if (fadeOut) {
777        m_pageOverlay->startFadeOutAnimation();
778        return;
779    }
780
781    m_pageOverlay->setPage(0);
782    m_pageOverlay = nullptr;
783
784    m_drawingArea->didUninstallPageOverlay();
785}
786
787PassRefPtr<WebImage> WebPage::snapshotInViewCoordinates(const IntRect& rect, ImageOptions options)
788{
789    FrameView* frameView = m_mainFrame->coreFrame()->view();
790    if (!frameView)
791        return 0;
792
793    frameView->updateLayoutAndStyleIfNeededRecursive();
794
795    PaintBehavior oldBehavior = frameView->paintBehavior();
796    frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
797
798    RefPtr<WebImage> snapshot = WebImage::create(rect.size(), options);
799    OwnPtr<WebCore::GraphicsContext> graphicsContext = snapshot->bitmap()->createGraphicsContext();
800
801    graphicsContext->save();
802    graphicsContext->translate(-rect.x(), -rect.y());
803    frameView->paint(graphicsContext.get(), rect);
804    graphicsContext->restore();
805
806    frameView->setPaintBehavior(oldBehavior);
807
808    return snapshot.release();
809}
810
811PassRefPtr<WebImage> WebPage::scaledSnapshotInDocumentCoordinates(const IntRect& rect, double scaleFactor, ImageOptions options)
812{
813    FrameView* frameView = m_mainFrame->coreFrame()->view();
814    if (!frameView)
815        return 0;
816
817    frameView->updateLayoutAndStyleIfNeededRecursive();
818
819    PaintBehavior oldBehavior = frameView->paintBehavior();
820    frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
821
822    bool scale = scaleFactor != 1;
823    IntSize size = rect.size();
824    if (scale)
825        size = IntSize(ceil(rect.width() * scaleFactor), ceil(rect.height() * scaleFactor));
826
827    RefPtr<WebImage> snapshot = WebImage::create(size, options);
828    OwnPtr<WebCore::GraphicsContext> graphicsContext = snapshot->bitmap()->createGraphicsContext();
829    graphicsContext->save();
830
831    if (scale)
832        graphicsContext->scale(FloatSize(scaleFactor, scaleFactor));
833
834    graphicsContext->translate(-rect.x(), -rect.y());
835    frameView->paintContents(graphicsContext.get(), rect);
836    graphicsContext->restore();
837
838    frameView->setPaintBehavior(oldBehavior);
839
840    return snapshot.release();
841}
842
843PassRefPtr<WebImage> WebPage::snapshotInDocumentCoordinates(const IntRect& rect, ImageOptions options)
844{
845    return scaledSnapshotInDocumentCoordinates(rect, 1, options);
846}
847
848void WebPage::pageDidScroll()
849{
850    // Hide the find indicator.
851    m_findController.hideFindIndicator();
852
853    m_uiClient.pageDidScroll(this);
854
855    send(Messages::WebPageProxy::PageDidScroll());
856}
857
858#if ENABLE(TILED_BACKING_STORE)
859void WebPage::pageDidRequestScroll(const IntPoint& point)
860{
861    send(Messages::WebPageProxy::PageDidRequestScroll(point));
862}
863#endif
864
865WebContextMenu* WebPage::contextMenu()
866{
867    if (!m_contextMenu)
868        m_contextMenu = WebContextMenu::create(this);
869    return m_contextMenu.get();
870}
871
872// Events
873
874static const WebEvent* g_currentEvent = 0;
875
876// FIXME: WebPage::currentEvent is used by the plug-in code to avoid having to convert from DOM events back to
877// WebEvents. When we get the event handling sorted out, this should go away and the Widgets should get the correct
878// platform events passed to the event handler code.
879const WebEvent* WebPage::currentEvent()
880{
881    return g_currentEvent;
882}
883
884class CurrentEvent {
885public:
886    explicit CurrentEvent(const WebEvent& event)
887        : m_previousCurrentEvent(g_currentEvent)
888    {
889        g_currentEvent = &event;
890    }
891
892    ~CurrentEvent()
893    {
894        g_currentEvent = m_previousCurrentEvent;
895    }
896
897private:
898    const WebEvent* m_previousCurrentEvent;
899};
900
901static bool isContextClick(const PlatformMouseEvent& event)
902{
903    if (event.button() == WebCore::RightButton)
904        return true;
905
906#if PLATFORM(MAC)
907    // FIXME: this really should be about OSX-style UI, not about the Mac port
908    if (event.button() == WebCore::LeftButton && event.ctrlKey())
909        return true;
910#endif
911
912    return false;
913}
914
915static bool handleMouseEvent(const WebMouseEvent& mouseEvent, Page* page)
916{
917    Frame* frame = page->mainFrame();
918    if (!frame->view())
919        return false;
920
921    PlatformMouseEvent platformMouseEvent = platform(mouseEvent);
922
923    switch (platformMouseEvent.eventType()) {
924        case WebCore::MouseEventPressed:
925        {
926            if (isContextClick(platformMouseEvent))
927                page->contextMenuController()->clearContextMenu();
928
929            bool handled = frame->eventHandler()->handleMousePressEvent(platformMouseEvent);
930
931            if (isContextClick(platformMouseEvent)) {
932                handled = frame->eventHandler()->sendContextMenuEvent(platformMouseEvent);
933                if (handled)
934                    page->chrome()->showContextMenu();
935            }
936
937            return handled;
938        }
939        case WebCore::MouseEventReleased:
940            return frame->eventHandler()->handleMouseReleaseEvent(platformMouseEvent);
941        case WebCore::MouseEventMoved:
942            return frame->eventHandler()->mouseMoved(platformMouseEvent);
943
944        default:
945            ASSERT_NOT_REACHED();
946            return false;
947    }
948}
949
950void WebPage::mouseEvent(const WebMouseEvent& mouseEvent)
951{
952    // Don't try to handle any pending mouse events if a context menu is showing.
953    if (m_isShowingContextMenu) {
954        send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), false));
955        return;
956    }
957
958    bool handled = false;
959
960    if (m_pageOverlay) {
961        // Let the page overlay handle the event.
962        handled = m_pageOverlay->mouseEvent(mouseEvent);
963    }
964
965    if (!handled) {
966        CurrentEvent currentEvent(mouseEvent);
967
968        handled = handleMouseEvent(mouseEvent, m_page.get());
969    }
970
971    send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), handled));
972}
973
974static bool handleWheelEvent(const WebWheelEvent& wheelEvent, Page* page)
975{
976    Frame* frame = page->mainFrame();
977    if (!frame->view())
978        return false;
979
980    PlatformWheelEvent platformWheelEvent = platform(wheelEvent);
981    return frame->eventHandler()->handleWheelEvent(platformWheelEvent);
982}
983
984void WebPage::wheelEvent(const WebWheelEvent& wheelEvent)
985{
986    CurrentEvent currentEvent(wheelEvent);
987
988    bool handled = handleWheelEvent(wheelEvent, m_page.get());
989    send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(wheelEvent.type()), handled));
990}
991
992static bool handleKeyEvent(const WebKeyboardEvent& keyboardEvent, Page* page)
993{
994    if (!page->mainFrame()->view())
995        return false;
996
997    if (keyboardEvent.type() == WebEvent::Char && keyboardEvent.isSystemKey())
998        return page->focusController()->focusedOrMainFrame()->eventHandler()->handleAccessKey(platform(keyboardEvent));
999    return page->focusController()->focusedOrMainFrame()->eventHandler()->keyEvent(platform(keyboardEvent));
1000}
1001
1002void WebPage::keyEvent(const WebKeyboardEvent& keyboardEvent)
1003{
1004    CurrentEvent currentEvent(keyboardEvent);
1005
1006    bool handled = handleKeyEvent(keyboardEvent, m_page.get());
1007    // FIXME: Platform default behaviors should be performed during normal DOM event dispatch (in most cases, in default keydown event handler).
1008    if (!handled)
1009        handled = performDefaultBehaviorForKeyEvent(keyboardEvent);
1010
1011    send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(keyboardEvent.type()), handled));
1012}
1013
1014#if ENABLE(GESTURE_EVENTS)
1015static bool handleGestureEvent(const WebGestureEvent& gestureEvent, Page* page)
1016{
1017    Frame* frame = page->mainFrame();
1018    if (!frame->view())
1019        return false;
1020
1021    PlatformGestureEvent platformGestureEvent = platform(gestureEvent);
1022    return frame->eventHandler()->handleGestureEvent(platformGestureEvent);
1023}
1024
1025void WebPage::gestureEvent(const WebGestureEvent& gestureEvent)
1026{
1027    CurrentEvent currentEvent(gestureEvent);
1028
1029    bool handled = handleGestureEvent(gestureEvent, m_page.get());
1030    send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(gestureEvent.type()), handled));
1031}
1032#endif
1033
1034void WebPage::validateCommand(const String& commandName, uint64_t callbackID)
1035{
1036    bool isEnabled = false;
1037    int32_t state = 0;
1038    Frame* frame = m_page->focusController()->focusedOrMainFrame();
1039    if (frame) {
1040        Editor::Command command = frame->editor()->command(commandName);
1041        state = command.state();
1042        isEnabled = command.isSupported() && command.isEnabled();
1043    }
1044
1045    send(Messages::WebPageProxy::ValidateCommandCallback(commandName, isEnabled, state, callbackID));
1046}
1047
1048void WebPage::executeEditCommand(const String& commandName)
1049{
1050    executeEditingCommand(commandName, String());
1051}
1052
1053uint64_t WebPage::restoreSession(const SessionState& sessionState)
1054{
1055    const BackForwardListItemVector& list = sessionState.list();
1056    size_t size = list.size();
1057    uint64_t currentItemID = 0;
1058    for (size_t i = 0; i < size; ++i) {
1059        WebBackForwardListItem* webItem = list[i].get();
1060        DecoderAdapter decoder(webItem->backForwardData().data(), webItem->backForwardData().size());
1061
1062        RefPtr<HistoryItem> item = HistoryItem::decodeBackForwardTree(webItem->url(), webItem->title(), webItem->originalURL(), decoder);
1063        if (!item) {
1064            LOG_ERROR("Failed to decode a HistoryItem from session state data.");
1065            return 0;
1066        }
1067
1068        if (i == sessionState.currentIndex())
1069            currentItemID = webItem->itemID();
1070
1071        WebBackForwardListProxy::addItemFromUIProcess(list[i]->itemID(), item.release());
1072    }
1073    ASSERT(currentItemID);
1074    return currentItemID;
1075}
1076
1077void WebPage::restoreSessionAndNavigateToCurrentItem(const SessionState& sessionState, const SandboxExtension::Handle& sandboxExtensionHandle)
1078{
1079    if (uint64_t currentItemID = restoreSession(sessionState))
1080        goToBackForwardItem(currentItemID, sandboxExtensionHandle);
1081}
1082
1083#if ENABLE(TOUCH_EVENTS)
1084static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page)
1085{
1086    Frame* frame = page->mainFrame();
1087    if (!frame->view())
1088        return false;
1089
1090    return frame->eventHandler()->handleTouchEvent(platform(touchEvent));
1091}
1092
1093void WebPage::touchEvent(const WebTouchEvent& touchEvent)
1094{
1095    CurrentEvent currentEvent(touchEvent);
1096
1097    bool handled = handleTouchEvent(touchEvent, m_page.get());
1098
1099    send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(touchEvent.type()), handled));
1100}
1101#endif
1102
1103void WebPage::scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity)
1104{
1105    page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity);
1106}
1107
1108void WebPage::logicalScroll(Page* page, ScrollLogicalDirection direction, ScrollGranularity granularity)
1109{
1110    page->focusController()->focusedOrMainFrame()->eventHandler()->logicalScrollRecursively(direction, granularity);
1111}
1112
1113void WebPage::scrollBy(uint32_t scrollDirection, uint32_t scrollGranularity)
1114{
1115    scroll(m_page.get(), static_cast<ScrollDirection>(scrollDirection), static_cast<ScrollGranularity>(scrollGranularity));
1116}
1117
1118void WebPage::setActive(bool isActive)
1119{
1120    m_page->focusController()->setActive(isActive);
1121
1122#if PLATFORM(MAC)
1123    // Tell all our plug-in views that the window focus changed.
1124    for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1125        (*it)->setWindowIsFocused(isActive);
1126#endif
1127}
1128
1129void WebPage::setDrawsBackground(bool drawsBackground)
1130{
1131    if (m_drawsBackground == drawsBackground)
1132        return;
1133
1134    m_drawsBackground = drawsBackground;
1135
1136    for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
1137        if (FrameView* view = coreFrame->view())
1138            view->setTransparent(!drawsBackground);
1139    }
1140
1141    m_drawingArea->pageBackgroundTransparencyChanged();
1142    m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
1143}
1144
1145void WebPage::setDrawsTransparentBackground(bool drawsTransparentBackground)
1146{
1147    if (m_drawsTransparentBackground == drawsTransparentBackground)
1148        return;
1149
1150    m_drawsTransparentBackground = drawsTransparentBackground;
1151
1152    Color backgroundColor = drawsTransparentBackground ? Color::transparent : Color::white;
1153    for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
1154        if (FrameView* view = coreFrame->view())
1155            view->setBaseBackgroundColor(backgroundColor);
1156    }
1157
1158    m_drawingArea->pageBackgroundTransparencyChanged();
1159    m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
1160}
1161
1162void WebPage::viewWillStartLiveResize()
1163{
1164    if (!m_page)
1165        return;
1166
1167    // FIXME: This should propagate to all ScrollableAreas.
1168    if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) {
1169        if (FrameView* view = frame->view())
1170            view->willStartLiveResize();
1171    }
1172}
1173
1174void WebPage::viewWillEndLiveResize()
1175{
1176    if (!m_page)
1177        return;
1178
1179    // FIXME: This should propagate to all ScrollableAreas.
1180    if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) {
1181        if (FrameView* view = frame->view())
1182            view->willEndLiveResize();
1183    }
1184}
1185
1186void WebPage::setFocused(bool isFocused)
1187{
1188    if (!isFocused && m_page->focusController()->focusedOrMainFrame()->editor()->behavior().shouldClearSelectionWhenLosingWebPageFocus())
1189        m_page->focusController()->focusedOrMainFrame()->selection()->clear();
1190
1191    m_page->focusController()->setFocused(isFocused);
1192}
1193
1194void WebPage::setInitialFocus(bool forward)
1195{
1196    if (!m_page || !m_page->focusController())
1197        return;
1198
1199    Frame* frame = m_page->focusController()->focusedOrMainFrame();
1200    frame->document()->setFocusedNode(0);
1201    m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, 0);
1202}
1203
1204void WebPage::setWindowResizerSize(const IntSize& windowResizerSize)
1205{
1206    if (m_windowResizerSize == windowResizerSize)
1207        return;
1208
1209    m_windowResizerSize = windowResizerSize;
1210
1211    for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
1212        FrameView* view = coreFrame->view();
1213        if (view)
1214            view->windowResizerRectChanged();
1215    }
1216}
1217
1218void WebPage::setIsInWindow(bool isInWindow)
1219{
1220    if (!isInWindow) {
1221        m_page->setCanStartMedia(false);
1222        m_page->willMoveOffscreen();
1223    } else {
1224        m_page->setCanStartMedia(true);
1225        m_page->didMoveOnscreen();
1226    }
1227}
1228
1229void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t downloadID)
1230{
1231    WebFrame* frame = WebProcess::shared().webFrame(frameID);
1232    if (!frame)
1233        return;
1234    frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), downloadID);
1235}
1236
1237void WebPage::show()
1238{
1239    send(Messages::WebPageProxy::ShowPage());
1240}
1241
1242void WebPage::setUserAgent(const String& userAgent)
1243{
1244    m_userAgent = userAgent;
1245}
1246
1247IntRect WebPage::windowToScreen(const IntRect& rect)
1248{
1249    IntRect screenRect;
1250    sendSync(Messages::WebPageProxy::WindowToScreen(rect), Messages::WebPageProxy::WindowToScreen::Reply(screenRect));
1251    return screenRect;
1252}
1253
1254IntRect WebPage::windowResizerRect() const
1255{
1256    if (m_windowResizerSize.isEmpty())
1257        return IntRect();
1258
1259    IntSize frameViewSize;
1260    if (Frame* coreFrame = m_mainFrame->coreFrame()) {
1261        if (FrameView* view = coreFrame->view())
1262            frameViewSize = view->size();
1263    }
1264
1265    return IntRect(frameViewSize.width() - m_windowResizerSize.width(), frameViewSize.height() - m_windowResizerSize.height(),
1266                   m_windowResizerSize.width(), m_windowResizerSize.height());
1267}
1268
1269KeyboardUIMode WebPage::keyboardUIMode()
1270{
1271    bool fullKeyboardAccessEnabled = WebProcess::shared().fullKeyboardAccessEnabled();
1272    return static_cast<KeyboardUIMode>((fullKeyboardAccessEnabled ? KeyboardAccessFull : KeyboardAccessDefault) | (m_tabToLinks ? KeyboardAccessTabsToLinks : 0));
1273}
1274
1275void WebPage::runJavaScriptInMainFrame(const String& script, uint64_t callbackID)
1276{
1277    // NOTE: We need to be careful when running scripts that the objects we depend on don't
1278    // disappear during script execution.
1279
1280    // Retain the SerializedScriptValue at this level so it (and the internal data) lives
1281    // long enough for the DataReference to be encoded by the sent message.
1282    RefPtr<SerializedScriptValue> serializedResultValue;
1283    CoreIPC::DataReference dataReference;
1284
1285    JSLock lock(SilenceAssertionsOnly);
1286    if (JSValue resultValue = m_mainFrame->coreFrame()->script()->executeScript(script, true).jsValue()) {
1287        if ((serializedResultValue = SerializedScriptValue::create(m_mainFrame->jsContext(),
1288            toRef(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec(), resultValue), 0)))
1289            dataReference = CoreIPC::DataReference(serializedResultValue->data().data(), serializedResultValue->data().size());
1290    }
1291
1292    send(Messages::WebPageProxy::ScriptValueCallback(dataReference, callbackID));
1293}
1294
1295void WebPage::getContentsAsString(uint64_t callbackID)
1296{
1297    String resultString = m_mainFrame->contentsAsString();
1298    send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1299}
1300
1301void WebPage::getRenderTreeExternalRepresentation(uint64_t callbackID)
1302{
1303    String resultString = renderTreeExternalRepresentation();
1304    send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1305}
1306
1307void WebPage::getSelectionOrContentsAsString(uint64_t callbackID)
1308{
1309    String resultString = m_mainFrame->selectionAsString();
1310    if (resultString.isEmpty())
1311        resultString = m_mainFrame->contentsAsString();
1312    send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1313}
1314
1315void WebPage::getSourceForFrame(uint64_t frameID, uint64_t callbackID)
1316{
1317    String resultString;
1318    if (WebFrame* frame = WebProcess::shared().webFrame(frameID))
1319       resultString = frame->source();
1320
1321    send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1322}
1323
1324void WebPage::getMainResourceDataOfFrame(uint64_t frameID, uint64_t callbackID)
1325{
1326    CoreIPC::DataReference dataReference;
1327
1328    RefPtr<SharedBuffer> buffer;
1329    if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1330        if (DocumentLoader* loader = frame->coreFrame()->loader()->documentLoader()) {
1331            if ((buffer = loader->mainResourceData()))
1332                dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size());
1333        }
1334    }
1335
1336    send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1337}
1338
1339void WebPage::getResourceDataFromFrame(uint64_t frameID, const String& resourceURL, uint64_t callbackID)
1340{
1341    CoreIPC::DataReference dataReference;
1342
1343    RefPtr<SharedBuffer> buffer;
1344    if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1345        if (DocumentLoader* loader = frame->coreFrame()->loader()->documentLoader()) {
1346            if (RefPtr<ArchiveResource> subresource = loader->subresource(KURL(KURL(), resourceURL))) {
1347                if ((buffer = subresource->data()))
1348                    dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size());
1349            }
1350        }
1351    }
1352
1353    send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1354}
1355
1356void WebPage::getWebArchiveOfFrame(uint64_t frameID, uint64_t callbackID)
1357{
1358    CoreIPC::DataReference dataReference;
1359
1360#if PLATFORM(MAC) || PLATFORM(WIN)
1361    RetainPtr<CFDataRef> data;
1362    if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1363        if (RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(frame->coreFrame()->document())) {
1364            if ((data = archive->rawDataRepresentation()))
1365                dataReference = CoreIPC::DataReference(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get()));
1366        }
1367    }
1368#endif
1369
1370    send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1371}
1372
1373void WebPage::forceRepaintWithoutCallback()
1374{
1375    m_drawingArea->forceRepaint();
1376}
1377
1378void WebPage::forceRepaint(uint64_t callbackID)
1379{
1380    forceRepaintWithoutCallback();
1381    send(Messages::WebPageProxy::VoidCallback(callbackID));
1382}
1383
1384void WebPage::preferencesDidChange(const WebPreferencesStore& store)
1385{
1386    WebPreferencesStore::removeTestRunnerOverrides();
1387    updatePreferences(store);
1388}
1389
1390void WebPage::updatePreferences(const WebPreferencesStore& store)
1391{
1392    Settings* settings = m_page->settings();
1393
1394    m_tabToLinks = store.getBoolValueForKey(WebPreferencesKey::tabsToLinksKey());
1395
1396    // FIXME: This should be generated from macro expansion for all preferences,
1397    // but we currently don't match the naming of WebCore exactly so we are
1398    // handrolling the boolean and integer preferences until that is fixed.
1399
1400#define INITIALIZE_SETTINGS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) settings->set##KeyUpper(store.get##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key()));
1401
1402    FOR_EACH_WEBKIT_STRING_PREFERENCE(INITIALIZE_SETTINGS)
1403
1404#undef INITIALIZE_SETTINGS
1405
1406    settings->setJavaScriptEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptEnabledKey()));
1407    settings->setLoadsImagesAutomatically(store.getBoolValueForKey(WebPreferencesKey::loadsImagesAutomaticallyKey()));
1408    settings->setLoadsSiteIconsIgnoringImageLoadingSetting(store.getBoolValueForKey(WebPreferencesKey::loadsSiteIconsIgnoringImageLoadingPreferenceKey()));
1409    settings->setPluginsEnabled(store.getBoolValueForKey(WebPreferencesKey::pluginsEnabledKey()));
1410    settings->setJavaEnabled(store.getBoolValueForKey(WebPreferencesKey::javaEnabledKey()));
1411    settings->setOfflineWebApplicationCacheEnabled(store.getBoolValueForKey(WebPreferencesKey::offlineWebApplicationCacheEnabledKey()));
1412    settings->setLocalStorageEnabled(store.getBoolValueForKey(WebPreferencesKey::localStorageEnabledKey()));
1413    settings->setXSSAuditorEnabled(store.getBoolValueForKey(WebPreferencesKey::xssAuditorEnabledKey()));
1414    settings->setFrameFlatteningEnabled(store.getBoolValueForKey(WebPreferencesKey::frameFlatteningEnabledKey()));
1415    settings->setPrivateBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey()));
1416    settings->setDeveloperExtrasEnabled(store.getBoolValueForKey(WebPreferencesKey::developerExtrasEnabledKey()));
1417    settings->setTextAreasAreResizable(store.getBoolValueForKey(WebPreferencesKey::textAreasAreResizableKey()));
1418    settings->setNeedsSiteSpecificQuirks(store.getBoolValueForKey(WebPreferencesKey::needsSiteSpecificQuirksKey()));
1419    settings->setJavaScriptCanOpenWindowsAutomatically(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanOpenWindowsAutomaticallyKey()));
1420    settings->setForceFTPDirectoryListings(store.getBoolValueForKey(WebPreferencesKey::forceFTPDirectoryListingsKey()));
1421    settings->setDNSPrefetchingEnabled(store.getBoolValueForKey(WebPreferencesKey::dnsPrefetchingEnabledKey()));
1422#if ENABLE(WEB_ARCHIVE)
1423    settings->setWebArchiveDebugModeEnabled(store.getBoolValueForKey(WebPreferencesKey::webArchiveDebugModeEnabledKey()));
1424#endif
1425    settings->setLocalFileContentSniffingEnabled(store.getBoolValueForKey(WebPreferencesKey::localFileContentSniffingEnabledKey()));
1426    settings->setUsesPageCache(store.getBoolValueForKey(WebPreferencesKey::usesPageCacheKey()));
1427    settings->setAuthorAndUserStylesEnabled(store.getBoolValueForKey(WebPreferencesKey::authorAndUserStylesEnabledKey()));
1428    settings->setPaginateDuringLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::paginateDuringLayoutEnabledKey()));
1429    settings->setDOMPasteAllowed(store.getBoolValueForKey(WebPreferencesKey::domPasteAllowedKey()));
1430    settings->setJavaScriptCanAccessClipboard(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanAccessClipboardKey()));
1431    settings->setShouldPrintBackgrounds(store.getBoolValueForKey(WebPreferencesKey::shouldPrintBackgroundsKey()));
1432    settings->setWebSecurityEnabled(store.getBoolValueForKey(WebPreferencesKey::webSecurityEnabledKey()));
1433    settings->setAllowUniversalAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowUniversalAccessFromFileURLsKey()));
1434    settings->setAllowFileAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowFileAccessFromFileURLsKey()));
1435
1436    settings->setMinimumFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumFontSizeKey()));
1437    settings->setMinimumLogicalFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumLogicalFontSizeKey()));
1438    settings->setDefaultFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFontSizeKey()));
1439    settings->setDefaultFixedFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFixedFontSizeKey()));
1440    settings->setEditableLinkBehavior(static_cast<WebCore::EditableLinkBehavior>(store.getUInt32ValueForKey(WebPreferencesKey::editableLinkBehaviorKey())));
1441
1442    settings->setAcceleratedCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingEnabledKey()) && LayerTreeHost::supportsAcceleratedCompositing());
1443    settings->setAcceleratedDrawingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedDrawingEnabledKey()) && LayerTreeHost::supportsAcceleratedCompositing());
1444    settings->setCanvasUsesAcceleratedDrawing(store.getBoolValueForKey(WebPreferencesKey::canvasUsesAcceleratedDrawingKey()) && LayerTreeHost::supportsAcceleratedCompositing());
1445    settings->setShowDebugBorders(store.getBoolValueForKey(WebPreferencesKey::compositingBordersVisibleKey()));
1446    settings->setShowRepaintCounter(store.getBoolValueForKey(WebPreferencesKey::compositingRepaintCountersVisibleKey()));
1447    settings->setWebGLEnabled(store.getBoolValueForKey(WebPreferencesKey::webGLEnabledKey()));
1448
1449#if ENABLE(DATABASE)
1450    AbstractDatabase::setIsAvailable(store.getBoolValueForKey(WebPreferencesKey::databasesEnabledKey()));
1451#endif
1452
1453#if ENABLE(FULLSCREEN_API)
1454    settings->setFullScreenEnabled(store.getBoolValueForKey(WebPreferencesKey::fullScreenEnabledKey()));
1455#endif
1456
1457#if ENABLE(DOM_STORAGE)
1458    settings->setLocalStorageDatabasePath(WebProcess::shared().localStorageDirectory());
1459#endif
1460
1461    platformPreferencesDidChange(store);
1462}
1463
1464#if ENABLE(INSPECTOR)
1465WebInspector* WebPage::inspector()
1466{
1467    if (m_isClosed)
1468        return 0;
1469    if (!m_inspector)
1470        m_inspector = WebInspector::create(this);
1471    return m_inspector.get();
1472}
1473#endif
1474
1475#if ENABLE(FULLSCREEN_API)
1476WebFullScreenManager* WebPage::fullScreenManager()
1477{
1478    if (!m_fullScreenManager)
1479        m_fullScreenManager = WebFullScreenManager::create(this);
1480    return m_fullScreenManager.get();
1481}
1482#endif
1483
1484#if !PLATFORM(GTK) && !PLATFORM(MAC)
1485bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt)
1486{
1487    Node* node = evt->target()->toNode();
1488    ASSERT(node);
1489    Frame* frame = node->document()->frame();
1490    ASSERT(frame);
1491
1492    const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
1493    if (!keyEvent)
1494        return false;
1495
1496    Editor::Command command = frame->editor()->command(interpretKeyEvent(evt));
1497
1498    if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
1499        // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
1500        // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
1501        // (e.g. Tab that inserts a Tab character, or Enter).
1502        return !command.isTextInsertion() && command.execute(evt);
1503    }
1504
1505    if (command.execute(evt))
1506        return true;
1507
1508    // Don't insert null or control characters as they can result in unexpected behaviour
1509    if (evt->charCode() < ' ')
1510        return false;
1511
1512    return frame->editor()->insertText(evt->keyEvent()->text(), evt);
1513}
1514#endif
1515
1516#if PLATFORM(WIN)
1517void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const WebCore::DragDataMap& dataMap, uint32_t flags)
1518{
1519    if (!m_page) {
1520        send(Messages::WebPageProxy::DidPerformDragControllerAction(DragOperationNone));
1521        return;
1522    }
1523
1524    DragData dragData(dataMap, clientPosition, globalPosition, static_cast<DragOperation>(draggingSourceOperationMask), static_cast<DragApplicationFlags>(flags));
1525    switch (action) {
1526    case DragControllerActionEntered:
1527        send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData)));
1528        break;
1529
1530    case DragControllerActionUpdated:
1531        send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData)));
1532        break;
1533
1534    case DragControllerActionExited:
1535        m_page->dragController()->dragExited(&dragData);
1536        break;
1537
1538    case DragControllerActionPerformDrag:
1539        m_page->dragController()->performDrag(&dragData);
1540        break;
1541
1542    default:
1543        ASSERT_NOT_REACHED();
1544    }
1545}
1546#else
1547void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const String& dragStorageName, uint32_t flags, const SandboxExtension::Handle& sandboxExtensionHandle)
1548{
1549    if (!m_page) {
1550        send(Messages::WebPageProxy::DidPerformDragControllerAction(DragOperationNone));
1551        return;
1552    }
1553
1554    DragData dragData(dragStorageName, clientPosition, globalPosition, static_cast<DragOperation>(draggingSourceOperationMask), static_cast<DragApplicationFlags>(flags));
1555    switch (action) {
1556    case DragControllerActionEntered:
1557        send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData)));
1558        break;
1559
1560    case DragControllerActionUpdated:
1561        send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData)));
1562        break;
1563
1564    case DragControllerActionExited:
1565        m_page->dragController()->dragExited(&dragData);
1566        break;
1567
1568    case DragControllerActionPerformDrag: {
1569        ASSERT(!m_pendingDropSandboxExtension);
1570
1571        m_pendingDropSandboxExtension = SandboxExtension::create(sandboxExtensionHandle);
1572
1573        m_page->dragController()->performDrag(&dragData);
1574
1575        // If we started loading a local file, the sandbox extension tracker would have adopted this
1576        // pending drop sandbox extension. If not, we'll play it safe and invalidate it.
1577        if (m_pendingDropSandboxExtension) {
1578            m_pendingDropSandboxExtension->invalidate();
1579            m_pendingDropSandboxExtension = nullptr;
1580        }
1581
1582        break;
1583    }
1584
1585    default:
1586        ASSERT_NOT_REACHED();
1587    }
1588}
1589#endif
1590
1591void WebPage::dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation)
1592{
1593    IntPoint adjustedClientPosition(clientPosition.x() + m_page->dragController()->dragOffset().x(), clientPosition.y() + m_page->dragController()->dragOffset().y());
1594    IntPoint adjustedGlobalPosition(globalPosition.x() + m_page->dragController()->dragOffset().x(), globalPosition.y() + m_page->dragController()->dragOffset().y());
1595
1596    platformDragEnded();
1597    m_page->dragController()->dragEnded();
1598    FrameView* view = m_page->mainFrame()->view();
1599    if (!view)
1600        return;
1601    // FIXME: These are fake modifier keys here, but they should be real ones instead.
1602    PlatformMouseEvent event(adjustedClientPosition, adjustedGlobalPosition, LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime());
1603    m_page->mainFrame()->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation);
1604}
1605
1606void WebPage::willPerformLoadDragDestinationAction()
1607{
1608    m_sandboxExtensionTracker.willPerformLoadDragDestinationAction(m_pendingDropSandboxExtension.release());
1609}
1610
1611WebEditCommand* WebPage::webEditCommand(uint64_t commandID)
1612{
1613    return m_editCommandMap.get(commandID).get();
1614}
1615
1616void WebPage::addWebEditCommand(uint64_t commandID, WebEditCommand* command)
1617{
1618    m_editCommandMap.set(commandID, command);
1619}
1620
1621void WebPage::removeWebEditCommand(uint64_t commandID)
1622{
1623    m_editCommandMap.remove(commandID);
1624}
1625
1626void WebPage::unapplyEditCommand(uint64_t commandID)
1627{
1628    WebEditCommand* command = webEditCommand(commandID);
1629    if (!command)
1630        return;
1631
1632    command->command()->unapply();
1633}
1634
1635void WebPage::reapplyEditCommand(uint64_t commandID)
1636{
1637    WebEditCommand* command = webEditCommand(commandID);
1638    if (!command)
1639        return;
1640
1641    m_isInRedo = true;
1642    command->command()->reapply();
1643    m_isInRedo = false;
1644}
1645
1646void WebPage::didRemoveEditCommand(uint64_t commandID)
1647{
1648    removeWebEditCommand(commandID);
1649}
1650
1651void WebPage::setActivePopupMenu(WebPopupMenu* menu)
1652{
1653    m_activePopupMenu = menu;
1654}
1655
1656void WebPage::setActiveOpenPanelResultListener(PassRefPtr<WebOpenPanelResultListener> openPanelResultListener)
1657{
1658    m_activeOpenPanelResultListener = openPanelResultListener;
1659}
1660
1661bool WebPage::findStringFromInjectedBundle(const String& target, FindOptions options)
1662{
1663    return m_page->findString(target, options);
1664}
1665
1666void WebPage::findString(const String& string, uint32_t options, uint32_t maxMatchCount)
1667{
1668    m_findController.findString(string, static_cast<FindOptions>(options), maxMatchCount);
1669}
1670
1671void WebPage::hideFindUI()
1672{
1673    m_findController.hideFindUI();
1674}
1675
1676void WebPage::countStringMatches(const String& string, uint32_t options, uint32_t maxMatchCount)
1677{
1678    m_findController.countStringMatches(string, static_cast<FindOptions>(options), maxMatchCount);
1679}
1680
1681void WebPage::didChangeSelectedIndexForActivePopupMenu(int32_t newIndex)
1682{
1683    if (!m_activePopupMenu)
1684        return;
1685
1686    m_activePopupMenu->didChangeSelectedIndex(newIndex);
1687    m_activePopupMenu = 0;
1688}
1689
1690void WebPage::didChooseFilesForOpenPanel(const Vector<String>& files)
1691{
1692    if (!m_activeOpenPanelResultListener)
1693        return;
1694
1695    m_activeOpenPanelResultListener->didChooseFiles(files);
1696    m_activeOpenPanelResultListener = 0;
1697}
1698
1699void WebPage::didCancelForOpenPanel()
1700{
1701    m_activeOpenPanelResultListener = 0;
1702}
1703
1704#if ENABLE(WEB_PROCESS_SANDBOX)
1705void WebPage::extendSandboxForFileFromOpenPanel(const SandboxExtension::Handle& handle)
1706{
1707    SandboxExtension::create(handle)->consumePermanently();
1708}
1709#endif
1710
1711void WebPage::didReceiveGeolocationPermissionDecision(uint64_t geolocationID, bool allowed)
1712{
1713    m_geolocationPermissionRequestManager.didReceiveGeolocationPermissionDecision(geolocationID, allowed);
1714}
1715
1716void WebPage::advanceToNextMisspelling(bool startBeforeSelection)
1717{
1718    Frame* frame = m_page->focusController()->focusedOrMainFrame();
1719    frame->editor()->advanceToNextMisspelling(startBeforeSelection);
1720}
1721
1722void WebPage::changeSpellingToWord(const String& word)
1723{
1724    replaceSelectionWithText(m_page->focusController()->focusedOrMainFrame(), word);
1725}
1726
1727void WebPage::unmarkAllMisspellings()
1728{
1729    for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1730        if (Document* document = frame->document())
1731            document->markers()->removeMarkers(DocumentMarker::Spelling);
1732    }
1733}
1734
1735void WebPage::unmarkAllBadGrammar()
1736{
1737    for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1738        if (Document* document = frame->document())
1739            document->markers()->removeMarkers(DocumentMarker::Grammar);
1740    }
1741}
1742
1743#if PLATFORM(MAC)
1744void WebPage::uppercaseWord()
1745{
1746    m_page->focusController()->focusedOrMainFrame()->editor()->uppercaseWord();
1747}
1748
1749void WebPage::lowercaseWord()
1750{
1751    m_page->focusController()->focusedOrMainFrame()->editor()->lowercaseWord();
1752}
1753
1754void WebPage::capitalizeWord()
1755{
1756    m_page->focusController()->focusedOrMainFrame()->editor()->capitalizeWord();
1757}
1758#endif
1759
1760void WebPage::setTextForActivePopupMenu(int32_t index)
1761{
1762    if (!m_activePopupMenu)
1763        return;
1764
1765    m_activePopupMenu->setTextForIndex(index);
1766}
1767
1768void WebPage::didSelectItemFromActiveContextMenu(const WebContextMenuItemData& item)
1769{
1770    ASSERT(m_contextMenu);
1771    m_contextMenu->itemSelected(item);
1772    m_contextMenu = 0;
1773}
1774
1775void WebPage::replaceSelectionWithText(Frame* frame, const String& text)
1776{
1777    if (frame->selection()->isNone())
1778        return;
1779
1780    RefPtr<DocumentFragment> textFragment = createFragmentFromText(frame->selection()->toNormalizedRange().get(), text);
1781    applyCommand(ReplaceSelectionCommand::create(frame->document(), textFragment.release(), ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::MatchStyle | ReplaceSelectionCommand::PreventNesting));
1782    frame->selection()->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
1783}
1784
1785bool WebPage::mainFrameHasCustomRepresentation() const
1786{
1787    return static_cast<WebFrameLoaderClient*>(mainFrame()->coreFrame()->loader()->client())->frameHasCustomRepresentation();
1788}
1789
1790void WebPage::didChangeScrollOffsetForMainFrame()
1791{
1792    Frame* frame = m_page->mainFrame();
1793    IntPoint scrollPosition = frame->view()->scrollPosition();
1794    IntPoint maximumScrollPosition = frame->view()->maximumScrollPosition();
1795    IntPoint minimumScrollPosition = frame->view()->minimumScrollPosition();
1796
1797    bool isPinnedToLeftSide = (scrollPosition.x() <= minimumScrollPosition.x());
1798    bool isPinnedToRightSide = (scrollPosition.x() >= maximumScrollPosition.x());
1799
1800    if (isPinnedToLeftSide != m_cachedMainFrameIsPinnedToLeftSide || isPinnedToRightSide != m_cachedMainFrameIsPinnedToRightSide) {
1801        send(Messages::WebPageProxy::DidChangeScrollOffsetPinningForMainFrame(isPinnedToLeftSide, isPinnedToRightSide));
1802
1803        m_cachedMainFrameIsPinnedToLeftSide = isPinnedToLeftSide;
1804        m_cachedMainFrameIsPinnedToRightSide = isPinnedToRightSide;
1805    }
1806}
1807
1808#if PLATFORM(MAC)
1809
1810void WebPage::addPluginView(PluginView* pluginView)
1811{
1812    ASSERT(!m_pluginViews.contains(pluginView));
1813
1814    m_pluginViews.add(pluginView);
1815}
1816
1817void WebPage::removePluginView(PluginView* pluginView)
1818{
1819    ASSERT(m_pluginViews.contains(pluginView));
1820
1821    m_pluginViews.remove(pluginView);
1822}
1823
1824void WebPage::setWindowIsVisible(bool windowIsVisible)
1825{
1826    m_windowIsVisible = windowIsVisible;
1827
1828    // Tell all our plug-in views that the window visibility changed.
1829    for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1830        (*it)->setWindowIsVisible(windowIsVisible);
1831}
1832
1833void WebPage::windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates, const WebCore::IntPoint& accessibilityViewCoordinates)
1834{
1835    m_windowFrameInScreenCoordinates = windowFrameInScreenCoordinates;
1836    m_viewFrameInWindowCoordinates = viewFrameInWindowCoordinates;
1837    m_accessibilityPosition = accessibilityViewCoordinates;
1838
1839    // Tell all our plug-in views that the window and view frames have changed.
1840    for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1841        (*it)->windowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates);
1842}
1843
1844#endif
1845
1846bool WebPage::windowIsFocused() const
1847{
1848    return m_page->focusController()->isActive();
1849}
1850
1851void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
1852{
1853    if (messageID.is<CoreIPC::MessageClassDrawingAreaLegacy>()) {
1854        if (m_drawingArea)
1855            m_drawingArea->didReceiveMessage(connection, messageID, arguments);
1856        return;
1857    }
1858
1859#if PLATFORM(MAC) || PLATFORM(WIN)
1860    if (messageID.is<CoreIPC::MessageClassDrawingArea>()) {
1861        if (m_drawingArea)
1862            m_drawingArea->didReceiveDrawingAreaMessage(connection, messageID, arguments);
1863        return;
1864    }
1865#endif
1866
1867#if ENABLE(INSPECTOR)
1868    if (messageID.is<CoreIPC::MessageClassWebInspector>()) {
1869        if (WebInspector* inspector = this->inspector())
1870            inspector->didReceiveWebInspectorMessage(connection, messageID, arguments);
1871        return;
1872    }
1873#endif
1874
1875#if ENABLE(FULLSCREEN_API)
1876    if (messageID.is<CoreIPC::MessageClassWebFullScreenManager>()) {
1877        fullScreenManager()->didReceiveMessage(connection, messageID, arguments);
1878        return;
1879    }
1880#endif
1881
1882    didReceiveWebPageMessage(connection, messageID, arguments);
1883}
1884
1885CoreIPC::SyncReplyMode WebPage::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, CoreIPC::ArgumentEncoder* reply)
1886{
1887    return didReceiveSyncWebPageMessage(connection, messageID, arguments, reply);
1888}
1889
1890InjectedBundleBackForwardList* WebPage::backForwardList()
1891{
1892    if (!m_backForwardList)
1893        m_backForwardList = InjectedBundleBackForwardList::create(this);
1894    return m_backForwardList.get();
1895}
1896
1897#if PLATFORM(QT)
1898void WebPage::findZoomableAreaForPoint(const WebCore::IntPoint& point)
1899{
1900    const int minimumZoomTargetWidth = 100;
1901
1902    Frame* mainframe = m_mainFrame->coreFrame();
1903    HitTestResult result = mainframe->eventHandler()->hitTestResultAtPoint(mainframe->view()->windowToContents(point), /*allowShadowContent*/ false, /*ignoreClipping*/ true);
1904
1905    Node* node = result.innerNode();
1906    while (node && node->getRect().width() < minimumZoomTargetWidth)
1907        node = node->parentNode();
1908
1909    IntRect zoomableArea;
1910    if (node)
1911        zoomableArea = node->getRect();
1912    send(Messages::WebPageProxy::DidFindZoomableArea(zoomableArea));
1913}
1914#endif
1915
1916WebPage::SandboxExtensionTracker::~SandboxExtensionTracker()
1917{
1918    invalidate();
1919}
1920
1921void WebPage::SandboxExtensionTracker::invalidate()
1922{
1923    if (m_pendingProvisionalSandboxExtension) {
1924        m_pendingProvisionalSandboxExtension->invalidate();
1925        m_pendingProvisionalSandboxExtension = 0;
1926    }
1927
1928    if (m_provisionalSandboxExtension) {
1929        m_provisionalSandboxExtension->invalidate();
1930        m_provisionalSandboxExtension = 0;
1931    }
1932
1933    if (m_committedSandboxExtension) {
1934        m_committedSandboxExtension->invalidate();
1935        m_committedSandboxExtension = 0;
1936    }
1937}
1938
1939void WebPage::SandboxExtensionTracker::willPerformLoadDragDestinationAction(PassRefPtr<SandboxExtension> pendingDropSandboxExtension)
1940{
1941    setPendingProvisionalSandboxExtension(pendingDropSandboxExtension);
1942}
1943
1944void WebPage::SandboxExtensionTracker::beginLoad(WebFrame* frame, const SandboxExtension::Handle& handle)
1945{
1946    ASSERT(frame->isMainFrame());
1947
1948    setPendingProvisionalSandboxExtension(SandboxExtension::create(handle));
1949}
1950
1951void WebPage::SandboxExtensionTracker::setPendingProvisionalSandboxExtension(PassRefPtr<SandboxExtension> pendingProvisionalSandboxExtension)
1952{
1953    // If we get two beginLoad calls in succession, without a provisional load starting, then
1954    // m_pendingProvisionalSandboxExtension will be non-null. Invalidate and null out the extension if that is the case.
1955    if (m_pendingProvisionalSandboxExtension) {
1956        m_pendingProvisionalSandboxExtension->invalidate();
1957        m_pendingProvisionalSandboxExtension = nullptr;
1958    }
1959
1960    m_pendingProvisionalSandboxExtension = pendingProvisionalSandboxExtension;
1961}
1962
1963static bool shouldReuseCommittedSandboxExtension(WebFrame* frame)
1964{
1965    ASSERT(frame->isMainFrame());
1966
1967    FrameLoader* frameLoader = frame->coreFrame()->loader();
1968    FrameLoadType frameLoadType = frameLoader->loadType();
1969
1970    // If the page is being reloaded, it should reuse whatever extension is committed.
1971    if (frameLoadType == FrameLoadTypeReload || frameLoadType == FrameLoadTypeReloadFromOrigin)
1972        return true;
1973
1974    DocumentLoader* documentLoader = frameLoader->documentLoader();
1975    DocumentLoader* provisionalDocumentLoader = frameLoader->provisionalDocumentLoader();
1976    if (!documentLoader || !provisionalDocumentLoader)
1977        return false;
1978
1979    if (documentLoader->url().isLocalFile() && provisionalDocumentLoader->url().isLocalFile())
1980        return true;
1981
1982    return false;
1983}
1984
1985void WebPage::SandboxExtensionTracker::didStartProvisionalLoad(WebFrame* frame)
1986{
1987    if (!frame->isMainFrame())
1988        return;
1989
1990    if (shouldReuseCommittedSandboxExtension(frame)) {
1991        m_pendingProvisionalSandboxExtension = m_committedSandboxExtension.release();
1992        ASSERT(!m_committedSandboxExtension);
1993    }
1994
1995    ASSERT(!m_provisionalSandboxExtension);
1996
1997    m_provisionalSandboxExtension = m_pendingProvisionalSandboxExtension.release();
1998    if (!m_provisionalSandboxExtension)
1999        return;
2000
2001    m_provisionalSandboxExtension->consume();
2002}
2003
2004void WebPage::SandboxExtensionTracker::didCommitProvisionalLoad(WebFrame* frame)
2005{
2006    if (!frame->isMainFrame())
2007        return;
2008
2009    ASSERT(!m_pendingProvisionalSandboxExtension);
2010
2011    // The provisional load has been committed. Invalidate the currently committed sandbox
2012    // extension and make the provisional sandbox extension the committed sandbox extension.
2013    if (m_committedSandboxExtension)
2014        m_committedSandboxExtension->invalidate();
2015
2016    m_committedSandboxExtension = m_provisionalSandboxExtension.release();
2017}
2018
2019void WebPage::SandboxExtensionTracker::didFailProvisionalLoad(WebFrame* frame)
2020{
2021    if (!frame->isMainFrame())
2022        return;
2023
2024    if (!m_provisionalSandboxExtension)
2025        return;
2026
2027    m_provisionalSandboxExtension->invalidate();
2028    m_provisionalSandboxExtension = nullptr;
2029}
2030
2031bool WebPage::hasLocalDataForURL(const KURL& url)
2032{
2033    if (url.isLocalFile())
2034        return true;
2035
2036    FrameLoader* frameLoader = m_page->mainFrame()->loader();
2037    DocumentLoader* documentLoader = frameLoader ? frameLoader->documentLoader() : 0;
2038    if (documentLoader && documentLoader->subresource(url))
2039        return true;
2040
2041    return platformHasLocalDataForURL(url);
2042}
2043
2044void WebPage::setCustomTextEncodingName(const String& encoding)
2045{
2046    m_page->mainFrame()->loader()->reloadWithOverrideEncoding(encoding);
2047}
2048
2049void WebPage::didRemoveBackForwardItem(uint64_t itemID)
2050{
2051    WebBackForwardListProxy::removeItem(itemID);
2052}
2053
2054#if PLATFORM(MAC)
2055
2056bool WebPage::isSpeaking()
2057{
2058    bool result;
2059    return sendSync(Messages::WebPageProxy::GetIsSpeaking(), Messages::WebPageProxy::GetIsSpeaking::Reply(result)) && result;
2060}
2061
2062void WebPage::speak(const String& string)
2063{
2064    send(Messages::WebPageProxy::Speak(string));
2065}
2066
2067void WebPage::stopSpeaking()
2068{
2069    send(Messages::WebPageProxy::StopSpeaking());
2070}
2071
2072#endif
2073
2074void WebPage::beginPrinting(uint64_t frameID, const PrintInfo& printInfo)
2075{
2076    WebFrame* frame = WebProcess::shared().webFrame(frameID);
2077    if (!frame)
2078        return;
2079
2080    Frame* coreFrame = frame->coreFrame();
2081    if (!coreFrame)
2082        return;
2083
2084    if (!m_printContext)
2085        m_printContext = adoptPtr(new PrintContext(coreFrame));
2086
2087    m_printContext->begin(printInfo.availablePaperWidth, printInfo.availablePaperHeight);
2088
2089    float fullPageHeight;
2090    m_printContext->computePageRects(FloatRect(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight), 0, 0, printInfo.pageSetupScaleFactor, fullPageHeight, true);
2091}
2092
2093void WebPage::endPrinting()
2094{
2095    m_printContext = nullptr;
2096}
2097
2098void WebPage::computePagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, uint64_t callbackID)
2099{
2100    Vector<IntRect> resultPageRects;
2101    double resultTotalScaleFactorForPrinting = 1;
2102
2103    beginPrinting(frameID, printInfo);
2104
2105    if (m_printContext) {
2106        resultPageRects = m_printContext->pageRects();
2107        resultTotalScaleFactorForPrinting = m_printContext->computeAutomaticScaleFactor(FloatSize(printInfo.availablePaperWidth, printInfo.availablePaperHeight)) * printInfo.pageSetupScaleFactor;
2108    }
2109
2110    // If we're asked to print, we should actually print at least a blank page.
2111    if (resultPageRects.isEmpty())
2112        resultPageRects.append(IntRect(0, 0, 1, 1));
2113
2114    send(Messages::WebPageProxy::ComputedPagesCallback(resultPageRects, resultTotalScaleFactorForPrinting, callbackID));
2115}
2116
2117#if PLATFORM(MAC) || PLATFORM(WIN)
2118void WebPage::drawRectToPDF(uint64_t frameID, const WebCore::IntRect& rect, uint64_t callbackID)
2119{
2120    WebFrame* frame = WebProcess::shared().webFrame(frameID);
2121    Frame* coreFrame = frame ? frame->coreFrame() : 0;
2122
2123    RetainPtr<CFMutableDataRef> pdfPageData(AdoptCF, CFDataCreateMutable(0, 0));
2124
2125    if (coreFrame) {
2126        ASSERT(coreFrame->document()->printing());
2127
2128#if USE(CG)
2129        // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
2130        RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get()));
2131
2132        CGRect mediaBox = CGRectMake(0, 0, rect.width(), rect.height());
2133        RetainPtr<CGContextRef> context(AdoptCF, CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0));
2134        RetainPtr<CFDictionaryRef> pageInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
2135        CGPDFContextBeginPage(context.get(), pageInfo.get());
2136
2137        GraphicsContext ctx(context.get());
2138        ctx.scale(FloatSize(1, -1));
2139        ctx.translate(0, -rect.height());
2140        m_printContext->spoolRect(ctx, rect);
2141
2142        CGPDFContextEndPage(context.get());
2143        CGPDFContextClose(context.get());
2144#endif
2145    }
2146
2147    send(Messages::WebPageProxy::DataCallback(CoreIPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID));
2148}
2149
2150void WebPage::drawPagesToPDF(uint64_t frameID, uint32_t first, uint32_t count, uint64_t callbackID)
2151{
2152    WebFrame* frame = WebProcess::shared().webFrame(frameID);
2153    Frame* coreFrame = frame ? frame->coreFrame() : 0;
2154
2155    RetainPtr<CFMutableDataRef> pdfPageData(AdoptCF, CFDataCreateMutable(0, 0));
2156
2157    if (coreFrame) {
2158        ASSERT(coreFrame->document()->printing());
2159
2160#if USE(CG)
2161        // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
2162        RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get()));
2163
2164        CGRect mediaBox = m_printContext->pageCount() ? m_printContext->pageRect(0) : CGRectMake(0, 0, 1, 1);
2165        RetainPtr<CGContextRef> context(AdoptCF, CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0));
2166        for (uint32_t page = first; page < first + count; ++page) {
2167            if (page >= m_printContext->pageCount())
2168                break;
2169
2170            RetainPtr<CFDictionaryRef> pageInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
2171            CGPDFContextBeginPage(context.get(), pageInfo.get());
2172
2173            GraphicsContext ctx(context.get());
2174            ctx.scale(FloatSize(1, -1));
2175            ctx.translate(0, -m_printContext->pageRect(page).height());
2176            m_printContext->spoolPage(ctx, page, m_printContext->pageRect(page).width());
2177
2178            CGPDFContextEndPage(context.get());
2179        }
2180        CGPDFContextClose(context.get());
2181#endif
2182    }
2183
2184    send(Messages::WebPageProxy::DataCallback(CoreIPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID));
2185}
2186#endif
2187
2188void WebPage::runModal()
2189{
2190    if (m_isClosed)
2191        return;
2192    if (m_isRunningModal)
2193        return;
2194
2195    m_isRunningModal = true;
2196    send(Messages::WebPageProxy::RunModal());
2197    RunLoop::run();
2198    ASSERT(!m_isRunningModal);
2199}
2200
2201void WebPage::setMemoryCacheMessagesEnabled(bool memoryCacheMessagesEnabled)
2202{
2203    m_page->setMemoryCacheClientCallsEnabled(memoryCacheMessagesEnabled);
2204}
2205
2206#if !PLATFORM(MAC)
2207void WebPage::platformDragEnded()
2208{
2209}
2210#endif
2211
2212bool WebPage::canHandleRequest(const WebCore::ResourceRequest& request)
2213{
2214    if (SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(request.url().protocol()))
2215        return true;
2216    return platformCanHandleRequest(request);
2217}
2218
2219#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD)
2220void WebPage::handleCorrectionPanelResult(const String& result)
2221{
2222    Frame* frame = m_page->focusController()->focusedOrMainFrame();
2223    if (!frame)
2224        return;
2225    frame->editor()->handleCorrectionPanelResult(result);
2226}
2227#endif
2228
2229void WebPage::simulateMouseDown(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time)
2230{
2231    mouseEvent(WebMouseEvent(WebMouseEvent::MouseDown, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time));
2232}
2233
2234void WebPage::simulateMouseUp(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time)
2235{
2236    mouseEvent(WebMouseEvent(WebMouseEvent::MouseUp, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time));
2237}
2238
2239void WebPage::simulateMouseMotion(WebCore::IntPoint position, double time)
2240{
2241    mouseEvent(WebMouseEvent(WebMouseEvent::MouseMove, WebMouseEvent::NoButton, position, position, 0, 0, 0, 0, WebMouseEvent::Modifiers(), time));
2242}
2243
2244} // namespace WebKit
2245