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/)
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.
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.
21 #include "core/page/Page.h"
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/DOMWindow.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/Settings.h"
38 #include "core/inspector/InspectorController.h"
39 #include "core/inspector/InspectorInstrumentation.h"
40 #include "core/loader/FrameLoader.h"
41 #include "core/loader/HistoryItem.h"
42 #include "core/page/AutoscrollController.h"
43 #include "core/page/Chrome.h"
44 #include "core/page/ChromeClient.h"
45 #include "core/page/ContextMenuController.h"
46 #include "core/page/DragController.h"
47 #include "core/page/FocusController.h"
48 #include "core/page/FrameTree.h"
49 #include "core/page/PageLifecycleNotifier.h"
50 #include "core/page/PointerLockController.h"
51 #include "core/page/StorageClient.h"
52 #include "core/page/ValidationMessageClient.h"
53 #include "core/page/scrolling/ScrollingCoordinator.h"
54 #include "core/rendering/FastTextAutosizer.h"
55 #include "core/rendering/RenderView.h"
56 #include "core/rendering/TextAutosizer.h"
57 #include "core/storage/StorageNamespace.h"
58 #include "platform/plugins/PluginData.h"
59 #include "wtf/HashMap.h"
60 #include "wtf/RefCountedLeakCounter.h"
61 #include "wtf/StdLibExtras.h"
62 #include "wtf/text/Base64.h"
66 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, pageCounter, ("Page"));
69 HashSet<Page*>& Page::allPages()
71 DEFINE_STATIC_LOCAL(HashSet<Page*>, allPages, ());
76 HashSet<Page*>& Page::ordinaryPages()
78 DEFINE_STATIC_LOCAL(HashSet<Page*>, ordinaryPages, ());
83 void Page::networkStateChanged(bool online)
85 Vector<RefPtr<LocalFrame> > frames;
87 // Get all the frames of all the pages in all the page groups
88 HashSet<Page*>::iterator end = allPages().end();
89 for (HashSet<Page*>::iterator it = allPages().begin(); it != end; ++it) {
90 for (LocalFrame* frame = (*it)->mainFrame(); frame; frame = frame->tree().traverseNext())
92 InspectorInstrumentation::networkStateChanged(*it, online);
95 AtomicString eventName = online ? EventTypeNames::online : EventTypeNames::offline;
96 for (unsigned i = 0; i < frames.size(); i++)
97 frames[i]->domWindow()->dispatchEvent(Event::create(eventName));
100 float deviceScaleFactor(LocalFrame* frame)
104 Page* page = frame->page();
107 return page->deviceScaleFactor();
110 Page::Page(PageClients& pageClients)
111 : SettingsDelegate(Settings::create())
113 , m_autoscrollController(AutoscrollController::create(*this))
114 , m_chrome(Chrome::create(this, pageClients.chromeClient))
115 , m_dragCaretController(DragCaretController::create())
116 , m_dragController(DragController::create(this, pageClients.dragClient))
117 , m_focusController(FocusController::create(this))
118 , m_contextMenuController(ContextMenuController::create(this, pageClients.contextMenuClient))
119 , m_inspectorController(InspectorController::create(this, pageClients.inspectorClient))
120 , m_pointerLockController(PointerLockController::create(this))
121 , m_undoStack(UndoStack::create())
122 , m_backForwardClient(pageClients.backForwardClient)
123 , m_editorClient(pageClients.editorClient)
124 , m_spellCheckerClient(pageClients.spellCheckerClient)
125 , m_storageClient(pageClients.storageClient)
127 , m_openedByDOM(false)
128 , m_tabKeyCyclesThroughElements(true)
129 , m_defersLoading(false)
130 , m_deviceScaleFactor(1)
131 , m_timerAlignmentInterval(DOMTimer::visiblePageAlignmentInterval())
132 , m_visibilityState(PageVisibilityStateVisible)
133 , m_isCursorVisible(true)
135 , m_isPainting(false)
137 , m_frameHost(FrameHost::create(*this))
139 ASSERT(m_editorClient);
141 ASSERT(!allPages().contains(this));
142 allPages().add(this);
145 pageCounter.increment();
153 void Page::makeOrdinary()
155 ASSERT(!ordinaryPages().contains(this));
156 ordinaryPages().add(this);
159 ViewportDescription Page::viewportDescription() const
161 return mainFrame() && mainFrame()->document() ? mainFrame()->document()->viewportDescription() : ViewportDescription();
164 ScrollingCoordinator* Page::scrollingCoordinator()
166 if (!m_scrollingCoordinator && m_settings->scrollingCoordinatorEnabled())
167 m_scrollingCoordinator = ScrollingCoordinator::create(this);
169 return m_scrollingCoordinator.get();
172 String Page::mainThreadScrollingReasonsAsText()
174 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
175 return scrollingCoordinator->mainThreadScrollingReasonsAsText();
180 PassRefPtrWillBeRawPtr<ClientRectList> Page::nonFastScrollableRects(const LocalFrame* frame)
182 if (Document* document = m_mainFrame->document())
183 document->updateLayout();
185 Vector<IntRect> rects;
186 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
187 rects = scrollingCoordinator->computeShouldHandleScrollGestureOnMainThreadRegion(frame, IntPoint()).rects();
189 Vector<FloatQuad> quads(rects.size());
190 for (size_t i = 0; i < rects.size(); ++i)
191 quads[i] = FloatRect(rects[i]);
192 return ClientRectList::create(quads);
195 void Page::setMainFrame(PassRefPtr<LocalFrame> mainFrame)
197 ASSERT(!m_mainFrame); // Should only be called during initialization
198 m_mainFrame = mainFrame;
201 void Page::documentDetached(Document* document)
203 m_multisamplingChangedObservers.clear();
204 m_pointerLockController->documentDetached(document);
205 m_contextMenuController->documentDetached(document);
206 if (m_validationMessageClient)
207 m_validationMessageClient->documentDetached(*document);
208 m_frameHost->eventHandlerRegistry().documentDetached(*document);
211 bool Page::openedByDOM() const
213 return m_openedByDOM;
216 void Page::setOpenedByDOM()
218 m_openedByDOM = true;
221 void Page::scheduleForcedStyleRecalcForAllPages()
223 HashSet<Page*>::iterator end = allPages().end();
224 for (HashSet<Page*>::iterator it = allPages().begin(); it != end; ++it)
225 for (LocalFrame* frame = (*it)->mainFrame(); frame; frame = frame->tree().traverseNext())
226 frame->document()->setNeedsStyleRecalc(SubtreeStyleChange);
229 void Page::setNeedsRecalcStyleInAllFrames()
231 for (LocalFrame* frame = mainFrame(); frame; frame = frame->tree().traverseNext())
232 frame->document()->styleResolverChanged(RecalcStyleDeferred);
235 void Page::setNeedsLayoutInAllFrames()
237 for (LocalFrame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
238 if (FrameView* view = frame->view()) {
239 view->setNeedsLayout();
240 view->scheduleRelayout();
245 void Page::refreshPlugins(bool reload)
247 if (allPages().isEmpty())
250 PluginData::refresh();
252 Vector<RefPtr<LocalFrame> > framesNeedingReload;
254 HashSet<Page*>::iterator end = allPages().end();
255 for (HashSet<Page*>::iterator it = allPages().begin(); it != end; ++it) {
258 // Clear out the page's plug-in data.
259 if (page->m_pluginData)
260 page->m_pluginData = nullptr;
265 for (LocalFrame* frame = (*it)->mainFrame(); frame; frame = frame->tree().traverseNext()) {
266 if (frame->document()->containsPlugins())
267 framesNeedingReload.append(frame);
271 for (size_t i = 0; i < framesNeedingReload.size(); ++i)
272 framesNeedingReload[i]->loader().reload();
275 PluginData* Page::pluginData() const
277 if (!mainFrame()->loader().allowPlugins(NotAboutToInstantiatePlugin))
280 m_pluginData = PluginData::create(this);
281 return m_pluginData.get();
284 static LocalFrame* incrementFrame(LocalFrame* curr, bool forward, bool wrapFlag)
287 ? curr->tree().traverseNextWithWrap(wrapFlag)
288 : curr->tree().traversePreviousWithWrap(wrapFlag);
291 void Page::unmarkAllTextMatches()
296 LocalFrame* frame = mainFrame();
298 frame->document()->markers().removeMarkers(DocumentMarker::TextMatch);
299 frame = incrementFrame(frame, true, false);
303 void Page::setValidationMessageClient(PassOwnPtr<ValidationMessageClient> client)
305 m_validationMessageClient = client;
308 void Page::setDefersLoading(bool defers)
310 if (defers == m_defersLoading)
313 m_defersLoading = defers;
314 for (LocalFrame* frame = mainFrame(); frame; frame = frame->tree().traverseNext())
315 frame->loader().setDefersLoading(defers);
318 void Page::setPageScaleFactor(float scale, const IntPoint& origin)
320 FrameView* view = mainFrame()->view();
321 PinchViewport& viewport = frameHost().pinchViewport();
323 if (scale != viewport.scale()) {
324 viewport.setScale(scale);
326 if (view && !settings().pinchVirtualViewportEnabled())
327 view->setVisibleContentScaleFactor(scale);
329 mainFrame()->deviceOrPageScaleFactorChanged();
330 m_chrome->client().deviceOrPageScaleFactorChanged();
333 view->viewportConstrainedVisibleContentSizeChanged(true, true);
335 mainFrame()->loader().saveScrollState();
338 if (view && view->scrollPosition() != origin)
339 view->notifyScrollPositionChanged(origin);
342 float Page::pageScaleFactor() const
344 return frameHost().pinchViewport().scale();
347 void Page::setDeviceScaleFactor(float scaleFactor)
349 if (m_deviceScaleFactor == scaleFactor)
352 m_deviceScaleFactor = scaleFactor;
353 setNeedsRecalcStyleInAllFrames();
356 mainFrame()->deviceOrPageScaleFactorChanged();
357 m_chrome->client().deviceOrPageScaleFactorChanged();
361 void Page::allVisitedStateChanged()
363 HashSet<Page*>::iterator pagesEnd = ordinaryPages().end();
364 for (HashSet<Page*>::iterator it = ordinaryPages().begin(); it != pagesEnd; ++it) {
366 for (LocalFrame* frame = page->m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
367 frame->document()->visitedLinkState().invalidateStyleForAllLinks();
371 void Page::visitedStateChanged(LinkHash linkHash)
373 HashSet<Page*>::iterator pagesEnd = ordinaryPages().end();
374 for (HashSet<Page*>::iterator it = ordinaryPages().begin(); it != pagesEnd; ++it) {
376 for (LocalFrame* frame = page->m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
377 frame->document()->visitedLinkState().invalidateStyleForLink(linkHash);
381 StorageNamespace* Page::sessionStorage(bool optionalCreate)
383 if (!m_sessionStorage && optionalCreate)
384 m_sessionStorage = m_storageClient->createSessionStorageNamespace();
385 return m_sessionStorage.get();
388 void Page::setTimerAlignmentInterval(double interval)
390 if (interval == m_timerAlignmentInterval)
393 m_timerAlignmentInterval = interval;
394 for (LocalFrame* frame = mainFrame(); frame; frame = frame->tree().traverseNextWithWrap(false)) {
395 if (frame->document())
396 frame->document()->didChangeTimerAlignmentInterval();
400 double Page::timerAlignmentInterval() const
402 return m_timerAlignmentInterval;
406 void Page::checkSubframeCountConsistency() const
408 ASSERT(m_subframeCount >= 0);
410 int subframeCount = 0;
411 for (LocalFrame* frame = mainFrame(); frame; frame = frame->tree().traverseNext())
414 ASSERT(m_subframeCount + 1 == subframeCount);
418 void Page::setVisibilityState(PageVisibilityState visibilityState, bool isInitialState)
420 if (m_visibilityState == visibilityState)
422 m_visibilityState = visibilityState;
424 if (visibilityState == WebCore::PageVisibilityStateHidden)
425 setTimerAlignmentInterval(DOMTimer::hiddenPageAlignmentInterval());
427 setTimerAlignmentInterval(DOMTimer::visiblePageAlignmentInterval());
430 lifecycleNotifier().notifyPageVisibilityChanged();
432 if (!isInitialState && m_mainFrame)
433 m_mainFrame->didChangeVisibilityState();
436 PageVisibilityState Page::visibilityState() const
438 return m_visibilityState;
441 bool Page::isCursorVisible() const
443 return m_isCursorVisible && settings().deviceSupportsMouse();
446 void Page::addMultisamplingChangedObserver(MultisamplingChangedObserver* observer)
448 m_multisamplingChangedObservers.add(observer);
451 void Page::removeMultisamplingChangedObserver(MultisamplingChangedObserver* observer)
453 m_multisamplingChangedObservers.remove(observer);
456 void Page::settingsChanged(SettingsDelegate::ChangeType changeType)
458 switch (changeType) {
459 case SettingsDelegate::StyleChange:
460 setNeedsRecalcStyleInAllFrames();
462 case SettingsDelegate::ViewportDescriptionChange:
464 mainFrame()->document()->updateViewportDescription();
466 case SettingsDelegate::MediaTypeChange:
467 m_mainFrame->view()->setMediaType(AtomicString(settings().mediaTypeOverride()));
468 setNeedsRecalcStyleInAllFrames();
470 case SettingsDelegate::DNSPrefetchingChange:
471 for (LocalFrame* frame = mainFrame(); frame; frame = frame->tree().traverseNext())
472 frame->document()->initDNSPrefetch();
474 case SettingsDelegate::MultisamplingChange: {
475 WillBeHeapHashSet<RawPtrWillBeWeakMember<MultisamplingChangedObserver> >::iterator stop = m_multisamplingChangedObservers.end();
476 for (WillBeHeapHashSet<RawPtrWillBeWeakMember<MultisamplingChangedObserver> >::iterator it = m_multisamplingChangedObservers.begin(); it != stop; ++it)
477 (*it)->multisamplingChanged(m_settings->openGLMultisamplingEnabled());
480 case SettingsDelegate::ImageLoadingChange:
481 for (LocalFrame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
482 frame->document()->fetcher()->setImagesEnabled(settings().imagesEnabled());
483 frame->document()->fetcher()->setAutoLoadImages(settings().loadsImagesAutomatically());
486 case SettingsDelegate::TextAutosizingChange:
489 if (FastTextAutosizer* textAutosizer = mainFrame()->document()->fastTextAutosizer()) {
490 textAutosizer->updatePageInfoInAllFrames();
492 for (LocalFrame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
493 if (TextAutosizer* textAutosizer = frame->document()->textAutosizer())
494 textAutosizer->recalculateMultipliers();
496 // TextAutosizing updates RenderStyle during layout phase (via TextAutosizer::processSubtree).
497 // We should invoke setNeedsLayout here.
498 setNeedsLayoutInAllFrames();
501 case SettingsDelegate::ScriptEnableChange:
502 m_inspectorController->scriptsEnabled(settings().scriptEnabled());
504 case SettingsDelegate::FontFamilyChange:
505 for (LocalFrame* frame = mainFrame(); frame; frame = frame->tree().traverseNext())
506 frame->document()->styleEngine()->updateGenericFontFamilySettings();
507 setNeedsRecalcStyleInAllFrames();
509 case SettingsDelegate::AcceleratedCompositingChange:
510 updateAcceleratedCompositingSettings();
515 void Page::updateAcceleratedCompositingSettings()
517 for (LocalFrame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
518 if (FrameView* view = frame->view())
519 view->updateAcceleratedCompositingSettings();
523 void Page::didCommitLoad(LocalFrame* frame)
525 lifecycleNotifier().notifyDidCommitLoad(frame);
526 if (m_mainFrame == frame) {
527 useCounter().didCommitLoad();
528 m_inspectorController->didCommitLoadForMainFrame();
532 PageLifecycleNotifier& Page::lifecycleNotifier()
534 return static_cast<PageLifecycleNotifier&>(LifecycleContext<Page>::lifecycleNotifier());
537 PassOwnPtr<LifecycleNotifier<Page> > Page::createLifecycleNotifier()
539 return PageLifecycleNotifier::create(this);
542 void Page::trace(Visitor* visitor)
544 visitor->trace(m_multisamplingChangedObservers);
545 visitor->trace(m_frameHost);
546 WillBeHeapSupplementable<Page>::trace(visitor);
549 void Page::willBeDestroyed()
551 // Disable all agents prior to resetting the frame view.
552 m_inspectorController->willBeDestroyed();
554 m_mainFrame->setView(nullptr);
556 allPages().remove(this);
557 if (ordinaryPages().contains(this))
558 ordinaryPages().remove(this);
560 for (LocalFrame* frame = mainFrame(); frame; frame = frame->tree().traverseNext())
561 frame->loader().frameDetached();
563 if (m_scrollingCoordinator)
564 m_scrollingCoordinator->willBeDestroyed();
567 pageCounter.decrement();
570 m_chrome->willBeDestroyed();
572 if (m_validationMessageClient)
573 m_validationMessageClient->willBeDestroyed();
574 WillBeHeapSupplementable<Page>::willBeDestroyed();
577 Page::PageClients::PageClients()
579 , contextMenuClient(0)
583 , backForwardClient(0)
584 , spellCheckerClient(0)
589 Page::PageClients::~PageClients()
593 } // namespace WebCore