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