88bfbfcb87fd825f37ed0d01fe1203afbe1d96d0
[WebKit-https.git] / Source / WebCore / page / Page.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All Rights Reserved.
3  * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "Page.h"
22
23 #include "AlternativeTextClient.h"
24 #include "BackForwardController.h"
25 #include "BackForwardList.h"
26 #include "Chrome.h"
27 #include "ChromeClient.h"
28 #include "ClientRectList.h"
29 #include "ContextMenuClient.h"
30 #include "ContextMenuController.h"
31 #include "DOMWindow.h"
32 #include "DocumentMarkerController.h"
33 #include "DocumentStyleSheetCollection.h"
34 #include "DragController.h"
35 #include "EditorClient.h"
36 #include "Event.h"
37 #include "EventNames.h"
38 #include "ExceptionCode.h"
39 #include "FileSystem.h"
40 #include "FocusController.h"
41 #include "Frame.h"
42 #include "FrameLoader.h"
43 #include "FrameLoaderClient.h"
44 #include "FrameSelection.h"
45 #include "FrameTree.h"
46 #include "FrameView.h"
47 #include "HTMLElement.h"
48 #include "HistoryItem.h"
49 #include "InspectorController.h"
50 #include "InspectorInstrumentation.h"
51 #include "Logging.h"
52 #include "MediaCanStartListener.h"
53 #include "Navigator.h"
54 #include "NetworkStateNotifier.h"
55 #include "PageCache.h"
56 #include "PageGroup.h"
57 #include "PlugInClient.h"
58 #include "PluginData.h"
59 #include "PluginView.h"
60 #include "PointerLockController.h"
61 #include "ProgressTracker.h"
62 #include "RenderArena.h"
63 #include "RenderTheme.h"
64 #include "RenderView.h"
65 #include "RenderWidget.h"
66 #include "RuntimeEnabledFeatures.h"
67 #include "SchemeRegistry.h"
68 #include "ScrollingCoordinator.h"
69 #include "Settings.h"
70 #include "SharedBuffer.h"
71 #include "StorageArea.h"
72 #include "StorageNamespace.h"
73 #include "TextResourceDecoder.h"
74 #include "VisitedLinkState.h"
75 #include "VoidCallback.h"
76 #include "WebCoreMemoryInstrumentation.h"
77 #include "Widget.h"
78 #include <wtf/HashMap.h>
79 #include <wtf/RefCountedLeakCounter.h>
80 #include <wtf/StdLibExtras.h>
81 #include <wtf/text/Base64.h>
82 #include <wtf/text/StringHash.h>
83
84 namespace WebCore {
85
86 static HashSet<Page*>* allPages;
87
88 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, pageCounter, ("Page"));
89
90 static void networkStateChanged()
91 {
92     Vector<RefPtr<Frame> > frames;
93     
94     // Get all the frames of all the pages in all the page groups
95     HashSet<Page*>::iterator end = allPages->end();
96     for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) {
97         for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext())
98             frames.append(frame);
99         InspectorInstrumentation::networkStateChanged(*it);
100     }
101
102     AtomicString eventName = networkStateNotifier().onLine() ? eventNames().onlineEvent : eventNames().offlineEvent;
103     for (unsigned i = 0; i < frames.size(); i++)
104         frames[i]->document()->dispatchWindowEvent(Event::create(eventName, false, false));
105 }
106
107 float deviceScaleFactor(Frame* frame)
108 {
109     if (!frame)
110         return 1;
111     Page* page = frame->page();
112     if (!page)
113         return 1;
114     return page->deviceScaleFactor();
115 }
116
117 Page::Page(PageClients& pageClients)
118     : m_chrome(Chrome::create(this, pageClients.chromeClient))
119     , m_dragCaretController(DragCaretController::create())
120 #if ENABLE(DRAG_SUPPORT)
121     , m_dragController(DragController::create(this, pageClients.dragClient))
122 #endif
123     , m_focusController(FocusController::create(this))
124 #if ENABLE(CONTEXT_MENUS)
125     , m_contextMenuController(ContextMenuController::create(this, pageClients.contextMenuClient))
126 #endif
127 #if ENABLE(INSPECTOR)
128     , m_inspectorController(InspectorController::create(this, pageClients.inspectorClient))
129 #endif
130 #if ENABLE(POINTER_LOCK)
131     , m_pointerLockController(PointerLockController::create(this))
132 #endif
133     , m_settings(Settings::create(this))
134     , m_progress(ProgressTracker::create())
135     , m_backForwardController(BackForwardController::create(this, pageClients.backForwardClient))
136     , m_theme(RenderTheme::themeForPage(this))
137     , m_editorClient(pageClients.editorClient)
138     , m_plugInClient(pageClients.plugInClient)
139     , m_validationMessageClient(pageClients.validationMessageClient)
140     , m_subframeCount(0)
141     , m_openedByDOM(false)
142     , m_tabKeyCyclesThroughElements(true)
143     , m_defersLoading(false)
144     , m_defersLoadingCallCount(0)
145     , m_inLowQualityInterpolationMode(false)
146     , m_cookieEnabled(true)
147     , m_areMemoryCacheClientCallsEnabled(true)
148     , m_mediaVolume(1)
149     , m_pageScaleFactor(1)
150     , m_deviceScaleFactor(1)
151     , m_suppressScrollbarAnimations(false)
152     , m_didLoadUserStyleSheet(false)
153     , m_userStyleSheetModificationTime(0)
154     , m_group(0)
155     , m_debugger(0)
156     , m_customHTMLTokenizerTimeDelay(-1)
157     , m_customHTMLTokenizerChunkSize(-1)
158     , m_canStartMedia(true)
159     , m_viewMode(ViewModeWindowed)
160     , m_minimumTimerInterval(Settings::defaultMinDOMTimerInterval())
161     , m_timerAlignmentInterval(Settings::defaultDOMTimerAlignmentInterval())
162     , m_isEditable(false)
163     , m_isOnscreen(true)
164 #if ENABLE(PAGE_VISIBILITY_API)
165     , m_visibilityState(PageVisibilityStateVisible)
166 #endif
167     , m_displayID(0)
168     , m_layoutMilestones(0)
169     , m_isCountingRelevantRepaintedObjects(false)
170 #ifndef NDEBUG
171     , m_isPainting(false)
172 #endif
173     , m_alternativeTextClient(pageClients.alternativeTextClient)
174     , m_scriptedAnimationsSuspended(false)
175 {
176     ASSERT(m_editorClient);
177
178     if (!allPages) {
179         allPages = new HashSet<Page*>;
180         
181         networkStateNotifier().setNetworkStateChangedFunction(networkStateChanged);
182     }
183
184     ASSERT(!allPages->contains(this));
185     allPages->add(this);
186
187 #ifndef NDEBUG
188     pageCounter.increment();
189 #endif
190 }
191
192 Page::~Page()
193 {
194     m_mainFrame->setView(0);
195     setGroupName(String());
196     allPages->remove(this);
197     
198     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
199         frame->willDetachPage();
200         frame->detachFromPage();
201     }
202
203     m_editorClient->pageDestroyed();
204     if (m_plugInClient)
205         m_plugInClient->pageDestroyed();
206     if (m_alternativeTextClient)
207         m_alternativeTextClient->pageDestroyed();
208
209 #if ENABLE(INSPECTOR)
210     m_inspectorController->inspectedPageDestroyed();
211 #endif
212
213     if (m_scrollingCoordinator)
214         m_scrollingCoordinator->pageDestroyed();
215
216     backForward()->close();
217
218 #ifndef NDEBUG
219     pageCounter.decrement();
220 #endif
221
222 }
223
224 ArenaSize Page::renderTreeSize() const
225 {
226     ArenaSize total(0, 0);
227     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
228         if (!frame->document())
229             continue;
230         if (RenderArena* arena = frame->document()->renderArena()) {
231             total.treeSize += arena->totalRenderArenaSize();
232             total.allocated += arena->totalRenderArenaAllocatedBytes();
233         }
234     }
235     return total;
236 }
237
238 ViewportArguments Page::viewportArguments() const
239 {
240     return mainFrame() && mainFrame()->document() ? mainFrame()->document()->viewportArguments() : ViewportArguments();
241 }
242
243 ScrollingCoordinator* Page::scrollingCoordinator()
244 {
245     if (!m_scrollingCoordinator && m_settings->scrollingCoordinatorEnabled())
246         m_scrollingCoordinator = ScrollingCoordinator::create(this);
247
248     return m_scrollingCoordinator.get();
249 }
250
251 String Page::scrollingStateTreeAsText()
252 {
253     if (Document* document = m_mainFrame->document())
254         document->updateLayout();
255
256     if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
257         return scrollingCoordinator->scrollingStateTreeAsText();
258
259     return String();
260 }
261
262 String Page::mainThreadScrollingReasonsAsText()
263 {
264     if (Document* document = m_mainFrame->document())
265         document->updateLayout();
266
267     if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
268         return scrollingCoordinator->mainThreadScrollingReasonsAsText();
269
270     return String();
271 }
272
273 PassRefPtr<ClientRectList> Page::nonFastScrollableRects(const Frame* frame)
274 {
275     if (Document* document = m_mainFrame->document())
276         document->updateLayout();
277
278     Vector<IntRect> rects;
279     if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
280         rects = scrollingCoordinator->computeNonFastScrollableRegion(frame, IntPoint()).rects();
281
282     Vector<FloatQuad> quads(rects.size());
283     for (size_t i = 0; i < rects.size(); ++i)
284         quads[i] = FloatRect(rects[i]);
285     return ClientRectList::create(quads);
286 }
287
288 struct ViewModeInfo {
289     const char* name;
290     Page::ViewMode type;
291 };
292 static const int viewModeMapSize = 5;
293 static ViewModeInfo viewModeMap[viewModeMapSize] = {
294     {"windowed", Page::ViewModeWindowed},
295     {"floating", Page::ViewModeFloating},
296     {"fullscreen", Page::ViewModeFullscreen},
297     {"maximized", Page::ViewModeMaximized},
298     {"minimized", Page::ViewModeMinimized}
299 };
300
301 Page::ViewMode Page::stringToViewMode(const String& text)
302 {
303     for (int i = 0; i < viewModeMapSize; ++i) {
304         if (text == viewModeMap[i].name)
305             return viewModeMap[i].type;
306     }
307     return Page::ViewModeInvalid;
308 }
309
310 void Page::setViewMode(ViewMode viewMode)
311 {
312     if (viewMode == m_viewMode || viewMode == ViewModeInvalid)
313         return;
314
315     m_viewMode = viewMode;
316
317     if (!m_mainFrame)
318         return;
319
320     if (m_mainFrame->view())
321         m_mainFrame->view()->forceLayout();
322
323     if (m_mainFrame->document())
324         m_mainFrame->document()->styleResolverChanged(RecalcStyleImmediately);
325 }
326
327 void Page::setMainFrame(PassRefPtr<Frame> mainFrame)
328 {
329     ASSERT(!m_mainFrame); // Should only be called during initialization
330     m_mainFrame = mainFrame;
331 }
332
333 bool Page::openedByDOM() const
334 {
335     return m_openedByDOM;
336 }
337
338 void Page::setOpenedByDOM()
339 {
340     m_openedByDOM = true;
341 }
342
343 BackForwardList* Page::backForwardList() const
344 {
345     return m_backForwardController->client();
346 }
347
348 bool Page::goBack()
349 {
350     HistoryItem* item = backForward()->backItem();
351     
352     if (item) {
353         goToItem(item, FrameLoadTypeBack);
354         return true;
355     }
356     return false;
357 }
358
359 bool Page::goForward()
360 {
361     HistoryItem* item = backForward()->forwardItem();
362     
363     if (item) {
364         goToItem(item, FrameLoadTypeForward);
365         return true;
366     }
367     return false;
368 }
369
370 bool Page::canGoBackOrForward(int distance) const
371 {
372     if (distance == 0)
373         return true;
374     if (distance > 0 && distance <= backForward()->forwardCount())
375         return true;
376     if (distance < 0 && -distance <= backForward()->backCount())
377         return true;
378     return false;
379 }
380
381 void Page::goBackOrForward(int distance)
382 {
383     if (distance == 0)
384         return;
385
386     HistoryItem* item = backForward()->itemAtIndex(distance);
387     if (!item) {
388         if (distance > 0) {
389             if (int forwardCount = backForward()->forwardCount()) 
390                 item = backForward()->itemAtIndex(forwardCount);
391         } else {
392             if (int backCount = backForward()->backCount())
393                 item = backForward()->itemAtIndex(-backCount);
394         }
395     }
396
397     if (!item)
398         return;
399
400     goToItem(item, FrameLoadTypeIndexedBackForward);
401 }
402
403 void Page::goToItem(HistoryItem* item, FrameLoadType type)
404 {
405     // stopAllLoaders may end up running onload handlers, which could cause further history traversals that may lead to the passed in HistoryItem
406     // being deref()-ed. Make sure we can still use it with HistoryController::goToItem later.
407     RefPtr<HistoryItem> protector(item);
408
409     if (m_mainFrame->loader()->history()->shouldStopLoadingForHistoryItem(item))
410         m_mainFrame->loader()->stopAllLoaders();
411
412     m_mainFrame->loader()->history()->goToItem(item, type);
413 }
414
415 int Page::getHistoryLength()
416 {
417     return backForward()->backCount() + 1 + backForward()->forwardCount();
418 }
419
420 void Page::setGroupName(const String& name)
421 {
422     if (m_group && !m_group->name().isEmpty()) {
423         ASSERT(m_group != m_singlePageGroup.get());
424         ASSERT(!m_singlePageGroup);
425         m_group->removePage(this);
426     }
427
428     if (name.isEmpty())
429         m_group = m_singlePageGroup.get();
430     else {
431         m_singlePageGroup.clear();
432         m_group = PageGroup::pageGroup(name);
433         m_group->addPage(this);
434     }
435 }
436
437 const String& Page::groupName() const
438 {
439     DEFINE_STATIC_LOCAL(String, nullString, ());
440     // FIXME: Why not just return String()?
441     return m_group ? m_group->name() : nullString;
442 }
443
444 void Page::initGroup()
445 {
446     ASSERT(!m_singlePageGroup);
447     ASSERT(!m_group);
448     m_singlePageGroup = PageGroup::create(this);
449     m_group = m_singlePageGroup.get();
450 }
451
452 void Page::scheduleForcedStyleRecalcForAllPages()
453 {
454     if (!allPages)
455         return;
456     HashSet<Page*>::iterator end = allPages->end();
457     for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it)
458         for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext())
459             frame->document()->scheduleForcedStyleRecalc();
460 }
461
462 void Page::setNeedsRecalcStyleInAllFrames()
463 {
464     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
465         frame->document()->styleResolverChanged(DeferRecalcStyle);
466 }
467
468 void Page::refreshPlugins(bool reload)
469 {
470     if (!allPages)
471         return;
472
473     PluginData::refresh();
474
475     Vector<RefPtr<Frame> > framesNeedingReload;
476
477     HashSet<Page*>::iterator end = allPages->end();
478     for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) {
479         Page* page = *it;
480         
481         // Clear out the page's plug-in data.
482         if (page->m_pluginData)
483             page->m_pluginData = 0;
484
485         if (!reload)
486             continue;
487         
488         for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
489             if (frame->loader()->subframeLoader()->containsPlugins())
490                 framesNeedingReload.append(frame);
491         }
492     }
493
494     for (size_t i = 0; i < framesNeedingReload.size(); ++i)
495         framesNeedingReload[i]->loader()->reload();
496 }
497
498 PluginData* Page::pluginData() const
499 {
500     if (!mainFrame()->loader()->subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin))
501         return 0;
502     if (!m_pluginData)
503         m_pluginData = PluginData::create(this);
504     return m_pluginData.get();
505 }
506
507 inline MediaCanStartListener* Page::takeAnyMediaCanStartListener()
508 {
509     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
510         if (MediaCanStartListener* listener = frame->document()->takeAnyMediaCanStartListener())
511             return listener;
512     }
513     return 0;
514 }
515
516 void Page::setCanStartMedia(bool canStartMedia)
517 {
518     if (m_canStartMedia == canStartMedia)
519         return;
520
521     m_canStartMedia = canStartMedia;
522
523     while (m_canStartMedia) {
524         MediaCanStartListener* listener = takeAnyMediaCanStartListener();
525         if (!listener)
526             break;
527         listener->mediaCanStart();
528     }
529 }
530
531 static Frame* incrementFrame(Frame* curr, bool forward, bool wrapFlag)
532 {
533     return forward
534         ? curr->tree()->traverseNextWithWrap(wrapFlag)
535         : curr->tree()->traversePreviousWithWrap(wrapFlag);
536 }
537
538 bool Page::findString(const String& target, TextCaseSensitivity caseSensitivity, FindDirection direction, bool shouldWrap)
539 {
540     return findString(target, (caseSensitivity == TextCaseInsensitive ? CaseInsensitive : 0) | (direction == FindDirectionBackward ? Backwards : 0) | (shouldWrap ? WrapAround : 0));
541 }
542
543 bool Page::findString(const String& target, FindOptions options)
544 {
545     if (target.isEmpty() || !mainFrame())
546         return false;
547
548     bool shouldWrap = options & WrapAround;
549     Frame* frame = focusController()->focusedOrMainFrame();
550     Frame* startFrame = frame;
551     do {
552         if (frame->editor()->findString(target, (options & ~WrapAround) | StartInSelection)) {
553             if (frame != startFrame)
554                 startFrame->selection()->clear();
555             focusController()->setFocusedFrame(frame);
556             return true;
557         }
558         frame = incrementFrame(frame, !(options & Backwards), shouldWrap);
559     } while (frame && frame != startFrame);
560
561     // Search contents of startFrame, on the other side of the selection that we did earlier.
562     // We cheat a bit and just research with wrap on
563     if (shouldWrap && !startFrame->selection()->isNone()) {
564         bool found = startFrame->editor()->findString(target, options | WrapAround | StartInSelection);
565         focusController()->setFocusedFrame(frame);
566         return found;
567     }
568
569     return false;
570 }
571
572 PassRefPtr<Range> Page::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
573 {
574     if (target.isEmpty() || !mainFrame())
575         return 0;
576
577     if (referenceRange && referenceRange->ownerDocument()->page() != this)
578         return 0;
579
580     bool shouldWrap = options & WrapAround;
581     Frame* frame = referenceRange ? referenceRange->ownerDocument()->frame() : mainFrame();
582     Frame* startFrame = frame;
583     do {
584         if (RefPtr<Range> resultRange = frame->editor()->rangeOfString(target, frame == startFrame ? referenceRange : 0, options & ~WrapAround))
585             return resultRange.release();
586
587         frame = incrementFrame(frame, !(options & Backwards), shouldWrap);
588     } while (frame && frame != startFrame);
589
590     // Search contents of startFrame, on the other side of the reference range that we did earlier.
591     // We cheat a bit and just search again with wrap on.
592     if (shouldWrap && referenceRange) {
593         if (RefPtr<Range> resultRange = startFrame->editor()->rangeOfString(target, referenceRange, options | WrapAround | StartInSelection))
594             return resultRange.release();
595     }
596
597     return 0;
598 }
599
600 unsigned int Page::markAllMatchesForText(const String& target, TextCaseSensitivity caseSensitivity, bool shouldHighlight, unsigned limit)
601 {
602     return markAllMatchesForText(target, caseSensitivity == TextCaseInsensitive ? CaseInsensitive : 0, shouldHighlight, limit);
603 }
604
605 unsigned int Page::markAllMatchesForText(const String& target, FindOptions options, bool shouldHighlight, unsigned limit)
606 {
607     if (target.isEmpty() || !mainFrame())
608         return 0;
609
610     unsigned matches = 0;
611
612     Frame* frame = mainFrame();
613     do {
614         frame->editor()->setMarkedTextMatchesAreHighlighted(shouldHighlight);
615         matches += frame->editor()->countMatchesForText(target, options, limit ? (limit - matches) : 0, true);
616         frame = incrementFrame(frame, true, false);
617     } while (frame);
618
619     return matches;
620 }
621
622 void Page::unmarkAllTextMatches()
623 {
624     if (!mainFrame())
625         return;
626
627     Frame* frame = mainFrame();
628     do {
629         frame->document()->markers()->removeMarkers(DocumentMarker::TextMatch);
630         frame = incrementFrame(frame, true, false);
631     } while (frame);
632 }
633
634 const VisibleSelection& Page::selection() const
635 {
636     return focusController()->focusedOrMainFrame()->selection()->selection();
637 }
638
639 void Page::setDefersLoading(bool defers)
640 {
641     if (!m_settings->loadDeferringEnabled())
642         return;
643
644     if (m_settings->wantsBalancedSetDefersLoadingBehavior()) {
645         ASSERT(defers || m_defersLoadingCallCount);
646         if (defers && ++m_defersLoadingCallCount > 1)
647             return;
648         if (!defers && --m_defersLoadingCallCount)
649             return;
650     } else {
651         ASSERT(!m_defersLoadingCallCount);
652         if (defers == m_defersLoading)
653             return;
654     }
655
656     m_defersLoading = defers;
657     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
658         frame->loader()->setDefersLoading(defers);
659 }
660
661 void Page::clearUndoRedoOperations()
662 {
663     m_editorClient->clearUndoRedoOperations();
664 }
665
666 bool Page::inLowQualityImageInterpolationMode() const
667 {
668     return m_inLowQualityInterpolationMode;
669 }
670
671 void Page::setInLowQualityImageInterpolationMode(bool mode)
672 {
673     m_inLowQualityInterpolationMode = mode;
674 }
675
676 void Page::setMediaVolume(float volume)
677 {
678     if (volume < 0 || volume > 1)
679         return;
680
681     if (m_mediaVolume == volume)
682         return;
683
684     m_mediaVolume = volume;
685     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
686         frame->document()->mediaVolumeDidChange();
687     }
688 }
689
690 void Page::setPageScaleFactor(float scale, const IntPoint& origin)
691 {
692     Document* document = mainFrame()->document();
693     FrameView* view = document->view();
694
695     if (scale == m_pageScaleFactor) {
696         if (view && (view->scrollPosition() != origin || view->delegatesScrolling())) {
697             document->updateLayoutIgnorePendingStylesheets();
698             view->setScrollPosition(origin);
699         }
700         return;
701     }
702
703     m_pageScaleFactor = scale;
704
705     if (document->renderer())
706         document->renderer()->setNeedsLayout(true);
707
708     document->recalcStyle(Node::Force);
709
710     // Transform change on RenderView doesn't trigger repaint on non-composited contents.
711     mainFrame()->view()->invalidateRect(IntRect(LayoutRect::infiniteRect()));
712
713 #if USE(ACCELERATED_COMPOSITING)
714     mainFrame()->deviceOrPageScaleFactorChanged();
715 #endif
716
717     if (view && view->scrollPosition() != origin) {
718         if (document->renderer() && document->renderer()->needsLayout() && view->didFirstLayout())
719             view->layout();
720         view->setScrollPosition(origin);
721     }
722 }
723
724
725 void Page::setDeviceScaleFactor(float scaleFactor)
726 {
727     if (m_deviceScaleFactor == scaleFactor)
728         return;
729
730     m_deviceScaleFactor = scaleFactor;
731     setNeedsRecalcStyleInAllFrames();
732
733 #if USE(ACCELERATED_COMPOSITING)
734     if (mainFrame())
735         mainFrame()->deviceOrPageScaleFactorChanged();
736 #endif
737
738     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
739         frame->editor()->deviceScaleFactorChanged();
740
741     pageCache()->markPagesForFullStyleRecalc(this);
742 }
743
744 void Page::setShouldSuppressScrollbarAnimations(bool suppressAnimations)
745 {
746     if (suppressAnimations == m_suppressScrollbarAnimations)
747         return;
748
749     if (!suppressAnimations) {
750         // If animations are not going to be suppressed anymore, then there is nothing to do here but
751         // change the cached value.
752         m_suppressScrollbarAnimations = suppressAnimations;
753         return;
754     }
755
756     // On the other hand, if we are going to start suppressing animations, then we need to make sure we
757     // finish any current scroll animations first.
758     FrameView* view = mainFrame()->view();
759     if (!view)
760         return;
761
762     view->finishCurrentScrollAnimations();
763     
764     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
765         FrameView* frameView = frame->view();
766         if (!frameView)
767             continue;
768
769         const HashSet<ScrollableArea*>* scrollableAreas = frameView->scrollableAreas();
770         if (!scrollableAreas)
771             continue;
772
773         for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(), end = scrollableAreas->end(); it != end; ++it) {
774             ScrollableArea* scrollableArea = *it;
775             ASSERT(scrollableArea->scrollbarsCanBeActive());
776
777             scrollableArea->finishCurrentScrollAnimations();
778         }
779     }
780
781     m_suppressScrollbarAnimations = suppressAnimations;
782 }
783
784 void Page::setPagination(const Pagination& pagination)
785 {
786     if (m_pagination == pagination)
787         return;
788
789     m_pagination = pagination;
790
791     setNeedsRecalcStyleInAllFrames();
792     pageCache()->markPagesForFullStyleRecalc(this);
793 }
794
795 unsigned Page::pageCount() const
796 {
797     if (m_pagination.mode == Pagination::Unpaginated)
798         return 0;
799
800     FrameView* frameView = mainFrame()->view();
801     if (frameView->needsLayout())
802         frameView->layout();
803
804     RenderView* contentRenderer = mainFrame()->contentRenderer();
805     return contentRenderer ? contentRenderer->columnCount(contentRenderer->columnInfo()) : 0;
806 }
807
808 void Page::didMoveOnscreen()
809 {
810     m_isOnscreen = true;
811
812     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
813         if (FrameView* frameView = frame->view())
814             frameView->didMoveOnscreen();
815     }
816     
817     resumeScriptedAnimations();
818 }
819
820 void Page::willMoveOffscreen()
821 {
822     m_isOnscreen = false;
823
824     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
825         if (FrameView* frameView = frame->view())
826             frameView->willMoveOffscreen();
827     }
828     
829     suspendScriptedAnimations();
830 }
831
832 void Page::windowScreenDidChange(PlatformDisplayID displayID)
833 {
834     m_displayID = displayID;
835     
836     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
837         if (frame->document())
838             frame->document()->windowScreenDidChange(displayID);
839     }
840 }
841
842 void Page::suspendScriptedAnimations()
843 {
844     m_scriptedAnimationsSuspended = true;
845     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
846         if (frame->document())
847             frame->document()->suspendScriptedAnimationControllerCallbacks();
848     }
849 }
850
851 void Page::resumeScriptedAnimations()
852 {
853     m_scriptedAnimationsSuspended = false;
854     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
855         if (frame->document())
856             frame->document()->resumeScriptedAnimationControllerCallbacks();
857     }
858 }
859
860 void Page::userStyleSheetLocationChanged()
861 {
862     // FIXME: Eventually we will move to a model of just being handed the sheet
863     // text instead of loading the URL ourselves.
864     KURL url = m_settings->userStyleSheetLocation();
865     
866     // Allow any local file URL scheme to be loaded.
867     if (SchemeRegistry::shouldTreatURLSchemeAsLocal(url.protocol()))
868         m_userStyleSheetPath = url.fileSystemPath();
869     else
870         m_userStyleSheetPath = String();
871
872     m_didLoadUserStyleSheet = false;
873     m_userStyleSheet = String();
874     m_userStyleSheetModificationTime = 0;
875
876     // Data URLs with base64-encoded UTF-8 style sheets are common. We can process them
877     // synchronously and avoid using a loader. 
878     if (url.protocolIsData() && url.string().startsWith("data:text/css;charset=utf-8;base64,")) {
879         m_didLoadUserStyleSheet = true;
880
881         Vector<char> styleSheetAsUTF8;
882         if (base64Decode(decodeURLEscapeSequences(url.string().substring(35)), styleSheetAsUTF8, Base64IgnoreWhitespace))
883             m_userStyleSheet = String::fromUTF8(styleSheetAsUTF8.data(), styleSheetAsUTF8.size());
884     }
885
886     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
887         if (frame->document())
888             frame->document()->styleSheetCollection()->updatePageUserSheet();
889     }
890 }
891
892 const String& Page::userStyleSheet() const
893 {
894     if (m_userStyleSheetPath.isEmpty())
895         return m_userStyleSheet;
896
897     time_t modTime;
898     if (!getFileModificationTime(m_userStyleSheetPath, modTime)) {
899         // The stylesheet either doesn't exist, was just deleted, or is
900         // otherwise unreadable. If we've read the stylesheet before, we should
901         // throw away that data now as it no longer represents what's on disk.
902         m_userStyleSheet = String();
903         return m_userStyleSheet;
904     }
905
906     // If the stylesheet hasn't changed since the last time we read it, we can
907     // just return the old data.
908     if (m_didLoadUserStyleSheet && modTime <= m_userStyleSheetModificationTime)
909         return m_userStyleSheet;
910
911     m_didLoadUserStyleSheet = true;
912     m_userStyleSheet = String();
913     m_userStyleSheetModificationTime = modTime;
914
915     // FIXME: It would be better to load this asynchronously to avoid blocking
916     // the process, but we will first need to create an asynchronous loading
917     // mechanism that is not tied to a particular Frame. We will also have to
918     // determine what our behavior should be before the stylesheet is loaded
919     // and what should happen when it finishes loading, especially with respect
920     // to when the load event fires, when Document::close is called, and when
921     // layout/paint are allowed to happen.
922     RefPtr<SharedBuffer> data = SharedBuffer::createWithContentsOfFile(m_userStyleSheetPath);
923     if (!data)
924         return m_userStyleSheet;
925
926     RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/css");
927     m_userStyleSheet = decoder->decode(data->data(), data->size());
928     m_userStyleSheet.append(decoder->flush());
929
930     return m_userStyleSheet;
931 }
932
933 void Page::removeAllVisitedLinks()
934 {
935     if (!allPages)
936         return;
937     HashSet<PageGroup*> groups;
938     HashSet<Page*>::iterator pagesEnd = allPages->end();
939     for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
940         if (PageGroup* group = (*it)->groupPtr())
941             groups.add(group);
942     }
943     HashSet<PageGroup*>::iterator groupsEnd = groups.end();
944     for (HashSet<PageGroup*>::iterator it = groups.begin(); it != groupsEnd; ++it)
945         (*it)->removeVisitedLinks();
946 }
947
948 void Page::allVisitedStateChanged(PageGroup* group)
949 {
950     ASSERT(group);
951     if (!allPages)
952         return;
953
954     HashSet<Page*>::iterator pagesEnd = allPages->end();
955     for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
956         Page* page = *it;
957         if (page->m_group != group)
958             continue;
959         for (Frame* frame = page->m_mainFrame.get(); frame; frame = frame->tree()->traverseNext())
960             frame->document()->visitedLinkState()->invalidateStyleForAllLinks();
961     }
962 }
963
964 void Page::visitedStateChanged(PageGroup* group, LinkHash linkHash)
965 {
966     ASSERT(group);
967     if (!allPages)
968         return;
969
970     HashSet<Page*>::iterator pagesEnd = allPages->end();
971     for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
972         Page* page = *it;
973         if (page->m_group != group)
974             continue;
975         for (Frame* frame = page->m_mainFrame.get(); frame; frame = frame->tree()->traverseNext())
976             frame->document()->visitedLinkState()->invalidateStyleForLink(linkHash);
977     }
978 }
979
980 void Page::setDebuggerForAllPages(JSC::Debugger* debugger)
981 {
982     ASSERT(allPages);
983
984     HashSet<Page*>::iterator end = allPages->end();
985     for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it)
986         (*it)->setDebugger(debugger);
987 }
988
989 void Page::setDebugger(JSC::Debugger* debugger)
990 {
991     if (m_debugger == debugger)
992         return;
993
994     m_debugger = debugger;
995
996     for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree()->traverseNext())
997         frame->script()->attachDebugger(m_debugger);
998 }
999
1000 StorageNamespace* Page::sessionStorage(bool optionalCreate)
1001 {
1002     if (!m_sessionStorage && optionalCreate)
1003         m_sessionStorage = StorageNamespace::sessionStorageNamespace(this, m_settings->sessionStorageQuota());
1004
1005     return m_sessionStorage.get();
1006 }
1007
1008 void Page::setSessionStorage(PassRefPtr<StorageNamespace> newStorage)
1009 {
1010     m_sessionStorage = newStorage;
1011 }
1012
1013 void Page::setCustomHTMLTokenizerTimeDelay(double customHTMLTokenizerTimeDelay)
1014 {
1015     if (customHTMLTokenizerTimeDelay < 0) {
1016         m_customHTMLTokenizerTimeDelay = -1;
1017         return;
1018     }
1019     m_customHTMLTokenizerTimeDelay = customHTMLTokenizerTimeDelay;
1020 }
1021
1022 void Page::setCustomHTMLTokenizerChunkSize(int customHTMLTokenizerChunkSize)
1023 {
1024     if (customHTMLTokenizerChunkSize < 0) {
1025         m_customHTMLTokenizerChunkSize = -1;
1026         return;
1027     }
1028     m_customHTMLTokenizerChunkSize = customHTMLTokenizerChunkSize;
1029 }
1030
1031 void Page::setMemoryCacheClientCallsEnabled(bool enabled)
1032 {
1033     if (m_areMemoryCacheClientCallsEnabled == enabled)
1034         return;
1035
1036     m_areMemoryCacheClientCallsEnabled = enabled;
1037     if (!enabled)
1038         return;
1039
1040     for (RefPtr<Frame> frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
1041         frame->loader()->tellClientAboutPastMemoryCacheLoads();
1042 }
1043
1044 void Page::setMinimumTimerInterval(double minimumTimerInterval)
1045 {
1046     double oldTimerInterval = m_minimumTimerInterval;
1047     m_minimumTimerInterval = minimumTimerInterval;
1048     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNextWithWrap(false)) {
1049         if (frame->document())
1050             frame->document()->adjustMinimumTimerInterval(oldTimerInterval);
1051     }
1052 }
1053
1054 double Page::minimumTimerInterval() const
1055 {
1056     return m_minimumTimerInterval;
1057 }
1058
1059 void Page::setTimerAlignmentInterval(double interval)
1060 {
1061     if (interval == m_timerAlignmentInterval)
1062         return;
1063
1064     m_timerAlignmentInterval = interval;
1065     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNextWithWrap(false)) {
1066         if (frame->document())
1067             frame->document()->didChangeTimerAlignmentInterval();
1068     }
1069 }
1070
1071 double Page::timerAlignmentInterval() const
1072 {
1073     return m_timerAlignmentInterval;
1074 }
1075
1076 void Page::dnsPrefetchingStateChanged()
1077 {
1078     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
1079         frame->document()->initDNSPrefetch();
1080 }
1081
1082 void Page::collectPluginViews(Vector<RefPtr<PluginViewBase>, 32>& pluginViewBases)
1083 {
1084     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1085         FrameView* view = frame->view();
1086         if (!view)
1087             return;
1088
1089         const HashSet<RefPtr<Widget> >* children = view->children();
1090         ASSERT(children);
1091
1092         HashSet<RefPtr<Widget> >::const_iterator end = children->end();
1093         for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
1094             Widget* widget = (*it).get();
1095             if (widget->isPluginViewBase())
1096                 pluginViewBases.append(static_cast<PluginViewBase*>(widget));
1097         }
1098     }
1099 }
1100
1101 void Page::storageBlockingStateChanged()
1102 {
1103     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
1104         frame->document()->storageBlockingStateDidChange();
1105
1106     // Collect the PluginViews in to a vector to ensure that action the plug-in takes
1107     // from below storageBlockingStateChanged does not affect their lifetime.
1108     Vector<RefPtr<PluginViewBase>, 32> pluginViewBases;
1109     collectPluginViews(pluginViewBases);
1110
1111     for (size_t i = 0; i < pluginViewBases.size(); ++i)
1112         pluginViewBases[i]->storageBlockingStateChanged();
1113 }
1114
1115 void Page::privateBrowsingStateChanged()
1116 {
1117     bool privateBrowsingEnabled = m_settings->privateBrowsingEnabled();
1118
1119     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
1120         frame->document()->privateBrowsingStateDidChange();
1121
1122     // Collect the PluginViews in to a vector to ensure that action the plug-in takes
1123     // from below privateBrowsingStateChanged does not affect their lifetime.
1124     Vector<RefPtr<PluginViewBase>, 32> pluginViewBases;
1125     collectPluginViews(pluginViewBases);
1126
1127     for (size_t i = 0; i < pluginViewBases.size(); ++i)
1128         pluginViewBases[i]->privateBrowsingStateChanged(privateBrowsingEnabled);
1129 }
1130
1131 #if !ASSERT_DISABLED
1132 void Page::checkSubframeCountConsistency() const
1133 {
1134     ASSERT(m_subframeCount >= 0);
1135
1136     int subframeCount = 0;
1137     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
1138         ++subframeCount;
1139
1140     ASSERT(m_subframeCount + 1 == subframeCount);
1141 }
1142 #endif
1143
1144 #if ENABLE(PAGE_VISIBILITY_API) || ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
1145 void Page::setVisibilityState(PageVisibilityState visibilityState, bool isInitialState)
1146 {
1147 #if ENABLE(PAGE_VISIBILITY_API)
1148     if (m_visibilityState == visibilityState)
1149         return;
1150     m_visibilityState = visibilityState;
1151
1152     if (!isInitialState && m_mainFrame)
1153         m_mainFrame->dispatchVisibilityStateChangeEvent();
1154 #endif
1155
1156 #if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
1157     if (visibilityState == WebCore::PageVisibilityStateHidden)
1158         setTimerAlignmentInterval(Settings::hiddenPageDOMTimerAlignmentInterval());
1159     else
1160         setTimerAlignmentInterval(Settings::defaultDOMTimerAlignmentInterval());
1161 #if !ENABLE(PAGE_VISIBILITY_API)
1162     UNUSED_PARAM(isInitialState);
1163 #endif
1164 #endif
1165 }
1166 #endif // ENABLE(PAGE_VISIBILITY_API) || ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
1167
1168 #if ENABLE(PAGE_VISIBILITY_API)
1169 PageVisibilityState Page::visibilityState() const
1170 {
1171     return m_visibilityState;
1172 }
1173 #endif
1174
1175 void Page::addLayoutMilestones(LayoutMilestones milestones)
1176 {
1177     // In the future, we may want a function that replaces m_layoutMilestones instead of just adding to it.
1178     m_layoutMilestones |= milestones;
1179 }
1180
1181 // These are magical constants that might be tweaked over time.
1182 static double gMinimumPaintedAreaRatio = 0.1;
1183 static double gMaximumUnpaintedAreaRatio = 0.04;
1184
1185 bool Page::isCountingRelevantRepaintedObjects() const
1186 {
1187     return m_isCountingRelevantRepaintedObjects && (m_layoutMilestones & DidHitRelevantRepaintedObjectsAreaThreshold);
1188 }
1189
1190 void Page::startCountingRelevantRepaintedObjects()
1191 {
1192     // Reset everything in case we didn't hit the threshold last time.
1193     resetRelevantPaintedObjectCounter();
1194
1195     m_isCountingRelevantRepaintedObjects = true;
1196 }
1197
1198 void Page::resetRelevantPaintedObjectCounter()
1199 {
1200     m_isCountingRelevantRepaintedObjects = false;
1201     m_relevantUnpaintedRenderObjects.clear();
1202     m_relevantPaintedRegion = Region();
1203     m_relevantUnpaintedRegion = Region();
1204 }
1205
1206 static LayoutRect relevantViewRect(RenderView* view)
1207 {
1208     // DidHitRelevantRepaintedObjectsAreaThreshold is a LayoutMilestone intended to indicate that
1209     // a certain relevant amount of content has been drawn to the screen. This is the rect that
1210     // has been determined to be relevant in the context of this goal. We may choose to tweak
1211     // the rect over time, much like we may choose to tweak gMinimumPaintedAreaRatio and
1212     // gMaximumUnpaintedAreaRatio. But this seems to work well right now.
1213     LayoutRect relevantViewRect = LayoutRect(0, 0, 980, 1300);
1214
1215     LayoutRect viewRect = view->viewRect();
1216     // If the viewRect is wider than the relevantViewRect, center the relevantViewRect.
1217     if (viewRect.width() > relevantViewRect.width())
1218         relevantViewRect.setX((viewRect.width() - relevantViewRect.width()) / 2);
1219
1220     return relevantViewRect;
1221 }
1222
1223 void Page::addRelevantRepaintedObject(RenderObject* object, const LayoutRect& objectPaintRect)
1224 {
1225     if (!isCountingRelevantRepaintedObjects())
1226         return;
1227
1228     // Objects inside sub-frames are not considered to be relevant.
1229     if (object->document()->frame() != mainFrame())
1230         return;
1231
1232     RenderView* view = object->view();
1233     if (!view)
1234         return;
1235
1236     LayoutRect relevantRect = relevantViewRect(view);
1237
1238     // The objects are only relevant if they are being painted within the viewRect().
1239     if (!objectPaintRect.intersects(pixelSnappedIntRect(relevantRect)))
1240         return;
1241
1242     IntRect snappedPaintRect = pixelSnappedIntRect(objectPaintRect);
1243
1244     // If this object was previously counted as an unpainted object, remove it from that HashSet
1245     // and corresponding Region. FIXME: This doesn't do the right thing if the objects overlap.
1246     HashSet<RenderObject*>::iterator it = m_relevantUnpaintedRenderObjects.find(object);
1247     if (it != m_relevantUnpaintedRenderObjects.end()) {
1248         m_relevantUnpaintedRenderObjects.remove(it);
1249         m_relevantUnpaintedRegion.subtract(snappedPaintRect);
1250     }
1251
1252     m_relevantPaintedRegion.unite(snappedPaintRect);
1253     
1254     float viewArea = relevantRect.width() * relevantRect.height();
1255     float ratioOfViewThatIsPainted = m_relevantPaintedRegion.totalArea() / viewArea;
1256     float ratioOfViewThatIsUnpainted = m_relevantUnpaintedRegion.totalArea() / viewArea;
1257
1258     if (ratioOfViewThatIsPainted > gMinimumPaintedAreaRatio && ratioOfViewThatIsUnpainted < gMaximumUnpaintedAreaRatio) {
1259         m_isCountingRelevantRepaintedObjects = false;
1260         resetRelevantPaintedObjectCounter();
1261         if (Frame* frame = mainFrame())
1262             frame->loader()->didLayout(DidHitRelevantRepaintedObjectsAreaThreshold);
1263     }
1264 }
1265
1266 void Page::addRelevantUnpaintedObject(RenderObject* object, const LayoutRect& objectPaintRect)
1267 {
1268     if (!isCountingRelevantRepaintedObjects())
1269         return;
1270
1271     // The objects are only relevant if they are being painted within the relevantViewRect().
1272     if (RenderView* view = object->view()) {
1273         if (!objectPaintRect.intersects(pixelSnappedIntRect(relevantViewRect(view))))
1274             return;
1275     }
1276
1277     m_relevantUnpaintedRenderObjects.add(object);
1278     m_relevantUnpaintedRegion.unite(pixelSnappedIntRect(objectPaintRect));
1279 }
1280
1281 void Page::suspendActiveDOMObjectsAndAnimations()
1282 {
1283     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
1284         frame->suspendActiveDOMObjectsAndAnimations();
1285 }
1286
1287 void Page::resumeActiveDOMObjectsAndAnimations()
1288 {
1289     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
1290         frame->resumeActiveDOMObjectsAndAnimations();
1291 }
1292
1293 bool Page::hasSeenAnyPlugin() const
1294 {
1295     return !m_seenPlugins.isEmpty();
1296 }
1297
1298 bool Page::hasSeenPlugin(const String& serviceType) const
1299 {
1300     return m_seenPlugins.contains(serviceType);
1301 }
1302
1303 void Page::sawPlugin(const String& serviceType)
1304 {
1305     m_seenPlugins.add(serviceType);
1306 }
1307
1308 void Page::resetSeenPlugins()
1309 {
1310     m_seenPlugins.clear();
1311 }
1312
1313 bool Page::hasSeenAnyMediaEngine() const
1314 {
1315     return !m_seenMediaEngines.isEmpty();
1316 }
1317
1318 bool Page::hasSeenMediaEngine(const String& engineDescription) const
1319 {
1320     return m_seenMediaEngines.contains(engineDescription);
1321 }
1322
1323 void Page::sawMediaEngine(const String& engineDescription)
1324 {
1325     m_seenMediaEngines.add(engineDescription);
1326 }
1327
1328 void Page::resetSeenMediaEngines()
1329 {
1330     m_seenMediaEngines.clear();
1331 }
1332
1333 void Page::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
1334 {
1335     MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::Page);
1336     info.addMember(m_chrome);
1337     info.addMember(m_dragCaretController);
1338
1339 #if ENABLE(DRAG_SUPPORT)
1340     info.addMember(m_dragController);
1341 #endif
1342     info.addMember(m_focusController);
1343 #if ENABLE(CONTEXT_MENUS)
1344     info.addMember(m_contextMenuController);
1345 #endif
1346 #if ENABLE(INSPECTOR)
1347     info.addMember(m_inspectorController);
1348 #endif
1349 #if ENABLE(POINTER_LOCK)
1350     info.addMember(m_pointerLockController);
1351 #endif
1352     info.addMember(m_scrollingCoordinator);
1353     info.addMember(m_settings);
1354     info.addMember(m_progress);
1355     info.addMember(m_backForwardController);
1356     info.addMember(m_mainFrame);
1357     info.addMember(m_pluginData);
1358     info.addMember(m_theme);
1359     info.addMember(m_featureObserver);
1360     info.addMember(m_groupName);
1361     info.addMember(m_pagination);
1362     info.addMember(m_userStyleSheetPath);
1363     info.addMember(m_userStyleSheet);
1364     info.addMember(m_singlePageGroup);
1365     info.addMember(m_group);
1366     info.addMember(m_sessionStorage);
1367     info.addMember(m_relevantUnpaintedRenderObjects);
1368     info.addMember(m_relevantPaintedRegion);
1369     info.addMember(m_relevantUnpaintedRegion);
1370     info.addMember(m_seenPlugins);
1371     info.addMember(m_seenMediaEngines);
1372
1373     info.ignoreMember(m_debugger);
1374     info.ignoreMember(m_alternativeTextClient);
1375     info.ignoreMember(m_editorClient);
1376     info.ignoreMember(m_validationMessageClient);
1377 }
1378
1379 Page::PageClients::PageClients()
1380     : alternativeTextClient(0)
1381     , chromeClient(0)
1382 #if ENABLE(CONTEXT_MENUS)
1383     , contextMenuClient(0)
1384 #endif
1385     , editorClient(0)
1386     , dragClient(0)
1387     , inspectorClient(0)
1388     , plugInClient(0)
1389     , validationMessageClient(0)
1390 {
1391 }
1392
1393 Page::PageClients::~PageClients()
1394 {
1395 }
1396
1397 } // namespace WebCore