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