tizen beta release
[framework/web/webkit-efl.git] / Source / WebCore / page / Page.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 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 "Page.h"
22
23 #include "BackForwardController.h"
24 #include "BackForwardList.h"
25 #include "Base64.h"
26 #include "CSSStyleSelector.h"
27 #include "Chrome.h"
28 #include "ChromeClient.h"
29 #include "ContextMenuClient.h"
30 #include "ContextMenuController.h"
31 #include "DOMWindow.h"
32 #include "DeviceMotionController.h"
33 #include "DeviceOrientationController.h"
34 #include "DocumentMarkerController.h"
35 #include "DragController.h"
36 #include "EditorClient.h"
37 #include "Event.h"
38 #include "EventNames.h"
39 #include "ExceptionCode.h"
40 #include "FileSystem.h"
41 #include "FocusController.h"
42 #include "Frame.h"
43 #include "FrameLoader.h"
44 #include "FrameLoaderClient.h"
45 #include "FrameSelection.h"
46 #include "FrameTree.h"
47 #include "FrameView.h"
48 #include "HTMLElement.h"
49 #include "HistoryItem.h"
50 #include "InspectorController.h"
51 #include "InspectorInstrumentation.h"
52 #include "Logging.h"
53 #include "MediaCanStartListener.h"
54 #include "Navigator.h"
55 #include "NetworkStateNotifier.h"
56 #include "NotificationController.h"
57 #include "NotificationPresenter.h"
58 #include "PageGroup.h"
59 #include "PluginData.h"
60 #include "PluginView.h"
61 #include "PluginViewBase.h"
62 #include "ProgressTracker.h"
63 #include "RenderTheme.h"
64 #include "RenderView.h"
65 #include "RenderWidget.h"
66 #include "RuntimeEnabledFeatures.h"
67 #include "SchemeRegistry.h"
68 #include "Settings.h"
69 #include "SharedBuffer.h"
70 #include "SpeechInput.h"
71 #include "SpeechInputClient.h"
72 #include "StorageArea.h"
73 #include "StorageNamespace.h"
74 #include "TextResourceDecoder.h"
75 #include "Widget.h"
76 #include <wtf/HashMap.h>
77 #include <wtf/RefCountedLeakCounter.h>
78 #include <wtf/StdLibExtras.h>
79 #include <wtf/text/StringHash.h>
80
81 #if ENABLE(CLIENT_BASED_GEOLOCATION)
82 #include "GeolocationController.h"
83 #endif
84
85 #if ENABLE(MEDIA_STREAM)
86 #include "UserMediaClient.h"
87 #endif
88
89 namespace WebCore {
90
91 static HashSet<Page*>* allPages;
92
93 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, pageCounter, ("Page"));
94
95 static void networkStateChanged()
96 {
97     Vector<RefPtr<Frame> > frames;
98     
99     // Get all the frames of all the pages in all the page groups
100     HashSet<Page*>::iterator end = allPages->end();
101     for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) {
102         for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext())
103             frames.append(frame);
104         InspectorInstrumentation::networkStateChanged(*it);
105     }
106
107     AtomicString eventName = networkStateNotifier().onLine() ? eventNames().onlineEvent : eventNames().offlineEvent;
108     for (unsigned i = 0; i < frames.size(); i++)
109         frames[i]->document()->dispatchWindowEvent(Event::create(eventName, false, false));
110 }
111
112 float deviceScaleFactor(Frame* frame)
113 {
114     if (!frame)
115         return 1;
116     Page* page = frame->page();
117     if (!page)
118         return 1;
119     return page->deviceScaleFactor();
120 }
121
122 Page::Page(PageClients& pageClients)
123     : m_chrome(adoptPtr(new Chrome(this, pageClients.chromeClient)))
124     , m_dragCaretController(adoptPtr(new DragCaretController))
125 #if ENABLE(DRAG_SUPPORT)
126     , m_dragController(adoptPtr(new DragController(this, pageClients.dragClient)))
127 #endif
128     , m_focusController(adoptPtr(new FocusController(this)))
129 #if ENABLE(CONTEXT_MENUS)
130     , m_contextMenuController(adoptPtr(new ContextMenuController(this, pageClients.contextMenuClient)))
131 #endif
132 #if ENABLE(INSPECTOR)
133     , m_inspectorController(adoptPtr(new InspectorController(this, pageClients.inspectorClient)))
134 #endif
135 #if ENABLE(CLIENT_BASED_GEOLOCATION)
136     , m_geolocationController(adoptPtr(new GeolocationController(this, pageClients.geolocationClient)))
137 #endif
138 #if ENABLE(DEVICE_ORIENTATION)
139     , m_deviceMotionController(RuntimeEnabledFeatures::deviceMotionEnabled() ? adoptPtr(new DeviceMotionController(pageClients.deviceMotionClient)) : nullptr)
140     , m_deviceOrientationController(RuntimeEnabledFeatures::deviceOrientationEnabled() ? adoptPtr(new DeviceOrientationController(this, pageClients.deviceOrientationClient)) : nullptr)
141 #endif
142 #if ENABLE(NOTIFICATIONS)
143     , m_notificationController(adoptPtr(new NotificationController(this, pageClients.notificationClient)))
144 #endif
145 #if ENABLE(INPUT_SPEECH)
146     , m_speechInputClient(pageClients.speechInputClient)
147 #endif
148 #if ENABLE(MEDIA_STREAM)
149     , m_userMediaClient(pageClients.userMediaClient)
150 #endif
151     , m_settings(adoptPtr(new Settings(this)))
152     , m_progress(adoptPtr(new ProgressTracker))
153     , m_backForwardController(adoptPtr(new BackForwardController(this, pageClients.backForwardClient)))
154     , m_theme(RenderTheme::themeForPage(this))
155     , m_editorClient(pageClients.editorClient)
156     , m_frameCount(0)
157     , m_openedByDOM(false)
158     , m_tabKeyCyclesThroughElements(true)
159     , m_defersLoading(false)
160     , m_inLowQualityInterpolationMode(false)
161     , m_cookieEnabled(true)
162     , m_areMemoryCacheClientCallsEnabled(true)
163     , m_mediaVolume(1)
164     , m_pageScaleFactor(1)
165     , m_deviceScaleFactor(1)
166     , m_javaScriptURLsAreAllowed(true)
167     , m_didLoadUserStyleSheet(false)
168     , m_userStyleSheetModificationTime(0)
169     , m_group(0)
170     , m_debugger(0)
171     , m_customHTMLTokenizerTimeDelay(-1)
172     , m_customHTMLTokenizerChunkSize(-1)
173     , m_canStartMedia(true)
174     , m_viewMode(ViewModeWindowed)
175     , m_minimumTimerInterval(Settings::defaultMinDOMTimerInterval())
176 #if ENABLE(TIZEN_JS_PERMISSION_CHECKER)
177     , m_deferStatus(RESUMED)
178     , m_deferrer(0)
179 #endif
180     , m_isEditable(false)
181 #if ENABLE(PAGE_VISIBILITY_API)
182     , m_visibilityState(PageVisibilityStateVisible)
183 #endif
184     , m_displayID(0)
185 {
186     if (!allPages) {
187         allPages = new HashSet<Page*>;
188         
189         networkStateNotifier().setNetworkStateChangedFunction(networkStateChanged);
190     }
191
192     ASSERT(!allPages->contains(this));
193     allPages->add(this);
194
195 #ifndef NDEBUG
196     pageCounter.increment();
197 #endif
198 }
199
200 Page::~Page()
201 {
202 #if ENABLE(TIZEN_JS_PERMISSION_CHECKER)
203     if (m_deferStatus != SUSPENDED)
204         delete m_deferrer;
205 #endif
206     m_mainFrame->setView(0);
207     setGroupName(String());
208     allPages->remove(this);
209     
210     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
211         frame->pageDestroyed();
212
213     if (m_scrollableAreaSet) {
214         ScrollableAreaSet::const_iterator end = m_scrollableAreaSet->end(); 
215         for (ScrollableAreaSet::const_iterator it = m_scrollableAreaSet->begin(); it != end; ++it)
216             (*it)->disconnectFromPage();
217     }
218
219     m_editorClient->pageDestroyed();
220
221 #if ENABLE(INSPECTOR)
222     m_inspectorController->inspectedPageDestroyed();
223 #endif
224
225 #if ENABLE(MEDIA_STREAM)
226     if (m_userMediaClient)
227         m_userMediaClient->pageDestroyed();
228 #endif
229
230     backForward()->close();
231
232 #ifndef NDEBUG
233     pageCounter.decrement();
234 #endif
235 }
236
237 struct ViewModeInfo {
238     const char* name;
239     Page::ViewMode type;
240 };
241 static const int viewModeMapSize = 5;
242 static ViewModeInfo viewModeMap[viewModeMapSize] = {
243     {"windowed", Page::ViewModeWindowed},
244     {"floating", Page::ViewModeFloating},
245     {"fullscreen", Page::ViewModeFullscreen},
246     {"maximized", Page::ViewModeMaximized},
247     {"minimized", Page::ViewModeMinimized}
248 };
249
250 Page::ViewMode Page::stringToViewMode(const String& text)
251 {
252     for (int i = 0; i < viewModeMapSize; ++i) {
253         if (text == viewModeMap[i].name)
254             return viewModeMap[i].type;
255     }
256     return Page::ViewModeInvalid;
257 }
258
259 void Page::setViewMode(ViewMode viewMode)
260 {
261     if (viewMode == m_viewMode || viewMode == ViewModeInvalid)
262         return;
263
264     m_viewMode = viewMode;
265
266     if (!m_mainFrame)
267         return;
268
269     if (m_mainFrame->view())
270         m_mainFrame->view()->forceLayout();
271
272     if (m_mainFrame->document())
273         m_mainFrame->document()->styleSelectorChanged(RecalcStyleImmediately);
274 }
275
276 void Page::setMainFrame(PassRefPtr<Frame> mainFrame)
277 {
278     ASSERT(!m_mainFrame); // Should only be called during initialization
279     m_mainFrame = mainFrame;
280 }
281
282 bool Page::openedByDOM() const
283 {
284     return m_openedByDOM;
285 }
286
287 void Page::setOpenedByDOM()
288 {
289     m_openedByDOM = true;
290 }
291
292 BackForwardList* Page::backForwardList() const
293 {
294     return m_backForwardController->client();
295 }
296
297 bool Page::goBack()
298 {
299     HistoryItem* item = backForward()->backItem();
300     
301     if (item) {
302         goToItem(item, FrameLoadTypeBack);
303         return true;
304     }
305     return false;
306 }
307
308 bool Page::goForward()
309 {
310     HistoryItem* item = backForward()->forwardItem();
311     
312     if (item) {
313         goToItem(item, FrameLoadTypeForward);
314         return true;
315     }
316     return false;
317 }
318
319 bool Page::canGoBackOrForward(int distance) const
320 {
321     if (distance == 0)
322         return true;
323     if (distance > 0 && distance <= backForward()->forwardCount())
324         return true;
325     if (distance < 0 && -distance <= backForward()->backCount())
326         return true;
327     return false;
328 }
329
330 void Page::goBackOrForward(int distance)
331 {
332     if (distance == 0)
333         return;
334
335     HistoryItem* item = backForward()->itemAtIndex(distance);
336     if (!item) {
337         if (distance > 0) {
338             if (int forwardCount = backForward()->forwardCount()) 
339                 item = backForward()->itemAtIndex(forwardCount);
340         } else {
341             if (int backCount = backForward()->backCount())
342                 item = backForward()->itemAtIndex(-backCount);
343         }
344     }
345
346     ASSERT(item);
347     if (!item)
348         return;
349
350     goToItem(item, FrameLoadTypeIndexedBackForward);
351 }
352
353 void Page::goToItem(HistoryItem* item, FrameLoadType type)
354 {
355     // stopAllLoaders may end up running onload handlers, which could cause further history traversals that may lead to the passed in HistoryItem
356     // being deref()-ed. Make sure we can still use it with HistoryController::goToItem later.
357     RefPtr<HistoryItem> protector(item);
358
359     if (m_mainFrame->loader()->history()->shouldStopLoadingForHistoryItem(item))
360         m_mainFrame->loader()->stopAllLoaders();
361
362     m_mainFrame->loader()->history()->goToItem(item, type);
363 }
364
365 int Page::getHistoryLength()
366 {
367     return backForward()->backCount() + 1 + backForward()->forwardCount();
368 }
369
370 void Page::setGroupName(const String& name)
371 {
372     if (m_group && !m_group->name().isEmpty()) {
373         ASSERT(m_group != m_singlePageGroup.get());
374         ASSERT(!m_singlePageGroup);
375         m_group->removePage(this);
376     }
377
378     if (name.isEmpty())
379         m_group = m_singlePageGroup.get();
380     else {
381         m_singlePageGroup.clear();
382         m_group = PageGroup::pageGroup(name);
383         m_group->addPage(this);
384     }
385 }
386
387 const String& Page::groupName() const
388 {
389     DEFINE_STATIC_LOCAL(String, nullString, ());
390     return m_group ? m_group->name() : nullString;
391 }
392
393 void Page::initGroup()
394 {
395     ASSERT(!m_singlePageGroup);
396     ASSERT(!m_group);
397     m_singlePageGroup = adoptPtr(new PageGroup(this));
398     m_group = m_singlePageGroup.get();
399 }
400
401 void Page::scheduleForcedStyleRecalcForAllPages()
402 {
403     if (!allPages)
404         return;
405     HashSet<Page*>::iterator end = allPages->end();
406     for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it)
407         for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext())
408             frame->document()->scheduleForcedStyleRecalc();
409 }
410
411 void Page::setNeedsRecalcStyleInAllFrames()
412 {
413     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
414         frame->document()->styleSelectorChanged(DeferRecalcStyle);
415 }
416
417 void Page::updateViewportArguments()
418 {
419     if (!mainFrame() || !mainFrame()->document())
420         return;
421
422     m_viewportArguments = mainFrame()->document()->viewportArguments();
423     chrome()->dispatchViewportPropertiesDidChange(m_viewportArguments);
424 }
425
426 void Page::refreshPlugins(bool reload)
427 {
428     if (!allPages)
429         return;
430
431     PluginData::refresh();
432
433     Vector<RefPtr<Frame> > framesNeedingReload;
434
435     HashSet<Page*>::iterator end = allPages->end();
436     for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) {
437         Page* page = *it;
438         
439         // Clear out the page's plug-in data.
440         if (page->m_pluginData)
441             page->m_pluginData = 0;
442
443         if (!reload)
444             continue;
445         
446         for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
447             if (frame->loader()->subframeLoader()->containsPlugins())
448                 framesNeedingReload.append(frame);
449         }
450     }
451
452     for (size_t i = 0; i < framesNeedingReload.size(); ++i)
453         framesNeedingReload[i]->loader()->reload();
454 }
455
456 PluginData* Page::pluginData() const
457 {
458     if (!mainFrame()->loader()->subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin))
459         return 0;
460     if (!m_pluginData)
461         m_pluginData = PluginData::create(this);
462     return m_pluginData.get();
463 }
464
465 inline MediaCanStartListener* Page::takeAnyMediaCanStartListener()
466 {
467     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
468         if (MediaCanStartListener* listener = frame->document()->takeAnyMediaCanStartListener())
469             return listener;
470     }
471     return 0;
472 }
473
474 void Page::setCanStartMedia(bool canStartMedia)
475 {
476     if (m_canStartMedia == canStartMedia)
477         return;
478
479     m_canStartMedia = canStartMedia;
480
481     while (m_canStartMedia) {
482         MediaCanStartListener* listener = takeAnyMediaCanStartListener();
483         if (!listener)
484             break;
485         listener->mediaCanStart();
486     }
487 }
488
489 static Frame* incrementFrame(Frame* curr, bool forward, bool wrapFlag)
490 {
491     return forward
492         ? curr->tree()->traverseNextWithWrap(wrapFlag)
493         : curr->tree()->traversePreviousWithWrap(wrapFlag);
494 }
495
496 bool Page::findString(const String& target, TextCaseSensitivity caseSensitivity, FindDirection direction, bool shouldWrap)
497 {
498     return findString(target, (caseSensitivity == TextCaseInsensitive ? CaseInsensitive : 0) | (direction == FindDirectionBackward ? Backwards : 0) | (shouldWrap ? WrapAround : 0));
499 }
500
501 bool Page::findString(const String& target, FindOptions options)
502 {
503     if (target.isEmpty() || !mainFrame())
504         return false;
505
506     bool shouldWrap = options & WrapAround;
507     Frame* frame = focusController()->focusedOrMainFrame();
508     Frame* startFrame = frame;
509     do {
510         if (frame->editor()->findString(target, (options & ~WrapAround) | StartInSelection)) {
511             if (frame != startFrame)
512                 startFrame->selection()->clear();
513             focusController()->setFocusedFrame(frame);
514             return true;
515         }
516         frame = incrementFrame(frame, !(options & Backwards), shouldWrap);
517     } while (frame && frame != startFrame);
518
519     // Search contents of startFrame, on the other side of the selection that we did earlier.
520     // We cheat a bit and just research with wrap on
521     if (shouldWrap && !startFrame->selection()->isNone()) {
522         bool found = startFrame->editor()->findString(target, options | WrapAround | StartInSelection);
523         focusController()->setFocusedFrame(frame);
524         return found;
525     }
526
527     return false;
528 }
529
530 PassRefPtr<Range> Page::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
531 {
532     if (target.isEmpty() || !mainFrame())
533         return 0;
534
535     if (referenceRange && referenceRange->ownerDocument()->page() != this)
536         return 0;
537
538     bool shouldWrap = options & WrapAround;
539     Frame* frame = referenceRange ? referenceRange->ownerDocument()->frame() : mainFrame();
540     Frame* startFrame = frame;
541     do {
542         if (RefPtr<Range> resultRange = frame->editor()->rangeOfString(target, frame == startFrame ? referenceRange : 0, options & ~WrapAround))
543             return resultRange.release();
544
545         frame = incrementFrame(frame, !(options & Backwards), shouldWrap);
546     } while (frame && frame != startFrame);
547
548     // Search contents of startFrame, on the other side of the reference range that we did earlier.
549     // We cheat a bit and just search again with wrap on.
550     if (shouldWrap && referenceRange) {
551         if (RefPtr<Range> resultRange = startFrame->editor()->rangeOfString(target, referenceRange, options | WrapAround | StartInSelection))
552             return resultRange.release();
553     }
554
555     return 0;
556 }
557
558 unsigned int Page::markAllMatchesForText(const String& target, TextCaseSensitivity caseSensitivity, bool shouldHighlight, unsigned limit)
559 {
560     return markAllMatchesForText(target, caseSensitivity == TextCaseInsensitive ? CaseInsensitive : 0, shouldHighlight, limit);
561 }
562
563 unsigned int Page::markAllMatchesForText(const String& target, FindOptions options, bool shouldHighlight, unsigned limit)
564 {
565     if (target.isEmpty() || !mainFrame())
566         return 0;
567
568     unsigned matches = 0;
569
570     Frame* frame = mainFrame();
571     do {
572         frame->editor()->setMarkedTextMatchesAreHighlighted(shouldHighlight);
573         matches += frame->editor()->countMatchesForText(target, options, limit ? (limit - matches) : 0, true);
574         frame = incrementFrame(frame, true, false);
575     } while (frame);
576
577     return matches;
578 }
579
580 void Page::unmarkAllTextMatches()
581 {
582     if (!mainFrame())
583         return;
584
585     Frame* frame = mainFrame();
586     do {
587         frame->document()->markers()->removeMarkers(DocumentMarker::TextMatch);
588         frame = incrementFrame(frame, true, false);
589     } while (frame);
590 }
591
592 const VisibleSelection& Page::selection() const
593 {
594     return focusController()->focusedOrMainFrame()->selection()->selection();
595 }
596
597 void Page::setDefersLoading(bool defers)
598 {
599     if (!m_settings->loadDeferringEnabled())
600         return;
601
602     if (defers == m_defersLoading)
603         return;
604
605     m_defersLoading = defers;
606     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
607         frame->loader()->setDefersLoading(defers);
608 }
609
610 void Page::clearUndoRedoOperations()
611 {
612     m_editorClient->clearUndoRedoOperations();
613 }
614
615 bool Page::inLowQualityImageInterpolationMode() const
616 {
617     return m_inLowQualityInterpolationMode;
618 }
619
620 void Page::setInLowQualityImageInterpolationMode(bool mode)
621 {
622     m_inLowQualityInterpolationMode = mode;
623 }
624
625 void Page::setMediaVolume(float volume)
626 {
627     if (volume < 0 || volume > 1)
628         return;
629
630     if (m_mediaVolume == volume)
631         return;
632
633     m_mediaVolume = volume;
634     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
635         frame->document()->mediaVolumeDidChange();
636     }
637 }
638
639 void Page::setPageScaleFactor(float scale, const IntPoint& origin)
640 {
641     if (scale == m_pageScaleFactor)
642         return;
643
644     Document* document = mainFrame()->document();
645
646     m_pageScaleFactor = scale;
647
648     if (document->renderer())
649         document->renderer()->setNeedsLayout(true);
650
651     document->recalcStyle(Node::Force);
652
653 #if USE(ACCELERATED_COMPOSITING)
654     mainFrame()->deviceOrPageScaleFactorChanged();
655 #endif
656
657     if (FrameView* view = document->view()) {
658         if (view->scrollPosition() != origin) {
659           if (document->renderer() && document->renderer()->needsLayout() && view->didFirstLayout())
660               view->layout();
661           view->setScrollPosition(origin);
662         }
663     }
664 }
665
666
667 void Page::setDeviceScaleFactor(float scaleFactor)
668 {
669     if (m_deviceScaleFactor == scaleFactor)
670         return;
671
672     m_deviceScaleFactor = scaleFactor;
673     setNeedsRecalcStyleInAllFrames();
674
675 #if USE(ACCELERATED_COMPOSITING)
676     if (mainFrame())
677         mainFrame()->deviceOrPageScaleFactorChanged();
678 #endif
679
680     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
681         frame->editor()->deviceScaleFactorChanged();
682
683     backForward()->markPagesForFullStyleRecalc();
684 }
685
686 void Page::setPagination(const Pagination& pagination)
687 {
688     if (m_pagination.mode == pagination.mode && m_pagination.gap == pagination.gap)
689         return;
690
691     m_pagination = pagination;
692
693     setNeedsRecalcStyleInAllFrames();
694     backForward()->markPagesForFullStyleRecalc();
695 }
696
697 unsigned Page::pageCount() const
698 {
699     if (m_pagination.mode == Pagination::Unpaginated)
700         return 0;
701
702     FrameView* frameView = mainFrame()->view();
703     if (!frameView->didFirstLayout())
704         return 0;
705
706     mainFrame()->view()->forceLayout();
707
708     RenderView* contentRenderer = mainFrame()->contentRenderer();
709     return contentRenderer->columnCount(contentRenderer->columnInfo());
710 }
711
712 void Page::didMoveOnscreen()
713 {
714     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
715         if (frame->view())
716             frame->view()->didMoveOnscreen();
717     }
718     
719     resumeScriptedAnimations();
720 }
721
722 void Page::willMoveOffscreen()
723 {
724     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
725         if (frame->view())
726             frame->view()->willMoveOffscreen();
727     }
728     
729     suspendScriptedAnimations();
730 }
731
732 void Page::windowScreenDidChange(PlatformDisplayID displayID)
733 {
734     m_displayID = displayID;
735     
736     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
737         if (frame->document())
738             frame->document()->windowScreenDidChange(displayID);
739     }
740 }
741
742 void Page::suspendScriptedAnimations()
743 {
744     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
745         if (frame->document())
746             frame->document()->suspendScriptedAnimationControllerCallbacks();
747     }
748 }
749
750 void Page::resumeScriptedAnimations()
751 {
752     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
753         if (frame->document())
754             frame->document()->resumeScriptedAnimationControllerCallbacks();
755     }
756 }
757
758 void Page::userStyleSheetLocationChanged()
759 {
760     // FIXME: Eventually we will move to a model of just being handed the sheet
761     // text instead of loading the URL ourselves.
762     KURL url = m_settings->userStyleSheetLocation();
763     
764     // Allow any local file URL scheme to be loaded.
765     if (SchemeRegistry::shouldTreatURLSchemeAsLocal(url.protocol()))
766         m_userStyleSheetPath = url.fileSystemPath();
767     else
768         m_userStyleSheetPath = String();
769
770     m_didLoadUserStyleSheet = false;
771     m_userStyleSheet = String();
772     m_userStyleSheetModificationTime = 0;
773
774     // Data URLs with base64-encoded UTF-8 style sheets are common. We can process them
775     // synchronously and avoid using a loader. 
776     if (url.protocolIsData() && url.string().startsWith("data:text/css;charset=utf-8;base64,")) {
777         m_didLoadUserStyleSheet = true;
778
779         Vector<char> styleSheetAsUTF8;
780         if (base64Decode(decodeURLEscapeSequences(url.string().substring(35)), styleSheetAsUTF8, IgnoreWhitespace))
781             m_userStyleSheet = String::fromUTF8(styleSheetAsUTF8.data(), styleSheetAsUTF8.size());
782     }
783
784     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
785         if (frame->document())
786             frame->document()->updatePageUserSheet();
787     }
788 }
789
790 const String& Page::userStyleSheet() const
791 {
792     if (m_userStyleSheetPath.isEmpty())
793         return m_userStyleSheet;
794
795     time_t modTime;
796     if (!getFileModificationTime(m_userStyleSheetPath, modTime)) {
797         // The stylesheet either doesn't exist, was just deleted, or is
798         // otherwise unreadable. If we've read the stylesheet before, we should
799         // throw away that data now as it no longer represents what's on disk.
800         m_userStyleSheet = String();
801         return m_userStyleSheet;
802     }
803
804     // If the stylesheet hasn't changed since the last time we read it, we can
805     // just return the old data.
806     if (m_didLoadUserStyleSheet && modTime <= m_userStyleSheetModificationTime)
807         return m_userStyleSheet;
808
809     m_didLoadUserStyleSheet = true;
810     m_userStyleSheet = String();
811     m_userStyleSheetModificationTime = modTime;
812
813     // FIXME: It would be better to load this asynchronously to avoid blocking
814     // the process, but we will first need to create an asynchronous loading
815     // mechanism that is not tied to a particular Frame. We will also have to
816     // determine what our behavior should be before the stylesheet is loaded
817     // and what should happen when it finishes loading, especially with respect
818     // to when the load event fires, when Document::close is called, and when
819     // layout/paint are allowed to happen.
820     RefPtr<SharedBuffer> data = SharedBuffer::createWithContentsOfFile(m_userStyleSheetPath);
821     if (!data)
822         return m_userStyleSheet;
823
824     RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/css");
825     m_userStyleSheet = decoder->decode(data->data(), data->size());
826     m_userStyleSheet += decoder->flush();
827
828     return m_userStyleSheet;
829 }
830
831 void Page::removeAllVisitedLinks()
832 {
833     if (!allPages)
834         return;
835     HashSet<PageGroup*> groups;
836     HashSet<Page*>::iterator pagesEnd = allPages->end();
837     for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
838         if (PageGroup* group = (*it)->groupPtr())
839             groups.add(group);
840     }
841     HashSet<PageGroup*>::iterator groupsEnd = groups.end();
842     for (HashSet<PageGroup*>::iterator it = groups.begin(); it != groupsEnd; ++it)
843         (*it)->removeVisitedLinks();
844 }
845
846 void Page::allVisitedStateChanged(PageGroup* group)
847 {
848     ASSERT(group);
849     if (!allPages)
850         return;
851
852     HashSet<Page*>::iterator pagesEnd = allPages->end();
853     for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
854         Page* page = *it;
855         if (page->m_group != group)
856             continue;
857         for (Frame* frame = page->m_mainFrame.get(); frame; frame = frame->tree()->traverseNext()) {
858             if (CSSStyleSelector* styleSelector = frame->document()->styleSelector())
859                 styleSelector->allVisitedStateChanged();
860         }
861     }
862 }
863
864 void Page::visitedStateChanged(PageGroup* group, LinkHash visitedLinkHash)
865 {
866     ASSERT(group);
867     if (!allPages)
868         return;
869
870     HashSet<Page*>::iterator pagesEnd = allPages->end();
871     for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
872         Page* page = *it;
873         if (page->m_group != group)
874             continue;
875         for (Frame* frame = page->m_mainFrame.get(); frame; frame = frame->tree()->traverseNext()) {
876             if (CSSStyleSelector* styleSelector = frame->document()->styleSelector())
877                 styleSelector->visitedStateChanged(visitedLinkHash);
878         }
879     }
880 }
881
882 void Page::setDebuggerForAllPages(JSC::Debugger* debugger)
883 {
884     ASSERT(allPages);
885
886     HashSet<Page*>::iterator end = allPages->end();
887     for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it)
888         (*it)->setDebugger(debugger);
889 }
890
891 void Page::setDebugger(JSC::Debugger* debugger)
892 {
893     if (m_debugger == debugger)
894         return;
895
896     m_debugger = debugger;
897
898     for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree()->traverseNext())
899         frame->script()->attachDebugger(m_debugger);
900 }
901
902 StorageNamespace* Page::sessionStorage(bool optionalCreate)
903 {
904     if (!m_sessionStorage && optionalCreate)
905         m_sessionStorage = StorageNamespace::sessionStorageNamespace(this, m_settings->sessionStorageQuota());
906
907     return m_sessionStorage.get();
908 }
909
910 void Page::setSessionStorage(PassRefPtr<StorageNamespace> newStorage)
911 {
912     m_sessionStorage = newStorage;
913 }
914
915 void Page::setCustomHTMLTokenizerTimeDelay(double customHTMLTokenizerTimeDelay)
916 {
917     if (customHTMLTokenizerTimeDelay < 0) {
918         m_customHTMLTokenizerTimeDelay = -1;
919         return;
920     }
921     m_customHTMLTokenizerTimeDelay = customHTMLTokenizerTimeDelay;
922 }
923
924 void Page::setCustomHTMLTokenizerChunkSize(int customHTMLTokenizerChunkSize)
925 {
926     if (customHTMLTokenizerChunkSize < 0) {
927         m_customHTMLTokenizerChunkSize = -1;
928         return;
929     }
930     m_customHTMLTokenizerChunkSize = customHTMLTokenizerChunkSize;
931 }
932
933 void Page::setMemoryCacheClientCallsEnabled(bool enabled)
934 {
935     if (m_areMemoryCacheClientCallsEnabled == enabled)
936         return;
937
938     m_areMemoryCacheClientCallsEnabled = enabled;
939     if (!enabled)
940         return;
941
942     for (RefPtr<Frame> frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
943         frame->loader()->tellClientAboutPastMemoryCacheLoads();
944 }
945
946 void Page::setJavaScriptURLsAreAllowed(bool areAllowed)
947 {
948     m_javaScriptURLsAreAllowed = areAllowed;
949 }
950
951 bool Page::javaScriptURLsAreAllowed() const
952 {
953     return m_javaScriptURLsAreAllowed;
954 }
955
956 void Page::setMinimumTimerInterval(double minimumTimerInterval)
957 {
958     double oldTimerInterval = m_minimumTimerInterval;
959     m_minimumTimerInterval = minimumTimerInterval;
960     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNextWithWrap(false)) {
961         if (frame->document())
962             frame->document()->adjustMinimumTimerInterval(oldTimerInterval);
963     }
964 }
965
966 double Page::minimumTimerInterval() const
967 {
968     return m_minimumTimerInterval;
969 }
970
971 #if ENABLE(INPUT_SPEECH)
972 SpeechInput* Page::speechInput()
973 {
974     ASSERT(m_speechInputClient);
975     if (!m_speechInput.get())
976         m_speechInput = adoptPtr(new SpeechInput(m_speechInputClient));
977     return m_speechInput.get();
978 }
979 #endif
980
981 void Page::dnsPrefetchingStateChanged()
982 {
983     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
984         frame->document()->initDNSPrefetch();
985 }
986
987 void Page::privateBrowsingStateChanged()
988 {
989     bool privateBrowsingEnabled = m_settings->privateBrowsingEnabled();
990
991     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
992         frame->document()->privateBrowsingStateDidChange();
993
994     // Collect the PluginViews in to a vector to ensure that action the plug-in takes
995     // from below privateBrowsingStateChanged does not affect their lifetime.
996     Vector<RefPtr<PluginViewBase>, 32> pluginViewBases;
997     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
998         FrameView* view = frame->view();
999         if (!view)
1000             return;
1001
1002         const HashSet<RefPtr<Widget> >* children = view->children();
1003         ASSERT(children);
1004
1005         HashSet<RefPtr<Widget> >::const_iterator end = children->end();
1006         for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
1007             Widget* widget = (*it).get();
1008             if (widget->isPluginViewBase())
1009                 pluginViewBases.append(static_cast<PluginViewBase*>(widget));
1010         }
1011     }
1012
1013     for (size_t i = 0; i < pluginViewBases.size(); ++i)
1014         pluginViewBases[i]->privateBrowsingStateChanged(privateBrowsingEnabled);
1015 }
1016
1017 void Page::addScrollableArea(ScrollableArea* scrollableArea)
1018 {
1019     if (!m_scrollableAreaSet)
1020         m_scrollableAreaSet = adoptPtr(new ScrollableAreaSet);
1021     m_scrollableAreaSet->add(scrollableArea);
1022 }
1023
1024 void Page::removeScrollableArea(ScrollableArea* scrollableArea)
1025 {
1026     if (!m_scrollableAreaSet)
1027         return;
1028     m_scrollableAreaSet->remove(scrollableArea);
1029 }
1030
1031 bool Page::containsScrollableArea(ScrollableArea* scrollableArea) const
1032 {
1033     if (!m_scrollableAreaSet)
1034         return false;
1035     return m_scrollableAreaSet->contains(scrollableArea);
1036 }
1037
1038 #if !ASSERT_DISABLED
1039 void Page::checkFrameCountConsistency() const
1040 {
1041     ASSERT(m_frameCount >= 0);
1042
1043     int frameCount = 0;
1044     for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
1045         ++frameCount;
1046
1047     ASSERT(m_frameCount + 1 == frameCount);
1048 }
1049 #endif
1050
1051 #if ENABLE(PAGE_VISIBILITY_API)
1052 void Page::setVisibilityState(PageVisibilityState visibilityState, bool isInitialState)
1053 {
1054     if (m_visibilityState == visibilityState)
1055         return;
1056     m_visibilityState = visibilityState;
1057
1058     if (!isInitialState && m_mainFrame)
1059         m_mainFrame->dispatchVisibilityStateChangeEvent();
1060 }
1061
1062 PageVisibilityState Page::visibilityState() const
1063 {
1064     return m_visibilityState;
1065 }
1066 #endif
1067
1068 Page::PageClients::PageClients()
1069     : chromeClient(0)
1070     , contextMenuClient(0)
1071     , editorClient(0)
1072     , dragClient(0)
1073     , inspectorClient(0)
1074     , geolocationClient(0)
1075     , deviceMotionClient(0)
1076     , deviceOrientationClient(0)
1077     , speechInputClient(0)
1078     , notificationClient(0)
1079     , userMediaClient(0)
1080 {
1081 }
1082
1083 Page::PageClients::~PageClients()
1084 {
1085 }
1086
1087 #if ENABLE(TIZEN_JS_PERMISSION_CHECKER)
1088 void Page::suspendJavaScript()
1089 {
1090     // Old deferrer could block different object then new one.
1091     // We need to "reblock" all active object once again.
1092     m_deferStatus = SUSPENDING;
1093     delete m_deferrer;
1094     m_deferrer = new PageGroupLoadDeferrer(this, true);
1095     m_deferStatus = SUSPENDED;
1096 }
1097
1098 void Page::resumeJavaScript()
1099 {
1100     if (m_deferStatus != SUSPENDED)
1101         return;
1102
1103     m_deferStatus = RESUMING;
1104     delete m_deferrer;
1105     m_deferrer = 0;
1106     m_deferStatus = RESUMED;
1107 }
1108 #endif
1109
1110 } // namespace WebCore