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