50051a2a1a431f851ce3558e38ae2de2e0b2f921
[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 "NotificationPermissionRequestManager.h"
39 #include "PageOverlay.h"
40 #include "PluginProxy.h"
41 #include "PluginView.h"
42 #include "PrintInfo.h"
43 #include "RunLoop.h"
44 #include "SessionState.h"
45 #include "ShareableBitmap.h"
46 #include "WebBackForwardList.h"
47 #include "WebBackForwardListItem.h"
48 #include "WebBackForwardListProxy.h"
49 #include "WebChromeClient.h"
50 #include "WebContextMenu.h"
51 #include "WebContextMenuClient.h"
52 #include "WebContextMessages.h"
53 #include "WebCoreArgumentCoders.h"
54 #include "WebDragClient.h"
55 #include "WebEditorClient.h"
56 #include "WebEvent.h"
57 #include "WebEventConversion.h"
58 #include "WebFrame.h"
59 #include "WebFullScreenManager.h"
60 #include "WebGeolocationClient.h"
61 #include "WebGeometry.h"
62 #include "WebImage.h"
63 #include "WebInspector.h"
64 #include "WebInspectorClient.h"
65 #include "WebNotificationClient.h"
66 #include "WebOpenPanelResultListener.h"
67 #include "WebPageCreationParameters.h"
68 #include "WebPageGroupProxy.h"
69 #include "WebPageProxyMessages.h"
70 #include "WebPopupMenu.h"
71 #include "WebPreferencesStore.h"
72 #include "WebProcess.h"
73 #include "WebProcessProxyMessages.h"
74 #include <JavaScriptCore/APICast.h>
75 #include <WebCore/AbstractDatabase.h>
76 #include <WebCore/ArchiveResource.h>
77 #include <WebCore/Chrome.h>
78 #include <WebCore/ContextMenuController.h>
79 #include <WebCore/DocumentFragment.h>
80 #include <WebCore/DocumentLoader.h>
81 #include <WebCore/DocumentMarkerController.h>
82 #include <WebCore/DragController.h>
83 #include <WebCore/DragData.h>
84 #include <WebCore/DragSession.h>
85 #include <WebCore/EventHandler.h>
86 #include <WebCore/FocusController.h>
87 #include <WebCore/FormState.h>
88 #include <WebCore/Frame.h>
89 #include <WebCore/FrameLoadRequest.h>
90 #include <WebCore/FrameLoaderTypes.h>
91 #include <WebCore/FrameView.h>
92 #include <WebCore/HTMLFormElement.h>
93 #include <WebCore/HistoryItem.h>
94 #include <WebCore/KeyboardEvent.h>
95 #include <WebCore/MouseEvent.h>
96 #include <WebCore/Page.h>
97 #include <WebCore/PlatformKeyboardEvent.h>
98 #include <WebCore/PluginDocument.h>
99 #include <WebCore/PrintContext.h>
100 #include <WebCore/RenderArena.h>
101 #include <WebCore/RenderLayer.h>
102 #include <WebCore/RenderTreeAsText.h>
103 #include <WebCore/RenderView.h>
104 #include <WebCore/ReplaceSelectionCommand.h>
105 #include <WebCore/ResourceRequest.h>
106 #include <WebCore/SchemeRegistry.h>
107 #include <WebCore/ScriptValue.h>
108 #include <WebCore/SerializedScriptValue.h>
109 #include <WebCore/Settings.h>
110 #include <WebCore/SharedBuffer.h>
111 #include <WebCore/SubstituteData.h>
112 #include <WebCore/TextIterator.h>
113 #include <WebCore/markup.h>
114 #include <runtime/JSLock.h>
115 #include <runtime/JSValue.h>
116
117 #include <WebCore/Range.h>
118 #include <WebCore/VisiblePosition.h>
119
120 #if ENABLE(PLUGIN_PROCESS)
121 #if PLATFORM(MAC)
122 #include "MachPort.h"
123 #endif
124 #endif
125
126 #if PLATFORM(MAC)
127 #include "BuiltInPDFView.h"
128 #endif
129
130 #if PLATFORM(QT)
131 #include "HitTestResult.h"
132 #include <QMimeData>
133 #endif
134
135 #if PLATFORM(GTK)
136 #include "DataObjectGtk.h"
137 #endif
138
139 #ifndef NDEBUG
140 #include <wtf/RefCountedLeakCounter.h>
141 #endif
142
143 using namespace JSC;
144 using namespace WebCore;
145 using namespace std;
146
147 namespace WebKit {
148
149 class SendStopResponsivenessTimer {
150 public:
151     SendStopResponsivenessTimer(WebPage* page)
152         : m_page(page)
153     {
154     }
155     
156     ~SendStopResponsivenessTimer()
157     {
158         m_page->send(Messages::WebPageProxy::StopResponsivenessTimer());
159     }
160
161 private:
162     WebPage* m_page;
163 };
164
165 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageCounter, ("WebPage"));
166
167 PassRefPtr<WebPage> WebPage::create(uint64_t pageID, const WebPageCreationParameters& parameters)
168 {
169     RefPtr<WebPage> page = adoptRef(new WebPage(pageID, parameters));
170
171     if (page->pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())
172         WebProcess::shared().injectedBundle()->didCreatePage(page.get());
173
174     return page.release();
175 }
176
177 WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
178     : m_viewSize(parameters.viewSize)
179     , m_useFixedLayout(false)
180     , m_drawsBackground(true)
181     , m_drawsTransparentBackground(false)
182     , m_isInRedo(false)
183     , m_isClosed(false)
184     , m_tabToLinks(false)
185 #if PLATFORM(MAC)
186     , m_windowIsVisible(false)
187     , m_isSmartInsertDeleteEnabled(parameters.isSmartInsertDeleteEnabled)
188     , m_keyboardEventBeingInterpreted(0)
189 #elif PLATFORM(WIN)
190     , m_nativeWindow(parameters.nativeWindow)
191 #endif
192     , m_setCanStartMediaTimer(WebProcess::shared().runLoop(), this, &WebPage::setCanStartMediaTimerFired)
193     , m_findController(this)
194     , m_geolocationPermissionRequestManager(this)
195     , m_pageID(pageID)
196     , m_canRunBeforeUnloadConfirmPanel(parameters.canRunBeforeUnloadConfirmPanel)
197     , m_canRunModal(parameters.canRunModal)
198     , m_isRunningModal(false)
199     , m_cachedMainFrameIsPinnedToLeftSide(false)
200     , m_cachedMainFrameIsPinnedToRightSide(false)
201     , m_cachedPageCount(0)
202     , m_isShowingContextMenu(false)
203 #if PLATFORM(WIN)
204     , m_gestureReachedScrollingLimit(false)
205 #endif
206 {
207     ASSERT(m_pageID);
208     // FIXME: This is a non-ideal location for this Setting and
209     // 4ms should be adopted project-wide now, https://bugs.webkit.org/show_bug.cgi?id=61214
210     Settings::setDefaultMinDOMTimerInterval(0.004);
211
212     Page::PageClients pageClients;
213     pageClients.chromeClient = new WebChromeClient(this);
214     pageClients.contextMenuClient = new WebContextMenuClient(this);
215     pageClients.editorClient = new WebEditorClient(this);
216     pageClients.dragClient = new WebDragClient(this);
217     pageClients.backForwardClient = WebBackForwardListProxy::create(this);
218 #if ENABLE(CLIENT_BASED_GEOLOCATION)
219     pageClients.geolocationClient = new WebGeolocationClient(this);
220 #endif
221 #if ENABLE(INSPECTOR)
222     pageClients.inspectorClient = new WebInspectorClient(this);
223 #endif
224 #if ENABLE(NOTIFICATIONS)
225     pageClients.notificationClient = new WebNotificationClient(this);
226 #endif
227     
228     m_page = adoptPtr(new Page(pageClients));
229
230     // Qt does not yet call setIsInWindow. Until it does, just leave
231     // this line out so plug-ins and video will work. Eventually all platforms
232     // should call setIsInWindow and this comment and #if should be removed,
233     // leaving behind the setCanStartMedia call.
234 #if !PLATFORM(QT)
235     m_page->setCanStartMedia(false);
236 #endif
237
238     updatePreferences(parameters.store);
239
240     m_pageGroup = WebProcess::shared().webPageGroup(parameters.pageGroupData);
241     m_page->setGroupName(m_pageGroup->identifier());
242
243     platformInitialize();
244
245     m_drawingArea = DrawingArea::create(this, parameters);
246     m_drawingArea->setPaintingEnabled(false);
247
248     m_mainFrame = WebFrame::createMainFrame(this);
249
250     setUseFixedLayout(parameters.useFixedLayout);
251
252     setDrawsBackground(parameters.drawsBackground);
253     setDrawsTransparentBackground(parameters.drawsTransparentBackground);
254
255     setPaginationMode(parameters.paginationMode);
256     setPageLength(parameters.pageLength);
257     setGapBetweenPages(parameters.gapBetweenPages);
258
259     setMemoryCacheMessagesEnabled(parameters.areMemoryCacheClientCallsEnabled);
260
261     setActive(parameters.isActive);
262     setFocused(parameters.isFocused);
263     setIsInWindow(parameters.isInWindow);
264
265     m_userAgent = parameters.userAgent;
266
267     WebBackForwardListProxy::setHighestItemIDFromUIProcess(parameters.highestUsedBackForwardItemID);
268     
269     if (!parameters.sessionState.isEmpty())
270         restoreSession(parameters.sessionState);
271
272     m_drawingArea->setPaintingEnabled(true);
273
274 #ifndef NDEBUG
275     webPageCounter.increment();
276 #endif
277 }
278
279 WebPage::~WebPage()
280 {
281     if (m_backForwardList)
282         m_backForwardList->detach();
283
284     ASSERT(!m_page);
285
286     m_sandboxExtensionTracker.invalidate();
287
288 #if PLATFORM(MAC)
289     ASSERT(m_pluginViews.isEmpty());
290 #endif
291
292 #ifndef NDEBUG
293     webPageCounter.decrement();
294 #endif
295 }
296
297 void WebPage::dummy(bool&)
298 {
299 }
300
301 CoreIPC::Connection* WebPage::connection() const
302 {
303     return WebProcess::shared().connection();
304 }
305
306 void WebPage::initializeInjectedBundleContextMenuClient(WKBundlePageContextMenuClient* client)
307 {
308     m_contextMenuClient.initialize(client);
309 }
310
311 void WebPage::initializeInjectedBundleEditorClient(WKBundlePageEditorClient* client)
312 {
313     m_editorClient.initialize(client);
314 }
315
316 void WebPage::initializeInjectedBundleFormClient(WKBundlePageFormClient* client)
317 {
318     m_formClient.initialize(client);
319 }
320
321 void WebPage::initializeInjectedBundleLoaderClient(WKBundlePageLoaderClient* client)
322 {
323     m_loaderClient.initialize(client);
324 }
325
326 void WebPage::initializeInjectedBundlePolicyClient(WKBundlePagePolicyClient* client)
327 {
328     m_policyClient.initialize(client);
329 }
330
331 void WebPage::initializeInjectedBundleResourceLoadClient(WKBundlePageResourceLoadClient* client)
332 {
333     m_resourceLoadClient.initialize(client);
334 }
335
336 void WebPage::initializeInjectedBundleUIClient(WKBundlePageUIClient* client)
337 {
338     m_uiClient.initialize(client);
339 }
340
341 #if ENABLE(FULLSCREEN_API)
342 void WebPage::initializeInjectedBundleFullScreenClient(WKBundlePageFullScreenClient* client)
343 {
344     m_fullScreenClient.initialize(client);
345 }
346 #endif
347
348 PassRefPtr<Plugin> WebPage::createPlugin(const Plugin::Parameters& parameters)
349 {
350     String pluginPath;
351
352     if (!WebProcess::shared().connection()->sendSync(
353             Messages::WebContext::GetPluginPath(parameters.mimeType, parameters.url.string()), 
354             Messages::WebContext::GetPluginPath::Reply(pluginPath), 0)) {
355         return 0;
356     }
357
358     if (pluginPath.isNull()) {
359 #if PLATFORM(MAC)
360         if (parameters.mimeType == "application/pdf"
361             || (parameters.mimeType.isEmpty() && parameters.url.path().lower().endsWith(".pdf")))
362             return BuiltInPDFView::create(m_page.get());
363 #endif
364         return 0;
365     }
366
367 #if ENABLE(PLUGIN_PROCESS)
368     return PluginProxy::create(pluginPath);
369 #else
370     NetscapePlugin::setSetExceptionFunction(NPRuntimeObjectMap::setGlobalException);
371     return NetscapePlugin::create(NetscapePluginModule::getOrCreate(pluginPath));
372 #endif
373 }
374
375 EditorState WebPage::editorState() const
376 {
377     Frame* frame = m_page->focusController()->focusedOrMainFrame();
378     ASSERT(frame);
379
380     EditorState result;
381     result.selectionIsNone = frame->selection()->isNone();
382     result.selectionIsRange = frame->selection()->isRange();
383     result.isContentEditable = frame->selection()->isContentEditable();
384     result.isContentRichlyEditable = frame->selection()->isContentRichlyEditable();
385     result.isInPasswordField = frame->selection()->isInPasswordField();
386     result.hasComposition = frame->editor()->hasComposition();
387
388 #if PLATFORM(QT)
389     size_t location = 0;
390     size_t length = 0;
391     Element* scope = frame->selection()->rootEditableElement();
392
393     RefPtr<Range> range;
394     if (result.hasComposition && (range = frame->editor()->compositionRange())) {
395         TextIterator::getLocationAndLengthFromRange(scope, range.get(), location, length);
396         result.compositionStart = location;
397         result.compositionLength = length;
398         result.compositionRect = range->boundingBox();
399     }
400
401     if (!result.selectionIsNone && (range = frame->selection()->selection().firstRange())) {
402         TextIterator::getLocationAndLengthFromRange(scope, range.get(), location, length);
403
404         ExceptionCode ec = 0;
405         RefPtr<Range> tempRange = range->cloneRange(ec);
406         tempRange->setStart(tempRange->startContainer(ec), tempRange->startOffset(ec) + location, ec);
407         IntRect rect = frame->editor()->firstRectForRange(tempRange.get());
408         bool baseIsFirst = frame->selection()->selection().isBaseFirst();
409
410         result.cursorPosition = (baseIsFirst) ? location + length : location;
411         result.anchorPosition = (baseIsFirst) ? location : location + length;
412         result.microFocus = frame->view()->contentsToWindow(rect);
413         result.selectedText = range->text();
414     }
415
416     if (scope && result.isContentEditable && !result.isInPasswordField) {
417         result.surroundingText = scope->innerText();
418         result.surroundingText.remove(result.compositionStart, result.compositionLength);
419     }
420 #endif
421
422     result.shouldIgnoreCompositionSelectionChange = frame->editor()->ignoreCompositionSelectionChange();
423
424     return result;
425 }
426
427 String WebPage::renderTreeExternalRepresentation() const
428 {
429     return externalRepresentation(m_mainFrame->coreFrame(), RenderAsTextBehaviorNormal);
430 }
431
432 uint64_t WebPage::renderTreeSize() const
433 {
434     if (!m_page)
435         return 0;
436
437     Frame* mainFrame = m_page->mainFrame();
438     if (!mainFrame)
439         return 0;
440
441     uint64_t size = 0;
442     for (Frame* coreFrame = mainFrame; coreFrame; coreFrame = coreFrame->tree()->traverseNext())
443         size += coreFrame->document()->renderArena()->totalRenderArenaSize();
444
445     return size;
446 }
447
448 void WebPage::setTracksRepaints(bool trackRepaints)
449 {
450     if (FrameView* view = mainFrameView())
451         view->setTracksRepaints(trackRepaints);
452 }
453
454 bool WebPage::isTrackingRepaints() const
455 {
456     if (FrameView* view = mainFrameView())
457         return view->isTrackingRepaints();
458
459     return false;
460 }
461
462 void WebPage::resetTrackedRepaints()
463 {
464     if (FrameView* view = mainFrameView())
465         view->resetTrackedRepaints();
466 }
467
468 PassRefPtr<ImmutableArray> WebPage::trackedRepaintRects()
469 {
470     FrameView* view = mainFrameView();
471     if (!view)
472         return ImmutableArray::create();
473
474     const Vector<IntRect>& rects = view->trackedRepaintRects();
475     size_t size = rects.size();
476     if (!size)
477         return ImmutableArray::create();
478
479     Vector<RefPtr<APIObject> > vector;
480     vector.reserveInitialCapacity(size);
481
482     for (size_t i = 0; i < size; ++i)
483         vector.uncheckedAppend(WebRect::create(toAPI(rects[i])));
484
485     return ImmutableArray::adopt(vector);
486 }
487
488 void WebPage::executeEditingCommand(const String& commandName, const String& argument)
489 {
490     Frame* frame = m_page->focusController()->focusedOrMainFrame();
491     if (!frame)
492         return;
493     frame->editor()->command(commandName).execute(argument);
494 }
495
496 bool WebPage::isEditingCommandEnabled(const String& commandName)
497 {
498     Frame* frame = m_page->focusController()->focusedOrMainFrame();
499     if (!frame)
500         return false;
501     
502     Editor::Command command = frame->editor()->command(commandName);
503     return command.isSupported() && command.isEnabled();
504 }
505     
506 void WebPage::clearMainFrameName()
507 {
508     if (Frame* frame = mainFrame())
509         frame->tree()->clearName();
510 }
511
512 #if USE(ACCELERATED_COMPOSITING)
513 void WebPage::enterAcceleratedCompositingMode(GraphicsLayer* layer)
514 {
515     m_drawingArea->setRootCompositingLayer(layer);
516 }
517
518 void WebPage::exitAcceleratedCompositingMode()
519 {
520     m_drawingArea->setRootCompositingLayer(0);
521 }
522 #endif
523
524 void WebPage::close()
525 {
526     if (m_isClosed)
527         return;
528
529     m_isClosed = true;
530
531     if (pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())
532         WebProcess::shared().injectedBundle()->willDestroyPage(this);
533
534 #if ENABLE(INSPECTOR)
535     m_inspector = 0;
536 #endif
537 #if ENABLE(FULLSCREEN_API)
538     m_fullScreenManager = 0;
539 #endif
540
541     if (m_activePopupMenu) {
542         m_activePopupMenu->disconnectFromPage();
543         m_activePopupMenu = 0;
544     }
545
546     if (m_activeOpenPanelResultListener) {
547         m_activeOpenPanelResultListener->disconnectFromPage();
548         m_activeOpenPanelResultListener = 0;
549     }
550
551     m_sandboxExtensionTracker.invalidate();
552
553     m_underlayPage = nullptr;
554     m_printContext = nullptr;
555     m_mainFrame->coreFrame()->loader()->detachFromParent();
556     m_page = nullptr;
557     m_drawingArea = nullptr;
558
559     bool isRunningModal = m_isRunningModal;
560     m_isRunningModal = false;
561
562     // The WebPage can be destroyed by this call.
563     WebProcess::shared().removeWebPage(m_pageID);
564
565     if (isRunningModal)
566         WebProcess::shared().runLoop()->stop();
567 }
568
569 void WebPage::tryClose()
570 {
571     SendStopResponsivenessTimer stopper(this);
572
573     if (!m_mainFrame->coreFrame()->loader()->shouldClose()) {
574         send(Messages::WebPageProxy::StopResponsivenessTimer());
575         return;
576     }
577
578     send(Messages::WebPageProxy::ClosePage(true));
579 }
580
581 void WebPage::sendClose()
582 {
583     send(Messages::WebPageProxy::ClosePage(false));
584 }
585
586 void WebPage::loadURL(const String& url, const SandboxExtension::Handle& sandboxExtensionHandle)
587 {
588     loadURLRequest(ResourceRequest(KURL(KURL(), url)), sandboxExtensionHandle);
589 }
590
591 void WebPage::loadURLRequest(const ResourceRequest& request, const SandboxExtension::Handle& sandboxExtensionHandle)
592 {
593     SendStopResponsivenessTimer stopper(this);
594
595     m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
596     m_mainFrame->coreFrame()->loader()->load(request, false);
597 }
598
599 void WebPage::loadData(PassRefPtr<SharedBuffer> sharedBuffer, const String& MIMEType, const String& encodingName, const KURL& baseURL, const KURL& unreachableURL)
600 {
601     SendStopResponsivenessTimer stopper(this);
602
603     ResourceRequest request(baseURL);
604     SubstituteData substituteData(sharedBuffer, MIMEType, encodingName, unreachableURL);
605     m_mainFrame->coreFrame()->loader()->load(request, substituteData, false);
606 }
607
608 void WebPage::loadHTMLString(const String& htmlString, const String& baseURLString)
609 {
610     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar));
611     KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString);
612     loadData(sharedBuffer, "text/html", "utf-16", baseURL, KURL());
613 }
614
615 void WebPage::loadAlternateHTMLString(const String& htmlString, const String& baseURLString, const String& unreachableURLString)
616 {
617     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar));
618     KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString);
619     KURL unreachableURL = unreachableURLString.isEmpty() ? KURL() : KURL(KURL(), unreachableURLString);
620     loadData(sharedBuffer, "text/html", "utf-16", baseURL, unreachableURL);
621 }
622
623 void WebPage::loadPlainTextString(const String& string)
624 {
625     RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(string.characters()), string.length() * sizeof(UChar));
626     loadData(sharedBuffer, "text/plain", "utf-16", blankURL(), KURL());
627 }
628
629 void WebPage::linkClicked(const String& url, const WebMouseEvent& event)
630 {
631     Frame* frame = m_page->mainFrame();
632     if (!frame)
633         return;
634
635     RefPtr<Event> coreEvent;
636     if (event.type() != WebEvent::NoType)
637         coreEvent = MouseEvent::create(eventNames().clickEvent, frame->document()->defaultView(), platform(event), 0, 0);
638
639     frame->loader()->loadFrameRequest(FrameLoadRequest(frame->document()->securityOrigin(), ResourceRequest(url)), 
640         false, false, coreEvent.get(), 0, MaybeSendReferrer);
641 }
642
643 void WebPage::stopLoadingFrame(uint64_t frameID)
644 {
645     WebFrame* frame = WebProcess::shared().webFrame(frameID);
646     if (!frame)
647         return;
648
649     frame->coreFrame()->loader()->stopForUserCancel();
650 }
651
652 void WebPage::stopLoading()
653 {
654     SendStopResponsivenessTimer stopper(this);
655
656     m_mainFrame->coreFrame()->loader()->stopForUserCancel();
657 }
658
659 void WebPage::setDefersLoading(bool defersLoading)
660 {
661     m_page->setDefersLoading(defersLoading);
662 }
663
664 void WebPage::reload(bool reloadFromOrigin)
665 {
666     SendStopResponsivenessTimer stopper(this);
667
668     m_mainFrame->coreFrame()->loader()->reload(reloadFromOrigin);
669 }
670
671 void WebPage::goForward(uint64_t backForwardItemID, const SandboxExtension::Handle& sandboxExtensionHandle)
672 {
673     SendStopResponsivenessTimer stopper(this);
674
675     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
676     ASSERT(item);
677     if (!item)
678         return;
679
680     m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
681     m_page->goToItem(item, FrameLoadTypeForward);
682 }
683
684 void WebPage::goBack(uint64_t backForwardItemID, const SandboxExtension::Handle& sandboxExtensionHandle)
685 {
686     SendStopResponsivenessTimer stopper(this);
687
688     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
689     ASSERT(item);
690     if (!item)
691         return;
692
693     m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
694     m_page->goToItem(item, FrameLoadTypeBack);
695 }
696
697 void WebPage::goToBackForwardItem(uint64_t backForwardItemID, const SandboxExtension::Handle& sandboxExtensionHandle)
698 {
699     SendStopResponsivenessTimer stopper(this);
700
701     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
702     ASSERT(item);
703     if (!item)
704         return;
705
706     m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle);
707     m_page->goToItem(item, FrameLoadTypeIndexedBackForward);
708 }
709
710 void WebPage::tryRestoreScrollPosition()
711 {
712     m_page->mainFrame()->loader()->history()->restoreScrollPositionAndViewState();
713 }
714
715 void WebPage::layoutIfNeeded()
716 {
717     if (m_mainFrame->coreFrame()->view())
718         m_mainFrame->coreFrame()->view()->updateLayoutAndStyleIfNeededRecursive();
719
720     if (m_underlayPage) {
721         if (FrameView *frameView = m_underlayPage->mainFrameView())
722             frameView->updateLayoutAndStyleIfNeededRecursive();
723     }
724 }
725
726 void WebPage::setSize(const WebCore::IntSize& viewSize)
727 {
728     FrameView* view = m_page->mainFrame()->view();
729
730 #if USE(TILED_BACKING_STORE)
731     // If we are resizing to content ignore external attempts.
732     if (view->useFixedLayout())
733         return;
734 #endif
735
736     if (m_viewSize == viewSize)
737         return;
738
739     view->resize(viewSize);
740     view->setNeedsLayout();
741     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), viewSize));
742     
743     m_viewSize = viewSize;
744 }
745
746 #if USE(TILED_BACKING_STORE)
747 void WebPage::setFixedVisibleContentRect(const IntRect& rect)
748 {
749     ASSERT(m_useFixedLayout);
750
751     Frame* frame = m_page->mainFrame();
752
753     frame->view()->setFixedVisibleContentRect(rect);
754 }
755
756 void WebPage::setResizesToContentsUsingLayoutSize(const IntSize& targetLayoutSize)
757 {
758     ASSERT(m_useFixedLayout);
759     ASSERT(!targetLayoutSize.isEmpty());
760
761     FrameView* view = m_page->mainFrame()->view();
762
763     view->setDelegatesScrolling(true);
764     view->setUseFixedLayout(true);
765     view->setPaintsEntireContents(true);
766
767     if (view->fixedLayoutSize() == targetLayoutSize)
768         return;
769
770     // Always reset even when empty.
771     view->setFixedLayoutSize(targetLayoutSize);
772
773     // Schedule a layout to use the new target size.
774     if (!view->layoutPending()) {
775         view->setNeedsLayout();
776         view->scheduleRelayout();
777     }
778 }
779
780 void WebPage::resizeToContentsIfNeeded()
781 {
782     ASSERT(m_useFixedLayout);
783
784     FrameView* view = m_page->mainFrame()->view();
785
786     if (!view->useFixedLayout())
787         return;
788
789     IntSize contentSize = view->contentsSize();
790     if (contentSize == m_viewSize)
791         return;
792
793     m_viewSize = contentSize;
794     view->resize(m_viewSize);
795     view->setNeedsLayout();
796 }
797
798 void WebPage::setViewportSize(const IntSize& size)
799 {
800     ASSERT(m_useFixedLayout);
801
802     if (m_viewportSize == size)
803         return;
804
805      m_viewportSize = size;
806
807     // Recalculate the recommended layout size, when the available size (device pixel) changes.
808     Settings* settings = m_page->settings();
809
810     int minimumLayoutFallbackWidth = std::max(settings->layoutFallbackWidth(), size.width());
811
812     IntSize targetLayoutSize = computeViewportAttributes(m_page->viewportArguments(), minimumLayoutFallbackWidth, settings->deviceWidth(), settings->deviceHeight(), settings->deviceDPI(), size).layoutSize;
813     setResizesToContentsUsingLayoutSize(targetLayoutSize);
814 }
815
816 #endif
817
818 void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset)
819 {
820     Frame* frame = m_page->mainFrame();
821
822     IntPoint scrollPosition = frame->view()->scrollPosition();
823     IntPoint maximumScrollPosition = frame->view()->maximumScrollPosition();
824
825     // If the current scroll position in a direction is the max scroll position 
826     // we don't want to scroll at all.
827     IntSize newScrollOffset;
828     if (scrollPosition.x() < maximumScrollPosition.x())
829         newScrollOffset.setWidth(scrollOffset.width());
830     if (scrollPosition.y() < maximumScrollPosition.y())
831         newScrollOffset.setHeight(scrollOffset.height());
832
833     if (newScrollOffset.isZero())
834         return;
835
836     frame->view()->setScrollPosition(frame->view()->scrollPosition() + newScrollOffset);
837 }
838
839 void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect)
840 {
841     GraphicsContextStateSaver stateSaver(graphicsContext);
842     graphicsContext.clip(rect);
843
844     if (m_underlayPage) {
845         m_underlayPage->drawRect(graphicsContext, rect);
846
847         graphicsContext.beginTransparencyLayer(1);
848         m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect);
849         graphicsContext.endTransparencyLayer();
850         return;
851     }
852
853     m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect);
854 }
855
856 void WebPage::drawPageOverlay(GraphicsContext& graphicsContext, const IntRect& rect)
857 {
858     ASSERT(m_pageOverlay);
859
860     GraphicsContextStateSaver stateSaver(graphicsContext);
861     graphicsContext.clip(rect);
862     m_pageOverlay->drawRect(graphicsContext, rect);
863 }
864
865 double WebPage::textZoomFactor() const
866 {
867     Frame* frame = m_mainFrame->coreFrame();
868     if (!frame)
869         return 1;
870     return frame->textZoomFactor();
871 }
872
873 void WebPage::setTextZoomFactor(double zoomFactor)
874 {
875     Frame* frame = m_mainFrame->coreFrame();
876     if (!frame)
877         return;
878     frame->setTextZoomFactor(static_cast<float>(zoomFactor));
879 }
880
881 double WebPage::pageZoomFactor() const
882 {
883     Frame* frame = m_mainFrame->coreFrame();
884     if (!frame)
885         return 1;
886     return frame->pageZoomFactor();
887 }
888
889 void WebPage::setPageZoomFactor(double zoomFactor)
890 {
891     Frame* frame = m_mainFrame->coreFrame();
892     if (!frame)
893         return;
894     frame->setPageZoomFactor(static_cast<float>(zoomFactor));
895 }
896
897 void WebPage::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
898 {
899     Frame* frame = m_mainFrame->coreFrame();
900     if (!frame)
901         return;
902     return frame->setPageAndTextZoomFactors(static_cast<float>(pageZoomFactor), static_cast<float>(textZoomFactor));
903 }
904
905 void WebPage::windowScreenDidChange(uint64_t displayID)
906 {
907     m_page->windowScreenDidChange(static_cast<PlatformDisplayID>(displayID));
908 }
909
910 void WebPage::scalePage(double scale, const IntPoint& origin)
911 {
912     m_page->setPageScaleFactor(scale, origin);
913
914     send(Messages::WebPageProxy::PageScaleFactorDidChange(scale));
915 }
916
917 double WebPage::pageScaleFactor() const
918 {
919     return m_page->pageScaleFactor();
920 }
921
922 void WebPage::setDeviceScaleFactor(float scaleFactor)
923 {
924     if (scaleFactor == m_page->deviceScaleFactor())
925         return;
926
927     m_page->setDeviceScaleFactor(scaleFactor);
928
929     // Tell all our plug-in views that the device scale factor changed.
930 #if PLATFORM(MAC)
931     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
932         (*it)->setDeviceScaleFactor(scaleFactor);
933 #endif
934
935     if (m_findController.isShowingOverlay()) {
936         // We must have updated layout to get the selection rects right.
937         layoutIfNeeded();
938         m_findController.deviceScaleFactorDidChange();
939     }
940 }
941
942 float WebPage::deviceScaleFactor() const
943 {
944     return m_page->deviceScaleFactor();
945 }
946
947 void WebPage::setUseFixedLayout(bool fixed)
948 {
949     m_useFixedLayout = fixed;
950
951     FrameView* view = mainFrameView();
952     if (!view)
953         return;
954
955     view->setUseFixedLayout(fixed);
956     if (!fixed)
957         view->setFixedLayoutSize(IntSize());
958 }
959
960 void WebPage::setFixedLayoutSize(const IntSize& size)
961 {
962     FrameView* view = mainFrameView();
963     if (!view)
964         return;
965
966     view->setFixedLayoutSize(size);
967     view->forceLayout();
968 }
969
970 void WebPage::setPaginationMode(uint32_t mode)
971 {
972     Page::Pagination pagination = m_page->pagination();
973     pagination.mode = static_cast<Page::Pagination::Mode>(mode);
974     m_page->setPagination(pagination);
975 }
976
977 void WebPage::setPageLength(double pageLength)
978 {
979     Page::Pagination pagination = m_page->pagination();
980     pagination.pageLength = pageLength;
981     m_page->setPagination(pagination);
982 }
983
984 void WebPage::setGapBetweenPages(double gap)
985 {
986     Page::Pagination pagination = m_page->pagination();
987     pagination.gap = gap;
988     m_page->setPagination(pagination);
989 }
990
991 void WebPage::installPageOverlay(PassRefPtr<PageOverlay> pageOverlay)
992 {
993     bool shouldFadeIn = true;
994     
995     if (m_pageOverlay) {
996         m_pageOverlay->setPage(0);
997
998         if (pageOverlay) {
999             // We're installing a page overlay when a page overlay is already active.
1000             // In this case we don't want to fade in the new overlay.
1001             shouldFadeIn = false;
1002         }
1003     }
1004
1005     m_pageOverlay = pageOverlay;
1006     m_pageOverlay->setPage(this);
1007
1008     if (shouldFadeIn)
1009         m_pageOverlay->startFadeInAnimation();
1010
1011     m_drawingArea->didInstallPageOverlay();
1012 #if PLATFORM(WIN)
1013     send(Messages::WebPageProxy::DidInstallOrUninstallPageOverlay(true));
1014 #endif
1015
1016     m_pageOverlay->setNeedsDisplay();
1017 }
1018
1019 void WebPage::uninstallPageOverlay(PageOverlay* pageOverlay, bool fadeOut)
1020 {
1021     if (pageOverlay != m_pageOverlay)
1022         return;
1023
1024     if (fadeOut) {
1025         m_pageOverlay->startFadeOutAnimation();
1026         return;
1027     }
1028
1029     m_pageOverlay->setPage(0);
1030     m_pageOverlay = nullptr;
1031
1032     m_drawingArea->didUninstallPageOverlay();
1033 #if PLATFORM(WIN)
1034     send(Messages::WebPageProxy::DidInstallOrUninstallPageOverlay(false));
1035 #endif
1036 }
1037
1038 PassRefPtr<WebImage> WebPage::snapshotInViewCoordinates(const IntRect& rect, ImageOptions options)
1039 {
1040     FrameView* frameView = m_mainFrame->coreFrame()->view();
1041     if (!frameView)
1042         return 0;
1043
1044     IntSize bitmapSize = rect.size();
1045     float deviceScaleFactor = corePage()->deviceScaleFactor();
1046     bitmapSize.scale(deviceScaleFactor);
1047
1048     RefPtr<WebImage> snapshot = WebImage::create(bitmapSize, options);
1049     if (!snapshot->bitmap())
1050         return 0;
1051     
1052     OwnPtr<WebCore::GraphicsContext> graphicsContext = snapshot->bitmap()->createGraphicsContext();
1053     graphicsContext->applyDeviceScaleFactor(deviceScaleFactor);
1054     graphicsContext->translate(-rect.x(), -rect.y());
1055
1056     frameView->updateLayoutAndStyleIfNeededRecursive();
1057
1058     PaintBehavior oldBehavior = frameView->paintBehavior();
1059     frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
1060     frameView->paint(graphicsContext.get(), rect);
1061     frameView->setPaintBehavior(oldBehavior);
1062
1063     return snapshot.release();
1064 }
1065
1066 PassRefPtr<WebImage> WebPage::scaledSnapshotInDocumentCoordinates(const IntRect& rect, double scaleFactor, ImageOptions options)
1067 {
1068     FrameView* frameView = m_mainFrame->coreFrame()->view();
1069     if (!frameView)
1070         return 0;
1071
1072     float combinedScaleFactor = scaleFactor * corePage()->deviceScaleFactor();
1073     IntSize size(ceil(rect.width() * combinedScaleFactor), ceil(rect.height() * combinedScaleFactor));
1074     RefPtr<WebImage> snapshot = WebImage::create(size, options);
1075     if (!snapshot->bitmap())
1076         return 0;
1077
1078     OwnPtr<WebCore::GraphicsContext> graphicsContext = snapshot->bitmap()->createGraphicsContext();
1079     graphicsContext->applyDeviceScaleFactor(combinedScaleFactor);
1080     graphicsContext->translate(-rect.x(), -rect.y());
1081
1082     frameView->updateLayoutAndStyleIfNeededRecursive();
1083
1084     PaintBehavior oldBehavior = frameView->paintBehavior();
1085     frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
1086     frameView->paintContents(graphicsContext.get(), rect);
1087     frameView->setPaintBehavior(oldBehavior);
1088
1089     return snapshot.release();
1090 }
1091
1092 PassRefPtr<WebImage> WebPage::snapshotInDocumentCoordinates(const IntRect& rect, ImageOptions options)
1093 {
1094     return scaledSnapshotInDocumentCoordinates(rect, 1, options);
1095 }
1096
1097 void WebPage::pageDidScroll()
1098 {
1099     // Hide the find indicator.
1100     m_findController.hideFindIndicator();
1101
1102     m_uiClient.pageDidScroll(this);
1103
1104     send(Messages::WebPageProxy::PageDidScroll());
1105 }
1106
1107 #if USE(TILED_BACKING_STORE)
1108 void WebPage::pageDidRequestScroll(const IntPoint& point)
1109 {
1110     send(Messages::WebPageProxy::PageDidRequestScroll(point));
1111 }
1112 #endif
1113
1114 WebContextMenu* WebPage::contextMenu()
1115 {
1116     if (!m_contextMenu)
1117         m_contextMenu = WebContextMenu::create(this);
1118     return m_contextMenu.get();
1119 }
1120
1121 // Events 
1122
1123 static const WebEvent* g_currentEvent = 0;
1124
1125 // FIXME: WebPage::currentEvent is used by the plug-in code to avoid having to convert from DOM events back to
1126 // WebEvents. When we get the event handling sorted out, this should go away and the Widgets should get the correct
1127 // platform events passed to the event handler code.
1128 const WebEvent* WebPage::currentEvent()
1129 {
1130     return g_currentEvent;
1131 }
1132
1133 class CurrentEvent {
1134 public:
1135     explicit CurrentEvent(const WebEvent& event)
1136         : m_previousCurrentEvent(g_currentEvent)
1137     {
1138         g_currentEvent = &event;
1139     }
1140
1141     ~CurrentEvent()
1142     {
1143         g_currentEvent = m_previousCurrentEvent;
1144     }
1145
1146 private:
1147     const WebEvent* m_previousCurrentEvent;
1148 };
1149
1150 static bool isContextClick(const PlatformMouseEvent& event)
1151 {
1152     if (event.button() == WebCore::RightButton)
1153         return true;
1154
1155 #if PLATFORM(MAC)
1156     // FIXME: this really should be about OSX-style UI, not about the Mac port
1157     if (event.button() == WebCore::LeftButton && event.ctrlKey())
1158         return true;
1159 #endif
1160
1161     return false;
1162 }
1163
1164 static bool handleContextMenuEvent(const PlatformMouseEvent& platformMouseEvent, Page* page)
1165 {
1166     IntPoint point = page->mainFrame()->view()->windowToContents(platformMouseEvent.position());
1167     HitTestResult result = page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, false);
1168
1169     Frame* frame = page->mainFrame();
1170     if (result.innerNonSharedNode())
1171         frame = result.innerNonSharedNode()->document()->frame();
1172     
1173     bool handled = frame->eventHandler()->sendContextMenuEvent(platformMouseEvent);
1174     if (handled)
1175         page->chrome()->showContextMenu();
1176
1177     return handled;
1178 }
1179
1180 static bool handleMouseEvent(const WebMouseEvent& mouseEvent, Page* page, bool onlyUpdateScrollbars)
1181 {
1182     Frame* frame = page->mainFrame();
1183     if (!frame->view())
1184         return false;
1185
1186     PlatformMouseEvent platformMouseEvent = platform(mouseEvent);
1187
1188     switch (platformMouseEvent.type()) {
1189         case PlatformEvent::MousePressed: {
1190             if (isContextClick(platformMouseEvent))
1191                 page->contextMenuController()->clearContextMenu();
1192             
1193             bool handled = frame->eventHandler()->handleMousePressEvent(platformMouseEvent);
1194             if (isContextClick(platformMouseEvent))
1195                 handled = handleContextMenuEvent(platformMouseEvent, page);
1196
1197             return handled;
1198         }
1199         case PlatformEvent::MouseReleased:
1200             return frame->eventHandler()->handleMouseReleaseEvent(platformMouseEvent);
1201         case PlatformEvent::MouseMoved:
1202             return frame->eventHandler()->mouseMoved(platformMouseEvent, onlyUpdateScrollbars);
1203         default:
1204             ASSERT_NOT_REACHED();
1205             return false;
1206     }
1207 }
1208
1209 void WebPage::mouseEvent(const WebMouseEvent& mouseEvent)
1210 {
1211     // Don't try to handle any pending mouse events if a context menu is showing.
1212     if (m_isShowingContextMenu) {
1213         send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), false));
1214         return;
1215     }
1216     
1217     bool handled = false;
1218     
1219     if (m_pageOverlay) {
1220         // Let the page overlay handle the event.
1221         handled = m_pageOverlay->mouseEvent(mouseEvent);
1222     }
1223
1224     if (!handled) {
1225         CurrentEvent currentEvent(mouseEvent);
1226
1227         // We need to do a full, normal hit test during this mouse event if the page is active or if a mouse
1228         // button is currently pressed. It is possible that neither of those things will be true since on 
1229         // Lion when legacy scrollbars are enabled, WebKit receives mouse events all the time. If it is one 
1230         // of those cases where the page is not active and the mouse is not pressed, then we can fire a more
1231         // efficient scrollbars-only version of the event.
1232         bool onlyUpdateScrollbars = !(m_page->focusController()->isActive() || (mouseEvent.button() != WebMouseEvent::NoButton));
1233         handled = handleMouseEvent(mouseEvent, m_page.get(), onlyUpdateScrollbars);
1234     }
1235
1236     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), handled));
1237 }
1238
1239 void WebPage::mouseEventSyncForTesting(const WebMouseEvent& mouseEvent, bool& handled)
1240 {
1241     // Don't try to handle any pending mouse events if a context menu is showing.
1242     if (m_isShowingContextMenu) {
1243         handled = true;
1244         return;
1245     }
1246
1247     handled = m_pageOverlay && m_pageOverlay->mouseEvent(mouseEvent);
1248
1249     if (!handled) {
1250         CurrentEvent currentEvent(mouseEvent);
1251
1252         // We need to do a full, normal hit test during this mouse event if the page is active or if a mouse
1253         // button is currently pressed. It is possible that neither of those things will be true since on 
1254         // Lion when legacy scrollbars are enabled, WebKit receives mouse events all the time. If it is one 
1255         // of those cases where the page is not active and the mouse is not pressed, then we can fire a more
1256         // efficient scrollbars-only version of the event.
1257         bool onlyUpdateScrollbars = !(m_page->focusController()->isActive() || (mouseEvent.button() != WebMouseEvent::NoButton));
1258         handled = handleMouseEvent(mouseEvent, m_page.get(), onlyUpdateScrollbars);
1259     }
1260 }
1261
1262 static bool handleWheelEvent(const WebWheelEvent& wheelEvent, Page* page)
1263 {
1264     Frame* frame = page->mainFrame();
1265     if (!frame->view())
1266         return false;
1267
1268     PlatformWheelEvent platformWheelEvent = platform(wheelEvent);
1269     return frame->eventHandler()->handleWheelEvent(platformWheelEvent);
1270 }
1271
1272 void WebPage::wheelEvent(const WebWheelEvent& wheelEvent)
1273 {
1274     CurrentEvent currentEvent(wheelEvent);
1275
1276     bool handled = handleWheelEvent(wheelEvent, m_page.get());
1277     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(wheelEvent.type()), handled));
1278 }
1279
1280 void WebPage::wheelEventSyncForTesting(const WebWheelEvent& wheelEvent, bool& handled)
1281 {
1282     CurrentEvent currentEvent(wheelEvent);
1283
1284     handled = handleWheelEvent(wheelEvent, m_page.get());
1285 }
1286
1287 static bool handleKeyEvent(const WebKeyboardEvent& keyboardEvent, Page* page)
1288 {
1289     if (!page->mainFrame()->view())
1290         return false;
1291
1292     if (keyboardEvent.type() == WebEvent::Char && keyboardEvent.isSystemKey())
1293         return page->focusController()->focusedOrMainFrame()->eventHandler()->handleAccessKey(platform(keyboardEvent));
1294     return page->focusController()->focusedOrMainFrame()->eventHandler()->keyEvent(platform(keyboardEvent));
1295 }
1296
1297 void WebPage::keyEvent(const WebKeyboardEvent& keyboardEvent)
1298 {
1299     CurrentEvent currentEvent(keyboardEvent);
1300
1301     bool handled = handleKeyEvent(keyboardEvent, m_page.get());
1302     // FIXME: Platform default behaviors should be performed during normal DOM event dispatch (in most cases, in default keydown event handler).
1303     if (!handled)
1304         handled = performDefaultBehaviorForKeyEvent(keyboardEvent);
1305
1306     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(keyboardEvent.type()), handled));
1307 }
1308
1309 void WebPage::keyEventSyncForTesting(const WebKeyboardEvent& keyboardEvent, bool& handled)
1310 {
1311     CurrentEvent currentEvent(keyboardEvent);
1312
1313     handled = handleKeyEvent(keyboardEvent, m_page.get());
1314     if (!handled)
1315         handled = performDefaultBehaviorForKeyEvent(keyboardEvent);
1316 }
1317
1318 #if ENABLE(GESTURE_EVENTS)
1319 static bool handleGestureEvent(const WebGestureEvent& gestureEvent, Page* page)
1320 {
1321     Frame* frame = page->mainFrame();
1322     if (!frame->view())
1323         return false;
1324
1325     PlatformGestureEvent platformGestureEvent = platform(gestureEvent);
1326     return frame->eventHandler()->handleGestureEvent(platformGestureEvent);
1327 }
1328
1329 void WebPage::gestureEvent(const WebGestureEvent& gestureEvent)
1330 {
1331     CurrentEvent currentEvent(gestureEvent);
1332
1333     bool handled = handleGestureEvent(gestureEvent, m_page.get());
1334     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(gestureEvent.type()), handled));
1335 }
1336 #endif
1337
1338 void WebPage::validateCommand(const String& commandName, uint64_t callbackID)
1339 {
1340     bool isEnabled = false;
1341     int32_t state = 0;
1342     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1343     if (frame) {
1344         Editor::Command command = frame->editor()->command(commandName);
1345         state = command.state();
1346         isEnabled = command.isSupported() && command.isEnabled();
1347     }
1348
1349     send(Messages::WebPageProxy::ValidateCommandCallback(commandName, isEnabled, state, callbackID));
1350 }
1351
1352 void WebPage::executeEditCommand(const String& commandName)
1353 {
1354     executeEditingCommand(commandName, String());
1355 }
1356
1357 uint64_t WebPage::restoreSession(const SessionState& sessionState)
1358 {
1359     const BackForwardListItemVector& list = sessionState.list();
1360     size_t size = list.size();
1361     uint64_t currentItemID = 0;
1362     for (size_t i = 0; i < size; ++i) {
1363         WebBackForwardListItem* webItem = list[i].get();
1364         DecoderAdapter decoder(webItem->backForwardData().data(), webItem->backForwardData().size());
1365         
1366         RefPtr<HistoryItem> item = HistoryItem::decodeBackForwardTree(webItem->url(), webItem->title(), webItem->originalURL(), decoder);
1367         if (!item) {
1368             LOG_ERROR("Failed to decode a HistoryItem from session state data.");
1369             return 0;
1370         }
1371         
1372         if (i == sessionState.currentIndex())
1373             currentItemID = webItem->itemID();
1374         
1375         WebBackForwardListProxy::addItemFromUIProcess(list[i]->itemID(), item.release());
1376     }    
1377     ASSERT(currentItemID);
1378     return currentItemID;
1379 }
1380
1381 void WebPage::restoreSessionAndNavigateToCurrentItem(const SessionState& sessionState, const SandboxExtension::Handle& sandboxExtensionHandle)
1382 {
1383     if (uint64_t currentItemID = restoreSession(sessionState))
1384         goToBackForwardItem(currentItemID, sandboxExtensionHandle);
1385 }
1386
1387 #if ENABLE(TOUCH_EVENTS)
1388 static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page)
1389 {
1390     Frame* frame = page->mainFrame();
1391     if (!frame->view())
1392         return false;
1393
1394     return frame->eventHandler()->handleTouchEvent(platform(touchEvent));
1395 }
1396
1397 void WebPage::touchEvent(const WebTouchEvent& touchEvent)
1398 {
1399     CurrentEvent currentEvent(touchEvent);
1400
1401     bool handled = handleTouchEvent(touchEvent, m_page.get());
1402
1403     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(touchEvent.type()), handled));
1404 }
1405
1406 void WebPage::touchEventSyncForTesting(const WebTouchEvent& touchEvent, bool& handled)
1407 {
1408     CurrentEvent currentEvent(touchEvent);
1409     handled = handleTouchEvent(touchEvent, m_page.get());
1410 }
1411 #endif
1412
1413 void WebPage::scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity)
1414 {
1415     page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity);
1416 }
1417
1418 void WebPage::logicalScroll(Page* page, ScrollLogicalDirection direction, ScrollGranularity granularity)
1419 {
1420     page->focusController()->focusedOrMainFrame()->eventHandler()->logicalScrollRecursively(direction, granularity);
1421 }
1422
1423 void WebPage::scrollBy(uint32_t scrollDirection, uint32_t scrollGranularity)
1424 {
1425     scroll(m_page.get(), static_cast<ScrollDirection>(scrollDirection), static_cast<ScrollGranularity>(scrollGranularity));
1426 }
1427
1428 void WebPage::centerSelectionInVisibleArea()
1429 {
1430     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1431     if (!frame)
1432         return;
1433     
1434     frame->selection()->revealSelection(ScrollAlignment::alignCenterAlways);
1435     m_findController.showFindIndicatorInSelection();
1436 }
1437
1438 void WebPage::setActive(bool isActive)
1439 {
1440     m_page->focusController()->setActive(isActive);
1441
1442 #if PLATFORM(MAC)    
1443     // Tell all our plug-in views that the window focus changed.
1444     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
1445         (*it)->setWindowIsFocused(isActive);
1446 #endif
1447 }
1448
1449 void WebPage::setDrawsBackground(bool drawsBackground)
1450 {
1451     if (m_drawsBackground == drawsBackground)
1452         return;
1453
1454     m_drawsBackground = drawsBackground;
1455
1456     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
1457         if (FrameView* view = coreFrame->view())
1458             view->setTransparent(!drawsBackground);
1459     }
1460
1461     m_drawingArea->pageBackgroundTransparencyChanged();
1462     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
1463 }
1464
1465 void WebPage::setDrawsTransparentBackground(bool drawsTransparentBackground)
1466 {
1467     if (m_drawsTransparentBackground == drawsTransparentBackground)
1468         return;
1469
1470     m_drawsTransparentBackground = drawsTransparentBackground;
1471
1472     Color backgroundColor = drawsTransparentBackground ? Color::transparent : Color::white;
1473     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
1474         if (FrameView* view = coreFrame->view())
1475             view->setBaseBackgroundColor(backgroundColor);
1476     }
1477
1478     m_drawingArea->pageBackgroundTransparencyChanged();
1479     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
1480 }
1481
1482 void WebPage::viewWillStartLiveResize()
1483 {
1484     if (!m_page)
1485         return;
1486
1487     // FIXME: This should propagate to all ScrollableAreas.
1488     if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) {
1489         if (FrameView* view = frame->view())
1490             view->willStartLiveResize();
1491     }
1492 }
1493
1494 void WebPage::viewWillEndLiveResize()
1495 {
1496     if (!m_page)
1497         return;
1498
1499     // FIXME: This should propagate to all ScrollableAreas.
1500     if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) {
1501         if (FrameView* view = frame->view())
1502             view->willEndLiveResize();
1503     }
1504 }
1505
1506 void WebPage::setFocused(bool isFocused)
1507 {
1508     m_page->focusController()->setFocused(isFocused);
1509 }
1510
1511 void WebPage::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& event)
1512 {
1513     if (!m_page || !m_page->focusController())
1514         return;
1515
1516     Frame* frame = m_page->focusController()->focusedOrMainFrame();
1517     frame->document()->setFocusedNode(0);
1518
1519     if (isKeyboardEventValid && event.type() == WebEvent::KeyDown) {
1520         PlatformKeyboardEvent platformEvent(platform(event));
1521         platformEvent.disambiguateKeyDownEvent(PlatformEvent::RawKeyDown);
1522         m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, KeyboardEvent::create(platformEvent, frame->document()->defaultView()).get());
1523         return;
1524     }
1525
1526     m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, 0);
1527 }
1528
1529 void WebPage::setWindowResizerSize(const IntSize& windowResizerSize)
1530 {
1531     if (m_windowResizerSize == windowResizerSize)
1532         return;
1533
1534     m_windowResizerSize = windowResizerSize;
1535
1536     for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) {
1537         FrameView* view = coreFrame->view();
1538         if (view)
1539             view->windowResizerRectChanged();
1540     }
1541 }
1542
1543 void WebPage::setCanStartMediaTimerFired()
1544 {
1545     if (m_page)
1546         m_page->setCanStartMedia(true);
1547 }
1548
1549 void WebPage::setIsInWindow(bool isInWindow)
1550 {
1551     if (!isInWindow) {
1552         m_setCanStartMediaTimer.stop();
1553         m_page->setCanStartMedia(false);
1554         m_page->willMoveOffscreen();
1555     } else {
1556         // Defer the call to Page::setCanStartMedia() since it ends up sending a syncrhonous messages to the UI process
1557         // in order to get plug-in connections, and the UI process will be waiting for the Web process to update the backing
1558         // store after moving the view into a window, until it times out and paints white. See <rdar://problem/9242771>.
1559         m_setCanStartMediaTimer.startOneShot(0);
1560         m_page->didMoveOnscreen();
1561     }
1562 }
1563
1564 void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t downloadID)
1565 {
1566     WebFrame* frame = WebProcess::shared().webFrame(frameID);
1567     if (!frame)
1568         return;
1569     frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), downloadID);
1570 }
1571
1572 void WebPage::show()
1573 {
1574     send(Messages::WebPageProxy::ShowPage());
1575 }
1576
1577 void WebPage::setUserAgent(const String& userAgent)
1578 {
1579     m_userAgent = userAgent;
1580 }
1581   
1582 IntPoint WebPage::screenToWindow(const IntPoint& point)
1583 {
1584     IntPoint windowPoint;
1585     sendSync(Messages::WebPageProxy::ScreenToWindow(point), Messages::WebPageProxy::ScreenToWindow::Reply(windowPoint));
1586     return windowPoint;
1587 }
1588     
1589 IntRect WebPage::windowToScreen(const IntRect& rect)
1590 {
1591     IntRect screenRect;
1592     sendSync(Messages::WebPageProxy::WindowToScreen(rect), Messages::WebPageProxy::WindowToScreen::Reply(screenRect));
1593     return screenRect;
1594 }
1595
1596 IntRect WebPage::windowResizerRect() const
1597 {
1598     if (m_windowResizerSize.isEmpty())
1599         return IntRect();
1600
1601     IntSize frameViewSize;
1602     if (Frame* coreFrame = m_mainFrame->coreFrame()) {
1603         if (FrameView* view = coreFrame->view())
1604             frameViewSize = view->size();
1605     }
1606
1607     return IntRect(frameViewSize.width() - m_windowResizerSize.width(), frameViewSize.height() - m_windowResizerSize.height(), 
1608                    m_windowResizerSize.width(), m_windowResizerSize.height());
1609 }
1610
1611 KeyboardUIMode WebPage::keyboardUIMode()
1612 {
1613     bool fullKeyboardAccessEnabled = WebProcess::shared().fullKeyboardAccessEnabled();
1614     return static_cast<KeyboardUIMode>((fullKeyboardAccessEnabled ? KeyboardAccessFull : KeyboardAccessDefault) | (m_tabToLinks ? KeyboardAccessTabsToLinks : 0));
1615 }
1616
1617 void WebPage::runJavaScriptInMainFrame(const String& script, uint64_t callbackID)
1618 {
1619     // NOTE: We need to be careful when running scripts that the objects we depend on don't
1620     // disappear during script execution.
1621
1622     // Retain the SerializedScriptValue at this level so it (and the internal data) lives
1623     // long enough for the DataReference to be encoded by the sent message.
1624     RefPtr<SerializedScriptValue> serializedResultValue;
1625     CoreIPC::DataReference dataReference;
1626
1627     JSLock lock(SilenceAssertionsOnly);
1628     if (JSValue resultValue = m_mainFrame->coreFrame()->script()->executeScript(script, true).jsValue()) {
1629         if ((serializedResultValue = SerializedScriptValue::create(m_mainFrame->jsContext(), toRef(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec(), resultValue), 0)))
1630             dataReference = serializedResultValue->data();
1631     }
1632
1633     send(Messages::WebPageProxy::ScriptValueCallback(dataReference, callbackID));
1634 }
1635
1636 void WebPage::getContentsAsString(uint64_t callbackID)
1637 {
1638     String resultString = m_mainFrame->contentsAsString();
1639     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1640 }
1641
1642 void WebPage::getRenderTreeExternalRepresentation(uint64_t callbackID)
1643 {
1644     String resultString = renderTreeExternalRepresentation();
1645     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1646 }
1647
1648 void WebPage::getSelectionOrContentsAsString(uint64_t callbackID)
1649 {
1650     String resultString = m_mainFrame->selectionAsString();
1651     if (resultString.isEmpty())
1652         resultString = m_mainFrame->contentsAsString();
1653     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1654 }
1655
1656 void WebPage::getSourceForFrame(uint64_t frameID, uint64_t callbackID)
1657 {
1658     String resultString;
1659     if (WebFrame* frame = WebProcess::shared().webFrame(frameID))
1660        resultString = frame->source();
1661
1662     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
1663 }
1664
1665 void WebPage::getMainResourceDataOfFrame(uint64_t frameID, uint64_t callbackID)
1666 {
1667     CoreIPC::DataReference dataReference;
1668
1669     RefPtr<SharedBuffer> buffer;
1670     if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1671         if (DocumentLoader* loader = frame->coreFrame()->loader()->documentLoader()) {
1672             if ((buffer = loader->mainResourceData()))
1673                 dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size());
1674         }
1675     }
1676
1677     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1678 }
1679
1680 static PassRefPtr<SharedBuffer> resourceDataForFrame(Frame* frame, const KURL& resourceURL)
1681 {
1682     DocumentLoader* loader = frame->loader()->documentLoader();
1683     if (!loader)
1684         return 0;
1685
1686     RefPtr<ArchiveResource> subresource = loader->subresource(resourceURL);
1687     if (!subresource)
1688         return 0;
1689
1690     return subresource->data();
1691 }
1692
1693 void WebPage::getResourceDataFromFrame(uint64_t frameID, const String& resourceURLString, uint64_t callbackID)
1694 {
1695     CoreIPC::DataReference dataReference;
1696     KURL resourceURL(KURL(), resourceURLString);
1697
1698     RefPtr<SharedBuffer> buffer;
1699     if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1700         buffer = resourceDataForFrame(frame->coreFrame(), resourceURL);
1701         if (!buffer) {
1702             // Try to get the resource data from the cache.
1703             buffer = cachedResponseDataForURL(resourceURL);
1704         }
1705
1706         if (buffer)
1707             dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size());
1708     }
1709
1710     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1711 }
1712
1713 void WebPage::getWebArchiveOfFrame(uint64_t frameID, uint64_t callbackID)
1714 {
1715     CoreIPC::DataReference dataReference;
1716
1717 #if PLATFORM(MAC) || PLATFORM(WIN)
1718     RetainPtr<CFDataRef> data;
1719     if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) {
1720         if ((data = frame->webArchiveData()))
1721             dataReference = CoreIPC::DataReference(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get()));
1722     }
1723 #endif
1724
1725     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
1726 }
1727
1728 void WebPage::forceRepaintWithoutCallback()
1729 {
1730     m_drawingArea->forceRepaint();
1731 }
1732
1733 void WebPage::forceRepaint(uint64_t callbackID)
1734 {
1735     forceRepaintWithoutCallback();
1736     send(Messages::WebPageProxy::VoidCallback(callbackID));
1737 }
1738
1739 void WebPage::preferencesDidChange(const WebPreferencesStore& store)
1740 {
1741     WebPreferencesStore::removeTestRunnerOverrides();
1742     updatePreferences(store);
1743 }
1744
1745 void WebPage::updatePreferences(const WebPreferencesStore& store)
1746 {
1747     Settings* settings = m_page->settings();
1748
1749     m_tabToLinks = store.getBoolValueForKey(WebPreferencesKey::tabsToLinksKey());
1750
1751     // FIXME: This should be generated from macro expansion for all preferences,
1752     // but we currently don't match the naming of WebCore exactly so we are
1753     // handrolling the boolean and integer preferences until that is fixed.
1754
1755 #define INITIALIZE_SETTINGS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) settings->set##KeyUpper(store.get##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key()));
1756
1757     FOR_EACH_WEBKIT_STRING_PREFERENCE(INITIALIZE_SETTINGS)
1758
1759 #undef INITIALIZE_SETTINGS
1760
1761     settings->setScriptEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptEnabledKey()));
1762     settings->setLoadsImagesAutomatically(store.getBoolValueForKey(WebPreferencesKey::loadsImagesAutomaticallyKey()));
1763     settings->setLoadsSiteIconsIgnoringImageLoadingSetting(store.getBoolValueForKey(WebPreferencesKey::loadsSiteIconsIgnoringImageLoadingPreferenceKey()));
1764     settings->setPluginsEnabled(store.getBoolValueForKey(WebPreferencesKey::pluginsEnabledKey()));
1765     settings->setJavaEnabled(store.getBoolValueForKey(WebPreferencesKey::javaEnabledKey()));
1766     settings->setOfflineWebApplicationCacheEnabled(store.getBoolValueForKey(WebPreferencesKey::offlineWebApplicationCacheEnabledKey()));
1767     settings->setLocalStorageEnabled(store.getBoolValueForKey(WebPreferencesKey::localStorageEnabledKey()));
1768     settings->setXSSAuditorEnabled(store.getBoolValueForKey(WebPreferencesKey::xssAuditorEnabledKey()));
1769     settings->setFrameFlatteningEnabled(store.getBoolValueForKey(WebPreferencesKey::frameFlatteningEnabledKey()));
1770     settings->setPrivateBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey()));
1771     settings->setDeveloperExtrasEnabled(store.getBoolValueForKey(WebPreferencesKey::developerExtrasEnabledKey()));
1772     settings->setTextAreasAreResizable(store.getBoolValueForKey(WebPreferencesKey::textAreasAreResizableKey()));
1773     settings->setNeedsSiteSpecificQuirks(store.getBoolValueForKey(WebPreferencesKey::needsSiteSpecificQuirksKey()));
1774     settings->setJavaScriptCanOpenWindowsAutomatically(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanOpenWindowsAutomaticallyKey()));
1775     settings->setForceFTPDirectoryListings(store.getBoolValueForKey(WebPreferencesKey::forceFTPDirectoryListingsKey()));
1776     settings->setDNSPrefetchingEnabled(store.getBoolValueForKey(WebPreferencesKey::dnsPrefetchingEnabledKey()));
1777 #if ENABLE(WEB_ARCHIVE)
1778     settings->setWebArchiveDebugModeEnabled(store.getBoolValueForKey(WebPreferencesKey::webArchiveDebugModeEnabledKey()));
1779 #endif
1780     settings->setLocalFileContentSniffingEnabled(store.getBoolValueForKey(WebPreferencesKey::localFileContentSniffingEnabledKey()));
1781     settings->setUsesPageCache(store.getBoolValueForKey(WebPreferencesKey::usesPageCacheKey()));
1782     settings->setPageCacheSupportsPlugins(store.getBoolValueForKey(WebPreferencesKey::pageCacheSupportsPluginsKey()));
1783     settings->setAuthorAndUserStylesEnabled(store.getBoolValueForKey(WebPreferencesKey::authorAndUserStylesEnabledKey()));
1784     settings->setPaginateDuringLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::paginateDuringLayoutEnabledKey()));
1785     settings->setDOMPasteAllowed(store.getBoolValueForKey(WebPreferencesKey::domPasteAllowedKey()));
1786     settings->setJavaScriptCanAccessClipboard(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanAccessClipboardKey()));
1787     settings->setShouldPrintBackgrounds(store.getBoolValueForKey(WebPreferencesKey::shouldPrintBackgroundsKey()));
1788     settings->setWebSecurityEnabled(store.getBoolValueForKey(WebPreferencesKey::webSecurityEnabledKey()));
1789     settings->setAllowUniversalAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowUniversalAccessFromFileURLsKey()));
1790     settings->setAllowFileAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowFileAccessFromFileURLsKey()));
1791
1792     settings->setMinimumFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumFontSizeKey()));
1793     settings->setMinimumLogicalFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumLogicalFontSizeKey()));
1794     settings->setDefaultFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFontSizeKey()));
1795     settings->setDefaultFixedFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFixedFontSizeKey()));
1796     settings->setLayoutFallbackWidth(store.getUInt32ValueForKey(WebPreferencesKey::layoutFallbackWidthKey()));
1797     settings->setDeviceDPI(store.getUInt32ValueForKey(WebPreferencesKey::deviceDPIKey()));
1798     settings->setDeviceWidth(store.getUInt32ValueForKey(WebPreferencesKey::deviceWidthKey()));
1799     settings->setDeviceHeight(store.getUInt32ValueForKey(WebPreferencesKey::deviceHeightKey()));
1800     settings->setEditableLinkBehavior(static_cast<WebCore::EditableLinkBehavior>(store.getUInt32ValueForKey(WebPreferencesKey::editableLinkBehaviorKey())));
1801     settings->setShowsToolTipOverTruncatedText(store.getBoolValueForKey(WebPreferencesKey::showsToolTipOverTruncatedTextKey()));
1802
1803     settings->setAcceleratedCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingEnabledKey()) && LayerTreeHost::supportsAcceleratedCompositing());
1804     settings->setAcceleratedDrawingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedDrawingEnabledKey()) && LayerTreeHost::supportsAcceleratedCompositing());
1805     settings->setCanvasUsesAcceleratedDrawing(store.getBoolValueForKey(WebPreferencesKey::canvasUsesAcceleratedDrawingKey()) && LayerTreeHost::supportsAcceleratedCompositing());
1806     settings->setShowDebugBorders(store.getBoolValueForKey(WebPreferencesKey::compositingBordersVisibleKey()));
1807     settings->setShowRepaintCounter(store.getBoolValueForKey(WebPreferencesKey::compositingRepaintCountersVisibleKey()));
1808     settings->setWebGLEnabled(store.getBoolValueForKey(WebPreferencesKey::webGLEnabledKey()));
1809     settings->setMediaPlaybackRequiresUserGesture(store.getBoolValueForKey(WebPreferencesKey::mediaPlaybackRequiresUserGestureKey()));
1810     settings->setMediaPlaybackAllowsInline(store.getBoolValueForKey(WebPreferencesKey::mediaPlaybackAllowsInlineKey()));
1811     settings->setMockScrollbarsEnabled(store.getBoolValueForKey(WebPreferencesKey::mockScrollbarsEnabledKey()));
1812
1813 #if ENABLE(SQL_DATABASE)
1814     AbstractDatabase::setIsAvailable(store.getBoolValueForKey(WebPreferencesKey::databasesEnabledKey()));
1815 #endif
1816
1817 #if ENABLE(FULLSCREEN_API)
1818     settings->setFullScreenEnabled(store.getBoolValueForKey(WebPreferencesKey::fullScreenEnabledKey()));
1819 #endif
1820
1821     settings->setLocalStorageDatabasePath(WebProcess::shared().localStorageDirectory());
1822
1823 #if USE(AVFOUNDATION)
1824     settings->setAVFoundationEnabled(store.getBoolValueForKey(WebPreferencesKey::isAVFoundationEnabledKey()));
1825 #endif
1826
1827 #if ENABLE(WEB_SOCKETS)
1828     settings->setUseHixie76WebSocketProtocol(store.getBoolValueForKey(WebPreferencesKey::hixie76WebSocketProtocolEnabledKey()));
1829 #endif
1830
1831 #if ENABLE(WEB_AUDIO)
1832     settings->setWebAudioEnabled(store.getBoolValueForKey(WebPreferencesKey::webAudioEnabledKey()));
1833 #endif
1834
1835     settings->setApplicationChromeMode(store.getBoolValueForKey(WebPreferencesKey::applicationChromeModeKey()));    
1836     settings->setSuppressIncrementalRendering(store.getBoolValueForKey(WebPreferencesKey::suppressIncrementalRenderingKey()));
1837     settings->setBackspaceKeyNavigationEnabled(store.getBoolValueForKey(WebPreferencesKey::backspaceKeyNavigationEnabledKey()));
1838     settings->setCaretBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::caretBrowsingEnabledKey()));
1839
1840 #if ENABLE(VIDEO_TRACK)
1841     settings->setShouldDisplaySubtitles(store.getBoolValueForKey(WebPreferencesKey::shouldDisplaySubtitlesKey()));
1842     settings->setShouldDisplayCaptions(store.getBoolValueForKey(WebPreferencesKey::shouldDisplayCaptionsKey()));
1843     settings->setShouldDisplayTextDescriptions(store.getBoolValueForKey(WebPreferencesKey::shouldDisplayTextDescriptionsKey()));
1844 #endif
1845
1846     platformPreferencesDidChange(store);
1847 }
1848
1849 #if ENABLE(INSPECTOR)
1850 WebInspector* WebPage::inspector()
1851 {
1852     if (m_isClosed)
1853         return 0;
1854     if (!m_inspector)
1855         m_inspector = WebInspector::create(this);
1856     return m_inspector.get();
1857 }
1858 #endif
1859
1860 #if ENABLE(FULLSCREEN_API)
1861 WebFullScreenManager* WebPage::fullScreenManager()
1862 {
1863     if (!m_fullScreenManager)
1864         m_fullScreenManager = WebFullScreenManager::create(this);
1865     return m_fullScreenManager.get();
1866 }
1867 #endif
1868
1869 NotificationPermissionRequestManager* WebPage::notificationPermissionRequestManager()
1870 {
1871     if (m_notificationPermissionRequestManager)
1872         return m_notificationPermissionRequestManager.get();
1873
1874     m_notificationPermissionRequestManager = NotificationPermissionRequestManager::create(this);
1875     return m_notificationPermissionRequestManager.get();
1876 }
1877
1878 #if !PLATFORM(GTK) && !PLATFORM(MAC)
1879 bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt)
1880 {
1881     Node* node = evt->target()->toNode();
1882     ASSERT(node);
1883     Frame* frame = node->document()->frame();
1884     ASSERT(frame);
1885
1886     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
1887     if (!keyEvent)
1888         return false;
1889
1890     Editor::Command command = frame->editor()->command(interpretKeyEvent(evt));
1891
1892     if (keyEvent->type() == PlatformEvent::RawKeyDown) {
1893         // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
1894         // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
1895         // (e.g. Tab that inserts a Tab character, or Enter).
1896         return !command.isTextInsertion() && command.execute(evt);
1897     }
1898
1899     if (command.execute(evt))
1900         return true;
1901
1902     // Don't insert null or control characters as they can result in unexpected behaviour
1903     if (evt->charCode() < ' ')
1904         return false;
1905
1906     return frame->editor()->insertText(evt->keyEvent()->text(), evt);
1907 }
1908 #endif
1909
1910 #if PLATFORM(WIN)
1911 void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const WebCore::DragDataMap& dataMap, uint32_t flags)
1912 {
1913     if (!m_page) {
1914         send(Messages::WebPageProxy::DidPerformDragControllerAction(WebCore::DragSession()));
1915         return;
1916     }
1917
1918     DragData dragData(dataMap, clientPosition, globalPosition, static_cast<DragOperation>(draggingSourceOperationMask), static_cast<DragApplicationFlags>(flags));
1919     switch (action) {
1920     case DragControllerActionEntered:
1921         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData)));
1922         break;
1923
1924     case DragControllerActionUpdated:
1925         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData)));
1926         break;
1927         
1928     case DragControllerActionExited:
1929         m_page->dragController()->dragExited(&dragData);
1930         break;
1931         
1932     case DragControllerActionPerformDrag:
1933         m_page->dragController()->performDrag(&dragData);
1934         break;
1935         
1936     default:
1937         ASSERT_NOT_REACHED();
1938     }
1939 }
1940
1941 #elif PLATFORM(QT) || PLATFORM(GTK)
1942 void WebPage::performDragControllerAction(uint64_t action, WebCore::DragData dragData)
1943 {
1944     if (!m_page) {
1945         send(Messages::WebPageProxy::DidPerformDragControllerAction(WebCore::DragSession()));
1946 #if PLATFORM(QT)
1947         QMimeData* data = const_cast<QMimeData*>(dragData.platformData());
1948 #elif PLATFORM(GTK)
1949         DataObjectGtk* data = const_cast<DataObjectGtk*>(dragData.platformData());
1950 #endif
1951         delete data;
1952         return;
1953     }
1954
1955     switch (action) {
1956     case DragControllerActionEntered:
1957         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData)));
1958         break;
1959
1960     case DragControllerActionUpdated:
1961         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData)));
1962         break;
1963
1964     case DragControllerActionExited:
1965         m_page->dragController()->dragExited(&dragData);
1966         break;
1967
1968     case DragControllerActionPerformDrag: {
1969         m_page->dragController()->performDrag(&dragData);
1970         break;
1971     }
1972
1973     default:
1974         ASSERT_NOT_REACHED();
1975     }
1976     // DragData does not delete its platformData so we need to do that here.
1977 #if PLATFORM(QT)
1978     QMimeData* data = const_cast<QMimeData*>(dragData.platformData());
1979 #elif PLATFORM(GTK)
1980     DataObjectGtk* data = const_cast<DataObjectGtk*>(dragData.platformData());
1981 #endif
1982     delete data;
1983 }
1984
1985 #else
1986 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)
1987 {
1988     if (!m_page) {
1989         send(Messages::WebPageProxy::DidPerformDragControllerAction(WebCore::DragSession()));
1990         return;
1991     }
1992
1993     DragData dragData(dragStorageName, clientPosition, globalPosition, static_cast<DragOperation>(draggingSourceOperationMask), static_cast<DragApplicationFlags>(flags));
1994     switch (action) {
1995     case DragControllerActionEntered:
1996         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData)));
1997         break;
1998
1999     case DragControllerActionUpdated:
2000         send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData)));
2001         break;
2002         
2003     case DragControllerActionExited:
2004         m_page->dragController()->dragExited(&dragData);
2005         break;
2006         
2007     case DragControllerActionPerformDrag: {
2008         ASSERT(!m_pendingDropSandboxExtension);
2009
2010         m_pendingDropSandboxExtension = SandboxExtension::create(sandboxExtensionHandle);
2011
2012         m_page->dragController()->performDrag(&dragData);
2013
2014         // If we started loading a local file, the sandbox extension tracker would have adopted this
2015         // pending drop sandbox extension. If not, we'll play it safe and invalidate it.
2016         if (m_pendingDropSandboxExtension) {
2017             m_pendingDropSandboxExtension->invalidate();
2018             m_pendingDropSandboxExtension = nullptr;
2019         }
2020
2021         break;
2022     }
2023
2024     default:
2025         ASSERT_NOT_REACHED();
2026     }
2027 }
2028 #endif
2029
2030 void WebPage::dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation)
2031 {
2032     IntPoint adjustedClientPosition(clientPosition.x() + m_page->dragController()->dragOffset().x(), clientPosition.y() + m_page->dragController()->dragOffset().y());
2033     IntPoint adjustedGlobalPosition(globalPosition.x() + m_page->dragController()->dragOffset().x(), globalPosition.y() + m_page->dragController()->dragOffset().y());
2034
2035     m_page->dragController()->dragEnded();
2036     FrameView* view = m_page->mainFrame()->view();
2037     if (!view)
2038         return;
2039     // FIXME: These are fake modifier keys here, but they should be real ones instead.
2040     PlatformMouseEvent event(adjustedClientPosition, adjustedGlobalPosition, LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, currentTime());
2041     m_page->mainFrame()->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation);
2042 }
2043
2044 void WebPage::willPerformLoadDragDestinationAction()
2045 {
2046     m_sandboxExtensionTracker.willPerformLoadDragDestinationAction(m_pendingDropSandboxExtension.release());
2047 }
2048
2049 WebUndoStep* WebPage::webUndoStep(uint64_t stepID)
2050 {
2051     return m_undoStepMap.get(stepID).get();
2052 }
2053
2054 void WebPage::addWebUndoStep(uint64_t stepID, WebUndoStep* entry)
2055 {
2056     m_undoStepMap.set(stepID, entry);
2057 }
2058
2059 void WebPage::removeWebEditCommand(uint64_t stepID)
2060 {
2061     m_undoStepMap.remove(stepID);
2062 }
2063
2064 void WebPage::unapplyEditCommand(uint64_t stepID)
2065 {
2066     WebUndoStep* step = webUndoStep(stepID);
2067     if (!step)
2068         return;
2069
2070     step->step()->unapply();
2071 }
2072
2073 void WebPage::reapplyEditCommand(uint64_t stepID)
2074 {
2075     WebUndoStep* step = webUndoStep(stepID);
2076     if (!step)
2077         return;
2078
2079     m_isInRedo = true;
2080     step->step()->reapply();
2081     m_isInRedo = false;
2082 }
2083
2084 void WebPage::didRemoveEditCommand(uint64_t commandID)
2085 {
2086     removeWebEditCommand(commandID);
2087 }
2088
2089 void WebPage::setActivePopupMenu(WebPopupMenu* menu)
2090 {
2091     m_activePopupMenu = menu;
2092 }
2093
2094 void WebPage::setActiveOpenPanelResultListener(PassRefPtr<WebOpenPanelResultListener> openPanelResultListener)
2095 {
2096     m_activeOpenPanelResultListener = openPanelResultListener;
2097 }
2098
2099 bool WebPage::findStringFromInjectedBundle(const String& target, FindOptions options)
2100 {
2101     return m_page->findString(target, options);
2102 }
2103
2104 void WebPage::findString(const String& string, uint32_t options, uint32_t maxMatchCount)
2105 {
2106     m_findController.findString(string, static_cast<FindOptions>(options), maxMatchCount);
2107 }
2108
2109 void WebPage::hideFindUI()
2110 {
2111     m_findController.hideFindUI();
2112 }
2113
2114 void WebPage::countStringMatches(const String& string, uint32_t options, uint32_t maxMatchCount)
2115 {
2116     m_findController.countStringMatches(string, static_cast<FindOptions>(options), maxMatchCount);
2117 }
2118
2119 void WebPage::didChangeSelectedIndexForActivePopupMenu(int32_t newIndex)
2120 {
2121     if (!m_activePopupMenu)
2122         return;
2123
2124     m_activePopupMenu->didChangeSelectedIndex(newIndex);
2125     m_activePopupMenu = 0;
2126 }
2127
2128 void WebPage::didChooseFilesForOpenPanel(const Vector<String>& files)
2129 {
2130     if (!m_activeOpenPanelResultListener)
2131         return;
2132
2133     m_activeOpenPanelResultListener->didChooseFiles(files);
2134     m_activeOpenPanelResultListener = 0;
2135 }
2136
2137 void WebPage::didCancelForOpenPanel()
2138 {
2139     m_activeOpenPanelResultListener = 0;
2140 }
2141
2142 #if ENABLE(WEB_PROCESS_SANDBOX)
2143 void WebPage::extendSandboxForFileFromOpenPanel(const SandboxExtension::Handle& handle)
2144 {
2145     SandboxExtension::create(handle)->consumePermanently();
2146 }
2147 #endif
2148
2149 void WebPage::didReceiveGeolocationPermissionDecision(uint64_t geolocationID, bool allowed)
2150 {
2151     m_geolocationPermissionRequestManager.didReceiveGeolocationPermissionDecision(geolocationID, allowed);
2152 }
2153
2154 void WebPage::didReceiveNotificationPermissionDecision(uint64_t notificationID, bool allowed)
2155 {
2156     notificationPermissionRequestManager()->didReceiveNotificationPermissionDecision(notificationID, allowed);
2157 }
2158
2159 void WebPage::advanceToNextMisspelling(bool startBeforeSelection)
2160 {
2161     Frame* frame = m_page->focusController()->focusedOrMainFrame();
2162     frame->editor()->advanceToNextMisspelling(startBeforeSelection);
2163 }
2164
2165 void WebPage::changeSpellingToWord(const String& word)
2166 {
2167     replaceSelectionWithText(m_page->focusController()->focusedOrMainFrame(), word);
2168 }
2169
2170 void WebPage::unmarkAllMisspellings()
2171 {
2172     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
2173         if (Document* document = frame->document())
2174             document->markers()->removeMarkers(DocumentMarker::Spelling);
2175     }
2176 }
2177
2178 void WebPage::unmarkAllBadGrammar()
2179 {
2180     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
2181         if (Document* document = frame->document())
2182             document->markers()->removeMarkers(DocumentMarker::Grammar);
2183     }
2184 }
2185
2186 #if PLATFORM(MAC)
2187 void WebPage::uppercaseWord()
2188 {
2189     m_page->focusController()->focusedOrMainFrame()->editor()->uppercaseWord();
2190 }
2191
2192 void WebPage::lowercaseWord()
2193 {
2194     m_page->focusController()->focusedOrMainFrame()->editor()->lowercaseWord();
2195 }
2196
2197 void WebPage::capitalizeWord()
2198 {
2199     m_page->focusController()->focusedOrMainFrame()->editor()->capitalizeWord();
2200 }
2201 #endif
2202     
2203 void WebPage::setTextForActivePopupMenu(int32_t index)
2204 {
2205     if (!m_activePopupMenu)
2206         return;
2207
2208     m_activePopupMenu->setTextForIndex(index);
2209 }
2210
2211 #if PLATFORM(GTK)
2212 void WebPage::failedToShowPopupMenu()
2213 {
2214     if (!m_activePopupMenu)
2215         return;
2216
2217     m_activePopupMenu->client()->popupDidHide();
2218 }
2219 #endif
2220
2221 void WebPage::didSelectItemFromActiveContextMenu(const WebContextMenuItemData& item)
2222 {
2223     if (!m_contextMenu)
2224         return;
2225
2226     m_contextMenu->itemSelected(item);
2227     m_contextMenu = 0;
2228 }
2229
2230 void WebPage::replaceSelectionWithText(Frame* frame, const String& text)
2231 {
2232     bool selectReplacement = true;
2233     bool smartReplace = false;
2234     return frame->editor()->replaceSelectionWithText(text, selectReplacement, smartReplace);
2235 }
2236
2237 void WebPage::clearSelection()
2238 {
2239     m_page->focusController()->focusedOrMainFrame()->selection()->clear();
2240 }
2241
2242 bool WebPage::mainFrameHasCustomRepresentation() const
2243 {
2244     if (Frame* frame = mainFrame())
2245         return static_cast<WebFrameLoaderClient*>(frame->loader()->client())->frameHasCustomRepresentation();
2246
2247     return false;
2248 }
2249
2250 void WebPage::didChangeScrollOffsetForMainFrame()
2251 {
2252     Frame* frame = m_page->mainFrame();
2253     IntPoint scrollPosition = frame->view()->scrollPosition();
2254     IntPoint maximumScrollPosition = frame->view()->maximumScrollPosition();
2255     IntPoint minimumScrollPosition = frame->view()->minimumScrollPosition();
2256
2257     bool isPinnedToLeftSide = (scrollPosition.x() <= minimumScrollPosition.x());
2258     bool isPinnedToRightSide = (scrollPosition.x() >= maximumScrollPosition.x());
2259
2260     if (isPinnedToLeftSide != m_cachedMainFrameIsPinnedToLeftSide || isPinnedToRightSide != m_cachedMainFrameIsPinnedToRightSide) {
2261         send(Messages::WebPageProxy::DidChangeScrollOffsetPinningForMainFrame(isPinnedToLeftSide, isPinnedToRightSide));
2262         
2263         m_cachedMainFrameIsPinnedToLeftSide = isPinnedToLeftSide;
2264         m_cachedMainFrameIsPinnedToRightSide = isPinnedToRightSide;
2265     }
2266 }
2267
2268 void WebPage::mainFrameDidLayout()
2269 {
2270     unsigned pageCount = m_page->pageCount();
2271     if (pageCount != m_cachedPageCount) {
2272         send(Messages::WebPageProxy::DidChangePageCount(pageCount));
2273         m_cachedPageCount = pageCount;
2274     }
2275 }
2276
2277 #if PLATFORM(MAC)
2278
2279 void WebPage::addPluginView(PluginView* pluginView)
2280 {
2281     ASSERT(!m_pluginViews.contains(pluginView));
2282
2283     m_pluginViews.add(pluginView);
2284 }
2285
2286 void WebPage::removePluginView(PluginView* pluginView)
2287 {
2288     ASSERT(m_pluginViews.contains(pluginView));
2289
2290     m_pluginViews.remove(pluginView);
2291 }
2292
2293 void WebPage::setWindowIsVisible(bool windowIsVisible)
2294 {
2295     m_windowIsVisible = windowIsVisible;
2296
2297     // Tell all our plug-in views that the window visibility changed.
2298     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
2299         (*it)->setWindowIsVisible(windowIsVisible);
2300 }
2301
2302 void WebPage::windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates, const WebCore::IntPoint& accessibilityViewCoordinates)
2303 {
2304     m_windowFrameInScreenCoordinates = windowFrameInScreenCoordinates;
2305     m_viewFrameInWindowCoordinates = viewFrameInWindowCoordinates;
2306     m_accessibilityPosition = accessibilityViewCoordinates;
2307     
2308     // Tell all our plug-in views that the window and view frames have changed.
2309     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it)
2310         (*it)->windowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates);
2311 }
2312
2313 #endif
2314
2315 bool WebPage::windowIsFocused() const
2316 {
2317 #if PLATFORM(MAC)
2318     if (!m_windowIsVisible)
2319         return false;
2320 #endif
2321     return m_page->focusController()->isFocused() && m_page->focusController()->isActive();
2322 }    
2323
2324 void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
2325 {
2326     if (messageID.is<CoreIPC::MessageClassDrawingArea>()) {
2327         if (m_drawingArea)
2328             m_drawingArea->didReceiveDrawingAreaMessage(connection, messageID, arguments);
2329         return;
2330     }
2331
2332 #if USE(TILED_BACKING_STORE) && USE(ACCELERATED_COMPOSITING)
2333     if (messageID.is<CoreIPC::MessageClassLayerTreeHost>()) {
2334         if (m_drawingArea)
2335             m_drawingArea->didReceiveLayerTreeHostMessage(connection, messageID, arguments);
2336         return;
2337     }
2338 #endif
2339     
2340 #if ENABLE(INSPECTOR)
2341     if (messageID.is<CoreIPC::MessageClassWebInspector>()) {
2342         if (WebInspector* inspector = this->inspector())
2343             inspector->didReceiveWebInspectorMessage(connection, messageID, arguments);
2344         return;
2345     }
2346 #endif
2347
2348 #if ENABLE(FULLSCREEN_API)
2349     if (messageID.is<CoreIPC::MessageClassWebFullScreenManager>()) {
2350         fullScreenManager()->didReceiveMessage(connection, messageID, arguments);
2351         return;
2352     }
2353 #endif
2354
2355     didReceiveWebPageMessage(connection, messageID, arguments);
2356 }
2357
2358 void WebPage::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, OwnPtr<CoreIPC::ArgumentEncoder>& reply)
2359 {   
2360     didReceiveSyncWebPageMessage(connection, messageID, arguments, reply);
2361 }
2362     
2363 InjectedBundleBackForwardList* WebPage::backForwardList()
2364 {
2365     if (!m_backForwardList)
2366         m_backForwardList = InjectedBundleBackForwardList::create(this);
2367     return m_backForwardList.get();
2368 }
2369
2370 #if PLATFORM(QT)
2371 void WebPage::findZoomableAreaForPoint(const WebCore::IntPoint& point)
2372 {
2373     Frame* mainframe = m_mainFrame->coreFrame();
2374     HitTestResult result = mainframe->eventHandler()->hitTestResultAtPoint(mainframe->view()->windowToContents(point), /*allowShadowContent*/ false, /*ignoreClipping*/ true);
2375
2376     Node* node = result.innerNode();
2377
2378     if (!node)
2379         return;
2380
2381     IntRect zoomableArea = node->getRect();
2382
2383     while (true) {
2384         bool found = !node->isTextNode() && !node->isShadowRoot();
2385
2386         // No candidate found, bail out.
2387         if (!found && !node->parentNode())
2388             return;
2389
2390         // Candidate found, and it is a better candidate than its parent.
2391         // NB: A parent is considered a better candidate iff the node is
2392         // contained by it and it is the only child.
2393         if (found && (!node->parentNode() || node->parentNode()->childNodeCount() != 1))
2394             break;
2395
2396         node = node->parentNode();
2397         zoomableArea.unite(node->getRect());
2398     }
2399
2400     if (node->document() && node->document()->frame() && node->document()->frame()->view()) {
2401         const ScrollView* view = node->document()->frame()->view();
2402         zoomableArea = view->contentsToWindow(zoomableArea);
2403     }
2404
2405     send(Messages::WebPageProxy::DidFindZoomableArea(point, zoomableArea));
2406 }
2407 #endif
2408
2409 WebPage::SandboxExtensionTracker::~SandboxExtensionTracker()
2410 {
2411     invalidate();
2412 }
2413
2414 void WebPage::SandboxExtensionTracker::invalidate()
2415 {
2416     if (m_pendingProvisionalSandboxExtension) {
2417         m_pendingProvisionalSandboxExtension->invalidate();
2418         m_pendingProvisionalSandboxExtension = 0;
2419     }
2420
2421     if (m_provisionalSandboxExtension) {
2422         m_provisionalSandboxExtension->invalidate();
2423         m_provisionalSandboxExtension = 0;
2424     }
2425
2426     if (m_committedSandboxExtension) {
2427         m_committedSandboxExtension->invalidate();
2428         m_committedSandboxExtension = 0;
2429     }
2430 }
2431
2432 void WebPage::SandboxExtensionTracker::willPerformLoadDragDestinationAction(PassRefPtr<SandboxExtension> pendingDropSandboxExtension)
2433 {
2434     setPendingProvisionalSandboxExtension(pendingDropSandboxExtension);
2435 }
2436
2437 void WebPage::SandboxExtensionTracker::beginLoad(WebFrame* frame, const SandboxExtension::Handle& handle)
2438 {
2439     ASSERT(frame->isMainFrame());
2440
2441     setPendingProvisionalSandboxExtension(SandboxExtension::create(handle));
2442 }
2443
2444 void WebPage::SandboxExtensionTracker::setPendingProvisionalSandboxExtension(PassRefPtr<SandboxExtension> pendingProvisionalSandboxExtension)
2445 {
2446     // If we get two beginLoad calls in succession, without a provisional load starting, then
2447     // m_pendingProvisionalSandboxExtension will be non-null. Invalidate and null out the extension if that is the case.
2448     if (m_pendingProvisionalSandboxExtension) {
2449         m_pendingProvisionalSandboxExtension->invalidate();
2450         m_pendingProvisionalSandboxExtension = nullptr;
2451     }
2452     
2453     m_pendingProvisionalSandboxExtension = pendingProvisionalSandboxExtension;    
2454 }
2455
2456 static bool shouldReuseCommittedSandboxExtension(WebFrame* frame)
2457 {
2458     ASSERT(frame->isMainFrame());
2459
2460     FrameLoader* frameLoader = frame->coreFrame()->loader();
2461     FrameLoadType frameLoadType = frameLoader->loadType();
2462
2463     // If the page is being reloaded, it should reuse whatever extension is committed.
2464     if (frameLoadType == FrameLoadTypeReload || frameLoadType == FrameLoadTypeReloadFromOrigin)
2465         return true;
2466
2467     DocumentLoader* documentLoader = frameLoader->documentLoader();
2468     DocumentLoader* provisionalDocumentLoader = frameLoader->provisionalDocumentLoader();
2469     if (!documentLoader || !provisionalDocumentLoader)
2470         return false;
2471
2472     if (documentLoader->url().isLocalFile() && provisionalDocumentLoader->url().isLocalFile())
2473         return true;
2474
2475     return false;
2476 }
2477
2478 void WebPage::SandboxExtensionTracker::didStartProvisionalLoad(WebFrame* frame)
2479 {
2480     if (!frame->isMainFrame())
2481         return;
2482
2483     // We should only reuse the commited sandbox extension if it is not null. It can be
2484     // null if the last load was for an error page.
2485     if (m_committedSandboxExtension && shouldReuseCommittedSandboxExtension(frame)) {
2486         m_pendingProvisionalSandboxExtension = m_committedSandboxExtension.release();
2487         ASSERT(!m_committedSandboxExtension);
2488     }
2489
2490     ASSERT(!m_provisionalSandboxExtension);
2491
2492     m_provisionalSandboxExtension = m_pendingProvisionalSandboxExtension.release();
2493     if (!m_provisionalSandboxExtension)
2494         return;
2495
2496     m_provisionalSandboxExtension->consume();
2497 }
2498
2499 void WebPage::SandboxExtensionTracker::didCommitProvisionalLoad(WebFrame* frame)
2500 {
2501     if (!frame->isMainFrame())
2502         return;
2503     
2504     ASSERT(!m_pendingProvisionalSandboxExtension);
2505
2506     // The provisional load has been committed. Invalidate the currently committed sandbox
2507     // extension and make the provisional sandbox extension the committed sandbox extension.
2508     if (m_committedSandboxExtension)
2509         m_committedSandboxExtension->invalidate();
2510
2511     m_committedSandboxExtension = m_provisionalSandboxExtension.release();
2512 }
2513
2514 void WebPage::SandboxExtensionTracker::didFailProvisionalLoad(WebFrame* frame)
2515 {
2516     if (!frame->isMainFrame())
2517         return;
2518
2519     if (!m_provisionalSandboxExtension)
2520         return;
2521
2522     m_provisionalSandboxExtension->invalidate();
2523     m_provisionalSandboxExtension = nullptr;
2524 }
2525
2526 bool WebPage::hasLocalDataForURL(const KURL& url)
2527 {
2528     if (url.isLocalFile())
2529         return true;
2530
2531     FrameLoader* frameLoader = m_page->mainFrame()->loader();
2532     DocumentLoader* documentLoader = frameLoader ? frameLoader->documentLoader() : 0;
2533     if (documentLoader && documentLoader->subresource(url))
2534         return true;
2535
2536     return platformHasLocalDataForURL(url);
2537 }
2538
2539 void WebPage::setCustomTextEncodingName(const String& encoding)
2540 {
2541     m_page->mainFrame()->loader()->reloadWithOverrideEncoding(encoding);
2542 }
2543
2544 void WebPage::didRemoveBackForwardItem(uint64_t itemID)
2545 {
2546     WebBackForwardListProxy::removeItem(itemID);
2547 }
2548
2549 #if PLATFORM(MAC)
2550
2551 bool WebPage::isSpeaking()
2552 {
2553     bool result;
2554     return sendSync(Messages::WebPageProxy::GetIsSpeaking(), Messages::WebPageProxy::GetIsSpeaking::Reply(result)) && result;
2555 }
2556
2557 void WebPage::speak(const String& string)
2558 {
2559     send(Messages::WebPageProxy::Speak(string));
2560 }
2561
2562 void WebPage::stopSpeaking()
2563 {
2564     send(Messages::WebPageProxy::StopSpeaking());
2565 }
2566
2567 #endif
2568
2569 #if USE(CG)
2570 static RetainPtr<CGPDFDocumentRef> pdfDocumentForPrintingFrame(Frame* coreFrame)
2571 {
2572     Document* document = coreFrame->document();
2573     if (!document)
2574         return 0;
2575
2576     if (!document->isPluginDocument())
2577         return 0;
2578
2579     PluginView* pluginView = static_cast<PluginView*>(toPluginDocument(document)->pluginWidget());
2580     if (!pluginView)
2581         return 0;
2582
2583     return pluginView->pdfDocumentForPrinting();
2584 }
2585 #endif // USE(CG)
2586
2587 void WebPage::beginPrinting(uint64_t frameID, const PrintInfo& printInfo)
2588 {
2589     WebFrame* frame = WebProcess::shared().webFrame(frameID);
2590     if (!frame)
2591         return;
2592
2593     Frame* coreFrame = frame->coreFrame();
2594     if (!coreFrame)
2595         return;
2596
2597 #if USE(CG)
2598     if (pdfDocumentForPrintingFrame(coreFrame))
2599         return;
2600 #endif // USE(CG)
2601
2602     if (!m_printContext)
2603         m_printContext = adoptPtr(new PrintContext(coreFrame));
2604
2605     m_printContext->begin(printInfo.availablePaperWidth, printInfo.availablePaperHeight);
2606
2607     float fullPageHeight;
2608     m_printContext->computePageRects(FloatRect(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight), 0, 0, printInfo.pageSetupScaleFactor, fullPageHeight, true);
2609 }
2610
2611 void WebPage::endPrinting()
2612 {
2613     m_printContext = nullptr;
2614 }
2615
2616 void WebPage::computePagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, uint64_t callbackID)
2617 {
2618     Vector<IntRect> resultPageRects;
2619     double resultTotalScaleFactorForPrinting = 1;
2620
2621     beginPrinting(frameID, printInfo);
2622
2623     if (m_printContext) {
2624         resultPageRects = m_printContext->pageRects();
2625         resultTotalScaleFactorForPrinting = m_printContext->computeAutomaticScaleFactor(FloatSize(printInfo.availablePaperWidth, printInfo.availablePaperHeight)) * printInfo.pageSetupScaleFactor;
2626     }
2627 #if USE(CG)
2628     else {
2629         WebFrame* frame = WebProcess::shared().webFrame(frameID);
2630         Frame* coreFrame = frame ? frame->coreFrame() : 0;
2631         RetainPtr<CGPDFDocumentRef> pdfDocument = coreFrame ? pdfDocumentForPrintingFrame(coreFrame) : 0;
2632         if (pdfDocument && CGPDFDocumentAllowsPrinting(pdfDocument.get())) {
2633             CFIndex pageCount = CGPDFDocumentGetNumberOfPages(pdfDocument.get());
2634             IntRect pageRect(0, 0, ceilf(printInfo.availablePaperWidth), ceilf(printInfo.availablePaperHeight));
2635             for (CFIndex i = 1; i <= pageCount; ++i) {
2636                 resultPageRects.append(pageRect);
2637                 pageRect.move(0, pageRect.height());
2638             }
2639         }
2640     }
2641 #endif // USE(CG)
2642
2643     // If we're asked to print, we should actually print at least a blank page.
2644     if (resultPageRects.isEmpty())
2645         resultPageRects.append(IntRect(0, 0, 1, 1));
2646
2647     send(Messages::WebPageProxy::ComputedPagesCallback(resultPageRects, resultTotalScaleFactorForPrinting, callbackID));
2648 }
2649
2650 #if USE(CG)
2651 static inline CGFloat roundCGFloat(CGFloat f)
2652 {
2653     if (sizeof(CGFloat) == sizeof(float))
2654         return roundf(static_cast<float>(f));
2655     return static_cast<CGFloat>(round(f));
2656 }
2657
2658 static void drawPDFPage(CGPDFDocumentRef pdfDocument, CFIndex pageIndex, CGContextRef context, CGFloat pageSetupScaleFactor, CGSize paperSize)
2659 {
2660     CGContextSaveGState(context);
2661
2662     CGContextScaleCTM(context, pageSetupScaleFactor, pageSetupScaleFactor);
2663
2664     CGPDFPageRef page = CGPDFDocumentGetPage(pdfDocument, pageIndex + 1);
2665     CGRect cropBox = CGPDFPageGetBoxRect(page, kCGPDFCropBox);
2666     if (CGRectIsEmpty(cropBox))
2667         cropBox = CGRectIntersection(cropBox, CGPDFPageGetBoxRect(page, kCGPDFMediaBox));
2668     else
2669         cropBox = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
2670
2671     bool shouldRotate = (paperSize.width < paperSize.height) != (cropBox.size.width < cropBox.size.height);
2672     if (shouldRotate)
2673         swap(cropBox.size.width, cropBox.size.height);
2674
2675     // Center.
2676     CGFloat widthDifference = paperSize.width / pageSetupScaleFactor - cropBox.size.width;
2677     CGFloat heightDifference = paperSize.height / pageSetupScaleFactor - cropBox.size.height;
2678     if (widthDifference || heightDifference)
2679         CGContextTranslateCTM(context, roundCGFloat(widthDifference / 2), roundCGFloat(heightDifference / 2));
2680
2681     if (shouldRotate) {
2682         CGContextRotateCTM(context, M_PI_2);
2683         CGContextTranslateCTM(context, 0, -cropBox.size.width);
2684     }
2685
2686     CGContextDrawPDFPage(context, page);
2687
2688     CGContextRestoreGState(context);
2689 }
2690 #endif // USE(CG)
2691
2692 #if PLATFORM(MAC) || PLATFORM(WIN)
2693 void WebPage::drawRectToPDF(uint64_t frameID, const PrintInfo& printInfo, const WebCore::IntRect& rect, uint64_t callbackID)
2694 {
2695     WebFrame* frame = WebProcess::shared().webFrame(frameID);
2696     Frame* coreFrame = frame ? frame->coreFrame() : 0;
2697
2698     RetainPtr<CFMutableDataRef> pdfPageData(AdoptCF, CFDataCreateMutable(0, 0));
2699
2700     if (coreFrame) {
2701         ASSERT(coreFrame->document()->printing()
2702 #if USE(CG)
2703             || pdfDocumentForPrintingFrame(coreFrame)
2704 #endif
2705         );
2706
2707 #if USE(CG)
2708         // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
2709         RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get()));
2710
2711         CGRect mediaBox = CGRectMake(0, 0, rect.width(), rect.height());
2712         RetainPtr<CGContextRef> context(AdoptCF, CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0));
2713         RetainPtr<CFDictionaryRef> pageInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
2714         CGPDFContextBeginPage(context.get(), pageInfo.get());
2715
2716         if (RetainPtr<CGPDFDocumentRef> pdfDocument = pdfDocumentForPrintingFrame(coreFrame)) {
2717             CFIndex pageCount = CGPDFDocumentGetNumberOfPages(pdfDocument.get());
2718             IntSize paperSize(ceilf(printInfo.availablePaperWidth), ceilf(printInfo.availablePaperHeight));
2719             IntRect pageRect(IntPoint(), paperSize);
2720             for (CFIndex i = 0; i < pageCount; ++i) {
2721                 if (pageRect.intersects(rect)) {
2722                     CGContextSaveGState(context.get());
2723
2724                     CGContextTranslateCTM(context.get(), pageRect.x() - rect.x(), pageRect.y() - rect.y());
2725                     drawPDFPage(pdfDocument.get(), i, context.get(), printInfo.pageSetupScaleFactor, paperSize);
2726
2727                     CGContextRestoreGState(context.get());
2728                 }
2729                 pageRect.move(0, pageRect.height());
2730             }
2731         } else {
2732             GraphicsContext ctx(context.get());
2733             ctx.scale(FloatSize(1, -1));
2734             ctx.translate(0, -rect.height());
2735             m_printContext->spoolRect(ctx, rect);
2736         }
2737
2738         CGPDFContextEndPage(context.get());
2739         CGPDFContextClose(context.get());
2740 #else
2741         UNUSED_PARAM(printInfo);
2742 #endif
2743     }
2744
2745     send(Messages::WebPageProxy::DataCallback(CoreIPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID));
2746 }
2747
2748 void WebPage::drawPagesToPDF(uint64_t frameID, const PrintInfo& printInfo, uint32_t first, uint32_t count, uint64_t callbackID)
2749 {
2750     WebFrame* frame = WebProcess::shared().webFrame(frameID);
2751     Frame* coreFrame = frame ? frame->coreFrame() : 0;
2752
2753     RetainPtr<CFMutableDataRef> pdfPageData(AdoptCF, CFDataCreateMutable(0, 0));
2754
2755     if (coreFrame) {
2756
2757         ASSERT(coreFrame->document()->printing()
2758 #if USE(CG)
2759             || pdfDocumentForPrintingFrame(coreFrame)
2760 #endif
2761         );
2762
2763 #if USE(CG)
2764         RetainPtr<CGPDFDocumentRef> pdfDocument = pdfDocumentForPrintingFrame(coreFrame);
2765
2766         // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data.
2767         RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get()));
2768
2769         CGRect mediaBox = m_printContext && m_printContext->pageCount() ? m_printContext->pageRect(0) : CGRectMake(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight);
2770         RetainPtr<CGContextRef> context(AdoptCF, CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0));
2771         size_t pageCount = m_printContext ? m_printContext->pageCount() : CGPDFDocumentGetNumberOfPages(pdfDocument.get());
2772         for (uint32_t page = first; page < first + count; ++page) {
2773             if (page >= pageCount)
2774                 break;
2775
2776             RetainPtr<CFDictionaryRef> pageInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
2777             CGPDFContextBeginPage(context.get(), pageInfo.get());
2778
2779             if (pdfDocument)
2780                 drawPDFPage(pdfDocument.get(), page, context.get(), printInfo.pageSetupScaleFactor, CGSizeMake(printInfo.availablePaperWidth, printInfo.availablePaperHeight));
2781             else {
2782                 GraphicsContext ctx(context.get());
2783                 ctx.scale(FloatSize(1, -1));
2784                 ctx.translate(0, -m_printContext->pageRect(page).height());
2785                 m_printContext->spoolPage(ctx, page, m_printContext->pageRect(page).width());
2786             }
2787
2788             CGPDFContextEndPage(context.get());
2789         }
2790         CGPDFContextClose(context.get());
2791 #endif
2792     }
2793
2794     send(Messages::WebPageProxy::DataCallback(CoreIPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID));
2795 }
2796 #endif
2797
2798 void WebPage::runModal()
2799 {
2800     if (m_isClosed)
2801         return;
2802     if (m_isRunningModal)
2803         return;
2804
2805     m_isRunningModal = true;
2806     send(Messages::WebPageProxy::RunModal());
2807     RunLoop::run();
2808     ASSERT(!m_isRunningModal);
2809 }
2810
2811 void WebPage::setMemoryCacheMessagesEnabled(bool memoryCacheMessagesEnabled)
2812 {
2813     m_page->setMemoryCacheClientCallsEnabled(memoryCacheMessagesEnabled);
2814 }
2815
2816 bool WebPage::canHandleRequest(const WebCore::ResourceRequest& request)
2817 {
2818     if (SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(request.url().protocol()))
2819         return true;
2820     return platformCanHandleRequest(request);
2821 }
2822
2823 #if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD)
2824 void WebPage::handleCorrectionPanelResult(const String& result)
2825 {
2826     Frame* frame = m_page->focusController()->focusedOrMainFrame();
2827     if (!frame)
2828         return;
2829     frame->editor()->handleCorrectionPanelResult(result);
2830 }
2831 #endif
2832
2833 void WebPage::simulateMouseDown(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time)
2834 {
2835     mouseEvent(WebMouseEvent(WebMouseEvent::MouseDown, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time));
2836 }
2837
2838 void WebPage::simulateMouseUp(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time)
2839 {
2840     mouseEvent(WebMouseEvent(WebMouseEvent::MouseUp, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time));
2841 }
2842
2843 void WebPage::simulateMouseMotion(WebCore::IntPoint position, double time)
2844 {
2845     mouseEvent(WebMouseEvent(WebMouseEvent::MouseMove, WebMouseEvent::NoButton, position, position, 0, 0, 0, 0, WebMouseEvent::Modifiers(), time));
2846 }
2847
2848 String WebPage::viewportConfigurationAsText(int deviceDPI, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight)
2849 {
2850     ViewportArguments arguments = mainFrame()->document()->viewportArguments();
2851     ViewportAttributes attrs = WebCore::computeViewportAttributes(arguments, /* default layout width for non-mobile pages */ 980, deviceWidth, deviceHeight, deviceDPI, IntSize(availableWidth, availableHeight));
2852     WebCore::restrictMinimumScaleFactorToViewportSize(attrs, IntSize(availableWidth, availableHeight));
2853     WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(attrs);
2854     return String::format("viewport size %dx%d scale %f with limits [%f, %f] and userScalable %f\n", attrs.layoutSize.width(), attrs.layoutSize.height(), attrs.initialScale, attrs.minimumScale, attrs.maximumScale, attrs.userScalable);
2855 }
2856
2857 void WebPage::setCompositionForTesting(const String& compositionString, uint64_t from, uint64_t length)
2858 {
2859     Frame* frame = m_page->focusController()->focusedOrMainFrame();
2860     if (!frame || !frame->editor()->canEdit())
2861         return;
2862
2863     Vector<CompositionUnderline> underlines;
2864     underlines.append(CompositionUnderline(0, compositionString.length(), Color(Color::black), false));
2865     frame->editor()->setComposition(compositionString, underlines, from, from + length);
2866 }
2867
2868 bool WebPage::hasCompositionForTesting()
2869 {
2870     Frame* frame = m_page->focusController()->focusedOrMainFrame();
2871     return frame && frame->editor()->hasComposition();
2872 }
2873
2874 void WebPage::confirmCompositionForTesting(const String& compositionString)
2875 {
2876     Frame* frame = m_page->focusController()->focusedOrMainFrame();
2877     if (!frame || !frame->editor()->canEdit())
2878         return;
2879
2880     if (compositionString.isNull())
2881         frame->editor()->confirmComposition();
2882     frame->editor()->confirmComposition(compositionString);
2883 }
2884
2885 Frame* WebPage::mainFrame() const
2886 {
2887     return m_page ? m_page->mainFrame() : 0;
2888 }
2889
2890 FrameView* WebPage::mainFrameView() const
2891 {
2892     if (Frame* frame = mainFrame())
2893         return frame->view();
2894     
2895     return 0;
2896 }
2897
2898 } // namespace WebKit