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