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