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