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