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