• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/events/ThreadLocalEventNames.h"
31 #include "core/fetch/ResourceFetcher.h"
32 #include "core/frame/DOMTimer.h"
33 #include "core/frame/DOMWindow.h"
34 #include "core/frame/Frame.h"
35 #include "core/frame/FrameView.h"
36 #include "core/history/HistoryItem.h"
37 #include "core/inspector/InspectorController.h"
38 #include "core/inspector/InspectorInstrumentation.h"
39 #include "core/loader/FrameLoader.h"
40 #include "core/loader/ProgressTracker.h"
41 #include "core/page/AutoscrollController.h"
42 #include "core/page/Chrome.h"
43 #include "core/page/ChromeClient.h"
44 #include "core/page/ContextMenuController.h"
45 #include "core/page/DragController.h"
46 #include "core/page/FocusController.h"
47 #include "core/page/FrameTree.h"
48 #include "core/page/PageConsole.h"
49 #include "core/page/PageGroup.h"
50 #include "core/page/PageLifecycleNotifier.h"
51 #include "core/page/PointerLockController.h"
52 #include "core/frame/Settings.h"
53 #include "core/page/ValidationMessageClient.h"
54 #include "core/page/scrolling/ScrollingCoordinator.h"
55 #include "core/rendering/RenderView.h"
56 #include "core/rendering/TextAutosizer.h"
57 #include "core/storage/StorageNamespace.h"
58 #include "core/workers/SharedWorkerRepositoryClient.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"
64 
65 namespace WebCore {
66 
67 static HashSet<Page*>* allPages;
68 
69 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, pageCounter, ("Page"));
70 
networkStateChanged(bool online)71 void Page::networkStateChanged(bool online)
72 {
73     if (!allPages)
74         return;
75 
76     Vector<RefPtr<Frame> > frames;
77 
78     // Get all the frames of all the pages in all the page groups
79     HashSet<Page*>::iterator end = allPages->end();
80     for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) {
81         for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree().traverseNext())
82             frames.append(frame);
83         InspectorInstrumentation::networkStateChanged(*it, online);
84     }
85 
86     AtomicString eventName = online ? EventTypeNames::online : EventTypeNames::offline;
87     for (unsigned i = 0; i < frames.size(); i++)
88         frames[i]->domWindow()->dispatchEvent(Event::create(eventName));
89 }
90 
deviceScaleFactor(Frame * frame)91 float deviceScaleFactor(Frame* frame)
92 {
93     if (!frame)
94         return 1;
95     Page* page = frame->page();
96     if (!page)
97         return 1;
98     return page->deviceScaleFactor();
99 }
100 
Page(PageClients & pageClients)101 Page::Page(PageClients& pageClients)
102     : SettingsDelegate(Settings::create())
103     , m_autoscrollController(AutoscrollController::create(*this))
104     , m_chrome(Chrome::create(this, pageClients.chromeClient))
105     , m_dragCaretController(DragCaretController::create())
106     , m_dragController(DragController::create(this, pageClients.dragClient))
107     , m_focusController(FocusController::create(this))
108     , m_contextMenuController(ContextMenuController::create(this, pageClients.contextMenuClient))
109     , m_inspectorController(InspectorController::create(this, pageClients.inspectorClient))
110     , m_pointerLockController(PointerLockController::create(this))
111     , m_historyController(adoptPtr(new HistoryController(this)))
112     , m_progress(ProgressTracker::create())
113     , m_undoStack(UndoStack::create())
114     , m_backForwardClient(pageClients.backForwardClient)
115     , m_editorClient(pageClients.editorClient)
116     , m_validationMessageClient(0)
117     , m_sharedWorkerRepositoryClient(0)
118     , m_spellCheckerClient(pageClients.spellCheckerClient)
119     , m_subframeCount(0)
120     , m_openedByDOM(false)
121     , m_tabKeyCyclesThroughElements(true)
122     , m_defersLoading(false)
123     , m_pageScaleFactor(1)
124     , m_deviceScaleFactor(1)
125     , m_group(0)
126     , m_timerAlignmentInterval(DOMTimer::visiblePageAlignmentInterval())
127     , m_visibilityState(PageVisibilityStateVisible)
128     , m_isCursorVisible(true)
129 #ifndef NDEBUG
130     , m_isPainting(false)
131 #endif
132     , m_console(PageConsole::create(this))
133 {
134     ASSERT(m_editorClient);
135 
136     if (!allPages)
137         allPages = new HashSet<Page*>;
138 
139     ASSERT(!allPages->contains(this));
140     allPages->add(this);
141 
142 #ifndef NDEBUG
143     pageCounter.increment();
144 #endif
145 }
146 
~Page()147 Page::~Page()
148 {
149     m_mainFrame->setView(0);
150     clearPageGroup();
151     allPages->remove(this);
152 
153     for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
154         frame->willDetachPage();
155         frame->detachFromPage();
156     }
157 
158     m_inspectorController->inspectedPageDestroyed();
159 
160     if (m_scrollingCoordinator)
161         m_scrollingCoordinator->pageDestroyed();
162 
163 #ifndef NDEBUG
164     pageCounter.decrement();
165 #endif
166 }
167 
viewportDescription() const168 ViewportDescription Page::viewportDescription() const
169 {
170     return mainFrame() && mainFrame()->document() ? mainFrame()->document()->viewportDescription() : ViewportDescription();
171 }
172 
scrollingCoordinator()173 ScrollingCoordinator* Page::scrollingCoordinator()
174 {
175     if (!m_scrollingCoordinator && m_settings->scrollingCoordinatorEnabled())
176         m_scrollingCoordinator = ScrollingCoordinator::create(this);
177 
178     return m_scrollingCoordinator.get();
179 }
180 
mainThreadScrollingReasonsAsText()181 String Page::mainThreadScrollingReasonsAsText()
182 {
183     if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
184         return scrollingCoordinator->mainThreadScrollingReasonsAsText();
185 
186     return String();
187 }
188 
nonFastScrollableRects(const Frame * frame)189 PassRefPtr<ClientRectList> Page::nonFastScrollableRects(const Frame* frame)
190 {
191     if (Document* document = m_mainFrame->document())
192         document->updateLayout();
193 
194     Vector<IntRect> rects;
195     if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
196         rects = scrollingCoordinator->computeShouldHandleScrollGestureOnMainThreadRegion(frame, IntPoint()).rects();
197 
198     Vector<FloatQuad> quads(rects.size());
199     for (size_t i = 0; i < rects.size(); ++i)
200         quads[i] = FloatRect(rects[i]);
201     return ClientRectList::create(quads);
202 }
203 
setMainFrame(PassRefPtr<Frame> mainFrame)204 void Page::setMainFrame(PassRefPtr<Frame> mainFrame)
205 {
206     ASSERT(!m_mainFrame); // Should only be called during initialization
207     m_mainFrame = mainFrame;
208 }
209 
documentDetached(Document * document)210 void Page::documentDetached(Document* document)
211 {
212     m_pointerLockController->documentDetached(document);
213     m_contextMenuController->documentDetached(document);
214     if (m_validationMessageClient)
215         m_validationMessageClient->documentDetached(*document);
216     if (m_sharedWorkerRepositoryClient)
217         m_sharedWorkerRepositoryClient->documentDetached(document);
218 }
219 
openedByDOM() const220 bool Page::openedByDOM() const
221 {
222     return m_openedByDOM;
223 }
224 
setOpenedByDOM()225 void Page::setOpenedByDOM()
226 {
227     m_openedByDOM = true;
228 }
229 
clearPageGroup()230 void Page::clearPageGroup()
231 {
232     if (!m_group)
233         return;
234     m_group->removePage(this);
235     m_group = 0;
236 }
237 
setGroupType(PageGroupType type)238 void Page::setGroupType(PageGroupType type)
239 {
240     clearPageGroup();
241 
242     switch (type) {
243     case PrivatePageGroup:
244         m_group = PageGroup::create();
245         break;
246     case SharedPageGroup:
247         m_group = PageGroup::sharedGroup();
248         break;
249     }
250 
251     m_group->addPage(this);
252 }
253 
scheduleForcedStyleRecalcForAllPages()254 void Page::scheduleForcedStyleRecalcForAllPages()
255 {
256     if (!allPages)
257         return;
258     HashSet<Page*>::iterator end = allPages->end();
259     for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it)
260         for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree().traverseNext())
261             frame->document()->setNeedsStyleRecalc();
262 }
263 
setNeedsRecalcStyleInAllFrames()264 void Page::setNeedsRecalcStyleInAllFrames()
265 {
266     for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext())
267         frame->document()->styleResolverChanged(RecalcStyleDeferred);
268 }
269 
refreshPlugins(bool reload)270 void Page::refreshPlugins(bool reload)
271 {
272     if (!allPages)
273         return;
274 
275     PluginData::refresh();
276 
277     Vector<RefPtr<Frame> > framesNeedingReload;
278 
279     HashSet<Page*>::iterator end = allPages->end();
280     for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) {
281         Page* page = *it;
282 
283         // Clear out the page's plug-in data.
284         if (page->m_pluginData)
285             page->m_pluginData = 0;
286 
287         if (!reload)
288             continue;
289 
290         for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree().traverseNext()) {
291             if (frame->document()->containsPlugins())
292                 framesNeedingReload.append(frame);
293         }
294     }
295 
296     for (size_t i = 0; i < framesNeedingReload.size(); ++i)
297         framesNeedingReload[i]->loader().reload();
298 }
299 
pluginData() const300 PluginData* Page::pluginData() const
301 {
302     if (!mainFrame()->loader().allowPlugins(NotAboutToInstantiatePlugin))
303         return 0;
304     if (!m_pluginData)
305         m_pluginData = PluginData::create(this);
306     return m_pluginData.get();
307 }
308 
incrementFrame(Frame * curr,bool forward,bool wrapFlag)309 static Frame* incrementFrame(Frame* curr, bool forward, bool wrapFlag)
310 {
311     return forward
312         ? curr->tree().traverseNextWithWrap(wrapFlag)
313         : curr->tree().traversePreviousWithWrap(wrapFlag);
314 }
315 
unmarkAllTextMatches()316 void Page::unmarkAllTextMatches()
317 {
318     if (!mainFrame())
319         return;
320 
321     Frame* frame = mainFrame();
322     do {
323         frame->document()->markers()->removeMarkers(DocumentMarker::TextMatch);
324         frame = incrementFrame(frame, true, false);
325     } while (frame);
326 }
327 
setDefersLoading(bool defers)328 void Page::setDefersLoading(bool defers)
329 {
330     if (defers == m_defersLoading)
331         return;
332 
333     m_defersLoading = defers;
334     m_historyController->setDefersLoading(defers);
335     for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext())
336         frame->loader().setDefersLoading(defers);
337 }
338 
setPageScaleFactor(float scale,const IntPoint & origin)339 void Page::setPageScaleFactor(float scale, const IntPoint& origin)
340 {
341     FrameView* view = mainFrame()->view();
342 
343     if (scale != m_pageScaleFactor) {
344         m_pageScaleFactor = scale;
345 
346         if (view)
347             view->setVisibleContentScaleFactor(scale);
348 
349         mainFrame()->deviceOrPageScaleFactorChanged();
350         m_chrome->client().deviceOrPageScaleFactorChanged();
351 
352         if (view)
353             view->setViewportConstrainedObjectsNeedLayout();
354     }
355 
356     if (view && view->scrollPosition() != origin)
357         view->notifyScrollPositionChanged(origin);
358 }
359 
setDeviceScaleFactor(float scaleFactor)360 void Page::setDeviceScaleFactor(float scaleFactor)
361 {
362     if (m_deviceScaleFactor == scaleFactor)
363         return;
364 
365     m_deviceScaleFactor = scaleFactor;
366     setNeedsRecalcStyleInAllFrames();
367 
368     if (mainFrame()) {
369         mainFrame()->deviceOrPageScaleFactorChanged();
370         m_chrome->client().deviceOrPageScaleFactorChanged();
371     }
372 }
373 
setPagination(const Pagination & pagination)374 void Page::setPagination(const Pagination& pagination)
375 {
376     if (m_pagination == pagination)
377         return;
378 
379     m_pagination = pagination;
380 
381     setNeedsRecalcStyleInAllFrames();
382 }
383 
allVisitedStateChanged(PageGroup * group)384 void Page::allVisitedStateChanged(PageGroup* group)
385 {
386     ASSERT(group);
387     if (!allPages)
388         return;
389 
390     HashSet<Page*>::iterator pagesEnd = allPages->end();
391     for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
392         Page* page = *it;
393         if (page->m_group != group)
394             continue;
395         for (Frame* frame = page->m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
396             frame->document()->visitedLinkState().invalidateStyleForAllLinks();
397     }
398 }
399 
visitedStateChanged(PageGroup * group,LinkHash linkHash)400 void Page::visitedStateChanged(PageGroup* group, LinkHash linkHash)
401 {
402     ASSERT(group);
403     if (!allPages)
404         return;
405 
406     HashSet<Page*>::iterator pagesEnd = allPages->end();
407     for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
408         Page* page = *it;
409         if (page->m_group != group)
410             continue;
411         for (Frame* frame = page->m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
412             frame->document()->visitedLinkState().invalidateStyleForLink(linkHash);
413     }
414 }
415 
sessionStorage(bool optionalCreate)416 StorageNamespace* Page::sessionStorage(bool optionalCreate)
417 {
418     if (!m_sessionStorage && optionalCreate)
419         m_sessionStorage = StorageNamespace::sessionStorageNamespace(this);
420     return m_sessionStorage.get();
421 }
422 
setTimerAlignmentInterval(double interval)423 void Page::setTimerAlignmentInterval(double interval)
424 {
425     if (interval == m_timerAlignmentInterval)
426         return;
427 
428     m_timerAlignmentInterval = interval;
429     for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNextWithWrap(false)) {
430         if (frame->document())
431             frame->document()->didChangeTimerAlignmentInterval();
432     }
433 }
434 
timerAlignmentInterval() const435 double Page::timerAlignmentInterval() const
436 {
437     return m_timerAlignmentInterval;
438 }
439 
440 #if !ASSERT_DISABLED
checkSubframeCountConsistency() const441 void Page::checkSubframeCountConsistency() const
442 {
443     ASSERT(m_subframeCount >= 0);
444 
445     int subframeCount = 0;
446     for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext())
447         ++subframeCount;
448 
449     ASSERT(m_subframeCount + 1 == subframeCount);
450 }
451 #endif
452 
setVisibilityState(PageVisibilityState visibilityState,bool isInitialState)453 void Page::setVisibilityState(PageVisibilityState visibilityState, bool isInitialState)
454 {
455     if (m_visibilityState == visibilityState)
456         return;
457     m_visibilityState = visibilityState;
458 
459     if (visibilityState == WebCore::PageVisibilityStateHidden)
460         setTimerAlignmentInterval(DOMTimer::hiddenPageAlignmentInterval());
461     else
462         setTimerAlignmentInterval(DOMTimer::visiblePageAlignmentInterval());
463 
464     if (!isInitialState)
465         lifecycleNotifier().notifyPageVisibilityChanged();
466 
467     if (!isInitialState && m_mainFrame)
468         m_mainFrame->dispatchVisibilityStateChangeEvent();
469 }
470 
visibilityState() const471 PageVisibilityState Page::visibilityState() const
472 {
473     return m_visibilityState;
474 }
475 
addMultisamplingChangedObserver(MultisamplingChangedObserver * observer)476 void Page::addMultisamplingChangedObserver(MultisamplingChangedObserver* observer)
477 {
478     m_multisamplingChangedObservers.add(observer);
479 }
480 
removeMultisamplingChangedObserver(MultisamplingChangedObserver * observer)481 void Page::removeMultisamplingChangedObserver(MultisamplingChangedObserver* observer)
482 {
483     m_multisamplingChangedObservers.remove(observer);
484 }
485 
settingsChanged(SettingsDelegate::ChangeType changeType)486 void Page::settingsChanged(SettingsDelegate::ChangeType changeType)
487 {
488     switch (changeType) {
489     case SettingsDelegate::StyleChange:
490         setNeedsRecalcStyleInAllFrames();
491         break;
492     case SettingsDelegate::ViewportDescriptionChange:
493         if (mainFrame())
494             mainFrame()->document()->updateViewportDescription();
495         break;
496     case SettingsDelegate::MediaTypeChange:
497         m_mainFrame->view()->setMediaType(settings().mediaTypeOverride());
498         setNeedsRecalcStyleInAllFrames();
499         break;
500     case SettingsDelegate::DNSPrefetchingChange:
501         for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext())
502             frame->document()->initDNSPrefetch();
503         break;
504     case SettingsDelegate::MultisamplingChange: {
505         HashSet<MultisamplingChangedObserver*>::iterator stop = m_multisamplingChangedObservers.end();
506         for (HashSet<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             frame->document()->fetcher()->setImagesEnabled(settings().imagesEnabled());
513             frame->document()->fetcher()->setAutoLoadImages(settings().loadsImagesAutomatically());
514         }
515         break;
516     case SettingsDelegate::TextAutosizingChange:
517         // FIXME: I wonder if this needs to traverse frames like in WebViewImpl::resize, or whether there is only one document per Settings instance?
518         for (Frame* frame = mainFrame(); frame; frame = frame->tree().traverseNext()) {
519             TextAutosizer* textAutosizer = frame->document()->textAutosizer();
520             if (textAutosizer)
521                 textAutosizer->recalculateMultipliers();
522         }
523         setNeedsRecalcStyleInAllFrames();
524         break;
525     }
526 }
527 
didCommitLoad(Frame * frame)528 void Page::didCommitLoad(Frame* frame)
529 {
530     lifecycleNotifier().notifyDidCommitLoad(frame);
531     if (m_mainFrame == frame)
532         useCounter().didCommitLoad();
533 }
534 
lifecycleNotifier()535 PageLifecycleNotifier& Page::lifecycleNotifier()
536 {
537     return static_cast<PageLifecycleNotifier&>(LifecycleContext<Page>::lifecycleNotifier());
538 }
539 
createLifecycleNotifier()540 PassOwnPtr<LifecycleNotifier<Page> > Page::createLifecycleNotifier()
541 {
542     return PageLifecycleNotifier::create(this);
543 }
544 
PageClients()545 Page::PageClients::PageClients()
546     : chromeClient(0)
547     , contextMenuClient(0)
548     , editorClient(0)
549     , dragClient(0)
550     , inspectorClient(0)
551     , backForwardClient(0)
552     , spellCheckerClient(0)
553 {
554 }
555 
~PageClients()556 Page::PageClients::~PageClients()
557 {
558 }
559 
560 } // namespace WebCore
561