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