summaryrefslogtreecommitdiffstats
path: root/WebCore/page/Page.cpp
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
commit1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353 (patch)
tree4457a7306ea5acb43fe05bfe0973b1f7faf97ba2 /WebCore/page/Page.cpp
parent9364f22aed35e1a1e9d07c121510f80be3ab0502 (diff)
downloadexternal_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.zip
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.gz
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.bz2
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'WebCore/page/Page.cpp')
-rw-r--r--WebCore/page/Page.cpp317
1 files changed, 268 insertions, 49 deletions
diff --git a/WebCore/page/Page.cpp b/WebCore/page/Page.cpp
index efae3bf..3c573d6 100644
--- a/WebCore/page/Page.cpp
+++ b/WebCore/page/Page.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -24,8 +24,11 @@
#include "ChromeClient.h"
#include "ContextMenuClient.h"
#include "ContextMenuController.h"
+#include "CSSStyleSelector.h"
#include "EditorClient.h"
+#include "DOMWindow.h"
#include "DragController.h"
+#include "EventNames.h"
#include "FileSystem.h"
#include "FocusController.h"
#include "Frame.h"
@@ -35,6 +38,10 @@
#include "HistoryItem.h"
#include "InspectorController.h"
#include "Logging.h"
+#include "NetworkStateNotifier.h"
+#include "Navigator.h"
+#include "PageGroup.h"
+#include "PluginData.h"
#include "ProgressTracker.h"
#include "RenderWidget.h"
#include "SelectionController.h"
@@ -42,32 +49,58 @@
#include "StringHash.h"
#include "TextResourceDecoder.h"
#include "Widget.h"
+#include "ScriptController.h"
#include <kjs/collector.h>
-#include <kjs/JSLock.h>
+#include <runtime/JSLock.h>
#include <wtf/HashMap.h>
+#include <wtf/RefCountedLeakCounter.h>
-using namespace KJS;
+#if ENABLE(DOM_STORAGE)
+#include "LocalStorage.h"
+#include "SessionStorage.h"
+#include "StorageArea.h"
+#endif
+
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+#include "JavaScriptDebugServer.h"
+#endif
namespace WebCore {
static HashSet<Page*>* allPages;
-static HashMap<String, HashSet<Page*>*>* frameNamespaces;
#ifndef NDEBUG
-WTFLogChannel LogWebCorePageLeaks = { 0x00000000, "", WTFLogChannelOn };
-
-struct PageCounter {
- static int count;
- ~PageCounter()
- {
- if (count)
- LOG(WebCorePageLeaks, "LEAK: %d Page\n", count);
- }
-};
-int PageCounter::count = 0;
-static PageCounter pageCounter;
+static WTF::RefCountedLeakCounter pageCounter("Page");
#endif
+static void networkStateChanged()
+{
+ Vector<RefPtr<Frame> > frames;
+
+ // Get all the frames of all the pages in all the page groups
+ HashSet<Page*>::iterator end = allPages->end();
+ for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) {
+ for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext())
+ frames.append(frame);
+ }
+
+ AtomicString eventName = networkStateNotifier().onLine() ? eventNames().onlineEvent : eventNames().offlineEvent;
+
+ for (unsigned i = 0; i < frames.size(); i++) {
+ Document* document = frames[i]->document();
+
+ if (!document)
+ continue;
+
+ // If the document does not have a body the event should be dispatched to the document
+ EventTargetNode* eventTarget = document->body();
+ if (!eventTarget)
+ eventTarget = document;
+
+ eventTarget->dispatchEventForType(eventName, false, false);
+ }
+}
+
Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, EditorClient* editorClient, DragClient* dragClient, InspectorClient* inspectorClient)
: m_chrome(new Chrome(this, chromeClient))
, m_dragCaretController(new SelectionController(0, true))
@@ -77,26 +110,38 @@ Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, Edi
, m_inspectorController(new InspectorController(this, inspectorClient))
, m_settings(new Settings(this))
, m_progress(new ProgressTracker)
- , m_backForwardList(new BackForwardList(this))
+ , m_backForwardList(BackForwardList::create(this))
, m_editorClient(editorClient)
, m_frameCount(0)
, m_tabKeyCyclesThroughElements(true)
, m_defersLoading(false)
, m_inLowQualityInterpolationMode(false)
+ , m_cookieEnabled(true)
, m_parentInspectorController(0)
, m_didLoadUserStyleSheet(false)
, m_userStyleSheetModificationTime(0)
+ , m_group(0)
+ , m_debugger(0)
+ , m_pendingUnloadEventCount(0)
+ , m_pendingBeforeUnloadEventCount(0)
+ , m_customHTMLTokenizerTimeDelay(-1)
+ , m_customHTMLTokenizerChunkSize(-1)
{
if (!allPages) {
allPages = new HashSet<Page*>;
- setFocusRingColorChangeFunction(setNeedsReapplyStyles);
+
+ networkStateNotifier().setNetworkStateChangedFunction(networkStateChanged);
}
ASSERT(!allPages->contains(this));
allPages->add(this);
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+ JavaScriptDebugServer::shared().pageCreated(this);
+#endif
+
#ifndef NDEBUG
- ++PageCounter::count;
+ pageCounter.increment();
#endif
}
@@ -106,15 +151,20 @@ Page::~Page()
setGroupName(String());
allPages->remove(this);
- for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
+ for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
+ if (frame->document())
+ frame->document()->documentWillBecomeInactive();
frame->pageDestroyed();
+ }
m_editorClient->pageDestroyed();
- m_inspectorController->pageDestroyed();
+ if (m_parentInspectorController)
+ m_parentInspectorController->pageDestroyed();
+ m_inspectorController->inspectedPageDestroyed();
m_backForwardList->close();
#ifndef NDEBUG
- --PageCounter::count;
+ pageCounter.decrement();
// Cancel keepAlive timers, to ensure we release all Frames before exiting.
// It's safe to do this because we prohibit closing a Page while JavaScript
@@ -165,37 +215,33 @@ void Page::goToItem(HistoryItem* item, FrameLoadType type)
void Page::setGroupName(const String& name)
{
- if (frameNamespaces && !m_groupName.isEmpty()) {
- HashSet<Page*>* oldNamespace = frameNamespaces->get(m_groupName);
- if (oldNamespace) {
- oldNamespace->remove(this);
- if (oldNamespace->isEmpty()) {
- frameNamespaces->remove(m_groupName);
- delete oldNamespace;
- }
- }
+ if (m_group && !m_group->name().isEmpty()) {
+ ASSERT(m_group != m_singlePageGroup.get());
+ ASSERT(!m_singlePageGroup);
+ m_group->removePage(this);
}
- m_groupName = name;
- if (!name.isEmpty()) {
- if (!frameNamespaces)
- frameNamespaces = new HashMap<String, HashSet<Page*>*>;
- HashSet<Page*>* newNamespace = frameNamespaces->get(name);
- if (!newNamespace) {
- newNamespace = new HashSet<Page*>;
- frameNamespaces->add(name, newNamespace);
- }
- newNamespace->add(this);
+
+ if (name.isEmpty())
+ m_group = 0;
+ else {
+ m_singlePageGroup.clear();
+ m_group = PageGroup::pageGroup(name);
+ m_group->addPage(this);
}
}
-const HashSet<Page*>* Page::frameNamespace() const
+const String& Page::groupName() const
{
- return (frameNamespaces && !m_groupName.isEmpty()) ? frameNamespaces->get(m_groupName) : 0;
+ static String nullString;
+ return m_group ? m_group->name() : nullString;
}
-const HashSet<Page*>* Page::frameNamespace(const String& groupName)
+void Page::initGroup()
{
- return (frameNamespaces && !groupName.isEmpty()) ? frameNamespaces->get(groupName) : 0;
+ ASSERT(!m_singlePageGroup);
+ ASSERT(!m_group);
+ m_singlePageGroup.set(new PageGroup(this));
+ m_group = m_singlePageGroup.get();
}
void Page::setNeedsReapplyStyles()
@@ -208,6 +254,38 @@ void Page::setNeedsReapplyStyles()
frame->setNeedsReapplyStyles();
}
+void Page::refreshPlugins(bool reload)
+{
+ if (!allPages)
+ return;
+
+ PluginData::refresh();
+
+ Vector<RefPtr<Frame> > framesNeedingReload;
+
+ HashSet<Page*>::iterator end = allPages->end();
+ for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) {
+ (*it)->m_pluginData = 0;
+
+ if (reload) {
+ for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
+ if (frame->loader()->containsPlugins())
+ framesNeedingReload.append(frame);
+ }
+ }
+ }
+
+ for (size_t i = 0; i < framesNeedingReload.size(); ++i)
+ framesNeedingReload[i]->loader()->reload();
+}
+
+PluginData* Page::pluginData() const
+{
+ if (!m_pluginData)
+ m_pluginData = PluginData::create(this);
+ return m_pluginData.get();
+}
+
static Frame* incrementFrame(Frame* curr, bool forward, bool wrapFlag)
{
return forward
@@ -225,7 +303,7 @@ bool Page::findString(const String& target, TextCaseSensitivity caseSensitivity,
do {
if (frame->findString(target, direction == FindDirectionForward, caseSensitivity == TextCaseSensitive, false, true)) {
if (frame != startFrame)
- startFrame->selectionController()->clear();
+ startFrame->selection()->clear();
focusController()->setFocusedFrame(frame);
return true;
}
@@ -234,7 +312,7 @@ bool Page::findString(const String& target, TextCaseSensitivity caseSensitivity,
// Search contents of startFrame, on the other side of the selection that we did earlier.
// We cheat a bit and just research with wrap on
- if (shouldWrap && !startFrame->selectionController()->isNone()) {
+ if (shouldWrap && !startFrame->selection()->isNone()) {
bool found = startFrame->findString(target, direction == FindDirectionForward, caseSensitivity == TextCaseSensitive, true, true);
focusController()->setFocusedFrame(frame);
return found;
@@ -275,7 +353,7 @@ void Page::unmarkAllTextMatches()
const Selection& Page::selection() const
{
- return focusController()->focusedOrMainFrame()->selectionController()->selection();
+ return focusController()->focusedOrMainFrame()->selection()->selection();
}
void Page::setDefersLoading(bool defers)
@@ -355,9 +433,150 @@ const String& Page::userStyleSheet() const
if (!data)
return m_userStyleSheet;
- m_userStyleSheet = TextResourceDecoder("text/css").decode(data->data(), data->size());
+ m_userStyleSheet = TextResourceDecoder::create("text/css")->decode(data->data(), data->size());
return m_userStyleSheet;
}
+void Page::removeAllVisitedLinks()
+{
+ if (!allPages)
+ return;
+ HashSet<PageGroup*> groups;
+ HashSet<Page*>::iterator pagesEnd = allPages->end();
+ for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
+ if (PageGroup* group = (*it)->groupPtr())
+ groups.add(group);
+ }
+ HashSet<PageGroup*>::iterator groupsEnd = groups.end();
+ for (HashSet<PageGroup*>::iterator it = groups.begin(); it != groupsEnd; ++it)
+ (*it)->removeVisitedLinks();
+}
+
+void Page::allVisitedStateChanged(PageGroup* group)
+{
+ ASSERT(group);
+ ASSERT(allPages);
+ HashSet<Page*>::iterator pagesEnd = allPages->end();
+ for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
+ Page* page = *it;
+ if (page->m_group != group)
+ continue;
+ for (Frame* frame = page->m_mainFrame.get(); frame; frame = frame->tree()->traverseNext()) {
+ if (CSSStyleSelector* styleSelector = frame->document()->styleSelector())
+ styleSelector->allVisitedStateChanged();
+ }
+ }
+}
+
+void Page::visitedStateChanged(PageGroup* group, unsigned visitedLinkHash)
+{
+ ASSERT(group);
+ ASSERT(allPages);
+ HashSet<Page*>::iterator pagesEnd = allPages->end();
+ for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
+ Page* page = *it;
+ if (page->m_group != group)
+ continue;
+ for (Frame* frame = page->m_mainFrame.get(); frame; frame = frame->tree()->traverseNext()) {
+ if (CSSStyleSelector* styleSelector = frame->document()->styleSelector())
+ styleSelector->visitedStateChanged(visitedLinkHash);
+ }
+ }
+}
+
+void Page::setDebuggerForAllPages(JSC::Debugger* debugger)
+{
+ ASSERT(allPages);
+
+ HashSet<Page*>::iterator end = allPages->end();
+ for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it)
+ (*it)->setDebugger(debugger);
+}
+
+void Page::setDebugger(JSC::Debugger* debugger)
+{
+ if (m_debugger == debugger)
+ return;
+
+ m_debugger = debugger;
+
+ for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree()->traverseNext())
+ frame->script()->attachDebugger(m_debugger);
+}
+
+#if ENABLE(DOM_STORAGE)
+SessionStorage* Page::sessionStorage(bool optionalCreate)
+{
+ if (!m_sessionStorage && optionalCreate)
+ m_sessionStorage = SessionStorage::create(this);
+
+ return m_sessionStorage.get();
+}
+
+void Page::setSessionStorage(PassRefPtr<SessionStorage> newStorage)
+{
+ ASSERT(newStorage->page() == this);
+ m_sessionStorage = newStorage;
+}
+#endif
+
+unsigned Page::pendingUnloadEventCount()
+{
+ return m_pendingUnloadEventCount;
+}
+
+void Page::changePendingUnloadEventCount(int delta)
+{
+ if (!delta)
+ return;
+ ASSERT( (delta + (int)m_pendingUnloadEventCount) >= 0 );
+
+ if (m_pendingUnloadEventCount == 0)
+ m_chrome->disableSuddenTermination();
+ else if ((m_pendingUnloadEventCount + delta) == 0)
+ m_chrome->enableSuddenTermination();
+
+ m_pendingUnloadEventCount += delta;
+ return;
+}
+
+unsigned Page::pendingBeforeUnloadEventCount()
+{
+ return m_pendingBeforeUnloadEventCount;
+}
+
+void Page::changePendingBeforeUnloadEventCount(int delta)
+{
+ if (!delta)
+ return;
+ ASSERT( (delta + (int)m_pendingBeforeUnloadEventCount) >= 0 );
+
+ if (m_pendingBeforeUnloadEventCount == 0)
+ m_chrome->disableSuddenTermination();
+ else if ((m_pendingBeforeUnloadEventCount + delta) == 0)
+ m_chrome->enableSuddenTermination();
+
+ m_pendingBeforeUnloadEventCount += delta;
+ return;
+}
+
+void Page::setCustomHTMLTokenizerTimeDelay(double customHTMLTokenizerTimeDelay)
+{
+ if (customHTMLTokenizerTimeDelay < 0) {
+ m_customHTMLTokenizerTimeDelay = -1;
+ return;
+ }
+ m_customHTMLTokenizerTimeDelay = customHTMLTokenizerTimeDelay;
+}
+
+void Page::setCustomHTMLTokenizerChunkSize(int customHTMLTokenizerChunkSize)
+{
+ if (customHTMLTokenizerChunkSize < 0) {
+ m_customHTMLTokenizerChunkSize = -1;
+ return;
+ }
+ m_customHTMLTokenizerChunkSize = customHTMLTokenizerChunkSize;
+}
+
} // namespace WebCore