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