1a4b76b9ca4f2adc2e8b74d815bb825e90d57247
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / page / Page.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 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 "core/page/Page.h"
22
23 #include "core/dom/ClientRectList.h"
24 #include "core/dom/DocumentMarkerController.h"
25 #include "core/dom/StyleEngine.h"
26 #include "core/dom/VisitedLinkState.h"
27 #include "core/editing/Caret.h"
28 #include "core/editing/UndoStack.h"
29 #include "core/events/Event.h"
30 #include "core/fetch/ResourceFetcher.h"
31 #include "core/frame/DOMTimer.h"
32 #include "core/frame/LocalDOMWindow.h"
33 #include "core/frame/EventHandlerRegistry.h"
34 #include "core/frame/FrameHost.h"
35 #include "core/frame/FrameView.h"
36 #include "core/frame/LocalFrame.h"
37 #include "core/frame/RemoteFrame.h"
38 #include "core/frame/RemoteFrameView.h"
39 #include "core/frame/Settings.h"
40 #include "core/inspector/InspectorController.h"
41 #include "core/inspector/InspectorInstrumentation.h"
42 #include "core/loader/FrameLoader.h"
43 #include "core/loader/HistoryItem.h"
44 #include "core/page/AutoscrollController.h"
45 #include "core/page/Chrome.h"
46 #include "core/page/ChromeClient.h"
47 #include "core/page/ContextMenuController.h"
48 #include "core/page/DragController.h"
49 #include "core/page/FocusController.h"
50 #include "core/page/FrameTree.h"
51 #include "core/page/PageLifecycleNotifier.h"
52 #include "core/page/PointerLockController.h"
53 #include "core/page/StorageClient.h"
54 #include "core/page/ValidationMessageClient.h"
55 #include "core/page/scrolling/ScrollingCoordinator.h"
56 #include "core/rendering/FastTextAutosizer.h"
57 #include "core/rendering/RenderView.h"
58 #include "core/rendering/TextAutosizer.h"
59 #include "core/storage/StorageNamespace.h"
60 #include "platform/plugins/PluginData.h"
61 #include "wtf/HashMap.h"
62 #include "wtf/RefCountedLeakCounter.h"
63 #include "wtf/StdLibExtras.h"
64 #include "wtf/text/Base64.h"
65
66 namespace WebCore {
67
68 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, pageCounter, ("Page"));
69
70 // static
71 HashSet<Page*>& Page::allPages()
72 {
73     DEFINE_STATIC_LOCAL(HashSet<Page*>, allPages, ());
74     return allPages;
75 }
76
77 // static
78 HashSet<Page*>& Page::ordinaryPages()
79 {
80     DEFINE_STATIC_LOCAL(HashSet<Page*>, ordinaryPages, ());
81     return ordinaryPages;
82 }
83
84
85 void Page::networkStateChanged(bool online)
86 {
87     Vector<RefPtr<LocalFrame> > frames;
88
89     // Get all the frames of all the pages in all the page groups
90     HashSet<Page*>::iterator end = allPages().end();
91     for (HashSet<Page*>::iterator it = allPages().begin(); it != end; ++it) {
92         for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree().traverseNext()) {
93             // FIXME: There is currently no way to dispatch events to out-of-process frames.
94             if (frame->isLocalFrame())
95                 frames.append(toLocalFrame(frame));
96         }
97         InspectorInstrumentation::networkStateChanged(*it, online);
98     }
99
100     AtomicString eventName = online ? EventTypeNames::online : EventTypeNames::offline;
101     for (unsigned i = 0; i < frames.size(); i++)
102         frames[i]->domWindow()->dispatchEvent(Event::create(eventName));
103 }
104
105 float deviceScaleFactor(LocalFrame* frame)
106 {
107     if (!frame)
108         return 1;
109     Page* page = frame->page();
110     if (!page)
111         return 1;
112     return page->deviceScaleFactor();
113 }
114
115 Page::Page(PageClients& pageClients)
116     : SettingsDelegate(Settings::create())
117     , m_animator(this)
118     , m_autoscrollController(AutoscrollController::create(*this))
119     , m_chrome(Chrome::create(this, pageClients.chromeClient))
120     , m_dragCaretController(DragCaretController::create())
121     , m_dragController(DragController::create(this, pageClients.dragClient))
122     , m_focusController(FocusController::create(this))
123     , m_contextMenuController(ContextMenuController::create(this, pageClients.contextMenuClient))
124     , m_inspectorController(InspectorController::create(this, pageClients.inspectorClient))
125     , m_pointerLockController(PointerLockController::create(this))
126     , m_undoStack(UndoStack::create())
127     , m_mainFrame(0)
128     , m_backForwardClient(pageClients.backForwardClient)
129     , m_editorClient(pageClients.editorClient)
130     , m_spellCheckerClient(pageClients.spellCheckerClient)
131     , m_storageClient(pageClients.storageClient)
132     , m_subframeCount(0)
133     , m_openedByDOM(false)
134     , m_tabKeyCyclesThroughElements(true)
135     , m_defersLoading(false)
136     , m_deviceScaleFactor(1)
137     , m_timerAlignmentInterval(DOMTimer::visiblePageAlignmentInterval())
138     , m_visibilityState(PageVisibilityStateVisible)
139     , m_isCursorVisible(true)
140 #ifndef NDEBUG
141     , m_isPainting(false)
142 #endif
143     , m_frameHost(FrameHost::create(*this))
144 {
145     ASSERT(m_editorClient);
146
147     ASSERT(!allPages().contains(this));
148     allPages().add(this);
149
150 #ifndef NDEBUG
151     pageCounter.increment();
152 #endif
153 }
154
155 Page::~Page()
156 {
157     // willBeDestroyed() must be called before Page destruction.
158     ASSERT(!m_mainFrame);
159 }
160
161 void Page::makeOrdinary()
162 {
163     ASSERT(!ordinaryPages().contains(this));
164     ordinaryPages().add(this);
165 }
166
167 ViewportDescription Page::viewportDescription() const
168 {
169     return mainFrame() && mainFrame()->isLocalFrame() && deprecatedLocalMainFrame()->document() ? deprecatedLocalMainFrame()->document()->viewportDescription() : ViewportDescription();
170 }
171
172 ScrollingCoordinator* Page::scrollingCoordinator()
173 {
174     if (!m_scrollingCoordinator && m_settings->acceleratedCompositingEnabled())
175         m_scrollingCoordinator = ScrollingCoordinator::create(this);
176
177     return m_scrollingCoordinator.get();
178 }
179
180 String Page::mainThreadScrollingReasonsAsText()
181 {
182     if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
183         return scrollingCoordinator->mainThreadScrollingReasonsAsText();
184
185     return String();
186 }
187
188 PassRefPtrWillBeRawPtr<ClientRectList> Page::nonFastScrollableRects(const LocalFrame* frame)
189 {
190     if (m_mainFrame->isLocalFrame() && deprecatedLocalMainFrame()->document())
191         deprecatedLocalMainFrame()->document()->updateLayout();
192
193     Vector<IntRect> rects;
194     if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
195         rects = scrollingCoordinator->computeShouldHandleScrollGestureOnMainThreadRegion(frame, IntPoint()).rects();
196
197     Vector<FloatQuad> quads(rects.size());
198     for (size_t i = 0; i < rects.size(); ++i)
199         quads[i] = FloatRect(rects[i]);
200     return ClientRectList::create(quads);
201 }
202
203 void Page::setMainFrame(Frame* mainFrame)
204 {
205     ASSERT(!m_mainFrame); // Should only be called during initialization
206     m_mainFrame = mainFrame;
207 }
208
209 void Page::documentDetached(Document* document)
210 {
211     m_multisamplingChangedObservers.clear();
212     m_pointerLockController->documentDetached(document);
213     m_contextMenuController->documentDetached(document);
214     if (m_validationMessageClient)
215         m_validationMessageClient->documentDetached(*document);
216     m_frameHost->eventHandlerRegistry().documentDetached(*document);
217 }
218
219 bool Page::openedByDOM() const
220 {
221     return m_openedByDOM;
222 }
223
224 void Page::setOpenedByDOM()
225 {
226     m_openedByDOM = true;
227 }
228
229 void Page::scheduleForcedStyleRecalcForAllPages()
230 {
231     HashSet<Page*>::iterator end = allPages().end();
232     for (HashSet<Page*>::iterator it = allPages().begin(); it != end; ++it)
233         for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree().traverseNext()) {
234             if (frame->isLocalFrame())
235                 toLocalFrame(frame)->document()->setNeedsStyleRecalc(SubtreeStyleChange);
236         }
237 }
238
239 void Page::setNeedsRecalcStyleInAllFrames()
240 {
241     for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
242         if (frame->isLocalFrame())
243             toLocalFrame(frame)->document()->styleResolverChanged();
244     }
245 }
246
247 void Page::setNeedsLayoutInAllFrames()
248 {
249     for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
250         if (!frame->isLocalFrame())
251             continue;
252         if (FrameView* view = toLocalFrame(frame)->view()) {
253             view->setNeedsLayout();
254             view->scheduleRelayout();
255         }
256     }
257 }
258
259 void Page::refreshPlugins(bool reload)
260 {
261     if (allPages().isEmpty())
262         return;
263
264     PluginData::refresh();
265
266     Vector<RefPtr<LocalFrame> > framesNeedingReload;
267
268     HashSet<Page*>::iterator end = allPages().end();
269     for (HashSet<Page*>::iterator it = allPages().begin(); it != end; ++it) {
270         Page* page = *it;
271
272         // Clear out the page's plug-in data.
273         if (page->m_pluginData)
274             page->m_pluginData = nullptr;
275
276         if (!reload)
277             continue;
278
279         for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree().traverseNext()) {
280             if (frame->isLocalFrame() && toLocalFrame(frame)->document()->containsPlugins())
281                 framesNeedingReload.append(toLocalFrame(frame));
282         }
283     }
284
285     for (size_t i = 0; i < framesNeedingReload.size(); ++i)
286         framesNeedingReload[i]->loader().reload();
287 }
288
289 PluginData* Page::pluginData() const
290 {
291     if (!deprecatedLocalMainFrame()->loader().allowPlugins(NotAboutToInstantiatePlugin))
292         return 0;
293     if (!m_pluginData)
294         m_pluginData = PluginData::create(this);
295     return m_pluginData.get();
296 }
297
298 static Frame* incrementFrame(Frame* curr, bool forward, bool wrapFlag)
299 {
300     return forward
301         ? curr->tree().traverseNextWithWrap(wrapFlag)
302         : curr->tree().traversePreviousWithWrap(wrapFlag);
303 }
304
305 void Page::unmarkAllTextMatches()
306 {
307     if (!mainFrame())
308         return;
309
310     Frame* frame = mainFrame();
311     do {
312         if (frame->isLocalFrame())
313             toLocalFrame(frame)->document()->markers().removeMarkers(DocumentMarker::TextMatch);
314         frame = incrementFrame(frame, true, false);
315     } while (frame);
316 }
317
318 void Page::setValidationMessageClient(PassOwnPtrWillBeRawPtr<ValidationMessageClient> client)
319 {
320     m_validationMessageClient = client;
321 }
322
323 void Page::setDefersLoading(bool defers)
324 {
325     if (defers == m_defersLoading)
326         return;
327
328     m_defersLoading = defers;
329     for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
330         if (frame->isLocalFrame())
331             toLocalFrame(frame)->loader().setDefersLoading(defers);
332     }
333 }
334
335 void Page::setPageScaleFactor(float scale, const IntPoint& origin)
336 {
337     if (!mainFrame()->isLocalFrame())
338         return;
339
340     FrameView* view = deprecatedLocalMainFrame()->view();
341     PinchViewport& viewport = frameHost().pinchViewport();
342
343     if (scale != viewport.scale()) {
344         viewport.setScale(scale);
345
346         if (view && !settings().pinchVirtualViewportEnabled())
347             view->setVisibleContentScaleFactor(scale);
348
349         deprecatedLocalMainFrame()->deviceOrPageScaleFactorChanged();
350         m_chrome->client().deviceOrPageScaleFactorChanged();
351
352         // FIXME: In virtual-viewport pinch mode, scale doesn't change the fixed-pos viewport;
353         // remove once it's the only pinch mode in town.
354         if (view)
355             view->viewportConstrainedVisibleContentSizeChanged(true, true);
356
357         deprecatedLocalMainFrame()->loader().saveScrollState();
358     }
359
360     if (view && view->scrollPosition() != origin)
361         view->notifyScrollPositionChanged(origin);
362 }
363
364 float Page::pageScaleFactor() const
365 {
366     return frameHost().pinchViewport().scale();
367 }
368
369 void Page::setDeviceScaleFactor(float scaleFactor)
370 {
371     if (m_deviceScaleFactor == scaleFactor)
372         return;
373
374     m_deviceScaleFactor = scaleFactor;
375     setNeedsRecalcStyleInAllFrames();
376
377     if (mainFrame() && mainFrame()->isLocalFrame()) {
378         deprecatedLocalMainFrame()->deviceOrPageScaleFactorChanged();
379         m_chrome->client().deviceOrPageScaleFactorChanged();
380     }
381 }
382
383 void Page::allVisitedStateChanged()
384 {
385     HashSet<Page*>::iterator pagesEnd = ordinaryPages().end();
386     for (HashSet<Page*>::iterator it = ordinaryPages().begin(); it != pagesEnd; ++it) {
387         Page* page = *it;
388         for (Frame* frame = page->m_mainFrame; frame; frame = frame->tree().traverseNext()) {
389             if (frame->isLocalFrame())
390                 toLocalFrame(frame)->document()->visitedLinkState().invalidateStyleForAllLinks();
391         }
392     }
393 }
394
395 void Page::visitedStateChanged(LinkHash linkHash)
396 {
397     HashSet<Page*>::iterator pagesEnd = ordinaryPages().end();
398     for (HashSet<Page*>::iterator it = ordinaryPages().begin(); it != pagesEnd; ++it) {
399         Page* page = *it;
400         for (Frame* frame = page->m_mainFrame; frame; frame = frame->tree().traverseNext()) {
401             if (frame->isLocalFrame())
402                 toLocalFrame(frame)->document()->visitedLinkState().invalidateStyleForLink(linkHash);
403         }
404     }
405 }
406
407 StorageNamespace* Page::sessionStorage(bool optionalCreate)
408 {
409     if (!m_sessionStorage && optionalCreate)
410         m_sessionStorage = m_storageClient->createSessionStorageNamespace();
411     return m_sessionStorage.get();
412 }
413
414 void Page::setTimerAlignmentInterval(double interval)
415 {
416     if (interval == m_timerAlignmentInterval)
417         return;
418
419     m_timerAlignmentInterval = interval;
420     for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNextWithWrap(false)) {
421         if (frame->isLocalFrame() && toLocalFrame(frame)->document())
422             toLocalFrame(frame)->document()->didChangeTimerAlignmentInterval();
423     }
424 }
425
426 double Page::timerAlignmentInterval() const
427 {
428     return m_timerAlignmentInterval;
429 }
430
431 #if ASSERT_ENABLED
432 void Page::checkSubframeCountConsistency() const
433 {
434     ASSERT(m_subframeCount >= 0);
435
436     int subframeCount = 0;
437     for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext())
438         ++subframeCount;
439
440     ASSERT(m_subframeCount + 1 == subframeCount);
441 }
442 #endif
443
444 void Page::setVisibilityState(PageVisibilityState visibilityState, bool isInitialState)
445 {
446     if (m_visibilityState == visibilityState)
447         return;
448     m_visibilityState = visibilityState;
449
450     if (visibilityState == WebCore::PageVisibilityStateHidden)
451         setTimerAlignmentInterval(DOMTimer::hiddenPageAlignmentInterval());
452     else
453         setTimerAlignmentInterval(DOMTimer::visiblePageAlignmentInterval());
454
455     if (!isInitialState)
456         lifecycleNotifier().notifyPageVisibilityChanged();
457
458     if (!isInitialState && m_mainFrame && m_mainFrame->isLocalFrame())
459         deprecatedLocalMainFrame()->didChangeVisibilityState();
460 }
461
462 PageVisibilityState Page::visibilityState() const
463 {
464     return m_visibilityState;
465 }
466
467 bool Page::isCursorVisible() const
468 {
469     return m_isCursorVisible && settings().deviceSupportsMouse();
470 }
471
472 void Page::addMultisamplingChangedObserver(MultisamplingChangedObserver* observer)
473 {
474     m_multisamplingChangedObservers.add(observer);
475 }
476
477 void Page::removeMultisamplingChangedObserver(MultisamplingChangedObserver* observer)
478 {
479     m_multisamplingChangedObservers.remove(observer);
480 }
481
482 void Page::settingsChanged(SettingsDelegate::ChangeType changeType)
483 {
484     switch (changeType) {
485     case SettingsDelegate::StyleChange:
486         setNeedsRecalcStyleInAllFrames();
487         break;
488     case SettingsDelegate::ViewportDescriptionChange:
489         if (mainFrame() && mainFrame()->isLocalFrame())
490             deprecatedLocalMainFrame()->document()->updateViewportDescription();
491         break;
492     case SettingsDelegate::MediaTypeChange:
493         if (m_mainFrame->isLocalFrame()) {
494             deprecatedLocalMainFrame()->view()->setMediaType(AtomicString(settings().mediaTypeOverride()));
495             setNeedsRecalcStyleInAllFrames();
496         }
497         break;
498     case SettingsDelegate::DNSPrefetchingChange:
499         for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
500             if (frame->isLocalFrame())
501                 toLocalFrame(frame)->document()->initDNSPrefetch();
502         }
503         break;
504     case SettingsDelegate::MultisamplingChange: {
505         WillBeHeapHashSet<RawPtrWillBeWeakMember<MultisamplingChangedObserver> >::iterator stop = m_multisamplingChangedObservers.end();
506         for (WillBeHeapHashSet<RawPtrWillBeWeakMember<MultisamplingChangedObserver> >::iterator it = m_multisamplingChangedObservers.begin(); it != stop; ++it)
507             (*it)->multisamplingChanged(m_settings->openGLMultisamplingEnabled());
508         break;
509     }
510     case SettingsDelegate::ImageLoadingChange:
511         for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
512             if (frame->isLocalFrame()) {
513                 toLocalFrame(frame)->document()->fetcher()->setImagesEnabled(settings().imagesEnabled());
514                 toLocalFrame(frame)->document()->fetcher()->setAutoLoadImages(settings().loadsImagesAutomatically());
515             }
516         }
517         break;
518     case SettingsDelegate::TextAutosizingChange:
519         if (!mainFrame() || !mainFrame()->isLocalFrame())
520             break;
521         if (FastTextAutosizer* textAutosizer = deprecatedLocalMainFrame()->document()->fastTextAutosizer()) {
522             textAutosizer->updatePageInfoInAllFrames();
523         } else {
524             for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
525                 if (!frame->isLocalFrame())
526                     continue;
527                 if (TextAutosizer* textAutosizer = toLocalFrame(frame)->document()->textAutosizer())
528                     textAutosizer->recalculateMultipliers();
529             }
530             // TextAutosizing updates RenderStyle during layout phase (via TextAutosizer::processSubtree).
531             // We should invoke setNeedsLayout here.
532             setNeedsLayoutInAllFrames();
533         }
534         break;
535     case SettingsDelegate::ScriptEnableChange:
536         m_inspectorController->scriptsEnabled(settings().scriptEnabled());
537         break;
538     case SettingsDelegate::FontFamilyChange:
539         for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
540             if (frame->isLocalFrame())
541                 toLocalFrame(frame)->document()->styleEngine()->updateGenericFontFamilySettings();
542         }
543         setNeedsRecalcStyleInAllFrames();
544         break;
545     case SettingsDelegate::AcceleratedCompositingChange:
546         updateAcceleratedCompositingSettings();
547         break;
548     }
549 }
550
551 void Page::updateAcceleratedCompositingSettings()
552 {
553     for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
554         if (!frame->isLocalFrame())
555             continue;
556         if (FrameView* view = toLocalFrame(frame)->view())
557             view->updateAcceleratedCompositingSettings();
558     }
559 }
560
561 void Page::didCommitLoad(LocalFrame* frame)
562 {
563     lifecycleNotifier().notifyDidCommitLoad(frame);
564     if (m_mainFrame == frame) {
565         useCounter().didCommitLoad();
566         m_inspectorController->didCommitLoadForMainFrame();
567     }
568 }
569
570 void Page::acceptLanguagesChanged()
571 {
572     Vector< RefPtr<LocalFrame> > frames;
573
574     // Even though we don't fire an event from here, the LocalDOMWindow's will fire
575     // an event so we keep the frames alive until we are done.
576     for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
577         if (frame->isLocalFrame())
578             frames.append(toLocalFrame(frame));
579     }
580
581     for (unsigned i = 0; i < frames.size(); ++i)
582         frames[i]->domWindow()->acceptLanguagesChanged();
583 }
584
585 PageLifecycleNotifier& Page::lifecycleNotifier()
586 {
587     return static_cast<PageLifecycleNotifier&>(LifecycleContext<Page>::lifecycleNotifier());
588 }
589
590 PassOwnPtr<LifecycleNotifier<Page> > Page::createLifecycleNotifier()
591 {
592     return PageLifecycleNotifier::create(this);
593 }
594
595 void Page::trace(Visitor* visitor)
596 {
597     visitor->trace(m_dragCaretController);
598     visitor->trace(m_dragController);
599     visitor->trace(m_contextMenuController);
600     visitor->trace(m_pointerLockController);
601     visitor->trace(m_undoStack);
602     visitor->trace(m_validationMessageClient);
603     visitor->trace(m_multisamplingChangedObservers);
604     visitor->trace(m_frameHost);
605     WillBeHeapSupplementable<Page>::trace(visitor);
606 }
607
608 void Page::willBeDestroyed()
609 {
610     RefPtr<Frame> mainFrame = m_mainFrame;
611
612     if (mainFrame->isLocalFrame())
613         toLocalFrame(mainFrame.get())->loader().frameDetached();
614
615     // Disable all agents prior to resetting the frame view.
616     m_inspectorController->willBeDestroyed();
617
618     if (mainFrame->isLocalFrame()) {
619         toLocalFrame(mainFrame.get())->setView(nullptr);
620     } else {
621         ASSERT(m_mainFrame->isRemoteFrame());
622         toRemoteFrame(mainFrame.get())->setView(nullptr);
623     }
624
625     allPages().remove(this);
626     if (ordinaryPages().contains(this))
627         ordinaryPages().remove(this);
628
629     if (m_scrollingCoordinator)
630         m_scrollingCoordinator->willBeDestroyed();
631
632 #ifndef NDEBUG
633     pageCounter.decrement();
634 #endif
635
636     m_chrome->willBeDestroyed();
637     m_mainFrame = 0;
638     if (m_validationMessageClient)
639         m_validationMessageClient->willBeDestroyed();
640     WillBeHeapSupplementable<Page>::willBeDestroyed();
641 }
642
643 Page::PageClients::PageClients()
644     : chromeClient(0)
645     , contextMenuClient(0)
646     , editorClient(0)
647     , dragClient(0)
648     , inspectorClient(0)
649     , backForwardClient(0)
650     , spellCheckerClient(0)
651     , storageClient(0)
652 {
653 }
654
655 Page::PageClients::~PageClients()
656 {
657 }
658
659 } // namespace WebCore