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/FrameConsole.h"
33 #include "core/frame/FrameHost.h"
34 #include "core/frame/FrameView.h"
35 #include "core/frame/LocalDOMWindow.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/RenderView.h"
57 #include "core/rendering/TextAutosizer.h"
58 #include "core/storage/StorageNamespace.h"
59 #include "platform/plugins/PluginData.h"
60 #include "wtf/HashMap.h"
61 #include "wtf/RefCountedLeakCounter.h"
62 #include "wtf/StdLibExtras.h"
63 #include "wtf/text/Base64.h"
67 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, pageCounter, ("Page"));
70 HashSet<Page*>& Page::allPages()
72 DEFINE_STATIC_LOCAL(HashSet<Page*>, allPages, ());
77 HashSet<Page*>& Page::ordinaryPages()
79 DEFINE_STATIC_LOCAL(HashSet<Page*>, ordinaryPages, ());
84 void Page::networkStateChanged(bool online)
86 WillBeHeapVector<RefPtrWillBeMember<LocalFrame> > frames;
88 // Get all the frames of all the pages in all the page groups
89 HashSet<Page*>::iterator end = allPages().end();
90 for (HashSet<Page*>::iterator it = allPages().begin(); it != end; ++it) {
91 for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree().traverseNext()) {
92 // FIXME: There is currently no way to dispatch events to out-of-process frames.
93 if (frame->isLocalFrame())
94 frames.append(toLocalFrame(frame));
96 InspectorInstrumentation::networkStateChanged(*it, online);
99 AtomicString eventName = online ? EventTypeNames::online : EventTypeNames::offline;
100 for (unsigned i = 0; i < frames.size(); i++)
101 frames[i]->domWindow()->dispatchEvent(Event::create(eventName));
104 float deviceScaleFactor(LocalFrame* frame)
108 Page* page = frame->page();
111 return page->deviceScaleFactor();
114 Page::Page(PageClients& pageClients)
115 : SettingsDelegate(Settings::create())
116 , m_animator(PageAnimator::create(*this))
117 , m_autoscrollController(AutoscrollController::create(*this))
118 , m_chrome(Chrome::create(this, pageClients.chromeClient))
119 , m_dragCaretController(DragCaretController::create())
120 , m_dragController(DragController::create(this, pageClients.dragClient))
121 , m_focusController(FocusController::create(this))
122 , m_contextMenuController(ContextMenuController::create(this, pageClients.contextMenuClient))
123 , m_inspectorController(InspectorController::create(this, pageClients.inspectorClient))
124 , m_pointerLockController(PointerLockController::create(this))
125 , m_undoStack(UndoStack::create())
126 , m_mainFrame(nullptr)
127 , m_backForwardClient(pageClients.backForwardClient)
128 , m_editorClient(pageClients.editorClient)
129 , m_spellCheckerClient(pageClients.spellCheckerClient)
130 , m_storageClient(pageClients.storageClient)
132 , m_openedByDOM(false)
133 , m_tabKeyCyclesThroughElements(true)
134 , m_defersLoading(false)
135 , m_deviceScaleFactor(1)
136 , m_timerAlignmentInterval(DOMTimer::visiblePageAlignmentInterval())
137 , m_visibilityState(PageVisibilityStateVisible)
138 , m_isCursorVisible(true)
140 , m_isPainting(false)
142 , m_frameHost(FrameHost::create(*this))
144 ASSERT(m_editorClient);
146 ASSERT(!allPages().contains(this));
147 allPages().add(this);
150 pageCounter.increment();
156 // willBeDestroyed() must be called before Page destruction.
157 ASSERT(!m_mainFrame);
160 void Page::makeOrdinary()
162 ASSERT(!ordinaryPages().contains(this));
163 ordinaryPages().add(this);
166 ViewportDescription Page::viewportDescription() const
168 return mainFrame() && mainFrame()->isLocalFrame() && deprecatedLocalMainFrame()->document() ? deprecatedLocalMainFrame()->document()->viewportDescription() : ViewportDescription();
171 ScrollingCoordinator* Page::scrollingCoordinator()
173 if (!m_scrollingCoordinator && m_settings->acceleratedCompositingEnabled())
174 m_scrollingCoordinator = ScrollingCoordinator::create(this);
176 return m_scrollingCoordinator.get();
179 String Page::mainThreadScrollingReasonsAsText()
181 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
182 return scrollingCoordinator->mainThreadScrollingReasonsAsText();
187 PassRefPtrWillBeRawPtr<ClientRectList> Page::nonFastScrollableRects(const LocalFrame* frame)
189 if (m_mainFrame->isLocalFrame() && deprecatedLocalMainFrame()->document())
190 deprecatedLocalMainFrame()->document()->updateLayout();
192 Vector<IntRect> rects;
193 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
194 rects = scrollingCoordinator->computeShouldHandleScrollGestureOnMainThreadRegion(frame, IntPoint()).rects();
196 Vector<FloatQuad> quads(rects.size());
197 for (size_t i = 0; i < rects.size(); ++i)
198 quads[i] = FloatRect(rects[i]);
199 return ClientRectList::create(quads);
202 void Page::setMainFrame(Frame* mainFrame)
204 // Should only be called during initialization or swaps between local and
206 // FIXME: Unfortunately we can't assert on this at the moment, because this
207 // is called in the base constructor for both LocalFrame and RemoteFrame,
208 // when the vtables for the derived classes have not yet been setup.
209 m_mainFrame = mainFrame;
212 void Page::documentDetached(Document* document)
214 m_multisamplingChangedObservers.clear();
215 m_pointerLockController->documentDetached(document);
216 m_contextMenuController->documentDetached(document);
217 if (m_validationMessageClient)
218 m_validationMessageClient->documentDetached(*document);
221 bool Page::openedByDOM() const
223 return m_openedByDOM;
226 void Page::setOpenedByDOM()
228 m_openedByDOM = true;
231 void Page::scheduleForcedStyleRecalcForAllPages()
233 HashSet<Page*>::iterator end = allPages().end();
234 for (HashSet<Page*>::iterator it = allPages().begin(); it != end; ++it)
235 for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree().traverseNext()) {
236 if (frame->isLocalFrame())
237 toLocalFrame(frame)->document()->setNeedsStyleRecalc(SubtreeStyleChange);
241 void Page::setNeedsRecalcStyleInAllFrames()
243 for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
244 if (frame->isLocalFrame())
245 toLocalFrame(frame)->document()->styleResolverChanged();
249 void Page::setNeedsLayoutInAllFrames()
251 for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
252 if (!frame->isLocalFrame())
254 if (FrameView* view = toLocalFrame(frame)->view()) {
255 view->setNeedsLayout();
256 view->scheduleRelayout();
261 void Page::refreshPlugins(bool reload)
263 if (allPages().isEmpty())
266 PluginData::refresh();
268 WillBeHeapVector<RefPtrWillBeMember<LocalFrame> > framesNeedingReload;
270 HashSet<Page*>::iterator end = allPages().end();
271 for (HashSet<Page*>::iterator it = allPages().begin(); it != end; ++it) {
274 // Clear out the page's plug-in data.
275 if (page->m_pluginData)
276 page->m_pluginData = nullptr;
281 for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree().traverseNext()) {
282 if (frame->isLocalFrame() && toLocalFrame(frame)->document()->containsPlugins())
283 framesNeedingReload.append(toLocalFrame(frame));
287 for (size_t i = 0; i < framesNeedingReload.size(); ++i)
288 framesNeedingReload[i]->loader().reload();
291 PluginData* Page::pluginData() const
293 if (!deprecatedLocalMainFrame()->loader().allowPlugins(NotAboutToInstantiatePlugin))
296 m_pluginData = PluginData::create(this);
297 return m_pluginData.get();
300 static Frame* incrementFrame(Frame* curr, bool forward, bool wrapFlag)
303 ? curr->tree().traverseNextWithWrap(wrapFlag)
304 : curr->tree().traversePreviousWithWrap(wrapFlag);
307 void Page::unmarkAllTextMatches()
312 Frame* frame = mainFrame();
314 if (frame->isLocalFrame())
315 toLocalFrame(frame)->document()->markers().removeMarkers(DocumentMarker::TextMatch);
316 frame = incrementFrame(frame, true, false);
320 void Page::setValidationMessageClient(PassOwnPtrWillBeRawPtr<ValidationMessageClient> client)
322 m_validationMessageClient = client;
325 void Page::setDefersLoading(bool defers)
327 if (defers == m_defersLoading)
330 m_defersLoading = defers;
331 for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
332 if (frame->isLocalFrame())
333 toLocalFrame(frame)->loader().setDefersLoading(defers);
337 void Page::setPageScaleFactor(float scale, const IntPoint& origin)
339 if (!mainFrame()->isLocalFrame())
342 FrameView* view = deprecatedLocalMainFrame()->view();
343 PinchViewport& viewport = frameHost().pinchViewport();
345 if (scale != viewport.scale()) {
346 viewport.setScale(scale);
348 if (view && !settings().pinchVirtualViewportEnabled())
349 view->setVisibleContentScaleFactor(scale);
351 deprecatedLocalMainFrame()->deviceOrPageScaleFactorChanged();
352 m_chrome->client().deviceOrPageScaleFactorChanged();
354 // FIXME: In virtual-viewport pinch mode, scale doesn't change the fixed-pos viewport;
355 // remove once it's the only pinch mode in town.
357 view->viewportConstrainedVisibleContentSizeChanged(true, true);
359 deprecatedLocalMainFrame()->loader().saveScrollState();
362 if (view && view->scrollPosition() != origin)
363 view->notifyScrollPositionChanged(origin);
366 float Page::pageScaleFactor() const
368 return frameHost().pinchViewport().scale();
371 void Page::setDeviceScaleFactor(float scaleFactor)
373 if (m_deviceScaleFactor == scaleFactor)
376 m_deviceScaleFactor = scaleFactor;
377 setNeedsRecalcStyleInAllFrames();
379 if (mainFrame() && mainFrame()->isLocalFrame()) {
380 deprecatedLocalMainFrame()->deviceOrPageScaleFactorChanged();
381 m_chrome->client().deviceOrPageScaleFactorChanged();
385 void Page::setDeviceColorProfile(const Vector<char>& profile)
390 void Page::resetDeviceColorProfile()
395 void Page::allVisitedStateChanged()
397 HashSet<Page*>::iterator pagesEnd = ordinaryPages().end();
398 for (HashSet<Page*>::iterator it = ordinaryPages().begin(); it != pagesEnd; ++it) {
400 for (Frame* frame = page->m_mainFrame; frame; frame = frame->tree().traverseNext()) {
401 if (frame->isLocalFrame())
402 toLocalFrame(frame)->document()->visitedLinkState().invalidateStyleForAllLinks();
407 void Page::visitedStateChanged(LinkHash linkHash)
409 HashSet<Page*>::iterator pagesEnd = ordinaryPages().end();
410 for (HashSet<Page*>::iterator it = ordinaryPages().begin(); it != pagesEnd; ++it) {
412 for (Frame* frame = page->m_mainFrame; frame; frame = frame->tree().traverseNext()) {
413 if (frame->isLocalFrame())
414 toLocalFrame(frame)->document()->visitedLinkState().invalidateStyleForLink(linkHash);
419 StorageNamespace* Page::sessionStorage(bool optionalCreate)
421 if (!m_sessionStorage && optionalCreate)
422 m_sessionStorage = m_storageClient->createSessionStorageNamespace();
423 return m_sessionStorage.get();
426 void Page::setTimerAlignmentInterval(double interval)
428 if (interval == m_timerAlignmentInterval)
431 m_timerAlignmentInterval = interval;
432 for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNextWithWrap(false)) {
433 if (frame->isLocalFrame() && toLocalFrame(frame)->document())
434 toLocalFrame(frame)->document()->didChangeTimerAlignmentInterval();
438 double Page::timerAlignmentInterval() const
440 return m_timerAlignmentInterval;
444 void Page::checkSubframeCountConsistency() const
446 ASSERT(m_subframeCount >= 0);
448 int subframeCount = 0;
449 for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext())
452 ASSERT(m_subframeCount + 1 == subframeCount);
456 void Page::setVisibilityState(PageVisibilityState visibilityState, bool isInitialState)
458 if (m_visibilityState == visibilityState)
460 m_visibilityState = visibilityState;
462 if (visibilityState == blink::PageVisibilityStateVisible)
463 setTimerAlignmentInterval(DOMTimer::visiblePageAlignmentInterval());
465 setTimerAlignmentInterval(DOMTimer::hiddenPageAlignmentInterval());
468 lifecycleNotifier().notifyPageVisibilityChanged();
470 if (!isInitialState && m_mainFrame && m_mainFrame->isLocalFrame())
471 deprecatedLocalMainFrame()->didChangeVisibilityState();
474 PageVisibilityState Page::visibilityState() const
476 return m_visibilityState;
479 bool Page::isCursorVisible() const
481 return m_isCursorVisible && settings().deviceSupportsMouse();
484 void Page::addMultisamplingChangedObserver(MultisamplingChangedObserver* observer)
486 m_multisamplingChangedObservers.add(observer);
489 void Page::removeMultisamplingChangedObserver(MultisamplingChangedObserver* observer)
491 m_multisamplingChangedObservers.remove(observer);
494 void Page::settingsChanged(SettingsDelegate::ChangeType changeType)
496 switch (changeType) {
497 case SettingsDelegate::StyleChange:
498 setNeedsRecalcStyleInAllFrames();
500 case SettingsDelegate::ViewportDescriptionChange:
501 if (mainFrame() && mainFrame()->isLocalFrame())
502 deprecatedLocalMainFrame()->document()->updateViewportDescription();
504 case SettingsDelegate::MediaTypeChange:
505 if (m_mainFrame->isLocalFrame()) {
506 deprecatedLocalMainFrame()->view()->setMediaType(AtomicString(settings().mediaTypeOverride()));
507 setNeedsRecalcStyleInAllFrames();
510 case SettingsDelegate::DNSPrefetchingChange:
511 for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
512 if (frame->isLocalFrame())
513 toLocalFrame(frame)->document()->initDNSPrefetch();
516 case SettingsDelegate::MultisamplingChange: {
517 WillBeHeapHashSet<RawPtrWillBeWeakMember<MultisamplingChangedObserver> >::iterator stop = m_multisamplingChangedObservers.end();
518 for (WillBeHeapHashSet<RawPtrWillBeWeakMember<MultisamplingChangedObserver> >::iterator it = m_multisamplingChangedObservers.begin(); it != stop; ++it)
519 (*it)->multisamplingChanged(m_settings->openGLMultisamplingEnabled());
522 case SettingsDelegate::ImageLoadingChange:
523 for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
524 if (frame->isLocalFrame()) {
525 toLocalFrame(frame)->document()->fetcher()->setImagesEnabled(settings().imagesEnabled());
526 toLocalFrame(frame)->document()->fetcher()->setAutoLoadImages(settings().loadsImagesAutomatically());
530 case SettingsDelegate::TextAutosizingChange:
531 if (!mainFrame() || !mainFrame()->isLocalFrame())
533 if (TextAutosizer* textAutosizer = deprecatedLocalMainFrame()->document()->textAutosizer())
534 textAutosizer->updatePageInfoInAllFrames();
536 case SettingsDelegate::ScriptEnableChange:
537 m_inspectorController->scriptsEnabled(settings().scriptEnabled());
539 case SettingsDelegate::FontFamilyChange:
540 for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
541 if (frame->isLocalFrame())
542 toLocalFrame(frame)->document()->styleEngine()->updateGenericFontFamilySettings();
544 setNeedsRecalcStyleInAllFrames();
546 case SettingsDelegate::AcceleratedCompositingChange:
547 updateAcceleratedCompositingSettings();
549 case SettingsDelegate::MediaQueryChange:
550 for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
551 if (frame->isLocalFrame())
552 toLocalFrame(frame)->document()->mediaQueryAffectingValueChanged();
554 setNeedsRecalcStyleInAllFrames();
559 void Page::updateAcceleratedCompositingSettings()
561 for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
562 if (!frame->isLocalFrame())
564 if (FrameView* view = toLocalFrame(frame)->view())
565 view->updateAcceleratedCompositingSettings();
569 void Page::didCommitLoad(LocalFrame* frame)
571 lifecycleNotifier().notifyDidCommitLoad(frame);
572 if (m_mainFrame == frame) {
573 frame->console().clearMessages();
574 useCounter().didCommitLoad();
575 m_inspectorController->didCommitLoadForMainFrame();
576 UserGestureIndicator::clearProcessedUserGestureSinceLoad();
580 void Page::acceptLanguagesChanged()
582 WillBeHeapVector<RefPtrWillBeMember<LocalFrame> > frames;
584 // Even though we don't fire an event from here, the LocalDOMWindow's will fire
585 // an event so we keep the frames alive until we are done.
586 for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
587 if (frame->isLocalFrame())
588 frames.append(toLocalFrame(frame));
591 for (unsigned i = 0; i < frames.size(); ++i)
592 frames[i]->domWindow()->acceptLanguagesChanged();
595 PageLifecycleNotifier& Page::lifecycleNotifier()
597 return static_cast<PageLifecycleNotifier&>(LifecycleContext<Page>::lifecycleNotifier());
600 PassOwnPtr<LifecycleNotifier<Page> > Page::createLifecycleNotifier()
602 return PageLifecycleNotifier::create(this);
605 void Page::trace(Visitor* visitor)
608 visitor->trace(m_animator);
609 visitor->trace(m_dragCaretController);
610 visitor->trace(m_dragController);
611 visitor->trace(m_focusController);
612 visitor->trace(m_contextMenuController);
613 visitor->trace(m_inspectorController);
614 visitor->trace(m_pointerLockController);
615 visitor->trace(m_undoStack);
616 visitor->trace(m_mainFrame);
617 visitor->trace(m_validationMessageClient);
618 visitor->trace(m_multisamplingChangedObservers);
619 visitor->trace(m_frameHost);
620 HeapSupplementable<Page>::trace(visitor);
622 LifecycleContext<Page>::trace(visitor);
625 void Page::willBeDestroyed()
627 // Destroy inspector first, since it uses frame and view during destruction.
628 m_inspectorController->willBeDestroyed();
630 RefPtrWillBeRawPtr<Frame> mainFrame = m_mainFrame;
634 if (mainFrame->isLocalFrame()) {
635 toLocalFrame(mainFrame.get())->setView(nullptr);
637 ASSERT(m_mainFrame->isRemoteFrame());
638 toRemoteFrame(mainFrame.get())->setView(nullptr);
641 allPages().remove(this);
642 if (ordinaryPages().contains(this))
643 ordinaryPages().remove(this);
645 if (m_scrollingCoordinator)
646 m_scrollingCoordinator->willBeDestroyed();
649 pageCounter.decrement();
652 m_chrome->willBeDestroyed();
653 if (m_validationMessageClient)
654 m_validationMessageClient->willBeDestroyed();
655 m_mainFrame = nullptr;
658 Page::PageClients::PageClients()
660 , contextMenuClient(0)
664 , backForwardClient(0)
665 , spellCheckerClient(0)
670 Page::PageClients::~PageClients()