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