Reviewed by Anders Carlsson and Darin Adler.
[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 "WebPage.h"
27
28 #include "Arguments.h"
29 #include "DataReference.h"
30 #include "DecoderAdapter.h"
31 #include "DrawingArea.h"
32 #include "InjectedBundle.h"
33 #include "InjectedBundleBackForwardList.h"
34 #include "MessageID.h"
35 #include "NetscapePlugin.h"
36 #include "PageOverlay.h"
37 #include "PluginProxy.h"
38 #include "PluginView.h"
39 #include "PrintInfo.h"
40 #include "SessionState.h"
41 #include "ShareableBitmap.h"
42 #include "WebBackForwardList.h"
43 #include "WebBackForwardListItem.h"
44 #include "WebBackForwardListProxy.h"
45 #include "WebChromeClient.h"
46 #include "WebContextMenu.h"
47 #include "WebContextMenuClient.h"
48 #include "WebContextMessages.h"
49 #include "WebCoreArgumentCoders.h"
50 #include "WebDragClient.h"
51 #include "WebEditorClient.h"
52 #include "WebEvent.h"
53 #include "WebEventConversion.h"
54 #include "WebFrame.h"
55 #include "WebGeolocationClient.h"
56 #include "WebImage.h"
57 #include "WebInspector.h"
58 #include "WebInspectorClient.h"
59 #include "WebOpenPanelResultListener.h"
60 #include "WebPageCreationParameters.h"
61 #include "WebPageGroupProxy.h"
62 #include "WebPageProxyMessages.h"
63 #include "WebPopupMenu.h"
64 #include "WebPreferencesStore.h"
65 #include "WebProcess.h"
66 #include "WebProcessProxyMessageKinds.h"
67 #include "WebProcessProxyMessages.h"
68 #include <WebCore/AbstractDatabase.h>
69 #include <WebCore/ArchiveResource.h>
70 #include <WebCore/Chrome.h>
71 #include <WebCore/ContextMenuController.h>
72 #include <WebCore/DocumentFragment.h>
73 #include <WebCore/DocumentLoader.h>
74 #include <WebCore/DocumentMarkerController.h>
75 #include <WebCore/DragController.h>
76 #include <WebCore/DragData.h>
77 #include <WebCore/EventHandler.h>
78 #include <WebCore/FocusController.h>
79 #include <WebCore/Frame.h>
80 #include <WebCore/FrameLoaderTypes.h>
81 #include <WebCore/FrameView.h>
82 #include <WebCore/HistoryItem.h>
83 #include <WebCore/KeyboardEvent.h>
84 #include <WebCore/Page.h>
85 #include <WebCore/PlatformKeyboardEvent.h>
86 #include <WebCore/PrintContext.h>
87 #include <WebCore/RenderTreeAsText.h>
88 #include <WebCore/RenderLayer.h>
89 #include <WebCore/RenderView.h>
90 #include <WebCore/ReplaceSelectionCommand.h>
91 #include <WebCore/ResourceRequest.h>
92 #include <WebCore/Settings.h>
93 #include <WebCore/SharedBuffer.h>
94 #include <WebCore/SubstituteData.h>
95 #include <WebCore/TextIterator.h>
96 #include <WebCore/markup.h>
97 #include <runtime/JSLock.h>
98 #include <runtime/JSValue.h>
99
100 #if PLATFORM(MAC) || PLATFORM(WIN)
101 #include <WebCore/LegacyWebArchive.h>
102 #endif
103
104 #if ENABLE(PLUGIN_PROCESS)
105 // FIXME: This is currently Mac-specific!
106 #include "MachPort.h"
107 #endif
108
109 #if PLATFORM(QT)
110 #include "HitTestResult.h"
111 #endif
112
113 #ifndef NDEBUG
114 #include <wtf/RefCountedLeakCounter.h>
115 #endif
116
117 using namespace JSC;
118 using namespace WebCore;
119
120 namespace WebKit {
121
122 #ifndef NDEBUG
123 static WTF::RefCountedLeakCounter webPageCounter("WebPage");
124 #endif
125
126 PassRefPtr<WebPage> WebPage::create(uint64_t pageID, const WebPageCreationParameters& parameters)
127 {
128     RefPtr<WebPage> page = adoptRef(new WebPage(pageID, parameters));
129
130     if (page->pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())
131         WebProcess::shared().injectedBundle()->didCreatePage(page.get());
132
133     return page.release();
134 }
135
136 WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
137     : m_viewSize(parameters.viewSize)
138     , m_drawsBackground(true)
139     , m_drawsTransparentBackground(false)
140     , m_isInRedo(false)
141     , m_isClosed(false)
142     , m_tabToLinks(false)
143 #if PLATFORM(MAC)
144     , m_windowIsVisible(false)
145     , m_isSmartInsertDeleteEnabled(parameters.isSmartInsertDeleteEnabled)
146 #elif PLATFORM(WIN)
147     , m_nativeWindow(parameters.nativeWindow)
148 #endif
149     , m_findController(this)
150     , m_geolocationPermissionRequestManager(this)
151     , m_pageID(pageID)
152 {
153     ASSERT(m_pageID);
154
155     Page::PageClients pageClients;
156     pageClients.chromeClient = new WebChromeClient(this);
157     pageClients.contextMenuClient = new WebContextMenuClient(this);
158     pageClients.editorClient = new WebEditorClient(this);
159     pageClients.dragClient = new WebDragClient(this);
160     pageClients.backForwardClient = WebBackForwardListProxy::create(this);
161 #if ENABLE(CLIENT_BASED_GEOLOCATION)
162     pageClients.geolocationClient = new WebGeolocationClient(this);
163 #endif
164 #if ENABLE(INSPECTOR)
165     pageClients.inspectorClient = new WebInspectorClient(this);
166 #endif
167     m_page = adoptPtr(new Page(pageClients));
168
169     // Qt does not yet call setIsInWindow. Until it does, just leave
170     // this line out so plug-ins and video will work. Eventually all platforms
171     // should call setIsInWindow and this comment and #if should be removed,
172     // leaving behind the setCanStartMedia call.
173 #if !PLATFORM(QT)
174     m_page->setCanStartMedia(false);
175 #endif
176
177     updatePreferences(parameters.store);
178
179     m_pageGroup = WebProcess::shared().webPageGroup(parameters.pageGroupData);
180     m_page->setGroupName(m_pageGroup->identifier());
181
182     platformInitialize();
183     Settings::setMinDOMTimerInterval(0.004);
184
185     m_drawingArea = DrawingArea::create(parameters.drawingAreaInfo.type, parameters.drawingAreaInfo.identifier, this);
186     m_mainFrame = WebFrame::createMainFrame(this);
187
188     setDrawsBackground(parameters.drawsBackground);
189     setDrawsTransparentBackground(parameters.drawsTransparentBackground);
190
191     setActive(parameters.isActive);
192     setFocused(parameters.isFocused);
193     setIsInWindow(parameters.isInWindow);
194
195     m_userAgent = parameters.userAgent;
196
197     WebBackForwardListProxy::setHighestItemIDFromUIProcess(parameters.highestUsedBackForwardItemID);
198     
199     if (!parameters.sessionState.isEmpty())
200         restoreSession(parameters.sessionState);
201
202 #ifndef NDEBUG
203     webPageCounter.increment();
204 #endif
205 }
206
207 WebPage::~WebPage()
208 {
209     if (m_backForwardList)
210         m_backForwardList->detach();
211
212     ASSERT(!m_page);
213
214     m_sandboxExtensionTracker.invalidate();
215
216 #if PLATFORM(MAC)
217     ASSERT(m_pluginViews.isEmpty());
218 #endif
219
220 #ifndef NDEBUG
221     webPageCounter.decrement();
222 #endif
223 }
224
225 void WebPage::dummy(bool&)
226 {
227 }
228
229 CoreIPC::Connection* WebPage::connection() const
230 {
231     return WebProcess::shared().connection();
232 }
233
234 void WebPage::initializeInjectedBundleContextMenuClient(WKBundlePageContextMenuClient* client)
235 {
236     m_contextMenuClient.initialize(client);
237 }
238
239 void WebPage::initializeInjectedBundleEditorClient(WKBundlePageEditorClient* client)
240 {
241     m_editorClient.initialize(client);
242 }
243
244 void WebPage::initializeInjectedBundleFormClient(WKBundlePageFormClient* client)
245 {
246     m_formClient.initialize(client);
247 }
248
249 void WebPage::initializeInjectedBundleLoaderClient(WKBundlePageLoaderClient* client)
250 {
251     m_loaderClient.initialize(client);
252 }
253
254 void WebPage::initializeInjectedBundleUIClient(WKBundlePageUIClient* client)
255 {
256     m_uiClient.initialize(client);
257 }
258
259 PassRefPtr<Plugin> WebPage::createPlugin(const Plugin::Parameters& parameters)
260 {
261     String pluginPath;
262
263     if (!WebProcess::shared().connection()->sendSync(
264             Messages::WebContext::GetPluginPath(parameters.mimeType, parameters.url.string()), 
265             Messages::WebContext::GetPluginPath::Reply(pluginPath), 0)) {
266         return 0;
267     }
268
269     if (pluginPath.isNull())
270         return 0;
271
272 #if ENABLE(PLUGIN_PROCESS)
273     return PluginProxy::create(pluginPath);
274 #else
275     return NetscapePlugin::create(NetscapePluginModule::getOrCreate(pluginPath));
276 #endif
277 }
278
279 String WebPage::renderTreeExternalRepresentation() const
280 {
281     return externalRepresentation(m_mainFrame->coreFrame(), RenderAsTextBehaviorNormal);
282 }
283
284 void WebPage::executeEditingCommand(const String& commandName, const String& argument)
285 {
286     Frame* frame = m_page->focusController()->focusedOrMainFrame();
287     if (!frame)
288         return;
289     frame->editor()->command(commandName).execute(argument);
290 }
291
292 bool WebPage::isEditingCommandEnabled(const String& commandName)
293 {
294     Frame* frame = m_page->focusController()->focusedOrMainFrame();
295     if (!frame)
296         return false;
297     
298     Editor::Command command = frame->editor()->command(commandName);
299     return command.isSupported() && command.isEnabled();
300 }
301     
302 void WebPage::clearMainFrameName()
303 {
304     mainFrame()->coreFrame()->tree()->clearName();
305 }
306
307 #if USE(ACCELERATED_COMPOSITING)
308 void WebPage::changeAcceleratedCompositingMode(WebCore::GraphicsLayer* layer)
309 {
310     if (m_isClosed)
311         return;
312
313     bool compositing = layer;
314     
315     // Tell the UI process that accelerated compositing changed. It may respond by changing
316     // drawing area types.
317     DrawingAreaInfo newDrawingAreaInfo;
318
319     if (!sendSync(Messages::WebPageProxy::DidChangeAcceleratedCompositing(compositing), Messages::WebPageProxy::DidChangeAcceleratedCompositing::Reply(newDrawingAreaInfo)))
320         return;
321     
322     if (newDrawingAreaInfo.type != drawingArea()->info().type) {
323         m_drawingArea = 0;
324         if (newDrawingAreaInfo.type != DrawingAreaInfo::None) {
325             m_drawingArea = DrawingArea::create(newDrawingAreaInfo.type, newDrawingAreaInfo.identifier, this);
326             m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
327         }
328     }
329 }
330
331 void WebPage::enterAcceleratedCompositingMode(GraphicsLayer* layer)
332 {
333     changeAcceleratedCompositingMode(layer);
334     m_drawingArea->setRootCompositingLayer(layer);
335 }
336
337 void WebPage::exitAcceleratedCompositingMode()
338 {
339     changeAcceleratedCompositingMode(0);
340 }
341 #endif
342
343 void WebPage::close()
344 {
345     if (m_isClosed)
346         return;
347
348     m_isClosed = true;
349
350     if (pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())
351         WebProcess::shared().injectedBundle()->willDestroyPage(this);
352
353 #if ENABLE(INSPECTOR)
354     m_inspector = 0;
355 #endif
356
357     if (m_activePopupMenu) {
358         m_activePopupMenu->disconnectFromPage();
359         m_activePopupMenu = 0;
360     }
361
362     if (m_activeOpenPanelResultListener) {
363         m_activeOpenPanelResultListener->disconnectFromPage();
364         m_activeOpenPanelResultListener = 0;
365     }
366
367     m_sandboxExtensionTracker.invalidate();
368
369     m_printContext = nullptr;
370
371     m_mainFrame->coreFrame()->loader()->detachFromParent();
372     m_page.clear();
373
374     m_drawingArea->onPageClose();
375     m_drawingArea.clear();
376
377     WebProcess::shared().removeWebPage(m_pageID);
378 }
379
380 void WebPage::tryClose()
381 {
382     if (!m_mainFrame->coreFrame()->loader()->shouldClose())
383         return;
384
385     sendClose();
386 }
387
388 void WebPage::sendClose()
389 {
390     send(Messages::WebPageProxy::ClosePage());
391 }
392
393 void WebPage::loadURL(const String& url, const SandboxExtension::Handle& sandboxExtensionHandle)
394 {
395     loadURLRequest(ResourceRequest(KURL(KURL(), url)), sandboxExtensionHandle);
396 }
397
398 void WebPage::loadURLRequest(const ResourceRequest& request, const SandboxExtension::Handle& sandboxExtensionHandle)
399 {
400     m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
401     m_mainFrame->coreFrame()->loader()->load(request, false);
402 }
403
404 void WebPage::loadData(PassRefPtr<SharedBuffer> sharedBuffer, const String& MIMEType, const String& encodingName, const KURL& baseURL, const KURL& unreachableURL)
405 {
406     ResourceRequest request(baseURL);
407     SubstituteData substituteData(sharedBuffer, MIMEType, encodingName, unreachableURL);
408     m_mainFrame->coreFrame()->loader()->load(request, substituteData, false);
409 }
410
411 void WebPage::loadHTMLString(const String& htmlString, const String& baseURLString)
412 {
413     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar));
414     KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString);
415     loadData(sharedBuffer, "text/html", "utf-16", baseURL, KURL());
416 }
417
418 void WebPage::loadAlternateHTMLString(const String& htmlString, const String& baseURLString, const String& unreachableURLString)
419 {
420     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar));
421     KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString);
422     KURL unreachableURL = unreachableURLString.isEmpty() ? KURL() : KURL(KURL(), unreachableURLString)  ;
423     loadData(sharedBuffer, "text/html", "utf-16", baseURL, unreachableURL);
424 }
425
426 void WebPage::loadPlainTextString(const String& string)
427 {
428     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(string.characters()), string.length() * sizeof(UChar));
429     loadData(sharedBuffer, "text/plain", "utf-16", blankURL(), KURL());
430 }
431
432 void WebPage::stopLoading()
433 {
434     m_mainFrame->coreFrame()->loader()->stopForUserCancel();
435 }
436
437 void WebPage::setDefersLoading(bool defersLoading)
438 {
439     m_page->setDefersLoading(defersLoading);
440 }
441
442 void WebPage::reload(bool reloadFromOrigin)
443 {
444     m_mainFrame->coreFrame()->loader()->reload(reloadFromOrigin);
445 }
446
447 void WebPage::goForward(uint64_t backForwardItemID)
448 {
449     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
450     m_page->goToItem(item, FrameLoadTypeForward);
451 }
452
453 void WebPage::goBack(uint64_t backForwardItemID)
454 {
455     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
456     m_page->goToItem(item, FrameLoadTypeBack);
457 }
458
459 void WebPage::goToBackForwardItem(uint64_t backForwardItemID)
460 {
461     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
462     m_page->goToItem(item, FrameLoadTypeIndexedBackForward);
463 }
464
465 void WebPage::layoutIfNeeded()
466 {
467     if (m_mainFrame->coreFrame()->view())
468         m_mainFrame->coreFrame()->view()->updateLayoutAndStyleIfNeededRecursive();
469 }
470
471 void WebPage::setSize(const WebCore::IntSize& viewSize)
472 {
473 #if ENABLE(TILED_BACKING_STORE)
474     // If we are resizing to content ignore external attempts.
475     if (!m_resizesToContentsLayoutSize.isEmpty())
476         return;
477 #endif
478
479     if (m_viewSize == viewSize)
480         return;
481
482     Frame* frame = m_page->mainFrame();
483     
484     frame->view()->resize(viewSize);
485     frame->view()->setNeedsLayout();
486     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), viewSize));
487     
488     m_viewSize = viewSize;
489 }
490
491 #if ENABLE(TILED_BACKING_STORE)
492 void WebPage::setActualVisibleContentRect(const IntRect& rect)
493 {
494     Frame* frame = m_page->mainFrame();
495
496     frame->view()->setActualVisibleContentRect(rect);
497 }
498
499 void WebPage::setResizesToContentsUsingLayoutSize(const IntSize& targetLayoutSize)
500 {
501     if (m_resizesToContentsLayoutSize == targetLayoutSize)
502         return;
503
504     m_resizesToContentsLayoutSize = targetLayoutSize;
505
506     Frame* frame = m_page->mainFrame();
507     if (m_resizesToContentsLayoutSize.isEmpty()) {
508         frame->view()->setDelegatesScrolling(false);
509         frame->view()->setUseFixedLayout(false);
510         frame->view()->setPaintsEntireContents(false);
511     } else {
512         frame->view()->setDelegatesScrolling(true);
513         frame->view()->setUseFixedLayout(true);
514         frame->view()->setPaintsEntireContents(true);
515         frame->view()->setFixedLayoutSize(m_resizesToContentsLayoutSize);
516     }
517     frame->view()->forceLayout();
518 }
519
520 void WebPage::resizeToContentsIfNeeded()
521 {
522     if (m_resizesToContentsLayoutSize.isEmpty())
523         return;
524
525     Frame* frame = m_page->mainFrame();
526
527     IntSize contentSize = frame->view()->contentsSize();
528     if (contentSize == m_viewSize)
529         return;
530
531     m_viewSize = contentSize;
532     frame->view()->resize(m_viewSize);
533     frame->view()->setNeedsLayout();
534 }
535 #endif
536
537 void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect)
538 {
539     graphicsContext.save();
540     graphicsContext.clip(rect);
541     m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect);
542     graphicsContext.restore();
543
544     if (m_pageOverlay) {
545         graphicsContext.save();
546         graphicsContext.clip(rect);
547         m_pageOverlay->drawRect(graphicsContext, rect);
548         graphicsContext.restore();
549     }
550 }
551
552 double WebPage::textZoomFactor() const
553 {
554     Frame* frame = m_mainFrame->coreFrame();
555     if (!frame)
556         return 1;
557     return frame->textZoomFactor();
558 }
559
560 void WebPage::setTextZoomFactor(double zoomFactor)
561 {
562     Frame* frame = m_mainFrame->coreFrame();
563     if (!frame)
564         return;
565     frame->setTextZoomFactor(static_cast<float>(zoomFactor));
566 }
567
568 double WebPage::pageZoomFactor() const
569 {
570     Frame* frame = m_mainFrame->coreFrame();
571     if (!frame)
572         return 1;
573     return frame->pageZoomFactor();
574 }
575
576 void WebPage::setPageZoomFactor(double zoomFactor)
577 {
578     Frame* frame = m_mainFrame->coreFrame();
579     if (!frame)
580         return;
581     frame->setPageZoomFactor(static_cast<float>(zoomFactor));
582 }
583
584 void WebPage::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
585 {
586     Frame* frame = m_mainFrame->coreFrame();
587     if (!frame)
588         return;
589     return frame->setPageAndTextZoomFactors(static_cast<float>(pageZoomFactor), static_cast<float>(textZoomFactor));
590 }
591
592 void WebPage::scaleWebView(double scale, const IntPoint& origin)
593 {
594     Frame* frame = m_mainFrame->coreFrame();
595     if (!frame)
596         return;
597     frame->scalePage(scale, origin);
598 }
599
600 double WebPage::viewScaleFactor() const
601 {
602     Frame* frame = m_mainFrame->coreFrame();
603     if (!frame)
604         return 1;
605     return frame->pageScaleFactor();
606 }
607
608 void WebPage::setUseFixedLayout(bool fixed)
609 {
610     Frame* frame = m_mainFrame->coreFrame();
611     if (!frame)
612         return;
613
614     FrameView* view = frame->view();
615     if (!view)
616         return;
617
618     view->setUseFixedLayout(fixed);
619     if (!fixed)
620         view->setFixedLayoutSize(IntSize());
621 }
622
623 void WebPage::setFixedLayoutSize(const IntSize& size)
624 {
625     Frame* frame = m_mainFrame->coreFrame();
626     if (!frame)
627         return;
628     
629     FrameView* view = frame->view();
630     if (!view)
631         return;
632
633     view->setFixedLayoutSize(size);
634     view->forceLayout();
635 }
636
637 void WebPage::installPageOverlay(PassRefPtr<PageOverlay> pageOverlay)
638 {
639     if (m_pageOverlay)
640         pageOverlay->setPage(0);
641
642     m_pageOverlay = pageOverlay;
643     m_pageOverlay->setPage(this);
644     m_pageOverlay->setNeedsDisplay();
645 }
646
647 void WebPage::uninstallPageOverlay(PageOverlay* pageOverlay)
648 {
649     if (pageOverlay != m_pageOverlay)
650         return;
651
652     m_pageOverlay->setPage(0);
653     m_pageOverlay = nullptr;
654     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
655 }
656
657 PassRefPtr<WebImage> WebPage::snapshotInViewCoordinates(const IntRect& rect, ImageOptions options)
658 {
659     FrameView* frameView = m_mainFrame->coreFrame()->view();
660     if (!frameView)
661         return 0;
662
663     frameView->updateLayoutAndStyleIfNeededRecursive();
664
665     PaintBehavior oldBehavior = frameView->paintBehavior();
666     frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
667
668     RefPtr<WebImage> snapshot = WebImage::create(rect.size(), options);
669     OwnPtr<WebCore::GraphicsContext> graphicsContext = snapshot->bitmap()->createGraphicsContext();
670
671     graphicsContext->save();
672     graphicsContext->translate(-rect.x(), -rect.y());
673     frameView->paint(graphicsContext.get(), rect);
674     graphicsContext->restore();
675
676     frameView->setPaintBehavior(oldBehavior);
677
678     return snapshot.release();
679 }
680
681 PassRefPtr<WebImage> WebPage::snapshotInDocumentCoordinates(const IntRect& rect, ImageOptions options)
682 {
683     FrameView* frameView = m_mainFrame->coreFrame()->view();
684     if (!frameView)
685         return 0;
686
687     frameView->updateLayoutAndStyleIfNeededRecursive();
688
689     PaintBehavior oldBehavior = frameView->paintBehavior();
690     frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
691
692     RefPtr<WebImage> snapshot = WebImage::create(rect.size(), options);
693     OwnPtr<WebCore::GraphicsContext> graphicsContext = snapshot->bitmap()->createGraphicsContext();
694
695     graphicsContext->save();
696     graphicsContext->translate(-rect.x(), -rect.y());
697     frameView->paintContents(graphicsContext.get(), rect);
698     graphicsContext->restore();
699
700     frameView->setPaintBehavior(oldBehavior);
701
702     return snapshot.release();
703 }
704
705 void WebPage::pageDidScroll()
706 {
707     // Hide the find indicator.
708     m_findController.hideFindIndicator();
709
710     m_uiClient.pageDidScroll(this);
711
712     send(Messages::WebPageProxy::PageDidScroll());
713 }
714
715 #if ENABLE(TILED_BACKING_STORE)
716 void WebPage::pageDidRequestScroll(const IntSize& delta)
717 {
718     send(Messages::WebPageProxy::PageDidRequestScroll(delta));
719 }
720 #endif
721
722 WebContextMenu* WebPage::contextMenu()
723 {
724     if (!m_contextMenu)
725         m_contextMenu = WebContextMenu::create(this);
726     return m_contextMenu.get();
727 }
728
729 void WebPage::getLocationAndLengthFromRange(Range* range, uint64_t& location, uint64_t& length)
730 {
731     location = notFound;
732     length = 0;
733
734     if (!range || !range->startContainer())
735         return;
736
737     Element* selectionRoot = range->ownerDocument()->frame()->selection()->rootEditableElement();
738     Element* scope = selectionRoot ? selectionRoot : range->ownerDocument()->documentElement();
739     
740     // Mouse events may cause TSM to attempt to create an NSRange for a portion of the view
741     // that is not inside the current editable region.  These checks ensure we don't produce
742     // potentially invalid data when responding to such requests.
743     if (range->startContainer() != scope && !range->startContainer()->isDescendantOf(scope))
744         return;
745     if (range->endContainer() != scope && !range->endContainer()->isDescendantOf(scope))
746         return;
747
748     RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
749     ASSERT(testRange->startContainer() == scope);
750     location = TextIterator::rangeLength(testRange.get());
751     
752     ExceptionCode ec;
753     testRange->setEnd(range->endContainer(), range->endOffset(), ec);
754     ASSERT(testRange->startContainer() == scope);
755     length = TextIterator::rangeLength(testRange.get()) - location;
756 }
757
758 // Events 
759
760 static const WebEvent* g_currentEvent = 0;
761
762 // FIXME: WebPage::currentEvent is used by the plug-in code to avoid having to convert from DOM events back to
763 // WebEvents. When we get the event handling sorted out, this should go away and the Widgets should get the correct
764 // platform events passed to the event handler code.
765 const WebEvent* WebPage::currentEvent()
766 {
767     return g_currentEvent;
768 }
769
770 class CurrentEvent {
771 public:
772     explicit CurrentEvent(const WebEvent& event)
773         : m_previousCurrentEvent(g_currentEvent)
774     {
775         g_currentEvent = &event;
776     }
777
778     ~CurrentEvent()
779     {
780         g_currentEvent = m_previousCurrentEvent;
781     }
782
783 private:
784     const WebEvent* m_previousCurrentEvent;
785 };
786
787 static bool isContextClick(const PlatformMouseEvent& event)
788 {
789     if (event.button() == WebCore::RightButton)
790         return true;
791
792 #if PLATFORM(MAC)
793     // FIXME: this really should be about OSX-style UI, not about the Mac port
794     if (event.button() == WebCore::LeftButton && event.ctrlKey())
795         return true;
796 #endif
797
798     return false;
799 }
800
801 static bool handleMouseEvent(const WebMouseEvent& mouseEvent, Page* page)
802 {
803     Frame* frame = page->mainFrame();
804     if (!frame->view())
805         return false;
806
807     PlatformMouseEvent platformMouseEvent = platform(mouseEvent);
808
809     switch (platformMouseEvent.eventType()) {
810         case WebCore::MouseEventPressed:
811         {
812             if (isContextClick(platformMouseEvent))
813                 page->contextMenuController()->clearContextMenu();
814             
815             bool handled = frame->eventHandler()->handleMousePressEvent(platformMouseEvent);
816             
817             if (isContextClick(platformMouseEvent)) {
818                 handled = frame->eventHandler()->sendContextMenuEvent(platformMouseEvent);
819                 if (handled)
820                     page->chrome()->showContextMenu();
821             }
822
823             return handled;
824         }
825         case WebCore::MouseEventReleased:
826             return frame->eventHandler()->handleMouseReleaseEvent(platformMouseEvent);
827         case WebCore::MouseEventMoved:
828             return frame->eventHandler()->mouseMoved(platformMouseEvent);
829
830         default:
831             ASSERT_NOT_REACHED();
832             return false;
833     }
834 }
835
836 void WebPage::mouseEvent(const WebMouseEvent& mouseEvent)
837 {
838     bool handled = false;
839     
840     if (m_pageOverlay) {
841         // Let the page overlay handle the event.
842         handled = m_pageOverlay->mouseEvent(mouseEvent);
843     }
844
845     if (!handled) {
846         CurrentEvent currentEvent(mouseEvent);
847
848         handled = handleMouseEvent(mouseEvent, m_page.get());
849     }
850
851     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), handled));
852 }
853
854 static bool handleWheelEvent(const WebWheelEvent& wheelEvent, Page* page)
855 {
856     Frame* frame = page->mainFrame();
857     if (!frame->view())
858         return false;
859
860     PlatformWheelEvent platformWheelEvent = platform(wheelEvent);
861     return frame->eventHandler()->handleWheelEvent(platformWheelEvent);
862 }
863
864 void WebPage::wheelEvent(const WebWheelEvent& wheelEvent)
865 {
866     CurrentEvent currentEvent(wheelEvent);
867
868     bool handled = handleWheelEvent(wheelEvent, m_page.get());
869     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(wheelEvent.type()), handled));
870 }
871
872 static bool handleKeyEvent(const WebKeyboardEvent& keyboardEvent, Page* page)
873 {
874     if (!page->mainFrame()->view())
875         return false;
876
877     if (keyboardEvent.type() == WebEvent::Char && keyboardEvent.isSystemKey())
878         return page->focusController()->focusedOrMainFrame()->eventHandler()->handleAccessKey(platform(keyboardEvent));
879     return page->focusController()->focusedOrMainFrame()->eventHandler()->keyEvent(platform(keyboardEvent));
880 }
881
882 void WebPage::keyEvent(const WebKeyboardEvent& keyboardEvent)
883 {
884     CurrentEvent currentEvent(keyboardEvent);
885
886     bool handled = handleKeyEvent(keyboardEvent, m_page.get());
887     if (!handled)
888         handled = performDefaultBehaviorForKeyEvent(keyboardEvent);
889
890     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(keyboardEvent.type()), handled));
891 }
892
893 void WebPage::validateMenuItem(const String& commandName)
894 {
895     bool isEnabled = false;
896     int32_t state = 0;
897     Frame* frame = m_page->focusController()->focusedOrMainFrame();
898     if (frame) {
899         Editor::Command command = frame->editor()->command(commandName);
900         state = command.state();
901         isEnabled = command.isSupported() && command.isEnabled();
902     }
903
904     send(Messages::WebPageProxy::DidValidateMenuItem(commandName, isEnabled, state));
905 }
906
907 void WebPage::executeEditCommand(const String& commandName)
908 {
909     executeEditingCommand(commandName, String());
910 }
911
912 uint64_t WebPage::restoreSession(const SessionState& sessionState)
913 {
914     const BackForwardListItemVector& list = sessionState.list();
915     size_t size = list.size();
916     uint64_t currentItemID = 0;
917     for (size_t i = 0; i < size; ++i) {
918         WebBackForwardListItem* webItem = list[i].get();
919         DecoderAdapter decoder(webItem->backForwardData().data(), webItem->backForwardData().size());
920         
921         RefPtr<HistoryItem> item = HistoryItem::decodeBackForwardTree(webItem->url(), webItem->title(), webItem->originalURL(), decoder);
922         if (!item) {
923             LOG_ERROR("Failed to decode a HistoryItem from session state data.");
924             return 0;
925         }
926         
927         if (i == sessionState.currentIndex())
928             currentItemID = webItem->itemID();
929         
930         WebBackForwardListProxy::addItemFromUIProcess(list[i]->itemID(), item.release());
931     }    
932     ASSERT(currentItemID);
933     return currentItemID;
934 }
935
936 void WebPage::restoreSessionAndNavigateToCurrentItem(const SessionState& sessionState)
937 {
938     if (uint64_t currentItemID = restoreSession(sessionState))
939         goToBackForwardItem(currentItemID);
940 }
941
942 #if ENABLE(TOUCH_EVENTS)
943 static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page)
944 {
945     Frame* frame = page->mainFrame();
946     if (!frame->view())
947         return false;
948
949     return frame->eventHandler()->handleTouchEvent(platform(touchEvent));
950 }
951
952 void WebPage::touchEvent(const WebTouchEvent& touchEvent)
953 {
954     CurrentEvent currentEvent(touchEvent);
955
956     bool handled = handleTouchEvent(touchEvent, m_page.get());
957
958     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(touchEvent.type()), handled));
959 }
960 #endif
961
962 void WebPage::setActive(bool isActive)
963 {
964     m_page->focusController()->setActive(isActive);
965
966 #if PLATFORM(MAC)    
967     // Tell all our plug-in views that the window focus changed.
968     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
969         (*it)->setWindowIsFocused(isActive);
970 #endif
971 }
972
973 void WebPage::setDrawsBackground(bool drawsBackground)
974 {
975     if (m_drawsBackground == drawsBackground)
976         return;
977
978     m_drawsBackground = drawsBackground;
979
980     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
981         if (FrameView* view = coreFrame->view())
982             view->setTransparent(!drawsBackground);
983     }
984
985     m_drawingArea->pageBackgroundTransparencyChanged();
986     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
987 }
988
989 void WebPage::setDrawsTransparentBackground(bool drawsTransparentBackground)
990 {
991     if (m_drawsTransparentBackground == drawsTransparentBackground)
992         return;
993
994     m_drawsTransparentBackground = drawsTransparentBackground;
995
996     Color backgroundColor = drawsTransparentBackground ? Color::transparent : Color::white;
997     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
998         if (FrameView* view = coreFrame->view())
999             view->setBaseBackgroundColor(backgroundColor);
1000     }
1001
1002     m_drawingArea->pageBackgroundTransparencyChanged();
1003     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
1004 }
1005
1006 void WebPage::setFocused(bool isFocused)
1007 {
1008     m_page->focusController()->setFocused(isFocused);
1009 }
1010
1011 void WebPage::setInitialFocus(bool forward)
1012 {
1013     if (!m_page || !m_page->focusController())
1014         return;
1015
1016     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1017     frame->document()->setFocusedNode(0);
1018     m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, 0);
1019 }
1020
1021 void WebPage::setWindowResizerSize(const IntSize& windowResizerSize)
1022 {
1023     if (m_windowResizerSize == windowResizerSize)
1024         return;
1025
1026     m_windowResizerSize = windowResizerSize;
1027
1028     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
1029         FrameView* view = coreFrame->view();
1030         if (view)
1031             view->windowResizerRectChanged();
1032     }
1033 }
1034
1035 void WebPage::setIsInWindow(bool isInWindow)
1036 {
1037     if (!isInWindow) {
1038         m_page->setCanStartMedia(false);
1039         m_page->willMoveOffscreen();
1040     } else {
1041         m_page->setCanStartMedia(true);
1042         m_page->didMoveOnscreen();
1043     }
1044 }
1045
1046 void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t downloadID)
1047 {
1048     WebFrame* frame = WebProcess::shared().webFrame(frameID);
1049     if (!frame)
1050         return;
1051     frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), downloadID);
1052 }
1053
1054 void WebPage::show()
1055 {
1056     send(Messages::WebPageProxy::ShowPage());
1057 }
1058
1059 void WebPage::setUserAgent(const String& userAgent)
1060 {
1061     m_userAgent = userAgent;
1062 }
1063
1064 IntRect WebPage::windowResizerRect() const
1065 {
1066     if (m_windowResizerSize.isEmpty())
1067         return IntRect();
1068
1069     IntSize frameViewSize;
1070     if (Frame* coreFrame = m_mainFrame->coreFrame()) {
1071         if (FrameView* view = coreFrame->view())
1072             frameViewSize = view->size();
1073     }
1074
1075     return IntRect(frameViewSize.width() - m_windowResizerSize.width(), frameViewSize.height() - m_windowResizerSize.height(), 
1076                    m_windowResizerSize.width(), m_windowResizerSize.height());
1077 }
1078
1079 void WebPage::runJavaScriptInMainFrame(const String& script, uint64_t callbackID)
1080 {
1081     // NOTE: We need to be careful when running scripts that the objects we depend on don't
1082     // disappear during script execution.
1083
1084     JSLock lock(SilenceAssertionsOnly);
1085     JSValue resultValue = m_mainFrame->coreFrame()->script()->executeScript(script, true).jsValue();
1086     String resultString;
1087     if (resultValue)
1088         resultString = ustringToString(resultValue.toString(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec()));
1089
1090     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1091 }
1092
1093 void WebPage::getContentsAsString(uint64_t callbackID)
1094 {
1095     String resultString = m_mainFrame->contentsAsString();
1096     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1097 }
1098
1099 void WebPage::getRenderTreeExternalRepresentation(uint64_t callbackID)
1100 {
1101     String resultString = renderTreeExternalRepresentation();
1102     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1103 }
1104
1105 void WebPage::getSelectionOrContentsAsString(uint64_t callbackID)
1106 {
1107     String resultString = m_mainFrame->selectionAsString();
1108     if (resultString.isEmpty())
1109         resultString = m_mainFrame->contentsAsString();
1110     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1111 }
1112
1113 void WebPage::getSourceForFrame(uint64_t frameID, uint64_t callbackID)
1114 {
1115     String resultString;
1116     if (WebFrame* frame = WebProcess::shared().webFrame(frameID))
1117        resultString = frame->source();
1118
1119     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1120 }
1121
1122 void WebPage::getMainResourceDataOfFrame(uint64_t frameID, uint64_t callbackID)
1123 {
1124     CoreIPC::DataReference dataReference;
1125
1126     RefPtr<SharedBuffer> buffer;
1127     if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1128         if (DocumentLoader* loader = frame->coreFrame()->loader()->documentLoader()) {
1129             if ((buffer = loader->mainResourceData()))
1130                 dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size());
1131         }
1132     }
1133
1134     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1135 }
1136
1137 void WebPage::getWebArchiveOfFrame(uint64_t frameID, uint64_t callbackID)
1138 {
1139     CoreIPC::DataReference dataReference;
1140
1141 #if PLATFORM(MAC) || PLATFORM(WIN)
1142     RetainPtr<CFDataRef> data;
1143     if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1144         if (RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(frame->coreFrame())) {
1145             if ((data = archive->rawDataRepresentation()))
1146                 dataReference = CoreIPC::DataReference(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get()));
1147         }
1148     }
1149 #endif
1150
1151     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1152 }
1153
1154 void WebPage::preferencesDidChange(const WebPreferencesStore& store)
1155 {
1156     WebPreferencesStore::removeTestRunnerOverrides();
1157     updatePreferences(store);
1158 }
1159
1160 void WebPage::updatePreferences(const WebPreferencesStore& store)
1161 {
1162     Settings* settings = m_page->settings();
1163
1164     m_tabToLinks = store.getBoolValueForKey(WebPreferencesKey::tabsToLinksKey());
1165
1166     // FIXME: This should be generated from macro expansion for all preferences,
1167     // but we currently don't match the naming of WebCore exactly so we are
1168     // handrolling the boolean and integer preferences until that is fixed.
1169
1170 #define INITIALIZE_SETTINGS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) settings->set##KeyUpper(store.get##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key()));
1171
1172     FOR_EACH_WEBKIT_STRING_PREFERENCE(INITIALIZE_SETTINGS)
1173
1174 #undef INITIALIZE_SETTINGS
1175
1176     settings->setJavaScriptEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptEnabledKey()));
1177     settings->setLoadsImagesAutomatically(store.getBoolValueForKey(WebPreferencesKey::loadsImagesAutomaticallyKey()));
1178     settings->setPluginsEnabled(store.getBoolValueForKey(WebPreferencesKey::pluginsEnabledKey()));
1179     settings->setJavaEnabled(store.getBoolValueForKey(WebPreferencesKey::javaEnabledKey()));
1180     settings->setOfflineWebApplicationCacheEnabled(store.getBoolValueForKey(WebPreferencesKey::offlineWebApplicationCacheEnabledKey()));
1181     settings->setLocalStorageEnabled(store.getBoolValueForKey(WebPreferencesKey::localStorageEnabledKey()));
1182     settings->setXSSAuditorEnabled(store.getBoolValueForKey(WebPreferencesKey::xssAuditorEnabledKey()));
1183     settings->setFrameFlatteningEnabled(store.getBoolValueForKey(WebPreferencesKey::frameFlatteningEnabledKey()));
1184     settings->setPrivateBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey()));
1185     settings->setDeveloperExtrasEnabled(store.getBoolValueForKey(WebPreferencesKey::developerExtrasEnabledKey()));
1186     settings->setTextAreasAreResizable(store.getBoolValueForKey(WebPreferencesKey::textAreasAreResizableKey()));
1187     settings->setNeedsSiteSpecificQuirks(store.getBoolValueForKey(WebPreferencesKey::needsSiteSpecificQuirksKey()));
1188     settings->setJavaScriptCanOpenWindowsAutomatically(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanOpenWindowsAutomaticallyKey()));
1189     settings->setForceFTPDirectoryListings(store.getBoolValueForKey(WebPreferencesKey::forceFTPDirectoryListingsKey()));
1190     settings->setDNSPrefetchingEnabled(store.getBoolValueForKey(WebPreferencesKey::dnsPrefetchingEnabledKey()));
1191     settings->setWebArchiveDebugModeEnabled(store.getBoolValueForKey(WebPreferencesKey::webArchiveDebugModeEnabledKey()));
1192     settings->setLocalFileContentSniffingEnabled(store.getBoolValueForKey(WebPreferencesKey::localFileContentSniffingEnabledKey()));
1193     settings->setUsesPageCache(store.getBoolValueForKey(WebPreferencesKey::usesPageCacheKey()));
1194     settings->setAuthorAndUserStylesEnabled(store.getBoolValueForKey(WebPreferencesKey::authorAndUserStylesEnabledKey()));
1195     settings->setPaginateDuringLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::paginateDuringLayoutEnabledKey()));
1196     settings->setDOMPasteAllowed(store.getBoolValueForKey(WebPreferencesKey::domPasteAllowedKey()));
1197     settings->setShouldPrintBackgrounds(store.getBoolValueForKey(WebPreferencesKey::shouldPrintBackgroundsKey()));
1198
1199     settings->setMinimumFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumFontSizeKey()));
1200     settings->setMinimumLogicalFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumLogicalFontSizeKey()));
1201     settings->setDefaultFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFontSizeKey()));
1202     settings->setDefaultFixedFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFixedFontSizeKey()));
1203
1204 #if PLATFORM(WIN)
1205     // Temporarily turn off accelerated compositing until we have a good solution for rendering it.
1206     settings->setAcceleratedCompositingEnabled(false);
1207 #else
1208     settings->setAcceleratedCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingEnabledKey()));
1209 #endif
1210     settings->setShowDebugBorders(store.getBoolValueForKey(WebPreferencesKey::compositingBordersVisibleKey()));
1211     settings->setShowRepaintCounter(store.getBoolValueForKey(WebPreferencesKey::compositingRepaintCountersVisibleKey()));
1212
1213 #if ENABLE(DATABASE)
1214     AbstractDatabase::setIsAvailable(store.getBoolValueForKey(WebPreferencesKey::databasesEnabledKey()));
1215 #endif
1216
1217     platformPreferencesDidChange(store);
1218 }
1219
1220 #if ENABLE(INSPECTOR)
1221 WebInspector* WebPage::inspector()
1222 {
1223     if (m_isClosed)
1224         return 0;
1225     if (!m_inspector)
1226         m_inspector = adoptPtr(new WebInspector(this));
1227     return m_inspector.get();
1228 }
1229 #endif
1230
1231 #if !PLATFORM(MAC)
1232 bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt)
1233 {
1234     Node* node = evt->target()->toNode();
1235     ASSERT(node);
1236     Frame* frame = node->document()->frame();
1237     ASSERT(frame);
1238
1239     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
1240     if (!keyEvent)
1241         return false;
1242
1243     Editor::Command command = frame->editor()->command(interpretKeyEvent(evt));
1244
1245     if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
1246         // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
1247         // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
1248         // (e.g. Tab that inserts a Tab character, or Enter).
1249         return !command.isTextInsertion() && command.execute(evt);
1250     }
1251
1252     if (command.execute(evt))
1253         return true;
1254
1255     // Don't insert null or control characters as they can result in unexpected behaviour
1256     if (evt->charCode() < ' ')
1257         return false;
1258
1259     return frame->editor()->insertText(evt->keyEvent()->text(), evt);
1260 }
1261 #endif
1262
1263 void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const String& dragStorageName, uint32_t flags)
1264 {
1265     if (!m_page) {
1266         send(Messages::WebPageProxy::DidPerformDragControllerAction(DragOperationNone));
1267         return;
1268     }
1269
1270     DragData dragData(dragStorageName, clientPosition, globalPosition, static_cast<DragOperation>(draggingSourceOperationMask), static_cast<DragApplicationFlags>(flags));
1271     switch (action) {
1272     case DragControllerActionEntered:
1273         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData)));
1274         break;
1275
1276     case DragControllerActionUpdated:
1277         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData)));
1278         break;
1279         
1280     case DragControllerActionExited:
1281         m_page->dragController()->dragExited(&dragData);
1282         break;
1283         
1284     case DragControllerActionPerformDrag:
1285         m_page->dragController()->performDrag(&dragData);
1286         break;
1287         
1288     default:
1289         ASSERT_NOT_REACHED();
1290     }
1291 }
1292
1293 WebEditCommand* WebPage::webEditCommand(uint64_t commandID)
1294 {
1295     return m_editCommandMap.get(commandID).get();
1296 }
1297
1298 void WebPage::addWebEditCommand(uint64_t commandID, WebEditCommand* command)
1299 {
1300     m_editCommandMap.set(commandID, command);
1301 }
1302
1303 void WebPage::removeWebEditCommand(uint64_t commandID)
1304 {
1305     m_editCommandMap.remove(commandID);
1306 }
1307
1308 void WebPage::unapplyEditCommand(uint64_t commandID)
1309 {
1310     WebEditCommand* command = webEditCommand(commandID);
1311     if (!command)
1312         return;
1313
1314     command->command()->unapply();
1315 }
1316
1317 void WebPage::reapplyEditCommand(uint64_t commandID)
1318 {
1319     WebEditCommand* command = webEditCommand(commandID);
1320     if (!command)
1321         return;
1322
1323     m_isInRedo = true;
1324     command->command()->reapply();
1325     m_isInRedo = false;
1326 }
1327
1328 void WebPage::didRemoveEditCommand(uint64_t commandID)
1329 {
1330     removeWebEditCommand(commandID);
1331 }
1332
1333 void WebPage::setActivePopupMenu(WebPopupMenu* menu)
1334 {
1335     m_activePopupMenu = menu;
1336 }
1337
1338 void WebPage::setActiveOpenPanelResultListener(PassRefPtr<WebOpenPanelResultListener> openPanelResultListener)
1339 {
1340     m_activeOpenPanelResultListener = openPanelResultListener;
1341 }
1342
1343 bool WebPage::findStringFromInjectedBundle(const String& target, FindOptions options)
1344 {
1345     return m_page->findString(target, options);
1346 }
1347
1348 void WebPage::findString(const String& string, uint32_t options, uint32_t maxMatchCount)
1349 {
1350     m_findController.findString(string, static_cast<FindOptions>(options), maxMatchCount);
1351 }
1352
1353 void WebPage::hideFindUI()
1354 {
1355     m_findController.hideFindUI();
1356 }
1357
1358 void WebPage::countStringMatches(const String& string, uint32_t options, uint32_t maxMatchCount)
1359 {
1360     m_findController.countStringMatches(string, static_cast<FindOptions>(options), maxMatchCount);
1361 }
1362
1363 void WebPage::didChangeSelectedIndexForActivePopupMenu(int32_t newIndex)
1364 {
1365     if (!m_activePopupMenu)
1366         return;
1367
1368     m_activePopupMenu->didChangeSelectedIndex(newIndex);
1369     m_activePopupMenu = 0;
1370 }
1371
1372 void WebPage::didChooseFilesForOpenPanel(const Vector<String>& files)
1373 {
1374     if (!m_activeOpenPanelResultListener)
1375         return;
1376
1377     m_activeOpenPanelResultListener->didChooseFiles(files);
1378     m_activeOpenPanelResultListener = 0;
1379 }
1380
1381 void WebPage::didCancelForOpenPanel()
1382 {
1383     m_activeOpenPanelResultListener = 0;
1384 }
1385
1386 void WebPage::didReceiveGeolocationPermissionDecision(uint64_t geolocationID, bool allowed)
1387 {
1388     m_geolocationPermissionRequestManager.didReceiveGeolocationPermissionDecision(geolocationID, allowed);
1389 }
1390
1391 void WebPage::advanceToNextMisspelling(bool startBeforeSelection)
1392 {
1393     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1394     frame->editor()->advanceToNextMisspelling(startBeforeSelection);
1395 }
1396
1397 void WebPage::changeSpellingToWord(const String& word)
1398 {
1399     replaceSelectionWithText(m_page->focusController()->focusedOrMainFrame(), word);
1400 }
1401
1402 void WebPage::unmarkAllMisspellings()
1403 {
1404     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1405         if (Document* document = frame->document())
1406             document->markers()->removeMarkers(DocumentMarker::Spelling);
1407     }
1408 }
1409
1410 void WebPage::unmarkAllBadGrammar()
1411 {
1412     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1413         if (Document* document = frame->document())
1414             document->markers()->removeMarkers(DocumentMarker::Grammar);
1415     }
1416 }
1417
1418 #if PLATFORM(MAC)
1419 void WebPage::uppercaseWord()
1420 {
1421     m_page->focusController()->focusedOrMainFrame()->editor()->uppercaseWord();
1422 }
1423
1424 void WebPage::lowercaseWord()
1425 {
1426     m_page->focusController()->focusedOrMainFrame()->editor()->lowercaseWord();
1427 }
1428
1429 void WebPage::capitalizeWord()
1430 {
1431     m_page->focusController()->focusedOrMainFrame()->editor()->capitalizeWord();
1432 }
1433 #endif
1434     
1435 void WebPage::setTextForActivePopupMenu(int32_t index)
1436 {
1437     if (!m_activePopupMenu)
1438         return;
1439
1440     m_activePopupMenu->setTextForIndex(index);
1441 }
1442
1443 void WebPage::didSelectItemFromActiveContextMenu(const WebContextMenuItemData& item)
1444 {
1445     ASSERT(m_contextMenu);
1446     m_contextMenu->itemSelected(item);
1447     m_contextMenu = 0;
1448 }
1449
1450 void WebPage::replaceSelectionWithText(Frame* frame, const String& text)
1451 {
1452     if (frame->selection()->isNone())
1453         return;
1454     
1455     RefPtr<DocumentFragment> textFragment = createFragmentFromText(frame->selection()->toNormalizedRange().get(), text);
1456     applyCommand(ReplaceSelectionCommand::create(frame->document(), textFragment.release(), true, false, true));
1457     frame->selection()->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
1458 }
1459
1460 bool WebPage::mainFrameHasCustomRepresentation() const
1461 {
1462     return static_cast<WebFrameLoaderClient*>(mainFrame()->coreFrame()->loader()->client())->frameHasCustomRepresentation();
1463 }
1464
1465 #if PLATFORM(MAC)
1466
1467 void WebPage::addPluginView(PluginView* pluginView)
1468 {
1469     ASSERT(!m_pluginViews.contains(pluginView));
1470
1471     m_pluginViews.add(pluginView);
1472 }
1473
1474 void WebPage::removePluginView(PluginView* pluginView)
1475 {
1476     ASSERT(m_pluginViews.contains(pluginView));
1477
1478     m_pluginViews.remove(pluginView);
1479 }
1480
1481 void WebPage::setWindowIsVisible(bool windowIsVisible)
1482 {
1483     m_windowIsVisible = windowIsVisible;
1484
1485     // Tell all our plug-in views that the window visibility changed.
1486     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1487         (*it)->setWindowIsVisible(windowIsVisible);
1488 }
1489
1490 void WebPage::windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates, const WebCore::IntPoint& accessibilityViewCoordinates)
1491 {
1492     m_windowFrameInScreenCoordinates = windowFrameInScreenCoordinates;
1493     m_viewFrameInWindowCoordinates = viewFrameInWindowCoordinates;
1494     m_accessibilityPosition = accessibilityViewCoordinates;
1495     
1496     // Tell all our plug-in views that the window and view frames have changed.
1497     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1498         (*it)->windowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates);
1499 }
1500
1501 bool WebPage::windowIsFocused() const
1502 {
1503     return m_page->focusController()->isActive();
1504 }
1505
1506 #endif
1507
1508 void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
1509 {
1510     if (messageID.is<CoreIPC::MessageClassDrawingAreaLegacy>()) {
1511         if (m_drawingArea)
1512             m_drawingArea->didReceiveMessage(connection, messageID, arguments);
1513         return;
1514     }
1515
1516 #ifdef __APPLE__
1517     if (messageID.is<CoreIPC::MessageClassDrawingArea>()) {
1518         if (m_drawingArea)
1519             m_drawingArea->didReceiveDrawingAreaMessage(connection, messageID, arguments);
1520         return;
1521     }
1522 #endif
1523     
1524 #if ENABLE(INSPECTOR)
1525     if (messageID.is<CoreIPC::MessageClassWebInspector>()) {
1526         if (WebInspector* inspector = this->inspector())
1527             inspector->didReceiveWebInspectorMessage(connection, messageID, arguments);
1528         return;
1529     }
1530 #endif
1531
1532     didReceiveWebPageMessage(connection, messageID, arguments);
1533 }
1534
1535 CoreIPC::SyncReplyMode WebPage::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, CoreIPC::ArgumentEncoder* reply)
1536 {   
1537     return didReceiveSyncWebPageMessage(connection, messageID, arguments, reply);
1538 }
1539     
1540 InjectedBundleBackForwardList* WebPage::backForwardList()
1541 {
1542     if (!m_backForwardList)
1543         m_backForwardList = InjectedBundleBackForwardList::create(this);
1544     return m_backForwardList.get();
1545 }
1546
1547 #if PLATFORM(QT)
1548 void WebPage::findZoomableAreaForPoint(const WebCore::IntPoint& point)
1549 {
1550     const int minimumZoomTargetWidth = 100;
1551
1552     Frame* mainframe = m_mainFrame->coreFrame();
1553     HitTestResult result = mainframe->eventHandler()->hitTestResultAtPoint(mainframe->view()->windowToContents(point), /*allowShadowContent*/ false, /*ignoreClipping*/ true);
1554
1555     Node* node = result.innerNode();
1556     while (node && node->getRect().width() < minimumZoomTargetWidth)
1557         node = node->parentNode();
1558
1559     IntRect zoomableArea;
1560     if (node)
1561         zoomableArea = node->getRect();
1562     send(Messages::WebPageProxy::DidFindZoomableArea(zoomableArea));
1563 }
1564 #endif
1565
1566 WebPage::SandboxExtensionTracker::~SandboxExtensionTracker()
1567 {
1568     invalidate();
1569 }
1570
1571 void WebPage::SandboxExtensionTracker::invalidate()
1572 {
1573     if (m_pendingProvisionalSandboxExtension) {
1574         m_pendingProvisionalSandboxExtension->invalidate();
1575         m_pendingProvisionalSandboxExtension = 0;
1576     }
1577
1578     if (m_provisionalSandboxExtension) {
1579         m_provisionalSandboxExtension->invalidate();
1580         m_provisionalSandboxExtension = 0;
1581     }
1582
1583     if (m_committedSandboxExtension) {
1584         m_committedSandboxExtension->invalidate();
1585         m_committedSandboxExtension = 0;
1586     }
1587 }
1588
1589 void WebPage::SandboxExtensionTracker::beginLoad(WebFrame* frame, const SandboxExtension::Handle& handle)
1590 {
1591     ASSERT(frame->isMainFrame());
1592
1593     ASSERT(!m_pendingProvisionalSandboxExtension);
1594     m_pendingProvisionalSandboxExtension = SandboxExtension::create(handle);
1595 }
1596
1597 void WebPage::SandboxExtensionTracker::didStartProvisionalLoad(WebFrame* frame)
1598 {
1599     if (!frame->isMainFrame())
1600         return;
1601
1602     ASSERT(!m_provisionalSandboxExtension);
1603
1604     m_provisionalSandboxExtension = m_pendingProvisionalSandboxExtension.release();
1605     if (!m_provisionalSandboxExtension)
1606         return;
1607
1608     m_provisionalSandboxExtension->consume();
1609 }
1610
1611 void WebPage::SandboxExtensionTracker::didCommitProvisionalLoad(WebFrame* frame)
1612 {
1613     if (!frame->isMainFrame())
1614         return;
1615     
1616     ASSERT(!m_pendingProvisionalSandboxExtension);
1617
1618     // The provisional load has been committed. Invalidate the currently committed sandbox
1619     // extension and make the provisional sandbox extension the committed sandbox extension.
1620     if (m_committedSandboxExtension)
1621         m_committedSandboxExtension->invalidate();
1622
1623     m_committedSandboxExtension = m_provisionalSandboxExtension.release();
1624 }
1625
1626 void WebPage::SandboxExtensionTracker::didFailProvisionalLoad(WebFrame* frame)
1627 {
1628     if (!frame->isMainFrame())
1629         return;
1630
1631     ASSERT(!m_pendingProvisionalSandboxExtension);
1632     if (!m_provisionalSandboxExtension)
1633         return;
1634
1635     m_provisionalSandboxExtension->invalidate();
1636     m_provisionalSandboxExtension = 0;
1637 }
1638
1639 bool WebPage::hasLocalDataForURL(const KURL& url)
1640 {
1641     if (url.isLocalFile())
1642         return true;
1643
1644     FrameLoader* frameLoader = m_page->mainFrame()->loader();
1645     DocumentLoader* documentLoader = frameLoader ? frameLoader->documentLoader() : 0;
1646     if (documentLoader && documentLoader->subresource(url))
1647         return true;
1648
1649     return platformHasLocalDataForURL(url);
1650 }
1651
1652 void WebPage::setCustomTextEncodingName(const String& encoding)
1653 {
1654     m_page->mainFrame()->loader()->reloadWithOverrideEncoding(encoding);
1655 }
1656
1657 void WebPage::didRemoveBackForwardItem(uint64_t itemID)
1658 {
1659     WebBackForwardListProxy::removeItem(itemID);
1660 }
1661
1662 #if PLATFORM(MAC)
1663
1664 bool WebPage::isSpeaking()
1665 {
1666     bool result;
1667     return sendSync(Messages::WebPageProxy::GetIsSpeaking(), Messages::WebPageProxy::GetIsSpeaking::Reply(result)) && result;
1668 }
1669
1670 void WebPage::speak(const String& string)
1671 {
1672     send(Messages::WebPageProxy::Speak(string));
1673 }
1674
1675 void WebPage::stopSpeaking()
1676 {
1677     send(Messages::WebPageProxy::StopSpeaking());
1678 }
1679
1680 #endif
1681
1682 void WebPage::beginPrinting(uint64_t frameID, const PrintInfo& printInfo)
1683 {
1684     WebFrame* frame = WebProcess::shared().webFrame(frameID);
1685     if (!frame)
1686         return;
1687
1688     Frame* coreFrame = frame->coreFrame();
1689     if (!coreFrame)
1690         return;
1691
1692     if (!m_printContext)
1693         m_printContext = adoptPtr(new PrintContext(coreFrame));
1694
1695     m_printContext->begin(printInfo.availablePaperWidth, printInfo.availablePaperHeight);
1696 }
1697
1698 void WebPage::endPrinting()
1699 {
1700     m_printContext = nullptr;
1701 }
1702
1703 void WebPage::computePagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, Vector<IntRect>& resultPageRects, double& resultTotalScaleFactorForPrinting)
1704 {
1705     beginPrinting(frameID, printInfo);
1706
1707     WebFrame* frame = WebProcess::shared().webFrame(frameID);
1708     if (!frame)
1709         return;
1710
1711     float fullPageHeight;
1712     m_printContext->computePageRects(FloatRect(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight), 0, 0, printInfo.pageSetupScaleFactor, fullPageHeight, true);
1713
1714     resultTotalScaleFactorForPrinting = m_printContext->computeAutomaticScaleFactor(printInfo.availablePaperWidth) * printInfo.pageSetupScaleFactor;
1715     resultPageRects = m_printContext->pageRects();
1716
1717     // If we're asked to print, we should actually print at least a blank page.
1718     if (resultPageRects.isEmpty())
1719         resultPageRects.append(IntRect(0, 0, 1, 1));
1720 }
1721
1722 #if PLATFORM(MAC)
1723 // FIXME: Find a better place for Mac specific code.
1724 void WebPage::drawRectToPDF(uint64_t frameID, const WebCore::IntRect& rect, Vector<uint8_t>& pdfData)
1725 {
1726     WebFrame* frame = WebProcess::shared().webFrame(frameID);
1727     if (!frame)
1728         return;
1729
1730     Frame* coreFrame = frame->coreFrame();
1731     if (!coreFrame)
1732         return;
1733
1734     ASSERT(coreFrame->document()->printing());
1735
1736     RetainPtr<CFMutableDataRef> pdfPageData(AdoptCF, CFDataCreateMutable(0, 0));
1737
1738     // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
1739     RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get()));
1740
1741     CGRect mediaBox = CGRectMake(0, 0, frame->size().width(), frame->size().height());
1742     RetainPtr<CGContextRef> context(AdoptCF, CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0));
1743     CFDictionaryRef pageInfo = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1744     CGPDFContextBeginPage(context.get(), pageInfo);
1745
1746     GraphicsContext ctx(context.get());
1747     m_printContext->spoolRect(ctx, rect);
1748
1749     CGPDFContextEndPage(context.get());
1750     CGPDFContextClose(context.get());
1751
1752     pdfData.resize(CFDataGetLength(pdfPageData.get()));
1753     CFDataGetBytes(pdfPageData.get(), CFRangeMake(0, pdfData.size()), pdfData.data());
1754 }
1755 #endif
1756
1757 } // namespace WebKit