summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordglazkov@google.com <dglazkov@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-06 19:48:07 +0000
committerdglazkov@google.com <dglazkov@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-06 19:48:07 +0000
commit9b814d9a263d92030e9be424c223f6f3cfa7b67a (patch)
tree50e4877d65acaffafa9e99f59e6a0c85980c407e
parent757449ab8a47562b490588e0e05e826fc8aceeeb (diff)
downloadchromium_src-9b814d9a263d92030e9be424c223f6f3cfa7b67a.zip
chromium_src-9b814d9a263d92030e9be424c223f6f3cfa7b67a.tar.gz
chromium_src-9b814d9a263d92030e9be424c223f6f3cfa7b67a.tar.bz2
Cleaning up the unfork
Removing files from pending Review URL: http://codereview.chromium.org/6500 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2892 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--DEPS2
-rw-r--r--webkit/build/WebCore/WebCore.vcproj56
-rw-r--r--webkit/pending/AtomicString.cpp300
-rw-r--r--webkit/pending/AtomicString.h143
-rw-r--r--webkit/pending/CSSStyleSelector.cpp5707
-rw-r--r--webkit/pending/CachedCSSStyleSheet.cpp124
-rw-r--r--webkit/pending/CachedResource.h211
-rw-r--r--webkit/pending/CachedScript.cpp105
-rw-r--r--webkit/pending/CanvasRenderingContext2D.cpp1352
-rw-r--r--webkit/pending/CanvasRenderingContext2D.h277
-rw-r--r--webkit/pending/CanvasRenderingContext2D.idl120
-rw-r--r--webkit/pending/CompositeAnimation.h104
-rw-r--r--webkit/pending/DOMWindow.cpp1192
-rw-r--r--webkit/pending/DOMWindow.h304
-rw-r--r--webkit/pending/Document.cpp4455
-rw-r--r--webkit/pending/Document.h1090
-rw-r--r--webkit/pending/DragController.cpp774
-rw-r--r--webkit/pending/EmptyClients.h410
-rw-r--r--webkit/pending/EventHandler.cpp2142
-rw-r--r--webkit/pending/FileSystem.h163
-rw-r--r--webkit/pending/FileSystemWin.cpp102
-rw-r--r--webkit/pending/Font.cpp839
-rw-r--r--webkit/pending/FontCache.cpp399
-rw-r--r--webkit/pending/FontCache.h106
-rw-r--r--webkit/pending/FontDescription.h145
-rw-r--r--webkit/pending/Frame.cpp1905
-rw-r--r--webkit/pending/FrameLoader.cpp5186
-rw-r--r--webkit/pending/FrameLoader.h702
-rw-r--r--webkit/pending/FrameLoaderClient.h216
29 files changed, 29 insertions, 28602 deletions
diff --git a/DEPS b/DEPS
index e087838..19d9f02 100644
--- a/DEPS
+++ b/DEPS
@@ -12,7 +12,7 @@ deps = {
"http://googletest.googlecode.com/svn/trunk@63",
"src/third_party/WebKit":
- "/trunk/deps/third_party/WebKit@2871",
+ "/trunk/deps/third_party/WebKit@2888",
"src/third_party/cygwin":
"/trunk/deps/third_party/cygwin@1788",
diff --git a/webkit/build/WebCore/WebCore.vcproj b/webkit/build/WebCore/WebCore.vcproj
index e8e5dd6..0ad44a9 100644
--- a/webkit/build/WebCore/WebCore.vcproj
+++ b/webkit/build/WebCore/WebCore.vcproj
@@ -242,7 +242,7 @@
>
</File>
<File
- RelativePath="..\..\pending\Console.h"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\page\Console.h"
>
</File>
<File
@@ -266,11 +266,11 @@
>
</File>
<File
- RelativePath="..\..\pending\DOMWindow.cpp"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\page\DOMWindow.cpp"
>
</File>
<File
- RelativePath="..\..\pending\DOMWindow.h"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\page\DOMWindow.h"
>
</File>
<File
@@ -282,7 +282,7 @@
>
</File>
<File
- RelativePath="..\..\pending\DragController.cpp"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\page\DragController.cpp"
>
</File>
<File
@@ -290,7 +290,7 @@
>
</File>
<File
- RelativePath="..\..\pending\EventHandler.cpp"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\page\EventHandler.cpp"
>
</File>
<File
@@ -310,7 +310,7 @@
>
</File>
<File
- RelativePath="..\..\pending\Frame.cpp"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\page\Frame.cpp"
>
</File>
<File
@@ -433,7 +433,7 @@
>
</File>
<File
- RelativePath="..\..\pending\CompositeAnimation.h"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\page\animation\CompositeAnimation.h"
>
</File>
<File
@@ -466,7 +466,7 @@
>
</File>
<File
- RelativePath="..\..\pending\CachedCSSStyleSheet.cpp"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\loader\CachedCSSStyleSheet.cpp"
>
</File>
<File
@@ -494,7 +494,7 @@
>
</File>
<File
- RelativePath="..\..\pending\CachedResource.h"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\loader\CachedResource.h"
>
</File>
<File
@@ -510,7 +510,7 @@
>
</File>
<File
- RelativePath="..\..\pending\CachedScript.cpp"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\loader\CachedScript.cpp"
>
</File>
<File
@@ -554,7 +554,7 @@
>
</File>
<File
- RelativePath="..\..\pending\EmptyClients.h"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\loader\EmptyClients.h"
>
</File>
<File
@@ -566,15 +566,15 @@
>
</File>
<File
- RelativePath="..\..\pending\FrameLoader.cpp"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\loader\FrameLoader.cpp"
>
</File>
<File
- RelativePath="..\..\pending\FrameLoader.h"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\loader\FrameLoader.h"
>
</File>
<File
- RelativePath="..\..\pending\FrameLoaderClient.h"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\loader\FrameLoaderClient.h"
>
</File>
<File
@@ -830,7 +830,7 @@
>
</File>
<File
- RelativePath="..\..\pending\FileSystem.h"
+ RelativePath="...\..\..\third_party\WebKit\WebCore\platform\FileSystem.h"
>
</File>
<File
@@ -838,7 +838,7 @@
>
</File>
<File
- RelativePath="..\..\pending\Font.cpp"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\platform\graphics\Font.cpp"
>
</File>
<File
@@ -846,11 +846,11 @@
>
</File>
<File
- RelativePath="..\..\pending\FontCache.cpp"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\platform\graphics\FontCache.cpp"
>
</File>
<File
- RelativePath="..\..\pending\FontCache.h"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\platform\graphics\FontCache.h"
>
</File>
<File
@@ -858,7 +858,7 @@
>
</File>
<File
- RelativePath="..\..\pending\FontDescription.h"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\platform\graphics\FontDescription.h"
>
</File>
<File
@@ -1357,7 +1357,7 @@
Name="win"
>
<File
- RelativePath="..\..\pending\FileSystemWin.cpp"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\platform\win\FileSystemWin.cpp"
>
</File>
</Filter>
@@ -1365,11 +1365,11 @@
Name="text"
>
<File
- RelativePath="..\..\pending\AtomicString.cpp"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\platform\text\AtomicString.cpp"
>
</File>
<File
- RelativePath="..\..\pending\AtomicString.h"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\platform\text\AtomicString.h"
>
</File>
<File
@@ -1846,7 +1846,7 @@
>
</File>
<File
- RelativePath="..\..\pending\CSSStyleSelector.cpp"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\css\CSSStyleSelector.cpp"
>
</File>
<File
@@ -3158,11 +3158,11 @@
>
</File>
<File
- RelativePath="..\..\pending\Document.cpp"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\dom\Document.cpp"
>
</File>
<File
- RelativePath="..\..\pending\Document.h"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\dom\Document.h"
>
</File>
<File
@@ -3678,7 +3678,7 @@
>
</File>
<File
- RelativePath="..\..\pending\DeleteButtonController.cpp"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\editing\DeleteButtonController.cpp"
>
</File>
<File
@@ -4042,11 +4042,11 @@
>
</File>
<File
- RelativePath="..\..\pending\CanvasRenderingContext2D.cpp"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\html\CanvasRenderingContext2D.cpp"
>
</File>
<File
- RelativePath="..\..\pending\CanvasRenderingContext2D.h"
+ RelativePath="..\..\..\third_party\WebKit\WebCore\html\CanvasRenderingContext2D.h"
>
</File>
<File
diff --git a/webkit/pending/AtomicString.cpp b/webkit/pending/AtomicString.cpp
deleted file mode 100644
index ccadfce..0000000
--- a/webkit/pending/AtomicString.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright (C) 2004, 2005, 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-
-#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC
-#define ATOMICSTRING_HIDE_GLOBALS 1
-#endif
-
-#include "AtomicString.h"
-
-#include "StaticConstructors.h"
-#include "StringHash.h"
-#include <kjs/identifier.h>
-#include <wtf/HashSet.h>
-
-#if USE(JSC)
-using KJS::Identifier;
-using KJS::UString;
-#endif
-
-namespace WebCore {
-
-static HashSet<StringImpl*>* stringTable;
-
-struct CStringTranslator {
- static unsigned hash(const char* c)
- {
- return StringImpl::computeHash(c);
- }
-
- static bool equal(StringImpl* r, const char* s)
- {
- int length = r->length();
- const UChar* d = r->characters();
- for (int i = 0; i != length; ++i) {
- unsigned char c = s[i];
- if (d[i] != c)
- return false;
- }
- return s[length] == 0;
- }
-
- static void translate(StringImpl*& location, const char* const& c, unsigned hash)
- {
- location = new StringImpl(c, strlen(c), hash);
- }
-};
-
-bool operator==(const AtomicString& a, const char* b)
-{
- StringImpl* impl = a.impl();
- if ((!impl || !impl->characters()) && !b)
- return true;
- if ((!impl || !impl->characters()) || !b)
- return false;
- return CStringTranslator::equal(impl, b);
-}
-
-PassRefPtr<StringImpl> AtomicString::add(const char* c)
-{
- if (!c)
- return 0;
- if (!*c)
- return StringImpl::empty();
- pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable->add<const char*, CStringTranslator>(c);
- if (!addResult.second)
- return *addResult.first;
- return adoptRef(*addResult.first);
-}
-
-struct UCharBuffer {
- const UChar* s;
- unsigned length;
-};
-
-static inline bool equal(StringImpl* string, const UChar* characters, unsigned length)
-{
- if (string->length() != length)
- return false;
-
-#if PLATFORM(ARM)
- const UChar* stringCharacters = string->characters();
- for (unsigned i = 0; i != length; ++i) {
- if (*stringCharacters++ != *characters++)
- return false;
- }
- return true;
-#else
- /* Do it 4-bytes-at-a-time on architectures where it's safe */
-
- const uint32_t* stringCharacters = reinterpret_cast<const uint32_t*>(string->characters());
- const uint32_t* bufferCharacters = reinterpret_cast<const uint32_t*>(characters);
-
- unsigned halfLength = length >> 1;
- for (unsigned i = 0; i != halfLength; ++i) {
- if (*stringCharacters++ != *bufferCharacters++)
- return false;
- }
-
- if (length & 1 && *reinterpret_cast<const uint16_t*>(stringCharacters) != *reinterpret_cast<const uint16_t*>(bufferCharacters))
- return false;
-
- return true;
-#endif
-}
-
-struct UCharBufferTranslator {
- static unsigned hash(const UCharBuffer& buf)
- {
- return StringImpl::computeHash(buf.s, buf.length);
- }
-
- static bool equal(StringImpl* const& str, const UCharBuffer& buf)
- {
- return WebCore::equal(str, buf.s, buf.length);
- }
-
- static void translate(StringImpl*& location, const UCharBuffer& buf, unsigned hash)
- {
- location = new StringImpl(buf.s, buf.length, hash);
- }
-};
-
-struct HashAndCharacters {
- unsigned hash;
- const UChar* characters;
- unsigned length;
-};
-
-struct HashAndCharactersTranslator {
- static unsigned hash(const HashAndCharacters& buffer)
- {
- ASSERT(buffer.hash == StringImpl::computeHash(buffer.characters, buffer.length));
- return buffer.hash;
- }
-
- static bool equal(StringImpl* const& string, const HashAndCharacters& buffer)
- {
- return WebCore::equal(string, buffer.characters, buffer.length);
- }
-
- static void translate(StringImpl*& location, const HashAndCharacters& buffer, unsigned hash)
- {
- location = new StringImpl(buffer.characters, buffer.length, hash);
- }
-};
-
-PassRefPtr<StringImpl> AtomicString::add(const UChar* s, int length)
-{
- if (!s)
- return 0;
-
- if (length == 0)
- return StringImpl::empty();
-
- UCharBuffer buf = { s, length };
- pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable->add<UCharBuffer, UCharBufferTranslator>(buf);
- if (!addResult.second)
- return *addResult.first;
- return adoptRef(*addResult.first);
-}
-
-PassRefPtr<StringImpl> AtomicString::add(const UChar* s)
-{
- if (!s)
- return 0;
-
- int length = 0;
- while (s[length] != UChar(0))
- length++;
-
- if (length == 0)
- return StringImpl::empty();
-
- UCharBuffer buf = {s, length};
- pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable->add<UCharBuffer, UCharBufferTranslator>(buf);
- if (!addResult.second)
- return *addResult.first;
- return adoptRef(*addResult.first);
-}
-
-PassRefPtr<StringImpl> AtomicString::add(StringImpl* r)
-{
- if (!r || r->m_inTable)
- return r;
-
- if (r->length() == 0)
- return StringImpl::empty();
-
- StringImpl* result = *stringTable->add(r).first;
- if (result == r)
- r->m_inTable = true;
- return result;
-}
-
-void AtomicString::remove(StringImpl* r)
-{
- stringTable->remove(r);
-}
-
-#if USE(JSC)
-PassRefPtr<StringImpl> AtomicString::add(const KJS::Identifier& identifier)
-{
- if (identifier.isNull())
- return 0;
-
- UString::Rep* string = identifier.ustring().rep();
- unsigned length = string->size();
- if (!length)
- return StringImpl::empty();
-
- HashAndCharacters buffer = { string->computedHash(), string->data(), length };
- pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable->add<HashAndCharacters, HashAndCharactersTranslator>(buffer);
- if (!addResult.second)
- return *addResult.first;
- return adoptRef(*addResult.first);
-}
-
-PassRefPtr<StringImpl> AtomicString::add(const KJS::UString& ustring)
-{
- if (ustring.isNull())
- return 0;
-
- UString::Rep* string = ustring.rep();
- unsigned length = string->size();
- if (!length)
- return StringImpl::empty();
-
- HashAndCharacters buffer = { string->hash(), string->data(), length };
- pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable->add<HashAndCharacters, HashAndCharactersTranslator>(buffer);
- if (!addResult.second)
- return *addResult.first;
- return adoptRef(*addResult.first);
-}
-
-AtomicStringImpl* AtomicString::find(const KJS::Identifier& identifier)
-{
- if (identifier.isNull())
- return 0;
-
- UString::Rep* string = identifier.ustring().rep();
- unsigned length = string->size();
- if (!length)
- return static_cast<AtomicStringImpl*>(StringImpl::empty());
-
- HashAndCharacters buffer = { string->computedHash(), string->data(), length };
- HashSet<StringImpl*>::iterator iterator = stringTable->find<HashAndCharacters, HashAndCharactersTranslator>(buffer);
- if (iterator == stringTable->end())
- return 0;
- return static_cast<AtomicStringImpl*>(*iterator);
-}
-
-AtomicString::operator UString() const
-{
- return m_string;
-}
-#endif
-
-DEFINE_GLOBAL(AtomicString, nullAtom)
-DEFINE_GLOBAL(AtomicString, emptyAtom, "")
-DEFINE_GLOBAL(AtomicString, textAtom, "#text")
-DEFINE_GLOBAL(AtomicString, commentAtom, "#comment")
-DEFINE_GLOBAL(AtomicString, starAtom, "*")
-
-void AtomicString::init()
-{
- static bool initialized;
- if (!initialized) {
- stringTable = new HashSet<StringImpl*>;
-
- // Use placement new to initialize the globals.
- new ((void*)&nullAtom) AtomicString;
- new ((void*)&emptyAtom) AtomicString("");
- new ((void*)&textAtom) AtomicString("#text");
- new ((void*)&commentAtom) AtomicString("#comment");
- new ((void*)&starAtom) AtomicString("*");
-
- initialized = true;
- }
-}
-
-}
diff --git a/webkit/pending/AtomicString.h b/webkit/pending/AtomicString.h
deleted file mode 100644
index 50be34a..0000000
--- a/webkit/pending/AtomicString.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2004, 2005, 2006, 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef AtomicString_h
-#define AtomicString_h
-
-#include "AtomicStringImpl.h"
-#include "PlatformString.h"
-
-namespace WebCore {
-
-class AtomicString {
-public:
- static void init();
-
- AtomicString() { }
- AtomicString(const char* s) : m_string(add(s)) { }
- AtomicString(const UChar* s, int length) : m_string(add(s, length)) { }
- AtomicString(const UChar* s) : m_string(add(s)) { }
-#if USE(JSC)
- AtomicString(const KJS::UString& s) : m_string(add(s)) { }
- AtomicString(const KJS::Identifier& s) : m_string(add(s)) { }
-#endif
- AtomicString(StringImpl* imp) : m_string(add(imp)) { }
- AtomicString(AtomicStringImpl* imp) : m_string(imp) { }
- AtomicString(const String& s) : m_string(add(s.impl())) { }
-
-#if USE(JSC)
- static AtomicStringImpl* find(const KJS::Identifier&);
-#endif
-
- operator const String&() const { return m_string; }
- const String& string() const { return m_string; };
-
-#if USE(JSC)
- operator KJS::UString() const;
-#endif
-
- AtomicStringImpl* impl() const { return static_cast<AtomicStringImpl *>(m_string.impl()); }
-
- const UChar* characters() const { return m_string.characters(); }
- unsigned length() const { return m_string.length(); }
-
- UChar operator[](unsigned int i) const { return m_string[i]; }
-
- bool contains(UChar c) const { return m_string.contains(c); }
- bool contains(const AtomicString& s, bool caseSensitive = true) const
- { return m_string.contains(s.string(), caseSensitive); }
-
- int find(UChar c, int start = 0) const { return m_string.find(c, start); }
- int find(const AtomicString& s, int start = 0, bool caseSentitive = true) const
- { return m_string.find(s.string(), start, caseSentitive); }
-
- bool startsWith(const AtomicString& s, bool caseSensitive = true) const
- { return m_string.startsWith(s.string(), caseSensitive); }
- bool endsWith(const AtomicString& s, bool caseSensitive = true) const
- { return m_string.endsWith(s.string(), caseSensitive); }
-
- int toInt(bool* ok = 0) const { return m_string.toInt(ok); }
- double toDouble(bool* ok = 0) const { return m_string.toDouble(ok); }
- float toFloat(bool* ok = 0) const { return m_string.toFloat(ok); }
- bool percentage(int& p) const { return m_string.percentage(p); }
- Length* toLengthArray(int& len) const { return m_string.toLengthArray(len); }
- Length* toCoordsArray(int& len) const { return m_string.toCoordsArray(len); }
-
- bool isNull() const { return m_string.isNull(); }
- bool isEmpty() const { return m_string.isEmpty(); }
-
- static void remove(StringImpl*);
-
-#ifdef __OBJC__
- AtomicString(NSString* s) : m_string(add(String(s).impl())) { }
- operator NSString*() const { return m_string; }
-#endif
-#if PLATFORM(SYMBIAN)
- AtomicString(const TDesC& s) : m_string(add(String(s).impl())) { }
- operator TPtrC() const { return m_string; }
-#endif
-#if PLATFORM(QT)
- AtomicString(const QString& s) : m_string(add(String(s).impl())) { }
- operator QString() const { return m_string; }
-#endif
-
-private:
- String m_string;
-
- static PassRefPtr<StringImpl> add(const char*);
- static PassRefPtr<StringImpl> add(const UChar*, int length);
- static PassRefPtr<StringImpl> add(const UChar*);
- static PassRefPtr<StringImpl> add(StringImpl*);
-#if USE(JSC)
- static PassRefPtr<StringImpl> add(const KJS::UString&);
- static PassRefPtr<StringImpl> add(const KJS::Identifier&);
-#endif
-};
-
-inline bool operator==(const AtomicString& a, const AtomicString& b) { return a.impl() == b.impl(); }
-bool operator==(const AtomicString& a, const char* b);
-inline bool operator==(const AtomicString& a, const String& b) { return equal(a.impl(), b.impl()); }
-inline bool operator==(const char* a, const AtomicString& b) { return b == a; }
-inline bool operator==(const String& a, const AtomicString& b) { return equal(a.impl(), b.impl()); }
-
-inline bool operator!=(const AtomicString& a, const AtomicString& b) { return a.impl() != b.impl(); }
-inline bool operator!=(const AtomicString& a, const char *b) { return !(a == b); }
-inline bool operator!=(const AtomicString& a, const String& b) { return !equal(a.impl(), b.impl()); }
-inline bool operator!=(const char* a, const AtomicString& b) { return !(b == a); }
-inline bool operator!=(const String& a, const AtomicString& b) { return !equal(a.impl(), b.impl()); }
-
-inline bool equalIgnoringCase(const AtomicString& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); }
-inline bool equalIgnoringCase(const AtomicString& a, const char* b) { return equalIgnoringCase(a.impl(), b); }
-inline bool equalIgnoringCase(const AtomicString& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); }
-inline bool equalIgnoringCase(const char* a, const AtomicString& b) { return equalIgnoringCase(a, b.impl()); }
-inline bool equalIgnoringCase(const String& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); }
-
-// Define external global variables for the commonly used atomic strings.
-#ifndef ATOMICSTRING_HIDE_GLOBALS
- extern const AtomicString nullAtom;
- extern const AtomicString emptyAtom;
- extern const AtomicString textAtom;
- extern const AtomicString commentAtom;
- extern const AtomicString starAtom;
-#endif
-
-} // namespace WebCore
-
-#endif // AtomicString_h
diff --git a/webkit/pending/CSSStyleSelector.cpp b/webkit/pending/CSSStyleSelector.cpp
deleted file mode 100644
index 766696f..0000000
--- a/webkit/pending/CSSStyleSelector.cpp
+++ /dev/null
@@ -1,5707 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
- * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
- * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
- * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "CSSStyleSelector.h"
-
-#include "CSSBorderImageValue.h"
-#include "CSSCursorImageValue.h"
-#include "CSSFontFace.h"
-#include "CSSFontFaceRule.h"
-#include "CSSFontFaceSource.h"
-#include "CSSImportRule.h"
-#include "CSSMediaRule.h"
-#include "CSSParser.h"
-#include "CSSPrimitiveValueMappings.h"
-#include "CSSProperty.h"
-#include "CSSPropertyNames.h"
-#include "CSSReflectValue.h"
-#include "CSSRuleList.h"
-#include "CSSSelector.h"
-#include "CSSStyleRule.h"
-#include "CSSStyleSheet.h"
-#include "CSSTimingFunctionValue.h"
-#include "CSSValueList.h"
-#include "CSSVariableDependentValue.h"
-#include "CSSVariablesDeclaration.h"
-#include "CSSVariablesRule.h"
-#include "CachedImage.h"
-#include "Counter.h"
-#include "FontCache.h"
-#include "FontFamilyValue.h"
-#include "FontValue.h"
-#include "Frame.h"
-#include "FrameView.h"
-#include "HTMLDocument.h"
-#include "HTMLElement.h"
-#include "HTMLInputElement.h"
-#include "HTMLTextAreaElement.h"
-#include "HTMLNames.h"
-#include "MediaList.h"
-#include "MediaQueryEvaluator.h"
-#include "Page.h"
-#include "PageGroup.h"
-#include "Pair.h"
-#include "Rect.h"
-#include "RenderTheme.h"
-#include "SelectionController.h"
-#include "Settings.h"
-#include "ShadowValue.h"
-#include "StyleCachedImage.h"
-#include "StyleGeneratedImage.h"
-#include "StyleSheetList.h"
-#include "Text.h"
-#include "UserAgentStyleSheets.h"
-#include "WebKitCSSKeyframeRule.h"
-#include "WebKitCSSKeyframesRule.h"
-#include "WebKitCSSTransformValue.h"
-#include "XMLNames.h"
-#include "loader.h"
-#include <wtf/Vector.h>
-
-#if ENABLE(DASHBOARD_SUPPORT)
-#include "DashboardRegion.h"
-#endif
-
-#if ENABLE(SVG)
-#include "XLinkNames.h"
-#include "SVGNames.h"
-#endif
-
-using namespace std;
-
-namespace WebCore {
-
-using namespace HTMLNames;
-
-// #define STYLE_SHARING_STATS 1
-
-#define HANDLE_INHERIT(prop, Prop) \
-if (isInherit) { \
- m_style->set##Prop(m_parentStyle->prop()); \
- return; \
-}
-
-#define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
-HANDLE_INHERIT(prop, Prop) \
-if (isInitial) { \
- m_style->set##Prop(RenderStyle::initial##Prop()); \
- return; \
-}
-
-#define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
-HANDLE_INHERIT(prop, Prop) \
-if (isInitial) { \
- m_style->set##Prop(RenderStyle::initial##Value());\
- return;\
-}
-
-#define HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(layerType, LayerType, prop, Prop) \
-if (isInherit) { \
- FillLayer* currChild = m_style->access##LayerType##Layers(); \
- FillLayer* prevChild = 0; \
- const FillLayer* currParent = m_parentStyle->layerType##Layers(); \
- while (currParent && currParent->is##Prop##Set()) { \
- if (!currChild) { \
- /* Need to make a new layer.*/ \
- currChild = new FillLayer(LayerType##FillLayer); \
- prevChild->setNext(currChild); \
- } \
- currChild->set##Prop(currParent->prop()); \
- prevChild = currChild; \
- currChild = prevChild->next(); \
- currParent = currParent->next(); \
- } \
- \
- while (currChild) { \
- /* Reset any remaining layers to not have the property set. */ \
- currChild->clear##Prop(); \
- currChild = currChild->next(); \
- } \
-} else if (isInitial) { \
- FillLayer* currChild = m_style->access##LayerType##Layers(); \
- currChild->set##Prop(FillLayer::initialFill##Prop(LayerType##FillLayer)); \
- for (currChild = currChild->next(); currChild; currChild = currChild->next()) \
- currChild->clear##Prop(); \
-}
-
-#define HANDLE_FILL_LAYER_VALUE(layerType, LayerType, prop, Prop, value) { \
-HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(layerType, LayerType, prop, Prop) \
-if (isInherit || isInitial) \
- return; \
-FillLayer* currChild = m_style->access##LayerType##Layers(); \
-FillLayer* prevChild = 0; \
-if (value->isValueList()) { \
- /* Walk each value and put it into a layer, creating new layers as needed. */ \
- CSSValueList* valueList = static_cast<CSSValueList*>(value); \
- for (unsigned int i = 0; i < valueList->length(); i++) { \
- if (!currChild) { \
- /* Need to make a new layer to hold this value */ \
- currChild = new FillLayer(LayerType##FillLayer); \
- prevChild->setNext(currChild); \
- } \
- mapFill##Prop(currChild, valueList->itemWithoutBoundsCheck(i)); \
- prevChild = currChild; \
- currChild = currChild->next(); \
- } \
-} else { \
- mapFill##Prop(currChild, value); \
- currChild = currChild->next(); \
-} \
-while (currChild) { \
- /* Reset all remaining layers to not have the property set. */ \
- currChild->clear##Prop(); \
- currChild = currChild->next(); \
-} }
-
-#define HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
-HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(background, Background, prop, Prop)
-
-#define HANDLE_BACKGROUND_VALUE(prop, Prop, value) \
-HANDLE_FILL_LAYER_VALUE(background, Background, prop, Prop, value)
-
-#define HANDLE_MASK_INHERIT_AND_INITIAL(prop, Prop) \
-HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(mask, Mask, prop, Prop)
-
-#define HANDLE_MASK_VALUE(prop, Prop, value) \
-HANDLE_FILL_LAYER_VALUE(mask, Mask, prop, Prop, value)
-
-#define HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \
-if (isInherit) { \
- AnimationList* list = m_style->accessAnimations(); \
- const AnimationList* parentList = m_parentStyle->animations(); \
- size_t i = 0, parentSize = parentList ? parentList->size() : 0; \
- for ( ; i < parentSize && (*parentList)[i]->is##Prop##Set(); ++i) { \
- if (list->size() <= i) \
- list->append(Animation::create()); \
- (*list)[i]->set##Prop((*parentList)[i]->prop()); \
- } \
- \
- /* Reset any remaining animations to not have the property set. */ \
- for ( ; i < list->size(); ++i) \
- (*list)[i]->clear##Prop(); \
-} else if (isInitial) { \
- AnimationList* list = m_style->accessAnimations(); \
- if (list->isEmpty()) \
- list->append(Animation::create()); \
- (*list)[0]->set##Prop(RenderStyle::initialAnimation##Prop()); \
- for (size_t i = 1; i < list->size(); ++i) \
- (*list)[0]->clear##Prop(); \
-}
-
-#define HANDLE_ANIMATION_VALUE(prop, Prop, value) { \
-HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \
-if (isInherit || isInitial) \
- return; \
-AnimationList* list = m_style->accessAnimations(); \
-size_t childIndex = 0; \
-if (value->isValueList()) { \
- /* Walk each value and put it into an animation, creating new animations as needed. */ \
- CSSValueList* valueList = static_cast<CSSValueList*>(value); \
- for (unsigned int i = 0; i < valueList->length(); i++) { \
- if (childIndex <= list->size()) \
- list->append(Animation::create()); \
- mapAnimation##Prop((*list)[childIndex].get(), valueList->itemWithoutBoundsCheck(i)); \
- ++childIndex; \
- } \
-} else { \
- if (list->isEmpty()) \
- list->append(Animation::create()); \
- mapAnimation##Prop((*list)[childIndex].get(), value); \
- childIndex = 1; \
-} \
-for ( ; childIndex < list->size(); ++childIndex) { \
- /* Reset all remaining animations to not have the property set. */ \
- (*list)[childIndex]->clear##Prop(); \
-} \
-}
-
-#define HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \
-if (isInherit) { \
- AnimationList* list = m_style->accessTransitions(); \
- const AnimationList* parentList = m_parentStyle->transitions(); \
- size_t i = 0, parentSize = parentList ? parentList->size() : 0; \
- for ( ; i < parentSize && (*parentList)[i]->is##Prop##Set(); ++i) { \
- if (list->size() <= i) \
- list->append(Animation::create()); \
- (*list)[i]->set##Prop((*parentList)[i]->prop()); \
- } \
- \
- /* Reset any remaining transitions to not have the property set. */ \
- for ( ; i < list->size(); ++i) \
- (*list)[i]->clear##Prop(); \
-} else if (isInitial) { \
- AnimationList* list = m_style->accessTransitions(); \
- if (list->isEmpty()) \
- list->append(Animation::create()); \
- (*list)[0]->set##Prop(RenderStyle::initialAnimation##Prop()); \
- for (size_t i = 1; i < list->size(); ++i) \
- (*list)[0]->clear##Prop(); \
-}
-
-#define HANDLE_TRANSITION_VALUE(prop, Prop, value) { \
-HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \
-if (isInherit || isInitial) \
- return; \
-AnimationList* list = m_style->accessTransitions(); \
-size_t childIndex = 0; \
-if (value->isValueList()) { \
- /* Walk each value and put it into a transition, creating new animations as needed. */ \
- CSSValueList* valueList = static_cast<CSSValueList*>(value); \
- for (unsigned int i = 0; i < valueList->length(); i++) { \
- if (childIndex <= list->size()) \
- list->append(Animation::create()); \
- mapAnimation##Prop((*list)[childIndex].get(), valueList->itemWithoutBoundsCheck(i)); \
- ++childIndex; \
- } \
-} else { \
- if (list->isEmpty()) \
- list->append(Animation::create()); \
- mapAnimation##Prop((*list)[childIndex].get(), value); \
- childIndex = 1; \
-} \
-for ( ; childIndex < list->size(); ++childIndex) { \
- /* Reset all remaining transitions to not have the property set. */ \
- (*list)[childIndex]->clear##Prop(); \
-} \
-}
-
-#define HANDLE_INHERIT_COND(propID, prop, Prop) \
-if (id == propID) { \
- m_style->set##Prop(m_parentStyle->prop()); \
- return; \
-}
-
-#define HANDLE_INHERIT_COND_WITH_BACKUP(propID, prop, propAlt, Prop) \
-if (id == propID) { \
- if (m_parentStyle->prop().isValid()) \
- m_style->set##Prop(m_parentStyle->prop()); \
- else \
- m_style->set##Prop(m_parentStyle->propAlt()); \
- return; \
-}
-
-#define HANDLE_INITIAL_COND(propID, Prop) \
-if (id == propID) { \
- m_style->set##Prop(RenderStyle::initial##Prop()); \
- return; \
-}
-
-#define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \
-if (id == propID) { \
- m_style->set##Prop(RenderStyle::initial##Value()); \
- return; \
-}
-
-class CSSRuleSet {
-public:
- CSSRuleSet();
- ~CSSRuleSet();
-
- typedef HashMap<AtomicStringImpl*, CSSRuleDataList*> AtomRuleMap;
-
- void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0);
-
- void addRule(CSSStyleRule* rule, CSSSelector* sel);
- void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
- CSSStyleRule* rule, CSSSelector* sel);
-
- CSSRuleDataList* getIDRules(AtomicStringImpl* key) { return m_idRules.get(key); }
- CSSRuleDataList* getClassRules(AtomicStringImpl* key) { return m_classRules.get(key); }
- CSSRuleDataList* getTagRules(AtomicStringImpl* key) { return m_tagRules.get(key); }
- CSSRuleDataList* getUniversalRules() { return m_universalRules; }
-
-public:
- AtomRuleMap m_idRules;
- AtomRuleMap m_classRules;
- AtomRuleMap m_tagRules;
- CSSRuleDataList* m_universalRules;
- unsigned m_ruleCount;
-};
-
-static CSSRuleSet* defaultStyle;
-static CSSRuleSet* defaultQuirksStyle;
-static CSSRuleSet* defaultPrintStyle;
-static CSSRuleSet* defaultViewSourceStyle;
-
-RenderStyle* CSSStyleSelector::s_styleNotYetAvailable;
-
-static PseudoState pseudoState;
-
-static void loadDefaultStyle();
-
-static const MediaQueryEvaluator& screenEval()
-{
- static const MediaQueryEvaluator staticScreenEval("screen");
- return staticScreenEval;
-}
-
-static const MediaQueryEvaluator& printEval()
-{
- static const MediaQueryEvaluator staticPrintEval("print");
- return staticPrintEval;
-}
-
-CSSStyleSelector::CSSStyleSelector(Document* doc, const String& userStyleSheet, StyleSheetList* styleSheets, CSSStyleSheet* mappedElementSheet, bool strictParsing, bool matchAuthorAndUserStyles)
- : m_backgroundData(BackgroundFillLayer)
- , m_checker(doc, strictParsing, false)
- , m_fontSelector(CSSFontSelector::create(doc))
-{
- init();
-
- m_matchAuthorAndUserStyles = matchAuthorAndUserStyles;
-
- if (!defaultStyle)
- loadDefaultStyle();
-
- m_userStyle = 0;
-
- // construct document root element default style. this is needed
- // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
- // This is here instead of constructor, because when constructor is run,
- // document doesn't have documentElement
- // NOTE: this assumes that element that gets passed to styleForElement -call
- // is always from the document that owns the style selector
- FrameView* view = doc->view();
- if (view)
- m_medium = new MediaQueryEvaluator(view->mediaType());
- else
- m_medium = new MediaQueryEvaluator("all");
-
- Element* root = doc->documentElement();
-
- if (root)
- m_rootDefaultStyle = styleForElement(root, 0, false, true); // dont ref, because the RenderStyle is allocated from global heap
-
- if (m_rootDefaultStyle && view) {
- delete m_medium;
- m_medium = new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle);
- }
-
- // FIXME: This sucks! The user sheet is reparsed every time!
- if (!userStyleSheet.isEmpty()) {
- m_userSheet = CSSStyleSheet::create(doc);
- m_userSheet->parseString(userStyleSheet, strictParsing);
-
- m_userStyle = new CSSRuleSet();
- m_userStyle->addRulesFromSheet(m_userSheet.get(), *m_medium, this);
- }
-
- // add stylesheets from document
- m_authorStyle = new CSSRuleSet();
-
- // Add rules from elments like SVG's <font-face>
- if (mappedElementSheet)
- m_authorStyle->addRulesFromSheet(mappedElementSheet, *m_medium, this);
-
- unsigned length = styleSheets->length();
- for (unsigned i = 0; i < length; i++) {
- StyleSheet* sheet = styleSheets->item(i);
- if (sheet->isCSSStyleSheet() && !sheet->disabled())
- m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(sheet), *m_medium, this);
- }
-}
-
-// this is a simplified style setting function for keyframe styles
-void CSSStyleSelector::addKeyframeStyle(Document* doc, const WebKitCSSKeyframesRule* rule)
-{
- AtomicString s(rule->name());
- RefPtr<KeyframeList> list;
- if (m_keyframeRuleMap.contains(s.impl()))
- list = m_keyframeRuleMap.get(s.impl()).get();
- else {
- list = KeyframeList::create(s);
- m_keyframeRuleMap.add(s.impl(), list);
- }
- list->clear();
-
- for (unsigned i = 0; i < rule->length(); ++i) {
- const WebKitCSSKeyframeRule* kf = rule->item(i);
- m_style = new (doc->renderArena()) RenderStyle();
- m_style->ref();
- CSSMutableStyleDeclaration* decl = kf->style();
- DeprecatedValueListConstIterator<CSSProperty> end;
- for (DeprecatedValueListConstIterator<CSSProperty> it = decl->valuesIterator(); it != end; ++it) {
- const CSSProperty& current = *it;
- applyProperty(current.id(), current.value());
- list->addProperty(current.id());
- }
- list->insert(kf->key(), *m_style);
- m_style->deref(doc->renderArena());
- m_style = 0;
- }
-}
-
-void CSSStyleSelector::init()
-{
- m_element = 0;
- m_matchedDecls.clear();
- m_ruleList = 0;
- m_rootDefaultStyle = 0;
- m_medium = 0;
-}
-
-CSSStyleSelector::~CSSStyleSelector()
-{
- m_fontSelector->clearDocument();
- delete m_medium;
- ::delete m_rootDefaultStyle;
- delete m_authorStyle;
- delete m_userStyle;
- deleteAllValues(m_viewportDependentMediaQueryResults);
- m_keyframeRuleMap.clear();
-}
-
-static CSSStyleSheet* parseUASheet(const char* characters, unsigned size)
-{
- CSSStyleSheet* sheet = CSSStyleSheet::create().releaseRef(); // leak the sheet on purpose
- sheet->parseString(String(characters, size));
- return sheet;
-}
-
-static void loadDefaultStyle()
-{
- ASSERT(!defaultStyle);
-
- defaultStyle = new CSSRuleSet;
- defaultPrintStyle = new CSSRuleSet;
- defaultQuirksStyle = new CSSRuleSet;
- defaultViewSourceStyle = new CSSRuleSet;
-
- // Strict-mode rules.
- CSSStyleSheet* defaultSheet = parseUASheet(html4UserAgentStyleSheet, sizeof(html4UserAgentStyleSheet));
- RenderTheme::adjustDefaultStyleSheet(defaultSheet);
- defaultStyle->addRulesFromSheet(defaultSheet, screenEval());
- defaultPrintStyle->addRulesFromSheet(defaultSheet, printEval());
-
- // Quirks-mode rules.
- defaultQuirksStyle->addRulesFromSheet(parseUASheet(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)), screenEval());
-
- // View source rules.
- defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval());
-}
-
-void CSSStyleSelector::addMatchedDeclaration(CSSMutableStyleDeclaration* decl)
-{
- if (!decl->hasVariableDependentValue()) {
- m_matchedDecls.append(decl);
- return;
- }
-
- // See if we have already resolved the variables in this declaration.
- CSSMutableStyleDeclaration* resolvedDecl = m_resolvedVariablesDeclarations.get(decl).get();
- if (resolvedDecl) {
- m_matchedDecls.append(resolvedDecl);
- return;
- }
-
- // If this declaration has any variables in it, then we need to make a cloned
- // declaration with as many variables resolved as possible for this style selector's media.
- RefPtr<CSSMutableStyleDeclaration> newDecl = CSSMutableStyleDeclaration::create(decl->parentRule());
- m_matchedDecls.append(newDecl.get());
- m_resolvedVariablesDeclarations.set(decl, newDecl);
-
- HashSet<String> usedBlockVariables;
- resolveVariablesForDeclaration(decl, newDecl.get(), usedBlockVariables);
-}
-
-void CSSStyleSelector::resolveVariablesForDeclaration(CSSMutableStyleDeclaration* decl, CSSMutableStyleDeclaration* newDecl, HashSet<String>& usedBlockVariables)
-{
- // Now iterate over the properties in the original declaration. As we resolve variables we'll end up
- // mutating the new declaration (possibly expanding shorthands). The new declaration has no m_node
- // though, so it can't mistakenly call setChanged on anything.
- DeprecatedValueListConstIterator<CSSProperty> end;
- for (DeprecatedValueListConstIterator<CSSProperty> it = decl->valuesIterator(); it != end; ++it) {
- const CSSProperty& current = *it;
- if (!current.value()->isVariableDependentValue()) {
- // We can just add the parsed property directly.
- newDecl->addParsedProperty(current);
- continue;
- }
- CSSValueList* valueList = static_cast<CSSVariableDependentValue*>(current.value())->valueList();
- if (!valueList)
- continue;
- CSSParserValueList resolvedValueList;
- unsigned s = valueList->length();
- bool fullyResolved = true;
- for (unsigned i = 0; i < s; ++i) {
- CSSValue* val = valueList->item(i);
- CSSPrimitiveValue* primitiveValue = val->isPrimitiveValue() ? static_cast<CSSPrimitiveValue*>(val) : 0;
- if (primitiveValue && primitiveValue->isVariable()) {
- CSSVariablesRule* rule = m_variablesMap.get(primitiveValue->getStringValue());
- if (!rule || !rule->variables()) {
- fullyResolved = false;
- break;
- }
-
- if (current.id() == CSSPropertyWebkitVariableDeclarationBlock && s == 1) {
- fullyResolved = false;
- if (!usedBlockVariables.contains(primitiveValue->getStringValue())) {
- CSSMutableStyleDeclaration* declBlock = rule->variables()->getParsedVariableDeclarationBlock(primitiveValue->getStringValue());
- if (declBlock) {
- usedBlockVariables.add(primitiveValue->getStringValue());
- resolveVariablesForDeclaration(declBlock, newDecl, usedBlockVariables);
- }
- }
- }
-
- CSSValueList* resolvedVariable = rule->variables()->getParsedVariable(primitiveValue->getStringValue());
- if (!resolvedVariable) {
- fullyResolved = false;
- break;
- }
- unsigned valueSize = resolvedVariable->length();
- for (unsigned j = 0; j < valueSize; ++j)
- resolvedValueList.addValue(resolvedVariable->item(j)->parserValue());
- } else
- resolvedValueList.addValue(val->parserValue());
- }
-
- if (!fullyResolved)
- continue;
-
- // We now have a fully resolved new value list. We want the parser to use this value list
- // and parse our new declaration.
- CSSParser(m_checker.m_strictParsing).parsePropertyWithResolvedVariables(current.id(), current.isImportant(), newDecl, &resolvedValueList);
- }
-}
-
-void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& lastRuleIndex)
-{
- m_matchedRules.clear();
-
- if (!rules || !m_element)
- return;
-
- // We need to collect the rules for id, class, tag, and everything else into a buffer and
- // then sort the buffer.
- if (m_element->hasID())
- matchRulesForList(rules->getIDRules(m_element->getIDAttribute().impl()), firstRuleIndex, lastRuleIndex);
- if (m_element->hasClass()) {
- ASSERT(m_styledElement);
- const ClassNames& classNames = m_styledElement->classNames();
- size_t size = classNames.size();
- for (size_t i = 0; i < size; ++i)
- matchRulesForList(rules->getClassRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex);
- }
- matchRulesForList(rules->getTagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex);
- matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex);
-
- // If we didn't match any rules, we're done.
- if (m_matchedRules.isEmpty())
- return;
-
- // Sort the set of matched rules.
- sortMatchedRules(0, m_matchedRules.size());
-
- // Now transfer the set of matched rules over to our list of decls.
- if (!m_checker.m_collectRulesOnly) {
- for (unsigned i = 0; i < m_matchedRules.size(); i++)
- addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
- } else {
- for (unsigned i = 0; i < m_matchedRules.size(); i++) {
- if (!m_ruleList)
- m_ruleList = CSSRuleList::create();
- m_ruleList->append(m_matchedRules[i]->rule());
- }
- }
-}
-
-void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules, int& firstRuleIndex, int& lastRuleIndex)
-{
- if (!rules)
- return;
-
- for (CSSRuleData* d = rules->first(); d; d = d->next()) {
- CSSStyleRule* rule = d->rule();
- const AtomicString& localName = m_element->localName();
- const AtomicString& selectorLocalName = d->selector()->m_tag.localName();
- if ((localName == selectorLocalName || selectorLocalName == starAtom) && checkSelector(d->selector())) {
- // If the rule has no properties to apply, then ignore it.
- CSSMutableStyleDeclaration* decl = rule->declaration();
- if (!decl || !decl->length())
- continue;
-
- // If we're matching normal rules, set a pseudo bit if
- // we really just matched a pseudo-element.
- if (m_dynamicPseudo != RenderStyle::NOPSEUDO && m_checker.m_pseudoStyle == RenderStyle::NOPSEUDO) {
- if (m_checker.m_collectRulesOnly)
- return;
- if (m_dynamicPseudo < RenderStyle::FIRST_INTERNAL_PSEUDOID)
- m_style->setHasPseudoStyle(m_dynamicPseudo);
- } else {
- // Update our first/last rule indices in the matched rules array.
- lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size();
- if (firstRuleIndex == -1)
- firstRuleIndex = lastRuleIndex;
-
- // Add this rule to our list of matched rules.
- addMatchedRule(d);
- }
- }
- }
-}
-
-bool operator >(CSSRuleData& r1, CSSRuleData& r2)
-{
- int spec1 = r1.selector()->specificity();
- int spec2 = r2.selector()->specificity();
- return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2;
-}
-bool operator <=(CSSRuleData& r1, CSSRuleData& r2)
-{
- return !(r1 > r2);
-}
-
-void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end)
-{
- if (start >= end || (end - start == 1))
- return; // Sanity check.
-
- if (end - start <= 6) {
- // Apply a bubble sort for smaller lists.
- for (unsigned i = end - 1; i > start; i--) {
- bool sorted = true;
- for (unsigned j = start; j < i; j++) {
- CSSRuleData* elt = m_matchedRules[j];
- CSSRuleData* elt2 = m_matchedRules[j + 1];
- if (*elt > *elt2) {
- sorted = false;
- m_matchedRules[j] = elt2;
- m_matchedRules[j + 1] = elt;
- }
- }
- if (sorted)
- return;
- }
- return;
- }
-
- // Peform a merge sort for larger lists.
- unsigned mid = (start + end) / 2;
- sortMatchedRules(start, mid);
- sortMatchedRules(mid, end);
-
- CSSRuleData* elt = m_matchedRules[mid - 1];
- CSSRuleData* elt2 = m_matchedRules[mid];
-
- // Handle the fast common case (of equal specificity). The list may already
- // be completely sorted.
- if (*elt <= *elt2)
- return;
-
- // We have to merge sort. Ensure our merge buffer is big enough to hold
- // all the items.
- Vector<CSSRuleData*> rulesMergeBuffer;
- rulesMergeBuffer.reserveCapacity(end - start);
-
- unsigned i1 = start;
- unsigned i2 = mid;
-
- elt = m_matchedRules[i1];
- elt2 = m_matchedRules[i2];
-
- while (i1 < mid || i2 < end) {
- if (i1 < mid && (i2 == end || *elt <= *elt2)) {
- rulesMergeBuffer.append(elt);
- if (++i1 < mid)
- elt = m_matchedRules[i1];
- } else {
- rulesMergeBuffer.append(elt2);
- if (++i2 < end)
- elt2 = m_matchedRules[i2];
- }
- }
-
- for (unsigned i = start; i < end; i++)
- m_matchedRules[i] = rulesMergeBuffer[i - start];
-}
-
-void CSSStyleSelector::initElementAndPseudoState(Element* e)
-{
- m_element = e;
- if (m_element && m_element->isStyledElement())
- m_styledElement = static_cast<StyledElement*>(m_element);
- else
- m_styledElement = 0;
- pseudoState = PseudoUnknown;
-}
-
-void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* parentStyle, RenderStyle::PseudoId pseudoID)
-{
- m_checker.m_pseudoStyle = pseudoID;
-
- m_parentNode = e ? e->parentNode() : 0;
-
-#if ENABLE(SVG)
- if (!m_parentNode && e && e->isSVGElement() && e->isShadowNode())
- m_parentNode = e->shadowParentNode();
-#endif
-
- if (parentStyle)
- m_parentStyle = parentStyle;
- else
- m_parentStyle = m_parentNode ? m_parentNode->renderStyle() : 0;
-
- m_style = 0;
-
- m_matchedDecls.clear();
-
- m_ruleList = 0;
-
- m_fontDirty = false;
-}
-
-static inline const AtomicString* linkAttribute(Node* node)
-{
- if (!node->isLink())
- return 0;
-
- ASSERT(node->isElementNode());
- Element* element = static_cast<Element*>(node);
- if (element->isHTMLElement())
- return &element->getAttribute(hrefAttr);
-#if ENABLE(SVG)
- if (element->isSVGElement())
- return &element->getAttribute(XLinkNames::hrefAttr);
-#endif
- return 0;
-}
-
-CSSStyleSelector::SelectorChecker::SelectorChecker(Document* document, bool strictParsing, bool collectRulesOnly)
- : m_document(document)
- , m_strictParsing(strictParsing)
- , m_collectRulesOnly(collectRulesOnly)
- , m_pseudoStyle(RenderStyle::NOPSEUDO)
- , m_documentIsHTML(document->isHTMLDocument())
-{
-}
-
-PseudoState CSSStyleSelector::SelectorChecker::checkPseudoState(Element* element, bool checkVisited) const
-{
- const AtomicString* attr = linkAttribute(element);
- if (!attr || attr->isNull())
- return PseudoNone;
-
- if (!checkVisited)
- return PseudoAnyLink;
-
- unsigned hash = m_document->visitedLinkHash(*attr);
- if (!hash)
- return PseudoLink;
-
- Frame* frame = m_document->frame();
- if (!frame)
- return PseudoLink;
-
- Page* page = frame->page();
- if (!page)
- return PseudoLink;
-
- m_linksCheckedForVisitedState.add(hash);
- return page->group().isLinkVisited(hash) ? PseudoVisited : PseudoLink;
-}
-
-bool CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* element) const
-{
- pseudoState = PseudoUnknown;
- RenderStyle::PseudoId dynamicPseudo = RenderStyle::NOPSEUDO;
-
- return checkSelector(sel, element, 0, dynamicPseudo, true, false) == SelectorMatches;
-}
-
-// a helper function for parsing nth-arguments
-static bool parseNth(const String& nth, int &a, int &b)
-{
- if (nth.isEmpty())
- return false;
- a = 0;
- b = 0;
- if (nth == "odd") {
- a = 2;
- b = 1;
- } else if (nth == "even") {
- a = 2;
- b = 0;
- } else {
- int n = nth.find('n');
- if (n != -1) {
- if (nth[0] == '-') {
- if (n == 1)
- a = -1; // -n == -1n
- else
- a = nth.substring(0, n).toInt();
- } else if (!n)
- a = 1; // n == 1n
- else
- a = nth.substring(0, n).toInt();
-
- int p = nth.find('+', n);
- if (p != -1)
- b = nth.substring(p + 1, nth.length() - p - 1).toInt();
- else {
- p = nth.find('-', n);
- b = -nth.substring(p + 1, nth.length() - p - 1).toInt();
- }
- } else
- b = nth.toInt();
- }
- return true;
-}
-
-// a helper function for checking nth-arguments
-static bool matchNth(int count, int a, int b)
-{
- if (!a)
- return count == b;
- else if (a > 0) {
- if (count < b)
- return false;
- return (count - b) % a == 0;
- } else {
- if (count > b)
- return false;
- return (b - count) % (-a) == 0;
- }
-}
-
-
-#ifdef STYLE_SHARING_STATS
-static int fraction = 0;
-static int total = 0;
-#endif
-
-static const unsigned cStyleSearchThreshold = 10;
-
-Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned depth)
-{
- if (parent && parent->isStyledElement()) {
- StyledElement* p = static_cast<StyledElement*>(parent);
- if (!p->inlineStyleDecl() && !p->hasID()) {
- Node* r = p->previousSibling();
- unsigned subcount = 0;
- RenderStyle* st = p->renderStyle();
- while (r) {
- if (r->renderStyle() == st)
- return r->lastChild();
- if (subcount++ == cStyleSearchThreshold)
- return 0;
- r = r->previousSibling();
- }
- if (!r && depth < cStyleSearchThreshold)
- r = locateCousinList(static_cast<Element*>(parent->parentNode()), depth + 1);
- while (r) {
- if (r->renderStyle() == st)
- return r->lastChild();
- if (subcount++ == cStyleSearchThreshold)
- return 0;
- r = r->previousSibling();
- }
- }
- }
- return 0;
-}
-
-bool CSSStyleSelector::canShareStyleWithElement(Node* n)
-{
- if (n->isStyledElement()) {
- StyledElement* s = static_cast<StyledElement*>(n);
- RenderStyle* style = s->renderStyle();
- if (style && !style->unique() &&
- (s->tagQName() == m_element->tagQName()) && !s->hasID() &&
- (s->hasClass() == m_element->hasClass()) && !s->inlineStyleDecl() &&
- (s->hasMappedAttributes() == m_styledElement->hasMappedAttributes()) &&
- (s->isLink() == m_element->isLink()) &&
- !style->affectedByAttributeSelectors() &&
- (s->hovered() == m_element->hovered()) &&
- (s->active() == m_element->active()) &&
- (s->focused() == m_element->focused()) &&
- (s != s->document()->getCSSTarget() && m_element != m_element->document()->getCSSTarget()) &&
- (s->getAttribute(typeAttr) == m_element->getAttribute(typeAttr)) &&
- (s->getAttribute(XMLNames::langAttr) == m_element->getAttribute(XMLNames::langAttr)) &&
- (s->getAttribute(langAttr) == m_element->getAttribute(langAttr)) &&
- (s->getAttribute(readonlyAttr) == m_element->getAttribute(readonlyAttr)) &&
- (s->getAttribute(cellpaddingAttr) == m_element->getAttribute(cellpaddingAttr))) {
- bool isControl = s->isControl();
- if (isControl != m_element->isControl())
- return false;
- if (isControl && (s->isEnabled() != m_element->isEnabled()) ||
- (s->isIndeterminate() != m_element->isIndeterminate()) ||
- (s->isChecked() != m_element->isChecked()))
- return false;
-
- if (style->transitions() || style->animations())
- return false;
-
- bool classesMatch = true;
- if (s->hasClass()) {
- const AtomicString& class1 = m_element->getAttribute(classAttr);
- const AtomicString& class2 = s->getAttribute(classAttr);
- classesMatch = (class1 == class2);
- }
-
- if (classesMatch) {
- bool mappedAttrsMatch = true;
- if (s->hasMappedAttributes())
- mappedAttrsMatch = s->mappedAttributes()->mapsEquivalent(m_styledElement->mappedAttributes());
- if (mappedAttrsMatch) {
- bool linksMatch = true;
-
- if (s->isLink()) {
- // We need to check to see if the visited state matches.
- if (pseudoState == PseudoUnknown) {
- const Color& linkColor = m_element->document()->linkColor();
- const Color& visitedColor = m_element->document()->visitedLinkColor();
- pseudoState = m_checker.checkPseudoState(m_element, style->pseudoState() != PseudoAnyLink || linkColor != visitedColor);
- }
- linksMatch = (pseudoState == style->pseudoState());
- }
-
- if (linksMatch)
- return true;
- }
- }
- }
- }
- return false;
-}
-
-RenderStyle* CSSStyleSelector::locateSharedStyle()
-{
- if (m_styledElement && !m_styledElement->inlineStyleDecl() && !m_styledElement->hasID() && !m_styledElement->document()->usesSiblingRules()) {
- // Check previous siblings.
- unsigned count = 0;
- Node* n;
- for (n = m_element->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
- while (n) {
- if (canShareStyleWithElement(n))
- return n->renderStyle();
- if (count++ == cStyleSearchThreshold)
- return 0;
- for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
- }
- if (!n)
- n = locateCousinList(static_cast<Element*>(m_element->parentNode()));
- while (n) {
- if (canShareStyleWithElement(n))
- return n->renderStyle();
- if (count++ == cStyleSearchThreshold)
- return 0;
- for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
- }
- }
- return 0;
-}
-
-void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule)
-{
- // First we match rules from the user agent sheet.
- CSSRuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
- ? defaultPrintStyle : defaultStyle;
- matchRules(userAgentStyleSheet, firstUARule, lastUARule);
-
- // In quirks mode, we match rules from the quirks user agent sheet.
- if (!m_checker.m_strictParsing)
- matchRules(defaultQuirksStyle, firstUARule, lastUARule);
-
- // If we're in view source mode, then we match rules from the view source style sheet.
- if (m_checker.m_document->frame() && m_checker.m_document->frame()->inViewSourceMode())
- matchRules(defaultViewSourceStyle, firstUARule, lastUARule);
-}
-
-// If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where
-// relative units are interpreted according to document root element style, styled only with UA stylesheet
-
-RenderStyle* CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault)
-{
- // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
- // will vanish if a style recalc happens during loading.
- if (allowSharing && !e->document()->haveStylesheetsLoaded() && !e->renderer()) {
- if (!s_styleNotYetAvailable) {
- s_styleNotYetAvailable = ::new RenderStyle;
- s_styleNotYetAvailable->ref();
- s_styleNotYetAvailable->setDisplay(NONE);
- s_styleNotYetAvailable->font().update(m_fontSelector);
- }
- s_styleNotYetAvailable->ref();
- e->document()->setHasNodesWithPlaceholderStyle();
- return s_styleNotYetAvailable;
- }
-
- initElementAndPseudoState(e);
- if (allowSharing) {
- m_style = locateSharedStyle();
-#ifdef STYLE_SHARING_STATS
- fraction += m_style != 0;
- total++;
- printf("Sharing %d out of %d\n", fraction, total);
-#endif
- if (m_style) {
- m_style->ref();
- return m_style;
- }
- }
- initForStyleResolve(e, defaultParent);
-
- if (resolveForRootDefault) {
- m_style = ::new RenderStyle();
- // don't ref, because we want to delete this, but we cannot unref it
- } else {
- m_style = new (e->document()->renderArena()) RenderStyle();
- m_style->ref();
- }
- if (m_parentStyle)
- m_style->inheritFrom(m_parentStyle);
- else
- m_parentStyle = m_style;
-
-#if ENABLE(SVG)
- static bool loadedSVGUserAgentSheet;
- if (e->isSVGElement() && !loadedSVGUserAgentSheet) {
- // SVG rules.
- loadedSVGUserAgentSheet = true;
- CSSStyleSheet* svgSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
- defaultStyle->addRulesFromSheet(svgSheet, screenEval());
- defaultPrintStyle->addRulesFromSheet(svgSheet, printEval());
- }
-#endif
-
- int firstUARule = -1, lastUARule = -1;
- int firstUserRule = -1, lastUserRule = -1;
- int firstAuthorRule = -1, lastAuthorRule = -1;
- matchUARules(firstUARule, lastUARule);
-
- if (!resolveForRootDefault) {
- // 4. Now we check user sheet rules.
- if (m_matchAuthorAndUserStyles)
- matchRules(m_userStyle, firstUserRule, lastUserRule);
-
- // 5. Now check author rules, beginning first with presentational attributes
- // mapped from HTML.
- if (m_styledElement) {
- // Ask if the HTML element has mapped attributes.
- if (m_styledElement->hasMappedAttributes()) {
- // Walk our attribute list and add in each decl.
- const NamedMappedAttrMap* map = m_styledElement->mappedAttributes();
- for (unsigned i = 0; i < map->length(); i++) {
- MappedAttribute* attr = map->attributeItem(i);
- if (attr->decl()) {
- lastAuthorRule = m_matchedDecls.size();
- if (firstAuthorRule == -1)
- firstAuthorRule = lastAuthorRule;
- addMatchedDeclaration(attr->decl());
- }
- }
- }
-
- // Now we check additional mapped declarations.
- // Tables and table cells share an additional mapped rule that must be applied
- // after all attributes, since their mapped style depends on the values of multiple attributes.
- if (m_styledElement->canHaveAdditionalAttributeStyleDecls()) {
- m_additionalAttributeStyleDecls.clear();
- m_styledElement->additionalAttributeStyleDecls(m_additionalAttributeStyleDecls);
- if (!m_additionalAttributeStyleDecls.isEmpty()) {
- unsigned additionalDeclsSize = m_additionalAttributeStyleDecls.size();
- if (firstAuthorRule == -1)
- firstAuthorRule = m_matchedDecls.size();
- lastAuthorRule = m_matchedDecls.size() + additionalDeclsSize - 1;
- for (unsigned i = 0; i < additionalDeclsSize; i++)
- addMatchedDeclaration(m_additionalAttributeStyleDecls[i]);
- }
- }
- }
-
- // 6. Check the rules in author sheets next.
- if (m_matchAuthorAndUserStyles)
- matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
-
- // 7. Now check our inline style attribute.
- if (m_matchAuthorAndUserStyles && m_styledElement) {
- CSSMutableStyleDeclaration* inlineDecl = m_styledElement->inlineStyleDecl();
- if (inlineDecl) {
- lastAuthorRule = m_matchedDecls.size();
- if (firstAuthorRule == -1)
- firstAuthorRule = lastAuthorRule;
- addMatchedDeclaration(inlineDecl);
- }
- }
- }
-
- // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
- // high-priority properties first, i.e., those properties that other properties depend on.
- // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
- // and (4) normal important.
- m_lineHeightValue = 0;
- applyDeclarations(true, false, 0, m_matchedDecls.size() - 1);
- if (!resolveForRootDefault) {
- applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
- applyDeclarations(true, true, firstUserRule, lastUserRule);
- }
- applyDeclarations(true, true, firstUARule, lastUARule);
-
- // If our font got dirtied, go ahead and update it now.
- if (m_fontDirty)
- updateFont();
-
- // Line-height is set when we are sure we decided on the font-size
- if (m_lineHeightValue)
- applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
-
- // Now do the normal priority UA properties.
- applyDeclarations(false, false, firstUARule, lastUARule);
-
- // Cache our border and background so that we can examine them later.
- cacheBorderAndBackground();
-
- // Now do the author and user normal priority properties and all the !important properties.
- if (!resolveForRootDefault) {
- applyDeclarations(false, false, lastUARule + 1, m_matchedDecls.size() - 1);
- applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
- applyDeclarations(false, true, firstUserRule, lastUserRule);
- }
- applyDeclarations(false, true, firstUARule, lastUARule);
-
- // If our font got dirtied by one of the non-essential font props,
- // go ahead and update it a second time.
- if (m_fontDirty)
- updateFont();
-
- // Clean up our style object's display and text decorations (among other fixups).
- adjustRenderStyle(m_style, e);
-
- // If we are a link, cache the determined pseudo-state.
- if (e->isLink())
- m_style->setPseudoState(pseudoState);
-
- // If we have first-letter pseudo style, do not share this style
- if (m_style->hasPseudoStyle(RenderStyle::FIRST_LETTER))
- m_style->setUnique();
-
- // Now return the style.
- return m_style;
-}
-
-RenderStyle* CSSStyleSelector::pseudoStyleForElement(RenderStyle::PseudoId pseudo, Element* e, RenderStyle* parentStyle)
-{
- if (!e)
- return 0;
-
- initElementAndPseudoState(e);
- initForStyleResolve(e, parentStyle, pseudo);
- m_style = parentStyle;
-
- // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
- // those rules.
-
- // Check UA, user and author rules.
- int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1;
- matchUARules(firstUARule, lastUARule);
-
- if (m_matchAuthorAndUserStyles) {
- matchRules(m_userStyle, firstUserRule, lastUserRule);
- matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
- }
-
- if (m_matchedDecls.isEmpty())
- return 0;
-
- m_style = new (e->document()->renderArena()) RenderStyle();
- m_style->ref();
- if (parentStyle)
- m_style->inheritFrom(parentStyle);
-
- m_style->noninherited_flags._styleType = pseudo;
-
- m_lineHeightValue = 0;
- // High-priority properties.
- applyDeclarations(true, false, 0, m_matchedDecls.size() - 1);
- applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
- applyDeclarations(true, true, firstUserRule, lastUserRule);
- applyDeclarations(true, true, firstUARule, lastUARule);
-
- // If our font got dirtied, go ahead and update it now.
- if (m_fontDirty)
- updateFont();
-
- // Line-height is set when we are sure we decided on the font-size
- if (m_lineHeightValue)
- applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
-
- // Now do the normal priority properties.
- applyDeclarations(false, false, firstUARule, lastUARule);
-
- // Cache our border and background so that we can examine them later.
- cacheBorderAndBackground();
-
- applyDeclarations(false, false, lastUARule + 1, m_matchedDecls.size() - 1);
- applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
- applyDeclarations(false, true, firstUserRule, lastUserRule);
- applyDeclarations(false, true, firstUARule, lastUARule);
-
- // If our font got dirtied by one of the non-essential font props,
- // go ahead and update it a second time.
- if (m_fontDirty)
- updateFont();
- // Clean up our style object's display and text decorations (among other fixups).
- adjustRenderStyle(m_style, 0);
-
- // Now return the style.
- return m_style;
-}
-
-static void addIntrinsicMargins(RenderStyle* style)
-{
- // Intrinsic margin value.
- const int intrinsicMargin = 2 * style->effectiveZoom();
-
- // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
- // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
- if (style->width().isIntrinsicOrAuto()) {
- if (style->marginLeft().quirk())
- style->setMarginLeft(Length(intrinsicMargin, Fixed));
- if (style->marginRight().quirk())
- style->setMarginRight(Length(intrinsicMargin, Fixed));
- }
-
- if (style->height().isAuto()) {
- if (style->marginTop().quirk())
- style->setMarginTop(Length(intrinsicMargin, Fixed));
- if (style->marginBottom().quirk())
- style->setMarginBottom(Length(intrinsicMargin, Fixed));
- }
-}
-
-void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, Element *e)
-{
- // Cache our original display.
- style->setOriginalDisplay(style->display());
-
- if (style->display() != NONE) {
- // If we have a <td> that specifies a float property, in quirks mode we just drop the float
- // property.
- // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
- // these tags to retain their display types.
- if (!m_checker.m_strictParsing && e) {
- if (e->hasTagName(tdTag)) {
- style->setDisplay(TABLE_CELL);
- style->setFloating(FNONE);
- }
- else if (e->hasTagName(tableTag))
- style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
- }
-
- // Tables never support the -webkit-* values for text-align and will reset back to the default.
- if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
- style->setTextAlign(TAAUTO);
-
- // Frames and framesets never honor position:relative or position:absolute. This is necessary to
- // fix a crash where a site tries to position these objects. They also never honor display.
- if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
- style->setPosition(StaticPosition);
- style->setDisplay(BLOCK);
- }
-
- // Table headers with a text-align of auto will change the text-align to center.
- if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO)
- style->setTextAlign(CENTER);
-
- // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
- // position or float an inline, compact, or run-in. Cache the original display, since it
- // may be needed for positioned elements that have to compute their static normal flow
- // positions. We also force inline-level roots to be block-level.
- if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
- (style->position() == AbsolutePosition || style->position() == FixedPosition || style->floating() != FNONE ||
- (e && e->document()->documentElement() == e))) {
- if (style->display() == INLINE_TABLE)
- style->setDisplay(TABLE);
- else if (style->display() == INLINE_BOX)
- style->setDisplay(BOX);
- else if (style->display() == LIST_ITEM) {
- // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
- // but only in quirks mode.
- if (!m_checker.m_strictParsing && style->floating() != FNONE)
- style->setDisplay(BLOCK);
- }
- else
- style->setDisplay(BLOCK);
- }
-
- // After performing the display mutation, check table rows. We do not honor position:relative on
- // table rows or cells. This has been established in CSS2.1 (and caused a crash in containingBlock()
- // on some sites).
- if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP ||
- style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_CELL) &&
- style->position() == RelativePosition)
- style->setPosition(StaticPosition);
- }
-
- // Make sure our z-index value is only applied if the object is positioned.
- if (style->position() == StaticPosition)
- style->setHasAutoZIndex();
-
- // Auto z-index becomes 0 for the root element and transparent objects. This prevents
- // cases where objects that should be blended as a single unit end up with a non-transparent
- // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
- if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f ||
- style->hasTransform() || style->hasMask() || style->boxReflect()))
- style->setZIndex(0);
-
- // Button, legend, input, select and textarea all consider width values of 'auto' to be 'intrinsic'.
- // This will be important when we use block flows for all form controls.
- if (e && (e->hasTagName(legendTag) || e->hasTagName(buttonTag) || e->hasTagName(inputTag) ||
- e->hasTagName(selectTag) || e->hasTagName(textareaTag))) {
- if (style->width().isAuto())
- style->setWidth(Length(Intrinsic));
- }
-
- // Textarea considers overflow visible as auto.
- if (e && e->hasTagName(textareaTag)) {
- style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
- style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
- }
-
- // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
- // tables, inline blocks, inline tables, or run-ins.
- if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
- || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX)
- style->setTextDecorationsInEffect(style->textDecoration());
- else
- style->addToTextDecorationsInEffect(style->textDecoration());
-
- // If either overflow value is not visible, change to auto.
- if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
- style->setOverflowY(OMARQUEE);
- else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
- style->setOverflowX(OMARQUEE);
- else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE)
- style->setOverflowX(OAUTO);
- else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
- style->setOverflowY(OAUTO);
-
- // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
- // FIXME: Eventually table sections will support auto and scroll.
- if (style->display() == TABLE || style->display() == INLINE_TABLE ||
- style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
- if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
- style->setOverflowX(OVISIBLE);
- if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
- style->setOverflowY(OVISIBLE);
- }
-
- // Cull out any useless layers and also repeat patterns into additional layers.
- style->adjustBackgroundLayers();
- style->adjustMaskLayers();
-
- // Do the same for animations and transitions.
- style->adjustAnimations();
- style->adjustTransitions();
-
- // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
- // alter fonts and heights/widths.
- if (e && e->isControl() && style->fontSize() >= 11) {
- // Don't apply intrinsic margins to image buttons. The designer knows how big the images are,
- // so we have to treat all image buttons as though they were explicitly sized.
- if (!e->hasTagName(inputTag) || static_cast<HTMLInputElement*>(e)->inputType() != HTMLInputElement::IMAGE)
- addIntrinsicMargins(style);
- }
-
- // Let the theme also have a crack at adjusting the style.
- if (style->hasAppearance())
- theme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor);
-
-#if ENABLE(SVG)
- if (e && e->isSVGElement()) {
- // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
- if (style->overflowY() == OSCROLL)
- style->setOverflowY(OHIDDEN);
- else if (style->overflowY() == OAUTO)
- style->setOverflowY(OVISIBLE);
-
- if (style->overflowX() == OSCROLL)
- style->setOverflowX(OHIDDEN);
- else if (style->overflowX() == OAUTO)
- style->setOverflowX(OVISIBLE);
-
- // Only the root <svg> element in an SVG document fragment tree honors css position
- if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
- style->setPosition(RenderStyle::initialPosition());
- }
-#endif
-}
-
-void CSSStyleSelector::updateFont()
-{
- checkForTextSizeAdjust();
- checkForGenericFamilyChange(m_style, m_parentStyle);
- checkForZoomChange(m_style, m_parentStyle);
- m_style->font().update(m_fontSelector);
- m_fontDirty = false;
-}
-
-void CSSStyleSelector::cacheBorderAndBackground()
-{
- m_hasUAAppearance = m_style->hasAppearance();
- if (m_hasUAAppearance) {
- m_borderData = m_style->border();
- m_backgroundData = *m_style->backgroundLayers();
- m_backgroundColor = m_style->backgroundColor();
- }
-}
-
-PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, bool authorOnly)
-{
- if (!e || !e->document()->haveStylesheetsLoaded())
- return 0;
-
- m_checker.m_collectRulesOnly = true;
-
- initElementAndPseudoState(e);
- initForStyleResolve(e);
-
- if (!authorOnly) {
- int firstUARule = -1, lastUARule = -1;
- // First we match rules from the user agent sheet.
- matchUARules(firstUARule, lastUARule);
-
- // Now we check user sheet rules.
- if (m_matchAuthorAndUserStyles) {
- int firstUserRule = -1, lastUserRule = -1;
- matchRules(m_userStyle, firstUserRule, lastUserRule);
- }
- }
-
- if (m_matchAuthorAndUserStyles) {
- // Check the rules in author sheets.
- int firstAuthorRule = -1, lastAuthorRule = -1;
- matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
- }
-
- m_checker.m_collectRulesOnly = false;
-
- return m_ruleList.release();
-}
-
-PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element*, const String& pseudoStyle, bool authorOnly)
-{
- // FIXME: Implement this.
- return 0;
-}
-
-bool CSSStyleSelector::checkSelector(CSSSelector* sel)
-{
- m_dynamicPseudo = RenderStyle::NOPSEUDO;
-
- // Check the selector
- SelectorMatch match = m_checker.checkSelector(sel, m_element, &m_selectorAttrs, m_dynamicPseudo, true, false, m_style, m_parentStyle);
- if (match != SelectorMatches)
- return false;
-
- if (m_checker.m_pseudoStyle != RenderStyle::NOPSEUDO && m_checker.m_pseudoStyle != m_dynamicPseudo)
- return false;
-
- return true;
-}
-
-// Recursive check of selectors and combinators
-// It can return 3 different values:
-// * SelectorMatches - the selector matches the element e
-// * SelectorFailsLocally - the selector fails for the element e
-// * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e
-CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, RenderStyle::PseudoId& dynamicPseudo, bool isAncestor, bool isSubSelector, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
-{
-#if ENABLE(SVG)
- // Spec: CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree
- // because its contents are not part of the formal document structure.
- if (e->isSVGElement() && e->isShadowNode())
- return SelectorFailsCompletely;
-#endif
-
- // first selector has to match
- if (!checkOneSelector(sel, e, selectorAttrs, dynamicPseudo, isAncestor, isSubSelector, elementStyle, elementParentStyle))
- return SelectorFailsLocally;
-
- // The rest of the selectors has to match
- CSSSelector::Relation relation = sel->relation();
-
- // Prepare next sel
- sel = sel->m_tagHistory;
- if (!sel)
- return SelectorMatches;
-
- if (relation != CSSSelector::SubSelector)
- // Bail-out if this selector is irrelevant for the pseudoStyle
- if (m_pseudoStyle != RenderStyle::NOPSEUDO && m_pseudoStyle != dynamicPseudo)
- return SelectorFailsCompletely;
-
- switch (relation) {
- case CSSSelector::Descendant:
- while (true) {
- Node* n = e->parentNode();
- if (!n || !n->isElementNode())
- return SelectorFailsCompletely;
- e = static_cast<Element*>(n);
- SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, true, false);
- if (match != SelectorFailsLocally)
- return match;
- }
- break;
- case CSSSelector::Child:
- {
- Node* n = e->parentNode();
- if (!n || !n->isElementNode())
- return SelectorFailsCompletely;
- e = static_cast<Element*>(n);
- return checkSelector(sel, e, selectorAttrs, dynamicPseudo, true, false);
- }
- case CSSSelector::DirectAdjacent:
- {
- if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
- RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
- if (parentStyle)
- parentStyle->setChildrenAffectedByDirectAdjacentRules();
- }
- Node* n = e->previousSibling();
- while (n && !n->isElementNode())
- n = n->previousSibling();
- if (!n)
- return SelectorFailsLocally;
- e = static_cast<Element*>(n);
- return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, false);
- }
- case CSSSelector::IndirectAdjacent:
- if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
- RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
- if (parentStyle)
- parentStyle->setChildrenAffectedByForwardPositionalRules();
- }
- while (true) {
- Node* n = e->previousSibling();
- while (n && !n->isElementNode())
- n = n->previousSibling();
- if (!n)
- return SelectorFailsLocally;
- e = static_cast<Element*>(n);
- SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, false);
- if (match != SelectorFailsLocally)
- return match;
- };
- break;
- case CSSSelector::SubSelector:
- // a selector is invalid if something follows a pseudo-element
- if (elementStyle && dynamicPseudo != RenderStyle::NOPSEUDO)
- return SelectorFailsCompletely;
- return checkSelector(sel, e, selectorAttrs, dynamicPseudo, isAncestor, true, elementStyle, elementParentStyle);
- }
-
- return SelectorFailsCompletely;
-}
-
-static void addLocalNameToSet(HashSet<AtomicStringImpl*>* set, const QualifiedName& qName)
-{
- set->add(qName.localName().impl());
-}
-
-static HashSet<AtomicStringImpl*>* createHtmlCaseInsensitiveAttributesSet()
-{
- // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive
- // Mozilla treats all other values as case-sensitive, thus so do we.
- HashSet<AtomicStringImpl*>* attrSet = new HashSet<AtomicStringImpl*>;
-
- addLocalNameToSet(attrSet, accept_charsetAttr);
- addLocalNameToSet(attrSet, acceptAttr);
- addLocalNameToSet(attrSet, alignAttr);
- addLocalNameToSet(attrSet, alinkAttr);
- addLocalNameToSet(attrSet, axisAttr);
- addLocalNameToSet(attrSet, bgcolorAttr);
- addLocalNameToSet(attrSet, charsetAttr);
- addLocalNameToSet(attrSet, checkedAttr);
- addLocalNameToSet(attrSet, clearAttr);
- addLocalNameToSet(attrSet, codetypeAttr);
- addLocalNameToSet(attrSet, colorAttr);
- addLocalNameToSet(attrSet, compactAttr);
- addLocalNameToSet(attrSet, declareAttr);
- addLocalNameToSet(attrSet, deferAttr);
- addLocalNameToSet(attrSet, dirAttr);
- addLocalNameToSet(attrSet, disabledAttr);
- addLocalNameToSet(attrSet, enctypeAttr);
- addLocalNameToSet(attrSet, faceAttr);
- addLocalNameToSet(attrSet, frameAttr);
- addLocalNameToSet(attrSet, hreflangAttr);
- addLocalNameToSet(attrSet, http_equivAttr);
- addLocalNameToSet(attrSet, langAttr);
- addLocalNameToSet(attrSet, languageAttr);
- addLocalNameToSet(attrSet, linkAttr);
- addLocalNameToSet(attrSet, mediaAttr);
- addLocalNameToSet(attrSet, methodAttr);
- addLocalNameToSet(attrSet, multipleAttr);
- addLocalNameToSet(attrSet, nohrefAttr);
- addLocalNameToSet(attrSet, noresizeAttr);
- addLocalNameToSet(attrSet, noshadeAttr);
- addLocalNameToSet(attrSet, nowrapAttr);
- addLocalNameToSet(attrSet, readonlyAttr);
- addLocalNameToSet(attrSet, relAttr);
- addLocalNameToSet(attrSet, revAttr);
- addLocalNameToSet(attrSet, rulesAttr);
- addLocalNameToSet(attrSet, scopeAttr);
- addLocalNameToSet(attrSet, scrollingAttr);
- addLocalNameToSet(attrSet, selectedAttr);
- addLocalNameToSet(attrSet, shapeAttr);
- addLocalNameToSet(attrSet, targetAttr);
- addLocalNameToSet(attrSet, textAttr);
- addLocalNameToSet(attrSet, typeAttr);
- addLocalNameToSet(attrSet, valignAttr);
- addLocalNameToSet(attrSet, valuetypeAttr);
- addLocalNameToSet(attrSet, vlinkAttr);
-
- return attrSet;
-}
-
-static bool htmlAttributeHasCaseInsensitiveValue(const QualifiedName& attr)
-{
- static HashSet<AtomicStringImpl*>* htmlCaseInsensitiveAttributesSet = createHtmlCaseInsensitiveAttributesSet();
- bool isPossibleHTMLAttr = !attr.hasPrefix() && (attr.namespaceURI() == nullAtom);
- return isPossibleHTMLAttr && htmlCaseInsensitiveAttributesSet->contains(attr.localName().impl());
-}
-
-bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, RenderStyle::PseudoId& dynamicPseudo, bool isAncestor, bool isSubSelector, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
-{
- if (!e)
- return false;
-
- if (sel->hasTag()) {
- const AtomicString& selLocalName = sel->m_tag.localName();
- if (selLocalName != starAtom && selLocalName != e->localName())
- return false;
- const AtomicString& selNS = sel->m_tag.namespaceURI();
- if (selNS != starAtom && selNS != e->namespaceURI())
- return false;
- }
-
- if (sel->hasAttribute()) {
- if (sel->m_match == CSSSelector::Class)
- return e->hasClass() && static_cast<StyledElement*>(e)->classNames().contains(sel->m_value);
-
- if (sel->m_match == CSSSelector::Id)
- return e->hasID() && e->getIDAttribute() == sel->m_value;
-
- // FIXME: Handle the case were elementStyle is 0.
- if (elementStyle && (!e->isStyledElement() || (!static_cast<StyledElement*>(e)->isMappedAttribute(sel->m_attr) && sel->m_attr != typeAttr && sel->m_attr != readonlyAttr))) {
- elementStyle->setAffectedByAttributeSelectors(); // Special-case the "type" and "readonly" attributes so input form controls can share style.
- if (selectorAttrs)
- selectorAttrs->add(sel->m_attr.localName().impl());
- }
-
- const AtomicString& value = e->getAttribute(sel->m_attr);
- if (value.isNull())
- return false; // attribute is not set
-
- bool caseSensitive = !m_documentIsHTML || !htmlAttributeHasCaseInsensitiveValue(sel->m_attr);
-
- switch (sel->m_match) {
- case CSSSelector::Exact:
- if (caseSensitive ? sel->m_value != value : !equalIgnoringCase(sel->m_value, value))
- return false;
- break;
- case CSSSelector::List:
- {
- // Ignore empty selectors or selectors containing spaces
- if (sel->m_value.contains(' ') || sel->m_value.isEmpty())
- return false;
-
- int startSearchAt = 0;
- while (true) {
- int foundPos = value.find(sel->m_value, startSearchAt, caseSensitive);
- if (foundPos == -1)
- return false;
- if (foundPos == 0 || value[foundPos-1] == ' ') {
- unsigned endStr = foundPos + sel->m_value.length();
- if (endStr == value.length() || value[endStr] == ' ')
- break; // We found a match.
- }
-
- // No match. Keep looking.
- startSearchAt = foundPos + 1;
- }
- break;
- }
- case CSSSelector::Contain:
- if (!value.contains(sel->m_value, caseSensitive) || sel->m_value.isEmpty())
- return false;
- break;
- case CSSSelector::Begin:
- if (!value.startsWith(sel->m_value, caseSensitive) || sel->m_value.isEmpty())
- return false;
- break;
- case CSSSelector::End:
- if (!value.endsWith(sel->m_value, caseSensitive) || sel->m_value.isEmpty())
- return false;
- break;
- case CSSSelector::Hyphen:
- if (value.length() < sel->m_value.length())
- return false;
- if (!value.startsWith(sel->m_value, caseSensitive))
- return false;
- // It they start the same, check for exact match or following '-':
- if (value.length() != sel->m_value.length() && value[sel->m_value.length()] != '-')
- return false;
- break;
- case CSSSelector::PseudoClass:
- case CSSSelector::PseudoElement:
- default:
- break;
- }
- }
- if (sel->m_match == CSSSelector::PseudoClass) {
- switch (sel->pseudoType()) {
- // Pseudo classes:
- case CSSSelector::PseudoEmpty: {
- bool result = true;
- for (Node* n = e->firstChild(); n; n = n->nextSibling()) {
- if (n->isElementNode()) {
- result = false;
- break;
- } else if (n->isTextNode()) {
- Text* textNode = static_cast<Text*>(n);
- if (!textNode->data().isEmpty()) {
- result = false;
- break;
- }
- }
- }
- if (!m_collectRulesOnly) {
- if (elementStyle)
- elementStyle->setEmptyState(result);
- else if (e->renderStyle() && (e->document()->usesSiblingRules() || e->renderStyle()->unique()))
- e->renderStyle()->setEmptyState(result);
- }
- return result;
- }
- case CSSSelector::PseudoFirstChild: {
- // first-child matches the first child that is an element
- if (e->parentNode() && e->parentNode()->isElementNode()) {
- bool result = false;
- Node* n = e->previousSibling();
- while (n && !n->isElementNode())
- n = n->previousSibling();
- if (!n)
- result = true;
- if (!m_collectRulesOnly) {
- RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
- RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
- if (parentStyle)
- parentStyle->setChildrenAffectedByFirstChildRules();
- if (result && childStyle)
- childStyle->setFirstChildState();
- }
- return result;
- }
- break;
- }
- case CSSSelector::PseudoFirstOfType: {
- // first-of-type matches the first element of its type
- if (e->parentNode() && e->parentNode()->isElementNode()) {
- bool result = false;
- const QualifiedName& type = e->tagQName();
- Node* n = e->previousSibling();
- while (n) {
- if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
- break;
- n = n->previousSibling();
- }
- if (!n)
- result = true;
- if (!m_collectRulesOnly) {
- RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
- if (parentStyle)
- parentStyle->setChildrenAffectedByForwardPositionalRules();
- }
- return result;
- }
- break;
- }
- case CSSSelector::PseudoLastChild: {
- // last-child matches the last child that is an element
- if (e->parentNode() && e->parentNode()->isElementNode()) {
- Element* parentNode = static_cast<Element*>(e->parentNode());
- bool result = false;
- if (parentNode->isFinishedParsingChildren()) {
- Node* n = e->nextSibling();
- while (n && !n->isElementNode())
- n = n->nextSibling();
- if (!n)
- result = true;
- }
- if (!m_collectRulesOnly) {
- RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
- RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentNode->renderStyle();
- if (parentStyle)
- parentStyle->setChildrenAffectedByLastChildRules();
- if (result && childStyle)
- childStyle->setLastChildState();
- }
- return result;
- }
- break;
- }
- case CSSSelector::PseudoLastOfType: {
- // last-of-type matches the last element of its type
- if (e->parentNode() && e->parentNode()->isElementNode()) {
- Element* parentNode = static_cast<Element*>(e->parentNode());
- if (!m_collectRulesOnly) {
- RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentNode->renderStyle();
- if (parentStyle)
- parentStyle->setChildrenAffectedByBackwardPositionalRules();
- }
- if (!parentNode->isFinishedParsingChildren())
- return false;
- bool result = false;
- const QualifiedName& type = e->tagQName();
- Node* n = e->nextSibling();
- while (n) {
- if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
- break;
- n = n->nextSibling();
- }
- if (!n)
- result = true;
- return result;
- }
- break;
- }
- case CSSSelector::PseudoOnlyChild: {
- if (e->parentNode() && e->parentNode()->isElementNode()) {
- Element* parentNode = static_cast<Element*>(e->parentNode());
- bool firstChild = false;
- bool lastChild = false;
-
- Node* n = e->previousSibling();
- while (n && !n->isElementNode())
- n = n->previousSibling();
- if (!n)
- firstChild = true;
- if (firstChild && parentNode->isFinishedParsingChildren()) {
- n = e->nextSibling();
- while (n && !n->isElementNode())
- n = n->nextSibling();
- if (!n)
- lastChild = true;
- }
- if (!m_collectRulesOnly) {
- RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
- RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentNode->renderStyle();
- if (parentStyle) {
- parentStyle->setChildrenAffectedByFirstChildRules();
- parentStyle->setChildrenAffectedByLastChildRules();
- }
- if (firstChild && childStyle)
- childStyle->setFirstChildState();
- if (lastChild && childStyle)
- childStyle->setLastChildState();
- }
- return firstChild && lastChild;
- }
- break;
- }
- case CSSSelector::PseudoOnlyOfType: {
- // FIXME: This selector is very slow.
- if (e->parentNode() && e->parentNode()->isElementNode()) {
- Element* parentNode = static_cast<Element*>(e->parentNode());
- if (!m_collectRulesOnly) {
- RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentNode->renderStyle();
- if (parentStyle) {
- parentStyle->setChildrenAffectedByForwardPositionalRules();
- parentStyle->setChildrenAffectedByBackwardPositionalRules();
- }
- }
- if (!parentNode->isFinishedParsingChildren())
- return false;
- bool firstChild = false;
- bool lastChild = false;
- const QualifiedName& type = e->tagQName();
- Node* n = e->previousSibling();
- while (n) {
- if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
- break;
- n = n->previousSibling();
- }
- if (!n)
- firstChild = true;
- if (firstChild) {
- n = e->nextSibling();
- while (n) {
- if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
- break;
- n = n->nextSibling();
- }
- if (!n)
- lastChild = true;
- }
- return firstChild && lastChild;
- }
- break;
- }
- case CSSSelector::PseudoNthChild: {
- int a, b;
- // calculate a and b every time we run through checkOneSelector
- // this should probably be saved after we calculate it once, but currently
- // would require increasing the size of CSSSelector
- if (!parseNth(sel->m_argument, a, b))
- break;
- if (e->parentNode() && e->parentNode()->isElementNode()) {
- int count = 1;
- Node* n = e->previousSibling();
- while (n) {
- if (n->isElementNode()) {
- RenderStyle* s = n->renderStyle();
- unsigned index = s ? s->childIndex() : 0;
- if (index) {
- count += index;
- break;
- }
- count++;
- }
- n = n->previousSibling();
- }
-
- if (!m_collectRulesOnly) {
- RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
- RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
- if (childStyle)
- childStyle->setChildIndex(count);
- if (parentStyle)
- parentStyle->setChildrenAffectedByForwardPositionalRules();
- }
-
- if (matchNth(count, a, b))
- return true;
- }
- break;
- }
- case CSSSelector::PseudoNthOfType: {
- // FIXME: This selector is very slow.
- int a, b;
- // calculate a and b every time we run through checkOneSelector (see above)
- if (!parseNth(sel->m_argument, a, b))
- break;
- if (e->parentNode() && e->parentNode()->isElementNode()) {
- int count = 1;
- const QualifiedName& type = e->tagQName();
- Node* n = e->previousSibling();
- while (n) {
- if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
- count++;
- n = n->previousSibling();
- }
-
- if (!m_collectRulesOnly) {
- RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
- if (parentStyle)
- parentStyle->setChildrenAffectedByForwardPositionalRules();
- }
-
- if (matchNth(count, a, b))
- return true;
- }
- break;
- }
- case CSSSelector::PseudoNthLastChild: {
- int a, b;
- // calculate a and b every time we run through checkOneSelector
- // this should probably be saved after we calculate it once, but currently
- // would require increasing the size of CSSSelector
- if (!parseNth(sel->m_argument, a, b))
- break;
- if (e->parentNode() && e->parentNode()->isElementNode()) {
- Element* parentNode = static_cast<Element*>(e->parentNode());
- if (!m_collectRulesOnly) {
- RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentNode->renderStyle();
- if (parentStyle)
- parentStyle->setChildrenAffectedByBackwardPositionalRules();
- }
- if (!parentNode->isFinishedParsingChildren())
- return false;
- int count = 1;
- Node* n = e->nextSibling();
- while (n) {
- if (n->isElementNode())
- count++;
- n = n->nextSibling();
- }
- if (matchNth(count, a, b))
- return true;
- }
- break;
- }
- case CSSSelector::PseudoNthLastOfType: {
- // FIXME: This selector is very slow.
- int a, b;
- // calculate a and b every time we run through checkOneSelector (see above)
- if (!parseNth(sel->m_argument, a, b))
- break;
- if (e->parentNode() && e->parentNode()->isElementNode()) {
- Element* parentNode = static_cast<Element*>(e->parentNode());
- if (!m_collectRulesOnly) {
- RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentNode->renderStyle();
- if (parentStyle)
- parentStyle->setChildrenAffectedByBackwardPositionalRules();
- }
- if (!parentNode->isFinishedParsingChildren())
- return false;
- int count = 1;
- const QualifiedName& type = e->tagQName();
- Node* n = e->nextSibling();
- while (n) {
- if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
- count++;
- n = n->nextSibling();
- }
- if (matchNth(count, a, b))
- return true;
- }
- break;
- }
- case CSSSelector::PseudoTarget:
- if (e == e->document()->getCSSTarget())
- return true;
- break;
- case CSSSelector::PseudoAnyLink:
- if (pseudoState == PseudoUnknown)
- pseudoState = checkPseudoState(e, false);
- if (pseudoState == PseudoAnyLink || pseudoState == PseudoLink || pseudoState == PseudoVisited)
- return true;
- break;
- case CSSSelector::PseudoAutofill:
- if (e && e->hasTagName(inputTag))
- return static_cast<HTMLInputElement*>(e)->autofilled();
- break;
- case CSSSelector::PseudoLink:
- if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink)
- pseudoState = checkPseudoState(e);
- if (pseudoState == PseudoLink)
- return true;
- break;
- case CSSSelector::PseudoVisited:
- if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink)
- pseudoState = checkPseudoState(e);
- if (pseudoState == PseudoVisited)
- return true;
- break;
- case CSSSelector::PseudoDrag: {
- if (elementStyle)
- elementStyle->setAffectedByDragRules(true);
- else if (e->renderStyle())
- e->renderStyle()->setAffectedByDragRules(true);
- if (e->renderer() && e->renderer()->isDragging())
- return true;
- break;
- }
- case CSSSelector::PseudoFocus:
- if (e && e->focused() && e->document()->frame()->selection()->isFocusedAndActive())
- return true;
- break;
- case CSSSelector::PseudoHover: {
- // If we're in quirks mode, then hover should never match anchors with no
- // href and *:hover should not match anything. This is important for sites like wsj.com.
- if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
- if (elementStyle)
- elementStyle->setAffectedByHoverRules(true);
- else if (e->renderStyle())
- e->renderStyle()->setAffectedByHoverRules(true);
- if (e->hovered())
- return true;
- }
- break;
- }
- case CSSSelector::PseudoActive:
- // If we're in quirks mode, then :active should never match anchors with no
- // href and *:active should not match anything.
- if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
- if (elementStyle)
- elementStyle->setAffectedByActiveRules(true);
- else if (e->renderStyle())
- e->renderStyle()->setAffectedByActiveRules(true);
- if (e->active())
- return true;
- }
- break;
- case CSSSelector::PseudoEnabled:
- if (e && e->isControl() && !e->isInputTypeHidden())
- // The UI spec states that you can't match :enabled unless you are an object that can
- // "receive focus and be activated." We will limit matching of this pseudo-class to elements
- // that are non-"hidden" controls.
- return e->isEnabled();
- break;
- case CSSSelector::PseudoFullPageMedia:
- return e && e->document() && e->document()->isMediaDocument();
- break;
- case CSSSelector::PseudoDisabled:
- if (e && e->isControl() && !e->isInputTypeHidden())
- // The UI spec states that you can't match :enabled unless you are an object that can
- // "receive focus and be activated." We will limit matching of this pseudo-class to elements
- // that are non-"hidden" controls.
- return !e->isEnabled();
- break;
- case CSSSelector::PseudoReadOnly:
- return e && e->isTextControl() && e->isReadOnlyControl();
- case CSSSelector::PseudoReadWrite:
- return e && e->isTextControl() && !e->isReadOnlyControl();
- case CSSSelector::PseudoChecked:
- // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that
- // you can't be both checked and indeterminate. We will behave like WinIE behind the scenes and just
- // obey the CSS spec here in the test for matching the pseudo.
- if (e && e->isChecked() && !e->isIndeterminate())
- return true;
- break;
- case CSSSelector::PseudoIndeterminate:
- if (e && e->isIndeterminate())
- return true;
- break;
- case CSSSelector::PseudoRoot:
- if (e == e->document()->documentElement())
- return true;
- break;
- case CSSSelector::PseudoLang: {
- Node* n = e;
- AtomicString value;
- // The language property is inherited, so we iterate over the parents
- // to find the first language.
- while (n && value.isEmpty()) {
- if (n->isElementNode()) {
- // Spec: xml:lang takes precedence -- http://www.w3.org/TR/xhtml1/#C_7
- value = static_cast<Element*>(n)->getAttribute(XMLNames::langAttr);
- if (value.isEmpty())
- value = static_cast<Element*>(n)->getAttribute(langAttr);
- } else if (n->isDocumentNode())
- // checking the MIME content-language
- value = static_cast<Document*>(n)->contentLanguage();
-
- n = n->parent();
- }
- if (value.isEmpty() || !value.startsWith(sel->m_argument, false))
- break;
- if (value.length() != sel->m_argument.length() && value[sel->m_argument.length()] != '-')
- break;
- return true;
- }
- case CSSSelector::PseudoNot: {
- // check the simple selector
- for (CSSSelector* subSel = sel->m_simpleSelector; subSel; subSel = subSel->m_tagHistory) {
- // :not cannot nest. I don't really know why this is a
- // restriction in CSS3, but it is, so let's honour it.
- if (subSel->m_simpleSelector)
- break;
- if (!checkOneSelector(subSel, e, selectorAttrs, dynamicPseudo, isAncestor, true, elementStyle, elementParentStyle))
- return true;
- }
- break;
- }
- case CSSSelector::PseudoUnknown:
- case CSSSelector::PseudoNotParsed:
- default:
- ASSERT_NOT_REACHED();
- break;
- }
- return false;
- }
- if (sel->m_match == CSSSelector::PseudoElement) {
- if (!elementStyle)
- return false;
-
- switch (sel->pseudoType()) {
- // Pseudo-elements:
- case CSSSelector::PseudoFirstLine:
- dynamicPseudo = RenderStyle::FIRST_LINE;
- return true;
- case CSSSelector::PseudoFirstLetter:
- dynamicPseudo = RenderStyle::FIRST_LETTER;
- if (Document* doc = e->document())
- doc->setUsesFirstLetterRules(true);
- return true;
- case CSSSelector::PseudoSelection:
- dynamicPseudo = RenderStyle::SELECTION;
- return true;
- case CSSSelector::PseudoBefore:
- dynamicPseudo = RenderStyle::BEFORE;
- return true;
- case CSSSelector::PseudoAfter:
- dynamicPseudo = RenderStyle::AFTER;
- return true;
- case CSSSelector::PseudoFileUploadButton:
- dynamicPseudo = RenderStyle::FILE_UPLOAD_BUTTON;
- return true;
- case CSSSelector::PseudoSliderThumb:
- dynamicPseudo = RenderStyle::SLIDER_THUMB;
- return true;
- case CSSSelector::PseudoSearchCancelButton:
- dynamicPseudo = RenderStyle::SEARCH_CANCEL_BUTTON;
- return true;
- case CSSSelector::PseudoSearchDecoration:
- dynamicPseudo = RenderStyle::SEARCH_DECORATION;
- return true;
- case CSSSelector::PseudoSearchResultsDecoration:
- dynamicPseudo = RenderStyle::SEARCH_RESULTS_DECORATION;
- return true;
- case CSSSelector::PseudoSearchResultsButton:
- dynamicPseudo = RenderStyle::SEARCH_RESULTS_BUTTON;
- return true;
- case CSSSelector::PseudoMediaControlsPanel:
- dynamicPseudo = RenderStyle::MEDIA_CONTROLS_PANEL;
- return true;
- case CSSSelector::PseudoMediaControlsMuteButton:
- dynamicPseudo = RenderStyle::MEDIA_CONTROLS_MUTE_BUTTON;
- return true;
- case CSSSelector::PseudoMediaControlsPlayButton:
- dynamicPseudo = RenderStyle::MEDIA_CONTROLS_PLAY_BUTTON;
- return true;
- case CSSSelector::PseudoMediaControlsTimeDisplay:
- dynamicPseudo = RenderStyle::MEDIA_CONTROLS_TIME_DISPLAY;
- return true;
- case CSSSelector::PseudoMediaControlsTimeline:
- dynamicPseudo = RenderStyle::MEDIA_CONTROLS_TIMELINE;
- return true;
- case CSSSelector::PseudoMediaControlsSeekBackButton:
- dynamicPseudo = RenderStyle::MEDIA_CONTROLS_SEEK_BACK_BUTTON;
- return true;
- case CSSSelector::PseudoMediaControlsSeekForwardButton:
- dynamicPseudo = RenderStyle::MEDIA_CONTROLS_SEEK_FORWARD_BUTTON;
- return true;
- case CSSSelector::PseudoMediaControlsFullscreenButton:
- dynamicPseudo = RenderStyle::MEDIA_CONTROLS_FULLSCREEN_BUTTON;
- return true;
- case CSSSelector::PseudoUnknown:
- case CSSSelector::PseudoNotParsed:
- default:
- ASSERT_NOT_REACHED();
- break;
- }
- return false;
- }
- // ### add the rest of the checks...
- return true;
-}
-
-void CSSStyleSelector::addVariables(CSSVariablesRule* variables)
-{
- CSSVariablesDeclaration* decl = variables->variables();
- if (!decl)
- return;
- unsigned size = decl->length();
- for (unsigned i = 0; i < size; ++i) {
- String name = decl->item(i);
- m_variablesMap.set(name, variables);
- }
-}
-
-CSSValue* CSSStyleSelector::resolveVariableDependentValue(CSSVariableDependentValue* val)
-{
- return 0;
-}
-
-// -----------------------------------------------------------------
-
-CSSRuleSet::CSSRuleSet()
-{
- m_universalRules = 0;
- m_ruleCount = 0;
-}
-
-CSSRuleSet::~CSSRuleSet()
-{
- deleteAllValues(m_idRules);
- deleteAllValues(m_classRules);
- deleteAllValues(m_tagRules);
-
- delete m_universalRules;
-}
-
-
-void CSSRuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
- CSSStyleRule* rule, CSSSelector* sel)
-{
- if (!key) return;
- CSSRuleDataList* rules = map.get(key);
- if (!rules) {
- rules = new CSSRuleDataList(m_ruleCount++, rule, sel);
- map.set(key, rules);
- } else
- rules->append(m_ruleCount++, rule, sel);
-}
-
-void CSSRuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
-{
- if (sel->m_match == CSSSelector::Id) {
- addToRuleSet(sel->m_value.impl(), m_idRules, rule, sel);
- return;
- }
- if (sel->m_match == CSSSelector::Class) {
- addToRuleSet(sel->m_value.impl(), m_classRules, rule, sel);
- return;
- }
-
- const AtomicString& localName = sel->m_tag.localName();
- if (localName != starAtom) {
- addToRuleSet(localName.impl(), m_tagRules, rule, sel);
- return;
- }
-
- // Just put it in the universal rule set.
- if (!m_universalRules)
- m_universalRules = new CSSRuleDataList(m_ruleCount++, rule, sel);
- else
- m_universalRules->append(m_ruleCount++, rule, sel);
-}
-
-void CSSRuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector)
-{
- if (!sheet)
- return;
-
- // No media implies "all", but if a media list exists it must
- // contain our current medium
- if (sheet->media() && !medium.eval(sheet->media(), styleSelector))
- return; // the style sheet doesn't apply
-
- int len = sheet->length();
-
- for (int i = 0; i < len; i++) {
- StyleBase* item = sheet->item(i);
- if (item->isStyleRule()) {
- CSSStyleRule* rule = static_cast<CSSStyleRule*>(item);
- for (CSSSelector* s = rule->selector(); s; s = s->next())
- addRule(rule, s);
- }
- else if (item->isImportRule()) {
- CSSImportRule* import = static_cast<CSSImportRule*>(item);
- if (!import->media() || medium.eval(import->media(), styleSelector))
- addRulesFromSheet(import->styleSheet(), medium, styleSelector);
- }
- else if (item->isMediaRule()) {
- CSSMediaRule* r = static_cast<CSSMediaRule*>(item);
- CSSRuleList* rules = r->cssRules();
-
- if ((!r->media() || medium.eval(r->media(), styleSelector)) && rules) {
- // Traverse child elements of the @media rule.
- for (unsigned j = 0; j < rules->length(); j++) {
- CSSRule *childItem = rules->item(j);
- if (childItem->isStyleRule()) {
- // It is a StyleRule, so append it to our list
- CSSStyleRule* rule = static_cast<CSSStyleRule*>(childItem);
- for (CSSSelector* s = rule->selector(); s; s = s->next())
- addRule(rule, s);
- } else if (childItem->isFontFaceRule() && styleSelector) {
- // Add this font face to our set.
- const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(childItem);
- styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
- } else if (childItem->isKeyframesRule() && styleSelector) {
- // Add this keyframe rule to our set.
- const WebKitCSSKeyframesRule* keyframesRule = static_cast<WebKitCSSKeyframesRule*>(childItem);
- styleSelector->addKeyframeStyle(sheet->doc(), keyframesRule);
- }
- } // for rules
- } // if rules
- } else if (item->isFontFaceRule() && styleSelector) {
- // Add this font face to our set.
- const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(item);
- styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
- } else if (item->isVariablesRule()) {
- // Evaluate the media query and make sure it matches.
- CSSVariablesRule* variables = static_cast<CSSVariablesRule*>(item);
- if (!variables->media() || medium.eval(variables->media(), styleSelector))
- styleSelector->addVariables(variables);
- } else if (item->isKeyframesRule()) {
- WebKitCSSKeyframesRule* r = static_cast<WebKitCSSKeyframesRule*>(item);
- styleSelector->addKeyframeStyle(sheet->doc(), r);
- }
- }
-}
-
-// -------------------------------------------------------------------------------------
-// this is mostly boring stuff on how to apply a certain rule to the renderstyle...
-
-static Length convertToLength(CSSPrimitiveValue *primitiveValue, RenderStyle *style, bool *ok = 0)
-{
- Length l;
- if (!primitiveValue) {
- if (ok)
- *ok = false;
- } else {
- int type = primitiveValue->primitiveType();
- if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
- l = Length(primitiveValue->computeLengthIntForLength(style), Fixed);
- else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
- l = Length(primitiveValue->getDoubleValue(), Percent);
- else if (type == CSSPrimitiveValue::CSS_NUMBER)
- l = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
- else if (ok)
- *ok = false;
- }
- return l;
-}
-
-void CSSStyleSelector::applyDeclarations(bool applyFirst, bool isImportant,
- int startIndex, int endIndex)
-{
- if (startIndex == -1)
- return;
-
- for (int i = startIndex; i <= endIndex; i++) {
- CSSMutableStyleDeclaration* decl = m_matchedDecls[i];
- DeprecatedValueListConstIterator<CSSProperty> end;
- for (DeprecatedValueListConstIterator<CSSProperty> it = decl->valuesIterator(); it != end; ++it) {
- const CSSProperty& current = *it;
- // give special priority to font-xxx, color properties
- if (isImportant == current.isImportant()) {
- bool first;
- switch (current.id()) {
- case CSSPropertyLineHeight:
- m_lineHeightValue = current.value();
- first = !applyFirst; // we apply line-height later
- break;
- case CSSPropertyColor:
- case CSSPropertyDirection:
- case CSSPropertyDisplay:
- case CSSPropertyFont:
- case CSSPropertyFontSize:
- case CSSPropertyFontStyle:
- case CSSPropertyFontFamily:
- case CSSPropertyFontWeight:
- case CSSPropertyWebkitTextSizeAdjust:
- case CSSPropertyFontVariant:
- case CSSPropertyZoom:
- // these have to be applied first, because other properties use the computed
- // values of these porperties.
- first = true;
- break;
- default:
- first = false;
- break;
- }
- if (first == applyFirst)
- applyProperty(current.id(), current.value());
- }
- }
- }
-}
-
-static void applyCounterList(RenderStyle* style, CSSValueList* list, bool isReset)
-{
- CounterDirectiveMap& map = style->accessCounterDirectives();
- typedef CounterDirectiveMap::iterator Iterator;
-
- Iterator end = map.end();
- for (Iterator it = map.begin(); it != end; ++it)
- if (isReset)
- it->second.m_reset = false;
- else
- it->second.m_increment = false;
-
- int length = list ? list->length() : 0;
- for (int i = 0; i < length; ++i) {
- Pair* pair = static_cast<CSSPrimitiveValue*>(list->itemWithoutBoundsCheck(i))->getPairValue();
- AtomicString identifier = static_cast<CSSPrimitiveValue*>(pair->first())->getStringValue();
- // FIXME: What about overflow?
- int value = static_cast<CSSPrimitiveValue*>(pair->second())->getIntValue();
- CounterDirectives& directives = map.add(identifier.impl(), CounterDirectives()).first->second;
- if (isReset) {
- directives.m_reset = true;
- directives.m_resetValue = value;
- } else {
- if (directives.m_increment)
- directives.m_incrementValue += value;
- else {
- directives.m_increment = true;
- directives.m_incrementValue = value;
- }
- }
- }
-}
-
-struct ScriptFamilyState {
- bool isGenericAdded;
- bool isPerScriptGenericChecked;
- ScriptFamilyState() : isGenericAdded(false), isPerScriptGenericChecked(false)
- {}
-};
-
-inline static void handleScriptFamily(const char* webkitFamily, UScriptCode script,
- FontDescription::GenericFamilyType generic,
- AtomicString& face, ScriptFamilyState& state, FontDescription& fontDescription,
- int& familyIndex)
-{
- if (!state.isGenericAdded) {
- face = webkitFamily;
- state.isGenericAdded = true;
- fontDescription.setGenericFamily(generic);
- // go through this once more to add per-script generic family.
- --familyIndex;
- } else if (!state.isPerScriptGenericChecked) {
- face = FontCache::getGenericFontForScript(script, fontDescription);
- state.isPerScriptGenericChecked = true;
- }
-}
-
-void CSSStyleSelector::applyPropertyToStyle(int id, CSSValue *value, RenderStyle* style)
-{
- initElementAndPseudoState(0);
- initForStyleResolve(0, style);
- m_style = style;
- applyProperty(id, value);
-}
-
-void CSSStyleSelector::applyProperty(int id, CSSValue *value)
-{
- CSSPrimitiveValue* primitiveValue = 0;
- if (value->isPrimitiveValue())
- primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-
- float zoomFactor = m_style->effectiveZoom();
-
- Length l;
- bool apply = false;
-
- unsigned short valueType = value->cssValueType();
-
- bool isInherit = m_parentNode && valueType == CSSValue::CSS_INHERIT;
- bool isInitial = valueType == CSSValue::CSS_INITIAL || (!m_parentNode && valueType == CSSValue::CSS_INHERIT);
-
- // These properties are used to set the correct margins/padding on RTL lists.
- if (id == CSSPropertyWebkitMarginStart)
- id = m_style->direction() == LTR ? CSSPropertyMarginLeft : CSSPropertyMarginRight;
- else if (id == CSSPropertyWebkitPaddingStart)
- id = m_style->direction() == LTR ? CSSPropertyPaddingLeft : CSSPropertyPaddingRight;
-
- // What follows is a list that maps the CSS properties into their corresponding front-end
- // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and
- // are only hit when mapping "inherit" or "initial" into front-end values.
- switch (static_cast<CSSPropertyID>(id)) {
-// ident only properties
- case CSSPropertyBackgroundAttachment:
- HANDLE_BACKGROUND_VALUE(attachment, Attachment, value)
- return;
- case CSSPropertyWebkitBackgroundClip:
- HANDLE_BACKGROUND_VALUE(clip, Clip, value)
- return;
- case CSSPropertyWebkitBackgroundComposite:
- HANDLE_BACKGROUND_VALUE(composite, Composite, value)
- return;
- case CSSPropertyWebkitBackgroundOrigin:
- HANDLE_BACKGROUND_VALUE(origin, Origin, value)
- return;
- case CSSPropertyBackgroundRepeat:
- HANDLE_BACKGROUND_VALUE(repeat, Repeat, value)
- return;
- case CSSPropertyWebkitBackgroundSize:
- HANDLE_BACKGROUND_VALUE(size, Size, value)
- return;
- case CSSPropertyWebkitMaskAttachment:
- HANDLE_MASK_VALUE(attachment, Attachment, value)
- return;
- case CSSPropertyWebkitMaskClip:
- HANDLE_MASK_VALUE(clip, Clip, value)
- return;
- case CSSPropertyWebkitMaskComposite:
- HANDLE_MASK_VALUE(composite, Composite, value)
- return;
- case CSSPropertyWebkitMaskOrigin:
- HANDLE_MASK_VALUE(origin, Origin, value)
- return;
- case CSSPropertyWebkitMaskRepeat:
- HANDLE_MASK_VALUE(repeat, Repeat, value)
- return;
- case CSSPropertyWebkitMaskSize:
- HANDLE_MASK_VALUE(size, Size, value)
- return;
- case CSSPropertyBorderCollapse:
- HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse)
- if (!primitiveValue)
- return;
- switch (primitiveValue->getIdent()) {
- case CSSValueCollapse:
- m_style->setBorderCollapse(true);
- break;
- case CSSValueSeparate:
- m_style->setBorderCollapse(false);
- break;
- default:
- return;
- }
- return;
-
- case CSSPropertyBorderTopStyle:
- HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle)
- if (primitiveValue)
- m_style->setBorderTopStyle(*primitiveValue);
- return;
- case CSSPropertyBorderRightStyle:
- HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle)
- if (primitiveValue)
- m_style->setBorderRightStyle(*primitiveValue);
- return;
- case CSSPropertyBorderBottomStyle:
- HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle)
- if (primitiveValue)
- m_style->setBorderBottomStyle(*primitiveValue);
- return;
- case CSSPropertyBorderLeftStyle:
- HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle)
- if (primitiveValue)
- m_style->setBorderLeftStyle(*primitiveValue);
- return;
- case CSSPropertyOutlineStyle:
- HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle)
- if (primitiveValue) {
- if (primitiveValue->getIdent() == CSSValueAuto)
- m_style->setOutlineStyle(DOTTED, true);
- else
- m_style->setOutlineStyle(*primitiveValue);
- }
- return;
- case CSSPropertyCaptionSide:
- {
- HANDLE_INHERIT_AND_INITIAL(captionSide, CaptionSide)
- if (primitiveValue)
- m_style->setCaptionSide(*primitiveValue);
- return;
- }
- case CSSPropertyClear:
- {
- HANDLE_INHERIT_AND_INITIAL(clear, Clear)
- if (primitiveValue)
- m_style->setClear(*primitiveValue);
- return;
- }
- case CSSPropertyDirection:
- {
- HANDLE_INHERIT_AND_INITIAL(direction, Direction)
- if (primitiveValue)
- m_style->setDirection(*primitiveValue);
- return;
- }
- case CSSPropertyDisplay:
- {
- HANDLE_INHERIT_AND_INITIAL(display, Display)
- if (primitiveValue)
- m_style->setDisplay(*primitiveValue);
- return;
- }
-
- case CSSPropertyEmptyCells:
- {
- HANDLE_INHERIT_AND_INITIAL(emptyCells, EmptyCells)
- if (primitiveValue)
- m_style->setEmptyCells(*primitiveValue);
- return;
- }
- case CSSPropertyFloat:
- {
- HANDLE_INHERIT_AND_INITIAL(floating, Floating)
- if (primitiveValue)
- m_style->setFloating(*primitiveValue);
- return;
- }
-
- case CSSPropertyFontStyle:
- {
- FontDescription fontDescription = m_style->fontDescription();
- if (isInherit)
- fontDescription.setItalic(m_parentStyle->fontDescription().italic());
- else if (isInitial)
- fontDescription.setItalic(false);
- else {
- if (!primitiveValue)
- return;
- switch (primitiveValue->getIdent()) {
- case CSSValueOblique:
- // FIXME: oblique is the same as italic for the moment...
- case CSSValueItalic:
- fontDescription.setItalic(true);
- break;
- case CSSValueNormal:
- fontDescription.setItalic(false);
- break;
- default:
- return;
- }
- }
- if (m_style->setFontDescription(fontDescription))
- m_fontDirty = true;
- return;
- }
-
- case CSSPropertyFontVariant:
- {
- FontDescription fontDescription = m_style->fontDescription();
- if (isInherit)
- fontDescription.setSmallCaps(m_parentStyle->fontDescription().smallCaps());
- else if (isInitial)
- fontDescription.setSmallCaps(false);
- else {
- if (!primitiveValue)
- return;
- int id = primitiveValue->getIdent();
- if (id == CSSValueNormal)
- fontDescription.setSmallCaps(false);
- else if (id == CSSValueSmallCaps)
- fontDescription.setSmallCaps(true);
- else
- return;
- }
- if (m_style->setFontDescription(fontDescription))
- m_fontDirty = true;
- return;
- }
-
- case CSSPropertyFontWeight:
- {
- FontDescription fontDescription = m_style->fontDescription();
- if (isInherit)
- fontDescription.setWeight(m_parentStyle->fontDescription().weight());
- else if (isInitial)
- fontDescription.setWeight(FontWeightNormal);
- else {
- if (!primitiveValue)
- return;
- if (primitiveValue->getIdent()) {
- switch (primitiveValue->getIdent()) {
- case CSSValueBolder:
- fontDescription.setWeight(fontDescription.bolderWeight());
- break;
- case CSSValueLighter:
- fontDescription.setWeight(fontDescription.lighterWeight());
- break;
- case CSSValueBold:
- case CSSValue700:
- fontDescription.setWeight(FontWeightBold);
- break;
- case CSSValueNormal:
- case CSSValue400:
- fontDescription.setWeight(FontWeightNormal);
- break;
- case CSSValue900:
- fontDescription.setWeight(FontWeight900);
- break;
- case CSSValue800:
- fontDescription.setWeight(FontWeight800);
- break;
- case CSSValue600:
- fontDescription.setWeight(FontWeight600);
- break;
- case CSSValue500:
- fontDescription.setWeight(FontWeight500);
- break;
- case CSSValue300:
- fontDescription.setWeight(FontWeight300);
- break;
- case CSSValue200:
- fontDescription.setWeight(FontWeight200);
- break;
- case CSSValue100:
- fontDescription.setWeight(FontWeight100);
- break;
- default:
- return;
- }
- } else
- ASSERT_NOT_REACHED();
- }
- if (m_style->setFontDescription(fontDescription))
- m_fontDirty = true;
- return;
- }
-
- case CSSPropertyListStylePosition:
- {
- HANDLE_INHERIT_AND_INITIAL(listStylePosition, ListStylePosition)
- if (primitiveValue)
- m_style->setListStylePosition(*primitiveValue);
- return;
- }
-
- case CSSPropertyListStyleType:
- {
- HANDLE_INHERIT_AND_INITIAL(listStyleType, ListStyleType)
- if (primitiveValue)
- m_style->setListStyleType(*primitiveValue);
- return;
- }
-
- case CSSPropertyOverflow:
- {
- if (isInherit) {
- m_style->setOverflowX(m_parentStyle->overflowX());
- m_style->setOverflowY(m_parentStyle->overflowY());
- return;
- }
-
- if (isInitial) {
- m_style->setOverflowX(RenderStyle::initialOverflowX());
- m_style->setOverflowY(RenderStyle::initialOverflowY());
- return;
- }
-
- EOverflow o = *primitiveValue;
-
- m_style->setOverflowX(o);
- m_style->setOverflowY(o);
- return;
- }
-
- case CSSPropertyOverflowX:
- {
- HANDLE_INHERIT_AND_INITIAL(overflowX, OverflowX)
- m_style->setOverflowX(*primitiveValue);
- return;
- }
-
- case CSSPropertyOverflowY:
- {
- HANDLE_INHERIT_AND_INITIAL(overflowY, OverflowY)
- m_style->setOverflowY(*primitiveValue);
- return;
- }
-
- case CSSPropertyPageBreakBefore:
- {
- HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
- if (primitiveValue)
- m_style->setPageBreakBefore(*primitiveValue);
- return;
- }
-
- case CSSPropertyPageBreakAfter:
- {
- HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
- if (primitiveValue)
- m_style->setPageBreakAfter(*primitiveValue);
- return;
- }
-
- case CSSPropertyPageBreakInside: {
- HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
- if (!primitiveValue)
- return;
- EPageBreak pageBreak = *primitiveValue;
- if (pageBreak != PBALWAYS)
- m_style->setPageBreakInside(pageBreak);
- return;
- }
-
- case CSSPropertyPosition:
- {
- HANDLE_INHERIT_AND_INITIAL(position, Position)
- if (primitiveValue)
- m_style->setPosition(*primitiveValue);
- return;
- }
-
- case CSSPropertyTableLayout: {
- HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout)
-
- ETableLayout l = *primitiveValue;
- if (l == TAUTO)
- l = RenderStyle::initialTableLayout();
-
- m_style->setTableLayout(l);
- return;
- }
-
- case CSSPropertyUnicodeBidi: {
- HANDLE_INHERIT_AND_INITIAL(unicodeBidi, UnicodeBidi)
- m_style->setUnicodeBidi(*primitiveValue);
- return;
- }
- case CSSPropertyTextTransform: {
- HANDLE_INHERIT_AND_INITIAL(textTransform, TextTransform)
- m_style->setTextTransform(*primitiveValue);
- return;
- }
-
- case CSSPropertyVisibility:
- {
- HANDLE_INHERIT_AND_INITIAL(visibility, Visibility)
- m_style->setVisibility(*primitiveValue);
- return;
- }
- case CSSPropertyWhiteSpace:
- HANDLE_INHERIT_AND_INITIAL(whiteSpace, WhiteSpace)
- m_style->setWhiteSpace(*primitiveValue);
- return;
-
- case CSSPropertyBackgroundPosition:
- HANDLE_BACKGROUND_INHERIT_AND_INITIAL(xPosition, XPosition);
- HANDLE_BACKGROUND_INHERIT_AND_INITIAL(yPosition, YPosition);
- return;
- case CSSPropertyBackgroundPositionX: {
- HANDLE_BACKGROUND_VALUE(xPosition, XPosition, value)
- return;
- }
- case CSSPropertyBackgroundPositionY: {
- HANDLE_BACKGROUND_VALUE(yPosition, YPosition, value)
- return;
- }
- case CSSPropertyWebkitMaskPosition:
- HANDLE_MASK_INHERIT_AND_INITIAL(xPosition, XPosition);
- HANDLE_MASK_INHERIT_AND_INITIAL(yPosition, YPosition);
- return;
- case CSSPropertyWebkitMaskPositionX: {
- HANDLE_MASK_VALUE(xPosition, XPosition, value)
- return;
- }
- case CSSPropertyWebkitMaskPositionY: {
- HANDLE_MASK_VALUE(yPosition, YPosition, value)
- return;
- }
- case CSSPropertyBorderSpacing: {
- if (isInherit) {
- m_style->setHorizontalBorderSpacing(m_parentStyle->horizontalBorderSpacing());
- m_style->setVerticalBorderSpacing(m_parentStyle->verticalBorderSpacing());
- }
- else if (isInitial) {
- m_style->setHorizontalBorderSpacing(0);
- m_style->setVerticalBorderSpacing(0);
- }
- return;
- }
- case CSSPropertyWebkitBorderHorizontalSpacing: {
- HANDLE_INHERIT_AND_INITIAL(horizontalBorderSpacing, HorizontalBorderSpacing)
- if (!primitiveValue)
- return;
- short spacing = primitiveValue->computeLengthShort(m_style, zoomFactor);
- m_style->setHorizontalBorderSpacing(spacing);
- return;
- }
- case CSSPropertyWebkitBorderVerticalSpacing: {
- HANDLE_INHERIT_AND_INITIAL(verticalBorderSpacing, VerticalBorderSpacing)
- if (!primitiveValue)
- return;
- short spacing = primitiveValue->computeLengthShort(m_style, zoomFactor);
- m_style->setVerticalBorderSpacing(spacing);
- return;
- }
- case CSSPropertyCursor:
- if (isInherit) {
- m_style->setCursor(m_parentStyle->cursor());
- m_style->setCursorList(m_parentStyle->cursors());
- return;
- }
- m_style->clearCursorList();
- if (isInitial) {
- m_style->setCursor(RenderStyle::initialCursor());
- return;
- }
- if (value->isValueList()) {
- CSSValueList* list = static_cast<CSSValueList*>(value);
- int len = list->length();
- m_style->setCursor(CURSOR_AUTO);
- for (int i = 0; i < len; i++) {
- CSSValue* item = list->itemWithoutBoundsCheck(i);
- if (!item->isPrimitiveValue())
- continue;
- primitiveValue = static_cast<CSSPrimitiveValue*>(item);
- int type = primitiveValue->primitiveType();
- if (type == CSSPrimitiveValue::CSS_URI) {
- CSSCursorImageValue* image = static_cast<CSSCursorImageValue*>(primitiveValue);
- if (image->updateIfSVGCursorIsUsed(m_element)) // Elements with SVG cursors are not allowed to share style.
- m_style->setUnique();
- // FIXME: Temporary clumsiness to pass off a CachedImage to an API that will eventually convert to using
- // StyleImage.
- RefPtr<StyleCachedImage> styleCachedImage(image->cachedImage(m_element->document()->docLoader()));
- if (styleCachedImage)
- m_style->addCursor(styleCachedImage->cachedImage(), image->hotspot());
- } else if (type == CSSPrimitiveValue::CSS_IDENT)
- m_style->setCursor(*primitiveValue);
- }
- } else if (primitiveValue) {
- int type = primitiveValue->primitiveType();
- if (type == CSSPrimitiveValue::CSS_IDENT)
- m_style->setCursor(*primitiveValue);
- }
- return;
-// colors || inherit
- case CSSPropertyColor:
- // If the 'currentColor' keyword is set on the 'color' property itself,
- // it is treated as 'color:inherit' at parse time
- if (primitiveValue && primitiveValue->getIdent() == CSSValueCurrentcolor)
- isInherit = true;
- case CSSPropertyBackgroundColor:
- case CSSPropertyBorderTopColor:
- case CSSPropertyBorderRightColor:
- case CSSPropertyBorderBottomColor:
- case CSSPropertyBorderLeftColor:
- case CSSPropertyOutlineColor:
- case CSSPropertyWebkitColumnRuleColor:
- case CSSPropertyWebkitTextStrokeColor:
- case CSSPropertyWebkitTextFillColor: {
- Color col;
- if (isInherit) {
- HANDLE_INHERIT_COND(CSSPropertyBackgroundColor, backgroundColor, BackgroundColor)
- HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyBorderTopColor, borderTopColor, color, BorderTopColor)
- HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyBorderBottomColor, borderBottomColor, color, BorderBottomColor)
- HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyBorderRightColor, borderRightColor, color, BorderRightColor)
- HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyBorderLeftColor, borderLeftColor, color, BorderLeftColor)
- HANDLE_INHERIT_COND(CSSPropertyColor, color, Color)
- HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyOutlineColor, outlineColor, color, OutlineColor)
- HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyWebkitColumnRuleColor, columnRuleColor, color, ColumnRuleColor)
- HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyWebkitTextStrokeColor, textStrokeColor, color, TextStrokeColor)
- HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyWebkitTextFillColor, textFillColor, color, TextFillColor)
- return;
- }
- if (isInitial) {
- // The border/outline colors will just map to the invalid color |col| above. This will have the
- // effect of forcing the use of the currentColor when it comes time to draw the borders (and of
- // not painting the background since the color won't be valid).
- if (id == CSSPropertyColor)
- col = RenderStyle::initialColor();
- } else {
- if (!primitiveValue)
- return;
- col = getColorFromPrimitiveValue(primitiveValue);
- }
-
- switch (id) {
- case CSSPropertyBackgroundColor:
- m_style->setBackgroundColor(col);
- break;
- case CSSPropertyBorderTopColor:
- m_style->setBorderTopColor(col);
- break;
- case CSSPropertyBorderRightColor:
- m_style->setBorderRightColor(col);
- break;
- case CSSPropertyBorderBottomColor:
- m_style->setBorderBottomColor(col);
- break;
- case CSSPropertyBorderLeftColor:
- m_style->setBorderLeftColor(col);
- break;
- case CSSPropertyColor:
- m_style->setColor(col);
- break;
- case CSSPropertyOutlineColor:
- m_style->setOutlineColor(col);
- break;
- case CSSPropertyWebkitColumnRuleColor:
- m_style->setColumnRuleColor(col);
- break;
- case CSSPropertyWebkitTextStrokeColor:
- m_style->setTextStrokeColor(col);
- break;
- case CSSPropertyWebkitTextFillColor:
- m_style->setTextFillColor(col);
- break;
- }
-
- return;
- }
-
-// uri || inherit
- case CSSPropertyBackgroundImage:
- HANDLE_BACKGROUND_VALUE(image, Image, value)
- return;
- case CSSPropertyWebkitMaskImage:
- HANDLE_MASK_VALUE(image, Image, value)
- return;
- case CSSPropertyListStyleImage:
- {
- HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage)
- m_style->setListStyleImage(styleImage(value));
- return;
- }
-
-// length
- case CSSPropertyBorderTopWidth:
- case CSSPropertyBorderRightWidth:
- case CSSPropertyBorderBottomWidth:
- case CSSPropertyBorderLeftWidth:
- case CSSPropertyOutlineWidth:
- case CSSPropertyWebkitColumnRuleWidth:
- {
- if (isInherit) {
- HANDLE_INHERIT_COND(CSSPropertyBorderTopWidth, borderTopWidth, BorderTopWidth)
- HANDLE_INHERIT_COND(CSSPropertyBorderRightWidth, borderRightWidth, BorderRightWidth)
- HANDLE_INHERIT_COND(CSSPropertyBorderBottomWidth, borderBottomWidth, BorderBottomWidth)
- HANDLE_INHERIT_COND(CSSPropertyBorderLeftWidth, borderLeftWidth, BorderLeftWidth)
- HANDLE_INHERIT_COND(CSSPropertyOutlineWidth, outlineWidth, OutlineWidth)
- HANDLE_INHERIT_COND(CSSPropertyWebkitColumnRuleWidth, columnRuleWidth, ColumnRuleWidth)
- return;
- }
- else if (isInitial) {
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopWidth, BorderTopWidth, BorderWidth)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderRightWidth, BorderRightWidth, BorderWidth)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomWidth, BorderBottomWidth, BorderWidth)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderLeftWidth, BorderLeftWidth, BorderWidth)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyOutlineWidth, OutlineWidth, BorderWidth)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitColumnRuleWidth, ColumnRuleWidth, BorderWidth)
- return;
- }
-
- if (!primitiveValue)
- return;
- short width = 3;
- switch (primitiveValue->getIdent()) {
- case CSSValueThin:
- width = 1;
- break;
- case CSSValueMedium:
- width = 3;
- break;
- case CSSValueThick:
- width = 5;
- break;
- case CSSValueInvalid:
- width = primitiveValue->computeLengthShort(m_style, zoomFactor);
- break;
- default:
- return;
- }
-
- if (width < 0) return;
- switch (id) {
- case CSSPropertyBorderTopWidth:
- m_style->setBorderTopWidth(width);
- break;
- case CSSPropertyBorderRightWidth:
- m_style->setBorderRightWidth(width);
- break;
- case CSSPropertyBorderBottomWidth:
- m_style->setBorderBottomWidth(width);
- break;
- case CSSPropertyBorderLeftWidth:
- m_style->setBorderLeftWidth(width);
- break;
- case CSSPropertyOutlineWidth:
- m_style->setOutlineWidth(width);
- break;
- case CSSPropertyWebkitColumnRuleWidth:
- m_style->setColumnRuleWidth(width);
- break;
- default:
- return;
- }
- return;
- }
-
- case CSSPropertyLetterSpacing:
- case CSSPropertyWordSpacing:
- {
-
- if (isInherit) {
- HANDLE_INHERIT_COND(CSSPropertyLetterSpacing, letterSpacing, LetterSpacing)
- HANDLE_INHERIT_COND(CSSPropertyWordSpacing, wordSpacing, WordSpacing)
- return;
- }
- else if (isInitial) {
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyLetterSpacing, LetterSpacing, LetterWordSpacing)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWordSpacing, WordSpacing, LetterWordSpacing)
- return;
- }
-
- int width = 0;
- if (primitiveValue && primitiveValue->getIdent() == CSSValueNormal){
- width = 0;
- } else {
- if (!primitiveValue)
- return;
- width = primitiveValue->computeLengthInt(m_style, zoomFactor);
- }
- switch (id) {
- case CSSPropertyLetterSpacing:
- m_style->setLetterSpacing(width);
- break;
- case CSSPropertyWordSpacing:
- m_style->setWordSpacing(width);
- break;
- // ### needs the definitions in renderstyle
- default: break;
- }
- return;
- }
-
- case CSSPropertyWordBreak: {
- HANDLE_INHERIT_AND_INITIAL(wordBreak, WordBreak)
- m_style->setWordBreak(*primitiveValue);
- return;
- }
-
- case CSSPropertyWordWrap: {
- HANDLE_INHERIT_AND_INITIAL(wordWrap, WordWrap)
- m_style->setWordWrap(*primitiveValue);
- return;
- }
-
- case CSSPropertyWebkitNbspMode:
- {
- HANDLE_INHERIT_AND_INITIAL(nbspMode, NBSPMode)
- m_style->setNBSPMode(*primitiveValue);
- return;
- }
-
- case CSSPropertyWebkitLineBreak:
- {
- HANDLE_INHERIT_AND_INITIAL(khtmlLineBreak, KHTMLLineBreak)
- m_style->setKHTMLLineBreak(*primitiveValue);
- return;
- }
-
- case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
- {
- HANDLE_INHERIT_AND_INITIAL(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor)
- m_style->setMatchNearestMailBlockquoteColor(*primitiveValue);
- return;
- }
-
- case CSSPropertyResize:
- {
- HANDLE_INHERIT_AND_INITIAL(resize, Resize)
-
- if (!primitiveValue->getIdent())
- return;
-
- EResize r = RESIZE_NONE;
- if (primitiveValue->getIdent() == CSSValueAuto) {
- if (Settings* settings = m_checker.m_document->settings())
- r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE;
- } else
- r = *primitiveValue;
-
- m_style->setResize(r);
- return;
- }
-
- // length, percent
- case CSSPropertyMaxWidth:
- // +none +inherit
- if (primitiveValue && primitiveValue->getIdent() == CSSValueNone)
- apply = true;
- case CSSPropertyTop:
- case CSSPropertyLeft:
- case CSSPropertyRight:
- case CSSPropertyBottom:
- case CSSPropertyWidth:
- case CSSPropertyMinWidth:
- case CSSPropertyMarginTop:
- case CSSPropertyMarginRight:
- case CSSPropertyMarginBottom:
- case CSSPropertyMarginLeft:
- // +inherit +auto
- if (id == CSSPropertyWidth || id == CSSPropertyMinWidth || id == CSSPropertyMaxWidth) {
- if (primitiveValue && primitiveValue->getIdent() == CSSValueIntrinsic) {
- l = Length(Intrinsic);
- apply = true;
- }
- else if (primitiveValue && primitiveValue->getIdent() == CSSValueMinIntrinsic) {
- l = Length(MinIntrinsic);
- apply = true;
- }
- }
- if (id != CSSPropertyMaxWidth && primitiveValue && primitiveValue->getIdent() == CSSValueAuto)
- apply = true;
- case CSSPropertyPaddingTop:
- case CSSPropertyPaddingRight:
- case CSSPropertyPaddingBottom:
- case CSSPropertyPaddingLeft:
- case CSSPropertyTextIndent:
- // +inherit
- {
- if (isInherit) {
- HANDLE_INHERIT_COND(CSSPropertyMaxWidth, maxWidth, MaxWidth)
- HANDLE_INHERIT_COND(CSSPropertyBottom, bottom, Bottom)
- HANDLE_INHERIT_COND(CSSPropertyTop, top, Top)
- HANDLE_INHERIT_COND(CSSPropertyLeft, left, Left)
- HANDLE_INHERIT_COND(CSSPropertyRight, right, Right)
- HANDLE_INHERIT_COND(CSSPropertyWidth, width, Width)
- HANDLE_INHERIT_COND(CSSPropertyMinWidth, minWidth, MinWidth)
- HANDLE_INHERIT_COND(CSSPropertyPaddingTop, paddingTop, PaddingTop)
- HANDLE_INHERIT_COND(CSSPropertyPaddingRight, paddingRight, PaddingRight)
- HANDLE_INHERIT_COND(CSSPropertyPaddingBottom, paddingBottom, PaddingBottom)
- HANDLE_INHERIT_COND(CSSPropertyPaddingLeft, paddingLeft, PaddingLeft)
- HANDLE_INHERIT_COND(CSSPropertyMarginTop, marginTop, MarginTop)
- HANDLE_INHERIT_COND(CSSPropertyMarginRight, marginRight, MarginRight)
- HANDLE_INHERIT_COND(CSSPropertyMarginBottom, marginBottom, MarginBottom)
- HANDLE_INHERIT_COND(CSSPropertyMarginLeft, marginLeft, MarginLeft)
- HANDLE_INHERIT_COND(CSSPropertyTextIndent, textIndent, TextIndent)
- return;
- }
- else if (isInitial) {
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMaxWidth, MaxWidth, MaxSize)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBottom, Bottom, Offset)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyTop, Top, Offset)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyLeft, Left, Offset)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyRight, Right, Offset)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWidth, Width, Size)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMinWidth, MinWidth, MinSize)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingTop, PaddingTop, Padding)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingRight, PaddingRight, Padding)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingBottom, PaddingBottom, Padding)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingLeft, PaddingLeft, Padding)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginTop, MarginTop, Margin)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginRight, MarginRight, Margin)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginBottom, MarginBottom, Margin)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginLeft, MarginLeft, Margin)
- HANDLE_INITIAL_COND(CSSPropertyTextIndent, TextIndent)
- return;
- }
-
- if (primitiveValue && !apply) {
- int type = primitiveValue->primitiveType();
- if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
- // Handle our quirky margin units if we have them.
- l = Length(primitiveValue->computeLengthIntForLength(m_style, zoomFactor), Fixed,
- primitiveValue->isQuirkValue());
- else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
- l = Length(primitiveValue->getDoubleValue(), Percent);
- else
- return;
- if (id == CSSPropertyPaddingLeft || id == CSSPropertyPaddingRight ||
- id == CSSPropertyPaddingTop || id == CSSPropertyPaddingBottom)
- // Padding can't be negative
- apply = !((l.isFixed() || l.isPercent()) && l.calcValue(100) < 0);
- else
- apply = true;
- }
- if (!apply) return;
- switch (id) {
- case CSSPropertyMaxWidth:
- m_style->setMaxWidth(l);
- break;
- case CSSPropertyBottom:
- m_style->setBottom(l);
- break;
- case CSSPropertyTop:
- m_style->setTop(l);
- break;
- case CSSPropertyLeft:
- m_style->setLeft(l);
- break;
- case CSSPropertyRight:
- m_style->setRight(l);
- break;
- case CSSPropertyWidth:
- m_style->setWidth(l);
- break;
- case CSSPropertyMinWidth:
- m_style->setMinWidth(l);
- break;
- case CSSPropertyPaddingTop:
- m_style->setPaddingTop(l);
- break;
- case CSSPropertyPaddingRight:
- m_style->setPaddingRight(l);
- break;
- case CSSPropertyPaddingBottom:
- m_style->setPaddingBottom(l);
- break;
- case CSSPropertyPaddingLeft:
- m_style->setPaddingLeft(l);
- break;
- case CSSPropertyMarginTop:
- m_style->setMarginTop(l);
- break;
- case CSSPropertyMarginRight:
- m_style->setMarginRight(l);
- break;
- case CSSPropertyMarginBottom:
- m_style->setMarginBottom(l);
- break;
- case CSSPropertyMarginLeft:
- m_style->setMarginLeft(l);
- break;
- case CSSPropertyTextIndent:
- m_style->setTextIndent(l);
- break;
- default:
- break;
- }
- return;
- }
-
- case CSSPropertyMaxHeight:
- if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
- l = Length(undefinedLength, Fixed);
- apply = true;
- }
- case CSSPropertyHeight:
- case CSSPropertyMinHeight:
- if (primitiveValue && primitiveValue->getIdent() == CSSValueIntrinsic) {
- l = Length(Intrinsic);
- apply = true;
- } else if (primitiveValue && primitiveValue->getIdent() == CSSValueMinIntrinsic) {
- l = Length(MinIntrinsic);
- apply = true;
- } else if (id != CSSPropertyMaxHeight && primitiveValue && primitiveValue->getIdent() == CSSValueAuto)
- apply = true;
- if (isInherit) {
- HANDLE_INHERIT_COND(CSSPropertyMaxHeight, maxHeight, MaxHeight)
- HANDLE_INHERIT_COND(CSSPropertyHeight, height, Height)
- HANDLE_INHERIT_COND(CSSPropertyMinHeight, minHeight, MinHeight)
- return;
- }
- if (isInitial) {
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMaxHeight, MaxHeight, MaxSize)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyHeight, Height, Size)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMinHeight, MinHeight, MinSize)
- return;
- }
-
- if (primitiveValue && !apply) {
- unsigned short type = primitiveValue->primitiveType();
- if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
- l = Length(primitiveValue->computeLengthIntForLength(m_style, zoomFactor), Fixed);
- else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
- l = Length(primitiveValue->getDoubleValue(), Percent);
- else
- return;
- apply = true;
- }
- if (apply)
- switch (id) {
- case CSSPropertyMaxHeight:
- m_style->setMaxHeight(l);
- break;
- case CSSPropertyHeight:
- m_style->setHeight(l);
- break;
- case CSSPropertyMinHeight:
- m_style->setMinHeight(l);
- break;
- }
- return;
-
- case CSSPropertyVerticalAlign:
- HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
- if (!primitiveValue)
- return;
- if (primitiveValue->getIdent()) {
- EVerticalAlign align;
-
- switch (primitiveValue->getIdent()) {
- case CSSValueTop:
- align = TOP; break;
- case CSSValueBottom:
- align = BOTTOM; break;
- case CSSValueMiddle:
- align = MIDDLE; break;
- case CSSValueBaseline:
- align = BASELINE; break;
- case CSSValueTextBottom:
- align = TEXT_BOTTOM; break;
- case CSSValueTextTop:
- align = TEXT_TOP; break;
- case CSSValueSub:
- align = SUB; break;
- case CSSValueSuper:
- align = SUPER; break;
- case CSSValueWebkitBaselineMiddle:
- align = BASELINE_MIDDLE; break;
- default:
- return;
- }
- m_style->setVerticalAlign(align);
- return;
- } else {
- int type = primitiveValue->primitiveType();
- Length l;
- if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
- l = Length(primitiveValue->computeLengthIntForLength(m_style, zoomFactor), Fixed);
- else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
- l = Length(primitiveValue->getDoubleValue(), Percent);
-
- m_style->setVerticalAlign(LENGTH);
- m_style->setVerticalAlignLength(l);
- }
- return;
-
- case CSSPropertyFontSize:
- {
- FontDescription fontDescription = m_style->fontDescription();
- fontDescription.setKeywordSize(0);
- bool familyIsFixed = fontDescription.genericFamily() == FontDescription::MonospaceFamily;
- float oldSize = 0;
- float size = 0;
-
- bool parentIsAbsoluteSize = false;
- if (m_parentNode) {
- oldSize = m_parentStyle->fontDescription().specifiedSize();
- parentIsAbsoluteSize = m_parentStyle->fontDescription().isAbsoluteSize();
- }
-
- if (isInherit) {
- size = oldSize;
- if (m_parentNode)
- fontDescription.setKeywordSize(m_parentStyle->fontDescription().keywordSize());
- } else if (isInitial) {
- size = fontSizeForKeyword(CSSValueMedium, m_style->htmlHacks(), familyIsFixed);
- fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
- } else if (primitiveValue->getIdent()) {
- // Keywords are being used.
- switch (primitiveValue->getIdent()) {
- case CSSValueXxSmall:
- case CSSValueXSmall:
- case CSSValueSmall:
- case CSSValueMedium:
- case CSSValueLarge:
- case CSSValueXLarge:
- case CSSValueXxLarge:
- case CSSValueWebkitXxxLarge:
- size = fontSizeForKeyword(primitiveValue->getIdent(), m_style->htmlHacks(), familyIsFixed);
- fontDescription.setKeywordSize(primitiveValue->getIdent() - CSSValueXxSmall + 1);
- break;
- case CSSValueLarger:
- size = largerFontSize(oldSize, m_style->htmlHacks());
- break;
- case CSSValueSmaller:
- size = smallerFontSize(oldSize, m_style->htmlHacks());
- break;
- default:
- return;
- }
-
- fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize &&
- (primitiveValue->getIdent() == CSSValueLarger ||
- primitiveValue->getIdent() == CSSValueSmaller));
- } else {
- int type = primitiveValue->primitiveType();
- fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize ||
- (type != CSSPrimitiveValue::CSS_PERCENTAGE &&
- type != CSSPrimitiveValue::CSS_EMS &&
- type != CSSPrimitiveValue::CSS_EXS));
- if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
- size = primitiveValue->computeLengthFloat(m_parentStyle, true);
- else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
- size = (primitiveValue->getFloatValue() * oldSize) / 100.0f;
- else
- return;
- }
-
- if (size < 0)
- return;
-
- setFontSize(fontDescription, size);
- if (m_style->setFontDescription(fontDescription))
- m_fontDirty = true;
- return;
- }
-
- case CSSPropertyZIndex: {
- if (isInherit) {
- if (m_parentStyle->hasAutoZIndex())
- m_style->setHasAutoZIndex();
- else
- m_style->setZIndex(m_parentStyle->zIndex());
- return;
- } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) {
- m_style->setHasAutoZIndex();
- return;
- }
-
- // FIXME: Should clamp all sorts of other integer properties too.
- const double minIntAsDouble = INT_MIN;
- const double maxIntAsDouble = INT_MAX;
- m_style->setZIndex(static_cast<int>(max(minIntAsDouble, min(primitiveValue->getDoubleValue(), maxIntAsDouble))));
- return;
- }
- case CSSPropertyWidows:
- {
- HANDLE_INHERIT_AND_INITIAL(widows, Widows)
- if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
- return;
- m_style->setWidows(primitiveValue->getIntValue());
- return;
- }
-
- case CSSPropertyOrphans:
- {
- HANDLE_INHERIT_AND_INITIAL(orphans, Orphans)
- if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
- return;
- m_style->setOrphans(primitiveValue->getIntValue());
- return;
- }
-
-// length, percent, number
- case CSSPropertyLineHeight:
- {
- HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
- if (!primitiveValue)
- return;
- Length lineHeight;
- int type = primitiveValue->primitiveType();
- if (primitiveValue->getIdent() == CSSValueNormal)
- lineHeight = Length(-100.0, Percent);
- else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
- double multiplier = m_style->effectiveZoom();
- if (m_style->textSizeAdjust() && m_checker.m_document->frame() && m_checker.m_document->frame()->shouldApplyTextZoom())
- multiplier *= m_checker.m_document->frame()->textZoomFactor();
- lineHeight = Length(primitiveValue->computeLengthIntForLength(m_style, multiplier), Fixed);
- } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
- lineHeight = Length((m_style->fontSize() * primitiveValue->getIntValue()) / 100, Fixed);
- else if (type == CSSPrimitiveValue::CSS_NUMBER)
- lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
- else
- return;
- m_style->setLineHeight(lineHeight);
- return;
- }
-
-// string
- case CSSPropertyTextAlign:
- {
- HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
- if (!primitiveValue)
- return;
- int id = primitiveValue->getIdent();
- if (id == CSSValueStart)
- m_style->setTextAlign(m_style->direction() == LTR ? LEFT : RIGHT);
- else if (id == CSSValueEnd)
- m_style->setTextAlign(m_style->direction() == LTR ? RIGHT : LEFT);
- else
- m_style->setTextAlign(*primitiveValue);
- return;
- }
-
-// rect
- case CSSPropertyClip:
- {
- Length top;
- Length right;
- Length bottom;
- Length left;
- bool hasClip = true;
- if (isInherit) {
- if (m_parentStyle->hasClip()) {
- top = m_parentStyle->clipTop();
- right = m_parentStyle->clipRight();
- bottom = m_parentStyle->clipBottom();
- left = m_parentStyle->clipLeft();
- }
- else {
- hasClip = false;
- top = right = bottom = left = Length();
- }
- } else if (isInitial) {
- hasClip = false;
- top = right = bottom = left = Length();
- } else if (!primitiveValue) {
- return;
- } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) {
- Rect* rect = primitiveValue->getRectValue();
- if (!rect)
- return;
- top = convertToLength(rect->top(), m_style);
- right = convertToLength(rect->right(), m_style);
- bottom = convertToLength(rect->bottom(), m_style);
- left = convertToLength(rect->left(), m_style);
-
- } else if (primitiveValue->getIdent() != CSSValueAuto) {
- return;
- }
- m_style->setClip(top, right, bottom, left);
- m_style->setHasClip(hasClip);
-
- // rect, ident
- return;
- }
-
-// lists
- case CSSPropertyContent:
- // list of string, uri, counter, attr, i
- {
- // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
- // note is a reminder that eventually "inherit" needs to be supported.
-
- if (isInitial) {
- m_style->clearContent();
- return;
- }
-
- if (!value->isValueList())
- return;
-
- CSSValueList* list = static_cast<CSSValueList*>(value);
- int len = list->length();
-
- bool didSet = false;
- for (int i = 0; i < len; i++) {
- CSSValue* item = list->itemWithoutBoundsCheck(i);
- if (item->isImageGeneratorValue()) {
- m_style->setContent(static_cast<CSSImageGeneratorValue*>(item)->generatedImage(), didSet);
- didSet = true;
- }
-
- if (!item->isPrimitiveValue())
- continue;
-
- CSSPrimitiveValue* val = static_cast<CSSPrimitiveValue*>(item);
- switch (val->primitiveType()) {
- case CSSPrimitiveValue::CSS_STRING:
- m_style->setContent(val->getStringValue().impl(), didSet);
- didSet = true;
- break;
- case CSSPrimitiveValue::CSS_ATTR: {
- // FIXME: Can a namespace be specified for an attr(foo)?
- if (m_style->styleType() == RenderStyle::NOPSEUDO)
- m_style->setUnique();
- else
- m_parentStyle->setUnique();
- QualifiedName attr(nullAtom, val->getStringValue().impl(), nullAtom);
- m_style->setContent(m_element->getAttribute(attr).impl(), didSet);
- didSet = true;
- // register the fact that the attribute value affects the style
- m_selectorAttrs.add(attr.localName().impl());
- break;
- }
- case CSSPrimitiveValue::CSS_URI: {
- CSSImageValue* image = static_cast<CSSImageValue*>(val);
- m_style->setContent(image->cachedImage(m_element->document()->docLoader()), didSet);
- didSet = true;
- break;
- }
- case CSSPrimitiveValue::CSS_COUNTER: {
- Counter* counterValue = val->getCounterValue();
- CounterContent* counter = new CounterContent(counterValue->identifier(),
- (EListStyleType)counterValue->listStyleNumber(), counterValue->separator());
- m_style->setContent(counter, didSet);
- didSet = true;
- }
- }
- }
- if (!didSet)
- m_style->clearContent();
- return;
- }
-
- case CSSPropertyCounterIncrement:
- applyCounterList(m_style, value->isValueList() ? static_cast<CSSValueList*>(value) : 0, false);
- return;
- case CSSPropertyCounterReset:
- applyCounterList(m_style, value->isValueList() ? static_cast<CSSValueList*>(value) : 0, true);
- return;
-
- case CSSPropertyFontFamily: {
- // list of strings and ids
- if (isInherit) {
- FontDescription parentFontDescription = m_parentStyle->fontDescription();
- FontDescription fontDescription = m_style->fontDescription();
- fontDescription.setGenericFamily(parentFontDescription.genericFamily());
- fontDescription.setFamily(parentFontDescription.firstFamily());
- if (m_style->setFontDescription(fontDescription))
- m_fontDirty = true;
- return;
- }
- else if (isInitial) {
- FontDescription initialDesc = FontDescription();
- FontDescription fontDescription = m_style->fontDescription();
- // We need to adjust the size to account for the generic family change from monospace
- // to non-monospace.
- if (fontDescription.keywordSize() && fontDescription.genericFamily() == FontDescription::MonospaceFamily)
- setFontSize(fontDescription, fontSizeForKeyword(CSSValueXxSmall + fontDescription.keywordSize() - 1, m_style->htmlHacks(), false));
- fontDescription.setGenericFamily(initialDesc.genericFamily());
- if (!initialDesc.firstFamily().familyIsEmpty())
- fontDescription.setFamily(initialDesc.firstFamily());
- if (m_style->setFontDescription(fontDescription))
- m_fontDirty = true;
- return;
- }
-
- if (!value->isValueList()) return;
- FontDescription fontDescription = m_style->fontDescription();
- CSSValueList *list = static_cast<CSSValueList*>(value);
- int len = list->length();
- FontFamily& firstFamily = fontDescription.firstFamily();
- FontFamily *currFamily = 0;
-
- // Before mapping in a new font-family property, we should reset the generic family.
- bool oldFamilyIsMonospace = fontDescription.genericFamily() == FontDescription::MonospaceFamily;
- fontDescription.setGenericFamily(FontDescription::NoFamily);
-
- // |script| is used to add a font per script and per CSS generic family.
- // Adding it here is not very efficient because we may never use it
- // if all the characters are covered by fonts specified for this element.
- // TODO(jungshik): Currently, it's document-wide constant inferred from
- // the document charset, but we should infer it from the value of
- // xml:lang or lang for |m_element|.
- UScriptCode script = m_checker.m_document->dominantScript();
- // serif, sans-serif, cursive, fantasy, monospace
- ScriptFamilyState scriptFamilyStates[5];
- Settings* settings = m_checker.m_document->settings();
- for (int i = 0; i < len; i++) {
- CSSValue *item = list->itemWithoutBoundsCheck(i);
- if (!item->isPrimitiveValue()) continue;
- CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item);
- AtomicString face;
- if (val->primitiveType() == CSSPrimitiveValue::CSS_STRING)
- face = static_cast<FontFamilyValue*>(val)->familyName();
- else if (val->primitiveType() == CSSPrimitiveValue::CSS_IDENT && settings) {
- switch (val->getIdent()) {
- case CSSValueWebkitBody:
- face = settings->standardFontFamily();
- break;
- // For each of 5 CSS generic families,
- // we add '-webkit-FOO' and a per-script generic family.
- // When |Settings| becomes expressive enough to support
- // per-script&per-generic family and we have a UI for
- // that, we'd just add the latter. Even without that,
- // I'm tempted to add per-script generic first, but I can't.
- // If I did, our font-selection UI would be all but
- // non-functional. Another issue is that we're adding
- // these fonts without regard for actual need in page
- // rendering. That is, it's not done in a lazy manner.
- // Somewhere in getGlyphDataForCharacter() could be
- // a better place in terms of performance.
- // See https://bugs.webkit.org/show_bug.cgi?id=18085
- // and http://bugs.webkit.org/show_bug.cgi?id=10874
- case CSSValueSerif:
- handleScriptFamily("-webkit-serif", script,
- FontDescription::SerifFamily, face,
- scriptFamilyStates[0], fontDescription, i);
- break;
- case CSSValueSansSerif:
- handleScriptFamily("-webkit-sans-serif", script,
- FontDescription::SansSerifFamily, face,
- scriptFamilyStates[1], fontDescription, i);
- break;
- case CSSValueCursive:
- handleScriptFamily("-webkit-cursive", script,
- FontDescription::CursiveFamily, face,
- scriptFamilyStates[2], fontDescription, i);
- break;
- case CSSValueFantasy:
- handleScriptFamily("-webkit-fantasy", script,
- FontDescription::FantasyFamily, face,
- scriptFamilyStates[3], fontDescription, i);
- break;
- case CSSValueMonospace:
- handleScriptFamily("-webkit-monospace", script,
- FontDescription::MonospaceFamily, face,
- scriptFamilyStates[4], fontDescription, i);
- break;
- }
- }
-
- if (!face.isEmpty()) {
- if (!currFamily) {
- // Filling in the first family.
- firstFamily.setFamily(face);
- currFamily = &firstFamily;
- }
- else {
- RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create();
- newFamily->setFamily(face);
- currFamily->appendFamily(newFamily);
- currFamily = newFamily.get();
- }
-
- if (fontDescription.keywordSize() && (fontDescription.genericFamily() == FontDescription::MonospaceFamily) != oldFamilyIsMonospace)
- setFontSize(fontDescription, fontSizeForKeyword(CSSValueXxSmall + fontDescription.keywordSize() - 1, m_style->htmlHacks(), !oldFamilyIsMonospace));
-
- if (m_style->setFontDescription(fontDescription))
- m_fontDirty = true;
- }
- }
-
- if (fontDescription.genericFamily() == FontDescription::NoFamily && currFamily) {
- FontDescription::GenericFamilyType generic;
- // TODO(jungshik) : Perhaps, we'd better add isStandardSerif()
- // method to |Settings| which will be set via WebPreference.
- if (settings) {
- if (settings->serifFontFamily() == settings->standardFontFamily())
- generic = FontDescription::SerifFamily ;
- else
- generic = FontDescription::SansSerifFamily;
- } else
- generic = FontDescription::StandardFamily;
- fontDescription.setGenericFamily(generic);
- AtomicString face = FontCache::getGenericFontForScript(script, fontDescription);
- if (!face.isEmpty()) {
- RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create();
- newFamily->setFamily(face);
- currFamily->appendFamily(newFamily);
- currFamily = newFamily.get();
- if (m_style->setFontDescription(fontDescription))
- m_fontDirty = true;
- }
- }
- return;
- }
- case CSSPropertyTextDecoration: {
- // list of ident
- HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration)
- int t = RenderStyle::initialTextDecoration();
- if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
- // do nothing
- } else {
- if (!value->isValueList()) return;
- CSSValueList *list = static_cast<CSSValueList*>(value);
- int len = list->length();
- for (int i = 0; i < len; i++)
- {
- CSSValue *item = list->itemWithoutBoundsCheck(i);
- if (!item->isPrimitiveValue()) continue;
- primitiveValue = static_cast<CSSPrimitiveValue*>(item);
- switch (primitiveValue->getIdent()) {
- case CSSValueNone:
- t = TDNONE; break;
- case CSSValueUnderline:
- t |= UNDERLINE; break;
- case CSSValueOverline:
- t |= OVERLINE; break;
- case CSSValueLineThrough:
- t |= LINE_THROUGH; break;
- case CSSValueBlink:
- t |= BLINK; break;
- default:
- return;
- }
- }
- }
-
- m_style->setTextDecoration(t);
- return;
- }
-
- case CSSPropertyZoom:
- {
- // Reset the zoom in effect before we do anything. This allows the setZoom method to accurately compute a new
- // zoom in effect.
- m_style->setEffectiveZoom(m_parentStyle ? m_parentStyle->effectiveZoom() : RenderStyle::initialZoom());
-
- // Now we can handle inherit and initial.
- HANDLE_INHERIT_AND_INITIAL(zoom, Zoom)
-
- // Handle normal/reset, numbers and percentages.
- int type = primitiveValue->primitiveType();
- if (primitiveValue->getIdent() == CSSValueNormal)
- m_style->setZoom(RenderStyle::initialZoom());
- else if (primitiveValue->getIdent() == CSSValueReset) {
- m_style->setEffectiveZoom(RenderStyle::initialZoom());
- m_style->setZoom(RenderStyle::initialZoom());
- } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) {
- if (primitiveValue->getFloatValue())
- m_style->setZoom(primitiveValue->getFloatValue() / 100.0f);
- } else if (type == CSSPrimitiveValue::CSS_NUMBER) {
- if (primitiveValue->getFloatValue())
- m_style->setZoom(primitiveValue->getFloatValue());
- }
-
- m_fontDirty = true;
- return;
- }
-// shorthand properties
- case CSSPropertyBackground:
- if (isInitial) {
- m_style->clearBackgroundLayers();
- m_style->setBackgroundColor(Color());
- }
- else if (isInherit) {
- m_style->inheritBackgroundLayers(*m_parentStyle->backgroundLayers());
- m_style->setBackgroundColor(m_parentStyle->backgroundColor());
- }
- return;
- case CSSPropertyWebkitMask:
- if (isInitial)
- m_style->clearMaskLayers();
- else if (isInherit)
- m_style->inheritMaskLayers(*m_parentStyle->maskLayers());
- return;
-
- case CSSPropertyBorder:
- case CSSPropertyBorderStyle:
- case CSSPropertyBorderWidth:
- case CSSPropertyBorderColor:
- if (id == CSSPropertyBorder || id == CSSPropertyBorderColor)
- {
- if (isInherit) {
- m_style->setBorderTopColor(m_parentStyle->borderTopColor().isValid() ? m_parentStyle->borderTopColor() : m_parentStyle->color());
- m_style->setBorderBottomColor(m_parentStyle->borderBottomColor().isValid() ? m_parentStyle->borderBottomColor() : m_parentStyle->color());
- m_style->setBorderLeftColor(m_parentStyle->borderLeftColor().isValid() ? m_parentStyle->borderLeftColor() : m_parentStyle->color());
- m_style->setBorderRightColor(m_parentStyle->borderRightColor().isValid() ? m_parentStyle->borderRightColor(): m_parentStyle->color());
- }
- else if (isInitial) {
- m_style->setBorderTopColor(Color()); // Reset to invalid color so currentColor is used instead.
- m_style->setBorderBottomColor(Color());
- m_style->setBorderLeftColor(Color());
- m_style->setBorderRightColor(Color());
- }
- }
- if (id == CSSPropertyBorder || id == CSSPropertyBorderStyle)
- {
- if (isInherit) {
- m_style->setBorderTopStyle(m_parentStyle->borderTopStyle());
- m_style->setBorderBottomStyle(m_parentStyle->borderBottomStyle());
- m_style->setBorderLeftStyle(m_parentStyle->borderLeftStyle());
- m_style->setBorderRightStyle(m_parentStyle->borderRightStyle());
- }
- else if (isInitial) {
- m_style->setBorderTopStyle(RenderStyle::initialBorderStyle());
- m_style->setBorderBottomStyle(RenderStyle::initialBorderStyle());
- m_style->setBorderLeftStyle(RenderStyle::initialBorderStyle());
- m_style->setBorderRightStyle(RenderStyle::initialBorderStyle());
- }
- }
- if (id == CSSPropertyBorder || id == CSSPropertyBorderWidth)
- {
- if (isInherit) {
- m_style->setBorderTopWidth(m_parentStyle->borderTopWidth());
- m_style->setBorderBottomWidth(m_parentStyle->borderBottomWidth());
- m_style->setBorderLeftWidth(m_parentStyle->borderLeftWidth());
- m_style->setBorderRightWidth(m_parentStyle->borderRightWidth());
- }
- else if (isInitial) {
- m_style->setBorderTopWidth(RenderStyle::initialBorderWidth());
- m_style->setBorderBottomWidth(RenderStyle::initialBorderWidth());
- m_style->setBorderLeftWidth(RenderStyle::initialBorderWidth());
- m_style->setBorderRightWidth(RenderStyle::initialBorderWidth());
- }
- }
- return;
- case CSSPropertyBorderTop:
- if (isInherit) {
- m_style->setBorderTopColor(m_parentStyle->borderTopColor().isValid() ? m_parentStyle->borderTopColor() : m_parentStyle->color());
- m_style->setBorderTopStyle(m_parentStyle->borderTopStyle());
- m_style->setBorderTopWidth(m_parentStyle->borderTopWidth());
- }
- else if (isInitial)
- m_style->resetBorderTop();
- return;
- case CSSPropertyBorderRight:
- if (isInherit) {
- m_style->setBorderRightColor(m_parentStyle->borderRightColor().isValid() ? m_parentStyle->borderRightColor() : m_parentStyle->color());
- m_style->setBorderRightStyle(m_parentStyle->borderRightStyle());
- m_style->setBorderRightWidth(m_parentStyle->borderRightWidth());
- }
- else if (isInitial)
- m_style->resetBorderRight();
- return;
- case CSSPropertyBorderBottom:
- if (isInherit) {
- m_style->setBorderBottomColor(m_parentStyle->borderBottomColor().isValid() ? m_parentStyle->borderBottomColor() : m_parentStyle->color());
- m_style->setBorderBottomStyle(m_parentStyle->borderBottomStyle());
- m_style->setBorderBottomWidth(m_parentStyle->borderBottomWidth());
- }
- else if (isInitial)
- m_style->resetBorderBottom();
- return;
- case CSSPropertyBorderLeft:
- if (isInherit) {
- m_style->setBorderLeftColor(m_parentStyle->borderLeftColor().isValid() ? m_parentStyle->borderLeftColor() : m_parentStyle->color());
- m_style->setBorderLeftStyle(m_parentStyle->borderLeftStyle());
- m_style->setBorderLeftWidth(m_parentStyle->borderLeftWidth());
- }
- else if (isInitial)
- m_style->resetBorderLeft();
- return;
- case CSSPropertyMargin:
- if (isInherit) {
- m_style->setMarginTop(m_parentStyle->marginTop());
- m_style->setMarginBottom(m_parentStyle->marginBottom());
- m_style->setMarginLeft(m_parentStyle->marginLeft());
- m_style->setMarginRight(m_parentStyle->marginRight());
- }
- else if (isInitial)
- m_style->resetMargin();
- return;
- case CSSPropertyPadding:
- if (isInherit) {
- m_style->setPaddingTop(m_parentStyle->paddingTop());
- m_style->setPaddingBottom(m_parentStyle->paddingBottom());
- m_style->setPaddingLeft(m_parentStyle->paddingLeft());
- m_style->setPaddingRight(m_parentStyle->paddingRight());
- }
- else if (isInitial)
- m_style->resetPadding();
- return;
- case CSSPropertyFont:
- if (isInherit) {
- FontDescription fontDescription = m_parentStyle->fontDescription();
- m_style->setLineHeight(m_parentStyle->lineHeight());
- m_lineHeightValue = 0;
- if (m_style->setFontDescription(fontDescription))
- m_fontDirty = true;
- } else if (isInitial) {
- Settings* settings = m_checker.m_document->settings();
- FontDescription fontDescription;
- fontDescription.setGenericFamily(FontDescription::StandardFamily);
- fontDescription.setRenderingMode(settings->fontRenderingMode());
- fontDescription.setUsePrinterFont(m_checker.m_document->printing());
- const AtomicString& standardFontFamily = m_checker.m_document->settings()->standardFontFamily();
- if (!standardFontFamily.isEmpty()) {
- fontDescription.firstFamily().setFamily(standardFontFamily);
- fontDescription.firstFamily().appendFamily(0);
- }
- fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
- setFontSize(fontDescription, fontSizeForKeyword(CSSValueMedium, m_style->htmlHacks(), false));
- m_style->setLineHeight(RenderStyle::initialLineHeight());
- m_lineHeightValue = 0;
- if (m_style->setFontDescription(fontDescription))
- m_fontDirty = true;
- } else if (primitiveValue) {
- m_style->setLineHeight(RenderStyle::initialLineHeight());
- m_lineHeightValue = 0;
- FontDescription fontDescription;
- theme()->systemFont(primitiveValue->getIdent(), m_checker.m_document, fontDescription);
- // Double-check and see if the theme did anything. If not, don't bother updating the font.
- if (fontDescription.isAbsoluteSize()) {
- // Handle the zoom factor.
- fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(fontDescription.isAbsoluteSize(), fontDescription.specifiedSize()));
- if (m_style->setFontDescription(fontDescription))
- m_fontDirty = true;
- }
- } else if (value->isFontValue()) {
- FontValue *font = static_cast<FontValue*>(value);
- if (!font->style || !font->variant || !font->weight ||
- !font->size || !font->lineHeight || !font->family)
- return;
- applyProperty(CSSPropertyFontStyle, font->style.get());
- applyProperty(CSSPropertyFontVariant, font->variant.get());
- applyProperty(CSSPropertyFontWeight, font->weight.get());
- applyProperty(CSSPropertyFontSize, font->size.get());
-
- m_lineHeightValue = font->lineHeight.get();
-
- applyProperty(CSSPropertyFontFamily, font->family.get());
- }
- return;
-
- case CSSPropertyListStyle:
- if (isInherit) {
- m_style->setListStyleType(m_parentStyle->listStyleType());
- m_style->setListStyleImage(m_parentStyle->listStyleImage());
- m_style->setListStylePosition(m_parentStyle->listStylePosition());
- }
- else if (isInitial) {
- m_style->setListStyleType(RenderStyle::initialListStyleType());
- m_style->setListStyleImage(RenderStyle::initialListStyleImage());
- m_style->setListStylePosition(RenderStyle::initialListStylePosition());
- }
- return;
- case CSSPropertyOutline:
- if (isInherit) {
- m_style->setOutlineWidth(m_parentStyle->outlineWidth());
- m_style->setOutlineColor(m_parentStyle->outlineColor().isValid() ? m_parentStyle->outlineColor() : m_parentStyle->color());
- m_style->setOutlineStyle(m_parentStyle->outlineStyle());
- }
- else if (isInitial)
- m_style->resetOutline();
- return;
-
- // CSS3 Properties
- case CSSPropertyWebkitAppearance: {
- HANDLE_INHERIT_AND_INITIAL(appearance, Appearance)
- if (!primitiveValue)
- return;
- m_style->setAppearance(*primitiveValue);
- return;
- }
- case CSSPropertyWebkitBinding: {
-#if ENABLE(XBL)
- if (isInitial || (primitiveValue && primitiveValue->getIdent() == CSSValueNone)) {
- m_style->deleteBindingURIs();
- return;
- }
- else if (isInherit) {
- if (m_parentStyle->bindingURIs())
- m_style->inheritBindingURIs(m_parentStyle->bindingURIs());
- else
- m_style->deleteBindingURIs();
- return;
- }
-
- if (!value->isValueList()) return;
- CSSValueList* list = static_cast<CSSValueList*>(value);
- bool firstBinding = true;
- for (unsigned int i = 0; i < list->length(); i++) {
- CSSValue *item = list->itemWithoutBoundsCheck(i);
- CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item);
- if (val->primitiveType() == CSSPrimitiveValue::CSS_URI) {
- if (firstBinding) {
- firstBinding = false;
- m_style->deleteBindingURIs();
- }
- m_style->addBindingURI(val->getStringValue());
- }
- }
-#endif
- return;
- }
-
- case CSSPropertyWebkitBorderImage:
- case CSSPropertyWebkitMaskBoxImage: {
- if (isInherit) {
- HANDLE_INHERIT_COND(CSSPropertyWebkitBorderImage, borderImage, BorderImage)
- HANDLE_INHERIT_COND(CSSPropertyWebkitMaskBoxImage, maskBoxImage, MaskBoxImage)
- return;
- } else if (isInitial) {
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitBorderImage, BorderImage, NinePieceImage)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitMaskBoxImage, MaskBoxImage, NinePieceImage)
- return;
- }
-
- NinePieceImage image;
- mapNinePieceImage(value, image);
-
- if (id == CSSPropertyWebkitBorderImage)
- m_style->setBorderImage(image);
- else
- m_style->setMaskBoxImage(image);
- return;
- }
-
- case CSSPropertyWebkitBorderRadius:
- if (isInherit) {
- m_style->setBorderTopLeftRadius(m_parentStyle->borderTopLeftRadius());
- m_style->setBorderTopRightRadius(m_parentStyle->borderTopRightRadius());
- m_style->setBorderBottomLeftRadius(m_parentStyle->borderBottomLeftRadius());
- m_style->setBorderBottomRightRadius(m_parentStyle->borderBottomRightRadius());
- return;
- }
- if (isInitial) {
- m_style->resetBorderRadius();
- return;
- }
- // Fall through
- case CSSPropertyWebkitBorderTopLeftRadius:
- case CSSPropertyWebkitBorderTopRightRadius:
- case CSSPropertyWebkitBorderBottomLeftRadius:
- case CSSPropertyWebkitBorderBottomRightRadius: {
- if (isInherit) {
- HANDLE_INHERIT_COND(CSSPropertyWebkitBorderTopLeftRadius, borderTopLeftRadius, BorderTopLeftRadius)
- HANDLE_INHERIT_COND(CSSPropertyWebkitBorderTopRightRadius, borderTopRightRadius, BorderTopRightRadius)
- HANDLE_INHERIT_COND(CSSPropertyWebkitBorderBottomLeftRadius, borderBottomLeftRadius, BorderBottomLeftRadius)
- HANDLE_INHERIT_COND(CSSPropertyWebkitBorderBottomRightRadius, borderBottomRightRadius, BorderBottomRightRadius)
- return;
- }
-
- if (isInitial) {
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitBorderTopLeftRadius, BorderTopLeftRadius, BorderRadius)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitBorderTopRightRadius, BorderTopRightRadius, BorderRadius)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitBorderBottomLeftRadius, BorderBottomLeftRadius, BorderRadius)
- HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitBorderBottomRightRadius, BorderBottomRightRadius, BorderRadius)
- return;
- }
-
- if (!primitiveValue)
- return;
-
- Pair* pair = primitiveValue->getPairValue();
- if (!pair)
- return;
-
- int width = pair->first()->computeLengthInt(m_style, zoomFactor);
- int height = pair->second()->computeLengthInt(m_style, zoomFactor);
- if (width < 0 || height < 0)
- return;
-
- if (width == 0)
- height = 0; // Null out the other value.
- else if (height == 0)
- width = 0; // Null out the other value.
-
- IntSize size(width, height);
- switch (id) {
- case CSSPropertyWebkitBorderTopLeftRadius:
- m_style->setBorderTopLeftRadius(size);
- break;
- case CSSPropertyWebkitBorderTopRightRadius:
- m_style->setBorderTopRightRadius(size);
- break;
- case CSSPropertyWebkitBorderBottomLeftRadius:
- m_style->setBorderBottomLeftRadius(size);
- break;
- case CSSPropertyWebkitBorderBottomRightRadius:
- m_style->setBorderBottomRightRadius(size);
- break;
- default:
- m_style->setBorderRadius(size);
- break;
- }
- return;
- }
-
- case CSSPropertyOutlineOffset:
- HANDLE_INHERIT_AND_INITIAL(outlineOffset, OutlineOffset)
- m_style->setOutlineOffset(primitiveValue->computeLengthInt(m_style, zoomFactor));
- return;
-
- case CSSPropertyTextShadow:
- case CSSPropertyWebkitBoxShadow: {
- if (isInherit) {
- if (id == CSSPropertyTextShadow)
- return m_style->setTextShadow(m_parentStyle->textShadow() ? new ShadowData(*m_parentStyle->textShadow()) : 0);
- return m_style->setBoxShadow(m_parentStyle->boxShadow() ? new ShadowData(*m_parentStyle->boxShadow()) : 0);
- }
- if (isInitial || primitiveValue) // initial | none
- return id == CSSPropertyTextShadow ? m_style->setTextShadow(0) : m_style->setBoxShadow(0);
-
- if (!value->isValueList())
- return;
-
- CSSValueList *list = static_cast<CSSValueList*>(value);
- int len = list->length();
- for (int i = 0; i < len; i++) {
- ShadowValue* item = static_cast<ShadowValue*>(list->itemWithoutBoundsCheck(i));
- int x = item->x->computeLengthInt(m_style, zoomFactor);
- int y = item->y->computeLengthInt(m_style, zoomFactor);
- int blur = item->blur ? item->blur->computeLengthInt(m_style, zoomFactor) : 0;
- Color color;
- if (item->color)
- color = getColorFromPrimitiveValue(item->color.get());
- ShadowData* shadowData = new ShadowData(x, y, blur, color.isValid() ? color : Color::transparent);
- if (id == CSSPropertyTextShadow)
- m_style->setTextShadow(shadowData, i != 0);
- else
- m_style->setBoxShadow(shadowData, i != 0);
- }
- return;
- }
- case CSSPropertyWebkitBoxReflect: {
- HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect)
- if (primitiveValue) {
- m_style->setBoxReflect(RenderStyle::initialBoxReflect());
- return;
- }
- CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value);
- RefPtr<StyleReflection> reflection = StyleReflection::create();
- reflection->setDirection(reflectValue->direction());
- if (reflectValue->offset()) {
- int type = reflectValue->offset()->primitiveType();
- if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
- reflection->setOffset(Length(reflectValue->offset()->getDoubleValue(), Percent));
- else
- reflection->setOffset(Length(reflectValue->offset()->computeLengthIntForLength(m_style, zoomFactor), Fixed));
- }
- NinePieceImage mask;
- mapNinePieceImage(reflectValue->mask(), mask);
- reflection->setMask(mask);
-
- m_style->setBoxReflect(reflection.release());
- return;
- }
- case CSSPropertyOpacity:
- HANDLE_INHERIT_AND_INITIAL(opacity, Opacity)
- if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
- return; // Error case.
- // Clamp opacity to the range 0-1
- m_style->setOpacity(min(1.0f, max(0.0f, primitiveValue->getFloatValue())));
- return;
- case CSSPropertyWebkitBoxAlign:
- {
- HANDLE_INHERIT_AND_INITIAL(boxAlign, BoxAlign)
- if (!primitiveValue)
- return;
- EBoxAlignment boxAlignment = *primitiveValue;
- if (boxAlignment != BJUSTIFY)
- m_style->setBoxAlign(boxAlignment);
- return;
- }
- case CSSPropertySrc: // Only used in @font-face rules.
- return;
- case CSSPropertyUnicodeRange: // Only used in @font-face rules.
- return;
- case CSSPropertyWebkitBoxDirection:
- HANDLE_INHERIT_AND_INITIAL(boxDirection, BoxDirection)
- if (primitiveValue)
- m_style->setBoxDirection(*primitiveValue);
- return;
- case CSSPropertyWebkitBoxLines:
- HANDLE_INHERIT_AND_INITIAL(boxLines, BoxLines)
- if (primitiveValue)
- m_style->setBoxLines(*primitiveValue);
- return;
- case CSSPropertyWebkitBoxOrient:
- HANDLE_INHERIT_AND_INITIAL(boxOrient, BoxOrient)
- if (primitiveValue)
- m_style->setBoxOrient(*primitiveValue);
- return;
- case CSSPropertyWebkitBoxPack:
- {
- HANDLE_INHERIT_AND_INITIAL(boxPack, BoxPack)
- if (!primitiveValue)
- return;
- EBoxAlignment boxPack = *primitiveValue;
- if (boxPack != BSTRETCH && boxPack != BBASELINE)
- m_style->setBoxPack(boxPack);
- return;
- }
- case CSSPropertyWebkitBoxFlex:
- HANDLE_INHERIT_AND_INITIAL(boxFlex, BoxFlex)
- if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
- return; // Error case.
- m_style->setBoxFlex(primitiveValue->getFloatValue());
- return;
- case CSSPropertyWebkitBoxFlexGroup:
- HANDLE_INHERIT_AND_INITIAL(boxFlexGroup, BoxFlexGroup)
- if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
- return; // Error case.
- m_style->setBoxFlexGroup((unsigned int)(primitiveValue->getDoubleValue()));
- return;
- case CSSPropertyWebkitBoxOrdinalGroup:
- HANDLE_INHERIT_AND_INITIAL(boxOrdinalGroup, BoxOrdinalGroup)
- if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
- return; // Error case.
- m_style->setBoxOrdinalGroup((unsigned int)(primitiveValue->getDoubleValue()));
- return;
- case CSSPropertyWebkitBoxSizing:
- HANDLE_INHERIT_AND_INITIAL(boxSizing, BoxSizing)
- if (!primitiveValue)
- return;
- if (primitiveValue->getIdent() == CSSValueContentBox)
- m_style->setBoxSizing(CONTENT_BOX);
- else
- m_style->setBoxSizing(BORDER_BOX);
- return;
- case CSSPropertyWebkitColumnCount: {
- if (isInherit) {
- if (m_parentStyle->hasAutoColumnCount())
- m_style->setHasAutoColumnCount();
- else
- m_style->setColumnCount(m_parentStyle->columnCount());
- return;
- } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) {
- m_style->setHasAutoColumnCount();
- return;
- }
- m_style->setColumnCount(static_cast<unsigned short>(primitiveValue->getDoubleValue()));
- return;
- }
- case CSSPropertyWebkitColumnGap: {
- if (isInherit) {
- if (m_parentStyle->hasNormalColumnGap())
- m_style->setHasNormalColumnGap();
- else
- m_style->setColumnGap(m_parentStyle->columnGap());
- return;
- } else if (isInitial || primitiveValue->getIdent() == CSSValueNormal) {
- m_style->setHasNormalColumnGap();
- return;
- }
- m_style->setColumnGap(primitiveValue->computeLengthFloat(m_style, zoomFactor));
- return;
- }
- case CSSPropertyWebkitColumnWidth: {
- if (isInherit) {
- if (m_parentStyle->hasAutoColumnWidth())
- m_style->setHasAutoColumnWidth();
- else
- m_style->setColumnWidth(m_parentStyle->columnWidth());
- return;
- } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) {
- m_style->setHasAutoColumnWidth();
- return;
- }
- m_style->setColumnWidth(primitiveValue->computeLengthFloat(m_style, zoomFactor));
- return;
- }
- case CSSPropertyWebkitColumnRuleStyle:
- HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnRuleStyle, ColumnRuleStyle, BorderStyle)
- m_style->setColumnRuleStyle(*primitiveValue);
- return;
- case CSSPropertyWebkitColumnBreakBefore: {
- HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnBreakBefore, ColumnBreakBefore, PageBreak)
- m_style->setColumnBreakBefore(*primitiveValue);
- return;
- }
- case CSSPropertyWebkitColumnBreakAfter: {
- HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnBreakAfter, ColumnBreakAfter, PageBreak)
- m_style->setColumnBreakAfter(*primitiveValue);
- return;
- }
- case CSSPropertyWebkitColumnBreakInside: {
- HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnBreakInside, ColumnBreakInside, PageBreak)
- EPageBreak pb = *primitiveValue;
- if (pb != PBALWAYS)
- m_style->setColumnBreakInside(pb);
- return;
- }
- case CSSPropertyWebkitColumnRule:
- if (isInherit) {
- m_style->setColumnRuleColor(m_parentStyle->columnRuleColor().isValid() ? m_parentStyle->columnRuleColor() : m_parentStyle->color());
- m_style->setColumnRuleStyle(m_parentStyle->columnRuleStyle());
- m_style->setColumnRuleWidth(m_parentStyle->columnRuleWidth());
- }
- else if (isInitial)
- m_style->resetColumnRule();
- return;
- case CSSPropertyWebkitColumns:
- if (isInherit) {
- if (m_parentStyle->hasAutoColumnWidth())
- m_style->setHasAutoColumnWidth();
- else
- m_style->setColumnWidth(m_parentStyle->columnWidth());
- m_style->setColumnCount(m_parentStyle->columnCount());
- } else if (isInitial) {
- m_style->setHasAutoColumnWidth();
- m_style->setColumnCount(RenderStyle::initialColumnCount());
- }
- return;
- case CSSPropertyWebkitMarquee:
- if (valueType != CSSValue::CSS_INHERIT || !m_parentNode) return;
- m_style->setMarqueeDirection(m_parentStyle->marqueeDirection());
- m_style->setMarqueeIncrement(m_parentStyle->marqueeIncrement());
- m_style->setMarqueeSpeed(m_parentStyle->marqueeSpeed());
- m_style->setMarqueeLoopCount(m_parentStyle->marqueeLoopCount());
- m_style->setMarqueeBehavior(m_parentStyle->marqueeBehavior());
- return;
- case CSSPropertyWebkitMarqueeRepetition: {
- HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount)
- if (!primitiveValue)
- return;
- if (primitiveValue->getIdent() == CSSValueInfinite)
- m_style->setMarqueeLoopCount(-1); // -1 means repeat forever.
- else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER)
- m_style->setMarqueeLoopCount(primitiveValue->getIntValue());
- return;
- }
- case CSSPropertyWebkitMarqueeSpeed: {
- HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed)
- if (!primitiveValue)
- return;
- if (primitiveValue->getIdent()) {
- switch (primitiveValue->getIdent()) {
- case CSSValueSlow:
- m_style->setMarqueeSpeed(500); // 500 msec.
- break;
- case CSSValueNormal:
- m_style->setMarqueeSpeed(85); // 85msec. The WinIE default.
- break;
- case CSSValueFast:
- m_style->setMarqueeSpeed(10); // 10msec. Super fast.
- break;
- }
- }
- else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
- m_style->setMarqueeSpeed(1000 * primitiveValue->getIntValue());
- else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS)
- m_style->setMarqueeSpeed(primitiveValue->getIntValue());
- else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support.
- m_style->setMarqueeSpeed(primitiveValue->getIntValue());
- return;
- }
- case CSSPropertyWebkitMarqueeIncrement: {
- HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement)
- if (!primitiveValue)
- return;
- if (primitiveValue->getIdent()) {
- switch (primitiveValue->getIdent()) {
- case CSSValueSmall:
- m_style->setMarqueeIncrement(Length(1, Fixed)); // 1px.
- break;
- case CSSValueNormal:
- m_style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
- break;
- case CSSValueLarge:
- m_style->setMarqueeIncrement(Length(36, Fixed)); // 36px.
- break;
- }
- }
- else {
- bool ok = true;
- Length l = convertToLength(primitiveValue, m_style, &ok);
- if (ok)
- m_style->setMarqueeIncrement(l);
- }
- return;
- }
- case CSSPropertyWebkitMarqueeStyle: {
- HANDLE_INHERIT_AND_INITIAL(marqueeBehavior, MarqueeBehavior)
- if (primitiveValue)
- m_style->setMarqueeBehavior(*primitiveValue);
- return;
- }
- case CSSPropertyWebkitMarqueeDirection: {
- HANDLE_INHERIT_AND_INITIAL(marqueeDirection, MarqueeDirection)
- if (primitiveValue)
- m_style->setMarqueeDirection(*primitiveValue);
- return;
- }
- case CSSPropertyWebkitUserDrag: {
- HANDLE_INHERIT_AND_INITIAL(userDrag, UserDrag)
- if (primitiveValue)
- m_style->setUserDrag(*primitiveValue);
- return;
- }
- case CSSPropertyWebkitUserModify: {
- HANDLE_INHERIT_AND_INITIAL(userModify, UserModify)
- if (primitiveValue)
- m_style->setUserModify(*primitiveValue);
- return;
- }
- case CSSPropertyWebkitUserSelect: {
- HANDLE_INHERIT_AND_INITIAL(userSelect, UserSelect)
- if (primitiveValue)
- m_style->setUserSelect(*primitiveValue);
- return;
- }
- case CSSPropertyTextOverflow: {
- // This property is supported by WinIE, and so we leave off the "-webkit-" in order to
- // work with WinIE-specific pages that use the property.
- HANDLE_INHERIT_AND_INITIAL(textOverflow, TextOverflow)
- if (!primitiveValue || !primitiveValue->getIdent())
- return;
- m_style->setTextOverflow(primitiveValue->getIdent() == CSSValueEllipsis);
- return;
- }
- case CSSPropertyWebkitMarginCollapse: {
- if (isInherit) {
- m_style->setMarginTopCollapse(m_parentStyle->marginTopCollapse());
- m_style->setMarginBottomCollapse(m_parentStyle->marginBottomCollapse());
- }
- else if (isInitial) {
- m_style->setMarginTopCollapse(MCOLLAPSE);
- m_style->setMarginBottomCollapse(MCOLLAPSE);
- }
- return;
- }
- case CSSPropertyWebkitMarginTopCollapse: {
- HANDLE_INHERIT_AND_INITIAL(marginTopCollapse, MarginTopCollapse)
- if (primitiveValue)
- m_style->setMarginTopCollapse(*primitiveValue);
- return;
- }
- case CSSPropertyWebkitMarginBottomCollapse: {
- HANDLE_INHERIT_AND_INITIAL(marginBottomCollapse, MarginBottomCollapse)
- if (primitiveValue)
- m_style->setMarginBottomCollapse(*primitiveValue);
- return;
- }
-
- // Apple-specific changes. Do not merge these properties into KHTML.
- case CSSPropertyWebkitLineClamp: {
- HANDLE_INHERIT_AND_INITIAL(lineClamp, LineClamp)
- if (!primitiveValue)
- return;
- m_style->setLineClamp(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_PERCENTAGE));
- return;
- }
- case CSSPropertyWebkitHighlight: {
- HANDLE_INHERIT_AND_INITIAL(highlight, Highlight);
- if (primitiveValue->getIdent() == CSSValueNone)
- m_style->setHighlight(nullAtom);
- else
- m_style->setHighlight(primitiveValue->getStringValue());
- return;
- }
- case CSSPropertyWebkitBorderFit: {
- HANDLE_INHERIT_AND_INITIAL(borderFit, BorderFit);
- if (primitiveValue->getIdent() == CSSValueBorder)
- m_style->setBorderFit(BorderFitBorder);
- else
- m_style->setBorderFit(BorderFitLines);
- return;
- }
- case CSSPropertyWebkitTextSizeAdjust: {
- HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust)
- if (!primitiveValue || !primitiveValue->getIdent()) return;
- m_style->setTextSizeAdjust(primitiveValue->getIdent() == CSSValueAuto);
- m_fontDirty = true;
- return;
- }
- case CSSPropertyWebkitTextSecurity: {
- HANDLE_INHERIT_AND_INITIAL(textSecurity, TextSecurity)
- if (primitiveValue)
- m_style->setTextSecurity(*primitiveValue);
- return;
- }
-#if ENABLE(DASHBOARD_SUPPORT)
- case CSSPropertyWebkitDashboardRegion: {
- HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions)
- if (!primitiveValue)
- return;
-
- if (primitiveValue->getIdent() == CSSValueNone) {
- m_style->setDashboardRegions(RenderStyle::noneDashboardRegions());
- return;
- }
-
- DashboardRegion *region = primitiveValue->getDashboardRegionValue();
- if (!region)
- return;
-
- DashboardRegion *first = region;
- while (region) {
- Length top = convertToLength (region->top(), m_style);
- Length right = convertToLength (region->right(), m_style);
- Length bottom = convertToLength (region->bottom(), m_style);
- Length left = convertToLength (region->left(), m_style);
- if (region->m_isCircle)
- m_style->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true);
- else if (region->m_isRectangle)
- m_style->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true);
- region = region->m_next.get();
- }
-
- m_element->document()->setHasDashboardRegions(true);
-
- return;
- }
-#endif
- case CSSPropertyWebkitRtlOrdering:
- HANDLE_INHERIT_AND_INITIAL(visuallyOrdered, VisuallyOrdered)
- if (!primitiveValue || !primitiveValue->getIdent())
- return;
- m_style->setVisuallyOrdered(primitiveValue->getIdent() == CSSValueVisual);
- return;
- case CSSPropertyWebkitTextStrokeWidth: {
- HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth)
- float width = 0;
- switch (primitiveValue->getIdent()) {
- case CSSValueThin:
- case CSSValueMedium:
- case CSSValueThick: {
- double result = 1.0 / 48;
- if (primitiveValue->getIdent() == CSSValueMedium)
- result *= 3;
- else if (primitiveValue->getIdent() == CSSValueThick)
- result *= 5;
- width = CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS)->computeLengthFloat(m_style, zoomFactor);
- break;
- }
- default:
- width = primitiveValue->computeLengthFloat(m_style, zoomFactor);
- break;
- }
- m_style->setTextStrokeWidth(width);
- return;
- }
- case CSSPropertyWebkitTransform: {
- HANDLE_INHERIT_AND_INITIAL(transform, Transform);
- TransformOperations operations;
- if (!value->isPrimitiveValue()) {
- CSSValueList* list = static_cast<CSSValueList*>(value);
- unsigned size = list->length();
- for (unsigned i = 0; i < size; i++) {
- WebKitCSSTransformValue* val = static_cast<WebKitCSSTransformValue*>(list->itemWithoutBoundsCheck(i));
-
- CSSPrimitiveValue* firstValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(0));
-
- switch (val->operationType()) {
- case WebKitCSSTransformValue::ScaleTransformOperation:
- case WebKitCSSTransformValue::ScaleXTransformOperation:
- case WebKitCSSTransformValue::ScaleYTransformOperation: {
- double sx = 1.0;
- double sy = 1.0;
- if (val->operationType() == WebKitCSSTransformValue::ScaleYTransformOperation)
- sy = firstValue->getDoubleValue();
- else {
- sx = firstValue->getDoubleValue();
- if (val->operationType() == WebKitCSSTransformValue::ScaleTransformOperation) {
- if (val->length() > 1) {
- CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1));
- sy = secondValue->getDoubleValue();
- } else
- sy = sx;
- }
- }
- operations.append(ScaleTransformOperation::create(sx, sy));
- break;
- }
- case WebKitCSSTransformValue::TranslateTransformOperation:
- case WebKitCSSTransformValue::TranslateXTransformOperation:
- case WebKitCSSTransformValue::TranslateYTransformOperation: {
- bool ok = true;
- Length tx = Length(0, Fixed);
- Length ty = Length(0, Fixed);
- if (val->operationType() == WebKitCSSTransformValue::TranslateYTransformOperation)
- ty = convertToLength(firstValue, m_style, &ok);
- else {
- tx = convertToLength(firstValue, m_style, &ok);
- if (val->operationType() == WebKitCSSTransformValue::TranslateTransformOperation) {
- if (val->length() > 1) {
- CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1));
- ty = convertToLength(secondValue, m_style, &ok);
- }
- }
- }
-
- if (!ok)
- return;
-
- operations.append(TranslateTransformOperation::create(tx, ty));
- break;
- }
- case WebKitCSSTransformValue::RotateTransformOperation: {
- double angle = firstValue->getDoubleValue();
- if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
- angle = rad2deg(angle);
- else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
- angle = grad2deg(angle);
- operations.append(RotateTransformOperation::create(angle));
- break;
- }
- case WebKitCSSTransformValue::SkewTransformOperation:
- case WebKitCSSTransformValue::SkewXTransformOperation:
- case WebKitCSSTransformValue::SkewYTransformOperation: {
- double angleX = 0;
- double angleY = 0;
- double angle = firstValue->getDoubleValue();
- if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
- angle = rad2deg(angle);
- else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
- angle = grad2deg(angle);
- if (val->operationType() == WebKitCSSTransformValue::SkewYTransformOperation)
- angleY = angle;
- else {
- angleX = angle;
- if (val->operationType() == WebKitCSSTransformValue::SkewTransformOperation) {
- if (val->length() > 1) {
- CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1));
- angleY = secondValue->getDoubleValue();
- if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
- angleY = rad2deg(angle);
- else if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
- angleY = grad2deg(angle);
- }
- }
- }
- operations.append(SkewTransformOperation::create(angleX, angleY));
- break;
- }
- case WebKitCSSTransformValue::MatrixTransformOperation: {
- double a = firstValue->getDoubleValue();
- double b = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1))->getDoubleValue();
- double c = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(2))->getDoubleValue();
- double d = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(3))->getDoubleValue();
- double e = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(4))->getDoubleValue();
- double f = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(5))->getDoubleValue();
- operations.append(MatrixTransformOperation::create(a, b, c, d, e, f));
- break;
- }
- case WebKitCSSTransformValue::UnknownTransformOperation:
- ASSERT_NOT_REACHED();
- break;
- }
- }
- }
- m_style->setTransform(operations);
- return;
- }
- case CSSPropertyWebkitTransformOrigin:
- HANDLE_INHERIT_AND_INITIAL(transformOriginX, TransformOriginX)
- HANDLE_INHERIT_AND_INITIAL(transformOriginY, TransformOriginY)
- return;
- case CSSPropertyWebkitTransformOriginX: {
- HANDLE_INHERIT_AND_INITIAL(transformOriginX, TransformOriginX)
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- Length l;
- int type = primitiveValue->primitiveType();
- if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
- l = Length(primitiveValue->computeLengthIntForLength(m_style, zoomFactor), Fixed);
- else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
- l = Length(primitiveValue->getDoubleValue(), Percent);
- else
- return;
- m_style->setTransformOriginX(l);
- break;
- }
- case CSSPropertyWebkitTransformOriginY: {
- HANDLE_INHERIT_AND_INITIAL(transformOriginY, TransformOriginY)
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- Length l;
- int type = primitiveValue->primitiveType();
- if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
- l = Length(primitiveValue->computeLengthIntForLength(m_style, zoomFactor), Fixed);
- else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
- l = Length(primitiveValue->getDoubleValue(), Percent);
- else
- return;
- m_style->setTransformOriginY(l);
- break;
- }
- case CSSPropertyWebkitAnimation:
- if (isInitial)
- m_style->clearAnimations();
- else if (isInherit)
- m_style->inheritAnimations(m_parentStyle->animations());
- return;
- case CSSPropertyWebkitAnimationDelay:
- HANDLE_ANIMATION_VALUE(delay, Delay, value)
- return;
- case CSSPropertyWebkitAnimationDirection:
- HANDLE_ANIMATION_VALUE(direction, Direction, value)
- return;
- case CSSPropertyWebkitAnimationDuration:
- HANDLE_ANIMATION_VALUE(duration, Duration, value)
- return;
- case CSSPropertyWebkitAnimationIterationCount:
- HANDLE_ANIMATION_VALUE(iterationCount, IterationCount, value)
- return;
- case CSSPropertyWebkitAnimationName:
- HANDLE_ANIMATION_VALUE(name, Name, value)
- return;
- case CSSPropertyWebkitAnimationPlayState:
- HANDLE_ANIMATION_VALUE(playState, PlayState, value)
- return;
- case CSSPropertyWebkitAnimationTimingFunction:
- HANDLE_ANIMATION_VALUE(timingFunction, TimingFunction, value)
- return;
- case CSSPropertyWebkitTransition:
- if (isInitial)
- m_style->clearTransitions();
- else if (isInherit)
- m_style->inheritTransitions(m_parentStyle->transitions());
- return;
- case CSSPropertyWebkitTransitionDelay:
- HANDLE_TRANSITION_VALUE(delay, Delay, value)
- return;
- case CSSPropertyWebkitTransitionDuration:
- HANDLE_TRANSITION_VALUE(duration, Duration, value)
- return;
- case CSSPropertyWebkitTransitionProperty:
- HANDLE_TRANSITION_VALUE(property, Property, value)
- return;
- case CSSPropertyWebkitTransitionTimingFunction:
- HANDLE_TRANSITION_VALUE(timingFunction, TimingFunction, value)
- return;
- case CSSPropertyInvalid:
- return;
- case CSSPropertyFontStretch:
- case CSSPropertyPage:
- case CSSPropertyQuotes:
- case CSSPropertyScrollbar3dlightColor:
- case CSSPropertyScrollbarArrowColor:
- case CSSPropertyScrollbarDarkshadowColor:
- case CSSPropertyScrollbarFaceColor:
- case CSSPropertyScrollbarHighlightColor:
- case CSSPropertyScrollbarShadowColor:
- case CSSPropertyScrollbarTrackColor:
- case CSSPropertySize:
- case CSSPropertyTextLineThrough:
- case CSSPropertyTextLineThroughColor:
- case CSSPropertyTextLineThroughMode:
- case CSSPropertyTextLineThroughStyle:
- case CSSPropertyTextLineThroughWidth:
- case CSSPropertyTextOverline:
- case CSSPropertyTextOverlineColor:
- case CSSPropertyTextOverlineMode:
- case CSSPropertyTextOverlineStyle:
- case CSSPropertyTextOverlineWidth:
- case CSSPropertyTextUnderline:
- case CSSPropertyTextUnderlineColor:
- case CSSPropertyTextUnderlineMode:
- case CSSPropertyTextUnderlineStyle:
- case CSSPropertyTextUnderlineWidth:
- case CSSPropertyWebkitFontSizeDelta:
- case CSSPropertyWebkitMarginStart:
- case CSSPropertyWebkitPaddingStart:
- case CSSPropertyWebkitTextDecorationsInEffect:
- case CSSPropertyWebkitTextStroke:
- return;
-#if ENABLE(SVG)
- default:
- // Try the SVG properties
- applySVGProperty(id, value);
-#endif
- }
-}
-
-void CSSStyleSelector::mapFillAttachment(FillLayer* layer, CSSValue* value)
-{
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- layer->setAttachment(FillLayer::initialFillAttachment(layer->type()));
- return;
- }
-
- if (!value->isPrimitiveValue())
- return;
-
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- switch (primitiveValue->getIdent()) {
- case CSSValueFixed:
- layer->setAttachment(false);
- break;
- case CSSValueScroll:
- layer->setAttachment(true);
- break;
- default:
- return;
- }
-}
-
-void CSSStyleSelector::mapFillClip(FillLayer* layer, CSSValue* value)
-{
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- layer->setClip(FillLayer::initialFillClip(layer->type()));
- return;
- }
-
- if (!value->isPrimitiveValue())
- return;
-
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- layer->setClip(*primitiveValue);
-}
-
-void CSSStyleSelector::mapFillComposite(FillLayer* layer, CSSValue* value)
-{
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- layer->setComposite(FillLayer::initialFillComposite(layer->type()));
- return;
- }
-
- if (!value->isPrimitiveValue())
- return;
-
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- layer->setComposite(*primitiveValue);
-}
-
-void CSSStyleSelector::mapFillOrigin(FillLayer* layer, CSSValue* value)
-{
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- layer->setOrigin(FillLayer::initialFillOrigin(layer->type()));
- return;
- }
-
- if (!value->isPrimitiveValue())
- return;
-
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- layer->setOrigin(*primitiveValue);
-}
-
-StyleImage* CSSStyleSelector::styleImage(CSSValue* value)
-{
- if (value->isImageValue())
- return static_cast<CSSImageValue*>(value)->cachedImage(m_element->document()->docLoader());
- if (value->isImageGeneratorValue())
- return static_cast<CSSImageGeneratorValue*>(value)->generatedImage();
- return 0;
-}
-
-void CSSStyleSelector::mapFillImage(FillLayer* layer, CSSValue* value)
-{
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- layer->setImage(FillLayer::initialFillImage(layer->type()));
- return;
- }
-
- layer->setImage(styleImage(value));
-}
-
-void CSSStyleSelector::mapFillRepeat(FillLayer* layer, CSSValue* value)
-{
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- layer->setRepeat(FillLayer::initialFillRepeat(layer->type()));
- return;
- }
-
- if (!value->isPrimitiveValue())
- return;
-
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- layer->setRepeat(*primitiveValue);
-}
-
-void CSSStyleSelector::mapFillSize(FillLayer* layer, CSSValue* value)
-{
- LengthSize b = FillLayer::initialFillSize(layer->type());
-
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- layer->setSize(b);
- return;
- }
-
- if (!value->isPrimitiveValue())
- return;
-
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- Pair* pair = primitiveValue->getPairValue();
- if (!pair)
- return;
-
- CSSPrimitiveValue* first = static_cast<CSSPrimitiveValue*>(pair->first());
- CSSPrimitiveValue* second = static_cast<CSSPrimitiveValue*>(pair->second());
-
- if (!first || !second)
- return;
-
- Length firstLength, secondLength;
- int firstType = first->primitiveType();
- int secondType = second->primitiveType();
-
- float zoomFactor = m_style->effectiveZoom();
-
- if (firstType == CSSPrimitiveValue::CSS_UNKNOWN)
- firstLength = Length(Auto);
- else if (firstType > CSSPrimitiveValue::CSS_PERCENTAGE && firstType < CSSPrimitiveValue::CSS_DEG)
- firstLength = Length(first->computeLengthIntForLength(m_style, zoomFactor), Fixed);
- else if (firstType == CSSPrimitiveValue::CSS_PERCENTAGE)
- firstLength = Length(first->getDoubleValue(), Percent);
- else
- return;
-
- if (secondType == CSSPrimitiveValue::CSS_UNKNOWN)
- secondLength = Length(Auto);
- else if (secondType > CSSPrimitiveValue::CSS_PERCENTAGE && secondType < CSSPrimitiveValue::CSS_DEG)
- secondLength = Length(second->computeLengthIntForLength(m_style, zoomFactor), Fixed);
- else if (secondType == CSSPrimitiveValue::CSS_PERCENTAGE)
- secondLength = Length(second->getDoubleValue(), Percent);
- else
- return;
-
- b.width = firstLength;
- b.height = secondLength;
- layer->setSize(b);
-}
-
-void CSSStyleSelector::mapFillXPosition(FillLayer* layer, CSSValue* value)
-{
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- layer->setXPosition(FillLayer::initialFillXPosition(layer->type()));
- return;
- }
-
- if (!value->isPrimitiveValue())
- return;
-
- float zoomFactor = m_style->effectiveZoom();
-
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- Length l;
- int type = primitiveValue->primitiveType();
- if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
- l = Length(primitiveValue->computeLengthIntForLength(m_style, zoomFactor), Fixed);
- else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
- l = Length(primitiveValue->getDoubleValue(), Percent);
- else
- return;
- layer->setXPosition(l);
-}
-
-void CSSStyleSelector::mapFillYPosition(FillLayer* layer, CSSValue* value)
-{
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- layer->setYPosition(FillLayer::initialFillYPosition(layer->type()));
- return;
- }
-
- if (!value->isPrimitiveValue())
- return;
-
- float zoomFactor = m_style->effectiveZoom();
-
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- Length l;
- int type = primitiveValue->primitiveType();
- if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
- l = Length(primitiveValue->computeLengthIntForLength(m_style, zoomFactor), Fixed);
- else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
- l = Length(primitiveValue->getDoubleValue(), Percent);
- else
- return;
- layer->setYPosition(l);
-}
-
-void CSSStyleSelector::mapAnimationDelay(Animation* animation, CSSValue* value)
-{
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- animation->setDelay(RenderStyle::initialAnimationDelay());
- return;
- }
-
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- if (primitiveValue->getIdent() == CSSValueNow)
- animation->setDelay(0);
- else {
- if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
- animation->setDelay(primitiveValue->getFloatValue());
- else
- animation->setDelay(primitiveValue->getFloatValue()/1000.0f);
- }
-}
-
-void CSSStyleSelector::mapAnimationDirection(Animation* layer, CSSValue* value)
-{
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- layer->setDirection(RenderStyle::initialAnimationDirection());
- return;
- }
-
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- layer->setDirection(primitiveValue->getIdent() == CSSValueAlternate);
-}
-
-void CSSStyleSelector::mapAnimationDuration(Animation* animation, CSSValue* value)
-{
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- animation->setDuration(RenderStyle::initialAnimationDuration());
- return;
- }
-
- if (!value->isPrimitiveValue())
- return;
-
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
- animation->setDuration(primitiveValue->getFloatValue());
- else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS)
- animation->setDuration(primitiveValue->getFloatValue()/1000.0f);
-}
-
-void CSSStyleSelector::mapAnimationIterationCount(Animation* animation, CSSValue* value)
-{
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- animation->setIterationCount(RenderStyle::initialAnimationIterationCount());
- return;
- }
-
- if (!value->isPrimitiveValue())
- return;
-
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- if (primitiveValue->getIdent() == CSSValueInfinite)
- animation->setIterationCount(-1);
- else
- animation->setIterationCount(int(primitiveValue->getFloatValue()));
-}
-
-void CSSStyleSelector::mapAnimationName(Animation* layer, CSSValue* value)
-{
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- layer->setName(RenderStyle::initialAnimationName());
- return;
- }
-
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
-
- if (primitiveValue->getIdent() == CSSValueNone) {
- layer->setIsNoneAnimation(true);
- } else {
- layer->setName(primitiveValue->getStringValue());
-
- // resolve to the keyframes
- RefPtr<KeyframeList> keyframe = findKeyframeRule(primitiveValue->getStringValue());
- layer->setAnimationKeyframe(keyframe);
- }
-}
-
-void CSSStyleSelector::mapAnimationPlayState(Animation* layer, CSSValue* value)
-{
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- layer->setPlayState(RenderStyle::initialAnimationPlayState());
- return;
- }
-
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- layer->setPlayState((primitiveValue->getIdent() == CSSValuePaused) ? AnimPlayStatePaused : AnimPlayStatePlaying);
-}
-
-void CSSStyleSelector::mapAnimationProperty(Animation* animation, CSSValue* value)
-{
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- animation->setProperty(RenderStyle::initialAnimationProperty());
- return;
- }
-
- if (!value->isPrimitiveValue())
- return;
-
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- animation->setProperty(static_cast<CSSPropertyID>(primitiveValue->getIdent()));
-}
-
-void CSSStyleSelector::mapAnimationTimingFunction(Animation* animation, CSSValue* value)
-{
- if (value->cssValueType() == CSSValue::CSS_INITIAL) {
- animation->setTimingFunction(RenderStyle::initialAnimationTimingFunction());
- return;
- }
-
- if (value->isPrimitiveValue()) {
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- switch (primitiveValue->getIdent()) {
- case CSSValueLinear:
- animation->setTimingFunction(TimingFunction(LinearTimingFunction, 0.0, 0.0, 1.0, 1.0));
- break;
- case CSSValueEase:
- animation->setTimingFunction(TimingFunction());
- break;
- case CSSValueEaseIn:
- animation->setTimingFunction(TimingFunction(CubicBezierTimingFunction, 0.42, 0.0, 1.0, 1.0));
- break;
- case CSSValueEaseOut:
- animation->setTimingFunction(TimingFunction(CubicBezierTimingFunction, 0.0, 0.0, 0.58, 1.0));
- break;
- case CSSValueEaseInOut:
- animation->setTimingFunction(TimingFunction(CubicBezierTimingFunction, 0.42, 0.0, 0.58, 1.0));
- break;
- }
- return;
- }
-
- if (value->isTimingFunctionValue()) {
- CSSTimingFunctionValue* timingFunction = static_cast<CSSTimingFunctionValue*>(value);
- animation->setTimingFunction(TimingFunction(CubicBezierTimingFunction, timingFunction->x1(), timingFunction->y1(), timingFunction->x2(), timingFunction->y2()));
- }
-}
-
-void CSSStyleSelector::mapNinePieceImage(CSSValue* value, NinePieceImage& image)
-{
- // If we're a primitive value, then we are "none" and don't need to alter the empty image at all.
- if (!value || value->isPrimitiveValue())
- return;
-
- // Retrieve the border image value.
- CSSBorderImageValue* borderImage = static_cast<CSSBorderImageValue*>(value);
-
- // Set the image (this kicks off the load).
- image.m_image = styleImage(borderImage->imageValue());
-
- // Set up a length box to represent our image slices.
- LengthBox& l = image.m_slices;
- Rect* r = borderImage->m_imageSliceRect.get();
- if (r->top()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
- l.top = Length(r->top()->getDoubleValue(), Percent);
- else
- l.top = Length(r->top()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
- if (r->bottom()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
- l.bottom = Length(r->bottom()->getDoubleValue(), Percent);
- else
- l.bottom = Length((int)r->bottom()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
- if (r->left()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
- l.left = Length(r->left()->getDoubleValue(), Percent);
- else
- l.left = Length(r->left()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
- if (r->right()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
- l.right = Length(r->right()->getDoubleValue(), Percent);
- else
- l.right = Length(r->right()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
-
- // Set the appropriate rules for stretch/round/repeat of the slices
- switch (borderImage->m_horizontalSizeRule) {
- case CSSValueStretch:
- image.m_horizontalRule = StretchImageRule;
- break;
- case CSSValueRound:
- image.m_horizontalRule = RoundImageRule;
- break;
- default: // CSSValueRepeat
- image.m_horizontalRule = RepeatImageRule;
- break;
- }
-
- switch (borderImage->m_verticalSizeRule) {
- case CSSValueStretch:
- image.m_verticalRule = StretchImageRule;
- break;
- case CSSValueRound:
- image.m_verticalRule = RoundImageRule;
- break;
- default: // CSSValueRepeat
- image.m_verticalRule = RepeatImageRule;
- break;
- }
-}
-
-void CSSStyleSelector::checkForTextSizeAdjust()
-{
- if (m_style->textSizeAdjust())
- return;
-
- FontDescription newFontDescription(m_style->fontDescription());
- newFontDescription.setComputedSize(newFontDescription.specifiedSize());
- m_style->setFontDescription(newFontDescription);
-}
-
-void CSSStyleSelector::checkForZoomChange(RenderStyle* style, RenderStyle* parentStyle)
-{
- if (style->effectiveZoom() == parentStyle->effectiveZoom())
- return;
-
- const FontDescription& childFont = style->fontDescription();
- FontDescription newFontDescription(childFont);
- setFontSize(newFontDescription, childFont.specifiedSize());
- style->setFontDescription(newFontDescription);
-}
-
-void CSSStyleSelector::checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle)
-{
- const FontDescription& childFont = style->fontDescription();
-
- if (childFont.isAbsoluteSize() || !parentStyle)
- return;
-
- const FontDescription& parentFont = parentStyle->fontDescription();
-
- if (childFont.genericFamily() == parentFont.genericFamily())
- return;
-
- // For now, lump all families but monospace together.
- if (childFont.genericFamily() != FontDescription::MonospaceFamily &&
- parentFont.genericFamily() != FontDescription::MonospaceFamily)
- return;
-
- // We know the parent is monospace or the child is monospace, and that font
- // size was unspecified. We want to scale our font size as appropriate.
- // If the font uses a keyword size, then we refetch from the table rather than
- // multiplying by our scale factor.
- float size;
- if (childFont.keywordSize()) {
- size = fontSizeForKeyword(CSSValueXxSmall + childFont.keywordSize() - 1, style->htmlHacks(),
- childFont.genericFamily() == FontDescription::MonospaceFamily);
- } else {
- Settings* settings = m_checker.m_document->settings();
- float fixedScaleFactor = settings
- ? static_cast<float>(settings->defaultFixedFontSize()) / settings->defaultFontSize()
- : 1;
- size = (parentFont.genericFamily() == FontDescription::MonospaceFamily) ?
- childFont.specifiedSize()/fixedScaleFactor :
- childFont.specifiedSize()*fixedScaleFactor;
- }
-
- FontDescription newFontDescription(childFont);
- setFontSize(newFontDescription, size);
- style->setFontDescription(newFontDescription);
-}
-
-void CSSStyleSelector::setFontSize(FontDescription& fontDescription, float size)
-{
- fontDescription.setSpecifiedSize(size);
- fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(fontDescription.isAbsoluteSize(), size));
-}
-
-float CSSStyleSelector::getComputedSizeFromSpecifiedSize(bool isAbsoluteSize, float specifiedSize)
-{
- // We support two types of minimum font size. The first is a hard override that applies to
- // all fonts. This is "minSize." The second type of minimum font size is a "smart minimum"
- // that is applied only when the Web page can't know what size it really asked for, e.g.,
- // when it uses logical sizes like "small" or expresses the font-size as a percentage of
- // the user's default font setting.
-
- // With the smart minimum, we never want to get smaller than the minimum font size to keep fonts readable.
- // However we always allow the page to set an explicit pixel size that is smaller,
- // since sites will mis-render otherwise (e.g., http://www.gamespot.com with a 9px minimum).
-
- Settings* settings = m_checker.m_document->settings();
- if (!settings)
- return 1.0f;
-
- int minSize = settings->minimumFontSize();
- int minLogicalSize = settings->minimumLogicalFontSize();
-
- float zoomFactor = m_style->effectiveZoom();
- if (m_checker.m_document->frame() && m_checker.m_document->frame()->shouldApplyTextZoom())
- zoomFactor *= m_checker.m_document->frame()->textZoomFactor();
-
- float zoomedSize = specifiedSize * zoomFactor;
-
- // Apply the hard minimum first. We only apply the hard minimum if after zooming we're still too small.
- if (zoomedSize < minSize)
- zoomedSize = minSize;
-
- // Now apply the "smart minimum." This minimum is also only applied if we're still too small
- // after zooming. The font size must either be relative to the user default or the original size
- // must have been acceptable. In other words, we only apply the smart minimum whenever we're positive
- // doing so won't disrupt the layout.
- if (zoomedSize < minLogicalSize && (specifiedSize >= minLogicalSize || !isAbsoluteSize))
- zoomedSize = minLogicalSize;
-
- // Also clamp to a reasonable maximum to prevent insane font sizes from causing crashes on various
- // platforms (I'm looking at you, Windows.)
- return min(1000000.0f, max(zoomedSize, 1.0f));
-}
-
-const int fontSizeTableMax = 16;
-const int fontSizeTableMin = 9;
-const int totalKeywords = 8;
-
-// WinIE/Nav4 table for font sizes. Designed to match the legacy font mapping system of HTML.
-static const int quirksFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] =
-{
- { 9, 9, 9, 9, 11, 14, 18, 28 },
- { 9, 9, 9, 10, 12, 15, 20, 31 },
- { 9, 9, 9, 11, 13, 17, 22, 34 },
- { 9, 9, 10, 12, 14, 18, 24, 37 },
- { 9, 9, 10, 13, 16, 20, 26, 40 }, // fixed font default (13)
- { 9, 9, 11, 14, 17, 21, 28, 42 },
- { 9, 10, 12, 15, 17, 23, 30, 45 },
- { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font default (16)
-};
-// HTML 1 2 3 4 5 6 7
-// CSS xxs xs s m l xl xxl
-// |
-// user pref
-
-// Strict mode table matches MacIE and Mozilla's settings exactly.
-static const int strictFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] =
-{
- { 9, 9, 9, 9, 11, 14, 18, 27 },
- { 9, 9, 9, 10, 12, 15, 20, 30 },
- { 9, 9, 10, 11, 13, 17, 22, 33 },
- { 9, 9, 10, 12, 14, 18, 24, 36 },
- { 9, 10, 12, 13, 16, 20, 26, 39 }, // fixed font default (13)
- { 9, 10, 12, 14, 17, 21, 28, 42 },
- { 9, 10, 13, 15, 18, 23, 30, 45 },
- { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font default (16)
-};
-// HTML 1 2 3 4 5 6 7
-// CSS xxs xs s m l xl xxl
-// |
-// user pref
-
-// For values outside the range of the table, we use Todd Fahrner's suggested scale
-// factors for each keyword value.
-static const float fontSizeFactors[totalKeywords] = { 0.60f, 0.75f, 0.89f, 1.0f, 1.2f, 1.5f, 2.0f, 3.0f };
-
-float CSSStyleSelector::fontSizeForKeyword(int keyword, bool quirksMode, bool fixed) const
-{
- Settings* settings = m_checker.m_document->settings();
- if (!settings)
- return 1.0f;
-
- int mediumSize = fixed ? settings->defaultFixedFontSize() : settings->defaultFontSize();
- if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) {
- // Look up the entry in the table.
- int row = mediumSize - fontSizeTableMin;
- int col = (keyword - CSSValueXxSmall);
- return quirksMode ? quirksFontSizeTable[row][col] : strictFontSizeTable[row][col];
- }
-
- // Value is outside the range of the table. Apply the scale factor instead.
- float minLogicalSize = max(settings->minimumLogicalFontSize(), 1);
- return max(fontSizeFactors[keyword - CSSValueXxSmall]*mediumSize, minLogicalSize);
-}
-
-float CSSStyleSelector::largerFontSize(float size, bool quirksMode) const
-{
- // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale up to
- // the next size level.
- return size * 1.2f;
-}
-
-float CSSStyleSelector::smallerFontSize(float size, bool quirksMode) const
-{
- // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale down to
- // the next size level.
- return size / 1.2f;
-}
-
-static Color colorForCSSValue(int cssValueId)
-{
- struct ColorValue {
- int cssValueId;
- RGBA32 color;
- };
-
- static const ColorValue colorValues[] = {
- { CSSValueAqua, 0xFF00FFFF },
- { CSSValueBlack, 0xFF000000 },
- { CSSValueBlue, 0xFF0000FF },
- { CSSValueFuchsia, 0xFFFF00FF },
- { CSSValueGray, 0xFF808080 },
- { CSSValueGreen, 0xFF008000 },
- { CSSValueGrey, 0xFF808080 },
- { CSSValueLime, 0xFF00FF00 },
- { CSSValueMaroon, 0xFF800000 },
- { CSSValueNavy, 0xFF000080 },
- { CSSValueOlive, 0xFF808000 },
- { CSSValueOrange, 0xFFFFA500 },
- { CSSValuePurple, 0xFF800080 },
- { CSSValueRed, 0xFFFF0000 },
- { CSSValueSilver, 0xFFC0C0C0 },
- { CSSValueTeal, 0xFF008080 },
- { CSSValueTransparent, 0x00000000 },
- { CSSValueWhite, 0xFFFFFFFF },
- { CSSValueYellow, 0xFFFFFF00 },
- { 0, 0 }
- };
-
- for (const ColorValue* col = colorValues; col->cssValueId; ++col) {
- if (col->cssValueId == cssValueId)
- return col->color;
- }
- return theme()->systemColor(cssValueId);
-}
-
-Color CSSStyleSelector::getColorFromPrimitiveValue(CSSPrimitiveValue* primitiveValue)
-{
- Color col;
- int ident = primitiveValue->getIdent();
- if (ident) {
- if (ident == CSSValueWebkitText)
- col = m_element->document()->textColor();
- else if (ident == CSSValueWebkitLink) {
- const Color& linkColor = m_element->document()->linkColor();
- const Color& visitedColor = m_element->document()->visitedLinkColor();
- if (linkColor == visitedColor)
- col = linkColor;
- else {
- if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink)
- pseudoState = m_checker.checkPseudoState(m_element);
- col = (pseudoState == PseudoLink) ? linkColor : visitedColor;
- }
- } else if (ident == CSSValueWebkitActivelink)
- col = m_element->document()->activeLinkColor();
- else if (ident == CSSValueWebkitFocusRingColor)
- col = focusRingColor();
- else if (ident == CSSValueCurrentcolor)
- col = m_style->color();
- else
- col = colorForCSSValue(ident);
- } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR)
- col.setRGB(primitiveValue->getRGBColorValue());
- return col;
-}
-
-bool CSSStyleSelector::hasSelectorForAttribute(const AtomicString &attrname)
-{
- return m_selectorAttrs.contains(attrname.impl());
-}
-
-void CSSStyleSelector::addViewportDependentMediaQueryResult(const MediaQueryExp* expr, bool result)
-{
- m_viewportDependentMediaQueryResults.append(new MediaQueryResult(*expr, result));
-}
-
-bool CSSStyleSelector::affectedByViewportChange() const
-{
- unsigned s = m_viewportDependentMediaQueryResults.size();
- for (unsigned i = 0; i < s; i++) {
- if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result)
- return true;
- }
- return false;
-}
-
-void CSSStyleSelector::SelectorChecker::allVisitedStateChanged()
-{
- if (m_linksCheckedForVisitedState.isEmpty())
- return;
- for (Node* node = m_document; node; node = node->traverseNextNode()) {
- if (node->isLink())
- node->setChanged();
- }
-}
-
-void CSSStyleSelector::SelectorChecker::visitedStateChanged(unsigned visitedHash)
-{
- if (!m_linksCheckedForVisitedState.contains(visitedHash))
- return;
- for (Node* node = m_document; node; node = node->traverseNextNode()) {
- const AtomicString* attr = linkAttribute(node);
- if (attr && m_document->visitedLinkHash(*attr) == visitedHash)
- node->setChanged();
- }
-}
-
-} // namespace WebCore
diff --git a/webkit/pending/CachedCSSStyleSheet.cpp b/webkit/pending/CachedCSSStyleSheet.cpp
deleted file mode 100644
index 8b9ee31..0000000
--- a/webkit/pending/CachedCSSStyleSheet.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
- Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
- Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
- Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
- Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-
- This class provides all functionality needed for loading images, style sheets and html
- pages from the web. It has a memory cache for these objects.
-*/
-
-#include "config.h"
-#include "CachedCSSStyleSheet.h"
-
-#include "CachedResourceClient.h"
-#include "CachedResourceClientWalker.h"
-#include "TextResourceDecoder.h"
-#include "loader.h"
-#include <wtf/Vector.h>
-
-namespace WebCore {
-
-CachedCSSStyleSheet::CachedCSSStyleSheet(const String& url, const String& charset)
- : CachedResource(url, CSSStyleSheet)
- , m_decoder(TextResourceDecoder::create("text/css", charset))
-{
- // Prefer text/css but accept any type (dell.com serves a stylesheet
- // as text/html; see <http://bugs.webkit.org/show_bug.cgi?id=11451>).
- setAccept("text/css,*/*;q=0.1");
-}
-
-CachedCSSStyleSheet::~CachedCSSStyleSheet()
-{
-}
-
-void CachedCSSStyleSheet::addClient(CachedResourceClient *c)
-{
- CachedResource::addClient(c);
-
- if (!m_loading)
- c->setCSSStyleSheet(m_url, m_decoder->encoding().name(), this);
-}
-
-void CachedCSSStyleSheet::setEncoding(const String& chs)
-{
- m_decoder->setEncoding(chs, TextResourceDecoder::EncodingFromHTTPHeader);
-}
-
-String CachedCSSStyleSheet::encoding() const
-{
- return m_decoder->encoding().name();
-}
-
-void CachedCSSStyleSheet::data(PassRefPtr<SharedBuffer> data, bool allDataReceived)
-{
- if (!allDataReceived)
- return;
-
- m_data = data;
- setEncodedSize(m_data.get() ? m_data->size() : 0);
- if (m_data.get()) {
- m_sheet = m_decoder->decode(m_data->data(), encodedSize());
- m_sheet += m_decoder->flush();
- m_data = 0; // We no longer need the raw buffer.
- }
- m_loading = false;
- checkNotify();
-}
-
-void CachedCSSStyleSheet::checkNotify()
-{
- if (m_loading)
- return;
-
- CachedResourceClientWalker w(m_clients);
- while (CachedResourceClient *c = w.next())
- c->setCSSStyleSheet(m_response.url().string(), m_decoder->encoding().name(), this);
-
-#if USE(LOW_BANDWIDTH_DISPLAY)
- // if checkNotify() is called from error(), client's setCSSStyleSheet(...)
- // can't find "this" from url, so they can't do clean up if needed.
- // call notifyFinished() to make sure they have a chance.
- CachedResourceClientWalker n(m_clients);
- while (CachedResourceClient* s = n.next())
- s->notifyFinished(this);
-#endif
-}
-
-void CachedCSSStyleSheet::error()
-{
- m_loading = false;
- m_errorOccurred = true;
- checkNotify();
-}
-
-bool CachedCSSStyleSheet::canUseSheet(bool enforceMIMEType) const
-{
- if (errorOccurred())
- return false;
-
- if (!enforceMIMEType)
- return true;
-
- // This check exactly matches Firefox.
- String mimeType = response().mimeType();
- return mimeType.isEmpty() || equalIgnoringCase(mimeType, "text/css") || equalIgnoringCase(mimeType, "application/x-unknown-content-type");
-}
-
-}
diff --git a/webkit/pending/CachedResource.h b/webkit/pending/CachedResource.h
deleted file mode 100644
index bcd03e0..0000000
--- a/webkit/pending/CachedResource.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
- Copyright (C) 2001 Dirk Mueller <mueller@kde.org>
- Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
- Copyright (C) 2004, 2005, 2006, 2007 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
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#ifndef CachedResource_h
-#define CachedResource_h
-
-#include "PlatformString.h"
-#include "ResourceResponse.h"
-#include "SharedBuffer.h"
-#include <wtf/HashCountedSet.h>
-#include <wtf/Vector.h>
-#include <time.h>
-
-namespace WebCore {
-
-class Cache;
-class CachedResourceClient;
-class CacheHandleBase;
-class DocLoader;
-class Request;
-
-// A resource that is held in the cache. Classes who want to use this object should derive
-// from CachedResourceClient, to get the function calls in case the requested data has arrived.
-// This class also does the actual communication with the loader to obtain the resource from the network.
-class CachedResource {
- friend class Cache;
-
-public:
- enum Type {
- ImageResource,
- CSSStyleSheet,
- Script,
- FontResource
-#if ENABLE(XSLT)
- , XSLStyleSheet
-#endif
-#if ENABLE(XBL)
- , XBL
-#endif
- };
-
- enum Status {
- NotCached, // this URL is not cached
- Unknown, // let cache decide what to do with it
- New, // inserting new item
- Pending, // only partially loaded
- Cached // regular case
- };
-
- CachedResource(const String& url, Type);
- virtual ~CachedResource();
-
- virtual void load(DocLoader* docLoader) { load(docLoader, false, false, true); }
- void load(DocLoader*, bool incremental, bool skipCanLoadCheck, bool sendResourceLoadCallbacks);
-
- virtual void setEncoding(const String&) { }
- virtual String encoding() const { return String(); }
- virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived) = 0;
- virtual void error() = 0;
-
- const String &url() const { return m_url; }
- Type type() const { return m_type; }
-
- virtual void addClient(CachedResourceClient*);
- void removeClient(CachedResourceClient*);
- bool hasClients() const { return !m_clients.isEmpty(); }
-
- enum PreloadResult {
- PreloadNotReferenced,
- PreloadReferenced,
- PreloadReferencedWhileLoading,
- PreloadReferencedWhileComplete
- };
- PreloadResult preloadResult() const { return m_preloadResult; }
- void setRequestedFromNetworkingLayer() { m_requestedFromNetworkingLayer = true; }
-
- virtual void allClientsRemoved() { };
-
- unsigned count() const { return m_clients.size(); }
-
- Status status() const { return m_status; }
-
- unsigned size() const { return encodedSize() + decodedSize(); }
- unsigned encodedSize() const { return m_encodedSize; }
- unsigned decodedSize() const { return m_decodedSize; }
-
- bool isLoaded() const { return !m_loading; }
- void setLoading(bool b) { m_loading = b; }
-
- virtual bool isImage() const { return false; }
-
- unsigned accessCount() const { return m_accessCount; }
- void increaseAccessCount() { m_accessCount++; }
-
- // Computes the status of an object after loading.
- // Updates the expire date on the cache entry file
- void finish();
-
- // Called by the cache if the object has been removed from the cache
- // while still being referenced. This means the object should delete itself
- // if the number of clients observing it ever drops to 0.
- void setInCache(bool b) { m_inCache = b; }
- bool inCache() const { return m_inCache; }
-
- void setInLiveDecodedResourcesList(bool b) { m_inLiveDecodedResourcesList = b; }
- bool inLiveDecodedResourcesList() { return m_inLiveDecodedResourcesList; }
-
- void setRequest(Request*);
-
- void setResponse(const ResourceResponse& response) { m_response = response; }
- const ResourceResponse& response() const { return m_response; }
-
- bool canDelete() const { return !hasClients() && !m_request && !m_preloadCount; }
-
- bool isExpired() const;
-
- virtual bool schedule() const { return false; }
-
- // List of acceptable MIME types seperated by ",".
- // A MIME type may contain a wildcard, e.g. "text/*".
- String accept() const { return m_accept; }
- void setAccept(const String& accept) { m_accept = accept; }
-
- bool errorOccurred() const { return m_errorOccurred; }
- bool sendResourceLoadCallbacks() const { return m_sendResourceLoadCallbacks; }
-
- virtual void destroyDecodedData() {};
-
- void setDocLoader(DocLoader* docLoader) { m_docLoader = docLoader; }
-
-#if PLATFORM(MAC)
- SharedBuffer* data() const { return m_data.get(); }
-#endif
-
- bool isPreloaded() const { return m_preloadCount; }
- void increasePreloadCount() { ++m_preloadCount; }
- void decreasePreloadCount() { ASSERT(m_preloadCount); --m_preloadCount; }
-
-protected:
- void setEncodedSize(unsigned);
- void setDecodedSize(unsigned);
- void didAccessDecodedData(double timeStamp);
-
- HashCountedSet<CachedResourceClient*> m_clients;
-
- String m_url;
- String m_accept;
- Request* m_request;
-
- ResourceResponse m_response;
- RefPtr<SharedBuffer> m_data;
-
- Type m_type;
- Status m_status;
-
- bool m_errorOccurred;
-
-private:
- unsigned m_encodedSize;
- unsigned m_decodedSize;
- unsigned m_accessCount;
- unsigned m_inLiveDecodedResourcesList;
- double m_lastDecodedAccessTime; // Used as a "thrash guard" in the cache
-
- bool m_sendResourceLoadCallbacks;
-
- unsigned m_preloadCount;
- PreloadResult m_preloadResult;
- bool m_requestedFromNetworkingLayer;
-
-protected:
- bool m_inCache;
- bool m_loading;
- bool m_expireDateChanged;
-#ifndef NDEBUG
- bool m_deleted;
- unsigned m_lruIndex;
-#endif
-
-private:
- CachedResource* m_nextInAllResourcesList;
- CachedResource* m_prevInAllResourcesList;
-
- CachedResource* m_nextInLiveResourcesList;
- CachedResource* m_prevInLiveResourcesList;
-
- DocLoader* m_docLoader; // only non-0 for resources that are not in the cache
-};
-
-}
-
-#endif
diff --git a/webkit/pending/CachedScript.cpp b/webkit/pending/CachedScript.cpp
deleted file mode 100644
index 6a67c6f..0000000
--- a/webkit/pending/CachedScript.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- This file is part of the KDE libraries
-
- Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
- Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
- Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
- Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
- Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-
- This class provides all functionality needed for loading images, style sheets and html
- pages from the web. It has a memory cache for these objects.
-*/
-
-#include "config.h"
-#include "CachedScript.h"
-
-#include "CachedResourceClient.h"
-#include "CachedResourceClientWalker.h"
-#include <wtf/Vector.h>
-
-namespace WebCore {
-
-CachedScript::CachedScript(const String& url, const String& charset)
- : CachedResource(url, Script)
- , m_encoding(charset)
-{
- // It's javascript we want.
- // But some websites think their scripts are <some wrong mimetype here>
- // and refuse to serve them if we only accept application/x-javascript.
- setAccept("*/*");
- if (!m_encoding.isValid())
- m_encoding = Latin1Encoding();
-}
-
-CachedScript::~CachedScript()
-{
-}
-
-void CachedScript::addClient(CachedResourceClient* c)
-{
- CachedResource::addClient(c);
- if (!m_loading)
- c->notifyFinished(this);
-}
-
-void CachedScript::setEncoding(const String& chs)
-{
- TextEncoding encoding(chs);
- if (encoding.isValid())
- m_encoding = encoding;
-}
-
-String CachedScript::encoding() const
-{
- return m_encoding.name();
-}
-
-void CachedScript::data(PassRefPtr<SharedBuffer> data, bool allDataReceived)
-{
- if (!allDataReceived)
- return;
-
- m_data = data;
- setEncodedSize(m_data.get() ? m_data->size() : 0);
- if (m_data.get()) {
- m_script = m_encoding.decode(m_data->data(), encodedSize());
- m_data = 0; // We no longer need the raw buffer.
- }
- m_loading = false;
- checkNotify();
-}
-
-void CachedScript::checkNotify()
-{
- if (m_loading)
- return;
-
- CachedResourceClientWalker w(m_clients);
- while (CachedResourceClient* c = w.next())
- c->notifyFinished(this);
-}
-
-void CachedScript::error()
-{
- m_loading = false;
- m_errorOccurred = true;
- checkNotify();
-}
-
-}
diff --git a/webkit/pending/CanvasRenderingContext2D.cpp b/webkit/pending/CanvasRenderingContext2D.cpp
deleted file mode 100644
index 12cdcd4..0000000
--- a/webkit/pending/CanvasRenderingContext2D.cpp
+++ /dev/null
@@ -1,1352 +0,0 @@
-/*
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Trolltech ASA
- * Copyright (C) 2007 Alp Toker <alp@atoker.com>
- * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "CanvasRenderingContext2D.h"
-
-#include "AffineTransform.h"
-#include "CSSParser.h"
-#include "CachedImage.h"
-#include "CanvasGradient.h"
-#include "CanvasPattern.h"
-#include "CanvasPixelArray.h"
-#include "CanvasStyle.h"
-#include "CSSPropertyNames.h"
-#include "CSSStyleSelector.h"
-#include "Document.h"
-#include "ExceptionCode.h"
-#include "FloatConversion.h"
-#include "Frame.h"
-#include "GraphicsContext.h"
-#include "HTMLCanvasElement.h"
-#include "HTMLImageElement.h"
-#include "HTMLNames.h"
-#include "ImageBuffer.h"
-#include "ImageData.h"
-#include "KURL.h"
-#include "NotImplemented.h"
-#include "Page.h"
-#include "RenderHTMLCanvas.h"
-#include "SecurityOrigin.h"
-#include "Settings.h"
-#include "TextMetrics.h"
-#include <kjs/interpreter.h>
-#include <stdio.h>
-#include <wtf/MathExtras.h>
-
-using namespace std;
-
-namespace WebCore {
-
-using namespace HTMLNames;
-
-const char* defaultFont = "10px sans-serif";
-
-CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas)
- : m_canvas(canvas)
- , m_stateStack(1)
-#if USE(V8)
- , m_peer(0)
-#endif
-{
-}
-
-void CanvasRenderingContext2D::ref()
-{
- m_canvas->ref();
-}
-
-void CanvasRenderingContext2D::deref()
-{
- m_canvas->deref();
-}
-
-void CanvasRenderingContext2D::reset()
-{
- m_stateStack.resize(1);
- m_stateStack.first() = State();
-}
-
-CanvasRenderingContext2D::State::State()
- : m_strokeStyle(CanvasStyle::create("black"))
- , m_fillStyle(CanvasStyle::create("black"))
- , m_lineWidth(1)
- , m_lineCap(ButtCap)
- , m_lineJoin(MiterJoin)
- , m_miterLimit(10)
- , m_shadowBlur(0)
- , m_shadowColor("black")
- , m_globalAlpha(1)
- , m_globalComposite(CompositeSourceOver)
- , m_textAlign(StartTextAlign)
- , m_textBaseline(AlphabeticTextBaseline)
- , m_unparsedFont(defaultFont)
- , m_realizedFont(false)
-{
-}
-
-void CanvasRenderingContext2D::save()
-{
- ASSERT(m_stateStack.size() >= 1);
- m_stateStack.append(state());
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- c->save();
-}
-
-void CanvasRenderingContext2D::restore()
-{
- ASSERT(m_stateStack.size() >= 1);
- if (m_stateStack.size() <= 1)
- return;
- m_path.transform(state().m_transform);
- m_stateStack.removeLast();
- m_path.transform(state().m_transform.inverse());
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- c->restore();
-}
-
-CanvasStyle* CanvasRenderingContext2D::strokeStyle() const
-{
- return state().m_strokeStyle.get();
-}
-
-void CanvasRenderingContext2D::setStrokeStyle(PassRefPtr<CanvasStyle> style)
-{
- if (!style)
- return;
-
- if (m_canvas->originClean()) {
- if (CanvasPattern* pattern = style->canvasPattern()) {
- if (!pattern->originClean())
- m_canvas->setOriginTainted();
- }
- }
-
- state().m_strokeStyle = style;
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- state().m_strokeStyle->applyStrokeColor(c);
-}
-
-CanvasStyle* CanvasRenderingContext2D::fillStyle() const
-{
- return state().m_fillStyle.get();
-}
-
-void CanvasRenderingContext2D::setFillStyle(PassRefPtr<CanvasStyle> style)
-{
- if (!style)
- return;
-
- if (m_canvas->originClean()) {
- if (CanvasPattern* pattern = style->canvasPattern()) {
- if (!pattern->originClean())
- m_canvas->setOriginTainted();
- }
- }
-
- state().m_fillStyle = style;
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- state().m_fillStyle->applyFillColor(c);
-}
-
-float CanvasRenderingContext2D::lineWidth() const
-{
- return state().m_lineWidth;
-}
-
-void CanvasRenderingContext2D::setLineWidth(float width)
-{
- if (!(width > 0))
- return;
- state().m_lineWidth = width;
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- c->setStrokeThickness(width);
-}
-
-String CanvasRenderingContext2D::lineCap() const
-{
- return lineCapName(state().m_lineCap);
-}
-
-void CanvasRenderingContext2D::setLineCap(const String& s)
-{
- LineCap cap;
- if (!parseLineCap(s, cap))
- return;
- state().m_lineCap = cap;
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- c->setLineCap(cap);
-}
-
-String CanvasRenderingContext2D::lineJoin() const
-{
- return lineJoinName(state().m_lineJoin);
-}
-
-void CanvasRenderingContext2D::setLineJoin(const String& s)
-{
- LineJoin join;
- if (!parseLineJoin(s, join))
- return;
- state().m_lineJoin = join;
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- c->setLineJoin(join);
-}
-
-float CanvasRenderingContext2D::miterLimit() const
-{
- return state().m_miterLimit;
-}
-
-void CanvasRenderingContext2D::setMiterLimit(float limit)
-{
- if (!(limit > 0))
- return;
- state().m_miterLimit = limit;
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- c->setMiterLimit(limit);
-}
-
-float CanvasRenderingContext2D::shadowOffsetX() const
-{
- return state().m_shadowOffset.width();
-}
-
-void CanvasRenderingContext2D::setShadowOffsetX(float x)
-{
- state().m_shadowOffset.setWidth(x);
- applyShadow();
-}
-
-float CanvasRenderingContext2D::shadowOffsetY() const
-{
- return state().m_shadowOffset.height();
-}
-
-void CanvasRenderingContext2D::setShadowOffsetY(float y)
-{
- state().m_shadowOffset.setHeight(y);
- applyShadow();
-}
-
-float CanvasRenderingContext2D::shadowBlur() const
-{
- return state().m_shadowBlur;
-}
-
-void CanvasRenderingContext2D::setShadowBlur(float blur)
-{
- state().m_shadowBlur = blur;
- applyShadow();
-}
-
-String CanvasRenderingContext2D::shadowColor() const
-{
- // FIXME: What should this return if you called setShadow with a non-string color?
- return state().m_shadowColor;
-}
-
-void CanvasRenderingContext2D::setShadowColor(const String& color)
-{
- state().m_shadowColor = color;
- applyShadow();
-}
-
-float CanvasRenderingContext2D::globalAlpha() const
-{
- return state().m_globalAlpha;
-}
-
-void CanvasRenderingContext2D::setGlobalAlpha(float alpha)
-{
- if (!(alpha >= 0 && alpha <= 1))
- return;
- state().m_globalAlpha = alpha;
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- c->setAlpha(alpha);
-}
-
-String CanvasRenderingContext2D::globalCompositeOperation() const
-{
- return compositeOperatorName(state().m_globalComposite);
-}
-
-void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operation)
-{
- CompositeOperator op;
- if (!parseCompositeOperator(operation, op))
- return;
- state().m_globalComposite = op;
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- c->setCompositeOperation(op);
-}
-
-void CanvasRenderingContext2D::scale(float sx, float sy)
-{
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- c->scale(FloatSize(sx, sy));
- state().m_transform.scale(sx, sy);
- m_path.transform(AffineTransform().scale(1.0/sx, 1.0/sy));
-}
-
-void CanvasRenderingContext2D::rotate(float angleInRadians)
-{
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- c->rotate(angleInRadians);
- state().m_transform.rotate(angleInRadians / piDouble * 180.0);
- m_path.transform(AffineTransform().rotate(-angleInRadians / piDouble * 180.0));
-}
-
-void CanvasRenderingContext2D::translate(float tx, float ty)
-{
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- c->translate(tx, ty);
- state().m_transform.translate(tx, ty);
- m_path.transform(AffineTransform().translate(-tx, -ty));
-}
-
-void CanvasRenderingContext2D::transform(float m11, float m12, float m21, float m22, float dx, float dy)
-{
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
-
- // HTML5 3.14.11.1 -- ignore any calls that pass non-finite numbers
- if (!isfinite(m11) | !isfinite(m21) | !isfinite(dx) |
- !isfinite(m12) | !isfinite(m22) | !isfinite(dy))
- return;
- AffineTransform transform(m11, m12, m21, m22, dx, dy);
- c->concatCTM(transform);
- state().m_transform.multiply(transform);
- m_path.transform(transform.inverse());
-}
-
-void CanvasRenderingContext2D::setStrokeColor(const String& color)
-{
- setStrokeStyle(CanvasStyle::create(color));
-}
-
-void CanvasRenderingContext2D::setStrokeColor(float grayLevel)
-{
- setStrokeStyle(CanvasStyle::create(grayLevel, 1));
-}
-
-void CanvasRenderingContext2D::setStrokeColor(const String& color, float alpha)
-{
- setStrokeStyle(CanvasStyle::create(color, alpha));
-}
-
-void CanvasRenderingContext2D::setStrokeColor(float grayLevel, float alpha)
-{
- setStrokeStyle(CanvasStyle::create(grayLevel, alpha));
-}
-
-void CanvasRenderingContext2D::setStrokeColor(float r, float g, float b, float a)
-{
- setStrokeStyle(CanvasStyle::create(r, g, b, a));
-}
-
-void CanvasRenderingContext2D::setStrokeColor(float c, float m, float y, float k, float a)
-{
- setStrokeStyle(CanvasStyle::create(c, m, y, k, a));
-}
-
-void CanvasRenderingContext2D::setFillColor(const String& color)
-{
- setFillStyle(CanvasStyle::create(color));
-}
-
-void CanvasRenderingContext2D::setFillColor(float grayLevel)
-{
- setFillStyle(CanvasStyle::create(grayLevel, 1));
-}
-
-void CanvasRenderingContext2D::setFillColor(const String& color, float alpha)
-{
- setFillStyle(CanvasStyle::create(color, 1));
-}
-
-void CanvasRenderingContext2D::setFillColor(float grayLevel, float alpha)
-{
- setFillStyle(CanvasStyle::create(grayLevel, alpha));
-}
-
-void CanvasRenderingContext2D::setFillColor(float r, float g, float b, float a)
-{
- setFillStyle(CanvasStyle::create(r, g, b, a));
-}
-
-void CanvasRenderingContext2D::setFillColor(float c, float m, float y, float k, float a)
-{
- setFillStyle(CanvasStyle::create(c, m, y, k, a));
-}
-
-void CanvasRenderingContext2D::beginPath()
-{
- m_path.clear();
-}
-
-void CanvasRenderingContext2D::closePath()
-{
- m_path.closeSubpath();
-}
-
-void CanvasRenderingContext2D::moveTo(float x, float y)
-{
- if (!isfinite(x) | !isfinite(y))
- return;
- m_path.moveTo(FloatPoint(x, y));
-}
-
-void CanvasRenderingContext2D::lineTo(float x, float y)
-{
- if (!isfinite(x) | !isfinite(y))
- return;
- m_path.addLineTo(FloatPoint(x, y));
-}
-
-void CanvasRenderingContext2D::quadraticCurveTo(float cpx, float cpy, float x, float y)
-{
- if (!isfinite(cpx) | !isfinite(cpy) | !isfinite(x) | !isfinite(y))
- return;
- m_path.addQuadCurveTo(FloatPoint(cpx, cpy), FloatPoint(x, y));
-}
-
-void CanvasRenderingContext2D::bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y)
-{
- if (!isfinite(cp1x) | !isfinite(cp1y) | !isfinite(cp2x) | !isfinite(cp2y) | !isfinite(x) | !isfinite(y))
- return;
- m_path.addBezierCurveTo(FloatPoint(cp1x, cp1y), FloatPoint(cp2x, cp2y), FloatPoint(x, y));
-}
-
-void CanvasRenderingContext2D::arcTo(float x0, float y0, float x1, float y1, float r, ExceptionCode& ec)
-{
- ec = 0;
- if (!isfinite(x0) | !isfinite(y0) | !isfinite(x1) | !isfinite(y1) | !isfinite(r))
- return;
-
- if (r < 0) {
- ec = INDEX_SIZE_ERR;
- return;
- }
-
- m_path.addArcTo(FloatPoint(x0, y0), FloatPoint(x1, y1), r);
-}
-
-void CanvasRenderingContext2D::arc(float x, float y, float r, float sa, float ea, bool anticlockwise, ExceptionCode& ec)
-{
- ec = 0;
- if (!isfinite(x) | !isfinite(y) | !isfinite(r) | !isfinite(sa) | !isfinite(ea))
- return;
-
- if (r < 0) {
- ec = INDEX_SIZE_ERR;
- return;
- }
-
- m_path.addArc(FloatPoint(x, y), r, sa, ea, anticlockwise);
-}
-
-static bool validateRectForCanvas(float& x, float& y, float& width, float& height)
-{
- if (!isfinite(x) | !isfinite(y) | !isfinite(width) | !isfinite(height))
- return false;
-
- if (width < 0) {
- width = -width;
- x -= width;
- }
-
- if (height < 0) {
- height = -height;
- y -= height;
- }
-
- return true;
-}
-
-void CanvasRenderingContext2D::rect(float x, float y, float width, float height)
-{
- if (!validateRectForCanvas(x, y, width, height))
- return;
-
- m_path.addRect(FloatRect(x, y, width, height));
-}
-
-#if ENABLE(DASHBOARD_SUPPORT)
-void CanvasRenderingContext2D::clearPathForDashboardBackwardCompatibilityMode()
-{
- if (Settings* settings = m_canvas->document()->settings())
- if (settings->usesDashboardBackwardCompatibilityMode())
- m_path.clear();
-}
-#endif
-
-void CanvasRenderingContext2D::fill()
-{
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
-
- c->beginPath();
- c->addPath(m_path);
- if (!m_path.isEmpty())
- willDraw(m_path.boundingRect());
-
- c->fillPath();
-
-#if ENABLE(DASHBOARD_SUPPORT)
- clearPathForDashboardBackwardCompatibilityMode();
-#endif
-}
-
-void CanvasRenderingContext2D::stroke()
-{
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- c->beginPath();
- c->addPath(m_path);
-
- if (!m_path.isEmpty()) {
- // FIXME: This is insufficient, need to use CGContextReplacePathWithStrokedPath to expand to required bounds
- float lineWidth = state().m_lineWidth;
- float inset = lineWidth / 2;
- FloatRect boundingRect = m_path.boundingRect();
- boundingRect.inflate(inset);
- willDraw(boundingRect);
- }
-
- c->strokePath();
-
-#if ENABLE(DASHBOARD_SUPPORT)
- clearPathForDashboardBackwardCompatibilityMode();
-#endif
-}
-
-void CanvasRenderingContext2D::clip()
-{
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- c->clip(m_path);
-#if ENABLE(DASHBOARD_SUPPORT)
- clearPathForDashboardBackwardCompatibilityMode();
-#endif
-}
-
-bool CanvasRenderingContext2D::isPointInPath(const float x, const float y)
-{
- GraphicsContext* c = drawingContext();
- if (!c)
- return false;
- FloatPoint point(x, y);
- // We have to invert the current transform to ensure we correctly handle the
- // transforms applied to the current path.
- AffineTransform ctm = state().m_transform;
- if (!ctm.isInvertible())
- return false;
- FloatPoint transformedPoint = ctm.inverse().mapPoint(point);
- return m_path.contains(transformedPoint);
-}
-
-void CanvasRenderingContext2D::clearRect(float x, float y, float width, float height)
-{
- if (!validateRectForCanvas(x, y, width, height))
- return;
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- FloatRect rect(x, y, width, height);
- willDraw(rect);
- c->clearRect(rect);
-}
-
-void CanvasRenderingContext2D::fillRect(float x, float y, float width, float height)
-{
- if (!validateRectForCanvas(x, y, width, height))
- return;
-
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
-
- FloatRect rect(x, y, width, height);
- willDraw(rect);
-
- c->save();
- c->fillRect(rect);
- c->restore();
-}
-
-void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float height)
-{
- if (!validateRectForCanvas(x, y, width, height))
- return;
- strokeRect(x, y, width, height, state().m_lineWidth);
-}
-
-void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float height, float lineWidth)
-{
- if (!validateRectForCanvas(x, y, width, height))
- return;
-
- if (!(lineWidth >= 0))
- return;
-
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
-
- FloatRect rect(x, y, width, height);
-
- FloatRect boundingRect = rect;
- boundingRect.inflate(lineWidth / 2);
- willDraw(boundingRect);
-
- c->strokeRect(rect, lineWidth);
-}
-
-#if PLATFORM(CG)
-static inline CGSize adjustedShadowSize(CGFloat width, CGFloat height)
-{
- // Work around <rdar://problem/5539388> by ensuring that shadow offsets will get truncated
- // to the desired integer.
- static const CGFloat extraShadowOffset = narrowPrecisionToCGFloat(1.0 / 128);
- if (width > 0)
- width += extraShadowOffset;
- else if (width < 0)
- width -= extraShadowOffset;
-
- if (height > 0)
- height += extraShadowOffset;
- else if (height < 0)
- height -= extraShadowOffset;
-
- return CGSizeMake(width, height);
-}
-#endif
-
-void CanvasRenderingContext2D::setShadow(float width, float height, float blur)
-{
- state().m_shadowOffset = FloatSize(width, height);
- state().m_shadowBlur = blur;
- state().m_shadowColor = "";
- applyShadow();
-}
-
-void CanvasRenderingContext2D::setShadow(float width, float height, float blur, const String& color)
-{
- state().m_shadowOffset = FloatSize(width, height);
- state().m_shadowBlur = blur;
- state().m_shadowColor = color;
- applyShadow();
-}
-
-void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float grayLevel)
-{
- state().m_shadowOffset = FloatSize(width, height);
- state().m_shadowBlur = blur;
- state().m_shadowColor = "";
-
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- // FIXME: Do this through platform-independent GraphicsContext API.
-#if PLATFORM(CG)
- const CGFloat components[2] = { grayLevel, 1 };
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
- CGColorRef color = CGColorCreate(colorSpace, components);
- CGColorSpaceRelease(colorSpace);
- CGContextSetShadowWithColor(c->platformContext(), adjustedShadowSize(width, -height), blur, color);
- CGColorRelease(color);
-#endif
-}
-
-void CanvasRenderingContext2D::setShadow(float width, float height, float blur, const String& color, float alpha)
-{
- state().m_shadowOffset = FloatSize(width, height);
- state().m_shadowBlur = blur;
- state().m_shadowColor = color;
-
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- // FIXME: Do this through platform-independent GraphicsContext API.
-#if PLATFORM(CG)
- RGBA32 rgba = 0; // default is transparent black
- CSSParser::parseColor(rgba, color);
- const CGFloat components[4] = {
- ((rgba >> 16) & 0xFF) / 255.0f,
- ((rgba >> 8) & 0xFF) / 255.0f,
- (rgba & 0xFF) / 255.0f,
- alpha
- };
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- CGColorRef shadowColor = CGColorCreate(colorSpace, components);
- CGColorSpaceRelease(colorSpace);
- CGContextSetShadowWithColor(c->platformContext(), adjustedShadowSize(width, -height), blur, shadowColor);
- CGColorRelease(shadowColor);
-#endif
-}
-
-void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float grayLevel, float alpha)
-{
- state().m_shadowOffset = FloatSize(width, height);
- state().m_shadowBlur = blur;
- state().m_shadowColor = "";
-
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- // FIXME: Do this through platform-independent GraphicsContext API.
-#if PLATFORM(CG)
- const CGFloat components[2] = { grayLevel, alpha };
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
- CGColorRef color = CGColorCreate(colorSpace, components);
- CGColorSpaceRelease(colorSpace);
- CGContextSetShadowWithColor(c->platformContext(), adjustedShadowSize(width, -height), blur, color);
- CGColorRelease(color);
-#endif
-}
-
-void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float r, float g, float b, float a)
-{
- state().m_shadowOffset = FloatSize(width, height);
- state().m_shadowBlur = blur;
- state().m_shadowColor = "";
-
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- // FIXME: Do this through platform-independent GraphicsContext API.
-#if PLATFORM(CG)
- const CGFloat components[4] = { r, g, b, a };
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- CGColorRef shadowColor = CGColorCreate(colorSpace, components);
- CGColorSpaceRelease(colorSpace);
- CGContextSetShadowWithColor(c->platformContext(), adjustedShadowSize(width, -height), blur, shadowColor);
- CGColorRelease(shadowColor);
-#endif
-}
-
-void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float c, float m, float y, float k, float a)
-{
- state().m_shadowOffset = FloatSize(width, height);
- state().m_shadowBlur = blur;
- state().m_shadowColor = "";
-
- GraphicsContext* dc = drawingContext();
- if (!dc)
- return;
- // FIXME: Do this through platform-independent GraphicsContext API.
-#if PLATFORM(CG)
- const CGFloat components[5] = { c, m, y, k, a };
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceCMYK();
- CGColorRef shadowColor = CGColorCreate(colorSpace, components);
- CGColorSpaceRelease(colorSpace);
- CGContextSetShadowWithColor(dc->platformContext(), adjustedShadowSize(width, -height), blur, shadowColor);
- CGColorRelease(shadowColor);
-#endif
-}
-
-void CanvasRenderingContext2D::clearShadow()
-{
- state().m_shadowOffset = FloatSize();
- state().m_shadowBlur = 0;
- state().m_shadowColor = "";
- applyShadow();
-}
-
-void CanvasRenderingContext2D::applyShadow()
-{
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- // FIXME: Do this through platform-independent GraphicsContext API.
-#if PLATFORM(CG)
- RGBA32 rgba = 0; // default is transparent black
- if (!state().m_shadowColor.isEmpty())
- CSSParser::parseColor(rgba, state().m_shadowColor);
- const CGFloat components[4] = {
- ((rgba >> 16) & 0xFF) / 255.0f,
- ((rgba >> 8) & 0xFF) / 255.0f,
- (rgba & 0xFF) / 255.0f,
- ((rgba >> 24) & 0xFF) / 255.0f
- };
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- CGColorRef color = CGColorCreate(colorSpace, components);
- CGColorSpaceRelease(colorSpace);
-
- CGContextSetShadowWithColor(c->platformContext(), adjustedShadowSize(state().m_shadowOffset.width(), -state().m_shadowOffset.height()), state().m_shadowBlur, color);
- CGColorRelease(color);
-#endif
-}
-
-static IntSize size(HTMLImageElement* image)
-{
- if (CachedImage* cachedImage = image->cachedImage())
- return cachedImage->imageSize(1.0f); // FIXME: Not sure about this.
- return IntSize();
-}
-
-static inline FloatRect normalizeRect(const FloatRect& rect)
-{
- return FloatRect(min(rect.x(), rect.right()),
- min(rect.y(), rect.bottom()),
- max(rect.width(), -rect.width()),
- max(rect.height(), -rect.height()));
-}
-
-void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, float x, float y)
-{
- ASSERT(image);
- IntSize s = size(image);
- ExceptionCode ec;
- drawImage(image, x, y, s.width(), s.height(), ec);
-}
-
-void CanvasRenderingContext2D::drawImage(HTMLImageElement* image,
- float x, float y, float width, float height, ExceptionCode& ec)
-{
- ASSERT(image);
- IntSize s = size(image);
- drawImage(image, FloatRect(0, 0, s.width(), s.height()), FloatRect(x, y, width, height), ec);
-}
-
-void CanvasRenderingContext2D::checkOrigin(const KURL& url)
-{
- RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url);
- if (!m_canvas->document()->securityOrigin()->canAccess(origin.get()))
- m_canvas->setOriginTainted();
-}
-
-void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRect& srcRect, const FloatRect& dstRect,
- ExceptionCode& ec)
-{
- ASSERT(image);
-
- ec = 0;
-
- FloatRect imageRect = FloatRect(FloatPoint(), size(image));
- if (!imageRect.contains(normalizeRect(srcRect)) || srcRect.width() == 0 || srcRect.height() == 0) {
- ec = INDEX_SIZE_ERR;
- return;
- }
-
- if (!dstRect.width() || !dstRect.height())
- return;
-
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
-
- CachedImage* cachedImage = image->cachedImage();
- if (!cachedImage)
- return;
-
- if (m_canvas->originClean())
- checkOrigin(cachedImage->response().url());
-
- if (m_canvas->originClean() && !cachedImage->image()->hasSingleSecurityOrigin())
- m_canvas->setOriginTainted();
-
- FloatRect sourceRect = c->roundToDevicePixels(srcRect);
- FloatRect destRect = c->roundToDevicePixels(dstRect);
- willDraw(destRect);
- c->drawImage(cachedImage->image(), destRect, sourceRect, state().m_globalComposite);
-}
-
-void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* canvas, float x, float y)
-{
- ASSERT(canvas);
- ExceptionCode ec;
- drawImage(canvas, x, y, canvas->width(), canvas->height(), ec);
-}
-
-void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* canvas,
- float x, float y, float width, float height, ExceptionCode& ec)
-{
- ASSERT(canvas);
- drawImage(canvas, FloatRect(0, 0, canvas->width(), canvas->height()), FloatRect(x, y, width, height), ec);
-}
-
-void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* canvas, const FloatRect& srcRect,
- const FloatRect& dstRect, ExceptionCode& ec)
-{
- ASSERT(canvas);
-
- ec = 0;
-
- FloatRect srcCanvasRect = FloatRect(FloatPoint(), canvas->size());
- if (!srcCanvasRect.contains(normalizeRect(srcRect)) || srcRect.width() == 0 || srcRect.height() == 0) {
- ec = INDEX_SIZE_ERR;
- return;
- }
-
- if (!dstRect.width() || !dstRect.height())
- return;
-
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
-
- FloatRect sourceRect = c->roundToDevicePixels(srcRect);
- FloatRect destRect = c->roundToDevicePixels(dstRect);
-
- // FIXME: Do this through platform-independent GraphicsContext API.
- ImageBuffer* buffer = canvas->buffer();
- if (!buffer)
- return;
-
- if (!canvas->originClean())
- m_canvas->setOriginTainted();
-
- c->drawImage(buffer->image(), destRect, sourceRect, state().m_globalComposite);
- willDraw(destRect); // This call comes after drawImage, since the buffer we draw into may be our own, and we need to make sure it is dirty.
- // FIXME: Arguably willDraw should become didDraw and occur after drawing calls and not before them to avoid problems like this.
-}
-
-// FIXME: Why isn't this just another overload of drawImage? Why have a different name?
-void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image,
- float sx, float sy, float sw, float sh,
- float dx, float dy, float dw, float dh,
- const String& compositeOperation)
-{
- if (!image)
- return;
-
- CachedImage* cachedImage = image->cachedImage();
- if (!cachedImage)
- return;
-
- if (m_canvas->originClean())
- checkOrigin(cachedImage->response().url());
-
- if (m_canvas->originClean() && !cachedImage->image()->hasSingleSecurityOrigin())
- m_canvas->setOriginTainted();
-
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
-
- CompositeOperator op;
- if (!parseCompositeOperator(compositeOperation, op))
- op = CompositeSourceOver;
-
- FloatRect destRect = FloatRect(dx, dy, dw, dh);
- willDraw(destRect);
- c->drawImage(cachedImage->image(), destRect, FloatRect(sx, sy, sw, sh), op);
-}
-
-void CanvasRenderingContext2D::setAlpha(float alpha)
-{
- setGlobalAlpha(alpha);
-}
-
-void CanvasRenderingContext2D::setCompositeOperation(const String& operation)
-{
- setGlobalCompositeOperation(operation);
-}
-
-PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1)
-{
- return CanvasGradient::create(FloatPoint(x0, y0), FloatPoint(x1, y1));
-}
-
-PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1)
-{
- return CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1);
-}
-
-PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageElement* image,
- const String& repetitionType, ExceptionCode& ec)
-{
- bool repeatX, repeatY;
- ec = 0;
- CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, ec);
- if (ec)
- return 0;
-
- if (!image->complete()) {
- ec = INVALID_STATE_ERR;
- return 0;
- }
-
- CachedImage* cachedImage = image->cachedImage();
- if (!cachedImage || !image->cachedImage()->image())
- return CanvasPattern::create(Image::nullImage(), repeatX, repeatY, true);
-
- KURL url(cachedImage->url());
- RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url);
- bool originClean = m_canvas->document()->securityOrigin()->canAccess(origin.get());
- return CanvasPattern::create(cachedImage->image(), repeatX, repeatY, originClean);
-}
-
-PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLCanvasElement* canvas,
- const String& repetitionType, ExceptionCode& ec)
-{
- bool repeatX, repeatY;
- ec = 0;
- CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, ec);
- if (ec)
- return 0;
- return CanvasPattern::create(canvas->buffer()->image(), repeatX, repeatY, canvas->originClean());
-}
-
-void CanvasRenderingContext2D::willDraw(const FloatRect& r)
-{
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
-
- m_canvas->willDraw(c->getCTM().mapRect(r));
-}
-
-GraphicsContext* CanvasRenderingContext2D::drawingContext() const
-{
- return m_canvas->drawingContext();
-}
-
-static PassRefPtr<ImageData> createEmptyImageData(const IntSize& size)
-{
- PassRefPtr<ImageData> data = ImageData::create(size.width(), size.height());
- memset(data->data()->data().data(), 0, data->data()->length());
- return data;
-}
-
-PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float sh) const
-{
- FloatSize unscaledSize(sw, sh);
- IntSize scaledSize = m_canvas->convertLogicalToDevice(unscaledSize);
- if (scaledSize.width() < 1)
- scaledSize.setWidth(1);
- if (scaledSize.height() < 1)
- scaledSize.setHeight(1);
-
- return createEmptyImageData(scaledSize);
-}
-
-PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(float sx, float sy, float sw, float sh, ExceptionCode& ec) const
-{
- if (!m_canvas->originClean()) {
- ec = SECURITY_ERR;
- return 0;
- }
-
- FloatRect unscaledRect(sx, sy, sw, sh);
- IntRect scaledRect = m_canvas->convertLogicalToDevice(unscaledRect);
- if (scaledRect.width() < 1)
- scaledRect.setWidth(1);
- if (scaledRect.height() < 1)
- scaledRect.setHeight(1);
- ImageBuffer* buffer = m_canvas ? m_canvas->buffer() : 0;
- if (!buffer)
- return createEmptyImageData(scaledRect.size());
- return buffer->getImageData(scaledRect);
-}
-
-void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, ExceptionCode& ec)
-{
- if (!data) {
- ec = TYPE_MISMATCH_ERR;
- return;
- }
- putImageData(data, dx, dy, 0, 0, data->width(), data->height(), ec);
-}
-
-void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, float dirtyX, float dirtyY,
- float dirtyWidth, float dirtyHeight, ExceptionCode& ec)
-{
- if (!data) {
- ec = TYPE_MISMATCH_ERR;
- return;
- }
- if (!isfinite(dx) || !isfinite(dy) || !isfinite(dirtyX) ||
- !isfinite(dirtyY) || !isfinite(dirtyWidth) || !isfinite(dirtyHeight)) {
- ec = INDEX_SIZE_ERR;
- return;
- }
-
- ImageBuffer* buffer = m_canvas->buffer();
- if (!buffer)
- return;
-
- if (dirtyWidth < 0) {
- dirtyX += dirtyWidth;
- dirtyWidth = -dirtyWidth;
- }
-
- if (dirtyHeight < 0) {
- dirtyY += dirtyHeight;
- dirtyHeight = -dirtyHeight;
- }
-
- FloatRect clipRect(dirtyX, dirtyY, dirtyWidth, dirtyHeight);
- clipRect.intersect(IntRect(0, 0, data->width(), data->height()));
- IntSize destOffset(static_cast<int>(dx), static_cast<int>(dy));
- IntRect sourceRect = enclosingIntRect(clipRect);
- sourceRect.move(destOffset);
- sourceRect.intersect(IntRect(IntPoint(), buffer->size()));
- if (sourceRect.isEmpty())
- return;
- willDraw(sourceRect);
- sourceRect.move(-destOffset);
- IntPoint destPoint(destOffset.width(), destOffset.height());
-
- buffer->putImageData(data, sourceRect, destPoint);
-}
-
-String CanvasRenderingContext2D::font() const
-{
- return state().m_unparsedFont;
-}
-
-void CanvasRenderingContext2D::setFont(const String& newFont)
-{
- RefPtr<CSSMutableStyleDeclaration> tempDecl = CSSMutableStyleDeclaration::create();
- CSSParser parser(!m_canvas->document()->inCompatMode()); // Use the parse mode of the canvas' document when parsing CSS.
-
- String declarationText("font: ");
- declarationText += newFont;
- parser.parseDeclaration(tempDecl.get(), declarationText);
- if (!tempDecl->length())
- return;
-
- // The parse succeeded.
- state().m_unparsedFont = newFont;
-
- // Map the <canvas> font into the text style. If the font uses keywords like larger/smaller, these will work
- // relative to the canvas.
- RenderArena* arena = m_canvas->document()->renderArena();
- RenderStyle* newStyle = new (arena) RenderStyle();
- newStyle->ref();
- if (m_canvas->computedStyle())
- newStyle->setFontDescription(m_canvas->computedStyle()->fontDescription());
-
- // Now map the font property into the style.
- CSSStyleSelector* styleSelector = m_canvas->document()->styleSelector();
- styleSelector->applyPropertyToStyle(CSSPropertyFont, tempDecl->getPropertyCSSValue(CSSPropertyFont).get(), newStyle);
-
- state().m_font = newStyle->font();
- state().m_font.update(styleSelector->fontSelector());
- state().m_realizedFont = true;
-
- newStyle->deref(arena);
-
- // Set the font in the graphics context.
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
- c->setFont(state().m_font);
-}
-
-String CanvasRenderingContext2D::textAlign() const
-{
- return textAlignName(state().m_textAlign);
-}
-
-void CanvasRenderingContext2D::setTextAlign(const String& s)
-{
- TextAlign align;
- if (!parseTextAlign(s, align))
- return;
- state().m_textAlign = align;
-}
-
-String CanvasRenderingContext2D::textBaseline() const
-{
- return textBaselineName(state().m_textBaseline);
-}
-
-void CanvasRenderingContext2D::setTextBaseline(const String& s)
-{
- TextBaseline baseline;
- if (!parseTextBaseline(s, baseline))
- return;
- state().m_textBaseline = baseline;
-}
-
-void CanvasRenderingContext2D::fillText(const String& text, float x, float y)
-{
- drawTextInternal(text, x, y, true);
-}
-
-void CanvasRenderingContext2D::fillText(const String& text, float x, float y, float maxWidth)
-{
- drawTextInternal(text, x, y, true, maxWidth, true);
-}
-
-void CanvasRenderingContext2D::strokeText(const String& text, float x, float y)
-{
- drawTextInternal(text, x, y, false);
-}
-
-void CanvasRenderingContext2D::strokeText(const String& text, float x, float y, float maxWidth)
-{
- drawTextInternal(text, x, y, false, maxWidth, true);
-}
-
-PassRefPtr<TextMetrics> CanvasRenderingContext2D::measureText(const String& text)
-{
- RefPtr<TextMetrics> metrics = TextMetrics::create();
- metrics->setWidth(accessFont().width(TextRun(text.characters(), text.length())));
- return metrics;
-}
-
-void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, float y, bool fill, float maxWidth, bool useMaxWidth)
-{
- GraphicsContext* c = drawingContext();
- if (!c)
- return;
-
- const Font& font = accessFont();
-
- // FIXME: Handle maxWidth.
- // FIXME: Need to turn off font smoothing.
-
- bool rtl = m_canvas->computedStyle() ? m_canvas->computedStyle()->direction() == RTL : false;
- bool override = m_canvas->computedStyle() ? m_canvas->computedStyle()->unicodeBidi() == Override : false;
-
- unsigned length = text.length();
- const UChar* string = text.characters();
- TextRun textRun(string, length, 0, 0, 0, rtl, override, false, false);
-
- // Draw the item text at the correct point.
- FloatPoint location(x, y);
- switch (state().m_textBaseline) {
- case TopTextBaseline:
- case HangingTextBaseline:
- location.setY(y + font.ascent());
- break;
- case BottomTextBaseline:
- case IdeographicTextBaseline:
- location.setY(y - font.descent());
- break;
- case MiddleTextBaseline:
- location.setY(y - font.descent() + font.height() / 2);
- break;
- case AlphabeticTextBaseline:
- default:
- // Do nothing.
- break;
- }
-
- float width = font.width(TextRun(text, false, 0, 0, rtl, override));
-
- TextAlign align = state().m_textAlign;
- if (align == StartTextAlign)
- align = rtl ? RightTextAlign : LeftTextAlign;
- else if (align == EndTextAlign)
- align = rtl ? LeftTextAlign : RightTextAlign;
-
- switch (align) {
- case CenterTextAlign:
- location.setX(location.x() - width / 2);
- break;
- case RightTextAlign:
- location.setX(location.x() - width);
- break;
- default:
- break;
- }
-
- // The slop built in to this mask rect matches the heuristic used in FontCGWin.cpp for GDI text.
- FloatRect textRect = FloatRect(location.x() - font.height() / 2, location.y() - font.ascent() - font.lineGap(),
- width + font.height(), font.lineSpacing());
- if (!fill)
- textRect.inflate(c->strokeThickness() / 2);
-
- CanvasStyle* drawStyle = fill ? state().m_fillStyle.get() : state().m_strokeStyle.get();
- if (drawStyle->canvasGradient() || drawStyle->canvasPattern()) {
- IntRect maskRect = enclosingIntRect(textRect);
-
- auto_ptr<ImageBuffer> maskImage = ImageBuffer::create(maskRect.size(), false);
-
- GraphicsContext* maskImageContext = maskImage->context();
-
- if (fill)
- maskImageContext->setFillColor(Color::black);
- else {
- maskImageContext->setStrokeColor(Color::black);
- maskImageContext->setStrokeThickness(c->strokeThickness());
- }
-
- maskImageContext->setTextDrawingMode(fill ? cTextFill : cTextStroke);
- maskImageContext->translate(-maskRect.x(), -maskRect.y());
-
- maskImageContext->setFont(font);
- maskImageContext->drawBidiText(textRun, location);
-
- c->save();
- c->clipToImageBuffer(maskRect, maskImage.get());
- drawStyle->applyFillColor(c);
- c->fillRect(maskRect);
- c->restore();
-
- return;
- }
-
- c->setTextDrawingMode(fill ? cTextFill : cTextStroke);
- c->drawBidiText(textRun, location);
-}
-
-const Font& CanvasRenderingContext2D::accessFont()
-{
- if (!state().m_realizedFont)
- setFont(state().m_unparsedFont);
- return state().m_font;
-}
-
-} // namespace WebCore
diff --git a/webkit/pending/CanvasRenderingContext2D.h b/webkit/pending/CanvasRenderingContext2D.h
deleted file mode 100644
index dfed379..0000000
--- a/webkit/pending/CanvasRenderingContext2D.h
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CanvasRenderingContext2D_h
-#define CanvasRenderingContext2D_h
-
-#include "AffineTransform.h"
-#include "FloatSize.h"
-#include "Font.h"
-#include "GraphicsTypes.h"
-#include "Path.h"
-#include "PlatformString.h"
-#include <wtf/Vector.h>
-
-#if PLATFORM(CG)
-#include <ApplicationServices/ApplicationServices.h>
-#endif
-
-namespace WebCore {
-
- class CanvasGradient;
- class CanvasPattern;
- class CanvasStyle;
- class FloatRect;
- class GraphicsContext;
- class HTMLCanvasElement;
- class HTMLImageElement;
- class ImageData;
- class KURL;
- class TextMetrics;
-
- typedef int ExceptionCode;
-
- class CanvasRenderingContext2D :
-#if USE(V8)
- Peerable // Already has Noncopyable as a superclass.
-#else
- Noncopyable
-#endif
- {
- public:
- CanvasRenderingContext2D(HTMLCanvasElement*);
-
- void ref();
- void deref();
-
-#if USE(V8)
- virtual void setPeer(void* peer)
- {
- ASSERT(m_peer != peer);
- if (peer)
- ref();
- else
- deref();
- m_peer = peer;
-
- }
- virtual void* peer() const
- {
- return m_peer;
- }
-#endif
-
- HTMLCanvasElement* canvas() const { return m_canvas; }
-
- CanvasStyle* strokeStyle() const;
- void setStrokeStyle(PassRefPtr<CanvasStyle>);
-
- CanvasStyle* fillStyle() const;
- void setFillStyle(PassRefPtr<CanvasStyle>);
-
- float lineWidth() const;
- void setLineWidth(float);
-
- String lineCap() const;
- void setLineCap(const String&);
-
- String lineJoin() const;
- void setLineJoin(const String&);
-
- float miterLimit() const;
- void setMiterLimit(float);
-
- float shadowOffsetX() const;
- void setShadowOffsetX(float);
-
- float shadowOffsetY() const;
- void setShadowOffsetY(float);
-
- float shadowBlur() const;
- void setShadowBlur(float);
-
- String shadowColor() const;
- void setShadowColor(const String&);
-
- float globalAlpha() const;
- void setGlobalAlpha(float);
-
- String globalCompositeOperation() const;
- void setGlobalCompositeOperation(const String&);
-
- void save();
- void restore();
-
- void scale(float sx, float sy);
- void rotate(float angleInRadians);
- void translate(float tx, float ty);
- void transform(float m11, float m12, float m21, float m22, float dx, float dy);
-
- void setStrokeColor(const String& color);
- void setStrokeColor(float grayLevel);
- void setStrokeColor(const String& color, float alpha);
- void setStrokeColor(float grayLevel, float alpha);
- void setStrokeColor(float r, float g, float b, float a);
- void setStrokeColor(float c, float m, float y, float k, float a);
-
- void setFillColor(const String& color);
- void setFillColor(float grayLevel);
- void setFillColor(const String& color, float alpha);
- void setFillColor(float grayLevel, float alpha);
- void setFillColor(float r, float g, float b, float a);
- void setFillColor(float c, float m, float y, float k, float a);
-
- void beginPath();
- void closePath();
-
- void moveTo(float x, float y);
- void lineTo(float x, float y);
- void quadraticCurveTo(float cpx, float cpy, float x, float y);
- void bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y);
- void arcTo(float x0, float y0, float x1, float y1, float radius, ExceptionCode&);
- void arc(float x, float y, float r, float sa, float ea, bool clockwise, ExceptionCode&);
- void rect(float x, float y, float width, float height);
-
- void fill();
- void stroke();
- void clip();
-
- bool isPointInPath(const float x, const float y);
-
- void clearRect(float x, float y, float width, float height);
- void fillRect(float x, float y, float width, float height);
- void strokeRect(float x, float y, float width, float height);
- void strokeRect(float x, float y, float width, float height, float lineWidth);
-
- void setShadow(float width, float height, float blur);
- void setShadow(float width, float height, float blur, const String& color);
- void setShadow(float width, float height, float blur, float grayLevel);
- void setShadow(float width, float height, float blur, const String& color, float alpha);
- void setShadow(float width, float height, float blur, float grayLevel, float alpha);
- void setShadow(float width, float height, float blur, float r, float g, float b, float a);
- void setShadow(float width, float height, float blur, float c, float m, float y, float k, float a);
-
- void clearShadow();
-
- void drawImage(HTMLImageElement*, float x, float y);
- void drawImage(HTMLImageElement*, float x, float y, float width, float height, ExceptionCode&);
- void drawImage(HTMLImageElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode&);
- void drawImage(HTMLCanvasElement*, float x, float y);
- void drawImage(HTMLCanvasElement*, float x, float y, float width, float height, ExceptionCode&);
- void drawImage(HTMLCanvasElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode&);
-
- void drawImageFromRect(HTMLImageElement*, float sx, float sy, float sw, float sh,
- float dx, float dy, float dw, float dh, const String& compositeOperation);
-
- void setAlpha(float);
-
- void setCompositeOperation(const String&);
-
- PassRefPtr<CanvasGradient> createLinearGradient(float x0, float y0, float x1, float y1);
- PassRefPtr<CanvasGradient> createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1);
- PassRefPtr<CanvasPattern> createPattern(HTMLImageElement*, const String& repetitionType, ExceptionCode&);
- PassRefPtr<CanvasPattern> createPattern(HTMLCanvasElement*, const String& repetitionType, ExceptionCode&);
-
- PassRefPtr<ImageData> createImageData(float width, float height) const;
- PassRefPtr<ImageData> getImageData(float sx, float sy, float sw, float sh, ExceptionCode&) const;
- void putImageData(ImageData*, float dx, float dy, ExceptionCode&);
- void putImageData(ImageData*, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionCode&);
-
- void reset();
-
- String font() const;
- void setFont(const String&);
-
- String textAlign() const;
- void setTextAlign(const String&);
-
- String textBaseline() const;
- void setTextBaseline(const String&);
-
- void fillText(const String& text, float x, float y);
- void fillText(const String& text, float x, float y, float maxWidth);
- void strokeText(const String& text, float x, float y);
- void strokeText(const String& text, float x, float y, float maxWidth);
- PassRefPtr<TextMetrics> measureText(const String& text);
-
- private:
- struct State {
- State();
-
- RefPtr<CanvasStyle> m_strokeStyle;
- RefPtr<CanvasStyle> m_fillStyle;
- float m_lineWidth;
- LineCap m_lineCap;
- LineJoin m_lineJoin;
- float m_miterLimit;
- FloatSize m_shadowOffset;
- float m_shadowBlur;
- String m_shadowColor;
- float m_globalAlpha;
- CompositeOperator m_globalComposite;
- AffineTransform m_transform;
-
- // Text state.
- TextAlign m_textAlign;
- TextBaseline m_textBaseline;
-
- String m_unparsedFont;
- Font m_font;
- bool m_realizedFont;
- };
- Path m_path;
-
- State& state() { return m_stateStack.last(); }
- const State& state() const { return m_stateStack.last(); }
-
- void applyShadow();
-
- void willDraw(const FloatRect&);
-
- GraphicsContext* drawingContext() const;
-
- void applyStrokePattern();
- void applyFillPattern();
-
- void drawTextInternal(const String& text, float x, float y, bool fill, float maxWidth = 0, bool useMaxWidth = false);
-
- const Font& accessFont();
-
-#if ENABLE(DASHBOARD_SUPPORT)
- void clearPathForDashboardBackwardCompatibilityMode();
-#endif
-
- void checkOrigin(const KURL&);
-
- HTMLCanvasElement* m_canvas;
- Vector<State, 1> m_stateStack;
-#if USE(V8)
- void* m_peer;
-#endif
- };
-
-} // namespace WebCore
-
-#endif
diff --git a/webkit/pending/CanvasRenderingContext2D.idl b/webkit/pending/CanvasRenderingContext2D.idl
deleted file mode 100644
index e1e1e06..0000000
--- a/webkit/pending/CanvasRenderingContext2D.idl
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-module html {
-
- interface [
- GenerateConstructor,
- InterfaceUUID=98fb48ae-7216-489c-862b-8e1217fc4443,
- ImplementationUUID=ab4f0781-152f-450e-9546-5b3987491a54
- ] CanvasRenderingContext2D {
-
- // Web Applications 1.0 draft
-
- readonly attribute HTMLCanvasElement canvas;
-
- void save();
- void restore();
-
- void scale(in float sx, in float sy);
- void rotate(in float angle);
- void translate(in float tx, in float ty);
- void transform(in float m11, in float m12, in float m21, in float m22, in float dx, in float dy);
-
- attribute float globalAlpha;
- attribute [ConvertNullToNullString] DOMString globalCompositeOperation;
-
- CanvasGradient createLinearGradient(in float x0, in float y0, in float x1, in float y1);
- CanvasGradient createRadialGradient(in float x0, in float y0, in float r0, in float x1, in float y1, in float r1);
-
- attribute float lineWidth;
- attribute [ConvertNullToNullString] DOMString lineCap;
- attribute [ConvertNullToNullString] DOMString lineJoin;
- attribute float miterLimit;
-
- attribute float shadowOffsetX;
- attribute float shadowOffsetY;
- attribute float shadowBlur;
- attribute [ConvertNullToNullString] DOMString shadowColor;
-
- void clearRect(in float x, in float y, in float width, in float height);
- void fillRect(in float x, in float y, in float width, in float height);
-
- void beginPath();
- void closePath();
- void moveTo(in float x, in float y);
- void lineTo(in float x, in float y);
- void quadraticCurveTo(in float cpx, in float cpy, in float x, in float y);
- void bezierCurveTo(in float cp1x, in float cp1y, in float cp2x, in float cp2y, in float x, in float y);
- void arcTo(in float x1, in float y1, in float x2, in float y2, in float radius)
- raises (DOMException);
- void rect(in float x, in float y, in float width, in float height);
- void arc(in float x, in float y, in float radius, in float startAngle, in float endAngle, in boolean anticlockwise)
- raises (DOMException);
- void fill();
- void stroke();
- void clip();
- boolean isPointInPath(in float x, in float y);
-
- // text
- attribute DOMString font;
- attribute DOMString textAlign;
- attribute DOMString textBaseline;
- [Custom] void fillText(/* 4 */);
- [Custom] void strokeText(/* 4 */);
- TextMetrics measureText(in DOMString text);
-
- // other
-
- void setAlpha(in float alpha);
- void setCompositeOperation(in DOMString compositeOperation);
-
- void setLineWidth(in float width);
- void setLineCap(in DOMString cap);
- void setLineJoin(in DOMString join);
- void setMiterLimit(in float limit);
-
- void clearShadow();
-
- [Custom] void setStrokeColor(/* 1 */);
- [Custom] void setFillColor(/* 1 */);
- [Custom] void strokeRect(/* 4 */);
- [Custom] void drawImage(/* 3 */);
- [Custom] void drawImageFromRect(/* 10 */);
- [Custom] void setShadow(/* 3 */);
- [Custom] void createPattern(/* 2 */);
-
- attribute [Custom] custom strokeStyle;
- attribute [Custom] custom fillStyle;
-
- // pixel manipulation
- ImageData createImageData(in float sw, in float sh);
- ImageData getImageData(in float sx, in float sy, in float sw, in float sh)
- raises(DOMException);
- [Custom] void putImageData(/* in ImageData imagedata, in float dx, in float dy [, in float dirtyX, in float dirtyY, in float dirtyWidth, in float dirtyHeight] */);
- };
-
-}
-
diff --git a/webkit/pending/CompositeAnimation.h b/webkit/pending/CompositeAnimation.h
deleted file mode 100644
index bd7523a..0000000
--- a/webkit/pending/CompositeAnimation.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CompositeAnimation_h
-#define CompositeAnimation_h
-
-#include "AtomicString.h"
-
-#include <wtf/HashMap.h>
-#include <wtf/Noncopyable.h>
-
-namespace WebCore {
-
-class AnimationController;
-class RenderStyle;
-class RenderObject;
-class KeyframeAnimation;
-class ImplicitAnimation;
-
-// A CompositeAnimation represents a collection of animations that are running
-// on a single RenderObject, such as a number of properties transitioning at once.
-class CompositeAnimation : public Noncopyable {
-public:
- CompositeAnimation(AnimationController* animationController)
- : m_suspended(false)
- , m_animationController(animationController)
- , m_numStyleAvailableWaiters(0)
- { }
-
- ~CompositeAnimation();
-
- RenderStyle* animate(RenderObject*, const RenderStyle* currentStyle, RenderStyle* targetStyle);
-
- void setAnimating(bool inAnimating);
- bool animating();
-
- bool hasAnimationForProperty(int prop) const { return m_transitions.contains(prop); }
-
- void resetTransitions(RenderObject*);
- void resetAnimations(RenderObject*);
-
- void cleanupFinishedAnimations(RenderObject*);
-
- void setAnimationStartTime(double t);
- void setTransitionStartTime(int property, double t);
-
- void suspendAnimations();
- void resumeAnimations();
- bool suspended() const { return m_suspended; }
-
- void overrideImplicitAnimations(int property);
- void resumeOverriddenImplicitAnimations(int property);
-
- void styleAvailable();
-
- bool isAnimatingProperty(int property, bool isRunningNow) const;
-
- void setWaitingForStyleAvailable(bool waiting);
-
-protected:
- void updateTransitions(RenderObject* renderer, const RenderStyle* currentStyle, RenderStyle* targetStyle);
- void updateKeyframeAnimations(RenderObject* renderer, const RenderStyle* currentStyle, RenderStyle* targetStyle);
-
- KeyframeAnimation* findKeyframeAnimation(const AtomicString& name);
-
-private:
- typedef HashMap<int, ImplicitAnimation*> CSSPropertyTransitionsMap;
- typedef HashMap<AtomicStringImpl*, KeyframeAnimation*> AnimationNameMap;
-
- CSSPropertyTransitionsMap m_transitions;
- AnimationNameMap m_keyframeAnimations;
- bool m_suspended;
- AnimationController* m_animationController;
- uint32_t m_numStyleAvailableWaiters;
-};
-
-}
-
-#endif
diff --git a/webkit/pending/DOMWindow.cpp b/webkit/pending/DOMWindow.cpp
deleted file mode 100644
index fc802c8..0000000
--- a/webkit/pending/DOMWindow.cpp
+++ /dev/null
@@ -1,1192 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "DOMWindow.h"
-
-#include "BarInfo.h"
-#include "CSSComputedStyleDeclaration.h"
-#include "CSSRuleList.h"
-#include "CSSStyleSelector.h"
-#include "CString.h"
-#include "Chrome.h"
-#include "Console.h"
-#include "DOMSelection.h"
-#include "Document.h"
-#include "Element.h"
-#include "ExceptionCode.h"
-#include "FloatRect.h"
-#include "Frame.h"
-#include "FrameLoader.h"
-#include "FrameTree.h"
-#include "FrameView.h"
-#include "HTMLFrameOwnerElement.h"
-#include "History.h"
-#include "Location.h"
-#include "MessageEvent.h"
-#include "Navigator.h"
-#include "Page.h"
-#include "PageGroup.h"
-#include "PlatformScreen.h"
-#include "PlatformString.h"
-#include "Screen.h"
-#include "SecurityOrigin.h"
-#include "Settings.h"
-#include "ScriptController.h"
-#include <algorithm>
-#include <wtf/MathExtras.h>
-
-#if ENABLE(DATABASE)
-#include "Database.h"
-#endif
-
-#if ENABLE(DOM_STORAGE)
-#include "LocalStorage.h"
-#include "SessionStorage.h"
-#include "Storage.h"
-#include "StorageArea.h"
-#endif
-
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
-#include "DOMApplicationCache.h"
-#endif
-
-using std::min;
-using std::max;
-
-#if USE(V8)
-#include "Location.h"
-#include "Navigator.h"
-#include "CString.h"
-#include "FloatRect.h"
-#include "FrameTree.h"
-#include "FrameView.h"
-#include "Page.h"
-#include "Chrome.h"
-#include "WindowFeatures.h"
-#include "FrameLoadRequest.h"
-#include "ScheduledAction.h"
-#include "PausedTimeouts.h"
-#include "v8_proxy.h"
-
-#if PLATFORM(WIN)
-#include <windows.h>
-#endif // WIN
-
-#include "CSSHelper.h" // parseURL
-#endif // V8
-
-
-namespace WebCore {
-
-class PostMessageTimer : public TimerBase {
-public:
- PostMessageTimer(DOMWindow* window, PassRefPtr<MessageEvent> event, SecurityOrigin* targetOrigin)
- : m_window(window)
- , m_event(event)
- , m_targetOrigin(targetOrigin)
- {
- }
-
- MessageEvent* event() const { return m_event.get(); }
- SecurityOrigin* targetOrigin() const { return m_targetOrigin.get(); }
-
-private:
- virtual void fired()
- {
- m_window->postMessageTimerFired(this);
- }
-
- RefPtr<DOMWindow> m_window;
- RefPtr<MessageEvent> m_event;
- RefPtr<SecurityOrigin> m_targetOrigin;
-};
-
-// This function:
-// 1) Validates the pending changes are not changing to NaN
-// 2) Constrains the window rect to no smaller than 100 in each dimension and no
-// bigger than the the float rect's dimensions.
-// 3) Constrain window rect to within the top and left boundaries of the screen rect
-// 4) Constraint the window rect to within the bottom and right boundaries of the
-// screen rect.
-// 5) Translate the window rect coordinates to be within the coordinate space of
-// the screen rect.
-void DOMWindow::adjustWindowRect(const FloatRect& screen, FloatRect& window, const FloatRect& pendingChanges)
-{
- // Make sure we're in a valid state before adjusting dimensions.
- ASSERT(isfinite(screen.x()));
- ASSERT(isfinite(screen.y()));
- ASSERT(isfinite(screen.width()));
- ASSERT(isfinite(screen.height()));
- ASSERT(isfinite(window.x()));
- ASSERT(isfinite(window.y()));
- ASSERT(isfinite(window.width()));
- ASSERT(isfinite(window.height()));
-
- // Update window values if new requested values are not NaN.
- if (!isnan(pendingChanges.x()))
- window.setX(pendingChanges.x());
- if (!isnan(pendingChanges.y()))
- window.setY(pendingChanges.y());
- if (!isnan(pendingChanges.width()))
- window.setWidth(pendingChanges.width());
- if (!isnan(pendingChanges.height()))
- window.setHeight(pendingChanges.height());
-
- // Resize the window to between 100 and the screen width and height.
- window.setWidth(min(max(100.0f, window.width()), screen.width()));
- window.setHeight(min(max(100.0f, window.height()), screen.height()));
-
- // Constrain the window position to the screen.
- window.setX(max(screen.x(), min(window.x(), screen.right() - window.width())));
- window.setY(max(screen.y(), min(window.y(), screen.bottom() - window.height())));
-}
-
-#if USE(V8)
-
-static int lastUsedTimeoutId;
-static int timerNestingLevel = 0;
-const int kMaxTimerNestingLevel = 5;
-const double kMinimumTimerInterval = 0.001; // Change this to speed up Javascript's setTimeout!
-
-class DOMWindowTimer : public TimerBase {
-public:
- DOMWindowTimer(int timeoutId, int nestingLevel,
- DOMWindow* o, ScheduledAction* a)
- : m_timeoutId(timeoutId), m_nestingLevel(nestingLevel),
- m_object(o), m_action(a) { }
-
- virtual ~DOMWindowTimer() { delete m_action; }
-
- int timeoutId() const { return m_timeoutId; }
-
- int nestingLevel() const { return m_nestingLevel; }
- void setNestingLevel(int n) { m_nestingLevel = n; }
-
- ScheduledAction* action() const { return m_action; }
- ScheduledAction* takeAction() { ScheduledAction* a = m_action; m_action = 0; return a; }
-
-private:
- virtual void fired();
-
- int m_timeoutId;
- int m_nestingLevel;
- DOMWindow* m_object;
- ScheduledAction* m_action;
-};
-
-void DOMWindowTimer::fired() {
- timerNestingLevel = m_nestingLevel;
- m_object->timerFired(this);
- timerNestingLevel = 0;
-}
-
-#endif // V8
-
-
-DOMWindow::DOMWindow(Frame* frame)
- : m_frame(frame)
-{
-}
-
-DOMWindow::~DOMWindow()
-{
- if (m_frame)
- m_frame->clearFormerDOMWindow(this);
-}
-
-void DOMWindow::disconnectFrame()
-{
- m_frame = 0;
- clear();
-}
-
-void DOMWindow::clear()
-{
- if (m_screen)
- m_screen->disconnectFrame();
- m_screen = 0;
-
- if (m_selection)
- m_selection->disconnectFrame();
- m_selection = 0;
-
- if (m_history)
- m_history->disconnectFrame();
- m_history = 0;
-
- if (m_locationbar)
- m_locationbar->disconnectFrame();
- m_locationbar = 0;
-
- if (m_menubar)
- m_menubar->disconnectFrame();
- m_menubar = 0;
-
- if (m_personalbar)
- m_personalbar->disconnectFrame();
- m_personalbar = 0;
-
- if (m_scrollbars)
- m_scrollbars->disconnectFrame();
- m_scrollbars = 0;
-
- if (m_statusbar)
- m_statusbar->disconnectFrame();
- m_statusbar = 0;
-
- if (m_toolbar)
- m_toolbar->disconnectFrame();
- m_toolbar = 0;
-
- if (m_console)
- m_console->disconnectFrame();
- m_console = 0;
-
- if (m_navigator)
- m_navigator->disconnectFrame();
- m_navigator = 0;
-
- if (m_location)
- m_location->disconnectFrame();
- m_location = 0;
-
-#if ENABLE(DOM_STORAGE)
- if (m_sessionStorage)
- m_sessionStorage->disconnectFrame();
- m_sessionStorage = 0;
-
- if (m_localStorage)
- m_localStorage->disconnectFrame();
- m_localStorage = 0;
-#endif
-
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- if (m_applicationCache)
- m_applicationCache->disconnectFrame();
- m_applicationCache = 0;
-#endif
-}
-
-Screen* DOMWindow::screen() const
-{
- if (!m_screen)
- m_screen = Screen::create(m_frame);
- return m_screen.get();
-}
-
-History* DOMWindow::history() const
-{
- if (!m_history)
- m_history = History::create(m_frame);
- return m_history.get();
-}
-
-BarInfo* DOMWindow::locationbar() const
-{
- if (!m_locationbar)
- m_locationbar = BarInfo::create(m_frame, BarInfo::Locationbar);
- return m_locationbar.get();
-}
-
-BarInfo* DOMWindow::menubar() const
-{
- if (!m_menubar)
- m_menubar = BarInfo::create(m_frame, BarInfo::Menubar);
- return m_menubar.get();
-}
-
-BarInfo* DOMWindow::personalbar() const
-{
- if (!m_personalbar)
- m_personalbar = BarInfo::create(m_frame, BarInfo::Personalbar);
- return m_personalbar.get();
-}
-
-BarInfo* DOMWindow::scrollbars() const
-{
- if (!m_scrollbars)
- m_scrollbars = BarInfo::create(m_frame, BarInfo::Scrollbars);
- return m_scrollbars.get();
-}
-
-BarInfo* DOMWindow::statusbar() const
-{
- if (!m_statusbar)
- m_statusbar = BarInfo::create(m_frame, BarInfo::Statusbar);
- return m_statusbar.get();
-}
-
-BarInfo* DOMWindow::toolbar() const
-{
- if (!m_toolbar)
- m_toolbar = BarInfo::create(m_frame, BarInfo::Toolbar);
- return m_toolbar.get();
-}
-
-Console* DOMWindow::console() const
-{
- if (!m_console)
- m_console = Console::create(m_frame);
- return m_console.get();
-}
-
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
-DOMApplicationCache* DOMWindow::applicationCache() const
-{
- if (!m_applicationCache)
- m_applicationCache = DOMApplicationCache::create(m_frame);
- return m_applicationCache.get();
-}
-#endif
-
-Navigator* DOMWindow::navigator() const
-{
- if (!m_navigator)
- m_navigator = Navigator::create(m_frame);
- return m_navigator.get();
-}
-
-Location* DOMWindow::location() const
-{
- if (!m_location)
- m_location = Location::create(m_frame);
- return m_location.get();
-}
-
-#if ENABLE(DOM_STORAGE)
-Storage* DOMWindow::sessionStorage() const
-{
- if (m_sessionStorage)
- return m_sessionStorage.get();
-
- Page* page = m_frame->page();
- if (!page)
- return 0;
-
- Document* document = m_frame->document();
- if (!document)
- return 0;
-
- RefPtr<StorageArea> storageArea = page->sessionStorage()->storageArea(document->securityOrigin());
- m_sessionStorage = Storage::create(m_frame, storageArea.release());
- return m_sessionStorage.get();
-}
-
-Storage* DOMWindow::localStorage() const
-{
- Document* document = this->document();
- if (!document)
- return 0;
-
- Page* page = document->page();
- if (!page)
- return 0;
-
- LocalStorage* localStorage = page->group().localStorage();
- RefPtr<StorageArea> storageArea = localStorage ? localStorage->storageArea(m_frame, document->securityOrigin()) : 0;
- if (storageArea)
- m_localStorage = Storage::create(m_frame, storageArea.release());
-
- return m_localStorage.get();
-}
-#endif
-
-void DOMWindow::postMessage(const String& message, const String& targetOrigin, DOMWindow* source, ExceptionCode& ec)
-{
- if (!m_frame)
- return;
-
- // Compute the target origin. We need to do this synchronously in order
- // to generate the SYNTAX_ERR exception correctly.
- RefPtr<SecurityOrigin> target;
- if (targetOrigin != "*") {
- target = SecurityOrigin::create(KURL(targetOrigin));
- if (target->isEmpty()) {
- ec = SYNTAX_ERR;
- return;
- }
- }
-
- // Capture the source of the message. We need to do this synchronously
- // in order to capture the source of the message correctly.
- Document* sourceDocument = source->document();
- if (!sourceDocument)
- return;
- String sourceOrigin = sourceDocument->securityOrigin()->toString();
-
- // Schedule the message.
- PostMessageTimer* timer = new PostMessageTimer(this, MessageEvent::create(message, sourceOrigin, "", source), target.get());
- timer->startOneShot(0);
-}
-
-void DOMWindow::postMessageTimerFired(PostMessageTimer* t)
-{
- OwnPtr<PostMessageTimer> timer(t);
-
- if (!document())
- return;
-
- if (timer->targetOrigin()) {
- // Check target origin now since the target document may have changed since the simer was scheduled.
- if (!timer->targetOrigin()->isSameSchemeHostPort(document()->securityOrigin())) {
- String message = String::format("Unable to post message to %s. Recipient has origin %s.\n",
- timer->targetOrigin()->toString().utf8().data(), document()->securityOrigin()->toString().utf8().data());
- console()->addMessage(JSMessageSource, ErrorMessageLevel, message, 0, String());
- return;
- }
- }
-
- document()->dispatchWindowEvent(timer->event());
-}
-
-DOMSelection* DOMWindow::getSelection()
-{
- if (!m_selection)
- m_selection = DOMSelection::create(m_frame);
- return m_selection.get();
-}
-
-Element* DOMWindow::frameElement() const
-{
- if (!m_frame)
- return 0;
-
- return m_frame->ownerElement();
-}
-
-void DOMWindow::focus()
-{
- if (!m_frame)
- return;
-
- m_frame->focusWindow();
-}
-
-void DOMWindow::blur()
-{
- if (!m_frame)
- return;
-
- m_frame->unfocusWindow();
-}
-
-void DOMWindow::close()
-{
- if (!m_frame)
- return;
-
- Settings* settings = m_frame->settings();
- bool allow_scripts_to_close_windows =
- (settings && settings->allowScriptsToCloseWindows());
-
- if (m_frame->loader()->openedByDOM()
- || m_frame->loader()->getHistoryLength() <= 1
- || allow_scripts_to_close_windows)
- m_frame->scheduleClose();
-}
-
-void DOMWindow::print()
-{
- if (!m_frame)
- return;
-
- Page* page = m_frame->page();
- if (!page)
- return;
-
- page->chrome()->print(m_frame);
-}
-
-void DOMWindow::stop()
-{
- if (!m_frame)
- return;
-
- // Ignores stop() in unload event handlers
- if (m_frame->loader()->firingUnloadEvents())
- return;
-
- // We must check whether the load is complete asynchronously,
- // because we might still be parsing the document until the
- // callstack unwinds.
- m_frame->loader()->stopForUserCancel(true);
-}
-
-void DOMWindow::alert(const String& message)
-{
-#if USE(V8)
- // Before showing the JavaScript dialog, we give
- // the proxy implementation a chance to process any
- // pending console messages.
- V8Proxy::ProcessConsoleMessages();
-#endif
-
- if (!m_frame)
- return;
-
- Document* doc = m_frame->document();
- ASSERT(doc);
- if (doc)
- doc->updateRendering();
-
- Page* page = m_frame->page();
- if (!page)
- return;
-
- page->chrome()->runJavaScriptAlert(m_frame, message);
-}
-
-bool DOMWindow::confirm(const String& message)
-{
-#if USE(V8)
- // Before showing the JavaScript dialog, we give
- // the proxy implementation a chance to process any
- // pending console messages.
- V8Proxy::ProcessConsoleMessages();
-#endif
-
- if (!m_frame)
- return false;
-
- Document* doc = m_frame->document();
- ASSERT(doc);
- if (doc)
- doc->updateRendering();
-
- Page* page = m_frame->page();
- if (!page)
- return false;
-
- return page->chrome()->runJavaScriptConfirm(m_frame, message);
-}
-
-String DOMWindow::prompt(const String& message, const String& defaultValue)
-{
-#if USE(V8)
- // Before showing the JavaScript dialog, we give
- // the proxy implementation a chance to process any
- // pending console messages.
- V8Proxy::ProcessConsoleMessages();
-#endif
-
- if (!m_frame)
- return String();
-
- Document* doc = m_frame->document();
- ASSERT(doc);
- if (doc)
- doc->updateRendering();
-
- Page* page = m_frame->page();
- if (!page)
- return String();
-
- String returnValue;
- if (page->chrome()->runJavaScriptPrompt(m_frame, message, defaultValue, returnValue))
- return returnValue;
-
- return String();
-}
-
-bool DOMWindow::find(const String& string, bool caseSensitive, bool backwards, bool wrap, bool wholeWord, bool searchInFrames, bool showDialog) const
-{
- if (!m_frame)
- return false;
-
- // FIXME (13016): Support wholeWord, searchInFrames and showDialog
- return m_frame->findString(string, !backwards, caseSensitive, wrap, false);
-}
-
-bool DOMWindow::offscreenBuffering() const
-{
- return true;
-}
-
-int DOMWindow::outerHeight() const
-{
- if (!m_frame)
- return 0;
-
- Page* page = m_frame->page();
- if (!page)
- return 0;
-
- return static_cast<int>(page->chrome()->windowRect().height());
-}
-
-int DOMWindow::outerWidth() const
-{
- if (!m_frame)
- return 0;
-
- Page* page = m_frame->page();
- if (!page)
- return 0;
-
- return static_cast<int>(page->chrome()->windowRect().width());
-}
-
-int DOMWindow::innerHeight() const
-{
- if (!m_frame)
- return 0;
-
- FrameView* view = m_frame->view();
- if (!view)
- return 0;
-
- return static_cast<int>(view->height() / m_frame->pageZoomFactor());
-}
-
-int DOMWindow::innerWidth() const
-{
- if (!m_frame)
- return 0;
-
- FrameView* view = m_frame->view();
- if (!view)
- return 0;
-
- return static_cast<int>(view->width() / m_frame->pageZoomFactor());
-}
-
-int DOMWindow::screenX() const
-{
- if (!m_frame)
- return 0;
-
- Page* page = m_frame->page();
- if (!page)
- return 0;
-
- return static_cast<int>(page->chrome()->windowRect().x());
-}
-
-int DOMWindow::screenY() const
-{
- if (!m_frame)
- return 0;
-
- Page* page = m_frame->page();
- if (!page)
- return 0;
-
- return static_cast<int>(page->chrome()->windowRect().y());
-}
-
-int DOMWindow::scrollX() const
-{
- if (!m_frame)
- return 0;
-
- FrameView* view = m_frame->view();
- if (!view)
- return 0;
-
- Document* doc = m_frame->document();
- ASSERT(doc);
- if (doc)
- doc->updateLayoutIgnorePendingStylesheets();
-
- return static_cast<int>(view->contentsX() / m_frame->pageZoomFactor());
-}
-
-int DOMWindow::scrollY() const
-{
- if (!m_frame)
- return 0;
-
- FrameView* view = m_frame->view();
- if (!view)
- return 0;
-
- Document* doc = m_frame->document();
- ASSERT(doc);
- if (doc)
- doc->updateLayoutIgnorePendingStylesheets();
-
- return static_cast<int>(view->contentsY() / m_frame->pageZoomFactor());
-}
-
-bool DOMWindow::closed() const
-{
- return !m_frame;
-}
-
-unsigned DOMWindow::length() const
-{
- if (!m_frame)
- return 0;
-
- return m_frame->tree()->childCount();
-}
-
-String DOMWindow::name() const
-{
- if (!m_frame)
- return String();
-
- return m_frame->tree()->name();
-}
-
-void DOMWindow::setName(const String& string)
-{
- if (!m_frame)
- return;
-
- m_frame->tree()->setName(string);
-}
-
-String DOMWindow::status() const
-{
- if (!m_frame)
- return String();
-
- return m_frame->jsStatusBarText();
-}
-
-void DOMWindow::setStatus(const String& string)
-{
- if (!m_frame)
- return;
-
- m_frame->setJSStatusBarText(string);
-}
-
-String DOMWindow::defaultStatus() const
-{
- if (!m_frame)
- return String();
-
- return m_frame->jsDefaultStatusBarText();
-}
-
-void DOMWindow::setDefaultStatus(const String& string)
-{
- if (!m_frame)
- return;
-
- m_frame->setJSDefaultStatusBarText(string);
-}
-
-DOMWindow* DOMWindow::self() const
-{
- if (!m_frame)
- return 0;
-
- return m_frame->domWindow();
-}
-
-DOMWindow* DOMWindow::opener() const
-{
- if (!m_frame)
- return 0;
-
- Frame* opener = m_frame->loader()->opener();
- if (!opener)
- return 0;
-
- return opener->domWindow();
-}
-
-DOMWindow* DOMWindow::parent() const
-{
- if (!m_frame)
- return 0;
-
- Frame* parent = m_frame->tree()->parent(true);
- if (parent)
- return parent->domWindow();
-
- return m_frame->domWindow();
-}
-
-DOMWindow* DOMWindow::top() const
-{
- if (!m_frame)
- return 0;
-
- Page* page = m_frame->page();
- if (!page)
- return 0;
-
- return m_frame->tree()->top(true)->domWindow();
-}
-
-Document* DOMWindow::document() const
-{
- if (!m_frame)
- return 0;
-
- ASSERT(m_frame->document());
- return m_frame->document();
-}
-
-PassRefPtr<CSSStyleDeclaration> DOMWindow::getComputedStyle(Element* elt, const String&) const
-{
- if (!elt)
- return 0;
-
- // FIXME: This needs take pseudo elements into account.
- return computedStyle(elt);
-}
-
-PassRefPtr<CSSRuleList> DOMWindow::getMatchedCSSRules(Element* elt, const String& pseudoElt, bool authorOnly) const
-{
- if (!m_frame)
- return 0;
-
- Document* doc = m_frame->document();
- ASSERT(doc);
- if (!doc)
- return 0;
-
- if (!pseudoElt.isEmpty())
- return doc->styleSelector()->pseudoStyleRulesForElement(elt, pseudoElt, authorOnly);
- return doc->styleSelector()->styleRulesForElement(elt, authorOnly);
-}
-
-double DOMWindow::devicePixelRatio() const
-{
- if (!m_frame)
- return 0.0;
-
- Page* page = m_frame->page();
- if (!page)
- return 0.0;
-
- return page->chrome()->scaleFactor();
-}
-
-#if USE(V8)
-
-static void setWindowFeature(const String& keyString, const String& valueString, WindowFeatures& windowFeatures) {
- int value;
-
- if (valueString.length() == 0 || // listing a key with no value is shorthand for key=yes
- valueString == "yes")
- value = 1;
- else
- value = valueString.toInt();
-
- if (keyString == "left" || keyString == "screenx") {
- windowFeatures.xSet = true;
- windowFeatures.x = value;
- } else if (keyString == "top" || keyString == "screeny") {
- windowFeatures.ySet = true;
- windowFeatures.y = value;
- } else if (keyString == "width" || keyString == "innerwidth") {
- windowFeatures.widthSet = true;
- windowFeatures.width = value;
- } else if (keyString == "height" || keyString == "innerheight") {
- windowFeatures.heightSet = true;
- windowFeatures.height = value;
- } else if (keyString == "menubar")
- windowFeatures.menuBarVisible = value;
- else if (keyString == "toolbar")
- windowFeatures.toolBarVisible = value;
- else if (keyString == "location")
- windowFeatures.locationBarVisible = value;
- else if (keyString == "status")
- windowFeatures.statusBarVisible = value;
- else if (keyString == "resizable")
- windowFeatures.resizable = value;
- else if (keyString == "fullscreen")
- windowFeatures.fullscreen = value;
- else if (keyString == "scrollbars")
- windowFeatures.scrollbarsVisible = value;
-}
-
-
-void DOMWindow::back()
-{
- if (m_history)
- m_history->back();
-}
-
-void DOMWindow::forward()
-{
- if (m_history)
- m_history->forward();
-}
-
-Location* DOMWindow::location()
-{
- if (!m_location)
- m_location = Location::create(m_frame);
- return m_location.get();
-}
-
-void DOMWindow::setLocation(const String& v) {
- if (!m_frame)
- return;
-
- Frame* active_frame = ScriptController::retrieveActiveFrame();
- if (!active_frame)
- return;
-
- if (!active_frame->loader()->shouldAllowNavigation(m_frame))
- return;
-
- if (!parseURL(v).startsWith("javascript:", false) ||
- ScriptController::isSafeScript(m_frame)) {
- String completed_url = active_frame->loader()->completeURL(v).string();
-
- m_frame->loader()->scheduleLocationChange(completed_url,
- active_frame->loader()->outgoingReferrer(), false,
- active_frame->script()->processingUserGesture());
- }
-}
-
-Navigator* DOMWindow::navigator()
-{
- if (!m_navigator)
- m_navigator = Navigator::create(m_frame);
-
- return m_navigator.get();
-}
-
-void DOMWindow::dump(const String& msg)
-{
- if (!m_frame)
- return;
-
- m_frame->domWindow()->console()->addMessage(JSMessageSource,
- ErrorMessageLevel, msg, 0, m_frame->document()->url());
-}
-
-void DOMWindow::scheduleClose()
-{
- if (!m_frame)
- return;
-
- m_frame->scheduleClose();
-}
-
-void DOMWindow::timerFired(DOMWindowTimer* timer) {
- if (!m_frame)
- return;
-
- // Simple case for non-one-shot timers.
- if (timer->isActive()) {
- int timeoutId = timer->timeoutId();
-
- timer->action()->execute(this);
- return;
- }
-
- // Delete timer before executing the action for one-shot timers.
- ScheduledAction* action = timer->takeAction();
- m_timeouts.remove(timer->timeoutId());
- delete timer;
- action->execute(this);
- delete action;
-}
-
-
-void DOMWindow::clearAllTimeouts()
-{
- deleteAllValues(m_timeouts);
- m_timeouts.clear();
-}
-
-int DOMWindow::installTimeout(ScheduledAction* a, int t, bool singleShot) {
- if (!m_frame)
- return 0;
-
- int timeoutId = ++lastUsedTimeoutId;
-
- // avoid wraparound going negative on us
- if (timeoutId <= 0)
- timeoutId = 1;
-
- int nestLevel = timerNestingLevel + 1;
-
- DOMWindowTimer* timer = new DOMWindowTimer(timeoutId, nestLevel, this, a);
- ASSERT(!m_timeouts.get(timeoutId));
- m_timeouts.set(timeoutId, timer);
- double interval = max(kMinimumTimerInterval, t * 0.001);
- if (singleShot)
- timer->startOneShot(interval);
- else
- timer->startRepeating(interval);
-
- return timeoutId;
-}
-
-void DOMWindow::clearTimeout(int timeoutId)
-{
- // timeout IDs have to be positive, and 0 and -1 are unsafe to
- // even look up since they are the empty and deleted value
- // respectively
- if (timeoutId <= 0)
- return;
-
- delete m_timeouts.take(timeoutId);
-}
-
-void DOMWindow::pauseTimeouts(OwnPtr<PausedTimeouts>& pausedTimeouts)
-{
- size_t count = m_timeouts.size();
- if (count == 0) {
- pausedTimeouts.clear();
- return;
- }
-
- PausedTimeout* t = new PausedTimeout[count];
- PausedTimeouts* result = new PausedTimeouts(t, count);
-
- TimeoutsMap::iterator it = m_timeouts.begin();
- for (size_t i = 0; i != count; ++i, ++it) {
- int timeoutId = it->first;
- DOMWindowTimer* timer = it->second;
- t[i].timeoutId = timeoutId;
- t[i].nestingLevel = timer->nestingLevel();
- t[i].nextFireInterval = timer->nextFireInterval();
- t[i].repeatInterval = timer->repeatInterval();
- t[i].action = timer->takeAction();
- }
- ASSERT(it == m_timeouts.end());
-
- deleteAllValues(m_timeouts);
- m_timeouts.clear();
-
- pausedTimeouts.set(result);
-}
-
-void DOMWindow::resumeTimeouts(OwnPtr<PausedTimeouts>& timeouts) {
- if (!timeouts)
- return;
- size_t count = timeouts->numTimeouts();
- PausedTimeout* array = timeouts->takeTimeouts();
- for (size_t i = 0; i != count; ++i) {
- int timeoutId = array[i].timeoutId;
- DOMWindowTimer* timer =
- new DOMWindowTimer(timeoutId, array[i].nestingLevel,
- this, array[i].action);
- m_timeouts.set(timeoutId, timer);
- timer->start(array[i].nextFireInterval, array[i].repeatInterval);
- }
- delete[] array;
- timeouts.clear();
-}
-
-#endif // V8
-
-void DOMWindow::updateLayout() const {
- WebCore::Document* docimpl = m_frame->document();
- if (docimpl)
- docimpl->updateLayoutIgnorePendingStylesheets();
-}
-
-void DOMWindow::moveTo(float x, float y) const {
- if (!m_frame || !m_frame->page()) return;
-
- Page* page = m_frame->page();
- FloatRect fr = page->chrome()->windowRect();
- FloatRect sr = screenAvailableRect(page->mainFrame()->view());
- fr.setLocation(sr.location());
- FloatRect update = fr;
- update.move(x, y);
- // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
- adjustWindowRect(sr, fr, update);
- page->chrome()->setWindowRect(fr);
-}
-
-void DOMWindow::moveBy(float x, float y) const {
- if (!m_frame || !m_frame->page()) return;
-
- Page* page = m_frame->page();
- FloatRect fr = page->chrome()->windowRect();
- FloatRect update = fr;
- update.move(x, y);
- // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
- adjustWindowRect(screenAvailableRect(page->mainFrame()->view()), fr, update);
- page->chrome()->setWindowRect(fr);
-}
-
-void DOMWindow::resizeTo(float x, float y) const {
- if (!m_frame || !m_frame->page()) return;
-
- Page* page = m_frame->page();
- FloatRect fr = page->chrome()->windowRect();
- FloatSize dest = FloatSize(x, y);
- FloatRect update(fr.location(), dest);
- adjustWindowRect(screenAvailableRect(page->mainFrame()->view()), fr, update);
- page->chrome()->setWindowRect(fr);
-}
-
-void DOMWindow::resizeBy(float x, float y) const {
- if (!m_frame || !m_frame->page()) return;
-
- Page* page = m_frame->page();
- FloatRect fr = page->chrome()->windowRect();
- FloatSize dest = fr.size() + FloatSize(x, y);
- FloatRect update(fr.location(), dest);
- adjustWindowRect(screenAvailableRect(page->mainFrame()->view()), fr, update);
- page->chrome()->setWindowRect(fr);
-}
-
-
-void DOMWindow::scrollTo(int x, int y) const {
- if (!m_frame || !m_frame->view())
- return;
-
- if (m_frame->isDisconnected())
- return;
-
- updateLayout();
- m_frame->view()->setContentsPos(x, y);
-}
-
-void DOMWindow::scrollBy(int x, int y) const {
- if (!m_frame || !m_frame->view()) return;
-
- updateLayout();
- m_frame->view()->scrollBy(x, y);
-}
-
-#if ENABLE(DATABASE)
-PassRefPtr<Database> DOMWindow::openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, ExceptionCode& ec)
-{
- if (!m_frame)
- return 0;
- return;
-
- if (m_frame->isDisconnected())
- return;
-
- Document* doc = m_frame->document();
- ASSERT(doc);
- if (!doc)
- return 0;
-
- return Database::openDatabase(doc, name, version, displayName, estimatedSize, ec);
-}
-#endif
-
-
-} // namespace WebCore
diff --git a/webkit/pending/DOMWindow.h b/webkit/pending/DOMWindow.h
deleted file mode 100644
index 4cc00b3..0000000
--- a/webkit/pending/DOMWindow.h
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DOMWindow_h
-#define DOMWindow_h
-
-#include "KURL.h"
-#include "PlatformString.h"
-#include "SecurityOrigin.h"
-#include <wtf/Forward.h>
-#include <wtf/RefCounted.h>
-
-#if USE(V8)
-#include <wtf/HashMap.h>
-#endif
-#include <wtf/RefPtr.h>
-
-namespace WebCore {
-
- class BarInfo;
- class CSSRuleList;
- class CSSStyleDeclaration;
- class Console;
- class DOMSelection;
- class Database;
- class Document;
- class Element;
- class FloatRect;
- class Frame;
- class History;
- class Location;
- class Navigator;
- class PostMessageTimer;
- class Screen;
- class String;
-
-#if USE(V8)
- class ScheduledAction;
- class PausedTimeouts;
- class DOMWindowTimer;
-#endif
-
-#if ENABLE(DOM_STORAGE)
- class SessionStorage;
- class Storage;
-#endif
-
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- class DOMApplicationCache;
-#endif
-
- typedef int ExceptionCode;
-
- class DOMWindow : public RefCounted<DOMWindow> {
- public:
- static PassRefPtr<DOMWindow> create(Frame* frame) { return adoptRef(new DOMWindow(frame)); }
- virtual ~DOMWindow();
-
- Frame* frame() { return m_frame; }
- void disconnectFrame();
-
- void clear();
-
- void setSecurityOrigin(SecurityOrigin* securityOrigin) { m_securityOrigin = securityOrigin; }
- SecurityOrigin* securityOrigin() const { return m_securityOrigin.get(); }
-
- void setURL(const KURL& url) { m_url = url; }
- KURL url() const { return m_url; }
-
- static void adjustWindowRect(const FloatRect& screen, FloatRect& window, const FloatRect& pendingChanges);
-
- // DOM Level 0
- Screen* screen() const;
- History* history() const;
- BarInfo* locationbar() const;
- BarInfo* menubar() const;
- BarInfo* personalbar() const;
- BarInfo* scrollbars() const;
- BarInfo* statusbar() const;
- BarInfo* toolbar() const;
- Navigator* navigator() const;
- Navigator* clientInformation() const { return navigator(); }
- Location* location() const;
-
- DOMSelection* getSelection();
-
- Element* frameElement() const;
-
- void focus();
- void blur();
- void close();
- void print();
- void stop();
-
- void alert(const String& message);
- bool confirm(const String& message);
- String prompt(const String& message, const String& defaultValue);
-
- bool find(const String&, bool caseSensitive, bool backwards, bool wrap, bool wholeWord, bool searchInFrames, bool showDialog) const;
-
- bool offscreenBuffering() const;
-
- int outerHeight() const;
- int outerWidth() const;
- int innerHeight() const;
- int innerWidth() const;
- int screenX() const;
- int screenY() const;
- int screenLeft() const { return screenX(); }
- int screenTop() const { return screenY(); }
- int scrollX() const;
- int scrollY() const;
- int pageXOffset() const { return scrollX(); }
- int pageYOffset() const { return scrollY(); }
-
- bool closed() const;
-
- unsigned length() const;
-
- String name() const;
- void setName(const String&);
-
- String status() const;
- void setStatus(const String&);
- String defaultStatus() const;
- void setDefaultStatus(const String&);
- // This attribute is an alias of defaultStatus and is necessary for legacy uses.
- String defaultstatus() const { return defaultStatus(); }
- void setDefaultstatus(const String& status) { setDefaultStatus(status); }
-
- // Self referential attributes
- DOMWindow* self() const;
- DOMWindow* window() const { return self(); }
- DOMWindow* frames() const { return self(); }
-
- DOMWindow* opener() const;
- DOMWindow* parent() const;
- DOMWindow* top() const;
-
- // DOM Level 2 AbstractView Interface
- Document* document() const;
-
- // DOM Level 2 Style Interface
- PassRefPtr<CSSStyleDeclaration> getComputedStyle(Element*, const String& pseudoElt) const;
-
- // WebKit extensions
- PassRefPtr<CSSRuleList> getMatchedCSSRules(Element*, const String& pseudoElt, bool authorOnly = true) const;
- double devicePixelRatio() const;
-
-#if ENABLE(DATABASE)
- // HTML 5 client-side database
- PassRefPtr<Database> openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, ExceptionCode&);
-#endif
-
-#if ENABLE(DOM_STORAGE)
- // HTML 5 key/value storage
- Storage* sessionStorage() const;
- Storage* localStorage() const;
-#endif
-
- Console* console() const;
-
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- DOMApplicationCache* applicationCache() const;
-#endif
-
- void postMessage(const String& message, const String& targetOrigin, DOMWindow* source, ExceptionCode&);
- void postMessageTimerFired(PostMessageTimer*);
-
- void scrollBy(int x, int y) const;
- void scrollTo(int x, int y) const;
- void scroll(int x, int y) const { scrollTo(x, y); }
-
- void moveBy(float x, float y) const;
- void moveTo(float x, float y) const;
-
- void resizeBy(float x, float y) const;
- void resizeTo(float width, float height) const;
-
- // These methods are used for GC marking. See JSDOMWindow::mark() in
- // JSDOMWindowCustom.cpp.
- Screen* optionalScreen() const { return m_screen.get(); }
- DOMSelection* optionalSelection() const { return m_selection.get(); }
- History* optionalHistory() const { return m_history.get(); }
- BarInfo* optionalLocationbar() const { return m_locationbar.get(); }
- BarInfo* optionalMenubar() const { return m_menubar.get(); }
- BarInfo* optionalPersonalbar() const { return m_personalbar.get(); }
- BarInfo* optionalScrollbars() const { return m_scrollbars.get(); }
- BarInfo* optionalStatusbar() const { return m_statusbar.get(); }
- BarInfo* optionalToolbar() const { return m_toolbar.get(); }
- Console* optionalConsole() const { return m_console.get(); }
- Navigator* optionalNavigator() const { return m_navigator.get(); }
- Location* optionalLocation() const { return m_location.get(); }
-#if ENABLE(DOM_STORAGE)
- Storage* optionalSessionStorage() const { return m_sessionStorage.get(); }
- Storage* optionalLocalStorage() const { return m_sessionStorage.get(); }
-#endif
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- DOMApplicationCache* optionalApplicationCache() const { return m_applicationCache.get(); }
-#endif
-
- private:
- DOMWindow(Frame*);
-
- RefPtr<SecurityOrigin> m_securityOrigin;
- KURL m_url;
-
- Frame* m_frame;
- mutable RefPtr<Screen> m_screen;
- mutable RefPtr<DOMSelection> m_selection;
- mutable RefPtr<History> m_history;
- mutable RefPtr<BarInfo> m_locationbar;
- mutable RefPtr<BarInfo> m_menubar;
- mutable RefPtr<BarInfo> m_personalbar;
- mutable RefPtr<BarInfo> m_scrollbars;
- mutable RefPtr<BarInfo> m_statusbar;
- mutable RefPtr<BarInfo> m_toolbar;
- mutable RefPtr<Console> m_console;
- mutable RefPtr<Navigator> m_navigator;
- mutable RefPtr<Location> m_location;
-#if ENABLE(DOM_STORAGE)
- mutable RefPtr<Storage> m_sessionStorage;
- mutable RefPtr<Storage> m_localStorage;
-#endif
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- mutable RefPtr<DOMApplicationCache> m_applicationCache;
-#endif
-
- private:
- void updateLayout() const;
-
-
-#if USE(V8)
- public:
- // DOM methods & attributes for Window.
-
- DOMWindow* open(const String& url = "",
- const String& name = "_blank",
- const String& options = "");
-
- void back();
- void forward();
-
- Navigator* navigator();
- void dump(const String&);
-
- Location* location();
-
- // Change the current window location to a new location.
- // The function checks domain security.
- void setLocation(const String& loc);
-
-// void home();
-// void stop();
-
- void clearTimeout(int id);
- void clearInterval(int id) { clearTimeout(id); }
-
- void timerFired(DOMWindowTimer* timer);
-
-// void updateCommands(const String&);
-//
-// String escape(const String&);
-// String unescape(const String&);
-
- int installTimeout(ScheduledAction* a, int t, bool singleShot);
-
- void scheduleClose();
- void clearAllTimeouts();
-
- void pauseTimeouts(OwnPtr<PausedTimeouts>&);
- void resumeTimeouts(OwnPtr<PausedTimeouts>&);
-
- private:
- typedef HashMap<int, DOMWindowTimer*> TimeoutsMap;
- TimeoutsMap m_timeouts;
-#endif
- };
-
-} // namespace WebCore
-
-#endif
diff --git a/webkit/pending/Document.cpp b/webkit/pending/Document.cpp
deleted file mode 100644
index 15c5952..0000000
--- a/webkit/pending/Document.cpp
+++ /dev/null
@@ -1,4455 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2001 Dirk Mueller (mueller@kde.org)
- * (C) 2006 Alexey Proskuryakov (ap@webkit.org)
- * Copyright (C) 2004, 2005, 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "Document.h"
-
-#include "AnimationController.h"
-#include "AXObjectCache.h"
-#include "CDATASection.h"
-#include "CSSHelper.h"
-#include "CSSStyleSelector.h"
-#include "CSSStyleSheet.h"
-#include "CSSValueKeywords.h"
-#include "CString.h"
-#include "CachedCSSStyleSheet.h"
-#include "Comment.h"
-#include "CookieJar.h"
-#include "DOMImplementation.h"
-#include "DOMWindow.h"
-#include "DocLoader.h"
-#include "DocumentFragment.h"
-#include "DocumentLoader.h"
-#include "DocumentType.h"
-#include "EditingText.h"
-#include "Editor.h"
-#include "EntityReference.h"
-#include "Event.h"
-#include "EventHandler.h"
-#include "EventListener.h"
-#include "EventNames.h"
-#include "ExceptionCode.h"
-#include "FocusController.h"
-#include "FontCache.h"
-#include "Frame.h"
-#include "FrameLoader.h"
-#include "FrameTree.h"
-#include "FrameView.h"
-#include "HTMLBodyElement.h"
-#include "HTMLCanvasElement.h"
-#include "HTMLDocument.h"
-#include "HTMLElementFactory.h"
-#include "HTMLFrameOwnerElement.h"
-#include "HTMLHeadElement.h"
-#include "HTMLImageLoader.h"
-#include "HTMLInputElement.h"
-#include "HTMLLinkElement.h"
-#include "HTMLMapElement.h"
-#include "HTMLNameCollection.h"
-#include "HTMLNames.h"
-#include "HTMLStyleElement.h"
-#include "HTMLTitleElement.h"
-#include "HTTPParsers.h"
-#include "HistoryItem.h"
-#include "HitTestRequest.h"
-#include "HitTestResult.h"
-#include "KeyboardEvent.h"
-#include "Logging.h"
-#include "MessageEvent.h"
-#include "MouseEvent.h"
-#include "MouseEventWithHitTestResults.h"
-#include "MutationEvent.h"
-#include "NameNodeList.h"
-#include "NodeFilter.h"
-#include "NodeIterator.h"
-#include "NodeWithIndex.h"
-#include "OverflowEvent.h"
-#include "Page.h"
-#include "PlatformKeyboardEvent.h"
-#include "ProcessingInstruction.h"
-#include "ProgressEvent.h"
-#include "RegisteredEventListener.h"
-#include "RegularExpression.h"
-#include "RenderArena.h"
-#include "RenderView.h"
-#include "RenderWidget.h"
-#include "SecurityOrigin.h"
-#include "SegmentedString.h"
-#include "SelectionController.h"
-#include "Settings.h"
-#include "StringHash.h"
-#include "StyleSheetList.h"
-#include "SystemTime.h"
-#include "TextEvent.h"
-#include "TextIterator.h"
-#include "TextResourceDecoder.h"
-#include "TreeWalker.h"
-#include "UIEvent.h"
-#include "WheelEvent.h"
-#include "XMLHttpRequest.h"
-#include "XMLNames.h"
-#include "XMLTokenizer.h"
-#include "ScriptController.h"
-
-#if USE(JSC)
-#include <kjs/JSLock.h>
-#include "JSDOMBinding.h"
-#endif
-
-#if ENABLE(DATABASE)
-#include "Database.h"
-#include "DatabaseThread.h"
-#endif
-
-#if ENABLE(XPATH)
-#include "XPathEvaluator.h"
-#include "XPathExpression.h"
-#include "XPathNSResolver.h"
-#include "XPathResult.h"
-#endif
-
-#if ENABLE(XSLT)
-#include "XSLTProcessor.h"
-#endif
-
-#if ENABLE(XBL)
-#include "XBLBindingManager.h"
-#endif
-
-#if ENABLE(SVG)
-#include "SVGDocumentExtensions.h"
-#include "SVGElementFactory.h"
-#include "SVGZoomEvent.h"
-#include "SVGStyleElement.h"
-#endif
-
-#if defined(__APPLE__)
-// we need to be PLATFORM(CHROMIUM) for this file, even if we're not building
-// that particular target, for the a11y ifdefs.
-#define WTF_PLATFORM_CHROMIUM 1
-#endif
-
-using namespace std;
-using namespace WTF;
-using namespace Unicode;
-
-namespace WebCore {
-
-using namespace EventNames;
-using namespace HTMLNames;
-
-// #define INSTRUMENT_LAYOUT_SCHEDULING 1
-
-// This amount of time must have elapsed before we will even consider scheduling a layout without a delay.
-// FIXME: For faster machines this value can really be lowered to 200. 250 is adequate, but a little high
-// for dual G5s. :)
-static const int cLayoutScheduleThreshold = 250;
-
-// Use 1 to represent the document's default form.
-static HTMLFormElement* const defaultForm = reinterpret_cast<HTMLFormElement*>(1);
-
-// Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
-static const unsigned PHI = 0x9e3779b9U;
-
-// DOM Level 2 says (letters added):
-//
-// a) Name start characters must have one of the categories Ll, Lu, Lo, Lt, Nl.
-// b) Name characters other than Name-start characters must have one of the categories Mc, Me, Mn, Lm, or Nd.
-// c) Characters in the compatibility area (i.e. with character code greater than #xF900 and less than #xFFFE) are not allowed in XML names.
-// d) Characters which have a font or compatibility decomposition (i.e. those with a "compatibility formatting tag" in field 5 of the database -- marked by field 5 beginning with a "<") are not allowed.
-// e) The following characters are treated as name-start characters rather than name characters, because the property file classifies them as Alphabetic: [#x02BB-#x02C1], #x0559, #x06E5, #x06E6.
-// f) Characters #x20DD-#x20E0 are excluded (in accordance with Unicode, section 5.14).
-// g) Character #x00B7 is classified as an extender, because the property list so identifies it.
-// h) Character #x0387 is added as a name character, because #x00B7 is its canonical equivalent.
-// i) Characters ':' and '_' are allowed as name-start characters.
-// j) Characters '-' and '.' are allowed as name characters.
-//
-// It also contains complete tables. If we decide it's better, we could include those instead of the following code.
-
-static inline bool isValidNameStart(UChar32 c)
-{
- // rule (e) above
- if ((c >= 0x02BB && c <= 0x02C1) || c == 0x559 || c == 0x6E5 || c == 0x6E6)
- return true;
-
- // rule (i) above
- if (c == ':' || c == '_')
- return true;
-
- // rules (a) and (f) above
- const uint32_t nameStartMask = Letter_Lowercase | Letter_Uppercase | Letter_Other | Letter_Titlecase | Number_Letter;
- if (!(Unicode::category(c) & nameStartMask))
- return false;
-
- // rule (c) above
- if (c >= 0xF900 && c < 0xFFFE)
- return false;
-
- // rule (d) above
- DecompositionType decompType = decompositionType(c);
- if (decompType == DecompositionFont || decompType == DecompositionCompat)
- return false;
-
- return true;
-}
-
-static inline bool isValidNamePart(UChar32 c)
-{
- // rules (a), (e), and (i) above
- if (isValidNameStart(c))
- return true;
-
- // rules (g) and (h) above
- if (c == 0x00B7 || c == 0x0387)
- return true;
-
- // rule (j) above
- if (c == '-' || c == '.')
- return true;
-
- // rules (b) and (f) above
- const uint32_t otherNamePartMask = Mark_NonSpacing | Mark_Enclosing | Mark_SpacingCombining | Letter_Modifier | Number_DecimalDigit;
- if (!(Unicode::category(c) & otherNamePartMask))
- return false;
-
- // rule (c) above
- if (c >= 0xF900 && c < 0xFFFE)
- return false;
-
- // rule (d) above
- DecompositionType decompType = decompositionType(c);
- if (decompType == DecompositionFont || decompType == DecompositionCompat)
- return false;
-
- return true;
-}
-
-static Widget* widgetForNode(Node* focusedNode)
-{
- if (!focusedNode)
- return 0;
- RenderObject* renderer = focusedNode->renderer();
- if (!renderer || !renderer->isWidget())
- return 0;
- return static_cast<RenderWidget*>(renderer)->widget();
-}
-
-static bool acceptsEditingFocus(Node *node)
-{
- ASSERT(node);
- ASSERT(node->isContentEditable());
-
- Node *root = node->rootEditableElement();
- Frame* frame = node->document()->frame();
- if (!frame || !root)
- return false;
-
- return frame->editor()->shouldBeginEditing(rangeOfContents(root).get());
-}
-
-static HashSet<Document*>* changedDocuments = 0;
-
-Document::Document(Frame* frame, bool isXHTML)
- : ContainerNode(0)
- , m_domtree_version(0)
- , m_styleSheets(StyleSheetList::create(this))
- , m_title("")
- , m_titleSetExplicitly(false)
- , m_imageLoadEventTimer(this, &Document::imageLoadEventTimerFired)
- , m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired)
-#if ENABLE(XSLT)
- , m_transformSource(0)
-#endif
- , m_xmlVersion("1.0")
- , m_xmlStandalone(false)
- , m_dominantScript(USCRIPT_INVALID_CODE)
-#if ENABLE(XBL)
- , m_bindingManager(new XBLBindingManager(this))
-#endif
- , m_savedRenderer(0)
- , m_secureForms(0)
- , m_designMode(inherit)
- , m_selfOnlyRefCount(0)
-#if ENABLE(SVG)
- , m_svgExtensions(0)
-#endif
-#if ENABLE(DASHBOARD_SUPPORT)
- , m_hasDashboardRegions(false)
- , m_dashboardRegionsDirty(false)
-#endif
- , m_accessKeyMapValid(false)
- , m_createRenderers(true)
- , m_inPageCache(false)
- , m_useSecureKeyboardEntryWhenActive(false)
- , m_isXHTML(isXHTML)
- , m_numNodeListCaches(0)
-#if ENABLE(DATABASE)
- , m_hasOpenDatabases(false)
-#endif
-#if USE(LOW_BANDWIDTH_DISPLAY)
- , m_inLowBandwidthDisplay(false)
-#endif
-{
- m_document.resetSkippingRef(this);
-
- m_printing = false;
-
- m_ignoreAutofocus = false;
-
- m_frame = frame;
- m_renderArena = 0;
-
- m_axObjectCache = 0;
-
- m_docLoader = new DocLoader(this);
-
- visuallyOrdered = false;
- m_bParsing = false;
- m_docChanged = false;
- m_tokenizer = 0;
- m_wellFormed = false;
-
- setParseMode(Strict);
-
- m_textColor = Color::black;
- m_listenerTypes = 0;
- m_inDocument = true;
- m_inStyleRecalc = false;
- m_closeAfterStyleRecalc = false;
- m_usesDescendantRules = false;
- m_usesSiblingRules = false;
- m_usesFirstLineRules = false;
- m_usesFirstLetterRules = false;
- m_gotoAnchorNeededAfterStylesheetsLoad = false;
-
- m_styleSelector = 0;
- m_didCalculateStyleSelector = false;
- m_pendingStylesheets = 0;
- m_ignorePendingStylesheets = false;
- m_hasNodesWithPlaceholderStyle = false;
- m_pendingSheetLayout = NoLayoutWithPendingSheets;
-
- m_cssTarget = 0;
-
- resetLinkColor();
- resetVisitedLinkColor();
- resetActiveLinkColor();
-
- m_processingLoadEvent = false;
- m_startTime = currentTime();
- m_overMinimumLayoutThreshold = false;
-
- initSecurityContext();
- initDNSPrefetchEnabled();
-
- static int docID = 0;
- m_docID = docID++;
-}
-
-void Document::removedLastRef()
-{
- ASSERT(!m_deletionHasBegun);
- if (m_selfOnlyRefCount) {
- // If removing a child removes the last self-only ref, we don't
- // want the document to be destructed until after
- // removeAllChildren returns, so we guard ourselves with an
- // extra self-only ref.
-
- DocPtr<Document> guard(this);
-
- // We must make sure not to be retaining any of our children through
- // these extra pointers or we will create a reference cycle.
- m_docType = 0;
- m_focusedNode = 0;
- m_hoverNode = 0;
- m_activeNode = 0;
- m_titleElement = 0;
- m_documentElement = 0;
-
- removeAllChildren();
-
- deleteAllValues(m_markers);
- m_markers.clear();
-
- delete m_tokenizer;
- m_tokenizer = 0;
-
-#ifndef NDEBUG
- m_inRemovedLastRefFunction = false;
-#endif
- } else {
-#ifndef NDEBUG
- m_deletionHasBegun = true;
-#endif
- delete this;
- }
-}
-
-Document::~Document()
-{
- ASSERT(!renderer());
- ASSERT(!m_inPageCache);
- ASSERT(!m_savedRenderer);
- ASSERT(m_ranges.isEmpty());
-
- removeAllEventListeners();
-
-#if ENABLE(SVG)
- delete m_svgExtensions;
-#endif
-
- XMLHttpRequest::detachRequests(this);
-#if USE(JSC)
- {
- KJS::JSLock lock(false);
- ScriptInterpreter::forgetAllDOMNodesForDocument(this);
- }
-#endif
-
- if (m_docChanged && changedDocuments)
- changedDocuments->remove(this);
- delete m_tokenizer;
- m_document.resetSkippingRef(0);
- delete m_styleSelector;
- delete m_docLoader;
-
- if (m_renderArena) {
- delete m_renderArena;
- m_renderArena = 0;
- }
-
-#if ENABLE(XSLT)
- xmlFreeDoc((xmlDocPtr)m_transformSource);
-#endif
-
-#if ENABLE(XBL)
- delete m_bindingManager;
-#endif
-
- deleteAllValues(m_markers);
-
- clearAXObjectCache();
-
- m_decoder = 0;
-
- unsigned count = sizeof(m_nameCollectionInfo) / sizeof(m_nameCollectionInfo[0]);
- for (unsigned i = 0; i < count; i++)
- deleteAllValues(m_nameCollectionInfo[i]);
-
-#if ENABLE(DATABASE)
- if (m_databaseThread) {
- ASSERT(m_databaseThread->terminationRequested());
- m_databaseThread = 0;
- }
-#endif
-
- if (m_styleSheets)
- m_styleSheets->documentDestroyed();
-
- m_document = 0;
-}
-
-void Document::resetLinkColor()
-{
- m_linkColor = Color(0, 0, 238);
-}
-
-void Document::resetVisitedLinkColor()
-{
- m_visitedLinkColor = Color(85, 26, 139);
-}
-
-void Document::resetActiveLinkColor()
-{
- m_activeLinkColor.setNamedColor("red");
-}
-
-void Document::setDocType(PassRefPtr<DocumentType> docType)
-{
- // This should never be called more than once.
- // Note: This is not a public DOM method and can only be called by the parser.
- ASSERT(!m_docType || !docType);
- if (m_docType && docType)
- return;
- m_docType = docType;
- if (m_docType)
- m_docType->setDocument(this);
- determineParseMode();
-}
-
-DOMImplementation* Document::implementation() const
-{
- if (!m_implementation)
- m_implementation = DOMImplementation::create();
- return m_implementation.get();
-}
-
-void Document::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
-{
- ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
-
- // Invalidate the document element we have cached in case it was replaced.
- m_documentElement = 0;
-}
-
-Element* Document::documentElement() const
-{
- if (!m_documentElement) {
- Node* n = firstChild();
- while (n && !n->isElementNode())
- n = n->nextSibling();
- m_documentElement = static_cast<Element*>(n);
- }
-
- return m_documentElement.get();
-}
-
-PassRefPtr<Element> Document::createElement(const AtomicString& name, ExceptionCode& ec)
-{
- if (!isValidName(name)) {
- ec = INVALID_CHARACTER_ERR;
- return 0;
- }
-
- if (m_isXHTML)
- return HTMLElementFactory::createHTMLElement(name, this, 0, false);
-
- return createElement(QualifiedName(nullAtom, name, nullAtom), false, ec);
-}
-
-PassRefPtr<DocumentFragment> Document::createDocumentFragment()
-{
- return new DocumentFragment(document());
-}
-
-PassRefPtr<Text> Document::createTextNode(const String& data)
-{
- return new Text(this, data);
-}
-
-PassRefPtr<Comment> Document::createComment(const String& data)
-{
- return new Comment(this, data);
-}
-
-PassRefPtr<CDATASection> Document::createCDATASection(const String& data, ExceptionCode& ec)
-{
- if (isHTMLDocument()) {
- ec = NOT_SUPPORTED_ERR;
- return 0;
- }
- return new CDATASection(this, data);
-}
-
-PassRefPtr<ProcessingInstruction> Document::createProcessingInstruction(const String& target, const String& data, ExceptionCode& ec)
-{
- if (!isValidName(target)) {
- ec = INVALID_CHARACTER_ERR;
- return 0;
- }
- if (isHTMLDocument()) {
- ec = NOT_SUPPORTED_ERR;
- return 0;
- }
- return new ProcessingInstruction(this, target, data);
-}
-
-PassRefPtr<EntityReference> Document::createEntityReference(const String& name, ExceptionCode& ec)
-{
- if (!isValidName(name)) {
- ec = INVALID_CHARACTER_ERR;
- return 0;
- }
- if (isHTMLDocument()) {
- ec = NOT_SUPPORTED_ERR;
- return 0;
- }
- return new EntityReference(this, name);
-}
-
-PassRefPtr<EditingText> Document::createEditingTextNode(const String& text)
-{
- return new EditingText(this, text);
-}
-
-PassRefPtr<CSSStyleDeclaration> Document::createCSSStyleDeclaration()
-{
- return CSSMutableStyleDeclaration::create();
-}
-
-PassRefPtr<Node> Document::importNode(Node* importedNode, bool deep, ExceptionCode& ec)
-{
- ec = 0;
-
- if (!importedNode
-#if ENABLE(SVG) && ENABLE(DASHBOARD_SUPPORT)
- || (importedNode->isSVGElement() && page() && page()->settings()->usesDashboardBackwardCompatibilityMode())
-#endif
- ) {
- ec = NOT_SUPPORTED_ERR;
- return 0;
- }
-
- switch (importedNode->nodeType()) {
- case TEXT_NODE:
- return createTextNode(importedNode->nodeValue());
- case CDATA_SECTION_NODE:
- return createCDATASection(importedNode->nodeValue(), ec);
- case ENTITY_REFERENCE_NODE:
- return createEntityReference(importedNode->nodeName(), ec);
- case PROCESSING_INSTRUCTION_NODE:
- return createProcessingInstruction(importedNode->nodeName(), importedNode->nodeValue(), ec);
- case COMMENT_NODE:
- return createComment(importedNode->nodeValue());
- case ELEMENT_NODE: {
- Element* oldElement = static_cast<Element*>(importedNode);
- RefPtr<Element> newElement = createElementNS(oldElement->namespaceURI(), oldElement->tagQName().toString(), ec);
-
- if (ec)
- return 0;
-
- NamedAttrMap* attrs = oldElement->attributes(true);
- if (attrs) {
- unsigned length = attrs->length();
- for (unsigned i = 0; i < length; i++) {
- Attribute* attr = attrs->attributeItem(i);
- newElement->setAttribute(attr->name(), attr->value().impl(), ec);
- if (ec)
- return 0;
- }
- }
-
- newElement->copyNonAttributeProperties(oldElement);
-
- if (deep) {
- for (Node* oldChild = oldElement->firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
- RefPtr<Node> newChild = importNode(oldChild, true, ec);
- if (ec)
- return 0;
- newElement->appendChild(newChild.release(), ec);
- if (ec)
- return 0;
- }
- }
-
- return newElement.release();
- }
- case ATTRIBUTE_NODE: {
- RefPtr<Attr> newAttr = new Attr(0, this, static_cast<Attr*>(importedNode)->attr()->clone());
- newAttr->createTextChild();
- return newAttr.release();
- }
- case DOCUMENT_FRAGMENT_NODE: {
- DocumentFragment* oldFragment = static_cast<DocumentFragment*>(importedNode);
- RefPtr<DocumentFragment> newFragment = createDocumentFragment();
- if (deep) {
- for (Node* oldChild = oldFragment->firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
- RefPtr<Node> newChild = importNode(oldChild, true, ec);
- if (ec)
- return 0;
- newFragment->appendChild(newChild.release(), ec);
- if (ec)
- return 0;
- }
- }
-
- return newFragment.release();
- }
- case ENTITY_NODE:
- case NOTATION_NODE:
- // FIXME: It should be possible to import these node types, however in DOM3 the DocumentType is readonly, so there isn't much sense in doing that.
- // Ability to add these imported nodes to a DocumentType will be considered for addition to a future release of the DOM.
- case DOCUMENT_NODE:
- case DOCUMENT_TYPE_NODE:
- case XPATH_NAMESPACE_NODE:
- break;
- }
-
- ec = NOT_SUPPORTED_ERR;
- return 0;
-}
-
-
-PassRefPtr<Node> Document::adoptNode(PassRefPtr<Node> source, ExceptionCode& ec)
-{
- if (!source) {
- ec = NOT_SUPPORTED_ERR;
- return 0;
- }
-
- if (source->isReadOnlyNode()) {
- ec = NO_MODIFICATION_ALLOWED_ERR;
- return 0;
- }
-
- switch (source->nodeType()) {
- case ENTITY_NODE:
- case NOTATION_NODE:
- case DOCUMENT_NODE:
- case DOCUMENT_TYPE_NODE:
- case XPATH_NAMESPACE_NODE:
- ec = NOT_SUPPORTED_ERR;
- return 0;
- case ATTRIBUTE_NODE: {
- Attr* attr = static_cast<Attr*>(source.get());
- if (attr->ownerElement())
- attr->ownerElement()->removeAttributeNode(attr, ec);
- attr->setSpecified(true);
- break;
- }
- default:
- if (source->parentNode())
- source->parentNode()->removeChild(source.get(), ec);
- }
-
- for (Node* node = source.get(); node; node = node->traverseNextNode(source.get()))
- node->setDocument(this);
-
- return source;
-}
-
-bool Document::hasPrefixNamespaceMismatch(const QualifiedName& qName)
-{
- static const AtomicString xmlnsNamespaceURI("http://www.w3.org/2000/xmlns/");
- static const AtomicString xmlns("xmlns");
- static const AtomicString xml("xml");
-
- // These checks are from DOM Core Level 2, createElementNS
- // http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-DocCrElNS
- if (!qName.prefix().isEmpty() && qName.namespaceURI().isNull()) // createElementNS(null, "html:div")
- return true;
- if (qName.prefix() == xml && qName.namespaceURI() != XMLNames::xmlNamespaceURI) // createElementNS("http://www.example.com", "xml:lang")
- return true;
-
- // Required by DOM Level 3 Core and unspecified by DOM Level 2 Core:
- // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-DocCrElNS
- // createElementNS("http://www.w3.org/2000/xmlns/", "foo:bar"), createElementNS(null, "xmlns:bar")
- if ((qName.prefix() == xmlns && qName.namespaceURI() != xmlnsNamespaceURI) || (qName.prefix() != xmlns && qName.namespaceURI() == xmlnsNamespaceURI))
- return true;
-
- return false;
-}
-
-// FIXME: This should really be in a possible ElementFactory class
-PassRefPtr<Element> Document::createElement(const QualifiedName& qName, bool createdByParser, ExceptionCode& ec)
-{
- RefPtr<Element> e;
-
- // FIXME: Use registered namespaces and look up in a hash to find the right factory.
- if (qName.namespaceURI() == xhtmlNamespaceURI)
- e = HTMLElementFactory::createHTMLElement(qName.localName(), this, 0, createdByParser);
-#if ENABLE(SVG)
- else if (qName.namespaceURI() == SVGNames::svgNamespaceURI)
- e = SVGElementFactory::createSVGElement(qName, this, createdByParser);
-#endif
-
- if (!e)
- e = new Element(qName, document());
-
- // FIXME: The element factories should be fixed to not ignore qName.prefix()
- // Instead they should pass the entire qName into element creation so we don't
- // need to manually set the prefix after creation.
- // Then this code can become ASSERT(qName == e.qname());
- // and Document::createElement can stop taking ExceptionCode& as well.
- if (e && !qName.prefix().isNull()) {
- ec = 0;
- e->setPrefix(qName.prefix(), ec);
- if (ec)
- return 0;
- }
-
- return e.release();
-}
-
-PassRefPtr<Element> Document::createElementNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode& ec)
-{
- String prefix, localName;
- if (!parseQualifiedName(qualifiedName, prefix, localName, ec))
- return 0;
-
- QualifiedName qName(prefix, localName, namespaceURI);
- if (hasPrefixNamespaceMismatch(qName)) {
- ec = NAMESPACE_ERR;
- return 0;
- }
-
- return createElement(qName, false, ec);
-}
-
-Element* Document::getElementById(const AtomicString& elementId) const
-{
- if (elementId.isEmpty())
- return 0;
-
- Element* element = m_elementsById.get(elementId.impl());
- if (element)
- return element;
-
- if (m_duplicateIds.contains(elementId.impl())) {
- // We know there's at least one node with this id, but we don't know what the first one is.
- for (Node *n = traverseNextNode(); n != 0; n = n->traverseNextNode()) {
- if (n->isElementNode()) {
- element = static_cast<Element*>(n);
- if (element->hasID() && element->getAttribute(idAttr) == elementId) {
- m_duplicateIds.remove(elementId.impl());
- m_elementsById.set(elementId.impl(), element);
- return element;
- }
- }
- }
- ASSERT_NOT_REACHED();
- }
- return 0;
-}
-
-String Document::readyState() const
-{
- if (Frame* f = frame()) {
- if (f->loader()->isComplete())
- return "complete";
- if (parsing())
- return "loading";
- return "loaded";
- // FIXME: What does "interactive" mean?
- // FIXME: Missing support for "uninitialized".
- }
- return String();
-}
-
-String Document::inputEncoding() const
-{
- if (TextResourceDecoder* d = decoder())
- return d->encoding().name();
- return String();
-}
-
-String Document::defaultCharset() const
-{
- if (Settings* settings = this->settings())
- return settings->defaultTextEncodingName();
- return String();
-}
-
-void Document::setCharset(const String& charset)
-{
- if (!decoder())
- return;
- decoder()->setEncoding(charset, TextResourceDecoder::UserChosenEncoding);
-}
-
-UScriptCode Document::dominantScript() const
-{
- struct EncodingScript {
- const char* encoding;
- UScriptCode script;
- };
-
- // inputEncoding() always returns a canonical name. We use
- // MIME names and IANA names (if the former is not available).
- static const EncodingScript encodingScriptList[] = {
- { "GB2312", USCRIPT_SIMPLIFIED_HAN },
- { "GBK", USCRIPT_SIMPLIFIED_HAN },
- { "GB18030", USCRIPT_SIMPLIFIED_HAN },
- { "Big5", USCRIPT_TRADITIONAL_HAN },
- { "Big5-HKSCS", USCRIPT_TRADITIONAL_HAN },
- { "Shift_JIS", USCRIPT_HIRAGANA},
- { "EUC-JP", USCRIPT_HIRAGANA }, // Japanese (USCRIPT_JAPANESE)
- { "ISO-2022-KR", USCRIPT_HIRAGANA },
- { "EUC-KR", USCRIPT_HANGUL }, // Korean (USCRIPT_KOREAN)
- { "TIS-620", USCRIPT_THAI },
- { "ISO-8859-1", USCRIPT_LATIN },
- { "ISO-8859-15", USCRIPT_LATIN },
- { "windows-1252", USCRIPT_LATIN },
- { "ISO-8859-2", USCRIPT_LATIN },
- { "windows-1250", USCRIPT_LATIN },
- { "ISO-8859-3", USCRIPT_LATIN },
- { "ISO-8859-4", USCRIPT_LATIN },
- { "ISO-8859-13", USCRIPT_LATIN },
- { "windows-1257", USCRIPT_LATIN },
- { "ISO-8859-5", USCRIPT_CYRILLIC },
- { "windows-1251", USCRIPT_CYRILLIC },
- { "KOI8-R", USCRIPT_CYRILLIC },
- { "KOI8-U", USCRIPT_CYRILLIC },
- { "ISO-8859-6", USCRIPT_ARABIC },
- { "windows-1256", USCRIPT_ARABIC },
- { "ISO-8859-7", USCRIPT_GREEK },
- { "windows-1253", USCRIPT_GREEK },
- { "ISO-8859-8", USCRIPT_HEBREW },
- { "windows-1255", USCRIPT_HEBREW },
- { "ISO-8859-9", USCRIPT_LATIN }, // Turkish
- { "windows-1254", USCRIPT_LATIN },
- { "ISO-8859-10", USCRIPT_LATIN }, // Nordic
- { "ISO-8859-14", USCRIPT_LATIN }, // Celtic
- { "ISO-8859-16", USCRIPT_LATIN }, // Romanian
- { "windows-1258", USCRIPT_LATIN }, // Vietnamese
- };
-
- static HashMap<String, UScriptCode> encodingScriptMap;
-
- if (encodingScriptMap.isEmpty()) {
- for (unsigned i = 0; i < sizeof(encodingScriptList) / sizeof(encodingScriptList[0]); ++i)
- encodingScriptMap.set(encodingScriptList[i].encoding,
- encodingScriptList[i].script);
- }
-
- if (m_dominantScript != USCRIPT_INVALID_CODE)
- return m_dominantScript;
- String encoding = inputEncoding();
- if (encoding.isEmpty())
- return m_dominantScript;
-
- HashMap<String, UScriptCode>::iterator it = encodingScriptMap.find(encoding);
- if (it != encodingScriptMap.end())
- m_dominantScript = it->second;
- else
- // TODO(jungshik) : should return a script corresponding to the locale.
- m_dominantScript = USCRIPT_COMMON;
- return m_dominantScript;
-}
-
-void Document::setXMLVersion(const String& version, ExceptionCode& ec)
-{
- if (!implementation()->hasFeature("XML", String())) {
- ec = NOT_SUPPORTED_ERR;
- return;
- }
-
- // FIXME: Also raise NOT_SUPPORTED_ERR if the version is set to a value that is not supported by this Document.
-
- m_xmlVersion = version;
-}
-
-void Document::setXMLStandalone(bool standalone, ExceptionCode& ec)
-{
- if (!implementation()->hasFeature("XML", String())) {
- ec = NOT_SUPPORTED_ERR;
- return;
- }
-
- m_xmlStandalone = standalone;
-}
-
-void Document::setDocumentURI(const String& uri)
-{
- m_documentURI = uri;
- updateBaseURL();
-}
-
-KURL Document::baseURI() const
-{
- return m_baseURL;
-}
-
-Element* Document::elementFromPoint(int x, int y) const
-{
- if (!renderer())
- return 0;
-
- HitTestRequest request(true, true);
- HitTestResult result(IntPoint(x, y));
- renderer()->layer()->hitTest(request, result);
-
- Node* n = result.innerNode();
- while (n && !n->isElementNode())
- n = n->parentNode();
- if (n)
- n = n->shadowAncestorNode();
- return static_cast<Element*>(n);
-}
-
-void Document::addElementById(const AtomicString& elementId, Element* element)
-{
- typedef HashMap<AtomicStringImpl*, Element*>::iterator iterator;
- if (!m_duplicateIds.contains(elementId.impl())) {
- // Fast path. The ID is not already in m_duplicateIds, so we assume that it's
- // also not already in m_elementsById and do an add. If that add succeeds, we're done.
- pair<iterator, bool> addResult = m_elementsById.add(elementId.impl(), element);
- if (addResult.second)
- return;
- // The add failed, so this ID was already cached in m_elementsById.
- // There are multiple elements with this ID. Remove the m_elementsById
- // cache for this ID so getElementById searches for it next time it is called.
- m_elementsById.remove(addResult.first);
- m_duplicateIds.add(elementId.impl());
- } else {
- // There are multiple elements with this ID. If it exists, remove the m_elementsById
- // cache for this ID so getElementById searches for it next time it is called.
- iterator cachedItem = m_elementsById.find(elementId.impl());
- if (cachedItem != m_elementsById.end()) {
- m_elementsById.remove(cachedItem);
- m_duplicateIds.add(elementId.impl());
- }
- }
- m_duplicateIds.add(elementId.impl());
-}
-
-void Document::removeElementById(const AtomicString& elementId, Element* element)
-{
- if (m_elementsById.get(elementId.impl()) == element)
- m_elementsById.remove(elementId.impl());
- else
- m_duplicateIds.remove(elementId.impl());
-}
-
-Element* Document::getElementByAccessKey(const String& key) const
-{
- if (key.isEmpty())
- return 0;
- if (!m_accessKeyMapValid) {
- for (Node* n = firstChild(); n; n = n->traverseNextNode()) {
- if (!n->isElementNode())
- continue;
- Element* element = static_cast<Element*>(n);
- const AtomicString& accessKey = element->getAttribute(accesskeyAttr);
- if (!accessKey.isEmpty())
- m_elementsByAccessKey.set(accessKey.impl(), element);
- }
- m_accessKeyMapValid = true;
- }
- return m_elementsByAccessKey.get(key.impl());
-}
-
-void Document::updateTitle()
-{
- if (Frame* f = frame())
- f->loader()->setTitle(m_title);
-}
-
-void Document::setTitle(const String& title, Element* titleElement)
-{
- if (!titleElement) {
- // Title set by JavaScript -- overrides any title elements.
- m_titleSetExplicitly = true;
- if (!isHTMLDocument())
- m_titleElement = 0;
- else if (!m_titleElement) {
- if (HTMLElement* headElement = head()) {
- ExceptionCode ec = 0;
- m_titleElement = createElement("title", ec);
- ASSERT(!ec);
- headElement->appendChild(m_titleElement, ec);
- ASSERT(!ec);
- }
- }
- } else if (titleElement != m_titleElement) {
- if (m_titleElement || m_titleSetExplicitly)
- // Only allow the first title element to change the title -- others have no effect.
- return;
- m_titleElement = titleElement;
- }
-
- if (m_title == title)
- return;
-
- m_title = title;
- updateTitle();
-
- if (m_titleSetExplicitly && m_titleElement && m_titleElement->hasTagName(titleTag))
- static_cast<HTMLTitleElement*>(m_titleElement.get())->setText(m_title);
-}
-
-void Document::removeTitle(Element* titleElement)
-{
- if (m_titleElement != titleElement)
- return;
-
- m_titleElement = 0;
- m_titleSetExplicitly = false;
-
- // Update title based on first title element in the head, if one exists.
- if (HTMLElement* headElement = head()) {
- for (Node* e = headElement->firstChild(); e; e = e->nextSibling())
- if (e->hasTagName(titleTag)) {
- HTMLTitleElement* titleElement = static_cast<HTMLTitleElement*>(e);
- setTitle(titleElement->text(), titleElement);
- break;
- }
- }
-
- if (!m_titleElement && !m_title.isEmpty()) {
- m_title = "";
- updateTitle();
- }
-}
-
-String Document::nodeName() const
-{
- return "#document";
-}
-
-Node::NodeType Document::nodeType() const
-{
- return DOCUMENT_NODE;
-}
-
-FrameView* Document::view() const
-{
- return m_frame ? m_frame->view() : 0;
-}
-
-Page* Document::page() const
-{
- return m_frame ? m_frame->page() : 0;
-}
-
-Settings* Document::settings() const
-{
- return m_frame ? m_frame->settings() : 0;
-}
-
-PassRefPtr<Range> Document::createRange()
-{
- return Range::create(this);
-}
-
-PassRefPtr<NodeIterator> Document::createNodeIterator(Node* root, unsigned whatToShow,
- PassRefPtr<NodeFilter> filter, bool expandEntityReferences, ExceptionCode& ec)
-{
- if (!root) {
- ec = NOT_SUPPORTED_ERR;
- return 0;
- }
- return NodeIterator::create(root, whatToShow, filter, expandEntityReferences);
-}
-
-PassRefPtr<TreeWalker> Document::createTreeWalker(Node *root, unsigned whatToShow,
- PassRefPtr<NodeFilter> filter, bool expandEntityReferences, ExceptionCode& ec)
-{
- if (!root) {
- ec = NOT_SUPPORTED_ERR;
- return 0;
- }
- return TreeWalker::create(root, whatToShow, filter, expandEntityReferences);
-}
-
-void Document::setDocumentChanged(bool b)
-{
- if (b) {
- if (!m_docChanged) {
- if (!changedDocuments)
- changedDocuments = new HashSet<Document*>;
- changedDocuments->add(this);
- }
- if (m_accessKeyMapValid) {
- m_accessKeyMapValid = false;
- m_elementsByAccessKey.clear();
- }
- } else {
- if (m_docChanged && changedDocuments)
- changedDocuments->remove(this);
- }
-
- m_docChanged = b;
-}
-
-void Document::recalcStyle(StyleChange change)
-{
- // we should not enter style recalc while painting
- if (frame() && frame()->isPainting()) {
- ASSERT(!frame()->isPainting());
- return;
- }
-
- if (m_inStyleRecalc)
- return; // Guard against re-entrancy. -dwh
-
- m_inStyleRecalc = true;
- suspendPostAttachCallbacks();
-
- ASSERT(!renderer() || renderArena());
- if (!renderer() || !renderArena())
- goto bail_out;
-
- if (change == Force) {
- // style selector may set this again during recalc
- m_hasNodesWithPlaceholderStyle = false;
-
- RenderStyle* oldStyle = renderer()->style();
- if (oldStyle)
- oldStyle->ref();
- RenderStyle* _style = new (m_renderArena) RenderStyle();
- _style->ref();
- _style->setDisplay(BLOCK);
- _style->setVisuallyOrdered(visuallyOrdered);
- _style->setZoom(frame()->pageZoomFactor());
- m_styleSelector->setStyle(_style);
-
- FontDescription fontDescription;
- fontDescription.setUsePrinterFont(printing());
- // TODO(jungshik): Eventually, we need to derive the dominant script
- // for the current node based on 'xml:lang' and 'lang' specified for
- // it or inherited from its parent rather than using the document-wide
- // value (inferred from charset). Note also that it does not work
- // for 'script-agnostic' charsets like UTF-8. In that case, Firefox
- // uses the script corresponding to the application locale.
- // While a document is loaded, this function is called multiple
- // times. At the beginning, the document charset is not known and
- // dominantScript remains invalid. Only when it's determined, we
- // change the font accordingly.
- // See http://bugs.webkit.org/show_bug.cgi?id=10874 and
- // https://bugs.webkit.org/show_bug.cgi?id=18085
- UScriptCode script = dominantScript();
- if (script != USCRIPT_INVALID_CODE)
- fontDescription.setDominantScript(script);
- if (Settings* settings = this->settings()) {
- fontDescription.setRenderingMode(settings->fontRenderingMode());
- if (printing() && !settings->shouldPrintBackgrounds())
- _style->setForceBackgroundsToWhite(true);
- const AtomicString& stdfont = settings->standardFontFamily();
- if (!stdfont.isEmpty()) {
- fontDescription.firstFamily().setFamily(stdfont);
- FontFamily& currFamily = fontDescription.firstFamily();
- if (script != USCRIPT_INVALID_CODE) {
- // TODO(jungshik) : I might as well modify |genericFamily| of
- // |fontDescription| here, but I'm wary of a potential breakage.
- // For now, just use a temporary variable.
- FontDescription tmpDescription;
- tmpDescription.setGenericFamily(FontDescription::StandardFamily);
- AtomicString docFont = FontCache::getGenericFontForScript(
- script, tmpDescription);
- if (!docFont.isEmpty()) {
- RefPtr<SharedFontFamily> newFamily(SharedFontFamily::create());
- newFamily->setFamily(docFont);
- currFamily.appendFamily(newFamily);
- currFamily = *newFamily;
- }
- }
- currFamily.appendFamily(0);
- }
- fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
- m_styleSelector->setFontSize(fontDescription, m_styleSelector->fontSizeForKeyword(CSSValueMedium, inCompatMode(), false));
- }
-
- _style->setFontDescription(fontDescription);
- _style->font().update(m_styleSelector->fontSelector());
- if (inCompatMode())
- _style->setHtmlHacks(true); // enable html specific rendering tricks
-
- StyleChange ch = diff(_style, oldStyle);
- if (renderer() && ch != NoChange)
- renderer()->setStyle(_style);
- if (change != Force)
- change = ch;
-
- _style->deref(m_renderArena);
- if (oldStyle)
- oldStyle->deref(m_renderArena);
- }
-
- for (Node* n = firstChild(); n; n = n->nextSibling())
- if (change >= Inherit || n->hasChangedChild() || n->changed())
- n->recalcStyle(change);
-
- if (changed() && view())
- view()->layout();
-
-bail_out:
- setChanged(NoStyleChange);
- setHasChangedChild(false);
- setDocumentChanged(false);
-
- resumePostAttachCallbacks();
- m_inStyleRecalc = false;
-
- // If we wanted to call implicitClose() during recalcStyle, do so now that we're finished.
- if (m_closeAfterStyleRecalc) {
- m_closeAfterStyleRecalc = false;
- implicitClose();
- }
-}
-
-void Document::updateRendering()
-{
- if (hasChangedChild() && !inPageCache())
- recalcStyle(NoChange);
-
- // Tell the animation controller that the style is available and it can start animations
- if (m_frame)
- m_frame->animation()->styleAvailable();
-}
-
-void Document::updateDocumentsRendering()
-{
- if (!changedDocuments)
- return;
-
- while (changedDocuments->size()) {
- HashSet<Document*>::iterator it = changedDocuments->begin();
- Document* doc = *it;
- changedDocuments->remove(it);
-
- doc->m_docChanged = false;
- doc->updateRendering();
- }
-}
-
-void Document::updateLayout()
-{
- if (Element* oe = ownerElement())
- oe->document()->updateLayout();
-
- // FIXME: Dave Hyatt's pretty sure we can remove this because layout calls recalcStyle as needed.
- updateRendering();
-
- // Only do a layout if changes have occurred that make it necessary.
- FrameView* v = view();
- if (v && renderer() && (v->layoutPending() || renderer()->needsLayout()))
- v->layout();
-}
-
-// FIXME: This is a bad idea and needs to be removed eventually.
-// Other browsers load stylesheets before they continue parsing the web page.
-// Since we don't, we can run JavaScript code that needs answers before the
-// stylesheets are loaded. Doing a layout ignoring the pending stylesheets
-// lets us get reasonable answers. The long term solution to this problem is
-// to instead suspend JavaScript execution.
-void Document::updateLayoutIgnorePendingStylesheets()
-{
- bool oldIgnore = m_ignorePendingStylesheets;
-
- if (!haveStylesheetsLoaded()) {
- m_ignorePendingStylesheets = true;
- // FIXME: We are willing to attempt to suppress painting with outdated style info only once. Our assumption is that it would be
- // dangerous to try to stop it a second time, after page content has already been loaded and displayed
- // with accurate style information. (Our suppression involves blanking the whole page at the
- // moment. If it were more refined, we might be able to do something better.)
- // It's worth noting though that this entire method is a hack, since what we really want to do is
- // suspend JS instead of doing a layout with inaccurate information.
- if (body() && !body()->renderer() && m_pendingSheetLayout == NoLayoutWithPendingSheets) {
- m_pendingSheetLayout = DidLayoutWithPendingSheets;
- updateStyleSelector();
- } else if (m_hasNodesWithPlaceholderStyle)
- // If new nodes have been added or style recalc has been done with style sheets still pending, some nodes
- // may not have had their real style calculated yet. Normally this gets cleaned when style sheets arrive
- // but here we need up-to-date style immediatly.
- recalcStyle(Force);
- }
-
- updateLayout();
-
- m_ignorePendingStylesheets = oldIgnore;
-}
-
-void Document::attach()
-{
- ASSERT(!attached());
- ASSERT(!m_inPageCache);
- ASSERT(!m_axObjectCache);
-
- if (!m_renderArena)
- m_renderArena = new RenderArena();
-
- // Create the rendering tree
- setRenderer(new (m_renderArena) RenderView(this, view()));
-
- if (!m_styleSelector) {
- bool matchAuthorAndUserStyles = true;
- if (Settings* docSettings = settings())
- matchAuthorAndUserStyles = docSettings->authorAndUserStylesEnabled();
- m_styleSelector = new CSSStyleSelector(this, userStyleSheet(), m_styleSheets.get(), m_mappedElementSheet.get(), !inCompatMode(), matchAuthorAndUserStyles);
- }
-
- recalcStyle(Force);
-
- RenderObject* render = renderer();
- setRenderer(0);
-
- ContainerNode::attach();
-
- setRenderer(render);
-}
-
-void Document::detach()
-{
- ASSERT(attached());
- ASSERT(!m_inPageCache);
-
- clearAXObjectCache();
-
- RenderObject* render = renderer();
-
- // indicate destruction mode, i.e. attached() but renderer == 0
- setRenderer(0);
-
- // Empty out these lists as a performance optimization, since detaching
- // all the individual render objects will cause all the RenderImage
- // objects to remove themselves from the lists.
- m_imageLoadEventDispatchSoonList.clear();
- m_imageLoadEventDispatchingList.clear();
-
- m_hoverNode = 0;
- m_focusedNode = 0;
- m_activeNode = 0;
-
- ContainerNode::detach();
-
- if (render)
- render->destroy();
-
- // This is required, as our Frame might delete itself as soon as it detaches
- // us. However, this violates Node::detach() symantics, as it's never
- // possible to re-attach. Eventually Document::detach() should be renamed
- // or this call made explicit in each of the callers of Document::detach().
- clearFramePointer();
-
- if (m_renderArena) {
- delete m_renderArena;
- m_renderArena = 0;
- }
-}
-
-void Document::clearFramePointer()
-{
- m_frame = 0;
-}
-
-void Document::removeAllEventListenersFromAllNodes()
-{
- m_windowEventListeners.clear();
- removeAllDisconnectedNodeEventListeners();
- for (Node *n = this; n; n = n->traverseNextNode()) {
- if (!n->isEventTargetNode())
- continue;
- EventTargetNodeCast(n)->removeAllEventListeners();
- }
-}
-
-void Document::registerDisconnectedNodeWithEventListeners(Node* node)
-{
- m_disconnectedNodesWithEventListeners.add(node);
-}
-
-void Document::unregisterDisconnectedNodeWithEventListeners(Node* node)
-{
- m_disconnectedNodesWithEventListeners.remove(node);
-}
-
-void Document::removeAllDisconnectedNodeEventListeners()
-{
- HashSet<Node*>::iterator end = m_disconnectedNodesWithEventListeners.end();
- for (HashSet<Node*>::iterator i = m_disconnectedNodesWithEventListeners.begin(); i != end; ++i)
- EventTargetNodeCast(*i)->removeAllEventListeners();
- m_disconnectedNodesWithEventListeners.clear();
-}
-
-void Document::clearAXObjectCache()
-{
- // clear cache in top document
- if (m_axObjectCache) {
- delete m_axObjectCache;
- m_axObjectCache = 0;
- return;
- }
-
- // ask the top-level document to clear its cache
- Document* doc = topDocument();
- if (doc != this)
- doc->clearAXObjectCache();
-}
-
-AXObjectCache* Document::axObjectCache() const
-{
- // The only document that actually has a AXObjectCache is the top-level
- // document. This is because we need to be able to get from any WebCoreAXObject
- // to any other WebCoreAXObject on the same page. Using a single cache allows
- // lookups across nested webareas (i.e. multiple documents).
-
- if (m_axObjectCache) {
- // return already known top-level cache
- if (!ownerElement())
- return m_axObjectCache;
-
- // In some pages with frames, the cache is created before the sub-webarea is
- // inserted into the tree. Here, we catch that case and just toss the old
- // cache and start over.
- // NOTE: This recovery may no longer be needed. I have been unable to trigger
- // it again. See rdar://5794454
- // FIXME: Can this be fixed when inserting the subframe instead of now?
- // FIXME: If this function was called to get the cache in order to remove
- // an AXObject, we are now deleting the cache as a whole and returning a
- // new empty cache that does not contain the AXObject! That should actually
- // be OK. I am concerned about other cases like this where accessing the
- // cache blows away the AXObject being operated on.
- delete m_axObjectCache;
- m_axObjectCache = 0;
- }
-
- // ask the top-level document for its cache
- Document* doc = topDocument();
- if (doc != this)
- return doc->axObjectCache();
-
- // this is the top-level document, so install a new cache
- m_axObjectCache = new AXObjectCache;
- return m_axObjectCache;
-}
-
-void Document::setVisuallyOrdered()
-{
- visuallyOrdered = true;
- if (renderer())
- renderer()->style()->setVisuallyOrdered(true);
-}
-
-Tokenizer* Document::createTokenizer()
-{
- // FIXME: this should probably pass the frame instead
- return new XMLTokenizer(this, view());
-}
-
-void Document::open(Document* ownerDocument)
-{
- if (ownerDocument) {
- setURL(ownerDocument->url());
- m_cookieURL = ownerDocument->cookieURL();
- m_securityOrigin = ownerDocument->securityOrigin();
- }
-
- if (m_frame) {
- if (m_frame->loader()->isLoadingMainResource() || (tokenizer() && tokenizer()->executingScript()))
- return;
-
- if (m_frame->loader()->state() == FrameStateProvisional)
- m_frame->loader()->stopAllLoaders();
- }
-
- implicitOpen();
-
- if (m_frame)
- m_frame->loader()->didExplicitOpen();
-}
-
-void Document::cancelParsing()
-{
- if (m_tokenizer) {
- // We have to clear the tokenizer to avoid possibly triggering
- // the onload handler when closing as a side effect of a cancel-style
- // change, such as opening a new document or closing the window while
- // still parsing
- delete m_tokenizer;
- m_tokenizer = 0;
- close();
- }
-}
-
-void Document::implicitOpen()
-{
- cancelParsing();
-
- clear();
- m_tokenizer = createTokenizer();
- setParsing(true);
-}
-
-HTMLElement* Document::body()
-{
- Node* de = documentElement();
- if (!de)
- return 0;
-
- // try to prefer a FRAMESET element over BODY
- Node* body = 0;
- for (Node* i = de->firstChild(); i; i = i->nextSibling()) {
- if (i->hasTagName(framesetTag))
- return static_cast<HTMLElement*>(i);
-
- if (i->hasTagName(bodyTag))
- body = i;
- }
- return static_cast<HTMLElement*>(body);
-}
-
-void Document::setBody(PassRefPtr<HTMLElement> newBody, ExceptionCode& ec)
-{
- if (!newBody || !documentElement()) {
- ec = HIERARCHY_REQUEST_ERR;
- return;
- }
-
- HTMLElement* b = body();
- if (!b)
- documentElement()->appendChild(newBody, ec);
- else
- documentElement()->replaceChild(newBody, b, ec);
-}
-
-HTMLHeadElement* Document::head()
-{
- Node* de = documentElement();
- if (!de)
- return 0;
-
- for (Node* e = de->firstChild(); e; e = e->nextSibling())
- if (e->hasTagName(headTag))
- return static_cast<HTMLHeadElement*>(e);
-
- return 0;
-}
-
-void Document::close()
-{
- Frame* frame = this->frame();
- if (frame) {
- // This code calls implicitClose() if all loading has completed.
- FrameLoader* frameLoader = frame->loader();
- frameLoader->endIfNotLoadingMainResource();
- frameLoader->checkCompleted();
- } else {
- // Because we have no frame, we don't know if all loading has completed,
- // so we just call implicitClose() immediately. FIXME: This might fire
- // the load event prematurely <http://bugs.webkit.org/show_bug.cgi?id=14568>.
- implicitClose();
- }
-}
-
-void Document::implicitClose()
-{
- // If we're in the middle of recalcStyle, we need to defer the close until the style information is accurate and all elements are re-attached.
- if (m_inStyleRecalc) {
- m_closeAfterStyleRecalc = true;
- return;
- }
-
- bool wasLocationChangePending = frame() && frame()->loader()->isScheduledLocationChangePending();
- bool doload = !parsing() && m_tokenizer && !m_processingLoadEvent && !wasLocationChangePending;
-
- if (!doload)
- return;
-
- m_processingLoadEvent = true;
-
- m_wellFormed = m_tokenizer && m_tokenizer->wellFormed();
-
- // We have to clear the tokenizer, in case someone document.write()s from the
- // onLoad event handler, as in Radar 3206524.
- delete m_tokenizer;
- m_tokenizer = 0;
-
- // Parser should have picked up all preloads by now
- m_docLoader->clearPreloads();
-
- // Create a body element if we don't already have one. See Radar 3758785.
- if (!this->body() && isHTMLDocument()) {
- if (Node* documentElement = this->documentElement()) {
- ExceptionCode ec = 0;
- documentElement->appendChild(new HTMLBodyElement(this), ec);
- ASSERT(!ec);
- }
- }
-
- // FIXME: We kick off the icon loader when the Document is done parsing.
- // There are earlier opportunities we could start it:
- // -When the <head> finishes parsing
- // -When any new HTMLLinkElement is inserted into the document
- // But those add a dynamic component to the favicon that has UI
- // ramifications, and we need to decide what is the Right Thing To Do(tm)
- Frame* f = frame();
- if (f)
- f->loader()->startIconLoader();
-
- // Resume the animations (or start them)
- if (f)
- f->animation()->resumeAnimations(this);
-
- dispatchImageLoadEventsNow();
- this->dispatchWindowEvent(loadEvent, false, false);
- if (f)
- f->loader()->handledOnloadEvents();
-#ifdef INSTRUMENT_LAYOUT_SCHEDULING
- if (!ownerElement())
- printf("onload fired at %d\n", elapsedTime());
-#endif
-
- m_processingLoadEvent = false;
-
- // An event handler may have removed the frame
- if (!frame())
- return;
-
- // Make sure both the initial layout and reflow happen after the onload
- // fires. This will improve onload scores, and other browsers do it.
- // If they wanna cheat, we can too. -dwh
-
- if (frame()->loader()->isScheduledLocationChangePending() && elapsedTime() < cLayoutScheduleThreshold) {
- // Just bail out. Before or during the onload we were shifted to another page.
- // The old i-Bench suite does this. When this happens don't bother painting or laying out.
- view()->unscheduleRelayout();
- return;
- }
-
- frame()->loader()->checkCallImplicitClose();
-
- // Now do our painting/layout, but only if we aren't in a subframe or if we're in a subframe
- // that has been sized already. Otherwise, our view size would be incorrect, so doing any
- // layout/painting now would be pointless.
- if (!ownerElement() || (ownerElement()->renderer() && !ownerElement()->renderer()->needsLayout())) {
- updateRendering();
-
- // Always do a layout after loading if needed.
- if (view() && renderer() && (!renderer()->firstChild() || renderer()->needsLayout()))
- view()->layout();
-
- // Paint immediately after the document is ready. We do this to ensure that any timers set by the
- // onload don't have a chance to fire before we would have painted. To avoid over-flushing we only
- // worry about this for the top-level document.
-#if !PLATFORM(MAC)
- // FIXME: This causes a timing issue with the dispatchDidFinishLoad delegate callback.
- // See <rdar://problem/5092361>
- if (view() && !ownerElement())
- view()->update();
-#endif
- }
-
-#if PLATFORM(MAC)
- if (renderer() && AXObjectCache::accessibilityEnabled())
- axObjectCache()->postNotificationToElement(renderer(), "AXLoadComplete");
-#endif
-
-#if ENABLE(SVG)
- // FIXME: Officially, time 0 is when the outermost <svg> receives its
- // SVGLoad event, but we don't implement those yet. This is close enough
- // for now. In some cases we should have fired earlier.
- if (svgExtensions())
- accessSVGExtensions()->startAnimations();
-#endif
-}
-
-void Document::setParsing(bool b)
-{
- m_bParsing = b;
- if (!m_bParsing && view())
- view()->scheduleRelayout();
-
-#ifdef INSTRUMENT_LAYOUT_SCHEDULING
- if (!ownerElement() && !m_bParsing)
- printf("Parsing finished at %d\n", elapsedTime());
-#endif
-}
-
-bool Document::shouldScheduleLayout()
-{
- // We can update layout if:
- // (a) we actually need a layout
- // (b) our stylesheets are all loaded
- // (c) we have a <body>
- return (renderer() && renderer()->needsLayout() && haveStylesheetsLoaded() &&
- documentElement() && documentElement()->renderer() &&
- (!documentElement()->hasTagName(htmlTag) || body()));
-}
-
-int Document::minimumLayoutDelay()
-{
- if (m_overMinimumLayoutThreshold)
- return 0;
-
- int elapsed = elapsedTime();
- m_overMinimumLayoutThreshold = elapsed > cLayoutScheduleThreshold;
-
- // We'll want to schedule the timer to fire at the minimum layout threshold.
- return max(0, cLayoutScheduleThreshold - elapsed);
-}
-
-int Document::elapsedTime() const
-{
- return static_cast<int>((currentTime() - m_startTime) * 1000);
-}
-
-void Document::write(const String& text, Document* ownerDocument)
-{
-#ifdef INSTRUMENT_LAYOUT_SCHEDULING
- if (!ownerElement())
- printf("Beginning a document.write at %d\n", elapsedTime());
-#endif
-
- if (!m_tokenizer) {
- open(ownerDocument);
- ASSERT(m_tokenizer);
- if (!m_tokenizer)
- return;
- write("<html>", ownerDocument);
- }
- m_tokenizer->write(text, false);
-
-#ifdef INSTRUMENT_LAYOUT_SCHEDULING
- if (!ownerElement())
- printf("Ending a document.write at %d\n", elapsedTime());
-#endif
-}
-
-void Document::writeln(const String& text, Document* ownerDocument)
-{
- write(text, ownerDocument);
- write("\n", ownerDocument);
-}
-
-void Document::finishParsing()
-{
-#ifdef INSTRUMENT_LAYOUT_SCHEDULING
- if (!ownerElement())
- printf("Received all data at %d\n", elapsedTime());
-#endif
-
- // Let the tokenizer go through as much data as it can. There will be three possible outcomes after
- // finish() is called:
- // (1) All remaining data is parsed, document isn't loaded yet
- // (2) All remaining data is parsed, document is loaded, tokenizer gets deleted
- // (3) Data is still remaining to be parsed.
- if (m_tokenizer)
- m_tokenizer->finish();
-}
-
-void Document::clear()
-{
- delete m_tokenizer;
- m_tokenizer = 0;
-
- removeChildren();
-
- m_windowEventListeners.clear();
-}
-
-void Document::setURL(const KURL& url)
-{
- const KURL& newURL = url.isEmpty() ? blankURL() : url;
- if (newURL == m_url)
- return;
-
- m_url = newURL;
- m_documentURI = m_url.string();
- updateBaseURL();
-}
-
-void Document::setBaseElementURL(const KURL& baseElementURL)
-{
- m_baseElementURL = baseElementURL;
- updateBaseURL();
-}
-
-void Document::updateBaseURL()
-{
- m_baseURL = m_baseElementURL.isEmpty() ? KURL(documentURI()) : m_baseElementURL;
- if (!m_baseURL.isValid())
- m_baseURL = KURL();
-
- if (m_elemSheet)
- m_elemSheet->setHref(m_baseURL.string());
- if (m_mappedElementSheet)
- m_mappedElementSheet->setHref(m_baseURL.string());
-}
-
-void Document::setCSSStyleSheet(const String& url, const String& charset, const CachedCSSStyleSheet* sheet)
-{
- m_sheet = CSSStyleSheet::create(this, url, charset);
- m_sheet->parseString(sheet->sheetText());
-
- updateStyleSelector();
-}
-
-#if FRAME_LOADS_USER_STYLESHEET
-void Document::setUserStyleSheet(const String& sheet)
-{
- if (m_usersheet != sheet) {
- m_usersheet = sheet;
- updateStyleSelector();
- }
-}
-#endif
-
-String Document::userStyleSheet() const
-{
-#if FRAME_LOADS_USER_STYLESHEET
- return m_usersheet;
-#else
- Page* page = this->page();
- if (!page)
- return String();
- return page->userStyleSheet();
-#endif
-}
-
-CSSStyleSheet* Document::elementSheet()
-{
- if (!m_elemSheet)
- m_elemSheet = CSSStyleSheet::create(this, m_baseURL.string());
- return m_elemSheet.get();
-}
-
-CSSStyleSheet* Document::mappedElementSheet()
-{
- if (!m_mappedElementSheet)
- m_mappedElementSheet = CSSStyleSheet::create(this, m_baseURL.string());
- return m_mappedElementSheet.get();
-}
-
-static Node* nextNodeWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
-{
- // Search is inclusive of start
- for (Node* n = start; n; n = n->traverseNextNode())
- if (n->isKeyboardFocusable(event) && n->tabIndex() == tabIndex)
- return n;
-
- return 0;
-}
-
-static Node* previousNodeWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
-{
- // Search is inclusive of start
- for (Node* n = start; n; n = n->traversePreviousNode())
- if (n->isKeyboardFocusable(event) && n->tabIndex() == tabIndex)
- return n;
-
- return 0;
-}
-
-static Node* nextNodeWithGreaterTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
-{
- // Search is inclusive of start
- int winningTabIndex = SHRT_MAX + 1;
- Node* winner = 0;
- for (Node* n = start; n; n = n->traverseNextNode())
- if (n->isKeyboardFocusable(event) && n->tabIndex() > tabIndex && n->tabIndex() < winningTabIndex) {
- winner = n;
- winningTabIndex = n->tabIndex();
- }
-
- return winner;
-}
-
-static Node* previousNodeWithLowerTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
-{
- // Search is inclusive of start
- int winningTabIndex = 0;
- Node* winner = 0;
- for (Node* n = start; n; n = n->traversePreviousNode())
- if (n->isKeyboardFocusable(event) && n->tabIndex() < tabIndex && n->tabIndex() > winningTabIndex) {
- winner = n;
- winningTabIndex = n->tabIndex();
- }
-
- return winner;
-}
-
-Node* Document::nextFocusableNode(Node* start, KeyboardEvent* event)
-{
- if (start) {
- // If a node is excluded from the normal tabbing cycle, the next focusable node is determined by tree order
- if (start->tabIndex() < 0) {
- for (Node* n = start->traverseNextNode(); n; n = n->traverseNextNode())
- if (n->isKeyboardFocusable(event) && n->tabIndex() >= 0)
- return n;
- }
-
- // First try to find a node with the same tabindex as start that comes after start in the document.
- if (Node* winner = nextNodeWithExactTabIndex(start->traverseNextNode(), start->tabIndex(), event))
- return winner;
-
- if (start->tabIndex() == 0)
- // We've reached the last node in the document with a tabindex of 0. This is the end of the tabbing order.
- return 0;
- }
-
- // Look for the first node in the document that:
- // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and
- // 2) comes first in the document, if there's a tie.
- if (Node* winner = nextNodeWithGreaterTabIndex(this, start ? start->tabIndex() : 0, event))
- return winner;
-
- // There are no nodes with a tabindex greater than start's tabindex,
- // so find the first node with a tabindex of 0.
- return nextNodeWithExactTabIndex(this, 0, event);
-}
-
-Node* Document::previousFocusableNode(Node* start, KeyboardEvent* event)
-{
- Node* last;
- for (last = this; last->lastChild(); last = last->lastChild())
- ; // Empty loop.
-
- // First try to find the last node in the document that comes before start and has the same tabindex as start.
- // If start is null, find the last node in the document with a tabindex of 0.
- Node* startingNode;
- int startingTabIndex;
- if (start) {
- startingNode = start->traversePreviousNode();
- startingTabIndex = start->tabIndex();
- } else {
- startingNode = last;
- startingTabIndex = 0;
- }
-
- // However, if a node is excluded from the normal tabbing cycle, the previous focusable node is determined by tree order
- if (startingTabIndex < 0) {
- for (Node* n = startingNode; n; n = n->traversePreviousNode())
- if (n->isKeyboardFocusable(event) && n->tabIndex() >= 0)
- return n;
- }
-
- if (Node* winner = previousNodeWithExactTabIndex(startingNode, startingTabIndex, event))
- return winner;
-
- // There are no nodes before start with the same tabindex as start, so look for a node that:
- // 1) has the highest non-zero tabindex (that is less than start's tabindex), and
- // 2) comes last in the document, if there's a tie.
- startingTabIndex = (start && start->tabIndex()) ? start->tabIndex() : SHRT_MAX;
- return previousNodeWithLowerTabIndex(last, startingTabIndex, event);
-}
-
-int Document::nodeAbsIndex(Node *node)
-{
- ASSERT(node->document() == this);
-
- int absIndex = 0;
- for (Node *n = node; n && n != this; n = n->traversePreviousNode())
- absIndex++;
- return absIndex;
-}
-
-Node *Document::nodeWithAbsIndex(int absIndex)
-{
- Node *n = this;
- for (int i = 0; n && (i < absIndex); i++) {
- n = n->traverseNextNode();
- }
- return n;
-}
-
-void Document::processHttpEquiv(const String &equiv, const String &content)
-{
- ASSERT(!equiv.isNull() && !content.isNull());
-
- Frame *frame = this->frame();
-
- if (equalIgnoringCase(equiv, "default-style")) {
- // The preferred style set has been overridden as per section
- // 14.3.2 of the HTML4.0 specification. We need to update the
- // sheet used variable and then update our style selector.
- // For more info, see the test at:
- // http://www.hixie.ch/tests/evil/css/import/main/preferred.html
- // -dwh
- m_selectedStylesheetSet = content;
- m_preferredStylesheetSet = content;
- updateStyleSelector();
- } else if (equalIgnoringCase(equiv, "refresh")) {
- double delay;
- String url;
- if (frame && parseHTTPRefresh(content, true, delay, url)) {
- if (url.isEmpty())
- url = frame->loader()->url().string();
- else
- url = completeURL(url).string();
- frame->loader()->scheduleHTTPRedirection(delay, url);
- }
- } else if (equalIgnoringCase(equiv, "set-cookie")) {
- // FIXME: make setCookie work on XML documents too; e.g. in case of <html:meta .....>
- if (isHTMLDocument())
- static_cast<HTMLDocument*>(this)->setCookie(content);
- } else if (equalIgnoringCase(equiv, "content-language"))
- setContentLanguage(content);
- else if (equalIgnoringCase(equiv, "x-dns-prefetch-control"))
- setDNSPrefetchControl(content);
-}
-
-MouseEventWithHitTestResults Document::prepareMouseEvent(const HitTestRequest& request, const IntPoint& documentPoint, const PlatformMouseEvent& event)
-{
- ASSERT(!renderer() || renderer()->isRenderView());
-
- if (!renderer())
- return MouseEventWithHitTestResults(event, HitTestResult(IntPoint()));
-
- HitTestResult result(documentPoint);
- renderer()->layer()->hitTest(request, result);
-
- if (!request.readonly)
- updateRendering();
-
- return MouseEventWithHitTestResults(event, result);
-}
-
-// DOM Section 1.1.1
-bool Document::childTypeAllowed(NodeType type)
-{
- switch (type) {
- case ATTRIBUTE_NODE:
- case CDATA_SECTION_NODE:
- case DOCUMENT_FRAGMENT_NODE:
- case DOCUMENT_NODE:
- case ENTITY_NODE:
- case ENTITY_REFERENCE_NODE:
- case NOTATION_NODE:
- case TEXT_NODE:
- case XPATH_NAMESPACE_NODE:
- return false;
- case COMMENT_NODE:
- case PROCESSING_INSTRUCTION_NODE:
- return true;
- case DOCUMENT_TYPE_NODE:
- case ELEMENT_NODE:
- // Documents may contain no more than one of each of these.
- // (One Element and one DocumentType.)
- for (Node* c = firstChild(); c; c = c->nextSibling())
- if (c->nodeType() == type)
- return false;
- return true;
- }
- return false;
-}
-
-bool Document::canReplaceChild(Node* newChild, Node* oldChild)
-{
- if (!oldChild)
- // ContainerNode::replaceChild will raise a NOT_FOUND_ERR.
- return true;
-
- if (oldChild->nodeType() == newChild->nodeType())
- return true;
-
- int numDoctypes = 0;
- int numElements = 0;
-
- // First, check how many doctypes and elements we have, not counting
- // the child we're about to remove.
- for (Node* c = firstChild(); c; c = c->nextSibling()) {
- if (c == oldChild)
- continue;
-
- switch (c->nodeType()) {
- case DOCUMENT_TYPE_NODE:
- numDoctypes++;
- break;
- case ELEMENT_NODE:
- numElements++;
- break;
- default:
- break;
- }
- }
-
- // Then, see how many doctypes and elements might be added by the new child.
- if (newChild->nodeType() == DOCUMENT_FRAGMENT_NODE) {
- for (Node* c = firstChild(); c; c = c->nextSibling()) {
- switch (c->nodeType()) {
- case ATTRIBUTE_NODE:
- case CDATA_SECTION_NODE:
- case DOCUMENT_FRAGMENT_NODE:
- case DOCUMENT_NODE:
- case ENTITY_NODE:
- case ENTITY_REFERENCE_NODE:
- case NOTATION_NODE:
- case TEXT_NODE:
- case XPATH_NAMESPACE_NODE:
- return false;
- case COMMENT_NODE:
- case PROCESSING_INSTRUCTION_NODE:
- break;
- case DOCUMENT_TYPE_NODE:
- numDoctypes++;
- break;
- case ELEMENT_NODE:
- numElements++;
- break;
- }
- }
- } else {
- switch (newChild->nodeType()) {
- case ATTRIBUTE_NODE:
- case CDATA_SECTION_NODE:
- case DOCUMENT_FRAGMENT_NODE:
- case DOCUMENT_NODE:
- case ENTITY_NODE:
- case ENTITY_REFERENCE_NODE:
- case NOTATION_NODE:
- case TEXT_NODE:
- case XPATH_NAMESPACE_NODE:
- return false;
- case COMMENT_NODE:
- case PROCESSING_INSTRUCTION_NODE:
- return true;
- case DOCUMENT_TYPE_NODE:
- numDoctypes++;
- break;
- case ELEMENT_NODE:
- numElements++;
- break;
- }
- }
-
- if (numElements > 1 || numDoctypes > 1)
- return false;
-
- return true;
-}
-
-PassRefPtr<Node> Document::cloneNode(bool /*deep*/)
-{
- // Spec says cloning Document nodes is "implementation dependent"
- // so we do not support it...
- return 0;
-}
-
-StyleSheetList* Document::styleSheets()
-{
- return m_styleSheets.get();
-}
-
-String Document::preferredStylesheetSet() const
-{
- return m_preferredStylesheetSet;
-}
-
-String Document::selectedStylesheetSet() const
-{
- return m_selectedStylesheetSet;
-}
-
-void Document::setSelectedStylesheetSet(const String& aString)
-{
- m_selectedStylesheetSet = aString;
- updateStyleSelector();
- if (renderer())
- renderer()->repaint();
-}
-
-// This method is called whenever a top-level stylesheet has finished loading.
-void Document::removePendingSheet()
-{
- // Make sure we knew this sheet was pending, and that our count isn't out of sync.
- ASSERT(m_pendingStylesheets > 0);
-
- m_pendingStylesheets--;
-
-#ifdef INSTRUMENT_LAYOUT_SCHEDULING
- if (!ownerElement())
- printf("Stylesheet loaded at time %d. %d stylesheets still remain.\n", elapsedTime(), m_pendingStylesheets);
-#endif
-
- updateStyleSelector();
-
- if (!m_pendingStylesheets && m_tokenizer)
- m_tokenizer->executeScriptsWaitingForStylesheets();
-
- if (!m_pendingStylesheets && m_gotoAnchorNeededAfterStylesheetsLoad && m_frame)
- m_frame->loader()->gotoAnchor();
-}
-
-void Document::updateStyleSelector()
-{
- // Don't bother updating, since we haven't loaded all our style info yet
- // and haven't calculated the style selector for the first time.
- if (!m_didCalculateStyleSelector && !haveStylesheetsLoaded())
- return;
-
- if (didLayoutWithPendingStylesheets() && m_pendingStylesheets <= 0) {
- m_pendingSheetLayout = IgnoreLayoutWithPendingSheets;
- if (renderer())
- renderer()->repaint();
- }
-
-#ifdef INSTRUMENT_LAYOUT_SCHEDULING
- if (!ownerElement())
- printf("Beginning update of style selector at time %d.\n", elapsedTime());
-#endif
-
- recalcStyleSelector();
- recalcStyle(Force);
-
-#ifdef INSTRUMENT_LAYOUT_SCHEDULING
- if (!ownerElement())
- printf("Finished update of style selector at time %d\n", elapsedTime());
-#endif
-
- if (renderer()) {
- renderer()->setNeedsLayoutAndPrefWidthsRecalc();
- if (view())
- view()->scheduleRelayout();
- }
-}
-
-void Document::addStyleSheetCandidateNode(Node* node, bool createdByParser)
-{
- // Until the <body> exists, we have no choice but to compare document positions,
- // since styles outside of the body and head continue to be shunted into the head
- // (and thus can shift to end up before dynamically added DOM content that is also
- // outside the body).
- if ((createdByParser && body()) || m_styleSheetCandidateNodes.isEmpty()) {
- m_styleSheetCandidateNodes.add(node);
- return;
- }
-
- // Determine an appropriate insertion point.
- ListHashSet<Node*>::iterator begin = m_styleSheetCandidateNodes.begin();
- ListHashSet<Node*>::iterator end = m_styleSheetCandidateNodes.end();
- ListHashSet<Node*>::iterator it = end;
- Node* followingNode = 0;
- do {
- --it;
- Node* n = *it;
- unsigned short position = n->compareDocumentPosition(node);
- if (position == DOCUMENT_POSITION_FOLLOWING) {
- m_styleSheetCandidateNodes.insertBefore(followingNode, node);
- return;
- }
- followingNode = n;
- } while (it != begin);
-
- m_styleSheetCandidateNodes.insertBefore(followingNode, node);
-}
-
-void Document::removeStyleSheetCandidateNode(Node* node)
-{
- m_styleSheetCandidateNodes.remove(node);
-}
-
-void Document::recalcStyleSelector()
-{
- if (!renderer() || !attached())
- return;
-
- StyleSheetVector sheets;
-
- bool matchAuthorAndUserStyles = true;
- if (Settings* settings = this->settings())
- matchAuthorAndUserStyles = settings->authorAndUserStylesEnabled();
-
- ListHashSet<Node*>::iterator begin = m_styleSheetCandidateNodes.begin();
- ListHashSet<Node*>::iterator end = m_styleSheetCandidateNodes.end();
- if (!matchAuthorAndUserStyles)
- end = begin;
- for (ListHashSet<Node*>::iterator it = begin; it != end; ++it) {
- Node* n = *it;
-
- StyleSheet* sheet = 0;
-
- if (n->nodeType() == PROCESSING_INSTRUCTION_NODE) {
- // Processing instruction (XML documents only)
- ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(n);
- sheet = pi->sheet();
-#if ENABLE(XSLT)
- // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806>
- if (pi->isXSL() && !transformSourceDocument()) {
- // Don't apply XSL transforms until loading is finished.
- if (!parsing())
- applyXSLTransform(pi);
- return;
- }
-#endif
- if (!sheet && !pi->localHref().isEmpty()) {
- // Processing instruction with reference to an element in this document - e.g.
- // <?xml-stylesheet href="#mystyle">, with the element
- // <foo id="mystyle">heading { color: red; }</foo> at some location in
- // the document
- Element* elem = getElementById(pi->localHref().impl());
- if (elem) {
- String sheetText("");
- for (Node* c = elem->firstChild(); c; c = c->nextSibling()) {
- if (c->nodeType() == TEXT_NODE || c->nodeType() == CDATA_SECTION_NODE)
- sheetText += c->nodeValue();
- }
-
- RefPtr<CSSStyleSheet> cssSheet = CSSStyleSheet::create(this);
- cssSheet->parseString(sheetText);
- pi->setCSSStyleSheet(cssSheet);
- sheet = cssSheet.get();
- }
- }
- } else if (n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag))
-#if ENABLE(SVG)
- || (n->isSVGElement() && n->hasTagName(SVGNames::styleTag))
-#endif
- ) {
- Element* e = static_cast<Element*>(n);
- AtomicString title = e->getAttribute(titleAttr);
- bool enabledViaScript = false;
- if (e->hasLocalName(linkTag)) {
- // <LINK> element
- HTMLLinkElement* l = static_cast<HTMLLinkElement*>(n);
- if (l->isDisabled())
- continue;
- enabledViaScript = l->isEnabledViaScript();
- if (l->isLoading()) {
- // it is loading but we should still decide which style sheet set to use
- if (!enabledViaScript && !title.isEmpty() && m_preferredStylesheetSet.isEmpty()) {
- const AtomicString& rel = e->getAttribute(relAttr);
- if (!rel.contains("alternate")) {
- m_preferredStylesheetSet = title;
- m_selectedStylesheetSet = title;
- }
- }
- continue;
- }
- if (!l->sheet())
- title = nullAtom;
- }
-
- // Get the current preferred styleset. This is the
- // set of sheets that will be enabled.
-#if ENABLE(SVG)
- if (n->isSVGElement() && n->hasTagName(SVGNames::styleTag))
- sheet = static_cast<SVGStyleElement*>(n)->sheet();
- else
-#endif
- if (e->hasLocalName(linkTag))
- sheet = static_cast<HTMLLinkElement*>(n)->sheet();
- else
- // <STYLE> element
- sheet = static_cast<HTMLStyleElement*>(n)->sheet();
-
- // Check to see if this sheet belongs to a styleset
- // (thus making it PREFERRED or ALTERNATE rather than
- // PERSISTENT).
- if (!enabledViaScript && !title.isEmpty()) {
- // Yes, we have a title.
- if (m_preferredStylesheetSet.isEmpty()) {
- // No preferred set has been established. If
- // we are NOT an alternate sheet, then establish
- // us as the preferred set. Otherwise, just ignore
- // this sheet.
- AtomicString rel = e->getAttribute(relAttr);
- if (e->hasLocalName(styleTag) || !rel.contains("alternate"))
- m_preferredStylesheetSet = m_selectedStylesheetSet = title;
- }
-
- if (title != m_preferredStylesheetSet)
- sheet = 0;
- }
- }
-
- if (sheet)
- sheets.append(sheet);
- }
-
- m_styleSheets->swap(sheets);
-
- // Create a new style selector
- delete m_styleSelector;
- m_styleSelector = new CSSStyleSelector(this, userStyleSheet(), m_styleSheets.get(), m_mappedElementSheet.get(), !inCompatMode(), matchAuthorAndUserStyles);
- m_didCalculateStyleSelector = true;
-}
-
-void Document::setHoverNode(PassRefPtr<Node> newHoverNode)
-{
- m_hoverNode = newHoverNode;
-}
-
-void Document::setActiveNode(PassRefPtr<Node> newActiveNode)
-{
- m_activeNode = newActiveNode;
-}
-
-void Document::focusedNodeRemoved()
-{
- setFocusedNode(0);
-}
-
-void Document::removeFocusedNodeOfSubtree(Node* node, bool amongChildrenOnly)
-{
- if (!m_focusedNode || this->inPageCache()) // If the document is in the page cache, then we don't need to clear out the focused node.
- return;
-
- bool nodeInSubtree = false;
- if (amongChildrenOnly)
- nodeInSubtree = m_focusedNode->isDescendantOf(node);
- else
- nodeInSubtree = (m_focusedNode == node) || m_focusedNode->isDescendantOf(node);
-
- if (nodeInSubtree)
- document()->focusedNodeRemoved();
-}
-
-void Document::hoveredNodeDetached(Node* node)
-{
- if (!m_hoverNode || (node != m_hoverNode && (!m_hoverNode->isTextNode() || node != m_hoverNode->parent())))
- return;
-
- m_hoverNode = node->parent();
- while (m_hoverNode && !m_hoverNode->renderer())
- m_hoverNode = m_hoverNode->parent();
- if (frame())
- frame()->eventHandler()->scheduleHoverStateUpdate();
-}
-
-void Document::activeChainNodeDetached(Node* node)
-{
- if (!m_activeNode || (node != m_activeNode && (!m_activeNode->isTextNode() || node != m_activeNode->parent())))
- return;
-
- m_activeNode = node->parent();
- while (m_activeNode && !m_activeNode->renderer())
- m_activeNode = m_activeNode->parent();
-}
-
-#if ENABLE(DASHBOARD_SUPPORT)
-const Vector<DashboardRegionValue>& Document::dashboardRegions() const
-{
- return m_dashboardRegions;
-}
-
-void Document::setDashboardRegions(const Vector<DashboardRegionValue>& regions)
-{
- m_dashboardRegions = regions;
- setDashboardRegionsDirty(false);
-}
-#endif
-
-bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode)
-{
- // Make sure newFocusedNode is actually in this document
- if (newFocusedNode && (newFocusedNode->document() != this))
- return true;
-
- if (m_focusedNode == newFocusedNode)
- return true;
-
- if (m_inPageCache)
- return false;
-
- bool focusChangeBlocked = false;
- RefPtr<Node> oldFocusedNode = m_focusedNode;
- m_focusedNode = 0;
-
- // Remove focus from the existing focus node (if any)
- if (oldFocusedNode && !oldFocusedNode->m_inDetach) {
- if (oldFocusedNode->active())
- oldFocusedNode->setActive(false);
-
- oldFocusedNode->setFocus(false);
-
- // Dispatch a change event for text fields or textareas that have been edited
- RenderObject *r = static_cast<RenderObject*>(oldFocusedNode.get()->renderer());
- if (r && (r->isTextArea() || r->isTextField()) && r->isEdited()) {
- EventTargetNodeCast(oldFocusedNode.get())->dispatchHTMLEvent(changeEvent, true, false);
- if ((r = static_cast<RenderObject*>(oldFocusedNode.get()->renderer())))
- r->setEdited(false);
- }
-
- // Dispatch the blur event and let the node do any other blur related activities (important for text fields)
- EventTargetNodeCast(oldFocusedNode.get())->dispatchBlurEvent();
-
- if (m_focusedNode) {
- // handler shifted focus
- focusChangeBlocked = true;
- newFocusedNode = 0;
- }
- EventTargetNodeCast(oldFocusedNode.get())->dispatchUIEvent(DOMFocusOutEvent);
- if (m_focusedNode) {
- // handler shifted focus
- focusChangeBlocked = true;
- newFocusedNode = 0;
- }
- if ((oldFocusedNode.get() == this) && oldFocusedNode->hasOneRef())
- return true;
-
- if (oldFocusedNode.get() == oldFocusedNode->rootEditableElement())
- frame()->editor()->didEndEditing();
- }
-
- if (newFocusedNode) {
- if (newFocusedNode == newFocusedNode->rootEditableElement() && !acceptsEditingFocus(newFocusedNode.get())) {
- // delegate blocks focus change
- focusChangeBlocked = true;
- goto SetFocusedNodeDone;
- }
- // Set focus on the new node
- m_focusedNode = newFocusedNode.get();
-
- // Dispatch the focus event and let the node do any other focus related activities (important for text fields)
- EventTargetNodeCast(m_focusedNode.get())->dispatchFocusEvent();
-
- if (m_focusedNode != newFocusedNode) {
- // handler shifted focus
- focusChangeBlocked = true;
- goto SetFocusedNodeDone;
- }
- EventTargetNodeCast(m_focusedNode.get())->dispatchUIEvent(DOMFocusInEvent);
- if (m_focusedNode != newFocusedNode) {
- // handler shifted focus
- focusChangeBlocked = true;
- goto SetFocusedNodeDone;
- }
- m_focusedNode->setFocus();
-
- if (m_focusedNode.get() == m_focusedNode->rootEditableElement())
- frame()->editor()->didBeginEditing();
-
- // eww, I suck. set the qt focus correctly
- // ### find a better place in the code for this
- if (view()) {
- Widget *focusWidget = widgetForNode(m_focusedNode.get());
- if (focusWidget) {
- // Make sure a widget has the right size before giving it focus.
- // Otherwise, we are testing edge cases of the Widget code.
- // Specifically, in WebCore this does not work well for text fields.
- updateLayout();
- // Re-get the widget in case updating the layout changed things.
- focusWidget = widgetForNode(m_focusedNode.get());
- }
- if (focusWidget)
- focusWidget->setFocus();
- else
- view()->setFocus();
- }
- }
-
-#if PLATFORM(MAC) && !PLATFORM(CHROMIUM)
- if (!focusChangeBlocked && m_focusedNode && AXObjectCache::accessibilityEnabled())
- axObjectCache()->handleFocusedUIElementChanged();
-#endif
-
-SetFocusedNodeDone:
- updateRendering();
- return !focusChangeBlocked;
- }
-
-void Document::setCSSTarget(Node* n)
-{
- if (m_cssTarget)
- m_cssTarget->setChanged();
- m_cssTarget = n;
- if (n)
- n->setChanged();
-}
-
-Node* Document::getCSSTarget() const
-{
- return m_cssTarget;
-}
-
-void Document::attachNodeIterator(NodeIterator *ni)
-{
- m_nodeIterators.add(ni);
-}
-
-void Document::detachNodeIterator(NodeIterator *ni)
-{
- m_nodeIterators.remove(ni);
-}
-
-void Document::nodeChildrenChanged(ContainerNode* container)
-{
- if (!page() || !page()->settings()->rangeMutationDisabledForOldAppleMail()) {
- HashSet<Range*>::const_iterator end = m_ranges.end();
- for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
- (*it)->nodeChildrenChanged(container);
- }
-}
-
-void Document::nodeWillBeRemoved(Node* n)
-{
- HashSet<NodeIterator*>::const_iterator nodeIteratorsEnd = m_nodeIterators.end();
- for (HashSet<NodeIterator*>::const_iterator it = m_nodeIterators.begin(); it != nodeIteratorsEnd; ++it)
- (*it)->nodeWillBeRemoved(n);
-
- if (!page() || !page()->settings()->rangeMutationDisabledForOldAppleMail()) {
- HashSet<Range*>::const_iterator rangesEnd = m_ranges.end();
- for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != rangesEnd; ++it)
- (*it)->nodeWillBeRemoved(n);
- }
-
- if (Frame* frame = this->frame()) {
- frame->selection()->nodeWillBeRemoved(n);
- frame->dragCaretController()->nodeWillBeRemoved(n);
- }
-}
-
-void Document::textInserted(Node* text, unsigned offset, unsigned length)
-{
- if (!page() || !page()->settings()->rangeMutationDisabledForOldAppleMail()) {
- HashSet<Range*>::const_iterator end = m_ranges.end();
- for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
- (*it)->textInserted(text, offset, length);
- }
-
- // Update the markers for spelling and grammar checking.
- shiftMarkers(text, offset, length);
-}
-
-void Document::textRemoved(Node* text, unsigned offset, unsigned length)
-{
- if (!page() || !page()->settings()->rangeMutationDisabledForOldAppleMail()) {
- HashSet<Range*>::const_iterator end = m_ranges.end();
- for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
- (*it)->textRemoved(text, offset, length);
- }
-
- // Update the markers for spelling and grammar checking.
- removeMarkers(text, offset, length);
- shiftMarkers(text, offset + length, 0 - length);
-}
-
-void Document::textNodesMerged(Text* oldNode, unsigned offset)
-{
- if (!page() || !page()->settings()->rangeMutationDisabledForOldAppleMail()) {
- NodeWithIndex oldNodeWithIndex(oldNode);
- HashSet<Range*>::const_iterator end = m_ranges.end();
- for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
- (*it)->textNodesMerged(oldNodeWithIndex, offset);
- }
-
- // FIXME: This should update markers for spelling and grammar checking.
-}
-
-void Document::textNodeSplit(Text* oldNode)
-{
- if (!page() || !page()->settings()->rangeMutationDisabledForOldAppleMail()) {
- HashSet<Range*>::const_iterator end = m_ranges.end();
- for (HashSet<Range*>::const_iterator it = m_ranges.begin(); it != end; ++it)
- (*it)->textNodeSplit(oldNode);
- }
-
- // FIXME: This should update markers for spelling and grammar checking.
-}
-
-// FIXME: eventually, this should return a DOMWindow stored in the document.
-DOMWindow* Document::domWindow() const
-{
- if (!frame())
- return 0;
- return frame()->domWindow();
-}
-
-PassRefPtr<Event> Document::createEvent(const String& eventType, ExceptionCode& ec)
-{
- if (eventType == "UIEvents" || eventType == "UIEvent")
- return UIEvent::create();
- if (eventType == "MouseEvents" || eventType == "MouseEvent")
- return MouseEvent::create();
- if (eventType == "MutationEvents" || eventType == "MutationEvent")
- return MutationEvent::create();
- if (eventType == "KeyboardEvents" || eventType == "KeyboardEvent")
- return KeyboardEvent::create();
- if (eventType == "HTMLEvents" || eventType == "Event" || eventType == "Events")
- return Event::create();
- if (eventType == "ProgressEvent")
- return ProgressEvent::create();
- if (eventType == "TextEvent")
- return TextEvent::create();
- if (eventType == "OverflowEvent")
- return OverflowEvent::create();
- if (eventType == "WheelEvent")
- return WheelEvent::create();
-#if ENABLE(SVG)
- if (eventType == "SVGEvents")
- return Event::create();
- if (eventType == "SVGZoomEvents")
- return SVGZoomEvent::create();
-#endif
- if (eventType == "MessageEvent")
- return MessageEvent::create();
- ec = NOT_SUPPORTED_ERR;
- return 0;
-}
-
-CSSStyleDeclaration* Document::getOverrideStyle(Element*, const String&)
-{
- return 0;
-}
-
-void Document::handleWindowEvent(Event *evt, bool useCapture)
-{
- if (m_windowEventListeners.isEmpty())
- return;
-
- // if any html event listeners are registered on the window, then dispatch them here
- RegisteredEventListenerList listenersCopy = m_windowEventListeners;
- RegisteredEventListenerList::iterator it = listenersCopy.begin();
-
- for (; it != listenersCopy.end(); ++it)
- if ((*it)->eventType() == evt->type() && (*it)->useCapture() == useCapture && !(*it)->removed())
- (*it)->listener()->handleEvent(evt, true);
-}
-
-void Document::setHTMLWindowEventListener(const AtomicString &eventType, PassRefPtr<EventListener> listener)
-{
- // If we already have it we don't want removeWindowEventListener to delete it
- removeHTMLWindowEventListener(eventType);
- if (listener)
- addWindowEventListener(eventType, listener, false);
-}
-
-EventListener *Document::getHTMLWindowEventListener(const AtomicString& eventType)
-{
- RegisteredEventListenerList::iterator it = m_windowEventListeners.begin();
- for (; it != m_windowEventListeners.end(); ++it) {
- if ((*it)->eventType() == eventType && (*it)->listener()->isHTMLEventListener())
- return (*it)->listener();
- }
- return 0;
-}
-
-void Document::removeHTMLWindowEventListener(const AtomicString& eventType)
-{
- RegisteredEventListenerList::iterator it = m_windowEventListeners.begin();
- for (; it != m_windowEventListeners.end(); ++it) {
- if ((*it)->eventType() == eventType && (*it)->listener()->isHTMLEventListener()) {
- if (eventType == unloadEvent)
- removePendingFrameUnloadEventCount();
- else if (eventType == beforeunloadEvent)
- removePendingFrameBeforeUnloadEventCount();
- m_windowEventListeners.remove(it);
- return;
- }
- }
-}
-
-void Document::addWindowEventListener(const AtomicString &eventType, PassRefPtr<EventListener> listener, bool useCapture)
-{
- if (eventType == unloadEvent)
- addPendingFrameUnloadEventCount();
- else if (eventType == beforeunloadEvent)
- addPendingFrameBeforeUnloadEventCount();
- // Remove existing identical listener set with identical arguments.
- // The DOM 2 spec says that "duplicate instances are discarded" in this case.
- removeWindowEventListener(eventType, listener.get(), useCapture);
- m_windowEventListeners.append(RegisteredEventListener::create(eventType, listener, useCapture));
-}
-
-void Document::removeWindowEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
-{
- RegisteredEventListenerList::iterator it = m_windowEventListeners.begin();
- for (; it != m_windowEventListeners.end(); ++it) {
- RegisteredEventListener& r = **it;
- if (r.eventType() == eventType && r.listener() == listener && r.useCapture() == useCapture) {
- if (eventType == unloadEvent)
- removePendingFrameUnloadEventCount();
- else if (eventType == beforeunloadEvent)
- removePendingFrameBeforeUnloadEventCount();
- m_windowEventListeners.remove(it);
- return;
- }
- }
-}
-
-bool Document::hasWindowEventListener(const AtomicString &eventType)
-{
- RegisteredEventListenerList::iterator it = m_windowEventListeners.begin();
- for (; it != m_windowEventListeners.end(); ++it)
- if ((*it)->eventType() == eventType) {
- return true;
- }
- return false;
-}
-
-void Document::addPendingFrameUnloadEventCount()
-{
- if (m_frame)
- m_frame->eventHandler()->addPendingFrameUnloadEventCount();
-}
-
-void Document::removePendingFrameUnloadEventCount()
-{
- if (m_frame)
- m_frame->eventHandler()->removePendingFrameUnloadEventCount();
-}
-
-void Document::addPendingFrameBeforeUnloadEventCount()
-{
- if (m_frame)
- m_frame->eventHandler()->addPendingFrameBeforeUnloadEventCount();
-}
-
- void Document::removePendingFrameBeforeUnloadEventCount()
-{
- if (m_frame)
- m_frame->eventHandler()->removePendingFrameBeforeUnloadEventCount();
-}
-
-bool Document::hasUnloadEventListener()
-{
- return (hasWindowEventListener(unloadEvent) ||
- hasWindowEventListener(beforeunloadEvent));
-}
-
-PassRefPtr<EventListener> Document::createHTMLEventListener(const String& functionName, const String& code, Node *node)
-{
- if (Frame* frm = frame())
- if (frm->script()->isEnabled())
- return frm->script()->createHTMLEventHandler(functionName, code, node);
- return 0;
-}
-
-void Document::setHTMLWindowEventListener(const AtomicString& eventType, Attribute* attr)
-{
- setHTMLWindowEventListener(eventType,
- createHTMLEventListener(attr->localName().string(), attr->value(), 0));
-}
-
-void Document::dispatchImageLoadEventSoon(HTMLImageLoader *image)
-{
- m_imageLoadEventDispatchSoonList.append(image);
- if (!m_imageLoadEventTimer.isActive())
- m_imageLoadEventTimer.startOneShot(0);
-}
-
-void Document::removeImage(HTMLImageLoader* image)
-{
- // Remove instances of this image from both lists.
- // Use loops because we allow multiple instances to get into the lists.
- while (m_imageLoadEventDispatchSoonList.removeRef(image)) { }
- while (m_imageLoadEventDispatchingList.removeRef(image)) { }
- if (m_imageLoadEventDispatchSoonList.isEmpty())
- m_imageLoadEventTimer.stop();
-}
-
-void Document::dispatchImageLoadEventsNow()
-{
- // need to avoid re-entering this function; if new dispatches are
- // scheduled before the parent finishes processing the list, they
- // will set a timer and eventually be processed
- if (!m_imageLoadEventDispatchingList.isEmpty()) {
- return;
- }
-
- m_imageLoadEventTimer.stop();
-
- m_imageLoadEventDispatchingList = m_imageLoadEventDispatchSoonList;
- m_imageLoadEventDispatchSoonList.clear();
- for (DeprecatedPtrListIterator<HTMLImageLoader> it(m_imageLoadEventDispatchingList); it.current();) {
- HTMLImageLoader* image = it.current();
- // Must advance iterator *before* dispatching call.
- // Otherwise, it might be advanced automatically if dispatching the call had a side effect
- // of destroying the current HTMLImageLoader, and then we would advance past the *next* item,
- // missing one altogether.
- ++it;
- image->dispatchLoadEvent();
- }
- m_imageLoadEventDispatchingList.clear();
-}
-
-void Document::imageLoadEventTimerFired(Timer<Document>*)
-{
- dispatchImageLoadEventsNow();
-}
-
-Element* Document::ownerElement() const
-{
- if (!frame())
- return 0;
- return frame()->ownerElement();
-}
-
-String Document::cookie() const
-{
- return cookies(this, cookieURL());
-}
-
-void Document::setCookie(const String& value)
-{
- setCookies(this, cookieURL(), policyBaseURL(), value);
-}
-
-String Document::referrer() const
-{
- if (frame())
- return frame()->loader()->referrer();
- return String();
-}
-
-String Document::domain() const
-{
- return m_securityOrigin->domain();
-}
-
-void Document::setDomain(const String& newDomain)
-{
- // Both NS and IE specify that changing the domain is only allowed when
- // the new domain is a suffix of the old domain.
-
- // FIXME: We should add logging indicating why a domain was not allowed.
-
- // If the new domain is the same as the old domain, still call
- // m_securityOrigin.setDomainForDOM. This will change the
- // security check behavior. For example, if a page loaded on port 8000
- // assigns its current domain using document.domain, the page will
- // allow other pages loaded on different ports in the same domain that
- // have also assigned to access this page.
- if (equalIgnoringCase(domain(), newDomain)) {
- m_securityOrigin->setDomainFromDOM(newDomain);
- return;
- }
-
- int oldLength = domain().length();
- int newLength = newDomain.length();
- // e.g. newDomain = webkit.org (10) and domain() = www.webkit.org (14)
- if (newLength >= oldLength)
- return;
-
- String test = domain();
- // Check that it's a subdomain, not e.g. "ebkit.org"
- if (test[oldLength - newLength - 1] != '.')
- return;
-
- // Now test is "webkit.org" from domain()
- // and we check that it's the same thing as newDomain
- test.remove(0, oldLength - newLength);
- if (test != newDomain)
- return;
-
- m_securityOrigin->setDomainFromDOM(newDomain);
-}
-
-String Document::lastModified() const
-{
- Frame* f = frame();
- if (!f)
- return String();
- DocumentLoader* loader = f->loader()->documentLoader();
- if (!loader)
- return String();
- return loader->response().httpHeaderField("Last-Modified");
-}
-
-static bool isValidNameNonASCII(const UChar* characters, unsigned length)
-{
- unsigned i = 0;
-
- UChar32 c;
- U16_NEXT(characters, i, length, c)
- if (!isValidNameStart(c))
- return false;
-
- while (i < length) {
- U16_NEXT(characters, i, length, c)
- if (!isValidNamePart(c))
- return false;
- }
-
- return true;
-}
-
-static inline bool isValidNameASCII(const UChar* characters, unsigned length)
-{
- UChar c = characters[0];
- if (!(isASCIIAlpha(c) || c == ':' || c == '_'))
- return false;
-
- for (unsigned i = 1; i < length; ++i) {
- c = characters[i];
- if (!(isASCIIAlphanumeric(c) || c == ':' || c == '_' || c == '-' || c == '.'))
- return false;
- }
-
- return true;
-}
-
-bool Document::isValidName(const String& name)
-{
- unsigned length = name.length();
- if (!length)
- return false;
-
- const UChar* characters = name.characters();
- return isValidNameASCII(characters, length) || isValidNameNonASCII(characters, length);
-}
-
-bool Document::parseQualifiedName(const String& qualifiedName, String& prefix, String& localName, ExceptionCode& ec)
-{
- unsigned length = qualifiedName.length();
-
- if (length == 0) {
- ec = INVALID_CHARACTER_ERR;
- return false;
- }
-
- bool nameStart = true;
- bool sawColon = false;
- int colonPos = 0;
-
- const UChar* s = qualifiedName.characters();
- for (unsigned i = 0; i < length;) {
- UChar32 c;
- U16_NEXT(s, i, length, c)
- if (c == ':') {
- if (sawColon) {
- ec = NAMESPACE_ERR;
- return false; // multiple colons: not allowed
- }
- nameStart = true;
- sawColon = true;
- colonPos = i - 1;
- } else if (nameStart) {
- if (!isValidNameStart(c)) {
- ec = INVALID_CHARACTER_ERR;
- return false;
- }
- nameStart = false;
- } else {
- if (!isValidNamePart(c)) {
- ec = INVALID_CHARACTER_ERR;
- return false;
- }
- }
- }
-
- if (!sawColon) {
- prefix = String();
- localName = qualifiedName;
- } else {
- prefix = qualifiedName.substring(0, colonPos);
- if (prefix.isEmpty()) {
- ec = NAMESPACE_ERR;
- return false;
- }
- localName = qualifiedName.substring(colonPos + 1);
- }
-
- if (localName.isEmpty()) {
- ec = NAMESPACE_ERR;
- return false;
- }
-
- return true;
-}
-
-void Document::addImageMap(HTMLMapElement* imageMap)
-{
- const AtomicString& name = imageMap->getName();
- if (!name.impl())
- return;
-
- // Add the image map, unless there's already another with that name.
- // "First map wins" is the rule other browsers seem to implement.
- m_imageMapsByName.add(name.impl(), imageMap);
-}
-
-void Document::removeImageMap(HTMLMapElement* imageMap)
-{
- // Remove the image map by name.
- // But don't remove some other image map that just happens to have the same name.
- // FIXME: Use a HashCountedSet as we do for IDs to find the first remaining map
- // once a map has been removed.
- const AtomicString& name = imageMap->getName();
- if (!name.impl())
- return;
-
- ImageMapsByName::iterator it = m_imageMapsByName.find(name.impl());
- if (it != m_imageMapsByName.end() && it->second == imageMap)
- m_imageMapsByName.remove(it);
-}
-
-HTMLMapElement *Document::getImageMap(const String& url) const
-{
- if (url.isNull())
- return 0;
- int hashPos = url.find('#');
- String name = (hashPos < 0 ? url : url.substring(hashPos + 1)).impl();
- AtomicString mapName = isHTMLDocument() ? name.lower() : name;
- return m_imageMapsByName.get(mapName.impl());
-}
-
-void Document::setDecoder(PassRefPtr<TextResourceDecoder> decoder)
-{
- m_decoder = decoder;
-}
-
-UChar Document::backslashAsCurrencySymbol() const
-{
- if (!m_decoder)
- return '\\';
- return m_decoder->encoding().backslashAsCurrencySymbol();
-}
-
-KURL Document::completeURL(const String& url) const
-{
- // Always return a null URL when passed a null string.
- // FIXME: Should we change the KURL constructor to have this behavior?
- if (url.isNull())
- return KURL();
- if (!m_decoder)
- return KURL(m_baseURL, url);
- return KURL(m_baseURL, url, m_decoder->encoding());
-}
-
-bool Document::inPageCache()
-{
- return m_inPageCache;
-}
-
-void Document::setInPageCache(bool flag)
-{
- if (m_inPageCache == flag)
- return;
-
- m_inPageCache = flag;
- if (flag) {
- ASSERT(m_savedRenderer == 0);
- m_savedRenderer = renderer();
- if (FrameView* v = view())
- v->resetScrollbars();
- } else {
- ASSERT(renderer() == 0 || renderer() == m_savedRenderer);
- ASSERT(m_renderArena);
- setRenderer(m_savedRenderer);
- m_savedRenderer = 0;
- }
-}
-
-void Document::willSaveToCache()
-{
- HashSet<Element*>::iterator end = m_pageCacheCallbackElements.end();
- for (HashSet<Element*>::iterator i = m_pageCacheCallbackElements.begin(); i != end; ++i)
- (*i)->willSaveToCache();
-}
-
-void Document::didRestoreFromCache()
-{
- HashSet<Element*>::iterator end = m_pageCacheCallbackElements.end();
- for (HashSet<Element*>::iterator i = m_pageCacheCallbackElements.begin(); i != end; ++i)
- (*i)->didRestoreFromCache();
-}
-
-void Document::registerForCacheCallbacks(Element* e)
-{
- m_pageCacheCallbackElements.add(e);
-}
-
-void Document::unregisterForCacheCallbacks(Element* e)
-{
- m_pageCacheCallbackElements.remove(e);
-}
-
-void Document::setShouldCreateRenderers(bool f)
-{
- m_createRenderers = f;
-}
-
-bool Document::shouldCreateRenderers()
-{
- return m_createRenderers;
-}
-
-// Support for Javascript execCommand, and related methods
-
-static Editor::Command command(Document* document, const String& commandName, bool userInterface = false)
-{
- Frame* frame = document->frame();
- if (!frame || frame->document() != document)
- return Editor::Command();
- return frame->editor()->command(commandName,
- userInterface ? CommandFromDOMWithUserInterface : CommandFromDOM);
-}
-
-bool Document::execCommand(const String& commandName, bool userInterface, const String& value)
-{
- return command(this, commandName, userInterface).execute(value);
-}
-
-bool Document::queryCommandEnabled(const String& commandName)
-{
- return command(this, commandName).isEnabled();
-}
-
-bool Document::queryCommandIndeterm(const String& commandName)
-{
- return command(this, commandName).state() == MixedTriState;
-}
-
-bool Document::queryCommandState(const String& commandName)
-{
- return command(this, commandName).state() != FalseTriState;
-}
-
-bool Document::queryCommandSupported(const String& commandName)
-{
- return command(this, commandName).isSupported();
-}
-
-String Document::queryCommandValue(const String& commandName)
-{
- return command(this, commandName).value();
-}
-
-static IntRect placeholderRectForMarker()
-{
- return IntRect(-1, -1, -1, -1);
-}
-
-void Document::addMarker(Range *range, DocumentMarker::MarkerType type, String description)
-{
- // Use a TextIterator to visit the potentially multiple nodes the range covers.
- for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
- RefPtr<Range> textPiece = markedText.range();
- int exception = 0;
- DocumentMarker marker = {type, textPiece->startOffset(exception), textPiece->endOffset(exception), description};
- addMarker(textPiece->startContainer(exception), marker);
- }
-}
-
-void Document::removeMarkers(Range* range, DocumentMarker::MarkerType markerType)
-{
- if (m_markers.isEmpty())
- return;
-
- ExceptionCode ec = 0;
- Node* startContainer = range->startContainer(ec);
- Node* endContainer = range->endContainer(ec);
-
- Node* pastLastNode = range->pastLastNode();
- for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) {
- int startOffset = node == startContainer ? range->startOffset(ec) : 0;
- int endOffset = node == endContainer ? range->endOffset(ec) : INT_MAX;
- int length = endOffset - startOffset;
- removeMarkers(node, startOffset, length, markerType);
- }
-}
-
-// Markers are stored in order sorted by their start offset.
-// Markers of the same type do not overlap each other.
-
-void Document::addMarker(Node* node, DocumentMarker newMarker)
-{
- ASSERT(newMarker.endOffset >= newMarker.startOffset);
- if (newMarker.endOffset == newMarker.startOffset)
- return;
-
- MarkerMapVectorPair* vectorPair = m_markers.get(node);
-
- if (!vectorPair) {
- vectorPair = new MarkerMapVectorPair;
- vectorPair->first.append(newMarker);
- vectorPair->second.append(placeholderRectForMarker());
- m_markers.set(node, vectorPair);
- } else {
- Vector<DocumentMarker>& markers = vectorPair->first;
- Vector<IntRect>& rects = vectorPair->second;
- size_t numMarkers = markers.size();
- ASSERT(numMarkers == rects.size());
- size_t i;
- // Iterate over all markers whose start offset is less than or equal to the new marker's.
- // If one of them is of the same type as the new marker and touches it or intersects with it
- // (there is at most one), remove it and adjust the new marker's start offset to encompass it.
- for (i = 0; i < numMarkers; ++i) {
- DocumentMarker marker = markers[i];
- if (marker.startOffset > newMarker.startOffset)
- break;
- if (marker.type == newMarker.type && marker.endOffset >= newMarker.startOffset) {
- newMarker.startOffset = marker.startOffset;
- markers.remove(i);
- rects.remove(i);
- numMarkers--;
- break;
- }
- }
- size_t j = i;
- // Iterate over all markers whose end offset is less than or equal to the new marker's,
- // removing markers of the same type as the new marker which touch it or intersect with it,
- // adjusting the new marker's end offset to cover them if necessary.
- while (j < numMarkers) {
- DocumentMarker marker = markers[j];
- if (marker.startOffset > newMarker.endOffset)
- break;
- if (marker.type == newMarker.type) {
- markers.remove(j);
- rects.remove(j);
- if (newMarker.endOffset <= marker.endOffset) {
- newMarker.endOffset = marker.endOffset;
- break;
- }
- numMarkers--;
- } else
- j++;
- }
- // At this point i points to the node before which we want to insert.
- markers.insert(i, newMarker);
- rects.insert(i, placeholderRectForMarker());
- }
-
- // repaint the affected node
- if (node->renderer())
- node->renderer()->repaint();
-}
-
-// copies markers from srcNode to dstNode, applying the specified shift delta to the copies. The shift is
-// useful if, e.g., the caller has created the dstNode from a non-prefix substring of the srcNode.
-void Document::copyMarkers(Node *srcNode, unsigned startOffset, int length, Node *dstNode, int delta, DocumentMarker::MarkerType markerType)
-{
- if (length <= 0)
- return;
-
- MarkerMapVectorPair* vectorPair = m_markers.get(srcNode);
- if (!vectorPair)
- return;
-
- ASSERT(vectorPair->first.size() == vectorPair->second.size());
-
- bool docDirty = false;
- unsigned endOffset = startOffset + length - 1;
- Vector<DocumentMarker>& markers = vectorPair->first;
- for (size_t i = 0; i != markers.size(); ++i) {
- DocumentMarker marker = markers[i];
-
- // stop if we are now past the specified range
- if (marker.startOffset > endOffset)
- break;
-
- // skip marker that is before the specified range or is the wrong type
- if (marker.endOffset < startOffset || (marker.type != markerType && markerType != DocumentMarker::AllMarkers))
- continue;
-
- // pin the marker to the specified range and apply the shift delta
- docDirty = true;
- if (marker.startOffset < startOffset)
- marker.startOffset = startOffset;
- if (marker.endOffset > endOffset)
- marker.endOffset = endOffset;
- marker.startOffset += delta;
- marker.endOffset += delta;
-
- addMarker(dstNode, marker);
- }
-
- // repaint the affected node
- if (docDirty && dstNode->renderer())
- dstNode->renderer()->repaint();
-}
-
-void Document::removeMarkers(Node* node, unsigned startOffset, int length, DocumentMarker::MarkerType markerType)
-{
- if (length <= 0)
- return;
-
- MarkerMapVectorPair* vectorPair = m_markers.get(node);
- if (!vectorPair)
- return;
-
- Vector<DocumentMarker>& markers = vectorPair->first;
- Vector<IntRect>& rects = vectorPair->second;
- ASSERT(markers.size() == rects.size());
- bool docDirty = false;
- unsigned endOffset = startOffset + length;
- for (size_t i = 0; i < markers.size();) {
- DocumentMarker marker = markers[i];
-
- // markers are returned in order, so stop if we are now past the specified range
- if (marker.startOffset >= endOffset)
- break;
-
- // skip marker that is wrong type or before target
- if (marker.endOffset < startOffset || (marker.type != markerType && markerType != DocumentMarker::AllMarkers)) {
- i++;
- continue;
- }
-
- // at this point we know that marker and target intersect in some way
- docDirty = true;
-
- // pitch the old marker and any associated rect
- markers.remove(i);
- rects.remove(i);
-
- // add either of the resulting slices that are left after removing target
- if (startOffset > marker.startOffset) {
- DocumentMarker newLeft = marker;
- newLeft.endOffset = startOffset;
- markers.insert(i, newLeft);
- rects.insert(i, placeholderRectForMarker());
- // i now points to the newly-inserted node, but we want to skip that one
- i++;
- }
- if (marker.endOffset > endOffset) {
- DocumentMarker newRight = marker;
- newRight.startOffset = endOffset;
- markers.insert(i, newRight);
- rects.insert(i, placeholderRectForMarker());
- // i now points to the newly-inserted node, but we want to skip that one
- i++;
- }
- }
-
- if (markers.isEmpty()) {
- ASSERT(rects.isEmpty());
- m_markers.remove(node);
- delete vectorPair;
- }
-
- // repaint the affected node
- if (docDirty && node->renderer())
- node->renderer()->repaint();
-}
-
-DocumentMarker* Document::markerContainingPoint(const IntPoint& point, DocumentMarker::MarkerType markerType)
-{
- // outer loop: process each node that contains any markers
- MarkerMap::iterator end = m_markers.end();
- for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
- // inner loop; process each marker in this node
- MarkerMapVectorPair* vectorPair = nodeIterator->second;
- Vector<DocumentMarker>& markers = vectorPair->first;
- Vector<IntRect>& rects = vectorPair->second;
- ASSERT(markers.size() == rects.size());
- unsigned markerCount = markers.size();
- for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) {
- DocumentMarker& marker = markers[markerIndex];
-
- // skip marker that is wrong type
- if (marker.type != markerType && markerType != DocumentMarker::AllMarkers)
- continue;
-
- IntRect& r = rects[markerIndex];
-
- // skip placeholder rects
- if (r == placeholderRectForMarker())
- continue;
-
- if (r.contains(point))
- return &marker;
- }
- }
-
- return 0;
-}
-
-Vector<DocumentMarker> Document::markersForNode(Node* node)
-{
- MarkerMapVectorPair* vectorPair = m_markers.get(node);
- if (vectorPair)
- return vectorPair->first;
- return Vector<DocumentMarker>();
-}
-
-Vector<IntRect> Document::renderedRectsForMarkers(DocumentMarker::MarkerType markerType)
-{
- Vector<IntRect> result;
-
- // outer loop: process each node
- MarkerMap::iterator end = m_markers.end();
- for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
- // inner loop; process each marker in this node
- MarkerMapVectorPair* vectorPair = nodeIterator->second;
- Vector<DocumentMarker>& markers = vectorPair->first;
- Vector<IntRect>& rects = vectorPair->second;
- ASSERT(markers.size() == rects.size());
- unsigned markerCount = markers.size();
- for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) {
- DocumentMarker marker = markers[markerIndex];
-
- // skip marker that is wrong type
- if (marker.type != markerType && markerType != DocumentMarker::AllMarkers)
- continue;
-
- IntRect r = rects[markerIndex];
- // skip placeholder rects
- if (r == placeholderRectForMarker())
- continue;
-
- result.append(r);
- }
- }
-
- return result;
-}
-
-void Document::removeMarkers(Node* node)
-{
- MarkerMap::iterator i = m_markers.find(node);
- if (i != m_markers.end()) {
- delete i->second;
- m_markers.remove(i);
- if (RenderObject* renderer = node->renderer())
- renderer->repaint();
- }
-}
-
-void Document::removeMarkers(DocumentMarker::MarkerType markerType)
-{
- // outer loop: process each markered node in the document
- MarkerMap markerMapCopy = m_markers;
- MarkerMap::iterator end = markerMapCopy.end();
- for (MarkerMap::iterator i = markerMapCopy.begin(); i != end; ++i) {
- Node* node = i->first.get();
- bool nodeNeedsRepaint = false;
-
- // inner loop: process each marker in the current node
- MarkerMapVectorPair* vectorPair = i->second;
- Vector<DocumentMarker>& markers = vectorPair->first;
- Vector<IntRect>& rects = vectorPair->second;
- ASSERT(markers.size() == rects.size());
- for (size_t i = 0; i != markers.size();) {
- DocumentMarker marker = markers[i];
-
- // skip nodes that are not of the specified type
- if (marker.type != markerType && markerType != DocumentMarker::AllMarkers) {
- ++i;
- continue;
- }
-
- // pitch the old marker
- markers.remove(i);
- rects.remove(i);
- nodeNeedsRepaint = true;
- // markerIterator now points to the next node
- }
-
- // Redraw the node if it changed. Do this before the node is removed from m_markers, since
- // m_markers might contain the last reference to the node.
- if (nodeNeedsRepaint) {
- RenderObject* renderer = node->renderer();
- if (renderer)
- renderer->repaint();
- }
-
- // delete the node's list if it is now empty
- if (markers.isEmpty()) {
- ASSERT(rects.isEmpty());
- m_markers.remove(node);
- delete vectorPair;
- }
- }
-}
-
-void Document::repaintMarkers(DocumentMarker::MarkerType markerType)
-{
- // outer loop: process each markered node in the document
- MarkerMap::iterator end = m_markers.end();
- for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
- Node* node = i->first.get();
-
- // inner loop: process each marker in the current node
- MarkerMapVectorPair* vectorPair = i->second;
- Vector<DocumentMarker>& markers = vectorPair->first;
- bool nodeNeedsRepaint = false;
- for (size_t i = 0; i != markers.size(); ++i) {
- DocumentMarker marker = markers[i];
-
- // skip nodes that are not of the specified type
- if (marker.type == markerType || markerType == DocumentMarker::AllMarkers) {
- nodeNeedsRepaint = true;
- break;
- }
- }
-
- if (!nodeNeedsRepaint)
- continue;
-
- // cause the node to be redrawn
- if (RenderObject* renderer = node->renderer())
- renderer->repaint();
- }
-}
-
-void Document::setRenderedRectForMarker(Node* node, DocumentMarker marker, const IntRect& r)
-{
- MarkerMapVectorPair* vectorPair = m_markers.get(node);
- if (!vectorPair) {
- ASSERT_NOT_REACHED(); // shouldn't be trying to set the rect for a marker we don't already know about
- return;
- }
-
- Vector<DocumentMarker>& markers = vectorPair->first;
- ASSERT(markers.size() == vectorPair->second.size());
- unsigned markerCount = markers.size();
- for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) {
- DocumentMarker m = markers[markerIndex];
- if (m == marker) {
- vectorPair->second[markerIndex] = r;
- return;
- }
- }
-
- ASSERT_NOT_REACHED(); // shouldn't be trying to set the rect for a marker we don't already know about
-}
-
-void Document::invalidateRenderedRectsForMarkersInRect(const IntRect& r)
-{
- // outer loop: process each markered node in the document
- MarkerMap::iterator end = m_markers.end();
- for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
-
- // inner loop: process each rect in the current node
- MarkerMapVectorPair* vectorPair = i->second;
- Vector<IntRect>& rects = vectorPair->second;
-
- unsigned rectCount = rects.size();
- for (unsigned rectIndex = 0; rectIndex < rectCount; ++rectIndex)
- if (rects[rectIndex].intersects(r))
- rects[rectIndex] = placeholderRectForMarker();
- }
-}
-
-void Document::shiftMarkers(Node *node, unsigned startOffset, int delta, DocumentMarker::MarkerType markerType)
-{
- MarkerMapVectorPair* vectorPair = m_markers.get(node);
- if (!vectorPair)
- return;
-
- Vector<DocumentMarker>& markers = vectorPair->first;
- Vector<IntRect>& rects = vectorPair->second;
- ASSERT(markers.size() == rects.size());
-
- bool docDirty = false;
- for (size_t i = 0; i != markers.size(); ++i) {
- DocumentMarker &marker = markers[i];
- if (marker.startOffset >= startOffset && (markerType == DocumentMarker::AllMarkers || marker.type == markerType)) {
- ASSERT((int)marker.startOffset + delta >= 0);
- marker.startOffset += delta;
- marker.endOffset += delta;
- docDirty = true;
-
- // Marker moved, so previously-computed rendered rectangle is now invalid
- rects[i] = placeholderRectForMarker();
- }
- }
-
- // repaint the affected node
- if (docDirty && node->renderer())
- node->renderer()->repaint();
-}
-
-#if ENABLE(XSLT)
-
-void Document::applyXSLTransform(ProcessingInstruction* pi)
-{
- RefPtr<XSLTProcessor> processor = XSLTProcessor::create();
- processor->setXSLStyleSheet(static_cast<XSLStyleSheet*>(pi->sheet()));
- String resultMIMEType;
- String newSource;
- String resultEncoding;
- if (!processor->transformToString(this, resultMIMEType, newSource, resultEncoding))
- return;
- // FIXME: If the transform failed we should probably report an error (like Mozilla does).
- processor->createDocumentFromSource(newSource, resultEncoding, resultMIMEType, this, frame());
-}
-
-void Document::setTransformSource(void* doc)
-{
- if (doc == m_transformSource)
- return;
-
- xmlFreeDoc((xmlDocPtr)m_transformSource);
- m_transformSource = doc;
-}
-
-#endif
-
-void Document::setDesignMode(InheritedBool value)
-{
- m_designMode = value;
-}
-
-Document::InheritedBool Document::getDesignMode() const
-{
- return m_designMode;
-}
-
-bool Document::inDesignMode() const
-{
- for (const Document* d = this; d; d = d->parentDocument()) {
- if (d->m_designMode != inherit)
- return d->m_designMode;
- }
- return false;
-}
-
-Document *Document::parentDocument() const
-{
- Frame *childPart = frame();
- if (!childPart)
- return 0;
- Frame *parent = childPart->tree()->parent();
- if (!parent)
- return 0;
- return parent->document();
-}
-
-Document *Document::topDocument() const
-{
- Document *doc = const_cast<Document *>(this);
- Element *element;
- while ((element = doc->ownerElement()))
- doc = element->document();
-
- return doc;
-}
-
-PassRefPtr<Attr> Document::createAttributeNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode& ec, bool shouldIgnoreNamespaceChecks)
-{
- String prefix, localName;
- if (!parseQualifiedName(qualifiedName, prefix, localName, ec))
- return 0;
-
- QualifiedName qName(prefix, localName, namespaceURI);
- if (!shouldIgnoreNamespaceChecks && hasPrefixNamespaceMismatch(qName)) {
- ec = NAMESPACE_ERR;
- return 0;
- }
-
- // Spec: DOM Level 2 Core: http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-DocCrAttrNS
- if (!shouldIgnoreNamespaceChecks && qName.localName() == "xmlns" && qName.namespaceURI() != "http://www.w3.org/2000/xmlns/") {
- ec = NAMESPACE_ERR;
- return 0;
- }
-
- // FIXME: Assume this is a mapped attribute, since createAttribute isn't namespace-aware. There's no harm to XML
- // documents if we're wrong.
- return new Attr(0, this, MappedAttribute::create(qName, StringImpl::empty()));
-}
-
-#if ENABLE(SVG)
-const SVGDocumentExtensions* Document::svgExtensions()
-{
- return m_svgExtensions;
-}
-
-SVGDocumentExtensions* Document::accessSVGExtensions()
-{
- if (!m_svgExtensions)
- m_svgExtensions = new SVGDocumentExtensions(this);
- return m_svgExtensions;
-}
-#endif
-
-PassRefPtr<HTMLCollection> Document::images()
-{
- return HTMLCollection::create(this, HTMLCollection::DocImages);
-}
-
-PassRefPtr<HTMLCollection> Document::applets()
-{
- return HTMLCollection::create(this, HTMLCollection::DocApplets);
-}
-
-PassRefPtr<HTMLCollection> Document::embeds()
-{
- return HTMLCollection::create(this, HTMLCollection::DocEmbeds);
-}
-
-PassRefPtr<HTMLCollection> Document::plugins()
-{
- // This is an alias for embeds() required for the JS DOM bindings.
- return HTMLCollection::create(this, HTMLCollection::DocEmbeds);
-}
-
-PassRefPtr<HTMLCollection> Document::objects()
-{
- return HTMLCollection::create(this, HTMLCollection::DocObjects);
-}
-
-PassRefPtr<HTMLCollection> Document::scripts()
-{
- return HTMLCollection::create(this, HTMLCollection::DocScripts);
-}
-
-PassRefPtr<HTMLCollection> Document::links()
-{
- return HTMLCollection::create(this, HTMLCollection::DocLinks);
-}
-
-PassRefPtr<HTMLCollection> Document::forms()
-{
- return HTMLCollection::create(this, HTMLCollection::DocForms);
-}
-
-PassRefPtr<HTMLCollection> Document::anchors()
-{
- return HTMLCollection::create(this, HTMLCollection::DocAnchors);
-}
-
-PassRefPtr<HTMLCollection> Document::all()
-{
- return HTMLCollection::create(this, HTMLCollection::DocAll);
-}
-
-PassRefPtr<HTMLCollection> Document::windowNamedItems(const String &name)
-{
- return HTMLNameCollection::create(this, HTMLCollection::WindowNamedItems, name);
-}
-
-PassRefPtr<HTMLCollection> Document::documentNamedItems(const String &name)
-{
- return HTMLNameCollection::create(this, HTMLCollection::DocumentNamedItems, name);
-}
-
-HTMLCollection::CollectionInfo* Document::nameCollectionInfo(HTMLCollection::Type type, const AtomicString& name)
-{
- ASSERT(type >= HTMLCollection::FirstNamedDocumentCachedType);
- unsigned index = type - HTMLCollection::FirstNamedDocumentCachedType;
- ASSERT(index < HTMLCollection::NumNamedDocumentCachedTypes);
-
- NamedCollectionMap& map = m_nameCollectionInfo[index];
- NamedCollectionMap::iterator iter = map.find(name.impl());
- if (iter == map.end())
- iter = map.add(name.impl(), new HTMLCollection::CollectionInfo).first;
- return iter->second;
-}
-
-void Document::finishedParsing()
-{
- setParsing(false);
-
- ExceptionCode ec = 0;
- dispatchEvent(Event::create(DOMContentLoadedEvent, true, false), ec);
-
- if (Frame* f = frame())
- f->loader()->finishedParsing();
-}
-
-Vector<String> Document::formElementsState() const
-{
- Vector<String> stateVector;
- stateVector.reserveCapacity(m_formElementsWithState.size() * 3);
- typedef ListHashSet<HTMLFormControlElementWithState*>::const_iterator Iterator;
- Iterator end = m_formElementsWithState.end();
- for (Iterator it = m_formElementsWithState.begin(); it != end; ++it) {
- HTMLFormControlElementWithState* e = *it;
- String value;
- if (e->saveState(value)) {
- stateVector.append(e->name().string());
- stateVector.append(e->type().string());
- stateVector.append(value);
- }
- }
- return stateVector;
-}
-
-#if ENABLE(XPATH)
-
-PassRefPtr<XPathExpression> Document::createExpression(const String& expression,
- XPathNSResolver* resolver,
- ExceptionCode& ec)
-{
- if (!m_xpathEvaluator)
- m_xpathEvaluator = XPathEvaluator::create();
- return m_xpathEvaluator->createExpression(expression, resolver, ec);
-}
-
-PassRefPtr<XPathNSResolver> Document::createNSResolver(Node* nodeResolver)
-{
- if (!m_xpathEvaluator)
- m_xpathEvaluator = XPathEvaluator::create();
- return m_xpathEvaluator->createNSResolver(nodeResolver);
-}
-
-PassRefPtr<XPathResult> Document::evaluate(const String& expression,
- Node* contextNode,
- XPathNSResolver* resolver,
- unsigned short type,
- XPathResult* result,
- ExceptionCode& ec)
-{
- if (!m_xpathEvaluator)
- m_xpathEvaluator = XPathEvaluator::create();
- return m_xpathEvaluator->evaluate(expression, contextNode, resolver, type, result, ec);
-}
-
-#endif // ENABLE(XPATH)
-
-void Document::setStateForNewFormElements(const Vector<String>& stateVector)
-{
- // Walk the state vector backwards so that the value to use for each
- // name/type pair first is the one at the end of each individual vector
- // in the FormElementStateMap. We're using them like stacks.
- typedef FormElementStateMap::iterator Iterator;
- m_formElementsWithState.clear();
- for (size_t i = stateVector.size() / 3 * 3; i; i -= 3) {
- AtomicString a = stateVector[i - 3];
- AtomicString b = stateVector[i - 2];
- const String& c = stateVector[i - 1];
- FormElementKey key(a.impl(), b.impl());
- Iterator it = m_stateForNewFormElements.find(key);
- if (it != m_stateForNewFormElements.end())
- it->second.append(c);
- else {
- Vector<String> v(1);
- v[0] = c;
- m_stateForNewFormElements.set(key, v);
- }
- }
-}
-
-bool Document::hasStateForNewFormElements() const
-{
- return !m_stateForNewFormElements.isEmpty();
-}
-
-bool Document::takeStateForFormElement(AtomicStringImpl* name, AtomicStringImpl* type, String& state)
-{
- typedef FormElementStateMap::iterator Iterator;
- Iterator it = m_stateForNewFormElements.find(FormElementKey(name, type));
- if (it == m_stateForNewFormElements.end())
- return false;
- ASSERT(it->second.size());
- state = it->second.last();
- if (it->second.size() > 1)
- it->second.removeLast();
- else
- m_stateForNewFormElements.remove(it);
- return true;
-}
-
-FormElementKey::FormElementKey(AtomicStringImpl* name, AtomicStringImpl* type)
- : m_name(name), m_type(type)
-{
- ref();
-}
-
-FormElementKey::~FormElementKey()
-{
- deref();
-}
-
-FormElementKey::FormElementKey(const FormElementKey& other)
- : m_name(other.name()), m_type(other.type())
-{
- ref();
-}
-
-FormElementKey& FormElementKey::operator=(const FormElementKey& other)
-{
- other.ref();
- deref();
- m_name = other.name();
- m_type = other.type();
- return *this;
-}
-
-void FormElementKey::ref() const
-{
- if (name())
- name()->ref();
- if (type())
- type()->ref();
-}
-
-void FormElementKey::deref() const
-{
- if (name())
- name()->deref();
- if (type())
- type()->deref();
-}
-
-unsigned FormElementKeyHash::hash(const FormElementKey& k)
-{
- ASSERT(sizeof(k) % (sizeof(uint16_t) * 2) == 0);
-
- unsigned l = sizeof(k) / (sizeof(uint16_t) * 2);
- const uint16_t* s = reinterpret_cast<const uint16_t*>(&k);
- uint32_t hash = PHI;
-
- // Main loop
- for (; l > 0; l--) {
- hash += s[0];
- uint32_t tmp = (s[1] << 11) ^ hash;
- hash = (hash << 16) ^ tmp;
- s += 2;
- hash += hash >> 11;
- }
-
- // Force "avalanching" of final 127 bits
- hash ^= hash << 3;
- hash += hash >> 5;
- hash ^= hash << 2;
- hash += hash >> 15;
- hash ^= hash << 10;
-
- // this avoids ever returning a hash code of 0, since that is used to
- // signal "hash not computed yet", using a value that is likely to be
- // effectively the same as 0 when the low bits are masked
- if (hash == 0)
- hash = 0x80000000;
-
- return hash;
-}
-
-void Document::setIconURL(const String& iconURL, const String& type)
-{
- // FIXME - <rdar://problem/4727645> - At some point in the future, we might actually honor the "type"
- if (m_iconURL.isEmpty())
- m_iconURL = iconURL;
- else if (!type.isEmpty())
- m_iconURL = iconURL;
-}
-
-void Document::setUseSecureKeyboardEntryWhenActive(bool usesSecureKeyboard)
-{
- if (m_useSecureKeyboardEntryWhenActive == usesSecureKeyboard)
- return;
-
- m_useSecureKeyboardEntryWhenActive = usesSecureKeyboard;
- m_frame->updateSecureKeyboardEntryIfActive();
-}
-
-bool Document::useSecureKeyboardEntryWhenActive() const
-{
- return m_useSecureKeyboardEntryWhenActive;
-}
-
-void Document::initSecurityContext()
-{
- if (m_securityOrigin && !m_securityOrigin->isEmpty())
- return; // m_securityOrigin has already been initialized.
-
- if (!m_frame) {
- // No source for a security context.
- // This can occur via document.implementation.createDocument().
- m_cookieURL = KURL("");
- m_securityOrigin = SecurityOrigin::createEmpty();
- return;
- }
-
- // In the common case, create the security context from the currently
- // loading URL.
- const KURL& url = m_frame->loader()->url();
- m_cookieURL = url;
- m_securityOrigin = SecurityOrigin::create(url);
-
- if (FrameLoader::allowSubstituteDataAccessToLocal()) {
- // If this document was loaded with substituteData, then the document can
- // load local resources. See https://bugs.webkit.org/show_bug.cgi?id=16756
- // and https://bugs.webkit.org/show_bug.cgi?id=19760 for further
- // discussion.
- DocumentLoader* documentLoader = m_frame->loader()->documentLoader();
- if (documentLoader && documentLoader->substituteData().isValid())
- m_securityOrigin->grantLoadLocalResources();
- }
-
- if (!m_securityOrigin->isEmpty())
- return;
-
- // If we do not obtain a meaningful origin from the URL, then we try to
- // find one via the frame hierarchy.
-
- Frame* ownerFrame = m_frame->tree()->parent();
- if (!ownerFrame)
- ownerFrame = m_frame->loader()->opener();
-
- if (ownerFrame && ownerFrame->document()) {
- m_cookieURL = ownerFrame->document()->cookieURL();
- // We alias the SecurityOrigins to match Firefox, see Bug 15313
- // https://bugs.webkit.org/show_bug.cgi?id=15313
- m_securityOrigin = ownerFrame->document()->securityOrigin();
- }
-}
-
-void Document::setSecurityOrigin(SecurityOrigin* securityOrigin)
-{
- m_securityOrigin = securityOrigin;
- initDNSPrefetchEnabled();
-}
-
-void Document::updateFocusAppearanceSoon()
-{
- if (!m_updateFocusAppearanceTimer.isActive())
- m_updateFocusAppearanceTimer.startOneShot(0);
-}
-
-void Document::cancelFocusAppearanceUpdate()
-{
- m_updateFocusAppearanceTimer.stop();
-}
-
-void Document::updateFocusAppearanceTimerFired(Timer<Document>*)
-{
- Node* node = focusedNode();
- if (!node)
- return;
- if (!node->isElementNode())
- return;
-
- updateLayout();
-
- Element* element = static_cast<Element*>(node);
- if (element->isFocusable())
- element->updateFocusAppearance(false);
-}
-
-// FF method for accessing the selection added for compatability.
-DOMSelection* Document::getSelection() const
-{
- return frame() ? frame()->domWindow()->getSelection() : 0;
-}
-
-static inline int findSlashDotDotSlash(const UChar* characters, size_t length)
-{
- if (length < 4)
- return -1;
- unsigned loopLimit = length - 3;
- for (unsigned i = 0; i < loopLimit; ++i) {
- if (characters[i] == '/' && characters[i + 1] == '.' && characters[i + 2] == '.' && characters[i + 3] == '/')
- return i;
- }
- return -1;
-}
-
-static inline int findSlashSlash(const UChar* characters, size_t length, int position)
-{
- if (length < 2)
- return -1;
- unsigned loopLimit = length - 1;
- for (unsigned i = position; i < loopLimit; ++i) {
- if (characters[i] == '/' && characters[i + 1] == '/')
- return i;
- }
- return -1;
-}
-
-static inline int findSlashDotSlash(const UChar* characters, size_t length)
-{
- if (length < 3)
- return -1;
- unsigned loopLimit = length - 2;
- for (unsigned i = 0; i < loopLimit; ++i) {
- if (characters[i] == '/' && characters[i + 1] == '.' && characters[i + 2] == '/')
- return i;
- }
- return -1;
-}
-
-static inline bool containsColonSlashSlash(const UChar* characters, unsigned length)
-{
- if (length < 3)
- return false;
- unsigned loopLimit = length - 2;
- for (unsigned i = 0; i < loopLimit; ++i) {
- if (characters[i] == ':' && characters[i + 1] == '/' && characters[i + 2] == '/')
- return true;
- }
- return false;
-}
-
-static inline void cleanPath(Vector<UChar, 512>& path)
-{
- // FIXME: Shold not do this in the query or anchor part.
- int pos;
- while ((pos = findSlashDotDotSlash(path.data(), path.size())) != -1) {
- int prev = reverseFind(path.data(), path.size(), '/', pos - 1);
- // don't remove the host, i.e. http://foo.org/../foo.html
- if (prev < 0 || (prev > 3 && path[prev - 2] == ':' && path[prev - 1] == '/'))
- path.remove(pos, 3);
- else
- path.remove(prev, pos - prev + 3);
- }
-
- // FIXME: Shold not do this in the query part.
- // Set refPos to -2 to mean "I haven't looked for the anchor yet".
- // We don't want to waste a function call on the search for the the anchor
- // in the vast majority of cases where there is no "//" in the path.
- pos = 0;
- int refPos = -2;
- while ((pos = findSlashSlash(path.data(), path.size(), pos)) != -1) {
- if (refPos == -2)
- refPos = find(path.data(), path.size(), '#');
- if (refPos > 0 && pos >= refPos)
- break;
-
- if (pos == 0 || path[pos - 1] != ':')
- path.remove(pos);
- else
- pos += 2;
- }
-
- // FIXME: Shold not do this in the query or anchor part.
- while ((pos = findSlashDotSlash(path.data(), path.size())) != -1)
- path.remove(pos, 2);
-}
-
-static inline bool matchLetter(UChar c, UChar lowercaseLetter)
-{
- return (c | 0x20) == lowercaseLetter;
-}
-
-static inline bool needsTrailingSlash(const UChar* characters, unsigned length)
-{
- if (length < 6)
- return false;
- if (!matchLetter(characters[0], 'h')
- || !matchLetter(characters[1], 't')
- || !matchLetter(characters[2], 't')
- || !matchLetter(characters[3], 'p'))
- return false;
- if (!(characters[4] == ':'
- || (matchLetter(characters[4], 's') && characters[5] == ':')))
- return false;
-
- unsigned pos = characters[4] == ':' ? 5 : 6;
-
- // Skip initial two slashes if present.
- if (pos + 1 < length && characters[pos] == '/' && characters[pos + 1] == '/')
- pos += 2;
-
- // Find next slash.
- while (pos < length && characters[pos] != '/')
- ++pos;
-
- return pos == length;
-}
-
-unsigned Document::visitedLinkHash(const AtomicString& attributeURL) const
-{
- const UChar* characters = attributeURL.characters();
- unsigned length = attributeURL.length();
- if (!length)
- return 0;
-
- // This is a poor man's completeURL. Faster with less memory allocation.
- // FIXME: It's missing a lot of what completeURL does and a lot of what KURL does.
- // For example, it does not handle international domain names properly.
-
- // FIXME: It is wrong that we do not do further processing on strings that have "://" in them:
- // 1) The "://" could be in the query or anchor.
- // 2) The URL's path could have a "/./" or a "/../" or a "//" sequence in it.
-
- // FIXME: needsTrailingSlash does not properly return true for a URL that has no path, but does
- // have a query or anchor.
-
- bool hasColonSlashSlash = containsColonSlashSlash(characters, length);
-
- if (hasColonSlashSlash && !needsTrailingSlash(characters, length))
- return AlreadyHashed::avoidDeletedValue(attributeURL.string().impl()->hash());
-
- Vector<UChar, 512> buffer;
-
- if (hasColonSlashSlash) {
- // FIXME: This is incorrect for URLs that have a query or anchor; the "/" needs to go at the
- // end of the path, *before* the query or anchor.
- buffer.append(characters, length);
- buffer.append('/');
- return AlreadyHashed::avoidDeletedValue(StringImpl::computeHash(buffer.data(), buffer.size()));
- }
-
- switch (characters[0]) {
- case '/':
- buffer.append(m_baseURL.string().characters(), m_baseURL.pathStart());
- break;
- case '#':
- buffer.append(m_baseURL.string().characters(), m_baseURL.pathEnd());
- break;
- default:
- buffer.append(m_baseURL.string().characters(), m_baseURL.pathAfterLastSlash());
- break;
- }
- buffer.append(characters, length);
- cleanPath(buffer);
- if (needsTrailingSlash(buffer.data(), buffer.size())) {
- // FIXME: This is incorrect for URLs that have a query or anchor; the "/" needs to go at the
- // end of the path, *before* the query or anchor.
- buffer.append('/');
- }
-
- return AlreadyHashed::avoidDeletedValue(StringImpl::computeHash(buffer.data(), buffer.size()));
-}
-
-#if ENABLE(DATABASE)
-
-void Document::addOpenDatabase(Database* database)
-{
- if (!m_openDatabaseSet)
- m_openDatabaseSet.set(new DatabaseSet);
-
- ASSERT(!m_openDatabaseSet->contains(database));
- m_openDatabaseSet->add(database);
-}
-
-void Document::removeOpenDatabase(Database* database)
-{
- ASSERT(m_openDatabaseSet && m_openDatabaseSet->contains(database));
- if (!m_openDatabaseSet)
- return;
-
- m_openDatabaseSet->remove(database);
-}
-
-DatabaseThread* Document::databaseThread()
-{
- if (!m_databaseThread && !m_hasOpenDatabases) {
- // Create the database thread on first request - but not if at least one database was already opened,
- // because in that case we already had a database thread and terminated it and should not create another.
- m_databaseThread = DatabaseThread::create(this);
- if (!m_databaseThread->start())
- m_databaseThread = 0;
- }
-
- return m_databaseThread.get();
-}
-
-void Document::stopDatabases()
-{
- if (m_openDatabaseSet) {
- DatabaseSet::iterator i = m_openDatabaseSet->begin();
- DatabaseSet::iterator end = m_openDatabaseSet->end();
- for (; i != end; ++i) {
- (*i)->stop();
- if (m_databaseThread)
- m_databaseThread->unscheduleDatabaseTasks(*i);
- }
- }
-
- if (m_databaseThread)
- m_databaseThread->requestTermination();
-}
-
-#endif
-
-void Document::attachRange(Range* range)
-{
- ASSERT(!m_ranges.contains(range));
- m_ranges.add(range);
-}
-
-void Document::detachRange(Range* range)
-{
- ASSERT(m_ranges.contains(range));
- m_ranges.remove(range);
-}
-
-CanvasRenderingContext2D* Document::getCSSCanvasContext(const String& type, const String& name, int width, int height)
-{
- HTMLCanvasElement* result = getCSSCanvasElement(name);
- if (!result)
- return 0;
- result->setSize(IntSize(width, height));
- return result->getContext(type);
-}
-
-HTMLCanvasElement* Document::getCSSCanvasElement(const String& name)
-{
- RefPtr<HTMLCanvasElement> result = m_cssCanvasElements.get(name).get();
- if (!result) {
- result = new HTMLCanvasElement(this);
- m_cssCanvasElements.set(name, result);
- }
- return result.get();
-}
-
-void Document::initDNSPrefetchEnabled()
-{
- m_haveExplicitlyDisabledDNSPrefetch = false;
- m_isDNSPrefetchEnabled = (securityOrigin()->protocol() == "http");
-
- // Inherit DNS prefetch opt-out from parent frame
- if (Document* parent = parentDocument())
- if (!parent->isDNSPrefetchEnabled())
- m_isDNSPrefetchEnabled = false;
-}
-
-void Document::setDNSPrefetchControl(const String& dnsPrefetchControl)
-{
- if (equalIgnoringCase(dnsPrefetchControl, "on") &&
- !m_haveExplicitlyDisabledDNSPrefetch) {
- m_isDNSPrefetchEnabled = true;
- return;
- }
-
- m_isDNSPrefetchEnabled = false;
- m_haveExplicitlyDisabledDNSPrefetch = true;
-}
-
-} // namespace WebCore
diff --git a/webkit/pending/Document.h b/webkit/pending/Document.h
deleted file mode 100644
index 90a1fc4..0000000
--- a/webkit/pending/Document.h
+++ /dev/null
@@ -1,1090 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2001 Dirk Mueller (mueller@kde.org)
- * (C) 2006 Alexey Proskuryakov (ap@webkit.org)
- * Copyright (C) 2004, 2005, 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef Document_h
-#define Document_h
-
-#include "Attr.h"
-#include "Color.h"
-#include "DeprecatedPtrList.h"
-#include "DocumentMarker.h"
-#include "HTMLCollection.h"
-#include "HTMLFormElement.h"
-#include "KURL.h"
-#include "StringHash.h"
-#include "Timer.h"
-#include "unicode/uscript.h"
-#include <wtf/HashCountedSet.h>
-#include <wtf/ListHashSet.h>
-
-// FIXME: We should move Mac off of the old Frame-based user stylesheet loading
-// code and onto the new code in Page. We can't do that until the code in Page
-// supports non-file: URLs, however.
-#if PLATFORM(MAC) || PLATFORM(QT)
-#define FRAME_LOADS_USER_STYLESHEET 1
-#else
-#define FRAME_LOADS_USER_STYLESHEET 0
-#endif
-
-namespace WebCore {
-
- class AXObjectCache;
- class Attr;
- class Attribute;
- class CDATASection;
- class CachedCSSStyleSheet;
- class CanvasRenderingContext2D;
- class CharacterData;
- class CSSStyleDeclaration;
- class CSSStyleSelector;
- class CSSStyleSheet;
- class Comment;
- class Database;
- class DOMImplementation;
- class DOMSelection;
- class DOMWindow;
- class DatabaseThread;
- class DocLoader;
- class DocumentFragment;
- class DocumentType;
- class EditingText;
- class Element;
- class EntityReference;
- class Event;
- class EventListener;
- class Frame;
- class FrameView;
- class HTMLCanvasElement;
- class HTMLDocument;
- class HTMLElement;
- class HTMLFormControlElementWithState;
- class HTMLFormElement;
- class HTMLHeadElement;
- class HTMLImageLoader;
- class HTMLInputElement;
- class HTMLMapElement;
- class IntPoint;
- class JSNode;
- class MouseEventWithHitTestResults;
- class NodeFilter;
- class NodeIterator;
- class Page;
- class PlatformMouseEvent;
- class ProcessingInstruction;
- class Range;
- class RegisteredEventListener;
- class RenderArena;
- class SecurityOrigin;
- class Settings;
- class StyleSheet;
- class StyleSheetList;
- class Text;
- class TextResourceDecoder;
- class Tokenizer;
- class TreeWalker;
-
-#if ENABLE(SVG)
- class SVGDocumentExtensions;
-#endif
-
-#if ENABLE(XBL)
- class XBLBindingManager;
-#endif
-
-#if ENABLE(XPATH)
- class XPathEvaluator;
- class XPathExpression;
- class XPathNSResolver;
- class XPathResult;
-#endif
-
-#if ENABLE(DASHBOARD_SUPPORT)
- struct DashboardRegionValue;
-#endif
- struct HitTestRequest;
-
- typedef int ExceptionCode;
-
-class FormElementKey {
-public:
- FormElementKey(AtomicStringImpl* = 0, AtomicStringImpl* = 0);
- ~FormElementKey();
- FormElementKey(const FormElementKey&);
- FormElementKey& operator=(const FormElementKey&);
-
- AtomicStringImpl* name() const { return m_name; }
- AtomicStringImpl* type() const { return m_type; }
-
- // Hash table deleted values, which are only constructed and never copied or destroyed.
- FormElementKey(WTF::HashTableDeletedValueType) : m_name(hashTableDeletedValue()) { }
- bool isHashTableDeletedValue() const { return m_name == hashTableDeletedValue(); }
-
-private:
- void ref() const;
- void deref() const;
-
- static AtomicStringImpl* hashTableDeletedValue() { return reinterpret_cast<AtomicStringImpl*>(-1); }
-
- AtomicStringImpl* m_name;
- AtomicStringImpl* m_type;
-};
-
-inline bool operator==(const FormElementKey& a, const FormElementKey& b)
-{
- return a.name() == b.name() && a.type() == b.type();
-}
-
-struct FormElementKeyHash {
- static unsigned hash(const FormElementKey&);
- static bool equal(const FormElementKey& a, const FormElementKey& b) { return a == b; }
- static const bool safeToCompareToEmptyOrDeleted = true;
-};
-
-struct FormElementKeyHashTraits : WTF::GenericHashTraits<FormElementKey> {
- static void constructDeletedValue(FormElementKey& slot) { new (&slot) FormElementKey(WTF::HashTableDeletedValue); }
- static bool isDeletedValue(const FormElementKey& value) { return value.isHashTableDeletedValue(); }
-};
-
-class Document : public ContainerNode {
-public:
- static PassRefPtr<Document> create(Frame* frame)
- {
- return new Document(frame, false);
- }
- static PassRefPtr<Document> createXHTML(Frame* frame)
- {
- return new Document(frame, true);
- }
- virtual ~Document();
-
- virtual void removedLastRef();
-
- // Nodes belonging to this document hold "self-only" references -
- // these are enough to keep the document from being destroyed, but
- // not enough to keep it from removing its children. This allows a
- // node that outlives its document to still have a valid document
- // pointer without introducing reference cycles
-
- void selfOnlyRef()
- {
- ASSERT(!m_deletionHasBegun);
- ++m_selfOnlyRefCount;
- }
- void selfOnlyDeref()
- {
- ASSERT(!m_deletionHasBegun);
- --m_selfOnlyRefCount;
- if (!m_selfOnlyRefCount && !refCount()) {
-#ifndef NDEBUG
- m_deletionHasBegun = true;
-#endif
- delete this;
- }
- }
-
- // DOM methods & attributes for Document
-
- DocumentType* doctype() const { return m_docType.get(); }
-
- DOMImplementation* implementation() const;
- virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
- Element* documentElement() const;
- virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&);
- PassRefPtr<DocumentFragment> createDocumentFragment ();
- PassRefPtr<Text> createTextNode(const String& data);
- PassRefPtr<Comment> createComment(const String& data);
- PassRefPtr<CDATASection> createCDATASection(const String& data, ExceptionCode&);
- PassRefPtr<ProcessingInstruction> createProcessingInstruction(const String& target, const String& data, ExceptionCode&);
- PassRefPtr<Attr> createAttribute(const String& name, ExceptionCode& ec) { return createAttributeNS(String(), name, ec, true); }
- PassRefPtr<Attr> createAttributeNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode&, bool shouldIgnoreNamespaceChecks = false);
- PassRefPtr<EntityReference> createEntityReference(const String& name, ExceptionCode&);
- PassRefPtr<Node> importNode(Node* importedNode, bool deep, ExceptionCode&);
- virtual PassRefPtr<Element> createElementNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode&);
- PassRefPtr<Element> createElement(const QualifiedName&, bool createdByParser, ExceptionCode& ec);
- Element* getElementById(const AtomicString&) const;
- bool hasElementWithId(AtomicStringImpl* id) const;
- bool containsMultipleElementsWithId(const AtomicString& elementId) { return m_duplicateIds.contains(elementId.impl()); }
-
- Element* elementFromPoint(int x, int y) const;
- String readyState() const;
- String inputEncoding() const;
- String defaultCharset() const;
-
- String charset() const { return inputEncoding(); }
- String characterSet() const { return inputEncoding(); }
-
- void setCharset(const String&);
- UScriptCode dominantScript() const;
-
- String contentLanguage() const { return m_contentLanguage; }
- void setContentLanguage(const String& lang) { m_contentLanguage = lang; }
-
- String xmlEncoding() const { return m_xmlEncoding; }
- String xmlVersion() const { return m_xmlVersion; }
- bool xmlStandalone() const { return m_xmlStandalone; }
-
- void setXMLEncoding(const String& encoding) { m_xmlEncoding = encoding; } // read-only property, only to be set from XMLTokenizer
- void setXMLVersion(const String&, ExceptionCode&);
- void setXMLStandalone(bool, ExceptionCode&);
-
- String documentURI() const { return m_documentURI; }
- void setDocumentURI(const String&);
-
- virtual KURL baseURI() const;
-
- PassRefPtr<Node> adoptNode(PassRefPtr<Node> source, ExceptionCode&);
-
- PassRefPtr<HTMLCollection> images();
- PassRefPtr<HTMLCollection> embeds();
- PassRefPtr<HTMLCollection> plugins(); // an alias for embeds() required for the JS DOM bindings.
- PassRefPtr<HTMLCollection> applets();
- PassRefPtr<HTMLCollection> links();
- PassRefPtr<HTMLCollection> forms();
- PassRefPtr<HTMLCollection> anchors();
- PassRefPtr<HTMLCollection> all();
- PassRefPtr<HTMLCollection> objects();
- PassRefPtr<HTMLCollection> scripts();
- PassRefPtr<HTMLCollection> windowNamedItems(const String& name);
- PassRefPtr<HTMLCollection> documentNamedItems(const String& name);
-
- HTMLCollection::CollectionInfo* collectionInfo(HTMLCollection::Type type)
- {
- ASSERT(type >= HTMLCollection::FirstUnnamedDocumentCachedType);
- unsigned index = type - HTMLCollection::FirstUnnamedDocumentCachedType;
- ASSERT(index < HTMLCollection::NumUnnamedDocumentCachedTypes);
- return &m_collectionInfo[index];
- }
-
- HTMLCollection::CollectionInfo* nameCollectionInfo(HTMLCollection::Type, const AtomicString& name);
-
- // DOM methods overridden from parent classes
-
- virtual String nodeName() const;
- virtual NodeType nodeType() const;
-
- // Other methods (not part of DOM)
- virtual bool isDocumentNode() const { return true; }
- virtual bool isHTMLDocument() const { return false; }
- virtual bool isImageDocument() const { return false; }
-#if ENABLE(SVG)
- virtual bool isSVGDocument() const { return false; }
-#endif
- virtual bool isPluginDocument() const { return false; }
- virtual bool isMediaDocument() const { return false; }
-
- CSSStyleSelector* styleSelector() const { return m_styleSelector; }
-
- Element* getElementByAccessKey(const String& key) const;
-
- /**
- * Updates the pending sheet count and then calls updateStyleSelector.
- */
- void removePendingSheet();
-
- /**
- * This method returns true if all top-level stylesheets have loaded (including
- * any @imports that they may be loading).
- */
- bool haveStylesheetsLoaded() const
- {
- return m_pendingStylesheets <= 0 || m_ignorePendingStylesheets
-#if USE(LOW_BANDWIDTH_DISPLAY)
- || m_inLowBandwidthDisplay
-#endif
- ;
- }
-
- /**
- * Increments the number of pending sheets. The <link> elements
- * invoke this to add themselves to the loading list.
- */
- void addPendingSheet() { m_pendingStylesheets++; }
-
- void addStyleSheetCandidateNode(Node*, bool createdByParser);
- void removeStyleSheetCandidateNode(Node*);
-
- bool gotoAnchorNeededAfterStylesheetsLoad() { return m_gotoAnchorNeededAfterStylesheetsLoad; }
- void setGotoAnchorNeededAfterStylesheetsLoad(bool b) { m_gotoAnchorNeededAfterStylesheetsLoad = b; }
-
- /**
- * Called when one or more stylesheets in the document may have been added, removed or changed.
- *
- * Creates a new style selector and assign it to this document. This is done by iterating through all nodes in
- * document (or those before <BODY> in a HTML document), searching for stylesheets. Stylesheets can be contained in
- * <LINK>, <STYLE> or <BODY> elements, as well as processing instructions (XML documents only). A list is
- * constructed from these which is used to create the a new style selector which collates all of the stylesheets
- * found and is used to calculate the derived styles for all rendering objects.
- */
- void updateStyleSelector();
-
- void recalcStyleSelector();
-
- bool usesDescendantRules() const { return m_usesDescendantRules; }
- void setUsesDescendantRules(bool b) { m_usesDescendantRules = b; }
- bool usesSiblingRules() const { return m_usesSiblingRules; }
- void setUsesSiblingRules(bool b) { m_usesSiblingRules = b; }
- bool usesFirstLineRules() const { return m_usesFirstLineRules; }
- void setUsesFirstLineRules(bool b) { m_usesFirstLineRules = b; }
- bool usesFirstLetterRules() const { return m_usesFirstLetterRules; }
- void setUsesFirstLetterRules(bool b) { m_usesFirstLetterRules = b; }
-
- // Machinery for saving and restoring state when you leave and then go back to a page.
- void registerFormElementWithState(HTMLFormControlElementWithState* e) { m_formElementsWithState.add(e); }
- void unregisterFormElementWithState(HTMLFormControlElementWithState* e) { m_formElementsWithState.remove(e); }
- Vector<String> formElementsState() const;
- void setStateForNewFormElements(const Vector<String>&);
- bool hasStateForNewFormElements() const;
- bool takeStateForFormElement(AtomicStringImpl* name, AtomicStringImpl* type, String& state);
-
- FrameView* view() const; // can be NULL
- Frame* frame() const { return m_frame; } // can be NULL
- Page* page() const; // can be NULL
- Settings* settings() const; // can be NULL
-
- PassRefPtr<Range> createRange();
-
- PassRefPtr<NodeIterator> createNodeIterator(Node* root, unsigned whatToShow,
- PassRefPtr<NodeFilter>, bool expandEntityReferences, ExceptionCode&);
-
- PassRefPtr<TreeWalker> createTreeWalker(Node* root, unsigned whatToShow,
- PassRefPtr<NodeFilter>, bool expandEntityReferences, ExceptionCode&);
-
- // Special support for editing
- PassRefPtr<CSSStyleDeclaration> createCSSStyleDeclaration();
- PassRefPtr<EditingText> createEditingTextNode(const String&);
-
- virtual void recalcStyle( StyleChange = NoChange );
- virtual void updateRendering();
- void updateLayout();
- void updateLayoutIgnorePendingStylesheets();
- static void updateDocumentsRendering();
- DocLoader* docLoader() { return m_docLoader; }
-
- virtual void attach();
- virtual void detach();
-
- void clearFramePointer();
-
- RenderArena* renderArena() { return m_renderArena; }
-
- void clearAXObjectCache();
- AXObjectCache* axObjectCache() const;
-
- // to get visually ordered hebrew and arabic pages right
- void setVisuallyOrdered();
-
- void open(Document* ownerDocument = 0);
- void implicitOpen();
- void close();
- void implicitClose();
- void cancelParsing();
-
- void write(const String& text, Document* ownerDocument = 0);
- void writeln(const String& text, Document* ownerDocument = 0);
- void finishParsing();
- void clear();
-
- bool wellFormed() const { return m_wellFormed; }
-
- const KURL& url() const { return m_url; }
- void setURL(const KURL&);
-
- const KURL& baseURL() const { return m_baseURL; }
- // Setting the BaseElementURL will change the baseURL.
- void setBaseElementURL(const KURL&);
-
- const String& baseTarget() const { return m_baseTarget; }
- // Setting the BaseElementTarget will change the baseTarget.
- void setBaseElementTarget(const String& baseTarget) { m_baseTarget = baseTarget; }
-
- KURL completeURL(const String&) const;
-
- unsigned visitedLinkHash(const AtomicString& attributeURL) const;
-
- // from cachedObjectClient
- virtual void setCSSStyleSheet(const String& url, const String& charset, const CachedCSSStyleSheet*);
-
-#if FRAME_LOADS_USER_STYLESHEET
- void setUserStyleSheet(const String& sheet);
-#endif
-
- String userStyleSheet() const;
-
- CSSStyleSheet* elementSheet();
- CSSStyleSheet* mappedElementSheet();
- virtual Tokenizer* createTokenizer();
- Tokenizer* tokenizer() { return m_tokenizer; }
-
- bool printing() const { return m_printing; }
- void setPrinting(bool p) { m_printing = p; }
-
- enum ParseMode { Compat, AlmostStrict, Strict };
-
- // Used by Chromium to know if it can just SIGKILL a renderer when navigating
- bool hasUnloadEventListener();
-
-private:
- virtual void determineParseMode() {}
-
-public:
- void setParseMode(ParseMode m) { m_parseMode = m; }
- ParseMode parseMode() const { return m_parseMode; }
-
- bool inCompatMode() const { return m_parseMode == Compat; }
- bool inAlmostStrictMode() const { return m_parseMode == AlmostStrict; }
- bool inStrictMode() const { return m_parseMode == Strict; }
-
- void setParsing(bool);
- bool parsing() const { return m_bParsing; }
- int minimumLayoutDelay();
- bool shouldScheduleLayout();
- int elapsedTime() const;
-
- void setTextColor(const Color& color) { m_textColor = color; }
- Color textColor() const { return m_textColor; }
-
- const Color& linkColor() const { return m_linkColor; }
- const Color& visitedLinkColor() const { return m_visitedLinkColor; }
- const Color& activeLinkColor() const { return m_activeLinkColor; }
- void setLinkColor(const Color& c) { m_linkColor = c; }
- void setVisitedLinkColor(const Color& c) { m_visitedLinkColor = c; }
- void setActiveLinkColor(const Color& c) { m_activeLinkColor = c; }
- void resetLinkColor();
- void resetVisitedLinkColor();
- void resetActiveLinkColor();
-
- MouseEventWithHitTestResults prepareMouseEvent(const HitTestRequest&, const IntPoint&, const PlatformMouseEvent&);
-
- virtual bool childTypeAllowed(NodeType);
- virtual PassRefPtr<Node> cloneNode(bool deep);
-
- virtual bool canReplaceChild(Node* newChild, Node* oldChild);
-
- StyleSheetList* styleSheets();
-
- /* Newly proposed CSS3 mechanism for selecting alternate
- stylesheets using the DOM. May be subject to change as
- spec matures. - dwh
- */
- String preferredStylesheetSet() const;
- String selectedStylesheetSet() const;
- void setSelectedStylesheetSet(const String&);
-
- bool setFocusedNode(PassRefPtr<Node>);
- Node* focusedNode() const { return m_focusedNode.get(); }
-
- // The m_ignoreAutofocus flag specifies whether or not the document has been changed by the user enough
- // for WebCore to ignore the autofocus attribute on any form controls
- bool ignoreAutofocus() const { return m_ignoreAutofocus; };
- void setIgnoreAutofocus(bool shouldIgnore = true) { m_ignoreAutofocus = shouldIgnore; };
-
- void setHoverNode(PassRefPtr<Node>);
- Node* hoverNode() const { return m_hoverNode.get(); }
-
- void setActiveNode(PassRefPtr<Node>);
- Node* activeNode() const { return m_activeNode.get(); }
-
- void focusedNodeRemoved();
- void removeFocusedNodeOfSubtree(Node*, bool amongChildrenOnly = false);
- void hoveredNodeDetached(Node*);
- void activeChainNodeDetached(Node*);
-
- // Updates for :target (CSS3 selector).
- void setCSSTarget(Node*);
- Node* getCSSTarget() const;
-
- void setDocumentChanged(bool);
-
- void attachNodeIterator(NodeIterator*);
- void detachNodeIterator(NodeIterator*);
-
- void attachRange(Range*);
- void detachRange(Range*);
-
- void nodeChildrenChanged(ContainerNode*);
- void nodeWillBeRemoved(Node*);
-
- void textInserted(Node*, unsigned offset, unsigned length);
- void textRemoved(Node*, unsigned offset, unsigned length);
- void textNodesMerged(Text* oldNode, unsigned offset);
- void textNodeSplit(Text* oldNode);
-
- DOMWindow* defaultView() const { return domWindow(); }
- DOMWindow* domWindow() const;
-
- PassRefPtr<Event> createEvent(const String& eventType, ExceptionCode&);
-
- // keep track of what types of event listeners are registered, so we don't
- // dispatch events unnecessarily
- enum ListenerType {
- DOMSUBTREEMODIFIED_LISTENER = 0x01,
- DOMNODEINSERTED_LISTENER = 0x02,
- DOMNODEREMOVED_LISTENER = 0x04,
- DOMNODEREMOVEDFROMDOCUMENT_LISTENER = 0x08,
- DOMNODEINSERTEDINTODOCUMENT_LISTENER = 0x10,
- DOMATTRMODIFIED_LISTENER = 0x20,
- DOMCHARACTERDATAMODIFIED_LISTENER = 0x40,
- OVERFLOWCHANGED_LISTENER = 0x80,
- ANIMATIONEND_LISTENER = 0x100,
- ANIMATIONSTART_LISTENER = 0x200,
- ANIMATIONITERATION_LISTENER = 0x400,
- TRANSITIONEND_LISTENER = 0x800
- };
-
- bool hasListenerType(ListenerType listenerType) const { return (m_listenerTypes & listenerType); }
- void addListenerType(ListenerType listenerType) { m_listenerTypes = m_listenerTypes | listenerType; }
-
- CSSStyleDeclaration* getOverrideStyle(Element*, const String& pseudoElt);
-
- void handleWindowEvent(Event*, bool useCapture);
- void setHTMLWindowEventListener(const AtomicString &eventType, PassRefPtr<EventListener>);
- EventListener* getHTMLWindowEventListener(const AtomicString &eventType);
- void removeHTMLWindowEventListener(const AtomicString &eventType);
-
- void setHTMLWindowEventListener(const AtomicString& eventType, Attribute*);
-
- void addWindowEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
- void removeWindowEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
- bool hasWindowEventListener(const AtomicString& eventType);
-
- void addPendingFrameUnloadEventCount();
- void removePendingFrameUnloadEventCount();
- void addPendingFrameBeforeUnloadEventCount();
- void removePendingFrameBeforeUnloadEventCount();
-
- PassRefPtr<EventListener> createHTMLEventListener(const String& functionName, const String& code, Node*);
-
- /**
- * Searches through the document, starting from fromNode, for the next selectable element that comes after fromNode.
- * The order followed is as specified in section 17.11.1 of the HTML4 spec, which is elements with tab indexes
- * first (from lowest to highest), and then elements without tab indexes (in document order).
- *
- * @param fromNode The node from which to start searching. The node after this will be focused. May be null.
- *
- * @return The focus node that comes after fromNode
- *
- * See http://www.w3.org/TR/html4/interact/forms.html#h-17.11.1
- */
- Node* nextFocusableNode(Node* start, KeyboardEvent*);
-
- /**
- * Searches through the document, starting from fromNode, for the previous selectable element (that comes _before_)
- * fromNode. The order followed is as specified in section 17.11.1 of the HTML4 spec, which is elements with tab
- * indexes first (from lowest to highest), and then elements without tab indexes (in document order).
- *
- * @param fromNode The node from which to start searching. The node before this will be focused. May be null.
- *
- * @return The focus node that comes before fromNode
- *
- * See http://www.w3.org/TR/html4/interact/forms.html#h-17.11.1
- */
- Node* previousFocusableNode(Node* start, KeyboardEvent*);
-
- int nodeAbsIndex(Node*);
- Node* nodeWithAbsIndex(int absIndex);
-
- /**
- * Handles a HTTP header equivalent set by a meta tag using <meta http-equiv="..." content="...">. This is called
- * when a meta tag is encountered during document parsing, and also when a script dynamically changes or adds a meta
- * tag. This enables scripts to use meta tags to perform refreshes and set expiry dates in addition to them being
- * specified in a HTML file.
- *
- * @param equiv The http header name (value of the meta tag's "equiv" attribute)
- * @param content The header value (value of the meta tag's "content" attribute)
- */
- void processHttpEquiv(const String& equiv, const String& content);
-
- void dispatchImageLoadEventSoon(HTMLImageLoader*);
- void dispatchImageLoadEventsNow();
- void removeImage(HTMLImageLoader*);
-
- // Returns the owning element in the parent document.
- // Returns 0 if this is the top level document.
- Element* ownerElement() const;
-
- String title() const { return m_title; }
- void setTitle(const String&, Element* titleElement = 0);
- void removeTitle(Element* titleElement);
-
- String cookie() const;
- void setCookie(const String&);
-
- String referrer() const;
-
- String domain() const;
- void setDomain(const String& newDomain);
-
- String lastModified() const;
-
- const KURL& cookieURL() const { return m_cookieURL; }
-
- const KURL& policyBaseURL() const { return m_policyBaseURL; }
- void setPolicyBaseURL(const KURL& url) { m_policyBaseURL = url; }
-
- // The following implements the rule from HTML 4 for what valid names are.
- // To get this right for all the XML cases, we probably have to improve this or move it
- // and make it sensitive to the type of document.
- static bool isValidName(const String&);
-
- // The following breaks a qualified name into a prefix and a local name.
- // It also does a validity check, and returns false if the qualified name
- // is invalid. It also sets ExceptionCode when name is invalid.
- static bool parseQualifiedName(const String& qualifiedName, String& prefix, String& localName, ExceptionCode&);
-
- // Checks to make sure prefix and namespace do not conflict (per DOM Core 3)
- static bool hasPrefixNamespaceMismatch(const QualifiedName&);
-
- void addElementById(const AtomicString& elementId, Element *element);
- void removeElementById(const AtomicString& elementId, Element *element);
-
- void addImageMap(HTMLMapElement*);
- void removeImageMap(HTMLMapElement*);
- HTMLMapElement* getImageMap(const String& url) const;
-
- HTMLElement* body();
- void setBody(PassRefPtr<HTMLElement>, ExceptionCode&);
-
- HTMLHeadElement* head();
-
- bool execCommand(const String& command, bool userInterface = false, const String& value = String());
- bool queryCommandEnabled(const String& command);
- bool queryCommandIndeterm(const String& command);
- bool queryCommandState(const String& command);
- bool queryCommandSupported(const String& command);
- String queryCommandValue(const String& command);
-
- void addMarker(Range*, DocumentMarker::MarkerType, String description = String());
- void addMarker(Node*, DocumentMarker);
- void copyMarkers(Node *srcNode, unsigned startOffset, int length, Node *dstNode, int delta, DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
- void removeMarkers(Range*, DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
- void removeMarkers(Node*, unsigned startOffset, int length, DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
- void removeMarkers(DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
- void removeMarkers(Node*);
- void repaintMarkers(DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
- void setRenderedRectForMarker(Node*, DocumentMarker, const IntRect&);
- void invalidateRenderedRectsForMarkersInRect(const IntRect&);
- void shiftMarkers(Node*, unsigned startOffset, int delta, DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
-
- DocumentMarker* markerContainingPoint(const IntPoint&, DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
- Vector<DocumentMarker> markersForNode(Node*);
- Vector<IntRect> renderedRectsForMarkers(DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
-
- // designMode support
- enum InheritedBool { off = false, on = true, inherit };
- void setDesignMode(InheritedBool value);
- InheritedBool getDesignMode() const;
- bool inDesignMode() const;
-
- Document* parentDocument() const;
- Document* topDocument() const;
-
- int docID() const { return m_docID; }
-
-#if ENABLE(XSLT)
- void applyXSLTransform(ProcessingInstruction* pi);
- void setTransformSource(void* doc);
- const void* transformSource() { return m_transformSource; }
- PassRefPtr<Document> transformSourceDocument() { return m_transformSourceDocument; }
- void setTransformSourceDocument(Document* doc) { m_transformSourceDocument = doc; }
-#endif
-
-#if ENABLE(XBL)
- // XBL methods
- XBLBindingManager* bindingManager() const { return m_bindingManager; }
-#endif
-
- void incDOMTreeVersion() { ++m_domtree_version; }
- unsigned domTreeVersion() const { return m_domtree_version; }
-
- void setDocType(PassRefPtr<DocumentType>);
-
- void finishedParsing();
-
-#if ENABLE(XPATH)
- // XPathEvaluator methods
- PassRefPtr<XPathExpression> createExpression(const String& expression,
- XPathNSResolver* resolver,
- ExceptionCode& ec);
- PassRefPtr<XPathNSResolver> createNSResolver(Node *nodeResolver);
- PassRefPtr<XPathResult> evaluate(const String& expression,
- Node* contextNode,
- XPathNSResolver* resolver,
- unsigned short type,
- XPathResult* result,
- ExceptionCode& ec);
-#endif // ENABLE(XPATH)
-
- enum PendingSheetLayout { NoLayoutWithPendingSheets, DidLayoutWithPendingSheets, IgnoreLayoutWithPendingSheets };
-
- bool didLayoutWithPendingStylesheets() const { return m_pendingSheetLayout == DidLayoutWithPendingSheets; }
-
- void setHasNodesWithPlaceholderStyle() { m_hasNodesWithPlaceholderStyle = true; }
-
- const String& iconURL() const { return m_iconURL; }
- void setIconURL(const String& iconURL, const String& type);
-
- void setUseSecureKeyboardEntryWhenActive(bool);
- bool useSecureKeyboardEntryWhenActive() const;
-
-#if USE(LOW_BANDWIDTH_DISPLAY)
- void setDocLoader(DocLoader* loader) { m_docLoader = loader; }
- bool inLowBandwidthDisplay() const { return m_inLowBandwidthDisplay; }
- void setLowBandwidthDisplay(bool lowBandWidth) { m_inLowBandwidthDisplay = lowBandWidth; }
-#endif
-
- void addNodeListCache() { ++m_numNodeListCaches; }
- void removeNodeListCache() { ASSERT(m_numNodeListCaches > 0); --m_numNodeListCaches; }
- bool hasNodeListCaches() const { return m_numNodeListCaches; }
-
- void updateFocusAppearanceSoon();
- void cancelFocusAppearanceUpdate();
-
- // FF method for accessing the selection added for compatability.
- DOMSelection* getSelection() const;
-
- // Extension for manipulating canvas drawing contexts for use in CSS
- CanvasRenderingContext2D* getCSSCanvasContext(const String& type, const String& name, int width, int height);
- HTMLCanvasElement* getCSSCanvasElement(const String& name);
-
- bool isDNSPrefetchEnabled() const { return m_isDNSPrefetchEnabled; }
- void initDNSPrefetchEnabled();
- void setDNSPrefetchControl(const WebCore::String&);
-
-protected:
- Document(Frame*, bool isXHTML);
-
-private:
- CSSStyleSelector* m_styleSelector;
- bool m_didCalculateStyleSelector;
-
- Frame* m_frame;
- DocLoader* m_docLoader;
- Tokenizer* m_tokenizer;
- bool m_wellFormed;
-
- // Document URLs.
- KURL m_url; // Document.URL: The URL from which this document was retrieved.
- KURL m_baseURL; // Node.baseURI: The URL to use when resolving relative URLs.
- KURL m_baseElementURL; // The URL set by the <base> element.
- KURL m_cookieURL; // The URL to use for cookie access.
- KURL m_policyBaseURL; // The policy URL for third-party cookie blocking.
-
- // Document.documentURI:
- // Although URL-like, Document.documentURI can actually be set to any
- // string by content. Document.documentURI affects m_baseURL unless the
- // document contains a <base> element, in which case the <base> element
- // takes precedence.
- String m_documentURI;
-
- String m_baseTarget;
-
- RefPtr<DocumentType> m_docType;
- mutable RefPtr<DOMImplementation> m_implementation;
-
- RefPtr<StyleSheet> m_sheet;
-#if FRAME_LOADS_USER_STYLESHEET
- String m_usersheet;
-#endif
-
- // Track the number of currently loading top-level stylesheets. Sheets
- // loaded using the @import directive are not included in this count.
- // We use this count of pending sheets to detect when we can begin attaching
- // elements.
- int m_pendingStylesheets;
-
- // But sometimes you need to ignore pending stylesheet count to
- // force an immediate layout when requested by JS.
- bool m_ignorePendingStylesheets;
-
- // If we do ignore the pending stylesheet count, then we need to add a boolean
- // to track that this happened so that we can do a full repaint when the stylesheets
- // do eventually load.
- PendingSheetLayout m_pendingSheetLayout;
-
- bool m_hasNodesWithPlaceholderStyle;
-
- RefPtr<CSSStyleSheet> m_elemSheet;
- RefPtr<CSSStyleSheet> m_mappedElementSheet;
-
- bool m_printing;
-
- bool m_ignoreAutofocus;
-
- ParseMode m_parseMode;
-
- Color m_textColor;
-
- RefPtr<Node> m_focusedNode;
- RefPtr<Node> m_hoverNode;
- RefPtr<Node> m_activeNode;
- mutable RefPtr<Element> m_documentElement;
-
- unsigned m_domtree_version;
-
- HashSet<NodeIterator*> m_nodeIterators;
- HashSet<Range*> m_ranges;
-
- unsigned short m_listenerTypes;
-
- RefPtr<StyleSheetList> m_styleSheets; // All of the stylesheets that are currently in effect for our media type and stylesheet set.
- ListHashSet<Node*> m_styleSheetCandidateNodes; // All of the nodes that could potentially provide stylesheets to the document (<link>, <style>, <?xml-stylesheet>)
-
- RegisteredEventListenerList m_windowEventListeners;
-
- typedef HashMap<FormElementKey, Vector<String>, FormElementKeyHash, FormElementKeyHashTraits> FormElementStateMap;
- ListHashSet<HTMLFormControlElementWithState*> m_formElementsWithState;
- FormElementStateMap m_stateForNewFormElements;
-
- Color m_linkColor;
- Color m_visitedLinkColor;
- Color m_activeLinkColor;
-
- String m_preferredStylesheetSet;
- String m_selectedStylesheetSet;
-
- bool m_loadingSheet;
- bool visuallyOrdered;
- bool m_bParsing;
- bool m_docChanged;
- bool m_inStyleRecalc;
- bool m_closeAfterStyleRecalc;
- bool m_usesDescendantRules;
- bool m_usesSiblingRules;
- bool m_usesFirstLineRules;
- bool m_usesFirstLetterRules;
- bool m_gotoAnchorNeededAfterStylesheetsLoad;
-
- bool m_isDNSPrefetchEnabled;
- bool m_haveExplicitlyDisabledDNSPrefetch;
-
- String m_title;
- bool m_titleSetExplicitly;
- RefPtr<Element> m_titleElement;
-
- RenderArena* m_renderArena;
-
- typedef std::pair<Vector<DocumentMarker>, Vector<IntRect> > MarkerMapVectorPair;
- typedef HashMap<RefPtr<Node>, MarkerMapVectorPair*> MarkerMap;
- MarkerMap m_markers;
-
- mutable AXObjectCache* m_axObjectCache;
-
- DeprecatedPtrList<HTMLImageLoader> m_imageLoadEventDispatchSoonList;
- DeprecatedPtrList<HTMLImageLoader> m_imageLoadEventDispatchingList;
- Timer<Document> m_imageLoadEventTimer;
-
- Timer<Document> m_updateFocusAppearanceTimer;
-
- Node* m_cssTarget;
-
- bool m_processingLoadEvent;
- double m_startTime;
- bool m_overMinimumLayoutThreshold;
-
-#if ENABLE(XSLT)
- void* m_transformSource;
- RefPtr<Document> m_transformSourceDocument;
-#endif
-
-#if ENABLE(XBL)
- XBLBindingManager* m_bindingManager; // The access point through which documents and elements communicate with XBL.
-#endif
-
- typedef HashMap<AtomicStringImpl*, HTMLMapElement*> ImageMapsByName;
- ImageMapsByName m_imageMapsByName;
-
- HashSet<Node*> m_disconnectedNodesWithEventListeners;
-
- int m_docID; // A unique document identifier used for things like document-specific mapped attributes.
-
- String m_xmlEncoding;
- String m_xmlVersion;
- bool m_xmlStandalone;
-
- String m_contentLanguage;
-
- // UScriptCode can be derived from non-Unicode charsets and help us select a fallback
- // font. Because it's derived from charset, it's a document-wide constant.
- // For instance, it'll be Latin, SimplifiedHan, TraditionalHan, Hiragana,
- // Hangul, Arabic and Hebrew for documents in ISO-8859-1, GBK, Big5, Shift_JIS,
- // EUC-KR, Windows-1256 and Windows-1255, respectively. In case of Japanese encodings,
- // either Hiragana or Katakana should work but Han does not because it does not
- // uniquely identify Japanese and as a result does not help the font selection.
- // Obviously, this does not work well for Unicode-encoded documents. In the meantime,
- // we can resort to the 'dominant' script of the current UI language.
- // In the future, we should refer to the value of xml:lang and lang to infer
- // this value for invididual text nodes. CSSStyleSelector might be a good place for that.
- // Moreover, the value of m_contentLanguage should be utilized as well.
- mutable UScriptCode m_dominantScript;
-
-public:
- bool inPageCache();
- void setInPageCache(bool flag);
-
- // Elements can register themselves for the "willSaveToCache()" and
- // "didRestoreFromCache()" callbacks
- void registerForCacheCallbacks(Element*);
- void unregisterForCacheCallbacks(Element*);
- void willSaveToCache();
- void didRestoreFromCache();
-
- void setShouldCreateRenderers(bool);
- bool shouldCreateRenderers();
-
- void setDecoder(PassRefPtr<TextResourceDecoder>);
- TextResourceDecoder* decoder() const { return m_decoder.get(); }
-
- UChar backslashAsCurrencySymbol() const;
-
-#if ENABLE(DASHBOARD_SUPPORT)
- void setDashboardRegionsDirty(bool f) { m_dashboardRegionsDirty = f; }
- bool dashboardRegionsDirty() const { return m_dashboardRegionsDirty; }
- bool hasDashboardRegions () const { return m_hasDashboardRegions; }
- void setHasDashboardRegions (bool f) { m_hasDashboardRegions = f; }
- const Vector<DashboardRegionValue>& dashboardRegions() const;
- void setDashboardRegions(const Vector<DashboardRegionValue>&);
-#endif
-
- void removeAllEventListenersFromAllNodes();
-
- void registerDisconnectedNodeWithEventListeners(Node*);
- void unregisterDisconnectedNodeWithEventListeners(Node*);
-
- HTMLFormElement::CheckedRadioButtons& checkedRadioButtons() { return m_checkedRadioButtons; }
-
-#if ENABLE(SVG)
- const SVGDocumentExtensions* svgExtensions();
- SVGDocumentExtensions* accessSVGExtensions();
-#endif
-
- void initSecurityContext();
- SecurityOrigin* securityOrigin() const { return m_securityOrigin.get(); }
-
- // Explicitly override the security origin for this document.
- // Note: It is dangerous to change the security origin of a document
- // that already contains content.
- void setSecurityOrigin(SecurityOrigin*);
-
- bool processingLoadEvent() const { return m_processingLoadEvent; }
-
-#if ENABLE(DATABASE)
- void addOpenDatabase(Database*);
- void removeOpenDatabase(Database*);
- DatabaseThread* databaseThread(); // Creates the thread as needed, but not if it has been already terminated.
- void setHasOpenDatabases() { m_hasOpenDatabases = true; }
- bool hasOpenDatabases() { return m_hasOpenDatabases; }
- void stopDatabases();
-#endif
-protected:
- void clearXMLVersion() { m_xmlVersion = String(); }
-
-private:
- void updateTitle();
- void removeAllDisconnectedNodeEventListeners();
- void imageLoadEventTimerFired(Timer<Document>*);
- void updateFocusAppearanceTimerFired(Timer<Document>*);
- void updateBaseURL();
-
- RefPtr<SecurityOrigin> m_securityOrigin;
-
- RenderObject* m_savedRenderer;
- int m_secureForms;
-
- RefPtr<TextResourceDecoder> m_decoder;
-
- // We maintain the invariant that m_duplicateIds is the count of all elements with a given ID
- // excluding the one referenced in m_elementsById, if any. This means it one less than the total count
- // when the first node with a given ID is cached, otherwise the same as the total count.
- mutable HashMap<AtomicStringImpl*, Element*> m_elementsById;
- mutable HashCountedSet<AtomicStringImpl*> m_duplicateIds;
-
- mutable HashMap<StringImpl*, Element*, CaseFoldingHash> m_elementsByAccessKey;
-
- InheritedBool m_designMode;
-
- int m_selfOnlyRefCount;
-
- HTMLFormElement::CheckedRadioButtons m_checkedRadioButtons;
-
- typedef HashMap<AtomicStringImpl*, HTMLCollection::CollectionInfo*> NamedCollectionMap;
- HTMLCollection::CollectionInfo m_collectionInfo[HTMLCollection::NumUnnamedDocumentCachedTypes];
- NamedCollectionMap m_nameCollectionInfo[HTMLCollection::NumNamedDocumentCachedTypes];
-
-#if ENABLE(XPATH)
- RefPtr<XPathEvaluator> m_xpathEvaluator;
-#endif
-
-#if ENABLE(SVG)
- SVGDocumentExtensions* m_svgExtensions;
-#endif
-
-#if ENABLE(DASHBOARD_SUPPORT)
- Vector<DashboardRegionValue> m_dashboardRegions;
- bool m_hasDashboardRegions;
- bool m_dashboardRegionsDirty;
-#endif
-
- HashMap<String, RefPtr<HTMLCanvasElement> > m_cssCanvasElements;
-
- mutable bool m_accessKeyMapValid;
- bool m_createRenderers;
- bool m_inPageCache;
- String m_iconURL;
-
- HashSet<Element*> m_pageCacheCallbackElements;
-
- bool m_useSecureKeyboardEntryWhenActive;
-
- bool m_isXHTML;
-
- unsigned m_numNodeListCaches;
-
-public:
- typedef HashMap<WebCore::Node*, JSNode*> JSWrapperCache;
- JSWrapperCache& wrapperCache() { return m_wrapperCache; }
-private:
- JSWrapperCache m_wrapperCache;
-
-#if ENABLE(DATABASE)
- RefPtr<DatabaseThread> m_databaseThread;
- bool m_hasOpenDatabases; // This never changes back to false, even as the database thread is closed.
- typedef HashSet<Database*> DatabaseSet;
- OwnPtr<DatabaseSet> m_openDatabaseSet;
-#endif
-
-#if USE(LOW_BANDWIDTH_DISPLAY)
- bool m_inLowBandwidthDisplay;
-#endif
-
-};
-
-inline bool Document::hasElementWithId(AtomicStringImpl* id) const
-{
- ASSERT(id);
- return m_elementsById.contains(id) || m_duplicateIds.contains(id);
-}
-
-} // namespace WebCore
-
-#endif // Document_h
diff --git a/webkit/pending/DragController.cpp b/webkit/pending/DragController.cpp
deleted file mode 100644
index f7c18c1..0000000
--- a/webkit/pending/DragController.cpp
+++ /dev/null
@@ -1,774 +0,0 @@
-/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "DragController.h"
-
-#include "CSSStyleDeclaration.h"
-#include "Clipboard.h"
-#include "ClipboardAccessPolicy.h"
-#include "DocLoader.h"
-#include "Document.h"
-#include "DocumentFragment.h"
-#include "DragActions.h"
-#include "DragClient.h"
-#include "DragData.h"
-#include "Editor.h"
-#include "EditorClient.h"
-#include "Element.h"
-#include "EventHandler.h"
-#include "FloatRect.h"
-#include "Frame.h"
-#include "FrameLoader.h"
-#include "FrameView.h"
-#include "HTMLAnchorElement.h"
-#include "HTMLInputElement.h"
-#include "HTMLNames.h"
-#include "HitTestResult.h"
-#include "Image.h"
-#include "MoveSelectionCommand.h"
-#include "Node.h"
-#include "Page.h"
-#include "RenderFileUploadControl.h"
-#include "RenderImage.h"
-#include "ReplaceSelectionCommand.h"
-#include "ResourceRequest.h"
-#include "SelectionController.h"
-#include "Settings.h"
-#include "SystemTime.h"
-#include "Text.h"
-#include "markup.h"
-#include <wtf/RefPtr.h>
-
-namespace WebCore {
-
-static PlatformMouseEvent createMouseEvent(DragData* dragData)
-{
- // FIXME: We should fake modifier keys here.
- return PlatformMouseEvent(dragData->clientPosition(), dragData->globalPosition(),
- LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime());
-
-}
-
-DragController::DragController(Page* page, DragClient* client)
- : m_page(page)
- , m_client(client)
- , m_document(0)
- , m_dragInitiator(0)
- , m_dragDestinationAction(DragDestinationActionNone)
- , m_dragSourceAction(DragSourceActionNone)
- , m_didInitiateDrag(false)
- , m_isHandlingDrag(false)
- , m_dragOperation(DragOperationNone)
-{
-}
-
-DragController::~DragController()
-{
- m_client->dragControllerDestroyed();
-}
-
-static PassRefPtr<DocumentFragment> documentFragmentFromDragData(DragData* dragData, RefPtr<Range> context,
- bool allowPlainText, bool& chosePlainText)
-{
- ASSERT(dragData);
- chosePlainText = false;
-
- Document* document = context->ownerDocument();
- ASSERT(document);
- if (document && dragData->containsCompatibleContent()) {
- if (PassRefPtr<DocumentFragment> fragment = dragData->asFragment(document))
- return fragment;
-
- if (dragData->containsURL()) {
- String title;
- String url = dragData->asURL(&title);
- if (!url.isEmpty()) {
- ExceptionCode ec;
- RefPtr<HTMLAnchorElement> anchor = static_cast<HTMLAnchorElement*>(document->createElement("a", ec).get());
- anchor->setHref(url);
- RefPtr<Node> anchorText = document->createTextNode(title);
- anchor->appendChild(anchorText, ec);
- RefPtr<DocumentFragment> fragment = document->createDocumentFragment();
- fragment->appendChild(anchor, ec);
- return fragment.get();
- }
- }
- }
- if (allowPlainText && dragData->containsPlainText()) {
- chosePlainText = true;
- return createFragmentFromText(context.get(), dragData->asPlainText()).get();
- }
-
- return 0;
-}
-
-bool DragController::dragIsMove(SelectionController* selection, DragData* dragData)
-{
- return m_document == m_dragInitiator
- && selection->isContentEditable()
- && !isCopyKeyDown();
-}
-
-void DragController::cancelDrag()
-{
- m_page->dragCaretController()->clear();
-}
-
-void DragController::dragEnded()
-{
- m_dragInitiator = 0;
- m_didInitiateDrag = false;
- m_page->dragCaretController()->clear();
-}
-
-DragOperation DragController::dragEntered(DragData* dragData)
-{
- return dragEnteredOrUpdated(dragData);
-}
-
-void DragController::dragExited(DragData* dragData)
-{
- ASSERT(dragData);
- Frame* mainFrame = m_page->mainFrame();
-
- if (RefPtr<FrameView> v = mainFrame->view()) {
- ClipboardAccessPolicy policy = mainFrame->loader()->baseURL().isLocalFile() ? ClipboardReadable : ClipboardTypesReadable;
- RefPtr<Clipboard> clipboard = dragData->createClipboard(policy);
- clipboard->setSourceOperation(dragData->draggingSourceOperationMask());
- mainFrame->eventHandler()->cancelDragAndDrop(createMouseEvent(dragData), clipboard.get());
- clipboard->setAccessPolicy(ClipboardNumb); // invalidate clipboard here for security
- }
-
- cancelDrag();
- m_document = 0;
-}
-
-DragOperation DragController::dragUpdated(DragData* dragData)
-{
- return dragEnteredOrUpdated(dragData);
-}
-
-bool DragController::performDrag(DragData* dragData)
-{
- ASSERT(dragData);
- m_document = m_page->mainFrame()->documentAtPoint(dragData->clientPosition());
- if (m_isHandlingDrag) {
- ASSERT(m_dragDestinationAction & DragDestinationActionDHTML);
- m_client->willPerformDragDestinationAction(DragDestinationActionDHTML, dragData);
- RefPtr<Frame> mainFrame = m_page->mainFrame();
- if (mainFrame->view()) {
- // Sending an event can result in the destruction of the view and part.
- RefPtr<Clipboard> clipboard = dragData->createClipboard(ClipboardReadable);
- clipboard->setSourceOperation(dragData->draggingSourceOperationMask());
- mainFrame->eventHandler()->performDragAndDrop(createMouseEvent(dragData), clipboard.get());
- clipboard->setAccessPolicy(ClipboardNumb); // invalidate clipboard here for security
- }
- m_document = 0;
- return true;
- }
-
- if ((m_dragDestinationAction & DragDestinationActionEdit) && concludeDrag(dragData, m_dragDestinationAction)) {
- m_document = 0;
- return true;
- }
-
- m_document = 0;
-
- if (operationForLoad(dragData) == DragOperationNone)
- return false;
-
- m_client->willPerformDragDestinationAction(DragDestinationActionLoad, dragData);
- m_page->mainFrame()->loader()->load(ResourceRequest(dragData->asURL()));
- return true;
-}
-
-DragOperation DragController::dragEnteredOrUpdated(DragData* dragData)
-{
- ASSERT(dragData);
- IntPoint windowPoint = dragData->clientPosition();
-
- Document* newDraggingDoc = 0;
- if (Frame* frame = m_page->mainFrame())
- newDraggingDoc = frame->documentAtPoint(windowPoint);
- if (m_document != newDraggingDoc) {
- if (m_document)
- cancelDrag();
- m_document = newDraggingDoc;
- }
-
- m_dragDestinationAction = m_client->actionMaskForDrag(dragData);
-
- DragOperation operation = DragOperationNone;
-
- if (m_dragDestinationAction == DragDestinationActionNone)
- cancelDrag();
- else {
- operation = tryDocumentDrag(dragData, m_dragDestinationAction);
- if (operation == DragOperationNone && (m_dragDestinationAction & DragDestinationActionLoad))
- return operationForLoad(dragData);
- }
-
- return operation;
-}
-
-static HTMLInputElement* asFileInput(Node* node)
-{
- ASSERT(node);
-
- // The button for a FILE input is a sub element with no set input type
- // In order to get around this problem we assume any non-FILE input element
- // is this internal button, and try querying the shadow parent node.
- if (node->hasTagName(HTMLNames::inputTag) && node->isShadowNode() && static_cast<HTMLInputElement*>(node)->inputType() != HTMLInputElement::FILE)
- node = node->shadowParentNode();
-
- if (!node || !node->hasTagName(HTMLNames::inputTag))
- return 0;
-
- HTMLInputElement* inputElem = static_cast<HTMLInputElement*>(node);
- if (inputElem->inputType() == HTMLInputElement::FILE)
- return inputElem;
-
- return 0;
-}
-
-DragOperation DragController::tryDocumentDrag(DragData* dragData, DragDestinationAction actionMask)
-{
- ASSERT(dragData);
-
- if (!m_document)
- return DragOperationNone;
-
- DragOperation operation = DragOperationNone;
- if (actionMask & DragDestinationActionDHTML)
- operation = tryDHTMLDrag(dragData);
- m_isHandlingDrag = operation != DragOperationNone;
-
- RefPtr<FrameView> frameView = m_document->view();
- if (!frameView)
- return operation;
-
- if ((actionMask & DragDestinationActionEdit) && !m_isHandlingDrag && canProcessDrag(dragData)) {
- if (dragData->containsColor())
- return DragOperationGeneric;
-
- IntPoint dragPos = dragData->clientPosition();
- IntPoint point = frameView->windowToContents(dragPos);
- Element* element = m_document->elementFromPoint(point.x(), point.y());
- ASSERT(element);
- Frame* innerFrame = element->document()->frame();
- ASSERT(innerFrame);
- if (!asFileInput(element)) {
- Selection dragCaret;
- if (Frame* frame = m_document->frame())
- dragCaret = frame->visiblePositionForPoint(point);
- m_page->dragCaretController()->setSelection(dragCaret);
- }
-
- return dragIsMove(innerFrame->selection(), dragData) ? DragOperationMove : DragOperationCopy;
- }
-
- m_page->dragCaretController()->clear();
- return operation;
-}
-
-DragSourceAction DragController::delegateDragSourceAction(const IntPoint& windowPoint)
-{
- m_dragSourceAction = m_client->dragSourceActionMaskForPoint(windowPoint);
- return m_dragSourceAction;
-}
-
-DragOperation DragController::operationForLoad(DragData* dragData)
-{
- ASSERT(dragData);
- Document* doc = 0;
- doc = m_page->mainFrame()->documentAtPoint(dragData->clientPosition());
- if (doc && (m_didInitiateDrag || doc->isPluginDocument() || (doc->frame() && doc->frame()->editor()->clientIsEditable())))
- return DragOperationNone;
- return dragOperation(dragData);
-}
-
-static bool setSelectionToDragCaret(Frame* frame, Selection& dragCaret, RefPtr<Range>& range, const IntPoint& point)
-{
- frame->selection()->setSelection(dragCaret);
- if (frame->selection()->isNone()) {
- dragCaret = frame->visiblePositionForPoint(point);
- frame->selection()->setSelection(dragCaret);
- range = dragCaret.toRange();
- }
- return !frame->selection()->isNone() && frame->selection()->isContentEditable();
-}
-
-bool DragController::concludeDrag(DragData* dragData, DragDestinationAction actionMask)
-{
- ASSERT(dragData);
- ASSERT(!m_isHandlingDrag);
- ASSERT(actionMask & DragDestinationActionEdit);
-
- if (!m_document)
- return false;
-
- IntPoint point = m_document->view()->windowToContents(dragData->clientPosition());
- Element* element = m_document->elementFromPoint(point.x(), point.y());
- ASSERT(element);
- Frame* innerFrame = element->ownerDocument()->frame();
- ASSERT(innerFrame);
-
- if (dragData->containsColor()) {
- Color color = dragData->asColor();
- if (!color.isValid())
- return false;
- if (!innerFrame)
- return false;
- RefPtr<Range> innerRange = innerFrame->selection()->toRange();
- RefPtr<CSSStyleDeclaration> style = m_document->createCSSStyleDeclaration();
- ExceptionCode ec;
- style->setProperty("color", color.name(), ec);
- if (!innerFrame->editor()->shouldApplyStyle(style.get(), innerRange.get()))
- return false;
- m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData);
- innerFrame->editor()->applyStyle(style.get(), EditActionSetColor);
- return true;
- }
-
- if (!m_page->dragController()->canProcessDrag(dragData)) {
- m_page->dragCaretController()->clear();
- return false;
- }
-
- if (HTMLInputElement* fileInput = asFileInput(element)) {
-
- if (!fileInput->isEnabled())
- return false;
-
- if (!dragData->containsFiles())
- return false;
-
- Vector<String> filenames;
- dragData->asFilenames(filenames);
- if (filenames.isEmpty())
- return false;
-
- // Ugly. For security none of the API's available to us to set the input value
- // on file inputs. Even forcing a change in HTMLInputElement doesn't work as
- // RenderFileUploadControl clears the file when doing updateFromElement()
- RenderFileUploadControl* renderer = static_cast<RenderFileUploadControl*>(fileInput->renderer());
-
- if (!renderer)
- return false;
-
- // Only take the first filename as <input type="file" /> can only accept one
- renderer->receiveDroppedFile(filenames[0]);
- return true;
- }
-
- Selection dragCaret(m_page->dragCaretController()->selection());
- m_page->dragCaretController()->clear();
- RefPtr<Range> range = dragCaret.toRange();
-
- // For range to be null a WebKit client must have done something bad while
- // manually controlling drag behaviour
- if (!range)
- return false;
- DocLoader* loader = range->ownerDocument()->docLoader();
- loader->setAllowStaleResources(true);
- if (dragIsMove(innerFrame->selection(), dragData) || dragCaret.isContentRichlyEditable()) {
- bool chosePlainText = false;
- RefPtr<DocumentFragment> fragment = documentFragmentFromDragData(dragData, range, true, chosePlainText);
- if (!fragment || !innerFrame->editor()->shouldInsertFragment(fragment, range, EditorInsertActionDropped)) {
- loader->setAllowStaleResources(false);
- return false;
- }
-
- m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData);
- if (dragIsMove(innerFrame->selection(), dragData)) {
- bool smartMove = innerFrame->selectionGranularity() == WordGranularity
- && innerFrame->editor()->smartInsertDeleteEnabled()
- && dragData->canSmartReplace();
- applyCommand(MoveSelectionCommand::create(fragment, dragCaret.base(), smartMove));
- } else {
- if (setSelectionToDragCaret(innerFrame, dragCaret, range, point))
- applyCommand(ReplaceSelectionCommand::create(m_document, fragment, true, dragData->canSmartReplace(), chosePlainText));
- }
- } else {
- String text = dragData->asPlainText();
- if (text.isEmpty() || !innerFrame->editor()->shouldInsertText(text, range.get(), EditorInsertActionDropped)) {
- loader->setAllowStaleResources(false);
- return false;
- }
-
- m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData);
- if (setSelectionToDragCaret(innerFrame, dragCaret, range, point))
- applyCommand(ReplaceSelectionCommand::create(m_document, createFragmentFromText(range.get(), text), true, false, true));
- }
- loader->setAllowStaleResources(false);
-
- return true;
-}
-
-
-bool DragController::canProcessDrag(DragData* dragData)
-{
- ASSERT(dragData);
-
- if (!dragData->containsCompatibleContent())
- return false;
-
- IntPoint point = m_page->mainFrame()->view()->windowToContents(dragData->clientPosition());
- HitTestResult result = HitTestResult(point);
- if (!m_page->mainFrame()->contentRenderer())
- return false;
-
- result = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, true);
-
- if (!result.innerNonSharedNode())
- return false;
-
- if (dragData->containsFiles() && asFileInput(result.innerNonSharedNode()))
- return true;
-
- if (!result.innerNonSharedNode()->isContentEditable())
- return false;
-
- if (m_didInitiateDrag && m_document == m_dragInitiator && result.isSelected())
- return false;
-
- return true;
-}
-
-DragOperation DragController::tryDHTMLDrag(DragData* dragData)
-{
- ASSERT(dragData);
- ASSERT(m_document);
- DragOperation op = DragOperationNone;
- RefPtr<Frame> frame = m_page->mainFrame();
- RefPtr<FrameView> viewProtector = frame->view();
- if (!viewProtector)
- return DragOperationNone;
-
- ClipboardAccessPolicy policy = frame->loader()->baseURL().isLocalFile() ? ClipboardReadable : ClipboardTypesReadable;
- RefPtr<Clipboard> clipboard = dragData->createClipboard(policy);
- DragOperation srcOp = dragData->draggingSourceOperationMask();
- clipboard->setSourceOperation(srcOp);
-
- PlatformMouseEvent event = createMouseEvent(dragData);
- if (frame->eventHandler()->updateDragAndDrop(event, clipboard.get())) {
- // *op unchanged if no source op was set
- if (!clipboard->destinationOperation(op)) {
- // The element accepted but they didn't pick an operation, so we pick one for them
- // (as does WinIE).
- if (srcOp & DragOperationCopy)
- op = DragOperationCopy;
- else if (srcOp & DragOperationMove || srcOp & DragOperationGeneric)
- op = DragOperationMove;
- else if (srcOp & DragOperationLink)
- op = DragOperationLink;
- else
- op = DragOperationGeneric;
- } else if (!(op & srcOp)) {
- op = DragOperationNone;
- }
-
- clipboard->setAccessPolicy(ClipboardNumb); // invalidate clipboard here for security
- return op;
- }
- return op;
-}
-
-bool DragController::mayStartDragAtEventLocation(const Frame* frame, const IntPoint& framePos)
-{
- ASSERT(frame);
- ASSERT(frame->settings());
-
- if (!frame->view() || !frame->contentRenderer())
- return false;
-
- HitTestResult mouseDownTarget = HitTestResult(framePos);
-
- mouseDownTarget = frame->eventHandler()->hitTestResultAtPoint(framePos, true);
-
- if (mouseDownTarget.image()
- && !mouseDownTarget.absoluteImageURL().isEmpty()
- && frame->settings()->loadsImagesAutomatically()
- && m_dragSourceAction & DragSourceActionImage)
- return true;
-
- if (!mouseDownTarget.absoluteLinkURL().isEmpty()
- && m_dragSourceAction & DragSourceActionLink
- && mouseDownTarget.isLiveLink())
- return true;
-
- if (mouseDownTarget.isSelected()
- && m_dragSourceAction & DragSourceActionSelection)
- return true;
-
- return false;
-
-}
-
-static CachedImage* getCachedImage(Element* element)
-{
- ASSERT(element);
- RenderObject* renderer = element->renderer();
- if (!renderer || !renderer->isImage())
- return 0;
- RenderImage* image = static_cast<RenderImage*>(renderer);
- return image->cachedImage();
-}
-
-static Image* getImage(Element* element)
-{
- ASSERT(element);
- RenderObject* renderer = element->renderer();
- if (!renderer || !renderer->isImage())
- return 0;
-
- RenderImage* image = static_cast<RenderImage*>(renderer);
- if (image->cachedImage() && !image->cachedImage()->errorOccurred())
- return image->cachedImage()->image();
- return 0;
-}
-
-static void prepareClipboardForImageDrag(Frame* src, Clipboard* clipboard, Element* node, const KURL& linkURL, const KURL& imageURL, const String& label)
-{
- RefPtr<Range> range = src->document()->createRange();
- ExceptionCode ec = 0;
- range->selectNode(node, ec);
- ASSERT(ec == 0);
- src->selection()->setSelection(Selection(range.get(), DOWNSTREAM));
- clipboard->declareAndWriteDragImage(node, !linkURL.isEmpty() ? linkURL : imageURL, label, src);
-}
-
-static IntPoint dragLocForDHTMLDrag(const IntPoint& mouseDraggedPoint, const IntPoint& dragOrigin, const IntPoint& dragImageOffset, bool isLinkImage)
-{
- // dragImageOffset is the cursor position relative to the lower-left corner of the image.
-#if PLATFORM(MAC)
- // We add in the Y dimension because we are a flipped view, so adding moves the image down.
- const int yOffset = dragImageOffset.y();
-#else
- const int yOffset = -dragImageOffset.y();
-#endif
-
- if (isLinkImage)
- return IntPoint(mouseDraggedPoint.x() - dragImageOffset.x(), mouseDraggedPoint.y() + yOffset);
-
- return IntPoint(dragOrigin.x() - dragImageOffset.x(), dragOrigin.y() + yOffset);
-}
-
-static IntPoint dragLocForSelectionDrag(Frame* src)
-{
- IntRect draggingRect = enclosingIntRect(src->selectionRect());
- int xpos = draggingRect.right();
- xpos = draggingRect.x() < xpos ? draggingRect.x() : xpos;
- int ypos = draggingRect.bottom();
-#if PLATFORM(MAC)
- // Deal with flipped coordinates on Mac
- ypos = draggingRect.y() > ypos ? draggingRect.y() : ypos;
-#else
- ypos = draggingRect.y() < ypos ? draggingRect.y() : ypos;
-#endif
- return IntPoint(xpos, ypos);
-}
-
-bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation srcOp, const PlatformMouseEvent& dragEvent, const IntPoint& dragOrigin, bool isDHTMLDrag)
-{
- ASSERT(src);
- ASSERT(clipboard);
-
- if (!src->view() || !src->contentRenderer())
- return false;
-
- HitTestResult dragSource = HitTestResult(dragOrigin);
- dragSource = src->eventHandler()->hitTestResultAtPoint(dragOrigin, true);
- KURL linkURL = dragSource.absoluteLinkURL();
- KURL imageURL = dragSource.absoluteImageURL();
- bool isSelected = dragSource.isSelected();
-
- IntPoint mouseDraggedPoint = src->view()->windowToContents(dragEvent.pos());
-
- m_draggingImageURL = KURL();
- m_dragOperation = srcOp;
-
- DragImageRef dragImage = 0;
- IntPoint dragLoc(0, 0);
- IntPoint dragImageOffset(0, 0);
-
- if (isDHTMLDrag)
- dragImage = clipboard->createDragImage(dragImageOffset);
-
- // We allow DHTML/JS to set the drag image, even if its a link, image or text we're dragging.
- // This is in the spirit of the IE API, which allows overriding of pasteboard data and DragOp.
- if (dragImage) {
- dragLoc = dragLocForDHTMLDrag(mouseDraggedPoint, dragOrigin, dragImageOffset, !linkURL.isEmpty());
- m_dragOffset = dragImageOffset;
- }
-
- bool startedDrag = true; // optimism - we almost always manage to start the drag
-
- Node* node = dragSource.innerNonSharedNode();
-
- if (!imageURL.isEmpty() && node && node->isElementNode()
- && getImage(static_cast<Element*>(node))
- && (m_dragSourceAction & DragSourceActionImage)) {
- Element* element = static_cast<Element*>(node);
- if (!clipboard->hasData()) {
- m_draggingImageURL = imageURL;
- prepareClipboardForImageDrag(src, clipboard, element, linkURL, imageURL, dragSource.altDisplayString());
- }
-
- m_client->willPerformDragSourceAction(DragSourceActionImage, dragOrigin, clipboard);
-
- if (!dragImage) {
- IntRect imageRect = dragSource.imageRect();
- imageRect.setLocation(m_page->mainFrame()->view()->windowToContents(src->view()->contentsToWindow(imageRect.location())));
- doImageDrag(element, dragOrigin, dragSource.imageRect(), clipboard, src, m_dragOffset);
- } else
- // DHTML defined drag image
- doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false);
-
- } else if (!linkURL.isEmpty() && (m_dragSourceAction & DragSourceActionLink)) {
- if (!clipboard->hasData())
- // Simplify whitespace so the title put on the clipboard resembles what the user sees
- // on the web page. This includes replacing newlines with spaces.
- clipboard->writeURL(linkURL, dragSource.textContent().simplifyWhiteSpace(), src);
-
- m_client->willPerformDragSourceAction(DragSourceActionLink, dragOrigin, clipboard);
- if (!dragImage) {
- dragImage = m_client->createDragImageForLink(linkURL, dragSource.textContent(), src);
- IntSize size = dragImageSize(dragImage);
- m_dragOffset = IntPoint(-size.width() / 2, -LinkDragBorderInset);
- dragLoc = IntPoint(mouseDraggedPoint.x() + m_dragOffset.x(), mouseDraggedPoint.y() + m_dragOffset.y());
- }
- doSystemDrag(dragImage, dragLoc, mouseDraggedPoint, clipboard, src, true);
- } else if (isSelected && (m_dragSourceAction & DragSourceActionSelection)) {
- RefPtr<Range> selectionRange = src->selection()->toRange();
- ASSERT(selectionRange);
- if (!clipboard->hasData())
- clipboard->writeRange(selectionRange.get(), src);
- m_client->willPerformDragSourceAction(DragSourceActionSelection, dragOrigin, clipboard);
- if (!dragImage) {
- dragImage = createDragImageForSelection(src);
- dragLoc = dragLocForSelectionDrag(src);
- m_dragOffset = IntPoint((int)(dragOrigin.x() - dragLoc.x()), (int)(dragOrigin.y() - dragLoc.y()));
- }
- doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false);
- } else if (isDHTMLDrag) {
- ASSERT(m_dragSourceAction & DragSourceActionDHTML);
- m_client->willPerformDragSourceAction(DragSourceActionDHTML, dragOrigin, clipboard);
- doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false);
- } else {
- // Only way I know to get here is if to get here is if the original element clicked on in the mousedown is no longer
- // under the mousedown point, so linkURL, imageURL and isSelected are all false/empty.
- startedDrag = false;
- }
-
- if (dragImage)
- deleteDragImage(dragImage);
- return startedDrag;
-}
-
-void DragController::doImageDrag(Element* element, const IntPoint& dragOrigin, const IntRect& rect, Clipboard* clipboard, Frame* frame, IntPoint& dragImageOffset)
-{
- IntPoint mouseDownPoint = dragOrigin;
- DragImageRef dragImage;
- IntPoint origin;
-
- Image* image = getImage(element);
- if (image && image->size().height() * image->size().width() <= MaxOriginalImageArea
- && (dragImage = createDragImageFromImage(image))) {
- IntSize originalSize = rect.size();
- origin = rect.location();
-
- dragImage = fitDragImageToMaxSize(dragImage, rect.size(), maxDragImageSize());
- dragImage = dissolveDragImageToFraction(dragImage, DragImageAlpha);
- IntSize newSize = dragImageSize(dragImage);
-
- // Properly orient the drag image and orient it differently if it's smaller than the original
- float scale = newSize.width() / (float)originalSize.width();
- float dx = origin.x() - mouseDownPoint.x();
- dx *= scale;
- origin.setX((int)(dx + 0.5));
-#if PLATFORM(MAC)
- //Compensate for accursed flipped coordinates in cocoa
- origin.setY(origin.y() + originalSize.height());
-#endif
- float dy = origin.y() - mouseDownPoint.y();
- dy *= scale;
- origin.setY((int)(dy + 0.5));
- } else {
- dragImage = createDragImageIconForCachedImage(getCachedImage(element));
- if (dragImage)
- origin = IntPoint(DragIconRightInset - dragImageSize(dragImage).width(), DragIconBottomInset);
- }
-
- dragImageOffset.setX(mouseDownPoint.x() + origin.x());
- dragImageOffset.setY(mouseDownPoint.y() + origin.y());
- doSystemDrag(dragImage, dragImageOffset, dragOrigin, clipboard, frame, false);
-
- deleteDragImage(dragImage);
-}
-
-void DragController::doSystemDrag(DragImageRef image, const IntPoint& dragLoc, const IntPoint& eventPos, Clipboard* clipboard, Frame* frame, bool forLink)
-{
- m_didInitiateDrag = true;
- m_dragInitiator = frame->document();
- // Protect this frame and view, as a load may occur mid drag and attempt to unload this frame
- RefPtr<Frame> frameProtector = m_page->mainFrame();
- RefPtr<FrameView> viewProtector = frameProtector->view();
- m_client->startDrag(image, viewProtector->windowToContents(frame->view()->contentsToWindow(dragLoc)),
- viewProtector->windowToContents(frame->view()->contentsToWindow(eventPos)), clipboard, frameProtector.get(), forLink);
-
- // Drag has ended, dragEnded *should* have been called, however it is possible
- // for the UIDelegate to take over the drag, and fail to send the appropriate
- // drag termination event. As dragEnded just resets drag variables, we just
- // call it anyway to be on the safe side
- // Except if drag and drop happens asynchronously, in which case dragging
- // has not ended.
- //dragEnded();
-}
-
-// Manual drag caret manipulation
-void DragController::placeDragCaret(const IntPoint& windowPoint)
-{
- Frame* mainFrame = m_page->mainFrame();
- Document* newDraggingDoc = mainFrame->documentAtPoint(windowPoint);
- if (m_document != newDraggingDoc) {
- if (m_document)
- cancelDrag();
- m_document = newDraggingDoc;
- }
- if (!m_document)
- return;
- Frame* frame = m_document->frame();
- ASSERT(frame);
- FrameView* frameView = frame->view();
- if (!frameView)
- return;
- IntPoint framePoint = frameView->windowToContents(windowPoint);
- Selection dragCaret(frame->visiblePositionForPoint(framePoint));
- m_page->dragCaretController()->setSelection(dragCaret);
-}
-
-}
diff --git a/webkit/pending/EmptyClients.h b/webkit/pending/EmptyClients.h
deleted file mode 100644
index ed169dc..0000000
--- a/webkit/pending/EmptyClients.h
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Copyright (C) 2006 Eric Seidel (eric@webkit.org)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef EmptyClients_h
-#define EmptyClients_h
-
-#include "ChromeClient.h"
-#include "ContextMenuClient.h"
-#include "DragClient.h"
-#include "DocumentLoader.h"
-#include "EditCommand.h"
-#include "EditorClient.h"
-#include "FocusDirection.h"
-#include "FloatRect.h"
-#include "FrameLoaderClient.h"
-#include "InspectorClient.h"
-#include "ResourceError.h"
-#include "SharedBuffer.h"
-
-/*
- This file holds empty Client stubs for use by WebCore.
- Viewless element needs to create a dummy Page->Frame->FrameView tree for use in parsing or executing JavaScript.
- This tree depends heavily on Clients (usually provided by WebKit classes).
-
- This file was first created for SVGImage as it had no way to access the current Page (nor should it,
- since Images are not tied to a page).
- See http://bugs.webkit.org/show_bug.cgi?id=5971 for the original discussion about this file.
-
- Ideally, whenever you change a Client class, you should add a stub here.
- Brittle, yes. Unfortunate, yes. Hopefully temporary.
-*/
-
-namespace WebCore {
-
-class EmptyChromeClient : public ChromeClient {
-public:
- virtual ~EmptyChromeClient() { }
- virtual void chromeDestroyed() { }
-
- virtual void setWindowRect(const FloatRect&) { }
- virtual FloatRect windowRect() { return FloatRect(); }
-
- virtual FloatRect pageRect() { return FloatRect(); }
-
- virtual float scaleFactor() { return 1.f; }
-
- virtual void focus() { }
- virtual void unfocus() { }
-
- virtual bool canTakeFocus(FocusDirection) { return false; }
- virtual void takeFocus(FocusDirection) { }
-
- virtual Page* createWindow(Frame*, const FrameLoadRequest&, const WindowFeatures&) { return 0; }
- virtual void show() { }
-
- virtual bool canRunModal() { return false; }
- virtual void runModal() { }
-
- virtual void setToolbarsVisible(bool) { }
- virtual bool toolbarsVisible() { return false; }
-
- virtual void setStatusbarVisible(bool) { }
- virtual bool statusbarVisible() { return false; }
-
- virtual void setScrollbarsVisible(bool) { }
- virtual bool scrollbarsVisible() { return false; }
-
- virtual void setMenubarVisible(bool) { }
- virtual bool menubarVisible() { return false; }
-
- virtual void setResizable(bool) { }
-
- virtual void addMessageToConsole(const String& message, unsigned int lineNumber, const String& sourceID) { }
-
- virtual bool canRunBeforeUnloadConfirmPanel() { return false; }
- virtual bool runBeforeUnloadConfirmPanel(const String& message, Frame* frame) { return true; }
-
- virtual void closeWindowSoon() { }
-
- virtual void runJavaScriptAlert(Frame*, const String&) { }
- virtual bool runJavaScriptConfirm(Frame*, const String&) { return false; }
- virtual bool runJavaScriptPrompt(Frame*, const String& message, const String& defaultValue, String& result) { return false; }
- virtual bool shouldInterruptJavaScript() { return false; }
-
- virtual void setStatusbarText(const String&) { }
-
- virtual bool tabsToLinks() const { return false; }
-
- virtual IntRect windowResizerRect() const { return IntRect(); }
- virtual void addToDirtyRegion(const IntRect&) { }
- virtual void scrollBackingStore(int dx, int dy, const IntRect& scrollViewRect, const IntRect& clipRect) { }
- virtual void updateBackingStore() { }
-
- virtual void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags) { }
-
- virtual void setToolTip(const String&) { }
-
- virtual void print(Frame*) { }
-
- virtual void exceededDatabaseQuota(Frame*, const String&) { }
-};
-
-class EmptyFrameLoaderClient : public FrameLoaderClient {
-public:
- virtual ~EmptyFrameLoaderClient() { }
- virtual void frameLoaderDestroyed() { }
-
- virtual bool hasWebView() const { return true; } // mainly for assertions
- virtual bool hasFrameView() const { return true; } // ditto
-
- virtual void makeRepresentation(DocumentLoader*) { }
- virtual void forceLayout() { }
- virtual void forceLayoutForNonHTML() { }
-
- virtual void updateHistoryForCommit() { }
-
- virtual void updateHistoryForBackForwardNavigation() { }
- virtual void updateHistoryForReload() { }
- virtual void updateHistoryForStandardLoad() { }
- virtual void updateHistoryForInternalLoad() { }
-
- virtual void updateHistoryAfterClientRedirect() { }
-
- virtual void setCopiesOnScroll() { }
-
- virtual void detachedFromParent2() { }
- virtual void detachedFromParent3() { }
- virtual void detachedFromParent4() { }
-
- virtual void download(ResourceHandle*, const ResourceRequest&, const ResourceRequest&, const ResourceResponse&) { }
-
- virtual void assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&) { }
- virtual void dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse) { }
- virtual void dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) { }
- virtual void dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) { }
- virtual void dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&) { }
- virtual void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int lengthReceived) { }
- virtual void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier) { }
- virtual void dispatchDidFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError&) { }
- virtual bool dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length) { return false; }
-
- virtual void dispatchDidHandleOnloadEvents() { }
- virtual void dispatchDidReceiveServerRedirectForProvisionalLoad() { }
- virtual void dispatchDidCancelClientRedirect() { }
- virtual void dispatchWillPerformClientRedirect(const KURL&, double interval, double fireDate) { }
- virtual void dispatchDidChangeLocationWithinPage() { }
- virtual void dispatchWillClose() { }
- virtual void dispatchDidReceiveIcon() { }
- virtual void dispatchDidStartProvisionalLoad() { }
- virtual void dispatchDidReceiveTitle(const String& title) { }
- virtual void dispatchDidCommitLoad() { }
- virtual void dispatchDidFailProvisionalLoad(const ResourceError&) { }
- virtual void dispatchDidFailLoad(const ResourceError&) { }
- virtual void dispatchDidFinishDocumentLoad() { }
- virtual void dispatchDidFinishLoad() { }
- virtual void dispatchDidFirstLayout() { }
-
- virtual Frame* dispatchCreatePage() { return 0; }
- virtual void dispatchShow() { }
-
- virtual void dispatchDecidePolicyForMIMEType(FramePolicyFunction, const String& MIMEType, const ResourceRequest&) { }
- virtual void dispatchDecidePolicyForNewWindowAction(FramePolicyFunction, const NavigationAction&, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName) { }
- virtual void dispatchDecidePolicyForNavigationAction(FramePolicyFunction, const NavigationAction&, const ResourceRequest&, PassRefPtr<FormState>) { }
- virtual void cancelPolicyCheck() { }
-
- virtual void dispatchUnableToImplementPolicy(const ResourceError&) { }
-
- virtual void dispatchWillSubmitForm(FramePolicyFunction, PassRefPtr<FormState>) { }
-
- virtual void dispatchDidLoadMainResource(DocumentLoader*) { }
- virtual void revertToProvisionalState(DocumentLoader*) { }
- virtual void setMainDocumentError(DocumentLoader*, const ResourceError&) { }
-
- virtual void willChangeEstimatedProgress() { }
- virtual void didChangeEstimatedProgress() { }
- virtual void postProgressStartedNotification() { }
- virtual void postProgressEstimateChangedNotification() { }
- virtual void postProgressFinishedNotification() { }
-
- virtual void setMainFrameDocumentReady(bool) { }
-
- virtual void startDownload(const ResourceRequest&) { }
-
- virtual void willChangeTitle(DocumentLoader*) { }
- virtual void didChangeTitle(DocumentLoader*) { }
-
- virtual void committedLoad(DocumentLoader*, const char*, int) { }
- virtual void finishedLoading(DocumentLoader*) { }
-
- virtual ResourceError cancelledError(const ResourceRequest&) { return ResourceError(); }
- virtual ResourceError blockedError(const ResourceRequest&) { return ResourceError(); }
- virtual ResourceError cannotShowURLError(const ResourceRequest&) { return ResourceError(); }
- virtual ResourceError interruptForPolicyChangeError(const ResourceRequest&) { return ResourceError(); }
-
- virtual ResourceError cannotShowMIMETypeError(const ResourceResponse&) { return ResourceError(); }
- virtual ResourceError fileDoesNotExistError(const ResourceResponse&) { return ResourceError(); }
- virtual ResourceError pluginWillHandleLoadError(const ResourceResponse&) { return ResourceError(); }
-
- virtual bool shouldFallBack(const ResourceError&) { return false; }
-
- virtual bool canHandleRequest(const ResourceRequest&) const { return false; }
- virtual bool canShowMIMEType(const String& MIMEType) const { return false; }
- virtual bool representationExistsForURLScheme(const String& URLScheme) const { return false; }
- virtual String generatedMIMETypeForURLScheme(const String& URLScheme) const { return ""; }
-
- virtual void frameLoadCompleted() { }
- virtual void restoreViewState() { }
- virtual void provisionalLoadStarted() { }
- virtual bool shouldTreatURLAsSameAsCurrent(const KURL&) const { return false; }
- virtual void addHistoryItemForFragmentScroll() { }
- virtual void didFinishLoad() { }
- virtual void prepareForDataSourceReplacement() { }
-
- virtual PassRefPtr<DocumentLoader> createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData) { return DocumentLoader::create(request, substituteData); }
- virtual void setTitle(const String& title, const KURL&) { }
-
- virtual String userAgent(const KURL&) { return ""; }
-
- virtual void savePlatformDataToCachedPage(CachedPage*) { }
- virtual void transitionToCommittedFromCachedPage(CachedPage*) { }
- virtual void transitionToCommittedForNewPage() { }
-
- virtual void updateGlobalHistory(const KURL&) { }
- virtual bool shouldGoToHistoryItem(HistoryItem*) const { return false; }
- virtual void saveViewStateToItem(HistoryItem*) { }
- virtual bool canCachePage() const { return false; }
-
- virtual PassRefPtr<Frame> createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
- const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight) { return 0; }
- virtual Widget* createPlugin(const IntSize&,Element*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool) { return 0; }
- virtual Widget* createJavaAppletWidget(const IntSize&, Element*, const KURL&, const Vector<String>&, const Vector<String>&) { return 0; }
-
- virtual ObjectContentType objectContentType(const KURL& url, const String& mimeType) { return ObjectContentType(); }
- virtual String overrideMediaType() const { return String(); }
-
- virtual void redirectDataToPlugin(Widget*) {}
- virtual void windowObjectCleared() {}
- virtual void didPerformFirstNavigation() const {}
-
- virtual void registerForIconNotification(bool listen) {}
-
- virtual void unloadListenerChanged() {}
-
-#if PLATFORM(MAC)
- virtual NSCachedURLResponse* willCacheResponse(DocumentLoader*, unsigned long identifier, NSCachedURLResponse* response) const { return response; }
-#endif
-
-};
-
-class EmptyEditorClient : public EditorClient {
-public:
- virtual ~EmptyEditorClient() { }
- virtual void pageDestroyed() { }
-
- virtual bool shouldDeleteRange(Range*) { return false; }
- virtual bool shouldShowDeleteInterface(HTMLElement*) { return false; }
- virtual bool smartInsertDeleteEnabled() { return false; }
- virtual bool isContinuousSpellCheckingEnabled() { return false; }
- virtual void toggleContinuousSpellChecking() { }
- virtual bool isGrammarCheckingEnabled() { return false; }
- virtual void toggleGrammarChecking() { }
- virtual int spellCheckerDocumentTag() { return -1; }
-
- virtual bool selectWordBeforeMenuEvent() { return false; }
- virtual bool isEditable() { return false; }
-
- virtual bool shouldBeginEditing(Range*) { return false; }
- virtual bool shouldEndEditing(Range*) { return false; }
- virtual bool shouldInsertNode(Node*, Range*, EditorInsertAction) { return false; }
- // virtual bool shouldInsertNode(Node*, Range* replacingRange, WebViewInsertAction) { return false; }
- virtual bool shouldInsertText(const String&, Range*, EditorInsertAction) { return false; }
- virtual bool shouldChangeSelectedRange(Range* fromRange, Range* toRange, EAffinity, bool stillSelecting) { return false; }
-
- virtual bool shouldApplyStyle(CSSStyleDeclaration*, Range*) { return false; }
- virtual bool shouldMoveRangeAfterDelete(Range*, Range*) { return false; }
- // virtual bool shouldChangeTypingStyle(CSSStyleDeclaration* fromStyle, CSSStyleDeclaration* toStyle) { return false; }
- // virtual bool doCommandBySelector(SEL selector) { return false; }
- //
- virtual void didBeginEditing() { }
- virtual void respondToChangedContents() { }
- virtual void respondToChangedSelection() { }
- virtual void didEndEditing() { }
- virtual void didWriteSelectionToPasteboard() { }
- virtual void didSetSelectionTypesForPasteboard() { }
- // virtual void webViewDidChangeTypingStyle:(NSNotification *)notification { }
- // virtual void webViewDidChangeSelection:(NSNotification *)notification { }
- // virtual NSUndoManager* undoManagerForWebView:(WebView *)webView { return 0; }
-
- virtual void registerCommandForUndo(PassRefPtr<EditCommand>) { }
- virtual void registerCommandForRedo(PassRefPtr<EditCommand>) { }
- virtual void clearUndoRedoOperations() { }
-
- virtual bool canUndo() const { return false; }
- virtual bool canRedo() const { return false; }
-
- virtual void undo() { }
- virtual void redo() { }
-
- virtual void handleKeyboardEvent(KeyboardEvent*) { }
- virtual void handleInputMethodKeydown(KeyboardEvent*) { }
-
- virtual void textFieldDidBeginEditing(Element*) { }
- virtual void textFieldDidEndEditing(Element*) { }
- virtual void textDidChangeInTextField(Element*) { }
- virtual bool doTextFieldCommandFromEvent(Element*, KeyboardEvent*) { return false; }
- virtual void textWillBeDeletedInTextField(Element*) { }
- virtual void textDidChangeInTextArea(Element*) { }
-
-#if PLATFORM(MAC)
- virtual void markedTextAbandoned(Frame*) { }
-
- virtual NSString* userVisibleString(NSURL*) { return 0; }
-#ifdef BUILDING_ON_TIGER
- virtual NSArray* pasteboardTypesForSelection(Frame*) { return 0; }
-#endif
-#endif
- virtual void ignoreWordInSpellDocument(const String&) { }
- virtual void learnWord(const String&) { }
- virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength) { }
- virtual void checkGrammarOfString(const UChar*, int length, Vector<GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength) { }
- virtual void updateSpellingUIWithGrammarString(const String&, const GrammarDetail&) { }
- virtual void updateSpellingUIWithMisspelledWord(const String&) { }
- virtual void showSpellingUI(bool show) { }
- virtual bool spellingUIIsShowing() { return false; }
- virtual void getGuessesForWord(const String&, Vector<String>& guesses) { }
- virtual void setInputMethodState(bool enabled) { }
-
-
-};
-
-class EmptyContextMenuClient : public ContextMenuClient {
-public:
- virtual ~EmptyContextMenuClient() { }
- virtual void contextMenuDestroyed() { }
-
- virtual PlatformMenuDescription getCustomMenuFromDefaultItems(ContextMenu*) { return 0; }
- virtual void contextMenuItemSelected(ContextMenuItem*, const ContextMenu*) { }
-
- virtual void downloadURL(const KURL& url) { }
- virtual void copyImageToClipboard(const HitTestResult&) { }
- virtual void searchWithGoogle(const Frame*) { }
- virtual void lookUpInDictionary(Frame*) { }
- virtual void speak(const String&) { }
- virtual void stopSpeaking() { }
-
-#if PLATFORM(MAC)
- virtual void searchWithSpotlight() { }
-#endif
-};
-
-class EmptyDragClient : public DragClient {
-public:
- virtual ~EmptyDragClient() {}
- virtual void willPerformDragDestinationAction(DragDestinationAction, DragData*) { }
- virtual void willPerformDragSourceAction(DragSourceAction, const IntPoint&, Clipboard*) { }
- virtual DragDestinationAction actionMaskForDrag(DragData*) { return DragDestinationActionNone; }
- virtual DragSourceAction dragSourceActionMaskForPoint(const IntPoint&) { return DragSourceActionNone; }
- virtual void startDrag(DragImageRef, const IntPoint&, const IntPoint&, Clipboard*, Frame*, bool) { }
- virtual DragImageRef createDragImageForLink(KURL&, const String& label, Frame*) { return 0; }
- virtual void dragControllerDestroyed() { }
-};
-
-class EmptyInspectorClient : public InspectorClient {
-public:
- virtual ~EmptyInspectorClient() {}
-
- virtual void inspectorDestroyed() {};
-
- virtual Page* createPage() { return 0; };
-
- virtual String localizedStringsURL() { return String(); };
-
- virtual void showWindow() {};
- virtual void closeWindow() {};
-
- virtual void attachWindow() {};
- virtual void detachWindow() {};
-
- virtual void setAttachedWindowHeight(unsigned) {};
-
- virtual void highlight(Node*) {};
- virtual void hideHighlight() {};
- virtual void inspectedURLChanged(const String& newURL) {};
-};
-
-}
-
-#endif // EmptyClients_h
diff --git a/webkit/pending/EventHandler.cpp b/webkit/pending/EventHandler.cpp
deleted file mode 100644
index 4570913..0000000
--- a/webkit/pending/EventHandler.cpp
+++ /dev/null
@@ -1,2142 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "EventHandler.h"
-
-#include "AXObjectCache.h"
-#include "CachedImage.h"
-#include "ChromeClient.h"
-#include "Cursor.h"
-#include "Document.h"
-#include "DragController.h"
-#include "Editor.h"
-#include "EventNames.h"
-#include "FloatPoint.h"
-#include "FloatRect.h"
-#include "FocusController.h"
-#include "Frame.h"
-#include "FrameLoader.h"
-#include "FrameTree.h"
-#include "FrameView.h"
-#include "HitTestRequest.h"
-#include "HitTestResult.h"
-#include "HTMLFrameSetElement.h"
-#include "HTMLFrameElementBase.h"
-#include "HTMLInputElement.h"
-#include "HTMLNames.h"
-#include "Image.h"
-#include "KeyboardEvent.h"
-#include "MouseEvent.h"
-#include "MouseEventWithHitTestResults.h"
-#include "Page.h"
-#include "PlatformKeyboardEvent.h"
-#include "PlatformScrollBar.h"
-#include "PlatformWheelEvent.h"
-#include "RenderFrameSet.h"
-#include "RenderWidget.h"
-#include "RenderView.h"
-#include "SelectionController.h"
-#include "Settings.h"
-#include "TextEvent.h"
-
-#if ENABLE(SVG)
-#include "SVGDocument.h"
-#include "SVGNames.h"
-#endif
-
-namespace WebCore {
-
-using namespace EventNames;
-using namespace HTMLNames;
-
-// The link drag hysteresis is much larger than the others because there
-// needs to be enough space to cancel the link press without starting a link drag,
-// and because dragging links is rare.
-const int LinkDragHysteresis = 40;
-const int ImageDragHysteresis = 5;
-const int TextDragHysteresis = 3;
-const int GeneralDragHysteresis = 3;
-
-// Match key code of composition keydown event on windows.
-// IE sends VK_PROCESSKEY which has value 229;
-const int CompositionEventKeyCode = 229;
-
-#if ENABLE(SVG)
-using namespace SVGNames;
-#endif
-
-// When the autoscroll or the panScroll is triggered when do the scroll every 0.05s to make it smooth
-const double autoscrollInterval = 0.05;
-
-static Frame* subframeForTargetNode(Node* node);
-
-static inline void scrollAndAcceptEvent(float delta, ScrollDirection positiveDirection, ScrollDirection negativeDirection, bool pageScrollEnabled, PlatformWheelEvent& e, Node* node, float windowHeightOrWidth)
-{
- if (!delta)
- return;
-
- float pixelsToScroll = delta > 0 ? delta : -delta;
- if (!e.isContinuous() && !pageScrollEnabled) {
- if (node->renderer()->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByLine, pixelsToScroll))
- e.accept();
- } else {
- if (pageScrollEnabled)
- pixelsToScroll = windowHeightOrWidth;
- if (node->renderer()->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPixel, pixelsToScroll))
- e.accept();
- }
-}
-
-EventHandler::EventHandler(Frame* frame)
- : m_frame(frame)
- , m_mousePressed(false)
- , m_mouseDownMayStartSelect(false)
- , m_mouseDownMayStartDrag(false)
- , m_mouseDownWasSingleClickInSelection(false)
- , m_beganSelectingText(false)
- , m_panScrollInProgress(false)
- , m_hoverTimer(this, &EventHandler::hoverTimerFired)
- , m_autoscrollTimer(this, &EventHandler::autoscrollTimerFired)
- , m_autoscrollRenderer(0)
- , m_autoscrollInProgress(false)
- , m_mouseDownMayStartAutoscroll(false)
- , m_mouseDownWasInSubframe(false)
-#if ENABLE(SVG)
- , m_svgPan(false)
-#endif
- , m_resizeLayer(0)
- , m_capturingMouseEventsNode(0)
- , m_clickCount(0)
- , m_mouseDownTimestamp(0)
- , m_pendingFrameUnloadEventCount(0)
- , m_pendingFrameBeforeUnloadEventCount(0)
-#if PLATFORM(MAC)
- , m_mouseDownView(nil)
- , m_sendingEventToSubview(false)
- , m_activationEventNumber(0)
-#endif
-{
-}
-
-EventHandler::~EventHandler()
-{
-}
-
-EventHandler::EventHandlerDragState& EventHandler::dragState()
-{
- static EventHandlerDragState state;
- return state;
-}
-
-void EventHandler::clear()
-{
- m_hoverTimer.stop();
- m_resizeLayer = 0;
- m_nodeUnderMouse = 0;
- m_lastNodeUnderMouse = 0;
- m_lastMouseMoveEventSubframe = 0;
- m_lastScrollbarUnderMouse = 0;
- m_clickCount = 0;
- m_clickNode = 0;
- m_frameSetBeingResized = 0;
- m_dragTarget = 0;
- m_currentMousePosition = IntPoint();
- m_mousePressNode = 0;
- m_mousePressed = false;
- m_capturingMouseEventsNode = 0;
-}
-
-void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result)
-{
- Node* innerNode = result.targetNode();
- Selection newSelection;
-
- if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {
- VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
- if (pos.isNotNull()) {
- newSelection = Selection(pos);
- newSelection.expandUsingGranularity(WordGranularity);
- }
-
- if (newSelection.isRange()) {
- m_frame->setSelectionGranularity(WordGranularity);
- m_beganSelectingText = true;
- }
-
- if (m_frame->shouldChangeSelection(newSelection))
- m_frame->selection()->setSelection(newSelection);
- }
-}
-
-void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults& result)
-{
- if (!result.hitTestResult().isLiveLink())
- return selectClosestWordFromMouseEvent(result);
-
- Node* innerNode = result.targetNode();
-
- if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {
- Selection newSelection;
- Element* URLElement = result.hitTestResult().URLElement();
- VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
- if (pos.isNotNull() && pos.deepEquivalent().node()->isDescendantOf(URLElement))
- newSelection = Selection::selectionFromContentsOfNode(URLElement);
-
- if (newSelection.isRange()) {
- m_frame->setSelectionGranularity(WordGranularity);
- m_beganSelectingText = true;
- }
-
- if (m_frame->shouldChangeSelection(newSelection))
- m_frame->selection()->setSelection(newSelection);
- }
-}
-
-bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event)
-{
- if (event.event().button() != LeftButton)
- return false;
-
- if (m_frame->selection()->isRange())
- // A double-click when range is already selected
- // should not change the selection. So, do not call
- // selectClosestWordFromMouseEvent, but do set
- // m_beganSelectingText to prevent handleMouseReleaseEvent
- // from setting caret selection.
- m_beganSelectingText = true;
- else
- selectClosestWordFromMouseEvent(event);
-
- return true;
-}
-
-bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event)
-{
- if (event.event().button() != LeftButton)
- return false;
-
- Node* innerNode = event.targetNode();
- if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
- return false;
-
- Selection newSelection;
- VisiblePosition pos(innerNode->renderer()->positionForPoint(event.localPoint()));
- if (pos.isNotNull()) {
- newSelection = Selection(pos);
- newSelection.expandUsingGranularity(ParagraphGranularity);
- }
- if (newSelection.isRange()) {
- m_frame->setSelectionGranularity(ParagraphGranularity);
- m_beganSelectingText = true;
- }
-
- if (m_frame->shouldChangeSelection(newSelection))
- m_frame->selection()->setSelection(newSelection);
-
- return true;
-}
-
-bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event)
-{
- if (event.event().button() != LeftButton)
- return false;
-
- Node* innerNode = event.targetNode();
- if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
- return false;
-
- // Extend the selection if the Shift key is down, unless the click is in a link.
- bool extendSelection = event.event().shiftKey() && !event.isOverLink();
-
- // Don't restart the selection when the mouse is pressed on an
- // existing selection so we can allow for text dragging.
- IntPoint vPoint = m_frame->view()->windowToContents(event.event().pos());
- if (!extendSelection && m_frame->selection()->contains(vPoint)) {
- m_mouseDownWasSingleClickInSelection = true;
- return false;
- }
-
- VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(event.localPoint()));
- if (visiblePos.isNull())
- visiblePos = VisiblePosition(innerNode, 0, DOWNSTREAM);
- Position pos = visiblePos.deepEquivalent();
-
- Selection newSelection = m_frame->selection()->selection();
- if (extendSelection && newSelection.isCaretOrRange()) {
- m_frame->selection()->setLastChangeWasHorizontalExtension(false);
-
- // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection
- // was created right-to-left
- Position start = newSelection.start();
- Position end = newSelection.end();
- short before = Range::compareBoundaryPoints(pos.node(), pos.offset(), start.node(), start.offset());
- if (before <= 0)
- newSelection = Selection(pos, end);
- else
- newSelection = Selection(start, pos);
-
- if (m_frame->selectionGranularity() != CharacterGranularity)
- newSelection.expandUsingGranularity(m_frame->selectionGranularity());
- m_beganSelectingText = true;
- } else {
- newSelection = Selection(visiblePos);
- m_frame->setSelectionGranularity(CharacterGranularity);
- }
-
- if (m_frame->shouldChangeSelection(newSelection))
- m_frame->selection()->setSelection(newSelection);
-
- return true;
-}
-
-bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& event)
-{
- // Reset drag state.
- dragState().m_dragSrc = 0;
-
- bool singleClick = event.event().clickCount() <= 1;
-
- // If we got the event back, that must mean it wasn't prevented,
- // so it's allowed to start a drag or selection.
- m_mouseDownMayStartSelect = canMouseDownStartSelect(event.targetNode());
-
- // Careful that the drag starting logic stays in sync with eventMayStartDrag()
- m_mouseDownMayStartDrag = singleClick;
-
- m_mouseDownWasSingleClickInSelection = false;
-
- if (passWidgetMouseDownEventToWidget(event))
- return true;
-
-#if ENABLE(SVG)
- if (m_frame->document()->isSVGDocument() &&
- static_cast<SVGDocument*>(m_frame->document())->zoomAndPanEnabled()) {
- if (event.event().shiftKey() && singleClick) {
- m_svgPan = true;
- static_cast<SVGDocument*>(m_frame->document())->startPan(event.event().pos());
- return true;
- }
- }
-#endif
-
- // We don't do this at the start of mouse down handling,
- // because we don't want to do it until we know we didn't hit a widget.
- if (singleClick)
- focusDocumentView();
-
- Node* innerNode = event.targetNode();
-
- m_mousePressNode = innerNode;
- m_dragStartPos = event.event().pos();
-
- bool swallowEvent = false;
- if (event.event().button() == LeftButton || event.event().button() == MiddleButton) {
- m_frame->selection()->setCaretBlinkingSuspended(true);
- m_mousePressed = true;
- m_beganSelectingText = false;
-
- if (event.event().clickCount() == 2)
- swallowEvent = handleMousePressEventDoubleClick(event);
- else if (event.event().clickCount() >= 3)
- swallowEvent = handleMousePressEventTripleClick(event);
- else
- swallowEvent = handleMousePressEventSingleClick(event);
- }
-
- m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect ||
- (m_mousePressNode && m_mousePressNode->renderer() && m_mousePressNode->renderer()->canBeProgramaticallyScrolled(true));
-
- return swallowEvent;
-}
-
-bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& event)
-{
- if (handleDrag(event))
- return true;
-
- if (!m_mousePressed)
- return false;
-
- Node* targetNode = event.targetNode();
- if (event.event().button() != LeftButton || !targetNode || !targetNode->renderer())
- return false;
-
-#if PLATFORM(MAC) // FIXME: Why does this assertion fire on other platforms?
- ASSERT(m_mouseDownMayStartSelect || m_mouseDownMayStartAutoscroll);
-#endif
-
- m_mouseDownMayStartDrag = false;
-
- if (m_mouseDownMayStartAutoscroll && !m_panScrollInProgress) {
- // If the selection is contained in a layer that can scroll, that layer should handle the autoscroll
- // Otherwise, let the bridge handle it so the view can scroll itself.
- RenderObject* renderer = targetNode->renderer();
- while (renderer && !renderer->canBeProgramaticallyScrolled(false)) {
- if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement())
- renderer = renderer->document()->ownerElement()->renderer();
- else
- renderer = renderer->parent();
- }
-
- if (renderer) {
- m_autoscrollInProgress = true;
- handleAutoscroll(renderer);
- }
-
- m_mouseDownMayStartAutoscroll = false;
- }
-
- updateSelectionForMouseDrag(targetNode, event.localPoint());
- return true;
-}
-
-bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const
-{
- // This is a pre-flight check of whether the event might lead to a drag being started. Be careful
- // that its logic needs to stay in sync with handleMouseMoveEvent() and the way we setMouseDownMayStartDrag
- // in handleMousePressEvent
-
- if (!m_frame->contentRenderer() || !m_frame->contentRenderer()->hasLayer()
- || event.button() != LeftButton || event.clickCount() != 1)
- return false;
-
- bool DHTMLFlag;
- bool UAFlag;
- allowDHTMLDrag(DHTMLFlag, UAFlag);
- if (!DHTMLFlag && !UAFlag)
- return false;
-
- HitTestRequest request(true, false);
- HitTestResult result(m_frame->view()->windowToContents(event.pos()));
- m_frame->contentRenderer()->layer()->hitTest(request, result);
- bool srcIsDHTML;
- return result.innerNode() && result.innerNode()->renderer()->draggableNode(DHTMLFlag, UAFlag, result.point().x(), result.point().y(), srcIsDHTML);
-}
-
-void EventHandler::updateSelectionForMouseDrag()
-{
- FrameView* view = m_frame->view();
- if (!view)
- return;
- RenderObject* renderer = m_frame->contentRenderer();
- if (!renderer)
- return;
- RenderLayer* layer = renderer->layer();
- if (!layer)
- return;
-
- HitTestResult result(view->windowToContents(m_currentMousePosition));
- layer->hitTest(HitTestRequest(true, true, true), result);
- updateSelectionForMouseDrag(result.innerNode(), result.localPoint());
-}
-
-void EventHandler::updateSelectionForMouseDrag(Node* targetNode, const IntPoint& localPoint)
-{
- if (!m_mouseDownMayStartSelect)
- return;
-
- if (!targetNode)
- return;
-
- RenderObject* targetRenderer = targetNode->renderer();
- if (!targetRenderer)
- return;
-
- if (!canMouseDragExtendSelect(targetNode))
- return;
-
- VisiblePosition targetPosition(targetRenderer->positionForPoint(localPoint));
-
- // Don't modify the selection if we're not on a node.
- if (targetPosition.isNull())
- return;
-
- // Restart the selection if this is the first mouse move. This work is usually
- // done in handleMousePressEvent, but not if the mouse press was on an existing selection.
- Selection newSelection = m_frame->selection()->selection();
-
-#if ENABLE(SVG)
- // Special case to limit selection to the containing block for SVG text.
- // FIXME: Isn't there a better non-SVG-specific way to do this?
- if (Node* selectionBaseNode = newSelection.base().node())
- if (RenderObject* selectionBaseRenderer = selectionBaseNode->renderer())
- if (selectionBaseRenderer->isSVGText())
- if (targetNode->renderer()->containingBlock() != selectionBaseRenderer->containingBlock())
- return;
-#endif
-
- if (!m_beganSelectingText) {
- m_beganSelectingText = true;
- newSelection = Selection(targetPosition);
- }
-
- newSelection.setExtent(targetPosition);
- if (m_frame->selectionGranularity() != CharacterGranularity)
- newSelection.expandUsingGranularity(m_frame->selectionGranularity());
-
- if (m_frame->shouldChangeSelection(newSelection)) {
- m_frame->selection()->setLastChangeWasHorizontalExtension(false);
- m_frame->selection()->setSelection(newSelection);
- }
-}
-
-bool EventHandler::handleMouseUp(const MouseEventWithHitTestResults& event)
-{
- if (eventLoopHandleMouseUp(event))
- return true;
-
- // If this was the first click in the window, we don't even want to clear the selection.
- // This case occurs when the user clicks on a draggable element, since we have to process
- // the mouse down and drag events to see if we might start a drag. For other first clicks
- // in a window, we just don't acceptFirstMouse, and the whole down-drag-up sequence gets
- // ignored upstream of this layer.
- return eventActivatedView(event.event());
-}
-
-bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event)
-{
- if (m_autoscrollInProgress)
- stopAutoscrollTimer();
-
- if (handleMouseUp(event))
- return true;
-
- // Used to prevent mouseMoveEvent from initiating a drag before
- // the mouse is pressed again.
- m_frame->selection()->setCaretBlinkingSuspended(false);
- m_mousePressed = false;
- m_mouseDownMayStartDrag = false;
- m_mouseDownMayStartSelect = false;
- m_mouseDownMayStartAutoscroll = false;
- m_mouseDownWasInSubframe = false;
-
- bool handled = false;
-
- // Clear the selection if the mouse didn't move after the last mouse press.
- // We do this so when clicking on the selection, the selection goes away.
- // However, if we are editing, place the caret.
- if (m_mouseDownWasSingleClickInSelection && !m_beganSelectingText
- && m_dragStartPos == event.event().pos()
- && m_frame->selection()->isRange()) {
- Selection newSelection;
- Node *node = event.targetNode();
- if (node && node->isContentEditable() && node->renderer()) {
- VisiblePosition pos = node->renderer()->positionForPoint(event.localPoint());
- newSelection = Selection(pos);
- }
- if (m_frame->shouldChangeSelection(newSelection))
- m_frame->selection()->setSelection(newSelection);
-
- handled = true;
- }
-
- m_frame->notifyRendererOfSelectionChange(true);
-
- m_frame->selection()->selectFrameElementInParentIfFullySelected();
-
- return handled;
-}
-
-void EventHandler::handleAutoscroll(RenderObject* renderer)
-{
- // We don't want to trigger the autoscroll or the panScroll if it's already active
- if (m_autoscrollTimer.isActive())
- return;
-
- setAutoscrollRenderer(renderer);
-
-#if PLATFORM(WIN)
- if (m_panScrollInProgress) {
- m_panScrollStartPos = currentMousePosition();
- m_frame->view()->printPanScrollIcon(m_panScrollStartPos);
- // If we're not in the top frame we notify it that we are using the panScroll
- if (m_frame != m_frame->page()->mainFrame())
- m_frame->page()->mainFrame()->eventHandler()->setPanScrollInProgress(true);
- }
-#endif
-
- startAutoscrollTimer();
-}
-
-void EventHandler::autoscrollTimerFired(Timer<EventHandler>*)
-{
- RenderObject* r = autoscrollRenderer();
- if (!r) {
- stopAutoscrollTimer();
- return;
- }
-
- if (m_autoscrollInProgress) {
- if (!m_mousePressed) {
- stopAutoscrollTimer();
- return;
- }
- r->autoscroll();
- } else {
- // we verify that the main frame hasn't received the order to stop the panScroll
- if (!m_frame->page()->mainFrame()->eventHandler()->panScrollInProgress()) {
- stopAutoscrollTimer();
- return;
- }
-#if PLATFORM(WIN)
- setPanScrollCursor();
- r->panScroll(m_panScrollStartPos);
-#endif
- }
-}
-
-void EventHandler::setPanScrollCursor()
-{
- // At the original click location we draw a 4 arrowed icon. Over this icon there won't be any scroll
- // So we don't want to change the cursor over this area
- const int noScrollRadius = 9;
- bool east = m_panScrollStartPos.x() < (m_currentMousePosition.x() - noScrollRadius);
- bool west = m_panScrollStartPos.x() > (m_currentMousePosition.x() + noScrollRadius);
- bool north = m_panScrollStartPos.y() > (m_currentMousePosition.y() + noScrollRadius);
- bool south = m_panScrollStartPos.y() < (m_currentMousePosition.y() - noScrollRadius);
-
- if (north) {
- if (east)
- m_frame->view()->setCursor(northEastPanningCursor());
- else if (west)
- m_frame->view()->setCursor(northWestPanningCursor());
- else
- m_frame->view()->setCursor(northPanningCursor());
- } else if (south) {
- if (east)
- m_frame->view()->setCursor(southEastPanningCursor());
- else if (west)
- m_frame->view()->setCursor(southWestPanningCursor());
- else
- m_frame->view()->setCursor(southPanningCursor());
- } else if (east)
- m_frame->view()->setCursor(eastPanningCursor());
- else if (west)
- m_frame->view()->setCursor(westPanningCursor());
- else
- m_frame->view()->setCursor(middlePanningCursor());
-}
-
-RenderObject* EventHandler::autoscrollRenderer() const
-{
- return m_autoscrollRenderer;
-}
-
-void EventHandler::updateAutoscrollRenderer()
-{
- if (!m_autoscrollRenderer)
- return;
-
- HitTestResult hitTest = hitTestResultAtPoint(m_panScrollStartPos, true);
-
- if (Node* nodeAtPoint = hitTest.innerNode())
- m_autoscrollRenderer = nodeAtPoint->renderer();
-
- while (m_autoscrollRenderer && !m_autoscrollRenderer->canBeProgramaticallyScrolled(false))
- m_autoscrollRenderer = m_autoscrollRenderer->parent();
-}
-
-void EventHandler::setAutoscrollRenderer(RenderObject* renderer)
-{
- m_autoscrollRenderer = renderer;
-}
-
-void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const
-{
- if (!m_frame || !m_frame->document()) {
- flagDHTML = false;
- flagUA = false;
- }
-
- unsigned mask = m_frame->page()->dragController()->delegateDragSourceAction(m_frame->view()->contentsToWindow(m_mouseDownPos));
- flagDHTML = (mask & DragSourceActionDHTML) != DragSourceActionNone;
- flagUA = ((mask & DragSourceActionImage) || (mask & DragSourceActionLink) || (mask & DragSourceActionSelection));
-}
-
-HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent)
-{
- HitTestResult result(point);
- if (!m_frame->contentRenderer())
- return result;
- m_frame->contentRenderer()->layer()->hitTest(HitTestRequest(true, true), result);
-
- while (true) {
- Node* n = result.innerNode();
- if (!n || !n->renderer() || !n->renderer()->isWidget())
- break;
- Widget* widget = static_cast<RenderWidget*>(n->renderer())->widget();
- if (!widget || !widget->isFrameView())
- break;
- Frame* frame = static_cast<HTMLFrameElementBase*>(n)->contentFrame();
- if (!frame || !frame->contentRenderer())
- break;
- FrameView* view = static_cast<FrameView*>(widget);
- IntPoint widgetPoint(result.localPoint().x() + view->contentsX() - n->renderer()->borderLeft() - n->renderer()->paddingLeft(),
- result.localPoint().y() + view->contentsY() - n->renderer()->borderTop() - n->renderer()->paddingTop());
- HitTestResult widgetHitTestResult(widgetPoint);
- frame->contentRenderer()->layer()->hitTest(HitTestRequest(true, true), widgetHitTestResult);
- result = widgetHitTestResult;
- }
-
- if (!allowShadowContent)
- result.setToNonShadowAncestor();
-
- return result;
-}
-
-
-void EventHandler::startAutoscrollTimer()
-{
- m_autoscrollTimer.startRepeating(autoscrollInterval);
-}
-
-void EventHandler::stopAutoscrollTimer(bool rendererIsBeingDestroyed)
-{
- if (m_autoscrollInProgress) {
- if (m_mouseDownWasInSubframe) {
- if (Frame* subframe = subframeForTargetNode(m_mousePressNode.get()))
- subframe->eventHandler()->stopAutoscrollTimer(rendererIsBeingDestroyed);
- return;
- }
- }
-
- if (autoscrollRenderer()) {
- if (!rendererIsBeingDestroyed && (m_autoscrollInProgress || m_panScrollInProgress))
- autoscrollRenderer()->stopAutoscroll();
-#if PLATFORM(WIN)
- if (m_panScrollInProgress) {
- m_frame->view()->removePanScrollIcon();
- }
-#endif
-
- setAutoscrollRenderer(0);
- }
-
- m_autoscrollTimer.stop();
-
- m_panScrollInProgress = false;
- // If we're not in the top frame we notify it that we are not using the panScroll anymore
- if (m_frame->page() && m_frame != m_frame->page()->mainFrame())
- m_frame->page()->mainFrame()->eventHandler()->setPanScrollInProgress(false);
- m_autoscrollInProgress = false;
-}
-
-Node* EventHandler::mousePressNode() const
-{
- return m_mousePressNode.get();
-}
-
-void EventHandler::setMousePressNode(PassRefPtr<Node> node)
-{
- m_mousePressNode = node;
-}
-
-bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity)
-{
- if (!m_frame->document())
- return false;
-
- Node* node = m_frame->document()->focusedNode();
- if (!node)
- node = m_mousePressNode.get();
-
- if (node) {
- RenderObject *r = node->renderer();
- if (r && !r->isListBox())
- return r->scroll(direction, granularity);
- }
-
- return false;
-}
-
-IntPoint EventHandler::currentMousePosition() const
-{
- return m_currentMousePosition;
-}
-
-Frame* subframeForTargetNode(Node* node)
-{
- if (!node)
- return 0;
-
- RenderObject* renderer = node->renderer();
- if (!renderer || !renderer->isWidget())
- return 0;
-
- Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
- if (!widget || !widget->isFrameView())
- return 0;
-
- return static_cast<FrameView*>(widget)->frame();
-}
-
-static bool isSubmitImage(Node* node)
-{
- return node && node->hasTagName(inputTag)
- && static_cast<HTMLInputElement*>(node)->inputType() == HTMLInputElement::IMAGE;
-}
-
-// Returns true if the node's editable block is not current focused for editing
-static bool nodeIsNotBeingEdited(Node* node, Frame* frame)
-{
- return frame->selection()->rootEditableElement() != node->rootEditableElement();
-}
-
-Cursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, PlatformScrollbar* scrollbar)
-{
- // During selection, use an I-beam no matter what we're over.
- // If you're capturing mouse events for a particular node, don't treat this as a selection.
- if (m_mousePressed && m_mouseDownMayStartSelect && m_frame->selection()->isCaretOrRange() && !m_capturingMouseEventsNode)
- return iBeamCursor();
-
- Node* node = event.targetNode();
- RenderObject* renderer = node ? node->renderer() : 0;
- RenderStyle* style = renderer ? renderer->style() : 0;
-
- if (renderer && renderer->isFrameSet()) {
- RenderFrameSet* fs = static_cast<RenderFrameSet*>(renderer);
- if (fs->canResizeRow(event.localPoint()))
- return rowResizeCursor();
- if (fs->canResizeColumn(event.localPoint()))
- return columnResizeCursor();
- }
-
- if (style && style->cursors()) {
- const CursorList* cursors = style->cursors();
- for (unsigned i = 0; i < cursors->size(); ++i) {
- CachedImage* cimage = (*cursors)[i].cursorImage;
- IntPoint hotSpot = (*cursors)[i].hotSpot;
- if (!cimage)
- continue;
- // Limit the size of cursors so that they cannot be used to cover UI elements in chrome.
- IntSize size = cimage->image()->size();
- if (size.width() > 128 || size.height() > 128)
- continue;
- // Do not let the hotspot be outside the bounds of the image.
- if (hotSpot.x() < 0 || hotSpot.y() < 0 || hotSpot.x() > size.width() || hotSpot.y() > size.height())
- continue;
- if (cimage->image()->isNull())
- break;
- if (!cimage->errorOccurred())
- return Cursor(cimage->image(), hotSpot);
- }
- }
-
- switch (style ? style->cursor() : CURSOR_AUTO) {
- case CURSOR_AUTO: {
- bool editable = (node && node->isContentEditable());
- bool editableLinkEnabled = false;
-
- // If the link is editable, then we need to check the settings to see whether or not the link should be followed
- if (editable) {
- ASSERT(m_frame->settings());
- switch(m_frame->settings()->editableLinkBehavior()) {
- default:
- case EditableLinkDefaultBehavior:
- case EditableLinkAlwaysLive:
- editableLinkEnabled = true;
- break;
-
- case EditableLinkNeverLive:
- editableLinkEnabled = false;
- break;
-
- case EditableLinkLiveWhenNotFocused:
- editableLinkEnabled = nodeIsNotBeingEdited(node, m_frame) || event.event().shiftKey();
- break;
-
- case EditableLinkOnlyLiveWithShiftKey:
- editableLinkEnabled = event.event().shiftKey();
- break;
- }
- }
-
- if ((event.isOverLink() || isSubmitImage(node)) && (!editable || editableLinkEnabled))
- return handCursor();
- RenderLayer* layer = renderer ? renderer->enclosingLayer() : 0;
- bool inResizer = false;
- if (m_frame->view() && layer && layer->isPointInResizeControl(m_frame->view()->windowToContents(event.event().pos())))
- inResizer = true;
- if ((editable || (renderer && renderer->isText() && node->canStartSelection())) && !inResizer && !scrollbar)
- return iBeamCursor();
- return pointerCursor();
- }
- case CURSOR_CROSS:
- return crossCursor();
- case CURSOR_POINTER:
- return handCursor();
- case CURSOR_MOVE:
- return moveCursor();
- case CURSOR_ALL_SCROLL:
- return moveCursor();
- case CURSOR_E_RESIZE:
- return eastResizeCursor();
- case CURSOR_W_RESIZE:
- return westResizeCursor();
- case CURSOR_N_RESIZE:
- return northResizeCursor();
- case CURSOR_S_RESIZE:
- return southResizeCursor();
- case CURSOR_NE_RESIZE:
- return northEastResizeCursor();
- case CURSOR_SW_RESIZE:
- return southWestResizeCursor();
- case CURSOR_NW_RESIZE:
- return northWestResizeCursor();
- case CURSOR_SE_RESIZE:
- return southEastResizeCursor();
- case CURSOR_NS_RESIZE:
- return northSouthResizeCursor();
- case CURSOR_EW_RESIZE:
- return eastWestResizeCursor();
- case CURSOR_NESW_RESIZE:
- return northEastSouthWestResizeCursor();
- case CURSOR_NWSE_RESIZE:
- return northWestSouthEastResizeCursor();
- case CURSOR_COL_RESIZE:
- return columnResizeCursor();
- case CURSOR_ROW_RESIZE:
- return rowResizeCursor();
- case CURSOR_TEXT:
- return iBeamCursor();
- case CURSOR_WAIT:
- return waitCursor();
- case CURSOR_HELP:
- return helpCursor();
- case CURSOR_VERTICAL_TEXT:
- return verticalTextCursor();
- case CURSOR_CELL:
- return cellCursor();
- case CURSOR_CONTEXT_MENU:
- return contextMenuCursor();
- case CURSOR_PROGRESS:
- return progressCursor();
- case CURSOR_NO_DROP:
- return noDropCursor();
- case CURSOR_ALIAS:
- return aliasCursor();
- case CURSOR_COPY:
- return copyCursor();
- case CURSOR_NONE:
- return noneCursor();
- case CURSOR_NOT_ALLOWED:
- return notAllowedCursor();
- case CURSOR_DEFAULT:
- return pointerCursor();
- case CURSOR_WEBKIT_ZOOM_IN:
- return zoomInCursor();
- case CURSOR_WEBKIT_ZOOM_OUT:
- return zoomOutCursor();
- }
- return pointerCursor();
-}
-
-bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
-{
- if (!m_frame->document())
- return false;
-
- RefPtr<FrameView> protector(m_frame->view());
-
- m_mousePressed = true;
- m_currentMousePosition = mouseEvent.pos();
- m_mouseDownTimestamp = mouseEvent.timestamp();
- m_mouseDownMayStartDrag = false;
- m_mouseDownMayStartSelect = false;
- m_mouseDownMayStartAutoscroll = false;
- m_mouseDownPos = m_frame->view()->windowToContents(mouseEvent.pos());
- m_mouseDownWasInSubframe = false;
-
- MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(false, true), mouseEvent);
-
- if (!mev.targetNode()) {
- invalidateClick();
- return false;
- }
-
- m_mousePressNode = mev.targetNode();
-
- Frame* subframe = subframeForTargetNode(mev.targetNode());
- if (subframe && passMousePressEventToSubframe(mev, subframe)) {
- // Start capturing future events for this frame. We only do this if we didn't clear
- // the m_mousePressed flag, which may happen if an AppKit widget entered a modal event loop.
- if (m_mousePressed)
- m_capturingMouseEventsNode = mev.targetNode();
- invalidateClick();
- return true;
- }
-
-#if PLATFORM(WIN)
- if (m_frame->page()->mainFrame()->eventHandler()->panScrollInProgress() || m_autoscrollInProgress) {
- stopAutoscrollTimer();
- invalidateClick();
- return true;
- }
-
- if (mouseEvent.button() == MiddleButton && !mev.isOverLink()) {
- RenderObject* renderer = mev.targetNode()->renderer();
-
- while (renderer && !renderer->canBeProgramaticallyScrolled(false)) {
- if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement())
- renderer = renderer->document()->ownerElement()->renderer();
- else
- renderer = renderer->parent();
- }
-
- if (renderer) {
- m_panScrollInProgress = true;
- handleAutoscroll(renderer);
- invalidateClick();
- return true;
- }
- }
-#endif
-
- m_clickCount = mouseEvent.clickCount();
- m_clickNode = mev.targetNode();
-
- RenderLayer* layer = m_clickNode->renderer() ? m_clickNode->renderer()->enclosingLayer() : 0;
- IntPoint p = m_frame->view()->windowToContents(mouseEvent.pos());
- if (layer && layer->isPointInResizeControl(p)) {
- layer->setInResizeMode(true);
- m_resizeLayer = layer;
- m_offsetFromResizeCorner = layer->offsetFromResizeCorner(p);
- invalidateClick();
- return true;
- }
-
- bool swallowEvent = dispatchMouseEvent(mousedownEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
-
- // If the hit testing originally determined the event was in a scrollbar, refetch the MouseEventWithHitTestResults
- // in case the scrollbar widget was destroyed when the mouse event was handled.
- if (mev.scrollbar()) {
- const bool wasLastScrollBar = mev.scrollbar() == m_lastScrollbarUnderMouse.get();
- mev = prepareMouseEvent(HitTestRequest(true, true), mouseEvent);
-
- if (wasLastScrollBar && mev.scrollbar() != m_lastScrollbarUnderMouse.get())
- m_lastScrollbarUnderMouse = 0;
- }
-
- if (swallowEvent) {
- // scrollbars should get events anyway, even disabled controls might be scrollable
- PlatformScrollbar* scrollbar = mev.scrollbar();
- if (!scrollbar)
- scrollbar = m_frame->view()->scrollbarUnderMouse(mouseEvent);
- if (scrollbar)
- passMousePressEventToScrollbar(mev, scrollbar);
- } else {
- // Refetch the event target node if it currently is the shadow node inside an <input> element.
- // If a mouse event handler changes the input element type to one that has a widget associated,
- // we'd like to EventHandler::handleMousePressEvent to pass the event to the widget and thus the
- // event target node can't still be the shadow node.
- if (mev.targetNode()->isShadowNode() && mev.targetNode()->shadowParentNode()->hasTagName(inputTag))
- mev = prepareMouseEvent(HitTestRequest(true, true), mouseEvent);
-
- PlatformScrollbar* scrollbar = m_frame->view()->scrollbarUnderMouse(mouseEvent);
- if (!scrollbar)
- scrollbar = mev.scrollbar();
- if (scrollbar && passMousePressEventToScrollbar(mev, scrollbar))
- swallowEvent = true;
- else
- swallowEvent = handleMousePressEvent(mev);
- }
-
- return swallowEvent;
-}
-
-// This method only exists for platforms that don't know how to deliver
-bool EventHandler::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEvent)
-{
- if (!m_frame->document())
- return false;
-
- RefPtr<FrameView> protector(m_frame->view());
-
- // We get this instead of a second mouse-up
- m_mousePressed = false;
- m_currentMousePosition = mouseEvent.pos();
-
- MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(false, true), mouseEvent);
- Frame* subframe = subframeForTargetNode(mev.targetNode());
- if (subframe && passMousePressEventToSubframe(mev, subframe)) {
- m_capturingMouseEventsNode = 0;
- return true;
- }
-
- m_clickCount = mouseEvent.clickCount();
- bool swallowMouseUpEvent = dispatchMouseEvent(mouseupEvent, mev.targetNode(), true, m_clickCount, mouseEvent, false);
-
- bool swallowClickEvent = false;
- // Don't ever dispatch click events for right clicks
- if (mouseEvent.button() != RightButton && mev.targetNode() == m_clickNode)
- swallowClickEvent = dispatchMouseEvent(clickEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
-
- bool swallowMouseReleaseEvent = false;
- if (!swallowMouseUpEvent)
- swallowMouseReleaseEvent = handleMouseReleaseEvent(mev);
-
- invalidateClick();
-
- return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
-}
-
-bool EventHandler::mouseMoved(const PlatformMouseEvent& event)
-{
- HitTestResult hoveredNode = HitTestResult(IntPoint());
- bool result = handleMouseMoveEvent(event, &hoveredNode);
-
- Page* page = m_frame->page();
- if (!page)
- return result;
-
- hoveredNode.setToNonShadowAncestor();
- page->chrome()->mouseDidMoveOverElement(hoveredNode, event.modifierFlags());
- page->chrome()->setToolTip(hoveredNode);
- return result;
-}
-
-bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, HitTestResult* hoveredNode)
-{
- // in Radar 3703768 we saw frequent crashes apparently due to the
- // part being null here, which seems impossible, so check for nil
- // but also assert so that we can try to figure this out in debug
- // builds, if it happens.
- ASSERT(m_frame);
- if (!m_frame || !m_frame->document())
- return false;
-
- RefPtr<FrameView> protector(m_frame->view());
- m_currentMousePosition = mouseEvent.pos();
-
- if (m_hoverTimer.isActive())
- m_hoverTimer.stop();
-
-#if ENABLE(SVG)
- if (m_svgPan) {
- static_cast<SVGDocument*>(m_frame->document())->updatePan(m_currentMousePosition);
- return true;
- }
-#endif
-
- if (m_frameSetBeingResized)
- return dispatchMouseEvent(mousemoveEvent, m_frameSetBeingResized.get(), false, 0, mouseEvent, false);
-
- // Send events right to a scrollbar if the mouse is pressed.
- if (m_lastScrollbarUnderMouse && m_mousePressed)
- return m_lastScrollbarUnderMouse->handleMouseMoveEvent(mouseEvent);
-
- // Treat mouse move events while the mouse is pressed as "read-only" in prepareMouseEvent
- // if we are allowed to select.
- // This means that :hover and :active freeze in the state they were in when the mouse
- // was pressed, rather than updating for nodes the mouse moves over as you hold the mouse down.
- HitTestRequest request(m_mousePressed && m_mouseDownMayStartSelect, m_mousePressed, true);
- MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
- if (hoveredNode)
- *hoveredNode = mev.hitTestResult();
-
- PlatformScrollbar* scrollbar = 0;
-
- if (m_resizeLayer && m_resizeLayer->inResizeMode())
- m_resizeLayer->resize(mouseEvent, m_offsetFromResizeCorner);
- else {
- if (m_frame->view())
- scrollbar = m_frame->view()->scrollbarUnderMouse(mouseEvent);
-
- if (!scrollbar)
- scrollbar = mev.scrollbar();
-
- if (m_lastScrollbarUnderMouse != scrollbar) {
- // Send mouse exited to the old scrollbar.
- if (m_lastScrollbarUnderMouse)
- m_lastScrollbarUnderMouse->handleMouseOutEvent(mouseEvent);
- m_lastScrollbarUnderMouse = m_mousePressed ? 0 : scrollbar;
- }
- }
-
- bool swallowEvent = false;
- Node* targetNode = m_capturingMouseEventsNode ? m_capturingMouseEventsNode.get() : mev.targetNode();
- RefPtr<Frame> newSubframe = subframeForTargetNode(targetNode);
-
- // We want mouseouts to happen first, from the inside out. First send a move event to the last subframe so that it will fire mouseouts.
- if (m_lastMouseMoveEventSubframe && m_lastMouseMoveEventSubframe->tree()->isDescendantOf(m_frame) && m_lastMouseMoveEventSubframe != newSubframe)
- passMouseMoveEventToSubframe(mev, m_lastMouseMoveEventSubframe.get());
-
- if (newSubframe) {
- // Update over/out state before passing the event to the subframe.
- updateMouseEventTargetNode(mev.targetNode(), mouseEvent, true);
-
- // Event dispatch in updateMouseEventTargetNode may have caused the subframe of the target
- // node to be detached from its FrameView, in which case the event should not be passed.
-
- // Manually merge changes from webkit trunk to fix the crash for
- // http://www.coolpc.com.tw/evaluate.php
- // See http://trac.webkit.org/changeset/31788.
- if (newSubframe->view())
- swallowEvent |= passMouseMoveEventToSubframe(mev, newSubframe.get(), hoveredNode);
- } else {
- if (scrollbar && !m_mousePressed)
- scrollbar->handleMouseMoveEvent(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
- if ((!m_resizeLayer || !m_resizeLayer->inResizeMode()) && !m_frame->page()->mainFrame()->eventHandler()->panScrollInProgress() && m_frame->view())
- m_frame->view()->setCursor(selectCursor(mev, scrollbar));
- }
-
- m_lastMouseMoveEventSubframe = newSubframe;
-
- if (swallowEvent)
- return true;
-
- swallowEvent = dispatchMouseEvent(mousemoveEvent, mev.targetNode(), false, 0, mouseEvent, true);
- if (!swallowEvent)
- swallowEvent = handleMouseDraggedEvent(mev);
-
- return swallowEvent;
-}
-
-void EventHandler::invalidateClick()
-{
- m_clickCount = 0;
- m_clickNode = 0;
-}
-
-bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
-{
- if (!m_frame->document())
- return false;
-
- RefPtr<FrameView> protector(m_frame->view());
-
- m_mousePressed = false;
- m_currentMousePosition = mouseEvent.pos();
-
-#if ENABLE(SVG)
- if (m_svgPan) {
- m_svgPan = false;
- static_cast<SVGDocument*>(m_frame->document())->updatePan(m_currentMousePosition);
- return true;
- }
-#endif
-
- if (m_frameSetBeingResized)
- return dispatchMouseEvent(mouseupEvent, m_frameSetBeingResized.get(), true, m_clickCount, mouseEvent, false);
-
- if (m_lastScrollbarUnderMouse) {
- invalidateClick();
- return m_lastScrollbarUnderMouse->handleMouseReleaseEvent(mouseEvent);
- }
-
- MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(false, false, false, true), mouseEvent);
- Node* targetNode = m_capturingMouseEventsNode.get() ? m_capturingMouseEventsNode.get() : mev.targetNode();
- Frame* subframe = subframeForTargetNode(targetNode);
- if (subframe && passMouseReleaseEventToSubframe(mev, subframe)) {
- m_capturingMouseEventsNode = 0;
- return true;
- }
-
- bool swallowMouseUpEvent = dispatchMouseEvent(mouseupEvent, mev.targetNode(), true, m_clickCount, mouseEvent, false);
-
- // Don't ever dispatch click events for right clicks
- bool swallowClickEvent = false;
- if (m_clickCount > 0 && mouseEvent.button() != RightButton && mev.targetNode() == m_clickNode)
- swallowClickEvent = dispatchMouseEvent(clickEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
-
- if (m_resizeLayer) {
- m_resizeLayer->setInResizeMode(false);
- m_resizeLayer = 0;
- }
-
- bool swallowMouseReleaseEvent = false;
- if (!swallowMouseUpEvent)
- swallowMouseReleaseEvent = handleMouseReleaseEvent(mev);
-
- invalidateClick();
-
- return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
-}
-
-bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard)
-{
- IntPoint contentsPos = m_frame->view()->windowToContents(event.pos());
-
- RefPtr<MouseEvent> me = MouseEvent::create(eventType,
- true, true, m_frame->document()->defaultView(),
- 0, event.globalX(), event.globalY(), contentsPos.x(), contentsPos.y(),
- event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(),
- 0, 0, clipboard);
-
- ExceptionCode ec = 0;
- EventTargetNodeCast(dragTarget)->dispatchEvent(me.get(), ec, true);
- return me->defaultPrevented();
-}
-
-bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
-{
- bool accept = false;
-
- if (!m_frame->document())
- return false;
-
- if (!m_frame->view())
- return false;
-
- MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(true, false), event);
-
- // Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch)
- Node* newTarget = mev.targetNode();
- if (newTarget && newTarget->isTextNode())
- newTarget = newTarget->parentNode();
- if (newTarget)
- newTarget = newTarget->shadowAncestorNode();
-
- if (m_dragTarget != newTarget) {
- // FIXME: this ordering was explicitly chosen to match WinIE. However,
- // it is sometimes incorrect when dragging within subframes, as seen with
- // LayoutTests/fast/events/drag-in-frames.html.
- if (newTarget)
- if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag))
- accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame()->eventHandler()->updateDragAndDrop(event, clipboard);
- else
- accept = dispatchDragEvent(dragenterEvent, newTarget, event, clipboard);
-
- if (m_dragTarget) {
- Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag))
- ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0;
- if (frame)
- accept = frame->eventHandler()->updateDragAndDrop(event, clipboard);
- else
- dispatchDragEvent(dragleaveEvent, m_dragTarget.get(), event, clipboard);
- }
- } else {
- if (newTarget)
- if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag))
- accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame()->eventHandler()->updateDragAndDrop(event, clipboard);
- else
- accept = dispatchDragEvent(dragoverEvent, newTarget, event, clipboard);
- }
- m_dragTarget = newTarget;
-
- return accept;
-}
-
-void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
-{
- if (m_dragTarget) {
- Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag))
- ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0;
- if (frame)
- frame->eventHandler()->cancelDragAndDrop(event, clipboard);
- else
- dispatchDragEvent(dragleaveEvent, m_dragTarget.get(), event, clipboard);
- }
- clearDragState();
-}
-
-bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
-{
- bool accept = false;
- if (m_dragTarget) {
- Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag))
- ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0;
- if (frame)
- accept = frame->eventHandler()->performDragAndDrop(event, clipboard);
- else
- accept = dispatchDragEvent(dropEvent, m_dragTarget.get(), event, clipboard);
- }
- clearDragState();
- return accept;
-}
-
-void EventHandler::clearDragState()
-{
- m_dragTarget = 0;
- m_capturingMouseEventsNode = 0;
-#if PLATFORM(MAC)
- m_sendingEventToSubview = false;
-#endif
-}
-
-Node* EventHandler::nodeUnderMouse() const
-{
- return m_nodeUnderMouse.get();
-}
-
-void EventHandler::setCapturingMouseEventsNode(PassRefPtr<Node> n)
-{
- m_capturingMouseEventsNode = n;
-}
-
-MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestRequest& request, const PlatformMouseEvent& mev)
-{
- ASSERT(m_frame);
- ASSERT(m_frame->document());
-
- IntPoint documentPoint = m_frame->view()->windowToContents(mev.pos());
- return m_frame->document()->prepareMouseEvent(request, documentPoint, mev);
-}
-
-void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMouseEvent& mouseEvent, bool fireMouseOverOut)
-{
- Node* result = targetNode;
-
- // If we're capturing, we always go right to that node.
- if (m_capturingMouseEventsNode)
- result = m_capturingMouseEventsNode.get();
- else {
- // If the target node is a text node, dispatch on the parent node - rdar://4196646
- if (result && result->isTextNode())
- result = result->parentNode();
- if (result)
- result = result->shadowAncestorNode();
- }
- m_nodeUnderMouse = result;
-
- // Fire mouseout/mouseover if the mouse has shifted to a different node.
- if (fireMouseOverOut) {
- if (m_lastNodeUnderMouse && m_lastNodeUnderMouse->document() != m_frame->document()) {
- m_lastNodeUnderMouse = 0;
- m_lastScrollbarUnderMouse = 0;
- }
-
- if (m_lastNodeUnderMouse != m_nodeUnderMouse) {
- // send mouseout event to the old node
- if (m_lastNodeUnderMouse)
- EventTargetNodeCast(m_lastNodeUnderMouse.get())->dispatchMouseEvent(mouseEvent, mouseoutEvent, 0, m_nodeUnderMouse.get());
- // send mouseover event to the new node
- if (m_nodeUnderMouse)
- EventTargetNodeCast(m_nodeUnderMouse.get())->dispatchMouseEvent(mouseEvent, mouseoverEvent, 0, m_lastNodeUnderMouse.get());
- }
- m_lastNodeUnderMouse = m_nodeUnderMouse;
- }
-}
-
-bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool cancelable, int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder)
-{
- updateMouseEventTargetNode(targetNode, mouseEvent, setUnder);
-
- bool swallowEvent = false;
-
- if (m_nodeUnderMouse)
- swallowEvent = EventTargetNodeCast(m_nodeUnderMouse.get())->dispatchMouseEvent(mouseEvent, eventType, clickCount);
-
- if (!swallowEvent && eventType == mousedownEvent) {
- // Blur current focus node when a link/button is clicked; this
- // is expected by some sites that rely on onChange handlers running
- // from form fields before the button click is processed.
- Node* node = m_nodeUnderMouse.get();
- RenderObject* renderer = node ? node->renderer() : 0;
-
- // Walk up the render tree to search for a node to focus.
- // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
- while (renderer) {
- node = renderer->element();
- if (node && node->isFocusable()) {
- // To fix <rdar://problem/4895428> Can't drag selected ToDo, we don't focus a
- // node on mouse down if it's selected and inside a focused node. It will be
- // focused if the user does a mouseup over it, however, because the mouseup
- // will set a selection inside it, which will call setFocuseNodeIfNeeded.
- ExceptionCode ec = 0;
- Node* n = node->isShadowNode() ? node->shadowParentNode() : node;
- if (m_frame->selection()->isRange() &&
- m_frame->selection()->toRange()->compareNode(n, ec) == Range::NODE_INSIDE &&
- n->isDescendantOf(m_frame->document()->focusedNode()))
- return false;
-
- break;
- }
-
- renderer = renderer->parent();
- }
- // If focus shift is blocked, we eat the event. Note we should never clear swallowEvent
- // if the page already set it (e.g., by canceling default behavior).
- if (node && node->isMouseFocusable()) {
- if (!m_frame->page()->focusController()->setFocusedNode(node, m_frame))
- swallowEvent = true;
- } else if (!node || !node->focused()) {
- if (!m_frame->page()->focusController()->setFocusedNode(0, m_frame))
- swallowEvent = true;
- }
- }
-
- return swallowEvent;
-}
-
-bool EventHandler::handleWheelEvent(PlatformWheelEvent& e)
-{
- Document* doc = m_frame->document();
- if (!doc)
- return false;
-
- RenderObject* docRenderer = doc->renderer();
- if (!docRenderer)
- return false;
-
- IntPoint vPoint = m_frame->view()->windowToContents(e.pos());
-
- HitTestRequest request(true, false);
- HitTestResult result(vPoint);
- doc->renderer()->layer()->hitTest(request, result);
- Node* node = result.innerNode();
-
- if (node) {
- // Figure out which view to send the event to.
- RenderObject* target = node->renderer();
-
- if (target && target->isWidget()) {
- Widget* widget = static_cast<RenderWidget*>(target)->widget();
-
- if (widget && passWheelEventToWidget(e, widget)) {
- e.accept();
- return true;
- }
- }
-
- node = node->shadowAncestorNode();
- EventTargetNodeCast(node)->dispatchWheelEvent(e);
- if (e.isAccepted())
- return true;
-
- if (node->renderer()) {
- // Just break up into two scrolls if we need to. Diagonal movement on
- // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set).
- float deltaX = e.isContinuous() ? e.continuousDeltaX() : e.deltaX();
- float deltaY = e.isContinuous() ? e.continuousDeltaY() : e.deltaY();
-
- scrollAndAcceptEvent(deltaX, ScrollLeft, ScrollRight, e.isPageXScrollModeEnabled(), e, node, m_frame->page()->chrome()->windowRect().width());
- scrollAndAcceptEvent(deltaY, ScrollUp, ScrollDown, e.isPageYScrollModeEnabled(), e, node, m_frame->page()->chrome()->windowRect().height());
- }
- }
-
- if (!e.isAccepted())
- m_frame->view()->wheelEvent(e);
-
- return e.isAccepted();
-}
-
-bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event)
-{
- Document* doc = m_frame->document();
- FrameView* v = m_frame->view();
- if (!doc || !v)
- return false;
-
- bool swallowEvent;
- IntPoint viewportPos = v->windowToContents(event.pos());
- MouseEventWithHitTestResults mev = doc->prepareMouseEvent(HitTestRequest(false, true), viewportPos, event);
-
-#if 0
- // The following commented out code tries to select the word below the
- // mouse cursor on right click. This used to be behavior that could be
- // changed by webkit embedders, but in change 24499, that functionality was
- // removed.
- // https://bugs.webkit.org/show_bug.cgi?id=15279
-
- if (!m_frame->selection()->contains(viewportPos) &&
- // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse.
- // If the selection is non-editable, we do word selection to make it easier to use the contextual menu items
- // available for text selections. But only if we're above text.
- (m_frame->selection()->isContentEditable() || mev.targetNode() && mev.targetNode()->isTextNode())) {
- m_mouseDownMayStartSelect = true; // context menu events are always allowed to perform a selection
- selectClosestWordOrLinkFromMouseEvent(mev);
- }
-#endif
- swallowEvent = dispatchMouseEvent(contextmenuEvent, mev.targetNode(), true, 0, event, true);
-
- return swallowEvent;
-}
-
-void EventHandler::scheduleHoverStateUpdate()
-{
- if (!m_hoverTimer.isActive())
- m_hoverTimer.startOneShot(0);
-}
-
-// Whether or not a mouse down can begin the creation of a selection. Fires the selectStart event.
-bool EventHandler::canMouseDownStartSelect(Node* node)
-{
- if (!node || !node->renderer())
- return true;
-
- // Some controls and images can't start a select on a mouse down.
- if (!node->canStartSelection())
- return false;
-
- for (RenderObject* curr = node->renderer(); curr; curr = curr->parent())
- if (Node* node = curr->element())
- return EventTargetNodeCast(node)->dispatchHTMLEvent(selectstartEvent, true, true);
-
- return true;
-}
-
-bool EventHandler::canMouseDragExtendSelect(Node* node)
-{
- if (!node || !node->renderer())
- return true;
-
- for (RenderObject* curr = node->renderer(); curr; curr = curr->parent())
- if (Node* node = curr->element())
- return EventTargetNodeCast(node)->dispatchHTMLEvent(selectstartEvent, true, true);
-
- return true;
-}
-
-void EventHandler::setResizingFrameSet(HTMLFrameSetElement* frameSet)
-{
- m_frameSetBeingResized = frameSet;
-}
-
-void EventHandler::resizeLayerDestroyed()
-{
- ASSERT(m_resizeLayer);
- m_resizeLayer = 0;
-}
-
-void EventHandler::hoverTimerFired(Timer<EventHandler>*)
-{
- m_hoverTimer.stop();
-
- ASSERT(m_frame);
- ASSERT(m_frame->document());
-
- if (RenderObject* renderer = m_frame->contentRenderer()) {
- HitTestResult result(m_frame->view()->windowToContents(m_currentMousePosition));
- renderer->layer()->hitTest(HitTestRequest(false, false, true), result);
- m_frame->document()->updateRendering();
- }
-}
-
-static EventTargetNode* eventTargetNodeForDocument(Document* doc)
-{
- if (!doc)
- return 0;
- Node* node = doc->focusedNode();
- if (!node) {
- if (doc->isHTMLDocument())
- node = doc->body();
- else
- node = doc->documentElement();
- if (!node)
- return 0;
- }
- return EventTargetNodeCast(node);
-}
-
-bool EventHandler::handleAccessKey(const PlatformKeyboardEvent& evt)
-{
- if ((evt.modifiers() & s_accessKeyModifiers) != s_accessKeyModifiers)
- return false;
- String key = evt.unmodifiedText();
- Element* elem = m_frame->document()->getElementByAccessKey(key.lower());
- if (!elem)
- return false;
- elem->accessKeyAction(false);
- return true;
-}
-
-#if !PLATFORM(MAC)
-bool EventHandler::needsKeyboardEventDisambiguationQuirks() const
-{
- return false;
-}
-#endif
-
-bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent)
-{
-#if PLATFORM(WIN) || (PLATFORM(WX) && PLATFORM(WIN_OS))
- String escKeyId = "U+001B";
- // If a key is pressed while the autoscroll/panScroll is in progress then we want to stop
- if (initialKeyEvent.keyIdentifier() == escKeyId && m_frame->page()->mainFrame()->eventHandler()->panScrollInProgress() || m_autoscrollInProgress)
- stopAutoscrollTimer();
-#endif
-
- // Check for cases where we are too early for events -- possible unmatched key up
- // from pressing return in the location bar.
- RefPtr<EventTargetNode> node = eventTargetNodeForDocument(m_frame->document());
- if (!node)
- return false;
-
- // FIXME: what is this doing here, in keyboard event handler?
- m_frame->loader()->resetMultipleFormSubmissionProtection();
-
- // In IE, access keys are special, they are handled after default keydown processing, but cannot be canceled - this is hard to match.
- // On Mac OS X, we process them before dispatching keydown, as the default keydown handler implements Emacs key bindings, which may conflict
- // with access keys. Then we dispatch keydown, but suppress its default handling.
- // On Windows, WebKit explicitly calls handleAccessKey() instead of dispatching a keypress event for WM_SYSCHAR messages.
- // Other platforms currently match either Mac or Windows behavior, depending on whether they send combined KeyDown events.
- bool matchedAnAccessKey = false;
- if (initialKeyEvent.type() == PlatformKeyboardEvent::KeyDown)
- matchedAnAccessKey = handleAccessKey(initialKeyEvent);
-
- // FIXME: it would be fair to let an input method handle KeyUp events before DOM dispatch.
- if (initialKeyEvent.type() == PlatformKeyboardEvent::KeyUp || initialKeyEvent.type() == PlatformKeyboardEvent::Char)
- return !node->dispatchKeyEvent(initialKeyEvent);
-
- bool backwardCompatibilityMode = needsKeyboardEventDisambiguationQuirks();
-
- ExceptionCode ec;
- PlatformKeyboardEvent keyDownEvent = initialKeyEvent;
- if (keyDownEvent.type() != PlatformKeyboardEvent::RawKeyDown)
- keyDownEvent.disambiguateKeyDownEvent(PlatformKeyboardEvent::RawKeyDown, backwardCompatibilityMode);
- RefPtr<KeyboardEvent> keydown = KeyboardEvent::create(keyDownEvent, m_frame->document()->defaultView());
- if (matchedAnAccessKey)
- keydown->setDefaultPrevented(true);
- keydown->setTarget(node);
-
- if (initialKeyEvent.type() == PlatformKeyboardEvent::RawKeyDown) {
- node->dispatchEvent(keydown, ec, true);
- return keydown->defaultHandled() || keydown->defaultPrevented();
- }
-
- // Run input method in advance of DOM event handling. This may result in the IM
- // modifying the page prior the keydown event, but this behaviour is necessary
- // in order to match IE:
- // 1. preventing default handling of keydown and keypress events has no effect on IM input;
- // 2. if an input method handles the event, its keyCode is set to 229 in keydown event.
- m_frame->editor()->handleInputMethodKeydown(keydown.get());
-
- bool handledByInputMethod = keydown->defaultHandled();
-
- if (handledByInputMethod) {
- keyDownEvent.setWindowsVirtualKeyCode(CompositionEventKeyCode);
- keydown = KeyboardEvent::create(keyDownEvent, m_frame->document()->defaultView());
- keydown->setTarget(node);
- keydown->setDefaultHandled();
- }
-
- node->dispatchEvent(keydown, ec, true);
- bool keydownResult = keydown->defaultHandled() || keydown->defaultPrevented();
- if (handledByInputMethod || (keydownResult && !backwardCompatibilityMode))
- return keydownResult;
-
- // Focus may have changed during keydown handling, so refetch node.
- // But if we are dispatching a fake backward compatibility keypress, then we pretend that the keypress happened on the original node.
- if (!keydownResult) {
- node = eventTargetNodeForDocument(m_frame->document());
- if (!node)
- return false;
- }
-
- PlatformKeyboardEvent keyPressEvent = initialKeyEvent;
- keyPressEvent.disambiguateKeyDownEvent(PlatformKeyboardEvent::Char, backwardCompatibilityMode);
- if (keyPressEvent.text().isEmpty())
- return keydownResult;
- RefPtr<KeyboardEvent> keypress = KeyboardEvent::create(keyPressEvent, m_frame->document()->defaultView());
- keypress->setTarget(node);
- if (keydownResult)
- keypress->setDefaultPrevented(true);
-#if PLATFORM(MAC)
- keypress->keypressCommands() = keydown->keypressCommands();
-#endif
- node->dispatchEvent(keypress, ec, true);
-
- return keydownResult || keypress->defaultPrevented() || keypress->defaultHandled();
-}
-
-void EventHandler::handleKeyboardSelectionMovement(KeyboardEvent* event)
-{
- if (!event)
- return;
-
- String key = event->keyIdentifier();
- bool isShifted = event->getModifierState("Shift");
- bool isOptioned = event->getModifierState("Alt");
-
- if (key == "Up") {
- m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::BACKWARD, LineGranularity, true);
- event->setDefaultHandled();
- }
- else if (key == "Down") {
- m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::FORWARD, LineGranularity, true);
- event->setDefaultHandled();
- }
- else if (key == "Left") {
- m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::LEFT, (isOptioned) ? WordGranularity : CharacterGranularity, true);
- event->setDefaultHandled();
- }
- else if (key == "Right") {
- m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::RIGHT, (isOptioned) ? WordGranularity : CharacterGranularity, true);
- event->setDefaultHandled();
- }
-}
-
-void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event)
-{
- if (event->type() == keydownEvent) {
- m_frame->editor()->handleKeyboardEvent(event);
- if (event->defaultHandled())
- return;
- if (event->keyIdentifier() == "U+0009")
- defaultTabEventHandler(event);
-
- // provides KB navigation and selection for enhanced accessibility users
- if (AXObjectCache::accessibilityEnhancedUserInterfaceEnabled())
- handleKeyboardSelectionMovement(event);
- }
- if (event->type() == keypressEvent) {
- m_frame->editor()->handleKeyboardEvent(event);
- if (event->defaultHandled())
- return;
- }
-}
-
-bool EventHandler::dragHysteresisExceeded(const FloatPoint& floatDragViewportLocation) const
-{
- IntPoint dragViewportLocation((int)floatDragViewportLocation.x(), (int)floatDragViewportLocation.y());
- return dragHysteresisExceeded(dragViewportLocation);
-}
-
-bool EventHandler::dragHysteresisExceeded(const IntPoint& dragViewportLocation) const
-{
- IntPoint dragLocation = m_frame->view()->windowToContents(dragViewportLocation);
- IntSize delta = dragLocation - m_mouseDownPos;
-
- int threshold = GeneralDragHysteresis;
- if (dragState().m_dragSrcIsImage)
- threshold = ImageDragHysteresis;
- else if (dragState().m_dragSrcIsLink)
- threshold = LinkDragHysteresis;
- else if (dragState().m_dragSrcInSelection)
- threshold = TextDragHysteresis;
-
- return abs(delta.width()) >= threshold || abs(delta.height()) >= threshold;
-}
-
-void EventHandler::freeClipboard()
-{
- if (dragState().m_dragClipboard)
- dragState().m_dragClipboard->setAccessPolicy(ClipboardNumb);
-}
-
-bool EventHandler::shouldDragAutoNode(Node* node, const IntPoint& point) const
-{
- ASSERT(node);
- if (node->hasChildNodes() || !m_frame->view())
- return false;
- return m_frame->page() && m_frame->page()->dragController()->mayStartDragAtEventLocation(m_frame, point);
-}
-
-void EventHandler::dragSourceMovedTo(const PlatformMouseEvent& event)
-{
- if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML)
- // for now we don't care if event handler cancels default behavior, since there is none
- dispatchDragSrcEvent(dragEvent, event);
-}
-
-void EventHandler::dragSourceEndedAt(const PlatformMouseEvent& event, DragOperation operation)
-{
- if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) {
- dragState().m_dragClipboard->setDestinationOperation(operation);
- // for now we don't care if event handler cancels default behavior, since there is none
- dispatchDragSrcEvent(dragendEvent, event);
- }
- freeClipboard();
- dragState().m_dragSrc = 0;
-}
-
-// returns if we should continue "default processing", i.e., whether eventhandler canceled
-bool EventHandler::dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent& event)
-{
- return !dispatchDragEvent(eventType, dragState().m_dragSrc.get(), event, dragState().m_dragClipboard.get());
-}
-
-bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event)
-{
- if (event.event().button() != LeftButton || event.event().eventType() != MouseEventMoved) {
- // If we allowed the other side of the bridge to handle a drag
- // last time, then m_mousePressed might still be set. So we
- // clear it now to make sure the next move after a drag
- // doesn't look like a drag.
- m_mousePressed = false;
- return false;
- }
-
- if (eventLoopHandleMouseDragged(event))
- return true;
-
- // Careful that the drag starting logic stays in sync with eventMayStartDrag()
-
- if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
- allowDHTMLDrag(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA);
- if (!dragState().m_dragSrcMayBeDHTML && !dragState().m_dragSrcMayBeUA)
- m_mouseDownMayStartDrag = false; // no element is draggable
- }
-
- if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
- // try to find an element that wants to be dragged
- HitTestRequest request(true, false);
- HitTestResult result(m_mouseDownPos);
- m_frame->contentRenderer()->layer()->hitTest(request, result);
- Node* node = result.innerNode();
- if (node && node->renderer())
- dragState().m_dragSrc = node->renderer()->draggableNode(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA,
- m_mouseDownPos.x(), m_mouseDownPos.y(), dragState().m_dragSrcIsDHTML);
- else
- dragState().m_dragSrc = 0;
-
- if (!dragState().m_dragSrc)
- m_mouseDownMayStartDrag = false; // no element is draggable
- else {
- // remember some facts about this source, while we have a HitTestResult handy
- node = result.URLElement();
- dragState().m_dragSrcIsLink = node && node->isLink();
-
- node = result.innerNonSharedNode();
- dragState().m_dragSrcIsImage = node && node->renderer() && node->renderer()->isImage();
-
- dragState().m_dragSrcInSelection = m_frame->selection()->contains(m_mouseDownPos);
- }
- }
-
- // For drags starting in the selection, the user must wait between the mousedown and mousedrag,
- // or else we bail on the dragging stuff and allow selection to occur
- if (m_mouseDownMayStartDrag && !dragState().m_dragSrcIsImage && dragState().m_dragSrcInSelection && event.event().timestamp() - m_mouseDownTimestamp < TextDragDelay) {
- m_mouseDownMayStartDrag = false;
- dragState().m_dragSrc = 0;
- // ...but if this was the first click in the window, we don't even want to start selection
- if (eventActivatedView(event.event()))
- m_mouseDownMayStartSelect = false;
- }
-
- if (!m_mouseDownMayStartDrag)
- return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll;
-
- // We are starting a text/image/url drag, so the cursor should be an arrow
- m_frame->view()->setCursor(pointerCursor());
-
- if (!dragHysteresisExceeded(event.event().pos()))
- return true;
-
- // Once we're past the hysteresis point, we don't want to treat this gesture as a click
- invalidateClick();
-
- DragOperation srcOp = DragOperationNone;
-
- freeClipboard(); // would only happen if we missed a dragEnd. Do it anyway, just
- // to make sure it gets numbified
- dragState().m_dragClipboard = createDraggingClipboard();
-
- if (dragState().m_dragSrcMayBeDHTML) {
- // Check to see if the is a DOM based drag, if it is get the DOM specified drag
- // image and offset
- if (dragState().m_dragSrcIsDHTML) {
- int srcX, srcY;
- if (RenderObject* renderer = dragState().m_dragSrc->renderer()) {
- renderer->absolutePosition(srcX, srcY);
- IntSize delta = m_mouseDownPos - IntPoint(srcX, srcY);
- dragState().m_dragClipboard->setDragImageElement(dragState().m_dragSrc.get(), IntPoint() + delta);
- } else {
- // The renderer has disappeared, this can happen if the onStartDrag handler has hidden
- // the element in some way. In this case we just kill the drag.
- m_mouseDownMayStartDrag = false;
- goto cleanupDrag;
- }
- }
-
- m_mouseDownMayStartDrag = dispatchDragSrcEvent(dragstartEvent, m_mouseDown)
- && !m_frame->selection()->isInPasswordField();
-
- // Invalidate clipboard here against anymore pasteboard writing for security. The drag
- // image can still be changed as we drag, but not the pasteboard data.
- dragState().m_dragClipboard->setAccessPolicy(ClipboardImageWritable);
-
- if (m_mouseDownMayStartDrag) {
- // gather values from DHTML element, if it set any
- dragState().m_dragClipboard->sourceOperation(srcOp);
-
- // Yuck, dragSourceMovedTo() can be called as a result of kicking off the drag with
- // dragImage! Because of that dumb reentrancy, we may think we've not started the
- // drag when that happens. So we have to assume it's started before we kick it off.
- dragState().m_dragClipboard->setDragHasStarted();
- }
- }
-
- if (m_mouseDownMayStartDrag) {
- DragController* dragController = m_frame->page() ? m_frame->page()->dragController() : 0;
- bool startedDrag = dragController && dragController->startDrag(m_frame, dragState().m_dragClipboard.get(), srcOp, event.event(), m_mouseDownPos, dragState().m_dragSrcIsDHTML);
- if (!startedDrag && dragState().m_dragSrcMayBeDHTML) {
- // Drag was canned at the last minute - we owe m_dragSrc a DRAGEND event
- dispatchDragSrcEvent(dragendEvent, event.event());
- m_mouseDownMayStartDrag = false;
- }
- }
-
-cleanupDrag:
- if (!m_mouseDownMayStartDrag) {
- // something failed to start the drag, cleanup
- freeClipboard();
- dragState().m_dragSrc = 0;
- }
-
- // No more default handling (like selection), whether we're past the hysteresis bounds or not
- return true;
-}
-
-bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEvent,
- bool isLineBreak, bool isBackTab)
-{
- if (!m_frame)
- return false;
-#ifndef NDEBUG
- // Platforms should differentiate real commands like selectAll from text input in disguise (like insertNewline),
- // and avoid dispatching text input events from keydown default handlers.
- if (underlyingEvent && underlyingEvent->isKeyboardEvent())
- ASSERT(static_cast<KeyboardEvent*>(underlyingEvent)->type() == keypressEvent);
-#endif
- EventTarget* target;
- if (underlyingEvent)
- target = underlyingEvent->target();
- else
- target = eventTargetNodeForDocument(m_frame->document());
- if (!target)
- return false;
- RefPtr<TextEvent> event = TextEvent::create(m_frame->domWindow(), text);
- event->setUnderlyingEvent(underlyingEvent);
- event->setIsLineBreak(isLineBreak);
- event->setIsBackTab(isBackTab);
- ExceptionCode ec;
- return target->dispatchEvent(event.release(), ec, true);
-}
-
-
-#if !PLATFORM(MAC) && !PLATFORM(QT)
-bool EventHandler::invertSenseOfTabsToLinks(KeyboardEvent*) const
-{
- return false;
-}
-#endif
-
-bool EventHandler::tabsToLinks(KeyboardEvent* event) const
-{
- Page* page = m_frame->page();
- if (!page)
- return false;
-
- if (page->chrome()->client()->tabsToLinks())
- return !invertSenseOfTabsToLinks(event);
-
- return invertSenseOfTabsToLinks(event);
-}
-
-void EventHandler::defaultTextInputEventHandler(TextEvent* event)
-{
- String data = event->data();
- if (data == "\n") {
- if (event->isLineBreak()) {
- if (m_frame->editor()->insertLineBreak())
- event->setDefaultHandled();
- } else {
- if (m_frame->editor()->insertParagraphSeparator())
- event->setDefaultHandled();
- }
- } else {
- if (m_frame->editor()->insertTextWithoutSendingTextEvent(data, false, event))
- event->setDefaultHandled();
- }
-}
-
-void EventHandler::defaultTabEventHandler(KeyboardEvent* event)
-{
- // We should only advance focus on tabs if no special modifier keys are held down.
- if (event->ctrlKey() || event->metaKey() || event->altGraphKey())
- return;
-
- Page* page = m_frame->page();
- if (!page)
- return;
- if (!page->tabKeyCyclesThroughElements())
- return;
-
- FocusDirection focusDirection = event->shiftKey() ? FocusDirectionBackward : FocusDirectionForward;
-
- // Tabs can be used in design mode editing.
- if (m_frame->document()->inDesignMode())
- return;
-
- if (page->focusController()->advanceFocus(focusDirection, event))
- event->setDefaultHandled();
-}
-
-void EventHandler::capsLockStateMayHaveChanged()
-{
- if (Document* d = m_frame->document())
- if (Node* node = d->focusedNode())
- if (RenderObject* r = node->renderer())
- r->capsLockStateMayHaveChanged();
-}
-
-unsigned EventHandler::pendingFrameUnloadEventCount()
-{
- return m_pendingFrameUnloadEventCount;
-}
-
-void EventHandler::addPendingFrameUnloadEventCount()
-{
- m_pendingFrameUnloadEventCount += 1;
- m_frame->page()->changePendingUnloadEventCount(1);
- return;
-}
-
-void EventHandler::removePendingFrameUnloadEventCount()
-{
- ASSERT( (-1 + (int)m_pendingFrameUnloadEventCount) >= 0 );
- m_pendingFrameUnloadEventCount -= 1;
- m_frame->page()->changePendingUnloadEventCount(-1);
- return;
-}
-
-void EventHandler::clearPendingFrameUnloadEventCount()
-{
- m_frame->page()->changePendingUnloadEventCount(-((int)m_pendingFrameUnloadEventCount));
- m_pendingFrameUnloadEventCount = 0;
- return;
-}
-
-unsigned EventHandler::pendingFrameBeforeUnloadEventCount()
-{
- return m_pendingFrameBeforeUnloadEventCount;
-}
-
-void EventHandler::addPendingFrameBeforeUnloadEventCount()
-{
- m_pendingFrameBeforeUnloadEventCount += 1;
- m_frame->page()->changePendingBeforeUnloadEventCount(1);
- return;
-}
-
-void EventHandler::removePendingFrameBeforeUnloadEventCount()
-{
- ASSERT( (-1 + (int)m_pendingFrameBeforeUnloadEventCount) >= 0 );
- m_pendingFrameBeforeUnloadEventCount -= 1;
- m_frame->page()->changePendingBeforeUnloadEventCount(-1);
- return;
-}
-
- void EventHandler::clearPendingFrameBeforeUnloadEventCount()
-{
- m_frame->page()->changePendingBeforeUnloadEventCount(-((int)m_pendingFrameBeforeUnloadEventCount));
- m_pendingFrameBeforeUnloadEventCount = 0;
- return;
-}
-}
diff --git a/webkit/pending/FileSystem.h b/webkit/pending/FileSystem.h
deleted file mode 100644
index 1e7edf1..0000000
--- a/webkit/pending/FileSystem.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Collabora, Ltd. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FileSystem_h
-#define FileSystem_h
-
-#if PLATFORM(GTK)
-#include <gmodule.h>
-#endif
-#if PLATFORM(QT)
-#include <QFile>
-#include <QLibrary>
-#if defined(Q_OS_WIN32)
-#include <windows.h>
-#endif
-#endif
-
-#include <time.h>
-
-#include <wtf/Platform.h>
-#include <wtf/Vector.h>
-
-#include "PlatformString.h"
-
-typedef const struct __CFData* CFDataRef;
-
-#if PLATFORM(WIN)
-// These are to avoid including <winbase.h> in a header for Chromium
-typedef void *HANDLE;
-// Assuming STRICT
-typedef struct HINSTANCE__* HINSTANCE;
-typedef HINSTANCE HMODULE;
-#endif
-
-namespace WebCore {
-
-class CString;
-
-#if PLATFORM(WIN)
-typedef HANDLE PlatformFileHandle;
-typedef HMODULE PlatformModule;
-// HACK: -1 is INVALID_HANDLE_VALUE, defined in <winbase.h>. Chromium tries to
-// avoid using Windows headers in headers. We'd rather move this into the .cpp.
-const PlatformFileHandle invalidPlatformFileHandle = (HANDLE)-1;
-
-struct PlatformModuleVersion {
- unsigned leastSig;
- unsigned mostSig;
-
- PlatformModuleVersion(unsigned)
- : leastSig(0)
- , mostSig(0)
- {
- }
-
- PlatformModuleVersion(unsigned lsb, unsigned msb)
- : leastSig(lsb)
- , mostSig(msb)
- {
- }
-
-};
-#elif PLATFORM(QT)
-
-typedef QFile* PlatformFileHandle;
-const PlatformFileHandle invalidPlatformFileHandle = 0;
-#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
-typedef QLibrary* PlatformModule;
-typedef unsigned PlatformModuleVersion;
-#elif defined(Q_OS_WIN32)
-typedef HMODULE PlatformModule;
-struct PlatformModuleVersion {
- unsigned leastSig;
- unsigned mostSig;
-
- PlatformModuleVersion(unsigned)
- : leastSig(0)
- , mostSig(0)
- {
- }
-
- PlatformModuleVersion(unsigned lsb, unsigned msb)
- : leastSig(lsb)
- , mostSig(msb)
- {
- }
-
-};
-#endif
-
-#else
-typedef int PlatformFileHandle;
-#if PLATFORM(GTK)
-typedef GModule* PlatformModule;
-#else
-typedef void* PlatformModule;
-#endif
-const PlatformFileHandle invalidPlatformFileHandle = -1;
-
-typedef unsigned PlatformModuleVersion;
-#endif
-
-bool fileExists(const String&);
-bool deleteFile(const String&);
-bool deleteEmptyDirectory(const String&);
-bool getFileSize(const String&, long long& result);
-bool getFileModificationTime(const String&, time_t& result);
-String pathByAppendingComponent(const String& path, const String& component);
-bool makeAllDirectories(const String& path);
-String homeDirectoryPath();
-String pathGetFileName(const String&);
-String directoryName(const String&);
-
-Vector<String> listDirectory(const String& path, const String& filter = String());
-
-CString fileSystemRepresentation(const String&);
-
-inline bool isHandleValid(const PlatformFileHandle& handle) { return handle != invalidPlatformFileHandle; }
-
-// Prefix is what the filename should be prefixed with, not the full path.
-CString openTemporaryFile(const char* prefix, PlatformFileHandle&);
-void closeFile(PlatformFileHandle&);
-int writeToFile(PlatformFileHandle, const char* data, int length);
-
-// Methods for dealing with loadable modules
-bool unloadModule(PlatformModule);
-
-#if PLATFORM(WIN)
-String localUserSpecificStorageDirectory();
-String roamingUserSpecificStorageDirectory();
-
-bool safeCreateFile(const String&, CFDataRef);
-#endif
-
-} // namespace WebCore
-
-#endif // FileSystem_h
diff --git a/webkit/pending/FileSystemWin.cpp b/webkit/pending/FileSystemWin.cpp
deleted file mode 100644
index d14babb..0000000
--- a/webkit/pending/FileSystemWin.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Collabora, Ltd. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include <windows.h>
-#include "FileSystem.h"
-
-#include "CString.h"
-#include "NotImplemented.h"
-#include "PlatformString.h"
-
-#include <shlwapi.h>
-
-namespace WebCore {
-
-// Don't include any of the file system code, since the renderer can't do
-// file system operations from sandbox.
-// These methods are hot referenced, so no definition is needed.
-
-String pathGetFileName(const String& path)
-{
- return String(::PathFindFileName(String(path).charactersWithNullTermination()));
-}
-
-String directoryName(const String& path)
-{
- notImplemented();
- return String();
-}
-
-// Used by Page::userStyleSheet().
-// The custom user stylesheets should be implemented more generically, in
-// order to support other protocols, like http: and data:
-bool getFileModificationTime(const String& /*path*/, time_t& /*result*/)
-{
- notImplemented();
- return false;
-}
-
-bool fileExists(const String& path)
-{
- notImplemented();
- return false;
-}
-
-bool getFileSize(const String&, long long& result)
-{
- notImplemented();
- return false;
-}
-
-// delteFile() and deleteEmptyDirectory() are used by
-// FormData::removeGeneratedFilesIfNeeded() for uploading bundles:
-// http://trac.webkit.org/changeset/32666
-// This approach will need refactoring to isolate file system operations
-// between browser/renderer
-
-bool deleteFile(const String& /*path*/)
-{
- notImplemented();
- return false;
-}
-
-bool deleteEmptyDirectory(const String& /*path*/)
-{
- notImplemented();
- return false;
-}
-
-bool unloadModule(PlatformModule module)
-{
- notImplemented();
- return false;
-}
-
-} // namespace WebCore
diff --git a/webkit/pending/Font.cpp b/webkit/pending/Font.cpp
deleted file mode 100644
index eafc11a..0000000
--- a/webkit/pending/Font.cpp
+++ /dev/null
@@ -1,839 +0,0 @@
-/**
- * This file is part of the html renderer for KDE.
- *
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2006 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "Font.h"
-
-#include "CharacterNames.h"
-#include "FloatRect.h"
-#include "FontCache.h"
-#include "FontFallbackList.h"
-#include "IntPoint.h"
-#include "GlyphBuffer.h"
-#include <wtf/unicode/Unicode.h>
-#include <wtf/MathExtras.h>
-
-#if USE(ICU_UNICODE)
-#include <unicode/unorm.h>
-#endif
-
-using namespace WTF;
-using namespace Unicode;
-
-namespace WebCore {
-
-// According to http://www.unicode.org/Public/UNIDATA/UCD.html#Canonical_Combining_Class_Values
-const uint8_t hiraganaKatakanaVoicingMarksCombiningClass = 8;
-
-const uint8_t Font::gRoundingHackCharacterTable[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*\t*/, 1 /*\n*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1 /*space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*-*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*?*/,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1 /*no-break space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-Font::CodePath Font::codePath = Auto;
-
-struct WidthIterator {
- WidthIterator(const Font* font, const TextRun& run);
-
- void advance(int to, GlyphBuffer* glyphBuffer = 0);
- bool advanceOneCharacter(float& width, GlyphBuffer* glyphBuffer = 0);
-
- const Font* m_font;
-
- const TextRun& m_run;
- int m_end;
-
- unsigned m_currentCharacter;
- float m_runWidthSoFar;
- float m_padding;
- float m_padPerSpace;
- float m_finalRoundingWidth;
-
-private:
- UChar32 normalizeVoicingMarks(int currentCharacter);
-};
-
-WidthIterator::WidthIterator(const Font* font, const TextRun& run)
- : m_font(font)
- , m_run(run)
- , m_end(run.length())
- , m_currentCharacter(0)
- , m_runWidthSoFar(0)
- , m_finalRoundingWidth(0)
-{
- // If the padding is non-zero, count the number of spaces in the run
- // and divide that by the padding for per space addition.
- m_padding = m_run.padding();
- if (!m_padding)
- m_padPerSpace = 0;
- else {
- float numSpaces = 0;
- for (int i = 0; i < run.length(); i++)
- if (Font::treatAsSpace(m_run[i]))
- numSpaces++;
-
- if (numSpaces == 0)
- m_padPerSpace = 0;
- else
- m_padPerSpace = ceilf(m_run.padding() / numSpaces);
- }
-}
-
-void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
-{
- if (offset > m_end)
- offset = m_end;
-
- int currentCharacter = m_currentCharacter;
- const UChar* cp = m_run.data(currentCharacter);
-
- bool rtl = m_run.rtl();
- bool hasExtraSpacing = m_font->letterSpacing() || m_font->wordSpacing() || m_padding;
-
- float runWidthSoFar = m_runWidthSoFar;
- float lastRoundingWidth = m_finalRoundingWidth;
-
- while (currentCharacter < offset) {
- UChar32 c = *cp;
- unsigned clusterLength = 1;
- if (c >= 0x3041) {
- if (c <= 0x30FE) {
- // Deal with Hiragana and Katakana voiced and semi-voiced syllables.
- // Normalize into composed form, and then look for glyph with base + combined mark.
- // Check above for character range to minimize performance impact.
- UChar32 normalized = normalizeVoicingMarks(currentCharacter);
- if (normalized) {
- c = normalized;
- clusterLength = 2;
- }
- } else if (U16_IS_SURROGATE(c)) {
- if (!U16_IS_SURROGATE_LEAD(c))
- break;
-
- // Do we have a surrogate pair? If so, determine the full Unicode (32 bit)
- // code point before glyph lookup.
- // Make sure we have another character and it's a low surrogate.
- if (currentCharacter + 1 >= m_run.length())
- break;
- UChar low = cp[1];
- if (!U16_IS_TRAIL(low))
- break;
- c = U16_GET_SUPPLEMENTARY(c, low);
- clusterLength = 2;
- }
- }
-
- const GlyphData& glyphData = m_font->glyphDataForCharacter(c, rtl);
- Glyph glyph = glyphData.glyph;
- const SimpleFontData* fontData = glyphData.fontData;
-
- ASSERT(fontData);
-
- // Now that we have a glyph and font data, get its width.
- float width;
- if (c == '\t' && m_run.allowTabs()) {
- float tabWidth = m_font->tabWidth();
- width = tabWidth - fmodf(m_run.xPos() + runWidthSoFar, tabWidth);
- } else {
- width = fontData->widthForGlyph(glyph);
- // We special case spaces in two ways when applying word rounding.
- // First, we round spaces to an adjusted width in all fonts.
- // Second, in fixed-pitch fonts we ensure that all characters that
- // match the width of the space character have the same width as the space character.
- if (width == fontData->m_spaceWidth && (fontData->m_treatAsFixedPitch || glyph == fontData->m_spaceGlyph) && m_run.applyWordRounding())
- width = fontData->m_adjustedSpaceWidth;
- }
-
- if (hasExtraSpacing && !m_run.spacingDisabled()) {
- // Account for letter-spacing.
- if (width && m_font->letterSpacing())
- width += m_font->letterSpacing();
-
- if (Font::treatAsSpace(c)) {
- // Account for padding. WebCore uses space padding to justify text.
- // We distribute the specified padding over the available spaces in the run.
- if (m_padding) {
- // Use left over padding if not evenly divisible by number of spaces.
- if (m_padding < m_padPerSpace) {
- width += m_padding;
- m_padding = 0;
- } else {
- width += m_padPerSpace;
- m_padding -= m_padPerSpace;
- }
- }
-
- // Account for word spacing.
- // We apply additional space between "words" by adding width to the space character.
- if (currentCharacter != 0 && !Font::treatAsSpace(cp[-1]) && m_font->wordSpacing())
- width += m_font->wordSpacing();
- }
- }
-
- // Advance past the character we just dealt with.
- cp += clusterLength;
- currentCharacter += clusterLength;
-
- // Account for float/integer impedance mismatch between CG and KHTML. "Words" (characters
- // followed by a character defined by isRoundingHackCharacter()) are always an integer width.
- // We adjust the width of the last character of a "word" to ensure an integer width.
- // If we move KHTML to floats we can remove this (and related) hacks.
-
- float oldWidth = width;
-
- // Force characters that are used to determine word boundaries for the rounding hack
- // to be integer width, so following words will start on an integer boundary.
- if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(c))
- width = ceilf(width);
-
- // Check to see if the next character is a "rounding hack character", if so, adjust
- // width so that the total run width will be on an integer boundary.
- if ((m_run.applyWordRounding() && currentCharacter < m_run.length() && Font::isRoundingHackCharacter(*cp))
- || (m_run.applyRunRounding() && currentCharacter >= m_end)) {
- float totalWidth = runWidthSoFar + width;
- width += ceilf(totalWidth) - totalWidth;
- }
-
- runWidthSoFar += width;
-
- if (glyphBuffer)
- glyphBuffer->add(glyph, fontData, (rtl ? oldWidth + lastRoundingWidth : width));
-
- lastRoundingWidth = width - oldWidth;
- }
-
- m_currentCharacter = currentCharacter;
- m_runWidthSoFar = runWidthSoFar;
- m_finalRoundingWidth = lastRoundingWidth;
-}
-
-bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer* glyphBuffer)
-{
- glyphBuffer->clear();
- advance(m_currentCharacter + 1, glyphBuffer);
- float w = 0;
- for (int i = 0; i < glyphBuffer->size(); ++i)
- w += glyphBuffer->advanceAt(i);
- width = w;
- return !glyphBuffer->isEmpty();
-}
-
-UChar32 WidthIterator::normalizeVoicingMarks(int currentCharacter)
-{
- if (currentCharacter + 1 < m_end) {
- if (combiningClass(m_run[currentCharacter + 1]) == hiraganaKatakanaVoicingMarksCombiningClass) {
-#if USE(ICU_UNICODE)
- // Normalize into composed form using 3.2 rules.
- UChar normalizedCharacters[2] = { 0, 0 };
- UErrorCode uStatus = U_ZERO_ERROR;
- int32_t resultLength = unorm_normalize(m_run.data(currentCharacter), 2,
- UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], 2, &uStatus);
- if (resultLength == 1 && uStatus == 0)
- return normalizedCharacters[0];
-#elif USE(QT4_UNICODE)
- QString tmp(reinterpret_cast<const QChar*>(m_run.data(currentCharacter)), 2);
- QString res = tmp.normalized(QString::NormalizationForm_C, QChar::Unicode_3_2);
- if (res.length() == 1)
- return res.at(0).unicode();
-#endif
- }
- }
- return 0;
-}
-
-// ============================================================================================
-// Font Implementation (Cross-Platform Portion)
-// ============================================================================================
-
-Font::Font()
- : m_pageZero(0)
- , m_cachedPrimaryFont(0)
- , m_letterSpacing(0)
- , m_wordSpacing(0)
- , m_isPlatformFont(false)
-{
-}
-
-Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing)
- : m_fontDescription(fd)
- , m_pageZero(0)
- , m_cachedPrimaryFont(0)
- , m_letterSpacing(letterSpacing)
- , m_wordSpacing(wordSpacing)
- , m_isPlatformFont(false)
-{
-}
-
-Font::Font(const FontPlatformData& fontData, bool isPrinterFont)
- : m_fontList(FontFallbackList::create())
- , m_pageZero(0)
- , m_cachedPrimaryFont(0)
- , m_letterSpacing(0)
- , m_wordSpacing(0)
- , m_isPlatformFont(true)
-{
- m_fontDescription.setUsePrinterFont(isPrinterFont);
- m_fontList->setPlatformFont(fontData);
-}
-
-Font::Font(const Font& other)
- : m_fontDescription(other.m_fontDescription)
- , m_fontList(other.m_fontList)
- , m_pages(other.m_pages)
- , m_pageZero(other.m_pageZero)
- , m_cachedPrimaryFont(other.m_cachedPrimaryFont)
- , m_letterSpacing(other.m_letterSpacing)
- , m_wordSpacing(other.m_wordSpacing)
- , m_isPlatformFont(other.m_isPlatformFont)
-{
-}
-
-Font& Font::operator=(const Font& other)
-{
- m_fontDescription = other.m_fontDescription;
- m_fontList = other.m_fontList;
- m_pages = other.m_pages;
- m_pageZero = other.m_pageZero;
- m_cachedPrimaryFont = other.m_cachedPrimaryFont;
- m_letterSpacing = other.m_letterSpacing;
- m_wordSpacing = other.m_wordSpacing;
- m_isPlatformFont = other.m_isPlatformFont;
- return *this;
-}
-
-Font::~Font()
-{
-}
-
-bool Font::operator==(const Font& other) const
-{
- // Our FontData don't have to be checked, since checking the font description will be fine.
- // FIXME: This does not work if the font was made with the FontPlatformData constructor.
- if ((m_fontList && m_fontList->loadingCustomFonts()) ||
- (other.m_fontList && other.m_fontList->loadingCustomFonts()))
- return false;
-
- FontSelector* first = m_fontList ? m_fontList->fontSelector() : 0;
- FontSelector* second = other.m_fontList ? other.m_fontList->fontSelector() : 0;
-
- return first == second
- && m_fontDescription == other.m_fontDescription
- && m_letterSpacing == other.m_letterSpacing
- && m_wordSpacing == other.m_wordSpacing
- && (m_fontList ? m_fontList->generation() : 0) == (other.m_fontList ? other.m_fontList->generation() : 0);
-}
-
-const GlyphData& Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCaps) const
-{
- bool useSmallCapsFont = forceSmallCaps;
- if (m_fontDescription.smallCaps()) {
- UChar32 upperC = Unicode::toUpper(c);
- if (upperC != c) {
- c = upperC;
- useSmallCapsFont = true;
- }
- }
-
- if (mirror)
- c = mirroredChar(c);
-
- unsigned pageNumber = (c / GlyphPage::size);
-
- GlyphPageTreeNode* node = pageNumber ? m_pages.get(pageNumber) : m_pageZero;
- if (!node) {
- node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber);
- if (pageNumber)
- m_pages.set(pageNumber, node);
- else
- m_pageZero = node;
- }
-
- GlyphPage* page;
- if (!useSmallCapsFont) {
- // Fastest loop, for the common case (not small caps).
- while (true) {
- page = node->page();
- if (page) {
- const GlyphData& data = page->glyphDataForCharacter(c);
- if (data.fontData)
- return data;
- if (node->isSystemFallback())
- break;
- }
-
- // Proceed with the fallback list.
- node = node->getChild(fontDataAt(node->level()), pageNumber);
- if (pageNumber)
- m_pages.set(pageNumber, node);
- else
- m_pageZero = node;
- }
- } else {
- while (true) {
- page = node->page();
- if (page) {
- const GlyphData& data = page->glyphDataForCharacter(c);
- if (data.fontData) {
- // The smallCapsFontData function should not normally return 0.
- // But if it does, we will just render the capital letter big.
- const SimpleFontData* smallCapsFontData = data.fontData->smallCapsFontData(m_fontDescription);
- if (!smallCapsFontData)
- return data;
-
- GlyphPageTreeNode* smallCapsNode = GlyphPageTreeNode::getRootChild(smallCapsFontData, pageNumber);
- const GlyphPage* smallCapsPage = smallCapsNode->page();
- if (smallCapsPage) {
- const GlyphData& data = smallCapsPage->glyphDataForCharacter(c);
- if (data.fontData)
- return data;
- }
-
- // Do not attempt system fallback off the smallCapsFontData. This is the very unlikely case that
- // a font has the lowercase character but the small caps font does not have its uppercase version.
- return smallCapsFontData->missingGlyphData();
- }
-
- if (node->isSystemFallback())
- break;
- }
-
- // Proceed with the fallback list.
- node = node->getChild(fontDataAt(node->level()), pageNumber);
- if (pageNumber)
- m_pages.set(pageNumber, node);
- else
- m_pageZero = node;
- }
- }
-
- ASSERT(page);
- ASSERT(node->isSystemFallback());
-
- // System fallback is character-dependent. When we get here, we
- // know that the character in question isn't in the system fallback
- // font's glyph page. Try to lazily create it here.
- UChar codeUnits[2];
- int codeUnitsLength;
- if (c <= 0xFFFF) {
- UChar c16 = c;
- if (Font::treatAsSpace(c16))
- codeUnits[0] = ' ';
- else if (Font::treatAsZeroWidthSpace(c16))
- codeUnits[0] = zeroWidthSpace;
- else
- codeUnits[0] = c16;
- codeUnitsLength = 1;
- } else {
- codeUnits[0] = U16_LEAD(c);
- codeUnits[1] = U16_TRAIL(c);
- codeUnitsLength = 2;
- }
- const SimpleFontData* characterFontData = FontCache::getFontDataForCharacters(*this, codeUnits, codeUnitsLength);
- if (useSmallCapsFont)
- characterFontData = characterFontData->smallCapsFontData(m_fontDescription);
- if (characterFontData) {
- // Got the fallback glyph and font.
- GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData, pageNumber)->page();
- const GlyphData& data = fallbackPage && fallbackPage->glyphDataForCharacter(c).fontData ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
- // Cache it so we don't have to do system fallback again next time.
- if (!useSmallCapsFont)
- page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
- return data;
- }
-
- // Even system fallback can fail; use the missing glyph in that case.
- // FIXME: It would be nicer to use the missing glyph from the last resort font instead.
- const GlyphData& data = primaryFont()->missingGlyphData();
- if (!useSmallCapsFont)
- page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
- return data;
-}
-
-void Font::cachePrimaryFont() const
-{
- ASSERT(m_fontList);
- ASSERT(!m_cachedPrimaryFont);
- m_cachedPrimaryFont = m_fontList->primaryFont(this)->fontDataForCharacter(' ');
-}
-
-const FontData* Font::fontDataAt(unsigned index) const
-{
- ASSERT(m_fontList);
- return m_fontList->fontDataAt(this, index);
-}
-
-const FontData* Font::fontDataForCharacters(const UChar* characters, int length) const
-{
- ASSERT(m_fontList);
- return m_fontList->fontDataForCharacters(this, characters, length);
-}
-
-void Font::update(PassRefPtr<FontSelector> fontSelector) const
-{
- // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up
- // being reasonably safe (because inherited fonts in the render tree pick up the new
- // style anyway. Other copies are transient, e.g., the state in the GraphicsContext, and
- // won't stick around long enough to get you in trouble). Still, this is pretty disgusting,
- // and could eventually be rectified by using RefPtrs for Fonts themselves.
- if (!m_fontList)
- m_fontList = FontFallbackList::create();
- m_fontList->invalidate(fontSelector);
- m_cachedPrimaryFont = 0;
- m_pageZero = 0;
- m_pages.clear();
-}
-
-int Font::width(const TextRun& run) const
-{
- return lroundf(floatWidth(run));
-}
-
-int Font::ascent() const
-{
- return primaryFont()->ascent();
-}
-
-int Font::descent() const
-{
- return primaryFont()->descent();
-}
-
-int Font::lineSpacing() const
-{
- return primaryFont()->lineSpacing();
-}
-
-int Font::lineGap() const
-{
- return primaryFont()->lineGap();
-}
-
-float Font::xHeight() const
-{
- return primaryFont()->xHeight();
-}
-
-unsigned Font::unitsPerEm() const
-{
- return primaryFont()->unitsPerEm();
-}
-
-int Font::spaceWidth() const
-{
- return (int)ceilf(primaryFont()->m_adjustedSpaceWidth + m_letterSpacing);
-}
-
-bool Font::isFixedPitch() const
-{
- ASSERT(m_fontList);
- return m_fontList->isFixedPitch(this);
-}
-
-void Font::setCodePath(CodePath p)
-{
- codePath = p;
-}
-
-bool Font::canUseGlyphCache(const TextRun& run) const
-{
- switch (codePath) {
- case Auto:
- break;
- case Simple:
- return true;
- case Complex:
- return false;
- }
-
- // Start from 0 since drawing and highlighting also measure the characters before run->from
- for (int i = 0; i < run.length(); i++) {
- const UChar c = run[i];
- if (c < 0x300) // U+0300 through U+036F Combining diacritical marks
- continue;
- if (c <= 0x36F)
- return false;
-
- if (c < 0x0591 || c == 0x05BE) // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
- continue;
- if (c <= 0x05CF)
- return false;
-
- if (c < 0x0600) // U+0600 through U+1059 Arabic, Syriac, Thaana, Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar
- continue;
- if (c <= 0x1059)
- return false;
-
- if (c < 0x1100) // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left here if you precompose; Modern Korean will be precomposed as a result of step A)
- continue;
- if (c <= 0x11FF)
- return false;
-
- if (c < 0x1780) // U+1780 through U+18AF Khmer, Mongolian
- continue;
- if (c <= 0x18AF)
- return false;
-
- if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0)
- continue;
- if (c <= 0x194F)
- return false;
-
- if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols
- continue;
- if (c <= 0x20FF)
- return false;
-
- if (c < 0xFE20) // U+FE20 through U+FE2F Combining half marks
- continue;
- if (c <= 0xFE2F)
- return false;
- }
-
- return true;
-
-}
-
-void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
-{
- // This glyph buffer holds our glyphs+advances+font data for each glyph.
- GlyphBuffer glyphBuffer;
-
- float startX = point.x();
- WidthIterator it(this, run);
- it.advance(from);
- float beforeWidth = it.m_runWidthSoFar;
- it.advance(to, &glyphBuffer);
-
- // We couldn't generate any glyphs for the run. Give up.
- if (glyphBuffer.isEmpty())
- return;
-
- float afterWidth = it.m_runWidthSoFar;
-
- if (run.rtl()) {
- float finalRoundingWidth = it.m_finalRoundingWidth;
- it.advance(run.length());
- startX += finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
- } else
- startX += beforeWidth;
-
- // Swap the order of the glyphs if right-to-left.
- if (run.rtl())
- for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end)
- glyphBuffer.swap(i, end);
-
- // Calculate the starting point of the glyphs to be displayed by adding
- // all the advances up to the first glyph.
- FloatPoint startPoint(startX, point.y());
- drawGlyphBuffer(context, glyphBuffer, run, startPoint);
-}
-
-void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuffer,
- const TextRun& run, const FloatPoint& point) const
-{
- // Draw each contiguous run of glyphs that use the same font data.
- const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
- FloatSize offset = glyphBuffer.offsetAt(0);
- FloatPoint startPoint(point);
- float nextX = startPoint.x();
- int lastFrom = 0;
- int nextGlyph = 0;
- while (nextGlyph < glyphBuffer.size()) {
- const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
- FloatSize nextOffset = glyphBuffer.offsetAt(nextGlyph);
- if (nextFontData != fontData || nextOffset != offset) {
- drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
-
- lastFrom = nextGlyph;
- fontData = nextFontData;
- offset = nextOffset;
- startPoint.setX(nextX);
- }
- nextX += glyphBuffer.advanceAt(nextGlyph);
- nextGlyph++;
- }
-
- drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
-}
-
-void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
-{
- // Don't draw anything while we are using custom fonts that are in the process of loading.
- if (m_fontList && m_fontList->loadingCustomFonts())
- return;
-
- to = (to == -1 ? run.length() : to);
-
-#if ENABLE(SVG_FONTS)
- if (primaryFont()->isSVGFont()) {
- drawTextUsingSVGFont(context, run, point, from, to);
- return;
- }
-#endif
-
- if (canUseGlyphCache(run))
- drawSimpleText(context, run, point, from, to);
- else
- drawComplexText(context, run, point, from, to);
-}
-
-float Font::floatWidth(const TextRun& run) const
-{
-#if ENABLE(SVG_FONTS)
- if (primaryFont()->isSVGFont())
- return floatWidthUsingSVGFont(run);
-#endif
-
- if (canUseGlyphCache(run))
- return floatWidthForSimpleText(run, 0);
- return floatWidthForComplexText(run);
-}
-
-float Font::floatWidth(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const
-{
-#if ENABLE(SVG_FONTS)
- if (primaryFont()->isSVGFont())
- return floatWidthUsingSVGFont(run, extraCharsAvailable, charsConsumed, glyphName);
-#endif
-
- charsConsumed = run.length();
- glyphName = "";
- if (canUseGlyphCache(run))
- return floatWidthForSimpleText(run, 0);
- return floatWidthForComplexText(run);
-}
-
-float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer) const
-{
- WidthIterator it(this, run);
- it.advance(run.length(), glyphBuffer);
- return it.m_runWidthSoFar;
-}
-
-FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
-{
-#if ENABLE(SVG_FONTS)
- if (primaryFont()->isSVGFont())
- return selectionRectForTextUsingSVGFont(run, point, h, from, to);
-#endif
-
- to = (to == -1 ? run.length() : to);
- if (canUseGlyphCache(run))
- return selectionRectForSimpleText(run, point, h, from, to);
- return selectionRectForComplexText(run, point, h, from, to);
-}
-
-FloatRect Font::selectionRectForSimpleText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
-{
- WidthIterator it(this, run);
- it.advance(from);
- float beforeWidth = it.m_runWidthSoFar;
- it.advance(to);
- float afterWidth = it.m_runWidthSoFar;
-
- // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning
- if (run.rtl()) {
- it.advance(run.length());
- float totalWidth = it.m_runWidthSoFar;
- return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h);
- } else {
- return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
- }
-}
-
-int Font::offsetForPosition(const TextRun& run, int x, bool includePartialGlyphs) const
-{
-#if ENABLE(SVG_FONTS)
- if (primaryFont()->isSVGFont())
- return offsetForPositionForTextUsingSVGFont(run, x, includePartialGlyphs);
-#endif
-
- if (canUseGlyphCache(run))
- return offsetForPositionForSimpleText(run, x, includePartialGlyphs);
- return offsetForPositionForComplexText(run, x, includePartialGlyphs);
-}
-
-int Font::offsetForPositionForSimpleText(const TextRun& run, int x, bool includePartialGlyphs) const
-{
- float delta = (float)x;
-
- WidthIterator it(this, run);
- GlyphBuffer localGlyphBuffer;
- unsigned offset;
- if (run.rtl()) {
- delta -= floatWidthForSimpleText(run, 0);
- while (1) {
- offset = it.m_currentCharacter;
- float w;
- if (!it.advanceOneCharacter(w, &localGlyphBuffer))
- break;
- delta += w;
- if (includePartialGlyphs) {
- if (delta - w / 2 >= 0)
- break;
- } else {
- if (delta >= 0)
- break;
- }
- }
- } else {
- while (1) {
- offset = it.m_currentCharacter;
- float w;
- if (!it.advanceOneCharacter(w, &localGlyphBuffer))
- break;
- delta -= w;
- if (includePartialGlyphs) {
- if (delta + w / 2 <= 0)
- break;
- } else {
- if (delta <= 0)
- break;
- }
- }
- }
-
- return offset;
-}
-
-#if ENABLE(SVG_FONTS)
-bool Font::isSVGFont() const
-{
- return primaryFont()->isSVGFont();
-}
-#endif
-
-FontSelector* Font::fontSelector() const
-{
- return m_fontList ? m_fontList->fontSelector() : 0;
-}
-
-}
diff --git a/webkit/pending/FontCache.cpp b/webkit/pending/FontCache.cpp
deleted file mode 100644
index 6ef1b63..0000000
--- a/webkit/pending/FontCache.cpp
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "FontCache.h"
-
-#include "Font.h"
-#include "FontFallbackList.h"
-#include "FontPlatformData.h"
-#include "FontSelector.h"
-#include "StringHash.h"
-#include <wtf/HashMap.h>
-#include <wtf/ListHashSet.h>
-
-using namespace WTF;
-
-namespace WebCore {
-
-struct FontPlatformDataCacheKey {
- FontPlatformDataCacheKey(const AtomicString& family = AtomicString(), unsigned size = 0, unsigned weight = 0, bool italic = false,
- bool isPrinterFont = false, FontRenderingMode renderingMode = NormalRenderingMode)
- : m_family(family)
- , m_size(size)
- , m_weight(weight)
- , m_italic(italic)
- , m_printerFont(isPrinterFont)
- , m_renderingMode(renderingMode)
- {
- }
-
- FontPlatformDataCacheKey(HashTableDeletedValueType) : m_size(hashTableDeletedSize()) { }
- bool isHashTableDeletedValue() const { return m_size == hashTableDeletedSize(); }
-
- bool operator==(const FontPlatformDataCacheKey& other) const
- {
- return equalIgnoringCase(m_family, other.m_family) && m_size == other.m_size &&
- m_weight == other.m_weight && m_italic == other.m_italic && m_printerFont == other.m_printerFont &&
- m_renderingMode == other.m_renderingMode;
- }
-
- AtomicString m_family;
- unsigned m_size;
- unsigned m_weight;
- bool m_italic;
- bool m_printerFont;
- FontRenderingMode m_renderingMode;
-
-private:
- static unsigned hashTableDeletedSize() { return 0xFFFFFFFFU; }
-};
-
-inline unsigned computeHash(const FontPlatformDataCacheKey& fontKey)
-{
- unsigned hashCodes[4] = {
- CaseFoldingHash::hash(fontKey.m_family),
- fontKey.m_size,
- fontKey.m_weight,
- static_cast<unsigned>(fontKey.m_italic) << 2 | static_cast<unsigned>(fontKey.m_printerFont) << 1 | static_cast<unsigned>(fontKey.m_renderingMode)
- };
- return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), sizeof(hashCodes) / sizeof(UChar));
-}
-
-struct FontPlatformDataCacheKeyHash {
- static unsigned hash(const FontPlatformDataCacheKey& font)
- {
- return computeHash(font);
- }
-
- static bool equal(const FontPlatformDataCacheKey& a, const FontPlatformDataCacheKey& b)
- {
- return a == b;
- }
-
- static const bool safeToCompareToEmptyOrDeleted = true;
-};
-
-struct FontPlatformDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformDataCacheKey> {
- static const bool emptyValueIsZero = true;
- static const FontPlatformDataCacheKey& emptyValue()
- {
- static FontPlatformDataCacheKey key(nullAtom);
- return key;
- }
- static void constructDeletedValue(FontPlatformDataCacheKey& slot)
- {
- new (&slot) FontPlatformDataCacheKey(HashTableDeletedValue);
- }
- static bool isDeletedValue(const FontPlatformDataCacheKey& value)
- {
- return value.isHashTableDeletedValue();
- }
-};
-
-typedef HashMap<FontPlatformDataCacheKey, FontPlatformData*, FontPlatformDataCacheKeyHash, FontPlatformDataCacheKeyTraits> FontPlatformDataCache;
-
-static FontPlatformDataCache* gFontPlatformDataCache = 0;
-
-FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fontDescription,
- const AtomicString& familyName,
- bool checkingAlternateName)
-{
- if (!gFontPlatformDataCache) {
- gFontPlatformDataCache = new FontPlatformDataCache;
- platformInit();
- }
-
- FontPlatformDataCacheKey key(familyName, fontDescription.computedPixelSize(), fontDescription.weight(), fontDescription.italic(),
- fontDescription.usePrinterFont(), fontDescription.renderingMode());
- FontPlatformData* result = 0;
- bool foundResult;
- FontPlatformDataCache::iterator it = gFontPlatformDataCache->find(key);
- if (it == gFontPlatformDataCache->end()) {
- result = createFontPlatformData(fontDescription, familyName);
- gFontPlatformDataCache->set(key, result);
- foundResult = result;
- } else {
- result = it->second;
- foundResult = true;
- }
-
- if (!foundResult && !checkingAlternateName) {
- // We were unable to find a font. We have a small set of fonts that we alias to other names,
- // e.g., Arial/Helvetica, Courier/Courier New, etc. Try looking up the font under the aliased name.
- const AtomicString& alternateName = alternateFamilyName(familyName);
- if (!alternateName.isEmpty())
- result = getCachedFontPlatformData(fontDescription, alternateName, true);
- if (result)
- gFontPlatformDataCache->set(key, new FontPlatformData(*result)); // Cache the result under the old name.
- }
-
- return result;
-}
-
-struct FontDataCacheKeyHash {
- static unsigned hash(const FontPlatformData& platformData)
- {
- return platformData.hash();
- }
-
- static bool equal(const FontPlatformData& a, const FontPlatformData& b)
- {
- return a == b;
- }
-
- static const bool safeToCompareToEmptyOrDeleted = true;
-};
-
-struct FontDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformData> {
- static const bool emptyValueIsZero = true;
- static const bool needsDestruction = true;
- static const FontPlatformData& emptyValue()
- {
- static FontPlatformData key;
- return key;
- }
- static void constructDeletedValue(FontPlatformData& slot)
- {
- new (&slot) FontPlatformData(HashTableDeletedValue);
- }
- static bool isDeletedValue(const FontPlatformData& value)
- {
- return value.isHashTableDeletedValue();
- }
-};
-
-typedef HashMap<FontPlatformData, pair<SimpleFontData*, unsigned>, FontDataCacheKeyHash, FontDataCacheKeyTraits> FontDataCache;
-
-static FontDataCache* gFontDataCache = 0;
-
-const int cMaxInactiveFontData = 120; // Pretty Low Threshold
-const float cTargetInactiveFontData = 100;
-static ListHashSet<const SimpleFontData*>* gInactiveFontData = 0;
-
-SimpleFontData* FontCache::getCachedFontData(const FontPlatformData* platformData)
-{
- if (!platformData)
- return 0;
-
- if (!gFontDataCache) {
- gFontDataCache = new FontDataCache;
- gInactiveFontData = new ListHashSet<const SimpleFontData*>;
- }
-
- FontDataCache::iterator result = gFontDataCache->find(*platformData);
- if (result == gFontDataCache->end()) {
- pair<SimpleFontData*, unsigned> newValue(new SimpleFontData(*platformData), 1);
- gFontDataCache->set(*platformData, newValue);
- return newValue.first;
- }
- if (!result.get()->second.second++) {
- ASSERT(gInactiveFontData->contains(result.get()->second.first));
- gInactiveFontData->remove(result.get()->second.first);
- }
-
- return result.get()->second.first;
-}
-
-void FontCache::releaseFontData(const SimpleFontData* fontData)
-{
- ASSERT(gFontDataCache);
- ASSERT(!fontData->isCustomFont());
-
- FontDataCache::iterator it = gFontDataCache->find(fontData->platformData());
- ASSERT(it != gFontDataCache->end());
-
- if (!--it->second.second) {
- gInactiveFontData->add(fontData);
- if (gInactiveFontData->size() > cMaxInactiveFontData)
- purgeInactiveFontData(gInactiveFontData->size() - cTargetInactiveFontData);
- }
-}
-
-void FontCache::purgeInactiveFontData(int count)
-{
- if (!gInactiveFontData)
- return;
-
- static bool isPurging; // Guard against reentry when e.g. a deleted FontData releases its small caps FontData.
- if (isPurging)
- return;
-
- isPurging = true;
-
- ListHashSet<const SimpleFontData*>::iterator end = gInactiveFontData->end();
- ListHashSet<const SimpleFontData*>::iterator it = gInactiveFontData->begin();
- for (int i = 0; i < count && it != end; ++it, ++i) {
- const SimpleFontData* fontData = *it.get();
- gFontDataCache->remove(fontData->platformData());
- delete fontData;
- }
-
- if (it == end) {
- // Removed everything
- gInactiveFontData->clear();
- } else {
- for (int i = 0; i < count; ++i)
- gInactiveFontData->remove(gInactiveFontData->begin());
- }
-
- Vector<FontPlatformDataCacheKey> keysToRemove;
- keysToRemove.reserveCapacity(gFontPlatformDataCache->size());
- FontPlatformDataCache::iterator platformDataEnd = gFontPlatformDataCache->end();
- for (FontPlatformDataCache::iterator platformData = gFontPlatformDataCache->begin(); platformData != platformDataEnd; ++platformData) {
- if (platformData->second && !gFontDataCache->contains(*platformData->second))
- keysToRemove.append(platformData->first);
- }
-
- size_t keysToRemoveCount = keysToRemove.size();
- for (size_t i = 0; i < keysToRemoveCount; ++i)
- delete gFontPlatformDataCache->take(keysToRemove[i]);
-
- isPurging = false;
-}
-
-size_t FontCache::fontDataCount()
-{
- if (gFontDataCache)
- return gFontDataCache->size();
- return 0;
-}
-
-size_t FontCache::inactiveFontDataCount()
-{
- if (gInactiveFontData)
- return gInactiveFontData->size();
- return 0;
-}
-
-const FontData* FontCache::getFontData(const Font& font, int& familyIndex, FontSelector* fontSelector)
-{
- FontPlatformData* result = 0;
-
- int startIndex = familyIndex;
- const FontFamily* startFamily = &font.fontDescription().family();
- for (int i = 0; startFamily && i < startIndex; i++)
- startFamily = startFamily->next();
- const FontFamily* currFamily = startFamily;
- while (currFamily && !result) {
- familyIndex++;
- if (currFamily->family().length()) {
- if (fontSelector) {
- FontData* data = fontSelector->getFontData(font.fontDescription(), currFamily->family());
- if (data)
- return data;
- }
- result = getCachedFontPlatformData(font.fontDescription(), currFamily->family());
- }
- currFamily = currFamily->next();
- }
-
- if (!currFamily)
- familyIndex = cAllFamiliesScanned;
-
- if (!result)
- // We didn't find a font. Try to find a similar font using our own specific knowledge about our platform.
- // For example on OS X, we know to map any families containing the words Arabic, Pashto, or Urdu to the
- // Geeza Pro font.
- result = getSimilarFontPlatformData(font);
-
- if (!result && startIndex == 0) {
- // If it's the primary font that we couldn't find, we try the following. In all other cases, we will
- // just use per-character system fallback.
-
- if (fontSelector) {
- // Try the user's preferred standard font.
- if (FontData* data = fontSelector->getFontData(font.fontDescription(), "-webkit-standard"))
- return data;
- }
-
- // Still no result. Hand back our last resort fallback font.
- result = getLastResortFallbackFont(font.fontDescription());
- }
-
- // Now that we have a result, we need to go from FontPlatformData -> FontData.
- return getCachedFontData(result);
-}
-
-static HashSet<FontSelector*>* gClients;
-
-void FontCache::addClient(FontSelector* client)
-{
- if (!gClients)
- gClients = new HashSet<FontSelector*>;
-
- ASSERT(!gClients->contains(client));
- gClients->add(client);
-}
-
-void FontCache::removeClient(FontSelector* client)
-{
- ASSERT(gClients);
- ASSERT(gClients->contains(client));
-
- gClients->remove(client);
-}
-
-static unsigned gGeneration = 0;
-
-unsigned FontCache::generation()
-{
- return gGeneration;
-}
-
-void FontCache::invalidate()
-{
- if (!gClients) {
- ASSERT(!gFontPlatformDataCache);
- return;
- }
-
- if (gFontPlatformDataCache) {
- deleteAllValues(*gFontPlatformDataCache);
- delete gFontPlatformDataCache;
- gFontPlatformDataCache = new FontPlatformDataCache;
- }
-
- gGeneration++;
-
- Vector<RefPtr<FontSelector> > clients;
- size_t numClients = gClients->size();
- clients.reserveCapacity(numClients);
- HashSet<FontSelector*>::iterator end = gClients->end();
- for (HashSet<FontSelector*>::iterator it = gClients->begin(); it != end; ++it)
- clients.append(*it);
-
- ASSERT(numClients == clients.size());
- for (size_t i = 0; i < numClients; ++i)
- clients[i]->fontCacheInvalidated();
-
- purgeInactiveFontData();
-}
-
-} // namespace WebCore
diff --git a/webkit/pending/FontCache.h b/webkit/pending/FontCache.h
deleted file mode 100644
index 9c588aa..0000000
--- a/webkit/pending/FontCache.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2006, 2008 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FontCache_h
-#define FontCache_h
-
-#include <limits.h>
-#include <wtf/Vector.h>
-#include <unicode/uscript.h>
-#include <wtf/unicode/Unicode.h>
-
-#if PLATFORM(WIN)
-#include <objidl.h>
-#include <mlang.h>
-#endif
-
-namespace WebCore
-{
-
-class AtomicString;
-class Font;
-class FontPlatformData;
-class FontData;
-class FontDescription;
-class FontSelector;
-class SimpleFontData;
-
-class FontCache {
-public:
- static const FontData* getFontData(const Font&, int& familyIndex, FontSelector*);
- static void releaseFontData(const SimpleFontData*);
-
- // This method is implemented by the platform.
- // FIXME: Font data returned by this method never go inactive because callers don't track and release them.
- static const SimpleFontData* getFontDataForCharacters(const Font&, const UChar* characters, int length);
-
- // Also implemented by the platform.
- static void platformInit();
-
-#if PLATFORM(WIN)
- static IMLangFontLink2* getFontLinkInterface();
-#endif
-
- static void getTraitsInFamily(const AtomicString&, Vector<unsigned>&);
-
- static FontPlatformData* getCachedFontPlatformData(const FontDescription&, const AtomicString& family, bool checkingAlternateName = false);
- static SimpleFontData* getCachedFontData(const FontPlatformData*);
- static FontPlatformData* getLastResortFallbackFont(const FontDescription&);
-
- bool fontExists(const FontDescription&, const AtomicString& family);
-
- // TODO(jungshik): Is this the best place to put this function? It may
- // or may not be. Font.h is another place we can cosider.
- // Return a font family for |script| and |FontDescription.genericFamily()|.
- // It will return an empty atom if we can't find a font matching
- // script and genericFamily in FontDescription. A caller should check
- // the emptyness before using it.
- static AtomicString getGenericFontForScript(UScriptCode script, const FontDescription&);
- static void addClient(FontSelector*);
- static void removeClient(FontSelector*);
-
- static unsigned generation();
- static void invalidate();
-
- static size_t fontDataCount();
- static size_t inactiveFontDataCount();
- static void purgeInactiveFontData(int count = INT_MAX);
-
-private:
- // These methods are implemented by each platform.
- static FontPlatformData* getSimilarFontPlatformData(const Font&);
- static FontPlatformData* createFontPlatformData(const FontDescription&, const AtomicString& family);
- static const AtomicString& alternateFamilyName(const AtomicString& family);
-
- friend class SimpleFontData;
- friend class FontFallbackList;
-};
-
-}
-
-#endif
diff --git a/webkit/pending/FontDescription.h b/webkit/pending/FontDescription.h
deleted file mode 100644
index fa95928..0000000
--- a/webkit/pending/FontDescription.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * (C) 2000 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIother.m_ If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USm_
- *
- */
-
-#ifndef FontDescription_h
-#define FontDescription_h
-
-#include "FontFamily.h"
-#include "FontRenderingMode.h"
-#include "FontTraitsMask.h"
-#include <unicode/uscript.h>
-
-namespace WebCore {
-
-enum FontWeight {
- FontWeight100,
- FontWeight200,
- FontWeight300,
- FontWeight400,
- FontWeight500,
- FontWeight600,
- FontWeight700,
- FontWeight800,
- FontWeight900,
- FontWeightNormal = FontWeight400,
- FontWeightBold = FontWeight700
-};
-
-class FontDescription {
-public:
- enum GenericFamilyType { NoFamily, StandardFamily, SerifFamily, SansSerifFamily,
- MonospaceFamily, CursiveFamily, FantasyFamily };
-
- FontDescription()
- : m_specifiedSize(0)
- , m_computedSize(0)
- , m_italic(false)
- , m_smallCaps(false)
- , m_isAbsoluteSize(false)
- , m_weight(FontWeightNormal)
- , m_genericFamily(NoFamily)
- , m_usePrinterFont(false)
- , m_renderingMode(NormalRenderingMode)
- , m_keywordSize(0)
- , m_dominantScript(USCRIPT_INVALID_CODE)
- {
- }
-
- bool operator==(const FontDescription&) const;
- bool operator!=(const FontDescription& other) const { return !(*this == other); }
-
- const FontFamily& family() const { return m_familyList; }
- FontFamily& firstFamily() { return m_familyList; }
- float specifiedSize() const { return m_specifiedSize; }
- float computedSize() const { return m_computedSize; }
- bool italic() const { return m_italic; }
- int computedPixelSize() const { return int(m_computedSize + 0.5f); }
- bool smallCaps() const { return m_smallCaps; }
- bool isAbsoluteSize() const { return m_isAbsoluteSize; }
- FontWeight weight() const { return static_cast<FontWeight>(m_weight); }
- FontWeight lighterWeight() const;
- FontWeight bolderWeight() const;
- GenericFamilyType genericFamily() const { return static_cast<GenericFamilyType>(m_genericFamily); }
- bool usePrinterFont() const { return m_usePrinterFont; }
- FontRenderingMode renderingMode() const { return static_cast<FontRenderingMode>(m_renderingMode); }
- int keywordSize() const { return m_keywordSize; }
- UScriptCode dominantScript() const { return m_dominantScript; }
-
- FontTraitsMask traitsMask() const;
-
- void setFamily(const FontFamily& family) { m_familyList = family; }
- void setComputedSize(float s) { m_computedSize = s; }
- void setSpecifiedSize(float s) { m_specifiedSize = s; }
- void setItalic(bool i) { m_italic = i; }
- void setSmallCaps(bool c) { m_smallCaps = c; }
- void setIsAbsoluteSize(bool s) { m_isAbsoluteSize = s; }
- void setWeight(FontWeight w) { m_weight = w; }
- void setGenericFamily(GenericFamilyType genericFamily) { m_genericFamily = genericFamily; }
- void setUsePrinterFont(bool p) { m_usePrinterFont = p; }
- void setRenderingMode(FontRenderingMode mode) { m_renderingMode = mode; }
- void setKeywordSize(int s) { m_keywordSize = s; }
- void setDominantScript(UScriptCode s) { m_dominantScript = s; }
-
-private:
- FontFamily m_familyList; // The list of font families to be used.
-
- float m_specifiedSize; // Specified CSS value. Independent of rendering issues such as integer
- // rounding, minimum font sizes, and zooming.
- float m_computedSize; // Computed size adjusted for the minimum font size and the zoom factor.
-
- bool m_italic : 1;
- bool m_smallCaps : 1;
- bool m_isAbsoluteSize : 1; // Whether or not CSS specified an explicit size
- // (logical sizes like "medium" don't count).
- unsigned m_weight : 8; // FontWeight
- unsigned m_genericFamily : 3; // GenericFamilyType
- bool m_usePrinterFont : 1;
-
- unsigned m_renderingMode : 1; // Used to switch between CG and GDI text on Windows.
-
- int m_keywordSize : 4; // We cache whether or not a font is currently represented by a CSS keyword (e.g., medium). If so,
- // then we can accurately translate across different generic families to adjust for different preference settings
- // (e.g., 13px monospace vs. 16px everything else). Sizes are 1-8 (like the HTML size values for <font>).
- UScriptCode m_dominantScript; // See the comment in Document.h
-
-};
-
-inline bool FontDescription::operator==(const FontDescription& other) const
-{
- return m_familyList == other.m_familyList
- && m_specifiedSize == other.m_specifiedSize
- && m_computedSize == other.m_computedSize
- && m_italic == other.m_italic
- && m_smallCaps == other.m_smallCaps
- && m_isAbsoluteSize == other.m_isAbsoluteSize
- && m_weight == other.m_weight
- && m_genericFamily == other.m_genericFamily
- && m_usePrinterFont == other.m_usePrinterFont
- && m_renderingMode == other.m_renderingMode
- && m_keywordSize == other.m_keywordSize;
-}
-
-}
-
-#endif
diff --git a/webkit/pending/Frame.cpp b/webkit/pending/Frame.cpp
deleted file mode 100644
index 0b1483a..0000000
--- a/webkit/pending/Frame.cpp
+++ /dev/null
@@ -1,1905 +0,0 @@
-/*
- * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
- * 1999 Lars Knoll <knoll@kde.org>
- * 1999 Antti Koivisto <koivisto@kde.org>
- * 2000 Simon Hausmann <hausmann@kde.org>
- * 2000 Stefan Schimanski <1Stein@gmx.de>
- * 2001 George Staikos <staikos@kde.org>
- * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com>
- * Copyright (C) 2007 Trolltech ASA
- * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "Frame.h"
-#include "FramePrivate.h"
-
-#include "ApplyStyleCommand.h"
-#include "BeforeUnloadEvent.h"
-#include "CSSComputedStyleDeclaration.h"
-#include "CSSProperty.h"
-#include "CSSPropertyNames.h"
-#include "CachedCSSStyleSheet.h"
-#include "DOMWindow.h"
-#include "DocLoader.h"
-#include "DocumentType.h"
-#include "EditingText.h"
-#include "EditorClient.h"
-#include "EventNames.h"
-#include "FocusController.h"
-#include "FrameLoader.h"
-#include "FrameView.h"
-#include "GraphicsContext.h"
-#include "HTMLDocument.h"
-#include "HTMLFormElement.h"
-#include "HTMLFrameElementBase.h"
-#include "HTMLFormControlElement.h"
-#include "HTMLNames.h"
-#include "HTMLTableCellElement.h"
-#include "HitTestResult.h"
-#include "Logging.h"
-#include "markup.h"
-#include "MediaFeatureNames.h"
-#include "Navigator.h"
-#include "NodeList.h"
-#include "Page.h"
-#include "RegularExpression.h"
-#include "RenderPart.h"
-#include "RenderTableCell.h"
-#include "RenderTextControl.h"
-#include "RenderTheme.h"
-#include "RenderView.h"
-#include "ScriptController.h"
-#include "Settings.h"
-#include "SystemTime.h"
-#include "TextIterator.h"
-#include "TextResourceDecoder.h"
-#include "XMLNames.h"
-#include "ScriptController.h"
-#include "npruntime_impl.h"
-#include "runtime_root.h"
-#include "visible_units.h"
-#include <wtf/RefCountedLeakCounter.h>
-
-#if USE(JSC)
-#include "JSDOMWindowShell.h"
-#endif
-
-#if FRAME_LOADS_USER_STYLESHEET
-#include "UserStyleSheetLoader.h"
-#endif
-
-#if ENABLE(SVG)
-#include "SVGDocument.h"
-#include "SVGDocumentExtensions.h"
-#include "SVGNames.h"
-#include "XLinkNames.h"
-#endif
-
-using namespace std;
-
-namespace WebCore {
-
-using namespace EventNames;
-using namespace HTMLNames;
-
-double Frame::s_currentPaintTimeStamp = 0.0;
-
-#ifndef NDEBUG
-static WTF::RefCountedLeakCounter frameCounter("Frame");
-#endif
-
-static inline Frame* parentFromOwnerElement(HTMLFrameOwnerElement* ownerElement)
-{
- if (!ownerElement)
- return 0;
- return ownerElement->document()->frame();
-}
-
-Frame::Frame(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* frameLoaderClient)
- : d(new FramePrivate(page, parentFromOwnerElement(ownerElement), this, ownerElement, frameLoaderClient))
-{
- AtomicString::init();
- EventNames::init();
- HTMLNames::init();
- QualifiedName::init();
- MediaFeatureNames::init();
-
-#if ENABLE(SVG)
- SVGNames::init();
- XLinkNames::init();
-#endif
-
- XMLNames::init();
-
- if (!ownerElement)
- page->setMainFrame(this);
- else {
- page->incrementFrameCount();
- // Make sure we will not end up with two frames referencing the same owner element.
- ASSERT((!(ownerElement->m_contentFrame)) || (ownerElement->m_contentFrame->ownerElement() != ownerElement));
- ownerElement->m_contentFrame = this;
- }
-
-#ifndef NDEBUG
- frameCounter.increment();
-#endif
-}
-
-Frame::~Frame()
-{
- setView(0);
- loader()->clearRecordedFormValues();
- loader()->cancelAndClear();
-
- // FIXME: We should not be doing all this work inside the destructor
-
- ASSERT(!d->m_lifeSupportTimer.isActive());
-
-#ifndef NDEBUG
- frameCounter.decrement();
-#endif
-
- d->m_script.disconnectFrame();
-
- disconnectOwnerElement();
-
- if (d->m_domWindow)
- d->m_domWindow->disconnectFrame();
-
- HashSet<DOMWindow*>::iterator end = d->m_liveFormerWindows.end();
- for (HashSet<DOMWindow*>::iterator it = d->m_liveFormerWindows.begin(); it != end; ++it)
- (*it)->disconnectFrame();
-
- if (d->m_view) {
- d->m_view->hide();
- d->m_view->clearFrame();
- }
-
- ASSERT(!d->m_lifeSupportTimer.isActive());
-
-#if FRAME_LOADS_USER_STYLESHEET
- delete d->m_userStyleSheetLoader;
-#endif
-
- delete d;
- d = 0;
-}
-
-void Frame::init()
-{
- d->m_loader.init();
-}
-
-FrameLoader* Frame::loader() const
-{
- return &d->m_loader;
-}
-
-FrameView* Frame::view() const
-{
- return d->m_view.get();
-}
-
-void Frame::setView(FrameView* view)
-{
- // Detach the document now, so any onUnload handlers get run - if
- // we wait until the view is destroyed, then things won't be
- // hooked up enough for some JavaScript calls to work.
- if (!view && d->m_doc && d->m_doc->attached() && !d->m_doc->inPageCache()) {
- // FIXME: We don't call willRemove here. Why is that OK?
- d->m_doc->detach();
- if (d->m_view)
- d->m_view->unscheduleRelayout();
- }
- eventHandler()->clear();
-
- d->m_view = view;
-
- // Only one form submission is allowed per view of a part.
- // Since this part may be getting reused as a result of being
- // pulled from the back/forward cache, reset this flag.
- loader()->resetMultipleFormSubmissionProtection();
-}
-
-ScriptController* Frame::script()
-{
- return &d->m_script;
-}
-
-Document* Frame::document() const
-{
- return d->m_doc.get();
-}
-
-void Frame::setDocument(PassRefPtr<Document> newDoc)
-{
- if (d->m_doc && d->m_doc->attached() && !d->m_doc->inPageCache()) {
- // FIXME: We don't call willRemove here. Why is that OK?
- d->m_doc->detach();
- }
-
- d->m_doc = newDoc;
- if (d->m_doc && selection()->isFocusedAndActive())
- setUseSecureKeyboardEntry(d->m_doc->useSecureKeyboardEntryWhenActive());
-
- if (d->m_doc && !d->m_doc->attached())
- d->m_doc->attach();
-
- // Update the cached 'document' property, which is now stale.
- d->m_script.updateDocument();
-}
-
-Settings* Frame::settings() const
-{
- return d->m_page ? d->m_page->settings() : 0;
-}
-
-String Frame::selectedText() const
-{
- return plainText(selection()->toRange().get());
-}
-
-IntRect Frame::firstRectForRange(Range* range) const
-{
- int extraWidthToEndOfLine = 0;
- ExceptionCode ec = 0;
- ASSERT(range->startContainer(ec));
- ASSERT(range->endContainer(ec));
- InlineBox* startInlineBox;
- int startCaretOffset;
- range->startPosition().getInlineBoxAndOffset(DOWNSTREAM, startInlineBox, startCaretOffset);
- IntRect startCaretRect = range->startContainer(ec)->renderer()->caretRect(startInlineBox, startCaretOffset, &extraWidthToEndOfLine);
-
- InlineBox* endInlineBox;
- int endCaretOffset;
- range->endPosition().getInlineBoxAndOffset(UPSTREAM, endInlineBox, endCaretOffset);
- IntRect endCaretRect = range->endContainer(ec)->renderer()->caretRect(endInlineBox, endCaretOffset);
-
- if (startCaretRect.y() == endCaretRect.y()) {
- // start and end are on the same line
- return IntRect(min(startCaretRect.x(), endCaretRect.x()),
- startCaretRect.y(),
- abs(endCaretRect.x() - startCaretRect.x()),
- max(startCaretRect.height(), endCaretRect.height()));
- }
-
- // start and end aren't on the same line, so go from start to the end of its line
- return IntRect(startCaretRect.x(),
- startCaretRect.y(),
- startCaretRect.width() + extraWidthToEndOfLine,
- startCaretRect.height());
-}
-
-SelectionController* Frame::selection() const
-{
- return &d->m_selectionController;
-}
-
-Editor* Frame::editor() const
-{
- return &d->m_editor;
-}
-
-TextGranularity Frame::selectionGranularity() const
-{
- return d->m_selectionGranularity;
-}
-
-void Frame::setSelectionGranularity(TextGranularity granularity) const
-{
- d->m_selectionGranularity = granularity;
-}
-
-SelectionController* Frame::dragCaretController() const
-{
- return d->m_page->dragCaretController();
-}
-
-
-AnimationController* Frame::animation() const
-{
- return &d->m_animationController;
-}
-
-static RegularExpression* createRegExpForLabels(const Vector<String>& labels)
-{
- // REVIEW- version of this call in FrameMac.mm caches based on the NSArray ptrs being
- // the same across calls. We can't do that.
-
- static RegularExpression wordRegExp = RegularExpression("\\w");
- String pattern("(");
- unsigned int numLabels = labels.size();
- unsigned int i;
- for (i = 0; i < numLabels; i++) {
- String label = labels[i];
-
- bool startsWithWordChar = false;
- bool endsWithWordChar = false;
- if (label.length() != 0) {
- startsWithWordChar = wordRegExp.search(label.substring(0, 1)) >= 0;
- endsWithWordChar = wordRegExp.search(label.substring(label.length() - 1, 1)) >= 0;
- }
-
- if (i != 0)
- pattern.append("|");
- // Search for word boundaries only if label starts/ends with "word characters".
- // If we always searched for word boundaries, this wouldn't work for languages
- // such as Japanese.
- if (startsWithWordChar) {
- pattern.append("\\b");
- }
- pattern.append(label);
- if (endsWithWordChar) {
- pattern.append("\\b");
- }
- }
- pattern.append(")");
- return new RegularExpression(pattern, false);
-}
-
-String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell)
-{
- RenderTableCell* cellRenderer = static_cast<RenderTableCell*>(cell->renderer());
-
- if (cellRenderer && cellRenderer->isTableCell()) {
- RenderTableCell* cellAboveRenderer = cellRenderer->table()->cellAbove(cellRenderer);
-
- if (cellAboveRenderer) {
- HTMLTableCellElement* aboveCell =
- static_cast<HTMLTableCellElement*>(cellAboveRenderer->element());
-
- if (aboveCell) {
- // search within the above cell we found for a match
- for (Node* n = aboveCell->firstChild(); n; n = n->traverseNextNode(aboveCell)) {
- if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) {
- // For each text chunk, run the regexp
- String nodeString = n->nodeValue();
- int pos = regExp->searchRev(nodeString);
- if (pos >= 0)
- return nodeString.substring(pos, regExp->matchedLength());
- }
- }
- }
- }
- }
- // Any reason in practice to search all cells in that are above cell?
- return String();
-}
-
-String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element* element)
-{
- OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
- // We stop searching after we've seen this many chars
- const unsigned int charsSearchedThreshold = 500;
- // This is the absolute max we search. We allow a little more slop than
- // charsSearchedThreshold, to make it more likely that we'll search whole nodes.
- const unsigned int maxCharsSearched = 600;
- // If the starting element is within a table, the cell that contains it
- HTMLTableCellElement* startingTableCell = 0;
- bool searchedCellAbove = false;
-
- // walk backwards in the node tree, until another element, or form, or end of tree
- int unsigned lengthSearched = 0;
- Node* n;
- for (n = element->traversePreviousNode();
- n && lengthSearched < charsSearchedThreshold;
- n = n->traversePreviousNode())
- {
- if (n->hasTagName(formTag)
- || (n->isHTMLElement()
- && static_cast<HTMLElement*>(n)->isGenericFormElement()))
- {
- // We hit another form element or the start of the form - bail out
- break;
- } else if (n->hasTagName(tdTag) && !startingTableCell) {
- startingTableCell = static_cast<HTMLTableCellElement*>(n);
- } else if (n->hasTagName(trTag) && startingTableCell) {
- String result = searchForLabelsAboveCell(regExp.get(), startingTableCell);
- if (!result.isEmpty())
- return result;
- searchedCellAbove = true;
- } else if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) {
- // For each text chunk, run the regexp
- String nodeString = n->nodeValue();
- // add 100 for slop, to make it more likely that we'll search whole nodes
- if (lengthSearched + nodeString.length() > maxCharsSearched)
- nodeString = nodeString.right(charsSearchedThreshold - lengthSearched);
- int pos = regExp->searchRev(nodeString);
- if (pos >= 0)
- return nodeString.substring(pos, regExp->matchedLength());
- lengthSearched += nodeString.length();
- }
- }
-
- // If we started in a cell, but bailed because we found the start of the form or the
- // previous element, we still might need to search the row above us for a label.
- if (startingTableCell && !searchedCellAbove) {
- return searchForLabelsAboveCell(regExp.get(), startingTableCell);
- }
- return String();
-}
-
-String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* element)
-{
- String name = element->getAttribute(nameAttr);
- if (name.isEmpty())
- return String();
-
- // Make numbers and _'s in field names behave like word boundaries, e.g., "address2"
- replace(name, RegularExpression("\\d"), " ");
- name.replace('_', ' ');
-
- OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels));
- // Use the largest match we can find in the whole name string
- int pos;
- int length;
- int bestPos = -1;
- int bestLength = -1;
- int start = 0;
- do {
- pos = regExp->search(name, start);
- if (pos != -1) {
- length = regExp->matchedLength();
- if (length >= bestLength) {
- bestPos = pos;
- bestLength = length;
- }
- start = pos + 1;
- }
- } while (pos != -1);
-
- if (bestPos != -1)
- return name.substring(bestPos, bestLength);
- return String();
-}
-
-const Selection& Frame::mark() const
-{
- return d->m_mark;
-}
-
-void Frame::setMark(const Selection& s)
-{
- ASSERT(!s.base().node() || s.base().node()->document() == document());
- ASSERT(!s.extent().node() || s.extent().node()->document() == document());
- ASSERT(!s.start().node() || s.start().node()->document() == document());
- ASSERT(!s.end().node() || s.end().node()->document() == document());
-
- d->m_mark = s;
-}
-
-void Frame::notifyRendererOfSelectionChange(bool userTriggered)
-{
- RenderObject* renderer = 0;
- if (selection()->rootEditableElement())
- renderer = selection()->rootEditableElement()->shadowAncestorNode()->renderer();
-
- // If the current selection is in a textfield or textarea, notify the renderer that the selection has changed
- if (renderer && (renderer->isTextArea() || renderer->isTextField()))
- static_cast<RenderTextControl*>(renderer)->selectionChanged(userTriggered);
-}
-
-void Frame::invalidateSelection()
-{
- selection()->setNeedsLayout();
- selectionLayoutChanged();
-}
-
-void Frame::setCaretVisible(bool flag)
-{
- if (d->m_caretVisible == flag)
- return;
- clearCaretRectIfNeeded();
- d->m_caretVisible = flag;
- selectionLayoutChanged();
-}
-
-void Frame::clearCaretRectIfNeeded()
-{
- if (d->m_caretPaint) {
- d->m_caretPaint = false;
- selection()->invalidateCaretRect();
- }
-}
-
-// Helper function that tells whether a particular node is an element that has an entire
-// Frame and FrameView, a <frame>, <iframe>, or <object>.
-static bool isFrameElement(const Node *n)
-{
- if (!n)
- return false;
- RenderObject *renderer = n->renderer();
- if (!renderer || !renderer->isWidget())
- return false;
- Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
- return widget && widget->isFrameView();
-}
-
-void Frame::setFocusedNodeIfNeeded()
-{
- if (!document() || selection()->isNone() || !selection()->isFocusedAndActive())
- return;
-
- Node* target = selection()->rootEditableElement();
- if (target) {
- RenderObject* renderer = target->renderer();
-
- // Walk up the render tree to search for a node to focus.
- // Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
- while (renderer) {
- // We don't want to set focus on a subframe when selecting in a parent frame,
- // so add the !isFrameElement check here. There's probably a better way to make this
- // work in the long term, but this is the safest fix at this time.
- if (target && target->isMouseFocusable() && !isFrameElement(target)) {
- page()->focusController()->setFocusedNode(target, this);
- return;
- }
- renderer = renderer->parent();
- if (renderer)
- target = renderer->element();
- }
- document()->setFocusedNode(0);
- }
-}
-
-void Frame::selectionLayoutChanged()
-{
- bool caretRectChanged = selection()->recomputeCaretRect();
-
- bool shouldBlink = d->m_caretVisible
- && selection()->isCaret() && selection()->isContentEditable();
-
- // If the caret moved, stop the blink timer so we can restart with a
- // black caret in the new location.
- if (caretRectChanged || !shouldBlink)
- d->m_caretBlinkTimer.stop();
-
- // Start blinking with a black caret. Be sure not to restart if we're
- // already blinking in the right location.
- if (shouldBlink && !d->m_caretBlinkTimer.isActive()) {
- d->m_caretBlinkTimer.startRepeating(theme()->caretBlinkFrequency());
- if (!d->m_caretPaint) {
- d->m_caretPaint = true;
- selection()->invalidateCaretRect();
- }
- }
-
- RenderView* canvas = contentRenderer();
- if (!canvas)
- return;
-
- Selection selection = this->selection()->selection();
-
- if (!selection.isRange())
- canvas->clearSelection();
- else {
- // Use the rightmost candidate for the start of the selection, and the leftmost candidate for the end of the selection.
- // Example: foo <a>bar</a>. Imagine that a line wrap occurs after 'foo', and that 'bar' is selected. If we pass [foo, 3]
- // as the start of the selection, the selection painting code will think that content on the line containing 'foo' is selected
- // and will fill the gap before 'bar'.
- Position startPos = selection.start();
- if (startPos.downstream().isCandidate())
- startPos = startPos.downstream();
- Position endPos = selection.end();
- if (endPos.upstream().isCandidate())
- endPos = endPos.upstream();
-
- // We can get into a state where the selection endpoints map to the same VisiblePosition when a selection is deleted
- // because we don't yet notify the SelectionController of text removal.
- if (startPos.isNotNull() && endPos.isNotNull() && selection.visibleStart() != selection.visibleEnd()) {
- RenderObject *startRenderer = startPos.node()->renderer();
- RenderObject *endRenderer = endPos.node()->renderer();
- canvas->setSelection(startRenderer, startPos.offset(), endRenderer, endPos.offset());
- }
- }
-}
-
-void Frame::caretBlinkTimerFired(Timer<Frame>*)
-{
- ASSERT(d->m_caretVisible);
- ASSERT(selection()->isCaret());
- bool caretPaint = d->m_caretPaint;
- if (selection()->isCaretBlinkingSuspended() && caretPaint)
- return;
- d->m_caretPaint = !caretPaint;
- selection()->invalidateCaretRect();
-}
-
-void Frame::paintCaret(GraphicsContext* p, const IntRect& rect) const
-{
- if (d->m_caretPaint && d->m_caretVisible)
- selection()->paintCaret(p, rect);
-}
-
-void Frame::paintDragCaret(GraphicsContext* p, const IntRect& rect) const
-{
- SelectionController* dragCaretController = d->m_page->dragCaretController();
- ASSERT(dragCaretController->selection().isCaret());
- if (dragCaretController->selection().start().node()->document()->frame() == this)
- dragCaretController->paintCaret(p, rect);
-}
-
-float Frame::zoomFactor() const
-{
- return d->m_zoomFactor;
-}
-
-bool Frame::isZoomFactorTextOnly() const
-{
- return d->m_page->settings()->zoomsTextOnly();
-}
-
-bool Frame::shouldApplyTextZoom() const
-{
- if (d->m_zoomFactor == 1.0f || !isZoomFactorTextOnly())
- return false;
-#if ENABLE(SVG)
- if (d->m_doc && d->m_doc->isSVGDocument())
- return false;
-#endif
- return true;
-}
-
-bool Frame::shouldApplyPageZoom() const
-{
- if (d->m_zoomFactor == 1.0f || isZoomFactorTextOnly())
- return false;
-#if ENABLE(SVG)
- if (d->m_doc && d->m_doc->isSVGDocument())
- return false;
-#endif
- return true;
-}
-
-void Frame::setZoomFactor(float percent, bool isTextOnly)
-{
- if (d->m_zoomFactor == percent && isZoomFactorTextOnly())
- return;
-
-#if ENABLE(SVG)
- // SVG doesn't care if the zoom factor is text only. It will always apply a
- // zoom to the whole SVG.
- if (d->m_doc && d->m_doc->isSVGDocument()) {
- if (!static_cast<SVGDocument*>(d->m_doc.get())->zoomAndPanEnabled())
- return;
- d->m_zoomFactor = percent;
- d->m_page->settings()->setZoomsTextOnly(true); // We do this to avoid doing any scaling of CSS pixels, since the SVG has its own notion of zoom.
- if (d->m_doc->renderer())
- d->m_doc->renderer()->repaint();
- return;
- }
-#endif
-
- d->m_zoomFactor = percent;
- d->m_page->settings()->setZoomsTextOnly(isTextOnly);
-
- if (d->m_doc)
- d->m_doc->recalcStyle(Node::Force);
-
- for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
- child->setZoomFactor(d->m_zoomFactor, isTextOnly);
-
- if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->needsLayout() && view()->didFirstLayout())
- view()->layout();
-}
-
-void Frame::setPrinting(bool printing, float minPageWidth, float maxPageWidth, bool adjustViewSize)
-{
- if (!d->m_doc)
- return;
-
- d->m_doc->setPrinting(printing);
- view()->setMediaType(printing ? "print" : "screen");
- d->m_doc->updateStyleSelector();
- forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth, adjustViewSize);
-
- for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
- child->setPrinting(printing, minPageWidth, maxPageWidth, adjustViewSize);
-}
-
-void Frame::setJSStatusBarText(const String& text)
-{
- d->m_kjsStatusBarText = text;
- if (d->m_page)
- d->m_page->chrome()->setStatusbarText(this, d->m_kjsStatusBarText);
-}
-
-void Frame::setJSDefaultStatusBarText(const String& text)
-{
- d->m_kjsDefaultStatusBarText = text;
- if (d->m_page)
- d->m_page->chrome()->setStatusbarText(this, d->m_kjsDefaultStatusBarText);
-}
-
-String Frame::jsStatusBarText() const
-{
- return d->m_kjsStatusBarText;
-}
-
-String Frame::jsDefaultStatusBarText() const
-{
- return d->m_kjsDefaultStatusBarText;
-}
-
-void Frame::setNeedsReapplyStyles()
-{
- if (d->m_needsReapplyStyles)
- return;
-
- d->m_needsReapplyStyles = true;
-
- // Invalidate the FrameView so that FrameView::layout will get called,
- // which calls reapplyStyles.
- FrameView* curView = view();
- if (curView)
- curView->invalidate();
-}
-
-bool Frame::needsReapplyStyles() const
-{
- return d->m_needsReapplyStyles;
-}
-
-void Frame::reapplyStyles()
-{
- d->m_needsReapplyStyles = false;
-
- // FIXME: This call doesn't really make sense in a method called
- // "reapplyStyles". We should probably eventually move it into its own
- // method.
- if (d->m_doc)
- d->m_doc->docLoader()->setAutoLoadImages(d->m_page && d->m_page->settings()->loadsImagesAutomatically());
-
-#if FRAME_LOADS_USER_STYLESHEET
- const KURL userStyleSheetLocation = d->m_page ? d->m_page->settings()->userStyleSheetLocation() : KURL();
- if (!userStyleSheetLocation.isEmpty())
- setUserStyleSheetLocation(userStyleSheetLocation);
- else
- setUserStyleSheet(String());
-#endif
-
- // FIXME: It's not entirely clear why the following is needed.
- // The document automatically does this as required when you set the style sheet.
- // But we had problems when this code was removed. Details are in
- // <http://bugs.webkit.org/show_bug.cgi?id=8079>.
- if (d->m_doc)
- d->m_doc->updateStyleSelector();
-}
-
-bool Frame::shouldChangeSelection(const Selection& newSelection) const
-{
- return shouldChangeSelection(selection()->selection(), newSelection, newSelection.affinity(), false);
-}
-
-bool Frame::shouldChangeSelection(const Selection& oldSelection, const Selection& newSelection, EAffinity affinity, bool stillSelecting) const
-{
- return editor()->client()->shouldChangeSelectedRange(oldSelection.toRange().get(), newSelection.toRange().get(),
- affinity, stillSelecting);
-}
-
-bool Frame::shouldDeleteSelection(const Selection& selection) const
-{
- return editor()->client()->shouldDeleteRange(selection.toRange().get());
-}
-
-bool Frame::isContentEditable() const
-{
- if (d->m_editor.clientIsEditable())
- return true;
- if (!d->m_doc)
- return false;
- return d->m_doc->inDesignMode();
-}
-
-#if !PLATFORM(MAC)
-
-void Frame::setUseSecureKeyboardEntry(bool)
-{
-}
-
-#endif
-
-void Frame::updateSecureKeyboardEntryIfActive()
-{
- if (selection()->isFocusedAndActive())
- setUseSecureKeyboardEntry(d->m_doc->useSecureKeyboardEntryWhenActive());
-}
-
-CSSMutableStyleDeclaration *Frame::typingStyle() const
-{
- return d->m_typingStyle.get();
-}
-
-void Frame::setTypingStyle(CSSMutableStyleDeclaration *style)
-{
- d->m_typingStyle = style;
-}
-
-void Frame::clearTypingStyle()
-{
- d->m_typingStyle = 0;
-}
-
-void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction editingAction)
-{
- if (!style || style->length() == 0) {
- clearTypingStyle();
- return;
- }
-
- // Calculate the current typing style.
- RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
- if (typingStyle()) {
- typingStyle()->merge(mutableStyle.get());
- mutableStyle = typingStyle();
- }
-
- Node* node = selection()->selection().visibleStart().deepEquivalent().node();
- computedStyle(node)->diff(mutableStyle.get());
-
- // Handle block styles, substracting these from the typing style.
- RefPtr<CSSMutableStyleDeclaration> blockStyle = mutableStyle->copyBlockProperties();
- blockStyle->diff(mutableStyle.get());
- if (document() && blockStyle->length() > 0)
- applyCommand(ApplyStyleCommand::create(document(), blockStyle.get(), editingAction));
-
- // Set the remaining style as the typing style.
- d->m_typingStyle = mutableStyle.release();
-}
-
-String Frame::selectionStartStylePropertyValue(int stylePropertyID) const
-{
- Node *nodeToRemove;
- RefPtr<CSSStyleDeclaration> selectionStyle = selectionComputedStyle(nodeToRemove);
- if (!selectionStyle)
- return String();
-
- String value = selectionStyle->getPropertyValue(stylePropertyID);
-
- if (nodeToRemove) {
- ExceptionCode ec = 0;
- nodeToRemove->remove(ec);
- ASSERT(ec == 0);
- }
-
- return value;
-}
-
-PassRefPtr<CSSComputedStyleDeclaration> Frame::selectionComputedStyle(Node*& nodeToRemove) const
-{
- nodeToRemove = 0;
-
- if (!document())
- return 0;
-
- if (selection()->isNone())
- return 0;
-
- RefPtr<Range> range(selection()->toRange());
- Position pos = range->editingStartPosition();
-
- Element *elem = pos.element();
- if (!elem)
- return 0;
-
- RefPtr<Element> styleElement = elem;
- ExceptionCode ec = 0;
-
- if (d->m_typingStyle) {
- styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
- ASSERT(ec == 0);
-
- styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec);
- ASSERT(ec == 0);
-
- styleElement->appendChild(document()->createEditingTextNode(""), ec);
- ASSERT(ec == 0);
-
- if (elem->renderer() && elem->renderer()->canHaveChildren()) {
- elem->appendChild(styleElement, ec);
- } else {
- Node *parent = elem->parent();
- Node *next = elem->nextSibling();
-
- if (next) {
- parent->insertBefore(styleElement, next, ec);
- } else {
- parent->appendChild(styleElement, ec);
- }
- }
- ASSERT(ec == 0);
-
- nodeToRemove = styleElement.get();
- }
-
- return computedStyle(styleElement.release());
-}
-
-void Frame::textFieldDidBeginEditing(Element* e)
-{
- if (editor()->client())
- editor()->client()->textFieldDidBeginEditing(e);
-}
-
-void Frame::textFieldDidEndEditing(Element* e)
-{
- if (editor()->client())
- editor()->client()->textFieldDidEndEditing(e);
-}
-
-void Frame::textDidChangeInTextField(Element* e)
-{
- if (editor()->client())
- editor()->client()->textDidChangeInTextField(e);
-}
-
-bool Frame::doTextFieldCommandFromEvent(Element* e, KeyboardEvent* ke)
-{
- if (editor()->client())
- return editor()->client()->doTextFieldCommandFromEvent(e, ke);
-
- return false;
-}
-
-void Frame::textWillBeDeletedInTextField(Element* input)
-{
- if (editor()->client())
- editor()->client()->textWillBeDeletedInTextField(input);
-}
-
-void Frame::textDidChangeInTextArea(Element* e)
-{
- if (editor()->client())
- editor()->client()->textDidChangeInTextArea(e);
-}
-
-void Frame::applyEditingStyleToBodyElement() const
-{
- if (!d->m_doc)
- return;
-
- RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
- unsigned len = list->length();
- for (unsigned i = 0; i < len; i++) {
- applyEditingStyleToElement(static_cast<Element*>(list->item(i)));
- }
-}
-
-void Frame::removeEditingStyleFromBodyElement() const
-{
- if (!d->m_doc)
- return;
-
- RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body");
- unsigned len = list->length();
- for (unsigned i = 0; i < len; i++) {
- removeEditingStyleFromElement(static_cast<Element*>(list->item(i)));
- }
-}
-
-void Frame::applyEditingStyleToElement(Element* element) const
-{
- if (!element)
- return;
-
- CSSStyleDeclaration* style = element->style();
- ASSERT(style);
-
- ExceptionCode ec = 0;
- style->setProperty(CSSPropertyWordWrap, "break-word", false, ec);
- ASSERT(ec == 0);
- style->setProperty(CSSPropertyWebkitNbspMode, "space", false, ec);
- ASSERT(ec == 0);
- style->setProperty(CSSPropertyWebkitLineBreak, "after-white-space", false, ec);
- ASSERT(ec == 0);
-}
-
-void Frame::removeEditingStyleFromElement(Element*) const
-{
-}
-
-#ifndef NDEBUG
-static HashSet<Frame*>& keepAliveSet()
-{
- static HashSet<Frame*> staticKeepAliveSet;
- return staticKeepAliveSet;
-}
-#endif
-
-void Frame::keepAlive()
-{
- if (d->m_lifeSupportTimer.isActive())
- return;
-#ifndef NDEBUG
- keepAliveSet().add(this);
-#endif
- ref();
- d->m_lifeSupportTimer.startOneShot(0);
-}
-
-#ifndef NDEBUG
-void Frame::cancelAllKeepAlive()
-{
- HashSet<Frame*>::iterator end = keepAliveSet().end();
- for (HashSet<Frame*>::iterator it = keepAliveSet().begin(); it != end; ++it) {
- Frame* frame = *it;
- frame->d->m_lifeSupportTimer.stop();
- frame->deref();
- }
- keepAliveSet().clear();
-}
-#endif
-
-void Frame::lifeSupportTimerFired(Timer<Frame>*)
-{
-#ifndef NDEBUG
- keepAliveSet().remove(this);
-#endif
- deref();
-}
-
-void Frame::clearDOMWindow()
-{
- if (d->m_domWindow) {
- d->m_liveFormerWindows.add(d->m_domWindow.get());
- d->m_domWindow->clear();
- }
- d->m_script.clearPluginObjects();
-}
-
-RenderView* Frame::contentRenderer() const
-{
- Document* doc = document();
- if (!doc)
- return 0;
- RenderObject* object = doc->renderer();
- if (!object)
- return 0;
- ASSERT(object->isRenderView());
- return static_cast<RenderView*>(object);
-}
-
-HTMLFrameOwnerElement* Frame::ownerElement() const
-{
- return d->m_ownerElement;
-}
-
-RenderPart* Frame::ownerRenderer() const
-{
- HTMLFrameOwnerElement* ownerElement = d->m_ownerElement;
- if (!ownerElement)
- return 0;
- RenderObject* object = ownerElement->renderer();
- if (!object)
- return 0;
- // FIXME: If <object> is ever fixed to disassociate itself from frames
- // that it has started but canceled, then this can turn into an ASSERT
- // since d->m_ownerElement would be 0 when the load is canceled.
- // https://bugs.webkit.org/show_bug.cgi?id=18585
- if (!object->isRenderPart())
- return 0;
- return static_cast<RenderPart*>(object);
-}
-
-bool Frame::isDisconnected() const
-{
- return d->m_isDisconnected;
-}
-
-void Frame::setIsDisconnected(bool isDisconnected)
-{
- d->m_isDisconnected = isDisconnected;
-}
-
-bool Frame::excludeFromTextSearch() const
-{
- return d->m_excludeFromTextSearch;
-}
-
-void Frame::setExcludeFromTextSearch(bool exclude)
-{
- d->m_excludeFromTextSearch = exclude;
-}
-
-// returns FloatRect because going through IntRect would truncate any floats
-FloatRect Frame::selectionRect(bool clipToVisibleContent) const
-{
- RenderView* root = contentRenderer();
- if (!root)
- return IntRect();
-
- IntRect selectionRect = root->selectionRect(clipToVisibleContent);
- return clipToVisibleContent ? intersection(selectionRect, d->m_view->visibleContentRect()) : selectionRect;
-}
-
-void Frame::selectionTextRects(Vector<FloatRect>& rects, bool clipToVisibleContent) const
-{
- RenderView* root = contentRenderer();
- if (!root)
- return;
-
- RefPtr<Range> selectedRange = selection()->toRange();
-
- Vector<IntRect> intRects;
- selectedRange->addLineBoxRects(intRects, true);
-
- unsigned size = intRects.size();
- FloatRect visibleContentRect = d->m_view->visibleContentRect();
- for (unsigned i = 0; i < size; ++i)
- if (clipToVisibleContent)
- rects.append(intersection(intRects[i], visibleContentRect));
- else
- rects.append(intRects[i]);
-}
-
-
-bool Frame::isFrameSet() const
-{
- Document* document = d->m_doc.get();
- if (!document || !document->isHTMLDocument())
- return false;
- Node *body = static_cast<HTMLDocument*>(document)->body();
- return body && body->renderer() && body->hasTagName(framesetTag);
-}
-
-// Scans logically forward from "start", including any child frames
-static HTMLFormElement *scanForForm(Node *start)
-{
- Node *n;
- for (n = start; n; n = n->traverseNextNode()) {
- if (n->hasTagName(formTag))
- return static_cast<HTMLFormElement*>(n);
- else if (n->isHTMLElement() && static_cast<HTMLElement*>(n)->isGenericFormElement())
- return static_cast<HTMLFormControlElement*>(n)->form();
- else if (n->hasTagName(frameTag) || n->hasTagName(iframeTag)) {
- Node *childDoc = static_cast<HTMLFrameElementBase*>(n)->contentDocument();
- if (HTMLFormElement *frameResult = scanForForm(childDoc))
- return frameResult;
- }
- }
- return 0;
-}
-
-// We look for either the form containing the current focus, or for one immediately after it
-HTMLFormElement *Frame::currentForm() const
-{
- // start looking either at the active (first responder) node, or where the selection is
- Node *start = d->m_doc ? d->m_doc->focusedNode() : 0;
- if (!start)
- start = selection()->start().node();
-
- // try walking up the node tree to find a form element
- Node *n;
- for (n = start; n; n = n->parentNode()) {
- if (n->hasTagName(formTag))
- return static_cast<HTMLFormElement*>(n);
- else if (n->isHTMLElement()
- && static_cast<HTMLElement*>(n)->isGenericFormElement())
- return static_cast<HTMLFormControlElement*>(n)->form();
- }
-
- // try walking forward in the node tree to find a form element
- return start ? scanForForm(start) : 0;
-}
-
-// FIXME: should this go in SelectionController?
-void Frame::revealSelection(const RenderLayer::ScrollAlignment& alignment) const
-{
- IntRect rect;
-
- switch (selection()->state()) {
- case Selection::NONE:
- return;
-
- case Selection::CARET:
- rect = selection()->caretRect();
- break;
-
- case Selection::RANGE:
- rect = enclosingIntRect(selectionRect(false));
- break;
- }
-
- Position start = selection()->start();
-
- ASSERT(start.node());
- if (start.node() && start.node()->renderer()) {
- // FIXME: This code only handles scrolling the startContainer's layer, but
- // the selection rect could intersect more than just that.
- // See <rdar://problem/4799899>.
- if (RenderLayer *layer = start.node()->renderer()->enclosingLayer())
- layer->scrollRectToVisible(rect, false, alignment, alignment);
- }
-}
-
-void Frame::revealCaret(const RenderLayer::ScrollAlignment& alignment) const
-{
- if (selection()->isNone())
- return;
-
- Position extent = selection()->extent();
- if (extent.node() && extent.node()->renderer()) {
- IntRect extentRect = VisiblePosition(extent).caretRect();
- RenderLayer* layer = extent.node()->renderer()->enclosingLayer();
- if (layer)
- layer->scrollRectToVisible(extentRect, false, alignment, alignment);
- }
-}
-
-// FIXME: why is this here instead of on the FrameView?
-void Frame::paint(GraphicsContext* p, const IntRect& rect)
-{
-#ifndef NDEBUG
- bool fillWithRed;
- if (!document() || document()->printing())
- fillWithRed = false; // Printing, don't fill with red (can't remember why).
- else if (document()->ownerElement())
- fillWithRed = false; // Subframe, don't fill with red.
- else if (view() && view()->isTransparent())
- fillWithRed = false; // Transparent, don't fill with red.
- else if (d->m_paintRestriction == PaintRestrictionSelectionOnly || d->m_paintRestriction == PaintRestrictionSelectionOnlyBlackText)
- fillWithRed = false; // Selections are transparent, don't fill with red.
- else if (d->m_elementToDraw)
- fillWithRed = false; // Element images are transparent, don't fill with red.
- else
- fillWithRed = true;
-
- if (fillWithRed)
- p->fillRect(rect, Color(0xFF, 0, 0));
-#endif
-
- bool isTopLevelPainter = !s_currentPaintTimeStamp;
- if (isTopLevelPainter)
- s_currentPaintTimeStamp = currentTime();
-
- if (contentRenderer()) {
- ASSERT(d->m_view && !d->m_view->needsLayout());
- ASSERT(!d->m_isPainting);
-
- d->m_isPainting = true;
-
- // d->m_elementToDraw is used to draw only one element
- RenderObject* eltRenderer = d->m_elementToDraw ? d->m_elementToDraw->renderer() : 0;
- if (d->m_paintRestriction == PaintRestrictionNone)
- document()->invalidateRenderedRectsForMarkersInRect(rect);
- contentRenderer()->layer()->paint(p, rect, d->m_paintRestriction, eltRenderer);
-
- d->m_isPainting = false;
-
-#if ENABLE(DASHBOARD_SUPPORT)
- // Regions may have changed as a result of the visibility/z-index of element changing.
- if (document()->dashboardRegionsDirty())
- view()->updateDashboardRegions();
-#endif
- } else
- LOG_ERROR("called Frame::paint with nil renderer");
-
- if (isTopLevelPainter)
- s_currentPaintTimeStamp = 0;
-}
-
-void Frame::setPaintRestriction(PaintRestriction pr)
-{
- d->m_paintRestriction = pr;
-}
-
-bool Frame::isPainting() const
-{
- return d->m_isPainting;
-}
-
-void Frame::adjustPageHeight(float *newBottom, float oldTop, float oldBottom, float bottomLimit)
-{
- RenderView* root = contentRenderer();
- if (root) {
- // Use a context with painting disabled.
- GraphicsContext context((PlatformGraphicsContext*)0);
- root->setTruncatedAt((int)floorf(oldBottom));
- IntRect dirtyRect(0, (int)floorf(oldTop), root->docWidth(), (int)ceilf(oldBottom - oldTop));
- root->layer()->paint(&context, dirtyRect);
- *newBottom = root->bestTruncatedAt();
- if (*newBottom == 0)
- *newBottom = oldBottom;
- } else
- *newBottom = oldBottom;
-}
-
-Frame* Frame::frameForWidget(const Widget* widget)
-{
- ASSERT_ARG(widget, widget);
-
- if (RenderWidget* renderer = RenderWidget::find(widget))
- if (Node* node = renderer->node())
- return node->document()->frame();
-
- // Assume all widgets are either a FrameView or owned by a RenderWidget.
- // FIXME: That assumption is not right for scroll bars!
- ASSERT(widget->isFrameView());
- return static_cast<const FrameView*>(widget)->frame();
-}
-
-void Frame::forceLayout(bool allowSubtree)
-{
- FrameView *v = d->m_view.get();
- if (v) {
- v->layout(allowSubtree);
- // We cannot unschedule a pending relayout, since the force can be called with
- // a tiny rectangle from a drawRect update. By unscheduling we in effect
- // "validate" and stop the necessary full repaint from occurring. Basically any basic
- // append/remove DHTML is broken by this call. For now, I have removed the optimization
- // until we have a better invalidation stategy. -dwh
- //v->unscheduleRelayout();
- }
-}
-
-void Frame::forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth, bool adjustViewSize)
-{
- // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
- // the state of things before and after the layout
- RenderView *root = static_cast<RenderView*>(document()->renderer());
- if (root) {
- // This magic is basically copied from khtmlview::print
- int pageW = (int)ceilf(minPageWidth);
- root->setWidth(pageW);
- root->setNeedsLayoutAndPrefWidthsRecalc();
- forceLayout();
-
- // If we don't fit in the minimum page width, we'll lay out again. If we don't fit in the
- // maximum page width, we will lay out to the maximum page width and clip extra content.
- // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
- // implementation should not do this!
- int rightmostPos = root->rightmostPosition();
- if (rightmostPos > minPageWidth) {
- pageW = min(rightmostPos, (int)ceilf(maxPageWidth));
- root->setWidth(pageW);
- root->setNeedsLayoutAndPrefWidthsRecalc();
- forceLayout();
- }
- }
-
- if (adjustViewSize && view())
- view()->adjustViewSize();
-}
-
-void Frame::sendResizeEvent()
-{
- if (Document* doc = document())
- doc->dispatchWindowEvent(EventNames::resizeEvent, false, false);
-}
-
-void Frame::sendScrollEvent()
-{
- FrameView* v = d->m_view.get();
- if (!v)
- return;
- v->setWasScrolledByUser(true);
- Document* doc = document();
- if (!doc)
- return;
- doc->dispatchHTMLEvent(scrollEvent, true, false);
-}
-
-void Frame::clearTimers(FrameView *view, Document *document)
-{
- if (view) {
- view->unscheduleRelayout();
- if (view->frame()) {
- if (document && document->renderer() && document->renderer()->hasLayer())
- document->renderer()->layer()->suspendMarquees();
- view->frame()->animation()->suspendAnimations(document);
- view->frame()->eventHandler()->stopAutoscrollTimer();
- }
- }
-}
-
-void Frame::clearTimers()
-{
- clearTimers(d->m_view.get(), document());
-}
-
-RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const
-{
- nodeToRemove = 0;
-
- if (!document())
- return 0;
- if (selection()->isNone())
- return 0;
-
- Position pos = selection()->selection().visibleStart().deepEquivalent();
- if (!pos.isCandidate())
- return 0;
- Node *node = pos.node();
- if (!node)
- return 0;
-
- if (!d->m_typingStyle)
- return node->renderer()->style();
-
- ExceptionCode ec = 0;
- RefPtr<Element> styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
- ASSERT(ec == 0);
-
- String styleText = d->m_typingStyle->cssText() + " display: inline";
- styleElement->setAttribute(styleAttr, styleText.impl(), ec);
- ASSERT(ec == 0);
-
- styleElement->appendChild(document()->createEditingTextNode(""), ec);
- ASSERT(ec == 0);
-
- node->parentNode()->appendChild(styleElement, ec);
- ASSERT(ec == 0);
-
- nodeToRemove = styleElement.get();
- return styleElement->renderer() ? styleElement->renderer()->style() : 0;
-}
-
-void Frame::setSelectionFromNone()
-{
- // Put a caret inside the body if the entire frame is editable (either the
- // entire WebView is editable or designMode is on for this document).
- Document *doc = document();
- if (!doc || !selection()->isNone() || !isContentEditable())
- return;
-
- Node* node = doc->documentElement();
- while (node && !node->hasTagName(bodyTag))
- node = node->traverseNextNode();
- if (node)
- selection()->setSelection(Selection(Position(node, 0), DOWNSTREAM));
-}
-
-bool Frame::inViewSourceMode() const
-{
- return d->m_inViewSourceMode;
-}
-
-void Frame::setInViewSourceMode(bool mode) const
-{
- d->m_inViewSourceMode = mode;
-}
-
-UChar Frame::backslashAsCurrencySymbol() const
-{
- Document *doc = document();
- if (!doc)
- return '\\';
- TextResourceDecoder *decoder = doc->decoder();
- if (!decoder)
- return '\\';
-
- return decoder->encoding().backslashAsCurrencySymbol();
-}
-
-// Searches from the beginning of the document if nothing is selected.
-bool Frame::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection)
-{
- if (target.isEmpty() || !document())
- return false;
-
- if (excludeFromTextSearch())
- return false;
-
- // Start from an edge of the selection, if there's a selection that's not in shadow content. Which edge
- // is used depends on whether we're searching forward or backward, and whether startInSelection is set.
- RefPtr<Range> searchRange(rangeOfContents(document()));
- Selection selection = this->selection()->selection();
-
- if (forward)
- setStart(searchRange.get(), startInSelection ? selection.visibleStart() : selection.visibleEnd());
- else
- setEnd(searchRange.get(), startInSelection ? selection.visibleEnd() : selection.visibleStart());
-
- Node* shadowTreeRoot = selection.shadowTreeRootNode();
- if (shadowTreeRoot) {
- ExceptionCode ec = 0;
- if (forward)
- searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec);
- else
- searchRange->setStart(shadowTreeRoot, 0, ec);
- }
-
- RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, forward, caseFlag));
- // If we started in the selection and the found range exactly matches the existing selection, find again.
- // Build a selection with the found range to remove collapsed whitespace.
- // Compare ranges instead of selection objects to ignore the way that the current selection was made.
- if (startInSelection && *Selection(resultRange.get()).toRange() == *selection.toRange()) {
- searchRange = rangeOfContents(document());
- if (forward)
- setStart(searchRange.get(), selection.visibleEnd());
- else
- setEnd(searchRange.get(), selection.visibleStart());
-
- if (shadowTreeRoot) {
- ExceptionCode ec = 0;
- if (forward)
- searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec);
- else
- searchRange->setStart(shadowTreeRoot, 0, ec);
- }
-
- resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
- }
-
- ExceptionCode exception = 0;
-
- // If nothing was found in the shadow tree, search in main content following the shadow tree.
- if (resultRange->collapsed(exception) && shadowTreeRoot) {
- searchRange = rangeOfContents(document());
- if (forward)
- searchRange->setStartAfter(shadowTreeRoot->shadowParentNode(), exception);
- else
- searchRange->setEndBefore(shadowTreeRoot->shadowParentNode(), exception);
-
- resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
- }
-
- if (!editor()->insideVisibleArea(resultRange.get())) {
- resultRange = editor()->nextVisibleRange(resultRange.get(), target, forward, caseFlag, wrapFlag);
- if (!resultRange)
- return false;
- }
-
- // If we didn't find anything and we're wrapping, search again in the entire document (this will
- // redundantly re-search the area already searched in some cases).
- if (resultRange->collapsed(exception) && wrapFlag) {
- searchRange = rangeOfContents(document());
- resultRange = findPlainText(searchRange.get(), target, forward, caseFlag);
- // We used to return false here if we ended up with the same range that we started with
- // (e.g., the selection was already the only instance of this text). But we decided that
- // this should be a success case instead, so we'll just fall through in that case.
- }
-
- if (resultRange->collapsed(exception))
- return false;
-
- this->selection()->setSelection(Selection(resultRange.get(), DOWNSTREAM));
- revealSelection();
- return true;
-}
-
-unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsigned limit)
-{
- if (target.isEmpty() || !document())
- return 0;
-
- RefPtr<Range> searchRange(rangeOfContents(document()));
-
- ExceptionCode exception = 0;
- unsigned matchCount = 0;
- do {
- RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, caseFlag));
- if (resultRange->collapsed(exception)) {
- if (!resultRange->startContainer()->isInShadowTree())
- break;
-
- searchRange = rangeOfContents(document());
- searchRange->setStartAfter(resultRange->startContainer()->shadowAncestorNode(), exception);
- continue;
- }
-
- // A non-collapsed result range can in some funky whitespace cases still not
- // advance the range's start position (4509328). Break to avoid infinite loop.
- VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM);
- if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM))
- break;
-
- // Only treat the result as a match if it is visible
- if (editor()->insideVisibleArea(resultRange.get())) {
- ++matchCount;
- document()->addMarker(resultRange.get(), DocumentMarker::TextMatch);
- }
-
- // Stop looking if we hit the specified limit. A limit of 0 means no limit.
- if (limit > 0 && matchCount >= limit)
- break;
-
- setStart(searchRange.get(), newStart);
- Node* shadowTreeRoot = searchRange->shadowTreeRootNode();
- if (searchRange->collapsed(exception) && shadowTreeRoot)
- searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), exception);
- } while (true);
-
- // Do a "fake" paint in order to execute the code that computes the rendered rect for
- // each text match.
- Document* doc = document();
- if (doc && d->m_view && contentRenderer()) {
- doc->updateLayout(); // Ensure layout is up to date.
- IntRect visibleRect(enclosingIntRect(d->m_view->visibleContentRect()));
- if (!visibleRect.isEmpty()) {
- GraphicsContext context((PlatformGraphicsContext*)0);
- context.setPaintingDisabled(true);
- paint(&context, visibleRect);
- }
- }
-
- return matchCount;
-}
-
-bool Frame::markedTextMatchesAreHighlighted() const
-{
- return d->m_highlightTextMatches;
-}
-
-void Frame::setMarkedTextMatchesAreHighlighted(bool flag)
-{
- if (flag == d->m_highlightTextMatches || !document())
- return;
-
- d->m_highlightTextMatches = flag;
- document()->repaintMarkers(DocumentMarker::TextMatch);
-}
-
-FrameTree* Frame::tree() const
-{
- return &d->m_treeNode;
-}
-
-DOMWindow* Frame::domWindow() const
-{
- if (!d->m_domWindow)
- d->m_domWindow = DOMWindow::create(const_cast<Frame*>(this));
-
- return d->m_domWindow.get();
-}
-
-void Frame::clearFormerDOMWindow(DOMWindow* window)
-{
- d->m_liveFormerWindows.remove(window);
-}
-
-Page* Frame::page() const
-{
- return d->m_page;
-}
-
-EventHandler* Frame::eventHandler() const
-{
- return &d->m_eventHandler;
-}
-
-void Frame::pageDestroyed()
-{
- if (Frame* parent = tree()->parent())
- parent->loader()->checkLoadComplete();
-
- // FIXME: It's unclear as to why this is called more than once, but it is,
- // so page() could be NULL.
- if (page() && page()->focusController()->focusedFrame() == this)
- page()->focusController()->setFocusedFrame(0);
-
- // This will stop any JS timers
- script()->disconnectFrame();
-
- script()->clearScriptObjects();
-
- d->m_page = 0;
-}
-
-void Frame::disconnectOwnerElement()
-{
- if (d->m_ownerElement) {
- if (Document* doc = document())
- doc->clearAXObjectCache();
- d->m_ownerElement->m_contentFrame = 0;
- if (d->m_page)
- d->m_page->decrementFrameCount();
- }
- d->m_ownerElement = 0;
-}
-
-String Frame::documentTypeString() const
-{
- if (Document* doc = document()) {
- if (DocumentType* doctype = doc->doctype())
- return createMarkup(doctype);
- }
-
- return String();
-}
-
-bool Frame::prohibitsScrolling() const
-{
- return d->m_prohibitsScrolling;
-}
-
-void Frame::setProhibitsScrolling(bool prohibit)
-{
- d->m_prohibitsScrolling = prohibit;
-}
-
-void Frame::focusWindow()
-{
- if (!page())
- return;
-
- // If we're a top level window, bring the window to the front.
- if (!tree()->parent())
- page()->chrome()->focus();
-
- eventHandler()->focusDocumentView();
-}
-
-void Frame::unfocusWindow()
-{
- if (!page())
- return;
-
- // If we're a top level window, deactivate the window.
- if (!tree()->parent())
- page()->chrome()->unfocus();
-}
-
-bool Frame::shouldClose()
-{
- Chrome* chrome = page() ? page()->chrome() : 0;
- if (!chrome || !chrome->canRunBeforeUnloadConfirmPanel())
- return true;
-
- RefPtr<Document> doc = document();
- if (!doc)
- return true;
- HTMLElement* body = doc->body();
- if (!body)
- return true;
-
- loader()->setFiringUnloadEvents(true);
-
- RefPtr<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create();
- beforeUnloadEvent->setTarget(doc);
- doc->handleWindowEvent(beforeUnloadEvent.get(), false);
-
- if (!beforeUnloadEvent->defaultPrevented() && doc)
- doc->defaultEventHandler(beforeUnloadEvent.get());
-
- loader()->setFiringUnloadEvents(false);
-
- if (beforeUnloadEvent->result().isNull())
- return true;
-
- String text = beforeUnloadEvent->result();
- text.replace('\\', backslashAsCurrencySymbol());
-
- return chrome->runBeforeUnloadConfirmPanel(text, this);
-}
-
-void Frame::scheduleClose()
-{
- if (!shouldClose())
- return;
-
- Chrome* chrome = page() ? page()->chrome() : 0;
- if (chrome)
- chrome->closeWindowSoon();
-}
-
-void Frame::respondToChangedSelection(const Selection& oldSelection, bool closeTyping)
-{
- if (document()) {
- bool isContinuousSpellCheckingEnabled = editor()->isContinuousSpellCheckingEnabled();
- bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled && editor()->isGrammarCheckingEnabled();
- if (isContinuousSpellCheckingEnabled) {
- Selection newAdjacentWords;
- Selection newSelectedSentence;
- if (selection()->selection().isContentEditable()) {
- VisiblePosition newStart(selection()->selection().visibleStart());
- newAdjacentWords = Selection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary));
- if (isContinuousGrammarCheckingEnabled)
- newSelectedSentence = Selection(startOfSentence(newStart), endOfSentence(newStart));
- }
-
- // When typing we check spelling elsewhere, so don't redo it here.
- // If this is a change in selection resulting from a delete operation,
- // oldSelection may no longer be in the document.
- if (closeTyping && oldSelection.isContentEditable() && oldSelection.start().node() && oldSelection.start().node()->inDocument()) {
- VisiblePosition oldStart(oldSelection.visibleStart());
- Selection oldAdjacentWords = Selection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary));
- if (oldAdjacentWords != newAdjacentWords) {
- editor()->markMisspellings(oldAdjacentWords);
- if (isContinuousGrammarCheckingEnabled) {
- Selection oldSelectedSentence = Selection(startOfSentence(oldStart), endOfSentence(oldStart));
- if (oldSelectedSentence != newSelectedSentence)
- editor()->markBadGrammar(oldSelectedSentence);
- }
- }
- }
-
- // This only erases markers that are in the first unit (word or sentence) of the selection.
- // Perhaps peculiar, but it matches AppKit.
- if (RefPtr<Range> wordRange = newAdjacentWords.toRange())
- document()->removeMarkers(wordRange.get(), DocumentMarker::Spelling);
- if (RefPtr<Range> sentenceRange = newSelectedSentence.toRange())
- document()->removeMarkers(sentenceRange.get(), DocumentMarker::Grammar);
- }
-
- // When continuous spell checking is off, existing markers disappear after the selection changes.
- if (!isContinuousSpellCheckingEnabled)
- document()->removeMarkers(DocumentMarker::Spelling);
- if (!isContinuousGrammarCheckingEnabled)
- document()->removeMarkers(DocumentMarker::Grammar);
- }
-
- editor()->respondToChangedSelection(oldSelection);
-}
-
-VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint)
-{
- HitTestResult result = eventHandler()->hitTestResultAtPoint(framePoint, true);
- Node* node = result.innerNode();
- if (!node)
- return VisiblePosition();
- RenderObject* renderer = node->renderer();
- if (!renderer)
- return VisiblePosition();
- VisiblePosition visiblePos = renderer->positionForCoordinates(result.localPoint().x(), result.localPoint().y());
- if (visiblePos.isNull())
- visiblePos = VisiblePosition(Position(node, 0));
- return visiblePos;
-}
-
-Document* Frame::documentAtPoint(const IntPoint& point)
-{
- if (!view())
- return 0;
-
- IntPoint pt = view()->windowToContents(point);
- HitTestResult result = HitTestResult(pt);
-
- if (contentRenderer())
- result = eventHandler()->hitTestResultAtPoint(pt, false);
- return result.innerNode() ? result.innerNode()->document() : 0;
-}
-
-FramePrivate::FramePrivate(Page* page, Frame* parent, Frame* thisFrame, HTMLFrameOwnerElement* ownerElement,
- FrameLoaderClient* frameLoaderClient)
- : m_page(page)
- , m_treeNode(thisFrame, parent)
- , m_loader(thisFrame, frameLoaderClient)
- , m_ownerElement(ownerElement)
- , m_script(thisFrame)
- , m_zoomFactor(parent ? parent->d->m_zoomFactor : 1.0f)
- , m_selectionGranularity(CharacterGranularity)
- , m_selectionController(thisFrame)
- , m_caretBlinkTimer(thisFrame, &Frame::caretBlinkTimerFired)
- , m_editor(thisFrame)
- , m_eventHandler(thisFrame)
- , m_animationController(thisFrame)
- , m_lifeSupportTimer(thisFrame, &Frame::lifeSupportTimerFired)
- , m_paintRestriction(PaintRestrictionNone)
- , m_caretVisible(false)
- , m_caretPaint(true)
- , m_isPainting(false)
- , m_highlightTextMatches(false)
- , m_inViewSourceMode(false)
- , m_prohibitsScrolling(false)
- , m_needsReapplyStyles(false)
- , m_isDisconnected(false)
- , m_excludeFromTextSearch(false)
-#if FRAME_LOADS_USER_STYLESHEET
- , m_userStyleSheetLoader(0)
-#endif
-{
-}
-
-FramePrivate::~FramePrivate()
-{
-}
-
-} // namespace WebCore
diff --git a/webkit/pending/FrameLoader.cpp b/webkit/pending/FrameLoader.cpp
deleted file mode 100644
index a5d1f27..0000000
--- a/webkit/pending/FrameLoader.cpp
+++ /dev/null
@@ -1,5186 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Trolltech ASA
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "FrameLoader.h"
-
-#include "Archive.h"
-#include "ArchiveFactory.h"
-#include "CString.h"
-#include "Cache.h"
-#include "CachedPage.h"
-#include "Chrome.h"
-#include "DOMImplementation.h"
-#include "DOMWindow.h"
-#include "DocLoader.h"
-#include "Document.h"
-#include "DocumentLoader.h"
-#include "Editor.h"
-#include "EditorClient.h"
-#include "Element.h"
-#include "Event.h"
-#include "EventNames.h"
-#include "FloatRect.h"
-#include "FormState.h"
-#include "Frame.h"
-#include "FrameLoadRequest.h"
-#include "FrameLoaderClient.h"
-#include "FramePrivate.h"
-#include "FrameTree.h"
-#include "FrameView.h"
-#include "HTMLFormElement.h"
-#include "HTMLFrameElement.h"
-#include "HTMLNames.h"
-#include "HTMLObjectElement.h"
-#include "HTTPParsers.h"
-#include "HistoryItem.h"
-#include "IconDatabase.h"
-#include "IconLoader.h"
-#include "InspectorController.h"
-#include "Logging.h"
-#include "MIMETypeRegistry.h"
-#include "MainResourceLoader.h"
-#include "Page.h"
-#include "PageCache.h"
-#include "PageGroup.h"
-#include "PluginData.h"
-#include "ProgressTracker.h"
-#include "RenderPart.h"
-#include "RenderWidget.h"
-#include "RenderView.h"
-#include "ResourceHandle.h"
-#include "ResourceRequest.h"
-#include "SecurityOrigin.h"
-#include "SegmentedString.h"
-#include "Settings.h"
-#include "SystemTime.h"
-#include "TextResourceDecoder.h"
-#include "WindowFeatures.h"
-#include "XMLHttpRequest.h"
-#include "XMLTokenizer.h"
-#include "ScriptController.h"
-
-#if USE(JSC)
-#include "JSDOMBinding.h"
-#include <kjs/JSObject.h>
-#endif
-
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
-#include "ApplicationCache.h"
-#include "ApplicationCacheResource.h"
-#endif
-
-#if ENABLE(SVG)
-#include "SVGDocument.h"
-#include "SVGLocatable.h"
-#include "SVGNames.h"
-#include "SVGPreserveAspectRatio.h"
-#include "SVGSVGElement.h"
-#include "SVGViewElement.h"
-#include "SVGViewSpec.h"
-#endif
-
-namespace WebCore {
-
-#if ENABLE(SVG)
-using namespace SVGNames;
-#endif
-using namespace HTMLNames;
-using namespace EventNames;
-
-#if USE(LOW_BANDWIDTH_DISPLAY)
-const unsigned int cMaxPendingSourceLengthInLowBandwidthDisplay = 128 * 1024;
-#endif
-
-struct FormSubmission {
- const char* action;
- String url;
- RefPtr<FormData> data;
- String target;
- String contentType;
- String boundary;
- RefPtr<Event> event;
-
- FormSubmission(const char* a, const String& u, PassRefPtr<FormData> d, const String& t,
- const String& ct, const String& b, PassRefPtr<Event> e)
- : action(a)
- , url(u)
- , data(d)
- , target(t)
- , contentType(ct)
- , boundary(b)
- , event(e)
- {
- }
-};
-
-struct ScheduledRedirection {
- enum Type { redirection, locationChange, historyNavigation, locationChangeDuringLoad, reload };
- Type type;
- double delay;
- String url;
- String referrer;
- bool lockHistory;
- bool wasUserGesture;
- RefPtr<HistoryItem> historyItem;
-
- ScheduledRedirection(double redirectDelay, const String& redirectURL, bool redirectLockHistory, bool userGesture)
- : type(redirection)
- , delay(redirectDelay)
- , url(redirectURL)
- , lockHistory(redirectLockHistory)
- , wasUserGesture(userGesture)
- {
- }
-
- ScheduledRedirection(Type locationChangeType,
- const String& locationChangeURL, const String& locationChangeReferrer,
- bool locationChangeLockHistory, bool locationChangeWasUserGesture)
- : type(locationChangeType)
- , delay(0)
- , url(locationChangeURL)
- , referrer(locationChangeReferrer)
- , lockHistory(locationChangeLockHistory)
- , wasUserGesture(locationChangeWasUserGesture)
- {
- }
-
- explicit ScheduledRedirection(HistoryItem* item)
- : type(historyNavigation)
- , delay(0)
- , lockHistory(false)
- , wasUserGesture(false)
- , historyItem(item)
- {
- }
-};
-
-static double storedTimeOfLastCompletedLoad;
-static FrameLoader::LocalLoadPolicy localLoadPolicy = FrameLoader::AllowLocalLoadsForLocalOnly;
-
-bool isBackForwardLoadType(FrameLoadType type)
-{
- switch (type) {
- case FrameLoadTypeStandard:
- case FrameLoadTypeReload:
- case FrameLoadTypeReloadAllowingStaleData:
- case FrameLoadTypeSame:
- case FrameLoadTypeRedirectWithLockedHistory:
- case FrameLoadTypeReplace:
- return false;
- case FrameLoadTypeBack:
- case FrameLoadTypeForward:
- case FrameLoadTypeIndexedBackForward:
- return true;
- }
- ASSERT_NOT_REACHED();
- return false;
-}
-
-static int numRequests(Document* document)
-{
- if (!document)
- return 0;
-
- return document->docLoader()->requestCount();
-}
-
-FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client)
- : m_frame(frame)
- , m_client(client)
- , m_state(FrameStateCommittedPage)
- , m_loadType(FrameLoadTypeStandard)
- , m_policyLoadType(FrameLoadTypeStandard)
- , m_delegateIsHandlingProvisionalLoadError(false)
- , m_delegateIsDecidingNavigationPolicy(false)
- , m_delegateIsHandlingUnimplementablePolicy(false)
- , m_firstLayoutDone(false)
- , m_quickRedirectComing(false)
- , m_sentRedirectNotification(false)
- , m_inStopAllLoaders(false)
- , m_navigationDuringLoad(false)
- , m_cachePolicy(CachePolicyVerify)
- , m_isExecutingJavaScriptFormAction(false)
- , m_isRunningScript(false)
- , m_didCallImplicitClose(false)
- , m_wasUnloadEventEmitted(false)
- , m_isComplete(false)
- , m_isLoadingMainResource(false)
- , m_firingUnloadEvents(false)
- , m_cancellingWithLoadInProgress(false)
- , m_needsClear(false)
- , m_receivedData(false)
- , m_encodingWasChosenByUser(false)
- , m_containsPlugIns(false)
- , m_redirectionTimer(this, &FrameLoader::redirectionTimerFired)
- , m_checkCompletedTimer(this, &FrameLoader::checkCompletedTimerFired)
- , m_checkLoadCompleteTimer(this, &FrameLoader::checkLoadCompleteTimerFired)
- , m_opener(0)
- , m_openedByDOM(false)
- , m_creatingInitialEmptyDocument(false)
- , m_isDisplayingInitialEmptyDocument(false)
- , m_committedFirstRealDocumentLoad(false)
- , m_didPerformFirstNavigation(false)
-#ifndef NDEBUG
- , m_didDispatchDidCommitLoad(false)
-#endif
-#if USE(LOW_BANDWIDTH_DISPLAY)
- , m_useLowBandwidthDisplay(true)
- , m_finishedParsingDuringLowBandwidthDisplay(false)
- , m_needToSwitchOutLowBandwidthDisplay(false)
-#endif
-{
-}
-
-FrameLoader::~FrameLoader()
-{
- setOpener(0);
-
- HashSet<Frame*>::iterator end = m_openedFrames.end();
- for (HashSet<Frame*>::iterator it = m_openedFrames.begin(); it != end; ++it)
- (*it)->loader()->m_opener = 0;
-
- m_client->frameLoaderDestroyed();
-}
-
-void FrameLoader::init()
-{
- // this somewhat odd set of steps is needed to give the frame an initial empty document
- m_isDisplayingInitialEmptyDocument = false;
- m_creatingInitialEmptyDocument = true;
- setPolicyDocumentLoader(m_client->createDocumentLoader(ResourceRequest(String("")), SubstituteData()).get());
- setProvisionalDocumentLoader(m_policyDocumentLoader.get());
- setState(FrameStateProvisional);
- m_provisionalDocumentLoader->setResponse(ResourceResponse(KURL(), "text/html", 0, String(), String()));
- m_provisionalDocumentLoader->finishedLoading();
- begin(KURL(), false);
- end();
- m_frame->document()->cancelParsing();
- m_creatingInitialEmptyDocument = false;
- m_didCallImplicitClose = true;
-}
-
-void FrameLoader::setDefersLoading(bool defers)
-{
- if (m_documentLoader)
- m_documentLoader->setDefersLoading(defers);
- if (m_provisionalDocumentLoader)
- m_provisionalDocumentLoader->setDefersLoading(defers);
- if (m_policyDocumentLoader)
- m_policyDocumentLoader->setDefersLoading(defers);
-}
-
-Frame* FrameLoader::createWindow(FrameLoader* frameLoaderForFrameLookup, const FrameLoadRequest& request, const WindowFeatures& features, bool& created)
-{
- ASSERT(!features.dialog || request.frameName().isEmpty());
-
- if (!request.frameName().isEmpty() && request.frameName() != "_blank") {
- Frame* frame = frameLoaderForFrameLookup->frame()->tree()->find(request.frameName());
- if (frame && shouldAllowNavigation(frame)) {
- if (!request.resourceRequest().url().isEmpty())
- frame->loader()->loadFrameRequestWithFormAndValues(request, false, 0, 0, HashMap<String, String>());
- if (Page* page = frame->page())
- page->chrome()->focus();
- created = false;
- return frame;
- }
- }
-
- // FIXME: Setting the referrer should be the caller's responsibility.
- FrameLoadRequest requestWithReferrer = request;
- requestWithReferrer.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
-
- Page* oldPage = m_frame->page();
- if (!oldPage)
- return 0;
-
- Page* page = oldPage->chrome()->createWindow(m_frame, requestWithReferrer, features);
- if (!page)
- return 0;
-
- Frame* frame = page->mainFrame();
- if (request.frameName() != "_blank")
- frame->tree()->setName(request.frameName());
-
- page->chrome()->setToolbarsVisible(features.toolBarVisible || features.locationBarVisible);
- page->chrome()->setStatusbarVisible(features.statusBarVisible);
- page->chrome()->setScrollbarsVisible(features.scrollbarsVisible);
- page->chrome()->setMenubarVisible(features.menuBarVisible);
- page->chrome()->setResizable(features.resizable);
-
- // 'x' and 'y' specify the location of the window, while 'width' and 'height'
- // specify the size of the page. We can only resize the window, so
- // adjust for the difference between the window size and the page size.
-
- FloatRect windowRect = page->chrome()->windowRect();
- FloatSize pageSize = page->chrome()->pageRect().size();
- if (features.xSet)
- windowRect.setX(features.x);
- if (features.ySet)
- windowRect.setY(features.y);
- if (features.widthSet)
- windowRect.setWidth(features.width + (windowRect.width() - pageSize.width()));
- if (features.heightSet)
- windowRect.setHeight(features.height + (windowRect.height() - pageSize.height()));
- page->chrome()->setWindowRect(windowRect);
-
- page->chrome()->show();
-
- created = true;
- return frame;
-}
-
-bool FrameLoader::canHandleRequest(const ResourceRequest& request)
-{
- return m_client->canHandleRequest(request);
-}
-
-void FrameLoader::changeLocation(const String& url, const String& referrer, bool lockHistory, bool userGesture)
-{
- // http://b/1082089
- // Hack to prevent FMW in WebCore::FrameLoader::checkNavigationPolicy.
- // Without this, if the frame's javascript onload handler removes the frame,
- // then once control returns into FrameLoader::checkNavigationPolicy (from
- // the call to m_client->dispatchDecidePolicyForNavigationAction()),
- // 'this' has been deallocated and we trash memory.
- RefPtr<Frame> protector(m_frame);
-
- changeLocation(completeURL(url), referrer, lockHistory, userGesture);
-}
-
-
-void FrameLoader::changeLocation(const KURL& url, const String& referrer, bool lockHistory, bool userGesture)
-{
- ResourceRequestCachePolicy policy = (m_cachePolicy == CachePolicyReload) || (m_cachePolicy == CachePolicyRefresh)
- ? ReloadIgnoringCacheData : UseProtocolCachePolicy;
- ResourceRequest request(url, referrer, policy);
-
- if (executeIfJavaScriptURL(request.url(), userGesture))
- return;
-
- urlSelected(request, "_self", 0, lockHistory, userGesture);
-}
-
-void FrameLoader::urlSelected(const FrameLoadRequest& request, Event* event, bool lockHistory)
-{
- FrameLoadRequest copy = request;
- if (copy.resourceRequest().httpReferrer().isEmpty())
- copy.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
-
- loadFrameRequestWithFormAndValues(copy, lockHistory, event, 0, HashMap<String, String>());
-}
-
-void FrameLoader::urlSelected(const ResourceRequest& request, const String& _target, Event* triggeringEvent, bool lockHistory, bool userGesture)
-{
- if (executeIfJavaScriptURL(request.url(), userGesture, false))
- return;
-
- String target = _target;
- if (target.isEmpty() && m_frame->document())
- target = m_frame->document()->baseTarget();
-
- FrameLoadRequest frameRequest(request, target);
-
- urlSelected(frameRequest, triggeringEvent, lockHistory);
-}
-
-bool FrameLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const String& urlString, const AtomicString& frameName)
-{
-#if USE(LOW_BANDWIDTH_DISPLAY)
- // don't create sub-frame during low bandwidth display
- if (frame()->document()->inLowBandwidthDisplay()) {
- m_needToSwitchOutLowBandwidthDisplay = true;
- return false;
- }
-#endif
-
- // Support for <frame src="javascript:string">
- KURL scriptURL;
- KURL url;
- if (protocolIs(urlString, "javascript")) {
- scriptURL = KURL(urlString);
- url = blankURL();
- } else
- url = completeURL(urlString);
-
- Frame* frame = ownerElement->contentFrame();
- if (frame)
- frame->loader()->scheduleLocationChange(url.string(), m_outgoingReferrer, true, userGestureHint());
- else
- frame = loadSubframe(ownerElement, url, frameName, m_outgoingReferrer);
-
- if (!frame)
- return false;
-
- if (!scriptURL.isEmpty())
- frame->loader()->executeIfJavaScriptURL(scriptURL);
-
- return true;
-}
-
-Frame* FrameLoader::loadSubframe(HTMLFrameOwnerElement* ownerElement, const KURL& url, const String& name, const String& referrer)
-{
- bool allowsScrolling = true;
- int marginWidth = -1;
- int marginHeight = -1;
- if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag)) {
- HTMLFrameElementBase* o = static_cast<HTMLFrameElementBase*>(ownerElement);
- allowsScrolling = o->scrollingMode() != ScrollbarAlwaysOff;
- marginWidth = o->getMarginWidth();
- marginHeight = o->getMarginHeight();
- }
-
- if (!canLoad(url, referrer)) {
- FrameLoader::reportLocalLoadFailed(m_frame, url.string());
- return 0;
- }
-
- bool hideReferrer = shouldHideReferrer(url, referrer);
- RefPtr<Frame> frame = m_client->createFrame(url, name, ownerElement, hideReferrer ? String() : referrer,
- allowsScrolling, marginWidth, marginHeight);
-
- if (!frame) {
- checkCallImplicitClose();
- return 0;
- }
-
- frame->loader()->m_isComplete = false;
-
- RenderObject* renderer = ownerElement->renderer();
- FrameView* view = frame->view();
- if (renderer && renderer->isWidget() && view)
- static_cast<RenderWidget*>(renderer)->setWidget(view);
-
- checkCallImplicitClose();
-
- // In these cases, the synchronous load would have finished
- // before we could connect the signals, so make sure to send the
- // completed() signal for the child by hand
- // FIXME: In this case the Frame will have finished loading before
- // it's being added to the child list. It would be a good idea to
- // create the child first, then invoke the loader separately.
- if (url.isEmpty() || url == blankURL()) {
- frame->loader()->completed();
- frame->loader()->checkCompleted();
- }
-
- return frame.get();
-}
-
-void FrameLoader::submitFormAgain()
-{
- if (m_isRunningScript)
- return;
- OwnPtr<FormSubmission> form(m_deferredFormSubmission.release());
- if (form)
- submitForm(form->action, form->url, form->data, form->target,
- form->contentType, form->boundary, form->event.get());
-}
-
-void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<FormData> formData,
- const String& target, const String& contentType, const String& boundary, Event* event)
-{
- ASSERT(formData);
-
- if (!m_frame->page())
- return;
-
- KURL u = completeURL(url.isNull() ? "" : url);
- // FIXME: Do we really need to special-case an empty URL?
- // Would it be better to just go on with the form submisson and let the I/O fail?
- if (u.isEmpty())
- return;
-
- if (u.protocolIs("javascript")) {
- m_isExecutingJavaScriptFormAction = true;
- executeIfJavaScriptURL(u, false, false);
- m_isExecutingJavaScriptFormAction = false;
- return;
- }
-
- if (m_isRunningScript) {
- if (m_deferredFormSubmission)
- return;
- m_deferredFormSubmission.set(new FormSubmission(action, url, formData, target,
- contentType, boundary, event));
- return;
- }
-
- formData->generateFiles(m_frame->page()->chrome()->client());
-
- FrameLoadRequest frameRequest;
-
- if (!m_outgoingReferrer.isEmpty())
- frameRequest.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
-
- frameRequest.setFrameName(target.isEmpty() ? m_frame->document()->baseTarget() : target);
-
- // Handle mailto: forms
- bool isMailtoForm = equalIgnoringCase(u.protocol(), "mailto");
- if (isMailtoForm && strcmp(action, "GET") != 0) {
- // Append body= for POST mailto, replace the whole query string for GET one.
- String body = formData->flattenToString();
- String query = u.query();
- if (!query.isEmpty())
- query.append('&');
- u.setQuery(query + body);
- }
-
- if (strcmp(action, "GET") == 0) {
- u.setQuery(formData->flattenToString());
- } else {
- if (!isMailtoForm)
- frameRequest.resourceRequest().setHTTPBody(formData.get());
- frameRequest.resourceRequest().setHTTPMethod("POST");
-
- // construct some user headers if necessary
- if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
- frameRequest.resourceRequest().setHTTPContentType(contentType);
- else // contentType must be "multipart/form-data"
- frameRequest.resourceRequest().setHTTPContentType(contentType + "; boundary=" + boundary);
- }
-
- frameRequest.resourceRequest().setURL(u);
-
- submitForm(frameRequest, event);
-}
-
-void FrameLoader::stopLoading(bool sendUnload)
-{
- if (m_frame->document() && m_frame->document()->tokenizer())
- m_frame->document()->tokenizer()->stopParsing();
-
- if (sendUnload) {
- if (m_frame->document()) {
- if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) {
- Node* currentFocusedNode = m_frame->document()->focusedNode();
- if (currentFocusedNode)
- currentFocusedNode->aboutToUnload();
- setFiringUnloadEvents(true);
- m_frame->document()->dispatchWindowEvent(unloadEvent, false, false);
- setFiringUnloadEvents(false);
- if (m_frame->document())
- m_frame->document()->updateRendering();
- m_wasUnloadEventEmitted = true;
- if (m_frame->eventHandler()->pendingFrameUnloadEventCount())
- m_frame->eventHandler()->clearPendingFrameUnloadEventCount();
- if (m_frame->eventHandler()->pendingFrameBeforeUnloadEventCount())
- m_frame->eventHandler()->clearPendingFrameBeforeUnloadEventCount();
- }
- }
- if (m_frame->document() && !m_frame->document()->inPageCache())
- m_frame->document()->removeAllEventListenersFromAllNodes();
- }
-
- m_isComplete = true; // to avoid calling completed() in finishedParsing() (David)
- m_isLoadingMainResource = false;
- m_didCallImplicitClose = true; // don't want that one either
- m_cachePolicy = CachePolicyVerify; // Why here?
-
- if (m_frame->document() && m_frame->document()->parsing()) {
- finishedParsing();
- m_frame->document()->setParsing(false);
- }
-
- m_workingURL = KURL();
-
- if (Document* doc = m_frame->document()) {
- if (DocLoader* docLoader = doc->docLoader())
- cache()->loader()->cancelRequests(docLoader);
- XMLHttpRequest::cancelRequests(doc);
-#if ENABLE(DATABASE)
-#endif
- }
-
- // tell all subframes to stop as well
- for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
- child->loader()->stopLoading(sendUnload);
-
- cancelRedirection();
-
-#if USE(LOW_BANDWIDTH_DISPLAY)
- if (m_frame->document() && m_frame->document()->inLowBandwidthDisplay()) {
- // Since loading is forced to stop, reset the state without really switching.
- m_needToSwitchOutLowBandwidthDisplay = false;
- switchOutLowBandwidthDisplayIfReady();
- }
-#endif
-}
-
-void FrameLoader::stop()
-{
- // http://bugs.webkit.org/show_bug.cgi?id=10854
- // The frame's last ref may be removed and it will be deleted by checkCompleted().
- RefPtr<Frame> protector(m_frame);
-
- if (m_frame->document()) {
- if (m_frame->document()->tokenizer())
- m_frame->document()->tokenizer()->stopParsing();
- m_frame->document()->finishParsing();
- } else
- // WebKit partially uses WebCore when loading non-HTML docs. In these cases doc==nil, but
- // WebCore is enough involved that we need to checkCompleted() in order for m_bComplete to
- // become true. An example is when a subframe is a pure text doc, and that subframe is the
- // last one to complete.
- checkCompleted();
- if (m_iconLoader)
- m_iconLoader->stopLoading();
-}
-
-bool FrameLoader::closeURL()
-{
- saveDocumentState();
- stopLoading(true);
- m_frame->editor()->clearUndoRedoOperations();
- return true;
-}
-
-void FrameLoader::cancelRedirection(bool cancelWithLoadInProgress)
-{
- m_cancellingWithLoadInProgress = cancelWithLoadInProgress;
-
- stopRedirectionTimer();
-
- m_scheduledRedirection.clear();
-}
-
-KURL FrameLoader::iconURL()
-{
- // If this isn't a top level frame, return nothing
- if (m_frame->tree() && m_frame->tree()->parent())
- return KURL();
-
- // If we have an iconURL from a Link element, return that
- if (m_frame->document() && !m_frame->document()->iconURL().isEmpty())
- return KURL(m_frame->document()->iconURL());
-
- // Don't return a favicon iconURL unless we're http or https
- if (!m_URL.protocolIs("http") && !m_URL.protocolIs("https"))
- return KURL();
-
- KURL url;
- url.setProtocol(m_URL.protocol());
- url.setHost(m_URL.host());
- if (int port = m_URL.port())
- url.setPort(port);
- url.setPath("/favicon.ico");
- return url;
-}
-
-bool FrameLoader::didOpenURL(const KURL& url)
-{
- if (m_scheduledRedirection && m_scheduledRedirection->type == ScheduledRedirection::locationChangeDuringLoad)
- // A redirect was scheduled before the document was created.
- // This can happen when one frame changes another frame's location.
- return false;
-
- cancelRedirection();
- m_frame->editor()->clearLastEditCommand();
- closeURL();
-
- m_isComplete = false;
- m_isLoadingMainResource = true;
- m_didCallImplicitClose = false;
-
- m_frame->setJSStatusBarText(String());
- m_frame->setJSDefaultStatusBarText(String());
-
- m_URL = url;
- if ((m_URL.protocolIs("http") || m_URL.protocolIs("https")) && !m_URL.host().isEmpty() && m_URL.path().isEmpty())
- m_URL.setPath("/");
- m_workingURL = m_URL;
-
- started();
-
- return true;
-}
-
-void FrameLoader::didExplicitOpen()
-{
- m_isComplete = false;
- m_didCallImplicitClose = false;
-
- // Calling document.open counts as committing the first real document load.
- m_committedFirstRealDocumentLoad = true;
-
- // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results
- // from a subsequent window.document.open / window.document.write call.
- // Cancelling redirection here works for all cases because document.open
- // implicitly precedes document.write.
- cancelRedirection();
- if (m_frame->document()->url() != blankURL())
- m_URL = m_frame->document()->url();
-}
-
-bool FrameLoader::executeIfJavaScriptURL(const KURL& url, bool userGesture, bool replaceDocument)
-{
- if (!url.protocolIs("javascript"))
- return false;
-
- String script = decodeURLEscapeSequences(url.string().substring(strlen("javascript:")));
-
- bool succ;
- String scriptResult = executeScript(script, &succ, userGesture);
- if (!succ) return true;
-
- SecurityOrigin* currentSecurityOrigin = 0;
- if (m_frame->document())
- currentSecurityOrigin = m_frame->document()->securityOrigin();
-
- // FIXME: We should always replace the document, but doing so
- // synchronously can cause crashes:
- // http://bugs.webkit.org/show_bug.cgi?id=16782
- if (replaceDocument) {
- begin(m_URL, true, currentSecurityOrigin);
- write(scriptResult);
- end();
- }
-
- return true;
-}
-
-void FrameLoader::executeScript(const String& url, int baseLine, const String& script) {
- bool succ;
- executeScript(url, baseLine, script, &succ);
-}
-
-void FrameLoader::executeScript(const String& script, bool forceUserGesture)
-{
- bool succ;
- executeScript(forceUserGesture ? String() : m_URL.string(), 0, script, &succ);
-}
-
-String FrameLoader::executeScript(const String& script, bool* succ, bool forceUserGesture)
-{
- return executeScript(forceUserGesture ? String() : m_URL.string(), 1, script, succ);
-}
-
-String FrameLoader::executeScript(const String& url, int baseLine, const String& script, bool* succ)
-{
- *succ = false;
- if (!m_frame->script()->isEnabled() || m_frame->script()->isPaused())
- return String();
-
- bool wasRunningScript = m_isRunningScript;
- m_isRunningScript = true;
-
- String result = m_frame->script()->evaluate(url, baseLine, script, 0, succ);
-
- if (!wasRunningScript) {
- m_isRunningScript = false;
- submitFormAgain();
- Document::updateDocumentsRendering();
- }
-
- return result;
-}
-
-void FrameLoader::cancelAndClear()
-{
- cancelRedirection();
-
- if (!m_isComplete)
- closeURL();
-
- clear(false);
-}
-
-void FrameLoader::clear(bool clearWindowProperties, bool clearScriptObjects)
-{
- // FIXME: Commenting out the below line causes <http://bugs.webkit.org/show_bug.cgi?id=11212>, but putting it
- // back causes a measurable performance regression which we will need to fix to restore the correct behavior
- // urlsBridgeKnowsAbout.clear();
-
- m_frame->editor()->clear();
-
- if (!m_needsClear)
- return;
- m_needsClear = false;
-
- if (m_frame->document() && !m_frame->document()->inPageCache()) {
- m_frame->document()->cancelParsing();
- if (m_frame->document()->attached()) {
- m_frame->document()->willRemove();
- m_frame->document()->detach();
-
- m_frame->document()->removeFocusedNodeOfSubtree(m_frame->document());
- }
- }
-
- // Do this after detaching the document so that the unload event works.
- if (clearWindowProperties) {
- m_frame->clearDOMWindow();
- m_frame->script()->clearWindowShell();
- }
-
- m_frame->selection()->clear();
- m_frame->eventHandler()->clear();
- if (m_frame->view())
- m_frame->view()->clear();
-
- m_frame->setSelectionGranularity(CharacterGranularity);
-
- // Do not drop the document before the ScriptController and view are cleared
- // as some destructors might still try to access the document.
- m_frame->setDocument(0);
- m_decoder = 0;
-
- m_containsPlugIns = false;
-
- if (clearScriptObjects)
- m_frame->script()->clearScriptObjects();
-
- m_redirectionTimer.stop();
- m_scheduledRedirection.clear();
-
- m_checkCompletedTimer.stop();
- m_checkLoadCompleteTimer.stop();
-
- m_receivedData = false;
- m_isDisplayingInitialEmptyDocument = false;
-
- if (!m_encodingWasChosenByUser)
- m_encoding = String();
-}
-
-void FrameLoader::receivedFirstData()
-{
- begin(m_workingURL, false);
-
- dispatchDidCommitLoad();
- dispatchWindowObjectAvailable();
-
- String ptitle = m_documentLoader->title();
- // If we have a title let the WebView know about it.
- if (!ptitle.isNull())
- m_client->dispatchDidReceiveTitle(ptitle);
-
- m_frame->document()->docLoader()->setCachePolicy(m_cachePolicy);
- m_workingURL = KURL();
-
- double delay;
- String url;
- if (!m_documentLoader)
- return;
- if (!parseHTTPRefresh(m_documentLoader->response().httpHeaderField("Refresh"), false, delay, url))
- return;
-
- if (url.isEmpty())
- url = m_URL.string();
- else
- url = m_frame->document()->completeURL(url).string();
-
- scheduleHTTPRedirection(delay, url);
-}
-
-const String& FrameLoader::responseMIMEType() const
-{
- return m_responseMIMEType;
-}
-
-void FrameLoader::setResponseMIMEType(const String& type)
-{
- m_responseMIMEType = type;
-}
-
-void FrameLoader::begin()
-{
- begin(KURL());
-}
-
-void FrameLoader::begin(const KURL& url, bool dispatch, SecurityOrigin* origin)
-{
- // We need to take a reference to the security origin because |clear|
- // might destroy the document that owns it.
- RefPtr<SecurityOrigin> forcedSecurityOrigin = origin;
-
- bool resetScripting = !(m_isDisplayingInitialEmptyDocument && m_frame->document() && m_frame->document()->securityOrigin()->isSecureTransitionTo(url));
- clear(resetScripting, resetScripting);
- if (dispatch)
- dispatchWindowObjectAvailable();
-
- m_needsClear = true;
- m_isComplete = false;
- m_didCallImplicitClose = false;
- m_isLoadingMainResource = true;
- m_isDisplayingInitialEmptyDocument = m_creatingInitialEmptyDocument;
-
- KURL ref(url);
- ref.setUser(String());
- ref.setPass(String());
- ref.setRef(String());
- m_outgoingReferrer = ref.string();
- m_URL = url;
-
- RefPtr<Document> document = DOMImplementation::createDocument(m_responseMIMEType, m_frame, m_frame->inViewSourceMode());
- m_frame->setDocument(document);
-
- document->setURL(m_URL);
- if (m_decoder)
- document->setDecoder(m_decoder.get());
- if (forcedSecurityOrigin)
- document->setSecurityOrigin(forcedSecurityOrigin.get());
-
- m_frame->domWindow()->setURL(document->url());
- m_frame->domWindow()->setSecurityOrigin(document->securityOrigin());
-
- updatePolicyBaseURL();
-
- Settings* settings = document->settings();
- document->docLoader()->setAutoLoadImages(settings && settings->loadsImagesAutomatically());
-
- if (m_documentLoader) {
- String dnsPrefetchControl = m_documentLoader->response().httpHeaderField("X-DNS-Prefetch-Control");
- if (!dnsPrefetchControl.isEmpty())
- document->setDNSPrefetchControl(dnsPrefetchControl);
- }
-
-#if FRAME_LOADS_USER_STYLESHEET
- KURL userStyleSheet = settings ? settings->userStyleSheetLocation() : KURL();
- if (!userStyleSheet.isEmpty())
- m_frame->setUserStyleSheetLocation(userStyleSheet);
-#endif
-
- restoreDocumentState();
-
- document->implicitOpen();
-
- if (m_frame->view())
- m_frame->view()->resizeContents(0, 0);
-
-#if USE(LOW_BANDWIDTH_DISPLAY)
- // Low bandwidth display is a first pass display without external resources
- // used to give an instant visual feedback. We currently only enable it for
- // HTML documents in the top frame.
- if (document->isHTMLDocument() && !m_frame->tree()->parent() && m_useLowBandwidthDisplay) {
- m_pendingSourceInLowBandwidthDisplay = String();
- m_finishedParsingDuringLowBandwidthDisplay = false;
- m_needToSwitchOutLowBandwidthDisplay = false;
- document->setLowBandwidthDisplay(true);
- }
-#endif
-}
-
-void FrameLoader::write(const char* str, int len, bool flush)
-{
- if (len == 0 && !flush)
- return;
-
- if (len == -1)
- len = strlen(str);
-
- Tokenizer* tokenizer = m_frame->document()->tokenizer();
- if (tokenizer && tokenizer->wantsRawData()) {
- if (len > 0)
- tokenizer->writeRawData(str, len);
- return;
- }
-
- if (!m_decoder) {
- Settings* settings = m_frame->settings();
- if (settings) {
- TextResourceDecoder* hintDecoder = NULL;
- Frame* parentFrame = m_frame->tree()->parent();
- if (parentFrame && parentFrame->document())
- hintDecoder = parentFrame->document()->decoder();
- m_decoder = TextResourceDecoder::create(m_responseMIMEType, settings->defaultTextEncodingName(), settings->usesEncodingDetector(), hintDecoder);
- } else
- m_decoder = TextResourceDecoder::create(m_responseMIMEType, String());
- if (m_encoding.isEmpty()) {
- Frame* parentFrame = m_frame->tree()->parent();
- // TODO(jungshik) : We might as well consider allowing inheriting charset
- // from parent even if canAccess returns false as long as the parent charset
- // is regarded as safe (that is, it's not UTF-7/ISO-2022-XX/HZ), of which
- // we're not yet sure.
- if (parentFrame && parentFrame->document()->securityOrigin()->canAccess(m_frame->document()->securityOrigin()))
- m_decoder->setEncoding(parentFrame->document()->inputEncoding(), TextResourceDecoder::EncodingFromParentFrame);
- } else {
- m_decoder->setEncoding(m_encoding,
- m_encodingWasChosenByUser ? TextResourceDecoder::UserChosenEncoding : TextResourceDecoder::EncodingFromHTTPHeader);
- }
- m_frame->document()->setDecoder(m_decoder.get());
- }
-
- String decoded = m_decoder->decode(str, len);
- if (flush)
- decoded += m_decoder->flush();
- if (decoded.isEmpty())
- return;
-
-#if USE(LOW_BANDWIDTH_DISPLAY)
- if (m_frame->document()->inLowBandwidthDisplay())
- m_pendingSourceInLowBandwidthDisplay.append(decoded);
- else // reset policy which is changed in switchOutLowBandwidthDisplayIfReady()
- m_frame->document()->docLoader()->setCachePolicy(m_cachePolicy);
-#endif
-
- if (!m_receivedData) {
- m_receivedData = true;
- if (m_decoder->encoding().usesVisualOrdering())
- m_frame->document()->setVisuallyOrdered();
- m_frame->document()->recalcStyle(Node::Force);
- }
-
- if (tokenizer) {
- ASSERT(!tokenizer->wantsRawData());
- tokenizer->write(decoded, true);
- }
-}
-
-void FrameLoader::write(const String& str)
-{
- if (str.isNull())
- return;
-
- if (!m_receivedData) {
- m_receivedData = true;
- m_frame->document()->setParseMode(Document::Strict);
- }
-
- if (Tokenizer* tokenizer = m_frame->document()->tokenizer())
- tokenizer->write(str, true);
-}
-
-void FrameLoader::end()
-{
- m_isLoadingMainResource = false;
- endIfNotLoadingMainResource();
-}
-
-void FrameLoader::endIfNotLoadingMainResource()
-{
- if (m_isLoadingMainResource || !m_frame->page())
- return;
-
- // http://bugs.webkit.org/show_bug.cgi?id=10854
- // The frame's last ref may be removed and it can be deleted by checkCompleted(),
- // so we'll add a protective refcount
- RefPtr<Frame> protector(m_frame);
-
- // make sure nothing's left in there
- if (m_frame->document()) {
- write(0, 0, true);
- m_frame->document()->finishParsing();
-#if USE(LOW_BANDWIDTH_DISPLAY)
- if (m_frame->document()->inLowBandwidthDisplay()) {
- m_finishedParsingDuringLowBandwidthDisplay = true;
- switchOutLowBandwidthDisplayIfReady();
- }
-#endif
- } else
- // WebKit partially uses WebCore when loading non-HTML docs. In these cases doc==nil, but
- // WebCore is enough involved that we need to checkCompleted() in order for m_bComplete to
- // become true. An example is when a subframe is a pure text doc, and that subframe is the
- // last one to complete.
- checkCompleted();
-}
-
-void FrameLoader::iconLoadDecisionAvailable()
-{
- if (!m_mayLoadIconLater)
- return;
- LOG(IconDatabase, "FrameLoader %p was told a load decision is available for its icon", this);
- startIconLoader();
- m_mayLoadIconLater = false;
-}
-
-void FrameLoader::startIconLoader()
-{
- // FIXME: We kick off the icon loader when the frame is done receiving its main resource.
- // But we should instead do it when we're done parsing the head element.
- if (!isLoadingMainFrame())
- return;
-
- if (!iconDatabase() || !iconDatabase()->isEnabled())
- return;
-
- KURL url(iconURL());
- String urlString(url.string());
- if (urlString.isEmpty())
- return;
-
- // If we're not reloading and the icon database doesn't say to load now then bail before we actually start the load
- if (loadType() != FrameLoadTypeReload) {
- IconLoadDecision decision = iconDatabase()->loadDecisionForIconURL(urlString, m_documentLoader.get());
- if (decision == IconLoadNo) {
- LOG(IconDatabase, "FrameLoader::startIconLoader() - Told not to load this icon, committing iconURL %s to database for pageURL mapping", urlString.ascii().data());
- commitIconURLToIconDatabase(url);
-
- // We were told not to load this icon - that means this icon is already known by the database
- // If the icon data hasn't been read in from disk yet, kick off the read of the icon from the database to make sure someone
- // has done it. This is after registering for the notification so the WebView can call the appropriate delegate method.
- // Otherwise if the icon data *is* available, notify the delegate
- if (!iconDatabase()->iconDataKnownForIconURL(urlString)) {
- LOG(IconDatabase, "Told not to load icon %s but icon data is not yet available - registering for notification and requesting load from disk", urlString.ascii().data());
- m_client->registerForIconNotification();
- iconDatabase()->iconForPageURL(m_URL.string(), IntSize(0, 0));
- iconDatabase()->iconForPageURL(originalRequestURL().string(), IntSize(0, 0));
- } else
- m_client->dispatchDidReceiveIcon();
-
- return;
- }
-
- if (decision == IconLoadUnknown) {
- // In this case, we may end up loading the icon later, but we still want to commit the icon url mapping to the database
- // just in case we don't end up loading later - if we commit the mapping a second time after the load, that's no big deal
- // We also tell the client to register for the notification that the icon is received now so it isn't missed in case the
- // icon is later read in from disk
- LOG(IconDatabase, "FrameLoader %p might load icon %s later", this, urlString.ascii().data());
- m_mayLoadIconLater = true;
- m_client->registerForIconNotification();
- commitIconURLToIconDatabase(url);
- return;
- }
- }
-
- // This is either a reload or the icon database said "yes, load the icon", so kick off the load!
- if (!m_iconLoader)
- m_iconLoader.set(IconLoader::create(m_frame).release());
-
- m_iconLoader->startLoading();
-}
-
-void FrameLoader::setLocalLoadPolicy(LocalLoadPolicy policy)
-{
- localLoadPolicy = policy;
-}
-
-bool FrameLoader::restrictAccessToLocal()
-{
- return localLoadPolicy != FrameLoader::AllowLocalLoadsForAll;
-}
-
-bool FrameLoader::allowSubstituteDataAccessToLocal()
-{
- return localLoadPolicy != FrameLoader::AllowLocalLoadsForLocalOnly;
-}
-
-static HashSet<String, CaseFoldingHash>& localSchemes()
-{
- static HashSet<String, CaseFoldingHash> localSchemes;
-
- if (localSchemes.isEmpty()) {
- localSchemes.add("file");
- localSchemes.add("chrome-resource");
-#if PLATFORM(MAC)
- localSchemes.add("applewebdata");
-#endif
-#if PLATFORM(QT)
- localSchemes.add("qrc");
-#endif
- }
-
- return localSchemes;
-}
-
-void FrameLoader::commitIconURLToIconDatabase(const KURL& icon)
-{
- ASSERT(iconDatabase());
- LOG(IconDatabase, "Committing iconURL %s to database for pageURLs %s and %s", icon.string().ascii().data(), m_URL.string().ascii().data(), originalRequestURL().string().ascii().data());
- iconDatabase()->setIconURLForPageURL(icon.string(), m_URL.string());
- iconDatabase()->setIconURLForPageURL(icon.string(), originalRequestURL().string());
-}
-
-void FrameLoader::restoreDocumentState()
-{
- Document* doc = m_frame->document();
- if (!doc)
- return;
-
- HistoryItem* itemToRestore = 0;
-
- switch (loadType()) {
- case FrameLoadTypeReload:
- case FrameLoadTypeReloadAllowingStaleData:
- case FrameLoadTypeSame:
- case FrameLoadTypeReplace:
- break;
- case FrameLoadTypeBack:
- case FrameLoadTypeForward:
- case FrameLoadTypeIndexedBackForward:
- case FrameLoadTypeRedirectWithLockedHistory:
- case FrameLoadTypeStandard:
- itemToRestore = m_currentHistoryItem.get();
- }
-
- if (!itemToRestore)
- return;
-
- doc->setStateForNewFormElements(itemToRestore->documentState());
-}
-
-void FrameLoader::gotoAnchor()
-{
- // If our URL has no ref, then we have no place we need to jump to.
- // OTOH If CSS target was set previously, we want to set it to 0, recalc
- // and possibly repaint because :target pseudo class may have been
- // set (see bug 11321).
- if (!m_URL.hasRef() && !(m_frame->document() && m_frame->document()->getCSSTarget()))
- return;
-
- String ref = m_URL.ref();
- if (gotoAnchor(ref))
- return;
-
- // Try again after decoding the ref, based on the document's encoding.
- if (m_decoder)
- gotoAnchor(decodeURLEscapeSequences(ref, m_decoder->encoding()));
-}
-
-void FrameLoader::finishedParsing()
-{
- if (m_creatingInitialEmptyDocument)
- return;
-
- // This can be called from the Frame's destructor, in which case we shouldn't protect ourselves
- // because doing so will cause us to re-enter the destructor when protector goes out of scope.
- // Null-checking the FrameView indicates whether or not we're in the destructor.
- RefPtr<Frame> protector = m_frame->view() ? m_frame : 0;
-
- checkCompleted();
-
- if (!m_frame->view())
- return; // We are being destroyed by something checkCompleted called.
-
- // Check if the scrollbars are really needed for the content.
- // If not, remove them, relayout, and repaint.
- m_frame->view()->restoreScrollbar();
-
- m_client->dispatchDidFinishDocumentLoad();
-
- gotoAnchor();
-}
-
-void FrameLoader::loadDone()
-{
- if (m_frame->document())
- checkCompleted();
-}
-
-void FrameLoader::checkCompleted()
-{
- // Any frame that hasn't completed yet?
- for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
- if (!child->loader()->m_isComplete)
- return;
-
- // Have we completed before?
- if (m_isComplete)
- return;
-
- // Are we still parsing?
- if (m_frame->document() && m_frame->document()->parsing())
- return;
-
- // Still waiting for images/scripts?
- if (m_frame->document())
- if (numRequests(m_frame->document()))
- return;
-
-#if USE(LOW_BANDWIDTH_DISPLAY)
- // as switch will be called, don't complete yet
- if (m_frame->document() && m_frame->document()->inLowBandwidthDisplay() && m_needToSwitchOutLowBandwidthDisplay)
- return;
-#endif
-
- // OK, completed.
- m_isComplete = true;
-
- RefPtr<Frame> protect(m_frame);
- checkCallImplicitClose(); // if we didn't do it before
-
- // Do not start a redirection timer for subframes here.
- // That is deferred until the parent is completed.
- if (m_scheduledRedirection && !m_frame->tree()->parent())
- startRedirectionTimer();
-
- completed();
- if (m_frame->page())
- checkLoadComplete();
-}
-
-void FrameLoader::checkCompletedTimerFired(Timer<FrameLoader>*)
-{
- checkCompleted();
-}
-
-void FrameLoader::scheduleCheckCompleted()
-{
- if (!m_checkCompletedTimer.isActive())
- m_checkCompletedTimer.startOneShot(0);
-}
-
-void FrameLoader::checkLoadCompleteTimerFired(Timer<FrameLoader>*)
-{
- if (!m_frame->page())
- return;
- checkLoadComplete();
-}
-
-void FrameLoader::scheduleCheckLoadComplete()
-{
- if (!m_checkLoadCompleteTimer.isActive())
- m_checkLoadCompleteTimer.startOneShot(0);
-}
-
-void FrameLoader::checkCallImplicitClose()
-{
- if (m_didCallImplicitClose || !m_frame->document() || m_frame->document()->parsing())
- return;
-
- for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
- if (!child->loader()->m_isComplete) // still got a frame running -> too early
- return;
-
- m_didCallImplicitClose = true;
- m_wasUnloadEventEmitted = false;
- if (m_frame->document())
- m_frame->document()->implicitClose();
-}
-
-KURL FrameLoader::baseURL() const
-{
- ASSERT(m_frame->document());
- return m_frame->document()->baseURL();
-}
-
-String FrameLoader::baseTarget() const
-{
- ASSERT(m_frame->document());
- return m_frame->document()->baseTarget();
-}
-
-KURL FrameLoader::completeURL(const String& url)
-{
- ASSERT(m_frame->document());
- return m_frame->document()->completeURL(url);
-}
-
-void FrameLoader::scheduleHTTPRedirection(double delay, const String& url)
-{
- if (delay < 0 || delay > INT_MAX / 1000)
- return;
-
- if (!m_frame->page())
- return;
-
- // We want a new history item if the refresh timeout is > 1 second.
- if (!m_scheduledRedirection || delay <= m_scheduledRedirection->delay)
- scheduleRedirection(new ScheduledRedirection(delay, url, delay <= 1, false));
-}
-
-void FrameLoader::scheduleLocationChange(const String& url, const String& referrer, bool lockHistory, bool wasUserGesture)
-{
- if (!m_frame->page())
- return;
-
- // If the URL we're going to navigate to is the same as the current one, except for the
- // fragment part, we don't need to schedule the location change.
- KURL parsedURL(url);
- if (parsedURL.hasRef() && equalIgnoringRef(m_URL, parsedURL)) {
- changeLocation(url, referrer, lockHistory, wasUserGesture);
- return;
- }
-
- // Handle a location change of a page with no document as a special case.
- // This may happen when a frame changes the location of another frame.
- bool duringLoad = !m_committedFirstRealDocumentLoad;
-
- // If a redirect was scheduled during a load, then stop the current load.
- // Otherwise when the current load transitions from a provisional to a
- // committed state, pending redirects may be cancelled.
- if (duringLoad) {
- if (m_provisionalDocumentLoader)
- m_provisionalDocumentLoader->stopLoading();
- stopLoading(true);
- }
-
- ScheduledRedirection::Type type = duringLoad
- ? ScheduledRedirection::locationChangeDuringLoad : ScheduledRedirection::locationChange;
- scheduleRedirection(new ScheduledRedirection(type, url, referrer, lockHistory, wasUserGesture));
-}
-
-void FrameLoader::scheduleRefresh(bool wasUserGesture)
-{
- if (!m_frame->page())
- return;
-
- // Handle a location change of a page with no document as a special case.
- // This may happen when a frame requests a refresh of another frame.
- bool duringLoad = !m_frame->document();
-
- // If a refresh was scheduled during a load, then stop the current load.
- // Otherwise when the current load transitions from a provisional to a
- // committed state, pending redirects may be cancelled.
- if (duringLoad)
- stopLoading(true);
-
- ScheduledRedirection::Type type = duringLoad
- ? ScheduledRedirection::locationChangeDuringLoad : ScheduledRedirection::locationChange;
- scheduleRedirection(new ScheduledRedirection(type, m_URL.string(), m_outgoingReferrer, true, wasUserGesture));
- m_cachePolicy = CachePolicyRefresh;
-}
-
-bool FrameLoader::isLocationChange(const ScheduledRedirection& redirection)
-{
- switch (redirection.type) {
- case ScheduledRedirection::redirection:
- return false;
- case ScheduledRedirection::reload:
- case ScheduledRedirection::historyNavigation:
- case ScheduledRedirection::locationChange:
- case ScheduledRedirection::locationChangeDuringLoad:
- return true;
- }
- ASSERT_NOT_REACHED();
- return false;
-}
-
-void FrameLoader::scheduleHistoryNavigation(int steps)
-{
- if (!m_frame->page())
- return;
-
- // navigation will always be allowed in the 0 steps case, which is OK because that's supposed to force a reload.
- if (!canGoBackOrForward(steps)) {
- cancelRedirection();
- return;
- }
-
- if (steps == 0) {
- // Special case for go(0) from a frame -> reload only the frame
- scheduleRedirection(new ScheduledRedirection(ScheduledRedirection::reload, String(), String(), false, false));
- return;
- }
-
- Page* page = m_frame->page();
- if (!page)
- return;
- BackForwardList* list = page->backForwardList();
- if (!list)
- return;
-
- // Asynchronously loads the item at the given offset in the history.
- list->goToItemAtIndexAsync(steps);
-
- // The redirection will be handled elsewhere.
- cancelRedirection();
-}
-
-// This is called by ContextMenuController, which is only used in test shell
-// and not Chrome.
-void FrameLoader::goBackOrForward(int distance)
-{
- if (distance == 0)
- return;
-
- Page* page = m_frame->page();
- if (!page)
- return;
- BackForwardList* list = page->backForwardList();
- if (!list)
- return;
-
- HistoryItem* item = list->itemAtIndex(distance);
- if (!item) {
- if (distance > 0) {
- int forwardListCount = list->forwardListCount();
- if (forwardListCount > 0)
- item = list->itemAtIndex(forwardListCount);
- } else {
- int backListCount = list->backListCount();
- if (backListCount > 0)
- item = list->itemAtIndex(-backListCount);
- }
- }
-
- ASSERT(item); // we should not reach this line with an empty back/forward list
- if (item)
- page->goToItem(item, FrameLoadTypeIndexedBackForward);
-}
-
-void FrameLoader::goToHistoryItem(HistoryItem* item)
-{
- Page* page = m_frame->page();
- if (!page)
- return;
-
- page->goToItem(item, FrameLoadTypeIndexedBackForward);
-}
-
-void FrameLoader::redirectionTimerFired(Timer<FrameLoader>*)
-{
- ASSERT(m_frame->page());
-
- OwnPtr<ScheduledRedirection> redirection(m_scheduledRedirection.release());
-
- switch (redirection->type) {
- case ScheduledRedirection::redirection:
- case ScheduledRedirection::locationChange:
- case ScheduledRedirection::locationChangeDuringLoad:
- changeLocation(redirection->url, redirection->referrer,
- redirection->lockHistory, redirection->wasUserGesture);
- return;
- case ScheduledRedirection::reload:
- urlSelected(m_URL, "", 0, false, false);
- return;
- case ScheduledRedirection::historyNavigation:
- goToHistoryItem(redirection->historyItem.get());
- return;
- }
-
- ASSERT_NOT_REACHED();
-}
-
-/*
- In the case of saving state about a page with frames, we store a tree of items that mirrors the frame tree.
- The item that was the target of the user's navigation is designated as the "targetItem".
- When this method is called with doClip=YES we're able to create the whole tree except for the target's children,
- which will be loaded in the future. That part of the tree will be filled out as the child loads are committed.
-*/
-void FrameLoader::loadURLIntoChildFrame(const KURL& url, const String& referer, Frame* childFrame)
-{
- ASSERT(childFrame);
- HistoryItem* parentItem = currentHistoryItem();
- FrameLoadType loadType = this->loadType();
- FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedHistory;
-
- KURL workingURL = url;
-
- // If we're moving in the backforward list, we might want to replace the content
- // of this child frame with whatever was there at that point.
- // Reload will maintain the frame contents, LoadSame will not.
- if (parentItem && parentItem->children().size() &&
- (isBackForwardLoadType(loadType) || loadType == FrameLoadTypeReloadAllowingStaleData))
- {
- HistoryItem* childItem = parentItem->childItemWithName(childFrame->tree()->name());
- if (childItem) {
- // Use the original URL to ensure we get all the side-effects, such as
- // onLoad handlers, of any redirects that happened. An example of where
- // this is needed is Radar 3213556.
- workingURL = KURL(childItem->originalURLString());
- // These behaviors implied by these loadTypes should apply to the child frames
- childLoadType = loadType;
-
- if (isBackForwardLoadType(loadType)) {
- // For back/forward, remember this item so we can traverse any child items as child frames load
- childFrame->loader()->setProvisionalHistoryItem(childItem);
- } else {
- // For reload, just reinstall the current item, since a new child frame was created but we won't be creating a new BF item
- childFrame->loader()->setCurrentHistoryItem(childItem);
- }
- }
- }
-
- RefPtr<Archive> subframeArchive = activeDocumentLoader()->popArchiveForSubframe(childFrame->tree()->name());
-
- if (subframeArchive)
- childFrame->loader()->loadArchive(subframeArchive.release());
- else
- childFrame->loader()->loadURL(workingURL, referer, String(), childLoadType, 0, 0);
-}
-
-void FrameLoader::loadArchive(PassRefPtr<Archive> prpArchive)
-{
- RefPtr<Archive> archive = prpArchive;
-
- ArchiveResource* mainResource = archive->mainResource();
- ASSERT(mainResource);
- if (!mainResource)
- return;
-
- SubstituteData substituteData(mainResource->data(), mainResource->mimeType(), mainResource->textEncoding(), KURL());
-
- ResourceRequest request(mainResource->url());
-#if PLATFORM(MAC)
- request.applyWebArchiveHackForMail();
-#endif
-
- RefPtr<DocumentLoader> documentLoader = m_client->createDocumentLoader(request, substituteData);
- documentLoader->addAllArchiveResources(archive.get());
- load(documentLoader.get());
-}
-
-String FrameLoader::encoding() const
-{
- if (m_encodingWasChosenByUser && !m_encoding.isEmpty())
- return m_encoding;
- if (m_decoder && m_decoder->encoding().isValid())
- return m_decoder->encoding().name();
- Settings* settings = m_frame->settings();
- return settings ? settings->defaultTextEncodingName() : String();
-}
-
-bool FrameLoader::gotoAnchor(const String& name)
-{
- ASSERT(m_frame->document());
-
- if (!m_frame->document()->haveStylesheetsLoaded()) {
- m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true);
- return false;
- }
-
- m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false);
-
- Node* anchorNode = m_frame->document()->getElementById(AtomicString(name));
- if (!anchorNode && !name.isEmpty())
- anchorNode = m_frame->document()->anchors()->namedItem(name, !m_frame->document()->inCompatMode());
-
-#if ENABLE(SVG)
- if (m_frame->document()->isSVGDocument()) {
- if (name.startsWith("xpointer(")) {
- // We need to parse the xpointer reference here
- } else if (name.startsWith("svgView(")) {
- RefPtr<SVGSVGElement> svg = static_cast<SVGDocument*>(m_frame->document())->rootElement();
- if (!svg->currentView()->parseViewSpec(name))
- return false;
- svg->setUseCurrentView(true);
- } else {
- if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) {
- RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0;
- if (viewElement.get()) {
- RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(SVGLocatable::nearestViewportElement(viewElement.get()));
- svg->inheritViewAttributes(viewElement.get());
- }
- }
- }
- // FIXME: need to decide which <svg> to focus on, and zoom to that one
- // FIXME: need to actually "highlight" the viewTarget(s)
- }
-#endif
-
- m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target.
-
- // Implement the rule that "" and "top" both mean top of page as in other browsers.
- if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
- return false;
-
- // We need to update the layout before scrolling, otherwise we could
- // really mess things up if an anchor scroll comes at a bad moment.
- if (m_frame->document()) {
- m_frame->document()->updateRendering();
- // Only do a layout if changes have occurred that make it necessary.
- if (m_frame->view() && m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())
- m_frame->view()->layout();
- }
-
- // Scroll nested layers and frames to reveal the anchor.
- // Align to the top and to the closest side (this matches other browsers).
- RenderObject* renderer;
- IntRect rect;
- if (!anchorNode)
- renderer = m_frame->document()->renderer(); // top of document
- else {
- renderer = anchorNode->renderer();
- rect = anchorNode->getRect();
- }
- if (renderer)
- renderer->enclosingLayer()->scrollRectToVisible(rect, true, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignTopAlways);
-
- return true;
-}
-
-bool FrameLoader::requestObject(RenderPart* renderer, const String& url, const AtomicString& frameName,
- const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues)
-{
- if (url.isEmpty() && mimeType.isEmpty())
- return false;
-
-#if USE(LOW_BANDWIDTH_DISPLAY)
- // don't care object during low bandwidth display
- if (frame()->document()->inLowBandwidthDisplay()) {
- m_needToSwitchOutLowBandwidthDisplay = true;
- return false;
- }
-#endif
-
- KURL completedURL;
- if (!url.isEmpty())
- completedURL = completeURL(url);
-
- bool useFallback;
- if (shouldUsePlugin(completedURL, mimeType, renderer->hasFallbackContent(), useFallback)) {
- Settings* settings = m_frame->settings();
- if (!settings || !settings->arePluginsEnabled() ||
- (!settings->isJavaEnabled() && MIMETypeRegistry::isJavaAppletMIMEType(mimeType)))
- return false;
- return loadPlugin(renderer, completedURL, mimeType, paramNames, paramValues, useFallback);
- }
-
- ASSERT(renderer->node()->hasTagName(objectTag) || renderer->node()->hasTagName(embedTag));
- HTMLPlugInElement* element = static_cast<HTMLPlugInElement*>(renderer->node());
-
- // FIXME: OK to always make a new frame? When does the old frame get removed?
- return loadSubframe(element, completedURL, frameName, m_outgoingReferrer);
-}
-
-bool FrameLoader::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback)
-{
- if (m_frame->page() && (mimeType == "image/tiff" || mimeType == "image/tif" || mimeType == "image/x-tiff")) {
- String pluginName = m_frame->page()->pluginData()->pluginNameForMimeType(mimeType);
- if (!pluginName.isEmpty() && !pluginName.contains("QuickTime", false))
- return true;
- }
-
- ObjectContentType objectType = m_client->objectContentType(url, mimeType);
- // If an object's content can't be handled and it has no fallback, let
- // it be handled as a plugin to show the broken plugin icon.
- useFallback = objectType == ObjectContentNone && hasFallback;
- return objectType == ObjectContentNone || objectType == ObjectContentNetscapePlugin || objectType == ObjectContentOtherPlugin;
-}
-
-bool FrameLoader::loadPlugin(RenderPart* renderer, const KURL& url, const String& mimeType,
- const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback)
-{
- Widget* widget = 0;
-
- if (renderer && !useFallback) {
- Element* pluginElement = 0;
- if (renderer->node() && renderer->node()->isElementNode())
- pluginElement = static_cast<Element*>(renderer->node());
-
- if (!canLoad(url, String(), frame()->document())) {
- FrameLoader::reportLocalLoadFailed(m_frame, url.string());
- return false;
- }
-
- widget = m_client->createPlugin(IntSize(renderer->contentWidth(), renderer->contentHeight()),
- pluginElement, url, paramNames, paramValues, mimeType,
- m_frame->document()->isPluginDocument());
- if (widget) {
- renderer->setWidget(widget);
- m_containsPlugIns = true;
- }
- }
-
- return widget != 0;
-}
-
-void FrameLoader::clearRecordedFormValues()
-{
- m_formAboutToBeSubmitted = 0;
- m_formValuesAboutToBeSubmitted.clear();
-}
-
-void FrameLoader::setFormAboutToBeSubmitted(PassRefPtr<HTMLFormElement> element)
-{
- m_formAboutToBeSubmitted = element;
-}
-
-void FrameLoader::recordFormValue(const String& name, const String& value)
-{
- m_formValuesAboutToBeSubmitted.set(name, value);
-}
-
-void FrameLoader::parentCompleted()
-{
- if (m_scheduledRedirection && !m_redirectionTimer.isActive())
- startRedirectionTimer();
-}
-
-String FrameLoader::outgoingReferrer() const
-{
- return m_outgoingReferrer;
-}
-
-Frame* FrameLoader::opener()
-{
- return m_opener;
-}
-
-void FrameLoader::setOpener(Frame* opener)
-{
- if (m_opener)
- m_opener->loader()->m_openedFrames.remove(m_frame);
- if (opener)
- opener->loader()->m_openedFrames.add(m_frame);
- m_opener = opener;
-
- if (m_frame->document()) {
- m_frame->document()->initSecurityContext();
- m_frame->domWindow()->setSecurityOrigin(m_frame->document()->securityOrigin());
- }
-}
-
-bool FrameLoader::openedByDOM() const
-{
- return m_openedByDOM;
-}
-
-void FrameLoader::setOpenedByDOM()
-{
- m_openedByDOM = true;
-}
-
-void FrameLoader::handleFallbackContent()
-{
- HTMLFrameOwnerElement* owner = m_frame->ownerElement();
- if (!owner || !owner->hasTagName(objectTag))
- return;
- static_cast<HTMLObjectElement*>(owner)->renderFallbackContent();
-}
-
-void FrameLoader::provisionalLoadStarted()
-{
- Page* page = m_frame->page();
-
- // this is used to update the current history item
- // in the event of a navigation aytime during loading
- m_navigationDuringLoad = false;
- if (page) {
- Document *document = page->mainFrame()->document();
- m_navigationDuringLoad = !page->mainFrame()->loader()->isComplete() || (document && document->processingLoadEvent());
- }
-
- m_firstLayoutDone = false;
- cancelRedirection(true);
- m_client->provisionalLoadStarted();
-}
-
-bool FrameLoader::userGestureHint()
-{
- Frame* rootFrame = m_frame;
- while (rootFrame->tree()->parent())
- rootFrame = rootFrame->tree()->parent();
-
- if (rootFrame->script()->isEnabled())
- return rootFrame->script()->processingUserGesture();
-
- return true; // If JavaScript is disabled, a user gesture must have initiated the navigation
-}
-
-void FrameLoader::didNotOpenURL(const KURL& url)
-{
- if (m_submittedFormURL == url)
- m_submittedFormURL = KURL();
-}
-
-void FrameLoader::resetMultipleFormSubmissionProtection()
-{
- m_submittedFormURL = KURL();
-}
-
-void FrameLoader::setEncoding(const String& name, bool userChosen)
-{
- if (!m_workingURL.isEmpty())
- receivedFirstData();
- m_encoding = name;
- m_encodingWasChosenByUser = userChosen;
-}
-
-void FrameLoader::addData(const char* bytes, int length)
-{
- ASSERT(m_workingURL.isEmpty());
- ASSERT(m_frame->document());
- ASSERT(m_frame->document()->parsing());
- write(bytes, length);
-}
-
-bool FrameLoader::canCachePage()
-{
- // Cache the page, if possible.
- // Don't write to the cache if in the middle of a redirect, since we will want to
- // store the final page we end up on.
- // No point writing to the cache on a reload or loadSame, since we will just write
- // over it again when we leave that page.
- // FIXME: <rdar://problem/4886592> - We should work out the complexities of caching pages with frames as they
- // are the most interesting pages on the web, and often those that would benefit the most from caching!
- FrameLoadType loadType = this->loadType();
-
- return m_documentLoader
- && m_documentLoader->mainDocumentError().isNull()
- && !m_frame->tree()->childCount()
- && !m_frame->tree()->parent()
- // FIXME: If we ever change this so that pages with plug-ins will be cached,
- // we need to make sure that we don't cache pages that have outstanding NPObjects
- // (objects created by the plug-in). Since there is no way to pause/resume a Netscape plug-in,
- // they would need to be destroyed and then recreated, and there is no way that we can recreate
- // the right NPObjects. See <rdar://problem/5197041> for more information.
- && !m_containsPlugIns
- && !m_URL.protocolIs("https")
- && m_frame->document()
- && !m_frame->document()->hasWindowEventListener(unloadEvent)
-#if ENABLE(DATABASE)
- && !m_frame->document()->hasOpenDatabases()
-#endif
- && m_frame->page()
- && m_frame->page()->backForwardList()->enabled()
- && m_frame->page()->backForwardList()->capacity() > 0
- && m_frame->page()->settings()->usesPageCache()
- && m_currentHistoryItem
- && !isQuickRedirectComing()
- && loadType != FrameLoadTypeReload
- && loadType != FrameLoadTypeReloadAllowingStaleData
- && loadType != FrameLoadTypeSame
- && !m_documentLoader->isLoadingInAPISense()
- && !m_documentLoader->isStopping()
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- // FIXME: We should investigating caching pages that have an associated
- // application cache. <rdar://problem/5917899> tracks that work.
- && !m_documentLoader->applicationCache()
- && !m_documentLoader->candidateApplicationCacheGroup()
-#endif
- ;
-}
-
-void FrameLoader::updatePolicyBaseURL()
-{
- if (m_frame->tree()->parent() && m_frame->tree()->parent()->document())
- setPolicyBaseURL(m_frame->tree()->parent()->document()->policyBaseURL());
- else
- setPolicyBaseURL(m_URL);
-}
-
-void FrameLoader::setPolicyBaseURL(const KURL& url)
-{
- if (m_frame->document())
- m_frame->document()->setPolicyBaseURL(url);
- for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
- child->loader()->setPolicyBaseURL(url);
-}
-
-// This does the same kind of work that didOpenURL does, except it relies on the fact
-// that a higher level already checked that the URLs match and the scrolling is the right thing to do.
-void FrameLoader::scrollToAnchor(const KURL& url)
-{
- m_URL = url;
- updateHistoryForAnchorScroll();
-
- // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor
- m_frame->eventHandler()->stopAutoscrollTimer();
- started();
- gotoAnchor();
-
- // It's important to model this as a load that starts and immediately finishes.
- // Otherwise, the parent frame may think we never finished loading.
- m_isComplete = false;
- checkCompleted();
-}
-
-bool FrameLoader::isComplete() const
-{
- return m_isComplete;
-}
-
-void FrameLoader::scheduleRedirection(ScheduledRedirection* redirection)
-{
- ASSERT(m_frame->page());
-
- stopRedirectionTimer();
- m_scheduledRedirection.set(redirection);
- if (!m_isComplete && redirection->type != ScheduledRedirection::redirection)
- completed();
- if (m_isComplete || redirection->type != ScheduledRedirection::redirection)
- startRedirectionTimer();
-}
-
-void FrameLoader::startRedirectionTimer()
-{
- ASSERT(m_frame->page());
- ASSERT(m_scheduledRedirection);
-
- m_redirectionTimer.stop();
- m_redirectionTimer.startOneShot(m_scheduledRedirection->delay);
-
- switch (m_scheduledRedirection->type) {
- case ScheduledRedirection::redirection:
- case ScheduledRedirection::locationChange:
- case ScheduledRedirection::locationChangeDuringLoad:
- clientRedirected(KURL(m_scheduledRedirection->url),
- m_scheduledRedirection->delay,
- currentTime() + m_redirectionTimer.nextFireInterval(),
- m_scheduledRedirection->lockHistory,
- m_isExecutingJavaScriptFormAction);
- return;
- case ScheduledRedirection::reload:
- case ScheduledRedirection::historyNavigation:
- // Don't report history navigations.
- return;
- }
- ASSERT_NOT_REACHED();
-}
-
-void FrameLoader::stopRedirectionTimer()
-{
- if (!m_redirectionTimer.isActive())
- return;
-
- m_redirectionTimer.stop();
-
- if (m_scheduledRedirection) {
- switch (m_scheduledRedirection->type) {
- case ScheduledRedirection::redirection:
- case ScheduledRedirection::locationChange:
- case ScheduledRedirection::locationChangeDuringLoad:
- clientRedirectCancelledOrFinished(m_cancellingWithLoadInProgress);
- return;
- case ScheduledRedirection::reload:
- case ScheduledRedirection::historyNavigation:
- // Don't report history navigations.
- return;
- }
- ASSERT_NOT_REACHED();
- }
-}
-
-void FrameLoader::completed()
-{
- RefPtr<Frame> protect(m_frame);
- for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
- child->loader()->parentCompleted();
- if (Frame* parent = m_frame->tree()->parent())
- parent->loader()->checkCompleted();
- submitFormAgain();
-}
-
-void FrameLoader::started()
-{
- for (Frame* frame = m_frame; frame; frame = frame->tree()->parent())
- frame->loader()->m_isComplete = false;
-}
-
-bool FrameLoader::containsPlugins() const
-{
- return m_containsPlugIns;
-}
-
-void FrameLoader::prepareForLoadStart()
-{
- if (Page* page = m_frame->page())
- page->progress()->progressStarted(m_frame);
- m_client->dispatchDidStartProvisionalLoad();
-}
-
-void FrameLoader::setupForReplace()
-{
- setState(FrameStateProvisional);
- m_provisionalDocumentLoader = m_documentLoader;
- m_documentLoader = 0;
- detachChildren();
-}
-
-void FrameLoader::setupForReplaceByMIMEType(const String& newMIMEType)
-{
- activeDocumentLoader()->setupForReplaceByMIMEType(newMIMEType);
-}
-
-void FrameLoader::loadFrameRequestWithFormState(const FrameLoadRequest& request, bool lockHistory, Event* event, PassRefPtr<FormState> prpFormState)
-{
- RefPtr<FormState> formState = prpFormState;
- KURL url = request.resourceRequest().url();
-
- String referrer;
- String argsReferrer = request.resourceRequest().httpReferrer();
- if (!argsReferrer.isEmpty())
- referrer = argsReferrer;
- else
- referrer = m_outgoingReferrer;
-
- ASSERT(frame()->document());
- if (url.protocolIs("file")) {
- if (!canLoad(url, String(), frame()->document()) && !canLoad(url, referrer)) {
- FrameLoader::reportLocalLoadFailed(m_frame, url.string());
- return;
- }
- }
-
- if (shouldHideReferrer(url, referrer))
- referrer = String();
-
- Frame* targetFrame = findFrameForNavigation(request.frameName());
-
- if (request.resourceRequest().httpMethod() != "POST") {
- FrameLoadType loadType;
- if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
- loadType = FrameLoadTypeReload;
- else if (lockHistory)
- loadType = FrameLoadTypeRedirectWithLockedHistory;
- else
- loadType = FrameLoadTypeStandard;
-
- loadURL(request.resourceRequest().url(), referrer, request.frameName(), loadType,
- event, formState.release());
- } else
- loadPostRequest(request.resourceRequest(), referrer, request.frameName(), event, formState.release());
-
- if (targetFrame && targetFrame != m_frame)
- if (Page* page = targetFrame->page())
- page->chrome()->focus();
-}
-
-
-void FrameLoader::loadFrameRequestWithFormAndValues(const FrameLoadRequest& request, bool lockHistory, Event* event,
- HTMLFormElement* submitForm, const HashMap<String, String>& formValues)
-{
- RefPtr<FormState> formState;
- if (submitForm && !formValues.isEmpty())
- formState = FormState::create(submitForm, formValues, m_frame);
-
- loadFrameRequestWithFormState(request, lockHistory, event, formState.release());
-}
-
-
-void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const String& frameName, FrameLoadType newLoadType,
- Event* event, PassRefPtr<FormState> prpFormState)
-{
- RefPtr<FormState> formState = prpFormState;
- bool isFormSubmission = formState;
-
- ResourceRequest request(newURL);
- if (!referrer.isEmpty())
- request.setHTTPReferrer(referrer);
- addExtraFieldsToRequest(request, true, event || isFormSubmission);
- if (newLoadType == FrameLoadTypeReload)
- request.setCachePolicy(ReloadIgnoringCacheData);
-
- ASSERT(newLoadType != FrameLoadTypeSame);
-
- NavigationAction action(newURL, newLoadType, isFormSubmission, event);
-
- if (!frameName.isEmpty()) {
- if (Frame* targetFrame = findFrameForNavigation(frameName))
- targetFrame->loader()->loadURL(newURL, referrer, String(), newLoadType, event, formState);
- else
- checkNewWindowPolicy(action, request, formState, frameName);
- return;
- }
-
- RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
-
- bool sameURL = shouldTreatURLAsSameAsCurrent(newURL);
-
- // Make sure to do scroll to anchor processing even if the URL is
- // exactly the same so pages with '#' links and DHTML side effects
- // work properly.
- if (shouldScrollToAnchor(isFormSubmission, newLoadType, newURL)) {
- oldDocumentLoader->setTriggeringAction(action);
- stopPolicyCheck();
- checkNavigationPolicy(request, oldDocumentLoader.get(), formState,
- callContinueFragmentScrollAfterNavigationPolicy, this);
- } else {
- // must grab this now, since this load may stop the previous load and clear this flag
- bool isRedirect = m_quickRedirectComing;
- loadWithNavigationAction(request, action, newLoadType, formState);
- if (isRedirect) {
- m_quickRedirectComing = false;
- if (m_provisionalDocumentLoader)
- m_provisionalDocumentLoader->setIsClientRedirect(true);
- } else if (sameURL)
- // Example of this case are sites that reload the same URL with a different cookie
- // driving the generated content, or a master frame with links that drive a target
- // frame, where the user has clicked on the same link repeatedly.
- // But if the load type is FrameLoadTypeReloadAllowingStaleData, which means the frame
- // is reloaded only because user select one encoding from encoding menu, so we do not
- // change the load type.
- if (m_loadType != FrameLoadTypeReloadAllowingStaleData)
- m_loadType = FrameLoadTypeSame;
- }
-}
-
-void FrameLoader::load(const ResourceRequest& request)
-{
- load(request, SubstituteData());
-}
-
-void FrameLoader::load(const ResourceRequest& request, const SubstituteData& substituteData)
-{
- if (m_inStopAllLoaders)
- return;
-
- // FIXME: is this the right place to reset loadType? Perhaps this should be done after loading is finished or aborted.
- m_loadType = FrameLoadTypeStandard;
- load(m_client->createDocumentLoader(request, substituteData).get());
-}
-
-void FrameLoader::load(const ResourceRequest& request, const String& frameName)
-{
- if (frameName.isEmpty()) {
- load(request);
- return;
- }
-
- Frame* frame = findFrameForNavigation(frameName);
- if (frame) {
- frame->loader()->load(request);
- return;
- }
-
- checkNewWindowPolicy(NavigationAction(request.url(), NavigationTypeOther), request, 0, frameName);
-}
-
-void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const NavigationAction& action, FrameLoadType type, PassRefPtr<FormState> formState)
-{
- RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
-
- loader->setTriggeringAction(action);
- if (m_documentLoader) {
- // if the load type is not FrameLoadTypeReloadAllowingStaleData,
- // which means we will load page by user action, so we need not
- // use original encoding override.
- if (type == FrameLoadTypeReloadAllowingStaleData)
- loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
- else
- loader->setOverrideEncoding(String());
- }
-
- loadWithDocumentLoader(loader.get(), type, formState);
-}
-
-void FrameLoader::load(DocumentLoader* newDocumentLoader)
-{
- ResourceRequest& r = newDocumentLoader->request();
- addExtraFieldsToRequest(r, true, false);
- FrameLoadType type;
-
- if (shouldTreatURLAsSameAsCurrent(newDocumentLoader->originalRequest().url())) {
- r.setCachePolicy(ReloadIgnoringCacheData);
- type = FrameLoadTypeSame;
- } else
- type = FrameLoadTypeStandard;
-
- // Do not use original encoding override since it is not loaded by user
- // selecting encoding.
- if (m_documentLoader)
- newDocumentLoader->setOverrideEncoding(String());
-
- // When we loading alternate content for an unreachable URL that we're
- // visiting in the history list, we treat it as a reload so the history list
- // is appropriately maintained.
- //
- // FIXME: This seems like a dangerous overloading of the meaning of "FrameLoadTypeReload" ...
- // shouldn't a more explicit type of reload be defined, that means roughly
- // "load without affecting history" ?
- if (shouldReloadToHandleUnreachableURL(newDocumentLoader)) {
- ASSERT(type == FrameLoadTypeStandard);
- type = FrameLoadTypeReload;
- }
-
- loadWithDocumentLoader(newDocumentLoader, type, 0);
-}
-
-void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType type, PassRefPtr<FormState> prpFormState)
-{
- ASSERT(m_client->hasWebView());
-
- // Unfortunately the view must be non-nil, this is ultimately due
- // to parser requiring a FrameView. We should fix this dependency.
-
- ASSERT(m_client->hasFrameView());
-
- m_policyLoadType = type;
- RefPtr<FormState> formState = prpFormState;
- bool isFormSubmission = formState;
-
- const KURL& newURL = loader->request().url();
-
- if (shouldScrollToAnchor(isFormSubmission, m_policyLoadType, newURL)) {
- RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
- NavigationAction action(newURL, m_policyLoadType, isFormSubmission);
-
- oldDocumentLoader->setTriggeringAction(action);
- stopPolicyCheck();
- checkNavigationPolicy(loader->request(), oldDocumentLoader.get(), formState,
- callContinueFragmentScrollAfterNavigationPolicy, this);
- } else {
- if (Frame* parent = m_frame->tree()->parent()) {
- if (type == FrameLoadTypeReloadAllowingStaleData)
- loader->setOverrideEncoding(parent->loader()->documentLoader()->overrideEncoding());
- else
- loader->setOverrideEncoding(String());
- }
-
- stopPolicyCheck();
- setPolicyDocumentLoader(loader);
-
- checkNavigationPolicy(loader->request(), loader, formState,
- callContinueLoadAfterNavigationPolicy, this);
- }
-}
-
-bool FrameLoader::canLoad(const KURL& url, const String& referrer, const Document* doc)
-{
- // We can always load any URL that isn't considered local (e.g. http URLs)
- if (!shouldTreatURLAsLocal(url.string()))
- return true;
-
- // If we were provided a document, we let its local file policy dictate the result,
- // otherwise we allow local loads only if the supplied referrer is also local.
- if (doc)
- return doc->securityOrigin()->canLoadLocalResources();
- else if (!referrer.isEmpty())
- return shouldTreatURLAsLocal(referrer);
- else
- return false;
-}
-
-void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url)
-{
- ASSERT(!url.isEmpty());
- if (!frame)
- return;
-
- frame->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, "Not allowed to load local resource: " + url, 0, String());
-}
-
-bool FrameLoader::shouldHideReferrer(const KURL& url, const String& referrer)
-{
- bool referrerIsSecureURL = protocolIs(referrer, "https");
- bool referrerIsWebURL = referrerIsSecureURL || protocolIs(referrer, "http");
-
- if (!referrerIsWebURL)
- return true;
-
- if (!referrerIsSecureURL)
- return false;
-
- bool URLIsSecureURL = url.protocolIs("https");
-
- return !URLIsSecureURL;
-}
-
-const ResourceRequest& FrameLoader::initialRequest() const
-{
- return activeDocumentLoader()->originalRequest();
-}
-
-void FrameLoader::receivedData(const char* data, int length)
-{
- activeDocumentLoader()->receivedData(data, length);
-}
-
-void FrameLoader::handleUnimplementablePolicy(const ResourceError& error)
-{
- m_delegateIsHandlingUnimplementablePolicy = true;
- m_client->dispatchUnableToImplementPolicy(error);
- m_delegateIsHandlingUnimplementablePolicy = false;
-}
-
-void FrameLoader::cannotShowMIMEType(const ResourceResponse& response)
-{
- handleUnimplementablePolicy(m_client->cannotShowMIMETypeError(response));
-}
-
-ResourceError FrameLoader::interruptionForPolicyChangeError(const ResourceRequest& request)
-{
- return m_client->interruptForPolicyChangeError(request);
-}
-
-void FrameLoader::checkNavigationPolicy(const ResourceRequest& newRequest, NavigationPolicyDecisionFunction function, void* argument)
-{
- checkNavigationPolicy(newRequest, activeDocumentLoader(), 0, function, argument);
-}
-
-void FrameLoader::checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction function, void* argument)
-{
- ASSERT(activeDocumentLoader());
-
- // Always show content with valid substitute data.
- if (activeDocumentLoader()->substituteData().isValid()) {
- function(argument, PolicyUse);
- return;
- }
-
-#if ENABLE(FTPDIR)
- // Respect the hidden FTP Directory Listing pref so it can be tested even if the policy delegate might otherwise disallow it
- Settings* settings = m_frame->settings();
- if (settings && settings->forceFTPDirectoryListings() && MIMEType == "application/x-ftp-directory") {
- function(argument, PolicyUse);
- return;
- }
-#endif
-
- m_policyCheck.set(function, argument);
- m_client->dispatchDecidePolicyForMIMEType(&FrameLoader::continueAfterContentPolicy,
- MIMEType, activeDocumentLoader()->request());
-}
-
-bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader)
-{
- KURL unreachableURL = docLoader->unreachableURL();
-
- if (unreachableURL.isEmpty())
- return false;
-
- if (!isBackForwardLoadType(m_policyLoadType))
- return false;
-
- // We only treat unreachableURLs specially during the delegate callbacks
- // for provisional load errors and navigation policy decisions. The former
- // case handles well-formed URLs that can't be loaded, and the latter
- // case handles malformed URLs and unknown schemes. Loading alternate content
- // at other times behaves like a standard load.
- DocumentLoader* compareDocumentLoader = 0;
- if (m_delegateIsDecidingNavigationPolicy || m_delegateIsHandlingUnimplementablePolicy)
- compareDocumentLoader = m_policyDocumentLoader.get();
- else if (m_delegateIsHandlingProvisionalLoadError)
- compareDocumentLoader = m_provisionalDocumentLoader.get();
-
- return compareDocumentLoader && unreachableURL == compareDocumentLoader->request().url();
-}
-
-void FrameLoader::reloadAllowingStaleData(const String& encoding)
-{
- if (!m_documentLoader)
- return;
-
- ResourceRequest request = m_documentLoader->request();
- KURL unreachableURL = m_documentLoader->unreachableURL();
- if (!unreachableURL.isEmpty())
- request.setURL(unreachableURL);
-
- request.setCachePolicy(ReturnCacheDataElseLoad);
-
- RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
- setPolicyDocumentLoader(loader.get());
-
- loader->setOverrideEncoding(encoding);
-
- loadWithDocumentLoader(loader.get(), FrameLoadTypeReloadAllowingStaleData, 0);
-}
-
-void FrameLoader::reload()
-{
- if (!m_documentLoader)
- return;
-
- ResourceRequest& initialRequest = m_documentLoader->request();
-
- // If a window is created by javascript, its main frame can have an empty but non-nil URL.
- // Reloading in this case will lose the current contents (see 4151001).
- if (initialRequest.url().isEmpty())
- return;
-
- // Replace error-page URL with the URL we were trying to reach.
- KURL unreachableURL = m_documentLoader->unreachableURL();
- if (!unreachableURL.isEmpty())
- initialRequest.setURL(unreachableURL);
-
- // Create a new document loader for the reload, this will become m_documentLoader eventually,
- // but first it has to be the "policy" document loader, and then the "provisional" document loader.
- RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(initialRequest, SubstituteData());
-
- ResourceRequest& request = loader->request();
-
- request.setCachePolicy(ReloadIgnoringCacheData);
- request.setHTTPHeaderField("Cache-Control", "max-age=0");
-
- // If we're about to re-post, set up action so the application can warn the user.
- if (request.httpMethod() == "POST")
- loader->setTriggeringAction(NavigationAction(request.url(), NavigationTypeFormResubmitted));
-
- loader->setOverrideEncoding(String());
-
- loadWithDocumentLoader(loader.get(), FrameLoadTypeReload, 0);
-}
-
-bool FrameLoader::shouldAllowNavigation(Frame* targetFrame) const
-{
- // The navigation change is safe if the active frame is:
- // - in the same security origin as the target or one of the target's ancestors
- // Or the target frame is:
- // - a top-level frame in the frame hierarchy
-
- if (!targetFrame)
- return true;
-
- if (m_frame == targetFrame)
- return true;
-
- if (!targetFrame->tree()->parent())
- return true;
-
- Document* activeDocument = m_frame->document();
- ASSERT(activeDocument);
- const SecurityOrigin* activeSecurityOrigin = activeDocument->securityOrigin();
- for (Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree()->parent()) {
- Document* ancestorDocument = ancestorFrame->document();
- if (!ancestorDocument)
- return true;
-
- const SecurityOrigin* ancestorSecurityOrigin = ancestorDocument->securityOrigin();
- if (activeSecurityOrigin->canAccess(ancestorSecurityOrigin))
- return true;
- }
-
- Settings* settings = targetFrame->settings();
- if (settings && !settings->privateBrowsingEnabled()) {
- Document* targetDocument = targetFrame->document();
- // FIXME: this error message should contain more specifics of why the navigation change is not allowed.
- String message = String::format("Unsafe JavaScript attempt to initiate a navigation change for frame with URL %s from frame with URL %s.\n",
- targetDocument->url().string().utf8().data(), activeDocument->url().string().utf8().data());
-
- // FIXME: should we print to the console of the activeFrame as well?
- targetFrame->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, message, 1, String());
- }
-
- return false;
-}
-
-void FrameLoader::stopLoadingSubframes()
-{
- for (RefPtr<Frame> child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
- child->loader()->stopAllLoaders();
-}
-
-void FrameLoader::stopAllLoaders()
-{
- // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
- if (m_inStopAllLoaders)
- return;
-
- m_inStopAllLoaders = true;
-
- stopPolicyCheck();
-
- stopLoadingSubframes();
- if (m_provisionalDocumentLoader)
- m_provisionalDocumentLoader->stopLoading();
- if (m_documentLoader)
- m_documentLoader->stopLoading();
-
- setProvisionalDocumentLoader(0);
-
- if (m_documentLoader)
- m_documentLoader->clearArchiveResources();
-
- m_inStopAllLoaders = false;
-}
-
-void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
-{
- stopAllLoaders();
-
- if (deferCheckLoadComplete)
- scheduleCheckLoadComplete();
- else if (m_frame->page())
- checkLoadComplete();
-}
-
-DocumentLoader* FrameLoader::activeDocumentLoader() const
-{
- if (m_state == FrameStateProvisional)
- return m_provisionalDocumentLoader.get();
- return m_documentLoader.get();
-}
-
-bool FrameLoader::isLoading() const
-{
- DocumentLoader* docLoader = activeDocumentLoader();
- if (!docLoader)
- return false;
- return docLoader->isLoadingMainResource() || docLoader->isLoadingSubresources() || docLoader->isLoadingPlugIns();
-}
-
-bool FrameLoader::frameHasLoaded() const
-{
- return m_committedFirstRealDocumentLoad || (m_provisionalDocumentLoader && !m_creatingInitialEmptyDocument);
-}
-
-void FrameLoader::setDocumentLoader(DocumentLoader* loader)
-{
- if (!loader && !m_documentLoader)
- return;
-
- ASSERT(loader != m_documentLoader);
- ASSERT(!loader || loader->frameLoader() == this);
-
- m_client->prepareForDataSourceReplacement();
- detachChildren();
- if (m_documentLoader)
- m_documentLoader->detachFromFrame();
-
- m_documentLoader = loader;
-}
-
-DocumentLoader* FrameLoader::documentLoader() const
-{
- return m_documentLoader.get();
-}
-
-void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
-{
- if (m_policyDocumentLoader == loader)
- return;
-
- ASSERT(m_frame);
- if (loader)
- loader->setFrame(m_frame);
- if (m_policyDocumentLoader
- && m_policyDocumentLoader != m_provisionalDocumentLoader
- && m_policyDocumentLoader != m_documentLoader)
- m_policyDocumentLoader->detachFromFrame();
-
- m_policyDocumentLoader = loader;
-}
-
-DocumentLoader* FrameLoader::policyDocumentLoader() const
-{
- return m_policyDocumentLoader.get();
-}
-
-DocumentLoader* FrameLoader::provisionalDocumentLoader() const
-{
- return m_provisionalDocumentLoader.get();
-}
-
-DocumentLoader* FrameLoader::policyDocumentLoader()
-{
- return m_policyDocumentLoader.get();
-}
-
-void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
-{
- ASSERT(!loader || !m_provisionalDocumentLoader);
- ASSERT(!loader || loader->frameLoader() == this);
-
- if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
- m_provisionalDocumentLoader->detachFromFrame();
-
- m_provisionalDocumentLoader = loader;
-}
-
-FrameState FrameLoader::state() const
-{
- return m_state;
-}
-
-double FrameLoader::timeOfLastCompletedLoad()
-{
- return storedTimeOfLastCompletedLoad;
-}
-
-void FrameLoader::setState(FrameState newState)
-{
- m_state = newState;
-
- if (newState == FrameStateProvisional)
- provisionalLoadStarted();
- else if (newState == FrameStateComplete) {
- frameLoadCompleted();
- storedTimeOfLastCompletedLoad = currentTime();
- if (m_documentLoader)
- m_documentLoader->stopRecordingResponses();
- }
-}
-
-void FrameLoader::clearProvisionalLoad()
-{
- setProvisionalDocumentLoader(0);
- if (Page* page = m_frame->page())
- page->progress()->progressCompleted(m_frame);
- setState(FrameStateComplete);
-}
-
-void FrameLoader::markLoadComplete()
-{
- setState(FrameStateComplete);
-}
-
-void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage)
-{
- RefPtr<CachedPage> cachedPage = prpCachedPage;
- RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
-
- // Check to see if we need to cache the page we are navigating away from into the back/forward cache.
- // We are doing this here because we know for sure that a new page is about to be loaded.
- if (canCachePage() && m_client->canCachePage() && !m_currentHistoryItem->isInPageCache())
- cachePageForHistoryItem(m_currentHistoryItem.get());
-
- if (m_loadType != FrameLoadTypeReplace)
- closeOldDataSources();
-
- if (!cachedPage && !m_creatingInitialEmptyDocument)
- m_client->makeRepresentation(pdl.get());
-
- transitionToCommitted(cachedPage);
-
- // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's
- // status has changed, if there was a redirect. The frame load delegate may have saved some state about
- // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are
- // just about to commit a new page, there cannot possibly be a pending redirect at this point.
- if (m_sentRedirectNotification)
- clientRedirectCancelledOrFinished(false);
-
- if (cachedPage && cachedPage->document()) {
- open(*cachedPage);
- cachedPage->clear();
- } else {
- KURL url = pdl->substituteData().responseURL();
- if (url.isEmpty())
- url = pdl->url();
- if (url.isEmpty())
- url = pdl->responseURL();
- if (url.isEmpty())
- url = blankURL();
-
- didOpenURL(url);
- }
- opened();
-}
-
-void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage)
-{
- ASSERT(m_client->hasWebView());
- ASSERT(m_state == FrameStateProvisional);
-
- if (m_state != FrameStateProvisional)
- return;
-
- m_client->setCopiesOnScroll();
- updateHistoryForCommit();
-
- // The call to closeURL() invokes the unload event handler, which can execute arbitrary
- // JavaScript. If the script initiates a new load, we need to abandon the current load,
- // or the two will stomp each other.
- DocumentLoader* pdl = m_provisionalDocumentLoader.get();
- if (m_documentLoader)
- closeURL();
- if (pdl != m_provisionalDocumentLoader)
- return;
-
- // Nothing else can interupt this commit - set the Provisional->Committed transition in stone
- if (m_documentLoader)
- m_documentLoader->stopLoadingSubresources();
- if (m_documentLoader)
- m_documentLoader->stopLoadingPlugIns();
-
- setDocumentLoader(m_provisionalDocumentLoader.get());
- setProvisionalDocumentLoader(0);
- setState(FrameStateCommittedPage);
-
- // Handle adding the URL to the back/forward list.
- DocumentLoader* dl = m_documentLoader.get();
- String ptitle = dl->title();
-
- switch (m_loadType) {
- case FrameLoadTypeForward:
- case FrameLoadTypeBack:
- case FrameLoadTypeIndexedBackForward:
- if (Page* page = m_frame->page())
- if (page->backForwardList()) {
- updateHistoryForBackForwardNavigation();
-
- // Create a document view for this document, or used the cached view.
- if (cachedPage) {
- DocumentLoader* cachedDocumentLoader = cachedPage->documentLoader();
- ASSERT(cachedDocumentLoader);
- cachedDocumentLoader->setFrame(m_frame);
- m_client->transitionToCommittedFromCachedPage(cachedPage.get());
-
- } else
- m_client->transitionToCommittedForNewPage();
- }
- break;
-
- case FrameLoadTypeReload:
- case FrameLoadTypeSame:
- case FrameLoadTypeReplace:
- updateHistoryForReload();
- m_client->transitionToCommittedForNewPage();
- break;
-
- // FIXME - just get rid of this case, and merge FrameLoadTypeReloadAllowingStaleData with the above case
- case FrameLoadTypeReloadAllowingStaleData:
- m_client->transitionToCommittedForNewPage();
- break;
-
- case FrameLoadTypeStandard:
- updateHistoryForStandardLoad();
-#ifndef BUILDING_ON_TIGER
- // This code was originally added for a Leopard performance imporvement. We decided to
- // ifdef it to fix correctness issues on Tiger documented in <rdar://problem/5441823>.
- if (m_frame->view())
- m_frame->view()->suppressScrollbars(true);
-#endif
- m_client->transitionToCommittedForNewPage();
- break;
-
- case FrameLoadTypeRedirectWithLockedHistory:
- updateHistoryForRedirectWithLockedHistory();
- m_client->transitionToCommittedForNewPage();
- break;
-
- // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
- // An exception should be thrown if we're in the FrameLoadTypeUninitialized state.
- default:
- ASSERT_NOT_REACHED();
- }
-
- m_responseMIMEType = dl->responseMIMEType();
-
- // Tell the client we've committed this URL.
- ASSERT(m_client->hasFrameView());
-
- if (m_creatingInitialEmptyDocument)
- return;
-
- m_committedFirstRealDocumentLoad = true;
-
- // For non-cached HTML pages, these methods are called in FrameLoader::begin.
- if (cachedPage || !m_client->hasHTMLView()) {
- dispatchDidCommitLoad();
-
- // If we have a title let the WebView know about it.
- if (!ptitle.isNull())
- m_client->dispatchDidReceiveTitle(ptitle);
- }
-}
-
-void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress)
-{
- // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
- // the redirect succeeded. We should either rename this API, or add a new method, like
- // -webView:didFinishClientRedirectForFrame:
- m_client->dispatchDidCancelClientRedirect();
-
- if (!cancelWithLoadInProgress)
- m_quickRedirectComing = false;
-
- m_sentRedirectNotification = false;
-}
-
-void FrameLoader::clientRedirected(const KURL& url, double seconds, double fireDate, bool lockHistory, bool isJavaScriptFormAction)
-{
- m_client->dispatchWillPerformClientRedirect(url, seconds, fireDate);
-
- // Remember that we sent a redirect notification to the frame load delegate so that when we commit
- // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
- m_sentRedirectNotification = true;
-
- // If a "quick" redirect comes in an, we set a special mode so we treat the next
- // load as part of the same navigation. If we don't have a document loader, we have
- // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
- m_quickRedirectComing = lockHistory && m_documentLoader && !isJavaScriptFormAction;
-}
-
-bool FrameLoader::shouldReload(const KURL& currentURL, const KURL& destinationURL)
-{
- // This function implements the rule: "Don't reload if navigating by fragment within
- // the same URL, but do reload if going to a new URL or to the same URL with no
- // fragment identifier at all."
- if (!destinationURL.hasRef())
- return true;
- return !equalIgnoringRef(currentURL, destinationURL);
-}
-
-void FrameLoader::closeOldDataSources()
-{
- // FIXME: Is it important for this traversal to be postorder instead of preorder?
- // If so, add helpers for postorder traversal, and use them. If not, then lets not
- // use a recursive algorithm here.
- for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
- child->loader()->closeOldDataSources();
-
- if (m_documentLoader)
- m_client->dispatchWillClose();
-
- m_client->setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
-}
-
-void FrameLoader::open(CachedPage& cachedPage)
-{
- ASSERT(m_frame->page());
- ASSERT(m_frame->page()->mainFrame() == m_frame);
-
- cancelRedirection();
-
- // We still have to close the previous part page.
- closeURL();
-
- m_isComplete = false;
-
- // Don't re-emit the load event.
- m_didCallImplicitClose = true;
-
- // Delete old status bar messages (if it _was_ activated on last URL).
- if (m_frame->script()->isEnabled()) {
- m_frame->setJSStatusBarText(String());
- m_frame->setJSDefaultStatusBarText(String());
- }
-
- KURL url = cachedPage.url();
-
- if ((url.protocolIs("http") || url.protocolIs("https")) && !url.host().isEmpty() && url.path().isEmpty())
- url.setPath("/");
-
- m_URL = url;
- m_workingURL = url;
-
- started();
-
- clear();
-
- Document* document = cachedPage.document();
- ASSERT(document);
- document->setInPageCache(false);
-
- m_needsClear = true;
- m_isComplete = false;
- m_didCallImplicitClose = false;
- m_outgoingReferrer = url.string();
-
- FrameView* view = cachedPage.view();
- if (view)
- view->setWasScrolledByUser(false);
- m_frame->setView(view);
-
- m_frame->setDocument(document);
- m_frame->domWindow()->setURL(document->url());
- m_frame->domWindow()->setSecurityOrigin(document->securityOrigin());
-
- m_decoder = document->decoder();
-
- updatePolicyBaseURL();
-
- cachedPage.restore(m_frame->page());
-
- checkCompleted();
-}
-
-bool FrameLoader::isStopping() const
-{
- return activeDocumentLoader()->isStopping();
-}
-
-void FrameLoader::finishedLoading()
-{
- // Retain because the stop may release the last reference to it.
- RefPtr<Frame> protect(m_frame);
-
- RefPtr<DocumentLoader> dl = activeDocumentLoader();
- dl->finishedLoading();
- if (!dl->mainDocumentError().isNull() || !dl->frameLoader())
- return;
- dl->setPrimaryLoadComplete(true);
- m_client->dispatchDidLoadMainResource(dl.get());
- checkLoadComplete();
-}
-
-bool FrameLoader::isHostedByObjectElement() const
-{
- HTMLFrameOwnerElement* owner = m_frame->ownerElement();
- return owner && owner->hasTagName(objectTag);
-}
-
-bool FrameLoader::isLoadingMainFrame() const
-{
- Page* page = m_frame->page();
- return page && m_frame == page->mainFrame();
-}
-
-bool FrameLoader::canShowMIMEType(const String& MIMEType) const
-{
- return m_client->canShowMIMEType(MIMEType);
-}
-
-bool FrameLoader::representationExistsForURLScheme(const String& URLScheme)
-{
- return m_client->representationExistsForURLScheme(URLScheme);
-}
-
-String FrameLoader::generatedMIMETypeForURLScheme(const String& URLScheme)
-{
- return m_client->generatedMIMETypeForURLScheme(URLScheme);
-}
-
-void FrameLoader::cancelContentPolicyCheck()
-{
- m_client->cancelPolicyCheck();
- m_policyCheck.clear();
-}
-
-void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame()
-{
- m_client->dispatchDidReceiveServerRedirectForProvisionalLoad();
-}
-
-void FrameLoader::finishedLoadingDocument(DocumentLoader* loader)
-{
-#if PLATFORM(WIN)
- if (m_creatingInitialEmptyDocument)
- return;
-#endif
-
- // If loading a webarchive, run through webarchive machinery
- const String& responseMIMEType = loader->responseMIMEType();
-
- // FIXME: Mac's FrameLoaderClient::finishedLoading() method does work that is required even with Archive loads
- // so we still need to call it. Other platforms should only call finishLoading for non-archive loads
- // That work should be factored out so this #ifdef can be removed
-#if PLATFORM(MAC)
- m_client->finishedLoading(loader);
- if (!ArchiveFactory::isArchiveMimeType(responseMIMEType))
- return;
-#else
- if (!ArchiveFactory::isArchiveMimeType(responseMIMEType)) {
- m_client->finishedLoading(loader);
- return;
- }
-#endif
-
- RefPtr<Archive> archive(ArchiveFactory::create(loader->mainResourceData().get(), responseMIMEType));
- if (!archive)
- return;
-
- loader->addAllArchiveResources(archive.get());
-
- ArchiveResource* mainResource = archive->mainResource();
- loader->setParsedArchiveData(mainResource->data());
- continueLoadWithData(mainResource->data(), mainResource->mimeType(), mainResource->textEncoding(), mainResource->url());
-}
-
-bool FrameLoader::isReplacing() const
-{
- return m_loadType == FrameLoadTypeReplace;
-}
-
-void FrameLoader::setReplacing()
-{
- m_loadType = FrameLoadTypeReplace;
-}
-
-void FrameLoader::revertToProvisional(DocumentLoader* loader)
-{
- m_client->revertToProvisionalState(loader);
-}
-
-bool FrameLoader::subframeIsLoading() const
-{
- // It's most likely that the last added frame is the last to load so we walk backwards.
- for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling()) {
- FrameLoader* childLoader = child->loader();
- DocumentLoader* documentLoader = childLoader->documentLoader();
- if (documentLoader && documentLoader->isLoadingInAPISense())
- return true;
- documentLoader = childLoader->provisionalDocumentLoader();
- if (documentLoader && documentLoader->isLoadingInAPISense())
- return true;
- }
- return false;
-}
-
-void FrameLoader::willChangeTitle(DocumentLoader* loader)
-{
- m_client->willChangeTitle(loader);
-}
-
-FrameLoadType FrameLoader::loadType() const
-{
- return m_loadType;
-}
-
-void FrameLoader::stopPolicyCheck()
-{
- m_client->cancelPolicyCheck();
- PolicyCheck check = m_policyCheck;
- m_policyCheck.clear();
- check.cancel();
-}
-
-void FrameLoader::checkLoadCompleteForThisFrame()
-{
- ASSERT(m_client->hasWebView());
-
- switch (m_state) {
- case FrameStateProvisional: {
- if (m_delegateIsHandlingProvisionalLoadError)
- return;
-
- RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
- if (!pdl)
- return;
-
- // If we've received any errors we may be stuck in the provisional state and actually complete.
- const ResourceError& error = pdl->mainDocumentError();
- if (error.isNull())
- return;
-
- // Check all children first.
- RefPtr<HistoryItem> item;
- if (Page* page = m_frame->page())
- if (isBackForwardLoadType(loadType()) && m_frame == page->mainFrame())
- item = m_currentHistoryItem;
-
- bool shouldReset = true;
- if (!pdl->isLoadingInAPISense()) {
- m_delegateIsHandlingProvisionalLoadError = true;
- m_client->dispatchDidFailProvisionalLoad(error);
- m_delegateIsHandlingProvisionalLoadError = false;
-
- // FIXME: can stopping loading here possibly have any effect, if isLoading is false,
- // which it must be to be in this branch of the if? And is it OK to just do a full-on
- // stopAllLoaders instead of stopLoadingSubframes?
- stopLoadingSubframes();
- pdl->stopLoading();
-
- // Finish resetting the load state, but only if another load hasn't been started by the
- // delegate callback.
- if (pdl == m_provisionalDocumentLoader)
- clearProvisionalLoad();
- else if (m_provisionalDocumentLoader) {
- KURL unreachableURL = m_provisionalDocumentLoader->unreachableURL();
- if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url())
- shouldReset = false;
- }
- }
- if (shouldReset && item)
- if (Page* page = m_frame->page())
- page->backForwardList()->goToItem(item.get());
- return;
- }
-
- case FrameStateCommittedPage: {
- DocumentLoader* dl = m_documentLoader.get();
- if (!dl || dl->isLoadingInAPISense())
- return;
-
- markLoadComplete();
-
- // FIXME: Is this subsequent work important if we already navigated away?
- // Maybe there are bugs because of that, or extra work we can skip because
- // the new page is ready.
-
- m_client->forceLayoutForNonHTML();
-
- // If the user had a scroll point, scroll to it, overriding the anchor point if any.
- if (Page* page = m_frame->page())
- if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload) && page->backForwardList())
- restoreScrollPositionAndViewState();
-
- if (m_creatingInitialEmptyDocument || !m_committedFirstRealDocumentLoad)
- return;
-
- const ResourceError& error = dl->mainDocumentError();
-#ifndef NDEBUG
- m_didDispatchDidCommitLoad = false;
-#endif
- if (!error.isNull())
- m_client->dispatchDidFailLoad(error);
- else
- m_client->dispatchDidFinishLoad();
-
- if (Page* page = m_frame->page())
- page->progress()->progressCompleted(m_frame);
- return;
- }
-
- case FrameStateComplete:
- // Even if already complete, we might have set a previous item on a frame that
- // didn't do any data loading on the past transaction. Make sure to clear these out.
- m_client->frameLoadCompleted();
- return;
- }
-
- ASSERT_NOT_REACHED();
-}
-
-void FrameLoader::continueAfterContentPolicy(PolicyAction policy)
-{
- PolicyCheck check = m_policyCheck;
- m_policyCheck.clear();
- check.call(policy);
-}
-
-void FrameLoader::continueLoadAfterWillSubmitForm(PolicyAction)
-{
- if (!m_provisionalDocumentLoader)
- return;
-
- // DocumentLoader calls back to our prepareForLoadStart
- m_provisionalDocumentLoader->prepareForLoadStart();
-
- // The load might be cancelled inside of prepareForLoadStart(), nulling out the m_provisionalDocumentLoader,
- // so we need to null check it again.
- if (!m_provisionalDocumentLoader)
- return;
-
- DocumentLoader* activeDocLoader = activeDocumentLoader();
- if (activeDocLoader && activeDocLoader->isLoadingMainResource())
- return;
-
- m_provisionalDocumentLoader->setLoadingFromCachedPage(false);
-
- unsigned long identifier = 0;
-
- if (Page* page = m_frame->page()) {
- identifier = page->progress()->createUniqueIdentifier();
- dispatchAssignIdentifierToInitialRequest(identifier, m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest());
- }
-
- if (!m_provisionalDocumentLoader->startLoadingMainResource(identifier))
- m_provisionalDocumentLoader->updateLoading();
-}
-
-void FrameLoader::didFirstLayout()
-{
- if (Page* page = m_frame->page())
- if (isBackForwardLoadType(m_loadType) && page->backForwardList())
- restoreScrollPositionAndViewState();
-
- m_firstLayoutDone = true;
- m_client->dispatchDidFirstLayout();
-}
-
-void FrameLoader::frameLoadCompleted()
-{
- m_client->frameLoadCompleted();
-
- // After a canceled provisional load, firstLayoutDone is false.
- // Reset it to true if we're displaying a page.
- if (m_documentLoader)
- m_firstLayoutDone = true;
-}
-
-bool FrameLoader::firstLayoutDone() const
-{
- return m_firstLayoutDone;
-}
-
-bool FrameLoader::isQuickRedirectComing() const
-{
- return m_quickRedirectComing;
-}
-
-void FrameLoader::detachChildren()
-{
- // FIXME: Is it really necessary to do this in reverse order?
- Frame* previous;
- for (Frame* child = m_frame->tree()->lastChild(); child; child = previous) {
- previous = child->tree()->previousSibling();
- child->loader()->detachFromParent();
- }
-}
-
-void FrameLoader::recursiveCheckLoadComplete()
-{
- Vector<RefPtr<Frame>, 10> frames;
-
- for (RefPtr<Frame> frame = m_frame->tree()->firstChild(); frame; frame = frame->tree()->nextSibling())
- frames.append(frame);
-
- unsigned size = frames.size();
- for (unsigned i = 0; i < size; i++)
- frames[i]->loader()->recursiveCheckLoadComplete();
-
- checkLoadCompleteForThisFrame();
-}
-
-// Called every time a resource is completely loaded, or an error is received.
-void FrameLoader::checkLoadComplete()
-{
- ASSERT(m_client->hasWebView());
-
- // FIXME: Always traversing the entire frame tree is a bit inefficient, but
- // is currently needed in order to null out the previous history item for all frames.
- if (Page* page = m_frame->page())
- page->mainFrame()->loader()->recursiveCheckLoadComplete();
-}
-
-int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
-{
- if (!recurse)
- return numRequests(m_frame->document());
-
- int count = 0;
- for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame))
- count += numRequests(frame->document());
- return count;
-}
-
-FrameLoaderClient* FrameLoader::client() const
-{
- return m_client;
-}
-
-void FrameLoader::submitForm(const FrameLoadRequest& request, Event* event)
-{
- // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way.
- // We do not want to submit more than one form from the same page,
- // nor do we want to submit a single form more than once.
- // This flag prevents these from happening; not sure how other browsers prevent this.
- // The flag is reset in each time we start handle a new mouse or key down event, and
- // also in setView since this part may get reused for a page from the back/forward cache.
- // The form multi-submit logic here is only needed when we are submitting a form that affects this frame.
- // FIXME: Frame targeting is only one of the ways the submission could end up doing something other
- // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly
- // needed any more now that we reset m_submittedFormURL on each mouse or key down event.
- Frame* target = m_frame->tree()->find(request.frameName());
- if (target && m_frame->tree()->isDescendantOf(target)) {
- if (m_submittedFormURL == request.resourceRequest().url())
- return;
- m_submittedFormURL = request.resourceRequest().url();
- }
-
- // FIXME: We should probably call userGestureHint() to tell whether this form submission was the result of a user gesture.
- loadFrameRequestWithFormAndValues(request, false, event, m_formAboutToBeSubmitted.get(), m_formValuesAboutToBeSubmitted);
-
- clearRecordedFormValues();
-}
-
-String FrameLoader::userAgent(const KURL& url) const
-{
- return m_client->userAgent(url);
-}
-
-void FrameLoader::tokenizerProcessedData()
-{
-// ASSERT(m_frame->page());
-// ASSERT(m_frame->document());
-
- checkCompleted();
-}
-
-void FrameLoader::didTellClientAboutLoad(const String& url)
-{
-#if 0
- // This hash table is unused in our fork. The only reader is
- // haveToldClientAboutLoad, and the only caller of that is
- // loadedResourceFromMemoryCache. We have commented out that location
- // because we want to send every URL to the client for mixed content
- // detection. Therefore, this hash table is unused.
- //
- // The table stores every URL ever loaded, or which has been attempted to be
- // loaded by a frame. For some apps like gmail, this can get into the
- // thousands after it has been running for a while. With Gmail URLs often
- // being more than 100 characters (and 2-bytes per char in a String), this
- // can quickly use a lot of memory we don't need.
- m_urlsClientKnowsAbout.add(url);
-#endif
-}
-
-bool FrameLoader::haveToldClientAboutLoad(const String& url)
-{
-#if 0
- // See didTellClientAboutLoad() above for why this is removed in our fork.
- // This is commented out for consistency only. All lookups will fail anyway.
- return m_urlsClientKnowsAbout.contains(url);
-#else
- return false;
-#endif
-}
-
-void FrameLoader::handledOnloadEvents()
-{
- m_client->dispatchDidHandleOnloadEvents();
-}
-
-void FrameLoader::frameDetached()
-{
- stopAllLoaders();
- detachFromParent();
-}
-
-void FrameLoader::detachFromParent()
-{
- RefPtr<Frame> protect(m_frame);
-
- closeURL();
- stopAllLoaders();
- saveScrollPositionAndViewStateToItem(currentHistoryItem());
- detachChildren();
-
- if (Page* page = m_frame->page())
- page->inspectorController()->frameDetachedFromParent(m_frame);
-
- m_client->detachedFromParent2();
- setDocumentLoader(0);
- m_client->detachedFromParent3();
- if (Frame* parent = m_frame->tree()->parent()) {
- parent->tree()->removeChild(m_frame);
- parent->loader()->scheduleCheckCompleted();
- } else {
- m_frame->setView(0);
- m_frame->pageDestroyed();
- }
- m_client->detachedFromParent4();
-}
-
-void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, bool mainResource, bool alwaysFromRequest)
-{
- applyUserAgent(request);
-
- if (m_loadType == FrameLoadTypeReload) {
- request.setCachePolicy(ReloadIgnoringCacheData);
- request.setHTTPHeaderField("Cache-Control", "max-age=0");
- }
-
- // Don't set the cookie policy URL if it's already been set.
- if (request.mainDocumentURL().isEmpty()) {
- if (mainResource && (isLoadingMainFrame() || alwaysFromRequest))
- request.setMainDocumentURL(request.url());
- else if (Page* page = m_frame->page())
- request.setMainDocumentURL(page->mainFrame()->loader()->url());
- }
-
- if (mainResource)
- request.setHTTPAccept("application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
-}
-
-void FrameLoader::committedLoad(DocumentLoader* loader, const char* data, int length)
-{
- if (ArchiveFactory::isArchiveMimeType(loader->response().mimeType()))
- return;
- m_client->committedLoad(loader, data, length);
-}
-
-void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String& referrer, const String& frameName,
- Event* event, PassRefPtr<FormState> prpFormState)
-{
- RefPtr<FormState> formState = prpFormState;
-
- // When posting, use the NSURLRequestReloadIgnoringCacheData load flag.
- // This prevents a potential bug which may cause a page with a form that uses itself
- // as an action to be returned from the cache without submitting.
-
- // FIXME: Where's the code that implements what the comment above says?
-
- // Previously when this method was reached, the original FrameLoadRequest had been deconstructed to build a
- // bunch of parameters that would come in here and then be built back up to a ResourceRequest. In case
- // any caller depends on the immutability of the original ResourceRequest, I'm rebuilding a ResourceRequest
- // from scratch as it did all along.
- const KURL& url = inRequest.url();
- RefPtr<FormData> formData = inRequest.httpBody();
- const String& contentType = inRequest.httpContentType();
-
- ResourceRequest workingResourceRequest(url);
- addExtraFieldsToRequest(workingResourceRequest, true, true);
-
- if (!referrer.isEmpty())
- workingResourceRequest.setHTTPReferrer(referrer);
- workingResourceRequest.setHTTPMethod("POST");
- workingResourceRequest.setHTTPBody(formData);
- workingResourceRequest.setHTTPContentType(contentType);
-
- NavigationAction action(url, FrameLoadTypeStandard, true, event);
-
- if (!frameName.isEmpty()) {
- if (Frame* targetFrame = findFrameForNavigation(frameName))
- targetFrame->loader()->loadWithNavigationAction(workingResourceRequest, action, FrameLoadTypeStandard, formState.release());
- else
- checkNewWindowPolicy(action, workingResourceRequest, formState.release(), frameName);
- } else
- loadWithNavigationAction(workingResourceRequest, action, FrameLoadTypeStandard, formState.release());
-}
-
-bool FrameLoader::isReloading() const
-{
- return documentLoader()->request().cachePolicy() == ReloadIgnoringCacheData;
-}
-
-void FrameLoader::loadEmptyDocumentSynchronously()
-{
- ResourceRequest request(KURL(""));
- load(request);
-}
-
-unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
-{
- // Since this is a subresource, we can load any URL (we ignore the return value).
- // But we still want to know whether we should hide the referrer or not, so we call the canLoad method.
- String referrer = m_outgoingReferrer;
- if (shouldHideReferrer(request.url(), referrer))
- referrer = String();
-
- ResourceRequest initialRequest = request;
- initialRequest.setTimeoutInterval(10);
-
- if (initialRequest.isConditional())
- initialRequest.setCachePolicy(ReloadIgnoringCacheData);
- else
- initialRequest.setCachePolicy(documentLoader()->request().cachePolicy());
-
- if (!referrer.isEmpty())
- initialRequest.setHTTPReferrer(referrer);
-
- if (Page* page = m_frame->page())
- initialRequest.setMainDocumentURL(page->mainFrame()->loader()->documentLoader()->request().url());
- initialRequest.setHTTPUserAgent(client()->userAgent(request.url()));
-
- unsigned long identifier = 0;
- ResourceRequest newRequest(initialRequest);
- requestFromDelegate(newRequest, identifier, error);
-
- if (error.isNull()) {
- ASSERT(!newRequest.isNull());
- didTellClientAboutLoad(newRequest.url().string());
-
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- ApplicationCacheResource* resource;
- if (documentLoader()->shouldLoadResourceFromApplicationCache(newRequest, resource)) {
- if (resource) {
- response = resource->response();
- data.append(resource->data()->data(), resource->data()->size());
- } else
- error = cannotShowURLError(newRequest);
- } else
-#endif
- ResourceHandle::loadResourceSynchronously(newRequest, error, response, data, m_frame);
- }
-
- sendRemainingDelegateMessages(identifier, response, data.size(), error);
- return identifier;
-}
-
-void FrameLoader::assignIdentifierToInitialRequest(unsigned long identifier, const ResourceRequest& clientRequest)
-{
- return dispatchAssignIdentifierToInitialRequest(identifier, activeDocumentLoader(), clientRequest);
-}
-
-void FrameLoader::willSendRequest(ResourceLoader* loader, ResourceRequest& clientRequest, const ResourceResponse& redirectResponse)
-{
- applyUserAgent(clientRequest);
- dispatchWillSendRequest(loader->documentLoader(), loader->identifier(), clientRequest, redirectResponse);
-}
-
-void FrameLoader::didReceiveResponse(ResourceLoader* loader, const ResourceResponse& r)
-{
- activeDocumentLoader()->addResponse(r);
-
- if (Page* page = m_frame->page())
- page->progress()->incrementProgress(loader->identifier(), r);
- dispatchDidReceiveResponse(loader->documentLoader(), loader->identifier(), r);
-}
-
-void FrameLoader::didReceiveData(ResourceLoader* loader, const char* data, int length, int lengthReceived)
-{
- if (Page* page = m_frame->page())
- page->progress()->incrementProgress(loader->identifier(), data, length);
- dispatchDidReceiveContentLength(loader->documentLoader(), loader->identifier(), lengthReceived);
-}
-
-void FrameLoader::didFailToLoad(ResourceLoader* loader, const ResourceError& error)
-{
- if (Page* page = m_frame->page())
- page->progress()->completeProgress(loader->identifier());
- if (!error.isNull())
- m_client->dispatchDidFailLoading(loader->documentLoader(), loader->identifier(), error);
-}
-
-const ResourceRequest& FrameLoader::originalRequest() const
-{
- return activeDocumentLoader()->originalRequestCopy();
-}
-
-void FrameLoader::receivedMainResourceError(const ResourceError& error, bool isComplete)
-{
- // Retain because the stop may release the last reference to it.
- RefPtr<Frame> protect(m_frame);
-
- RefPtr<DocumentLoader> loader = activeDocumentLoader();
-
- if (isComplete) {
- // FIXME: Don't want to do this if an entirely new load is going, so should check
- // that both data sources on the frame are either this or nil.
- stop();
- if (m_client->shouldFallBack(error))
- handleFallbackContent();
- }
-
- if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) {
- KURL failedURL = m_provisionalDocumentLoader->originalRequestCopy().url();
- didNotOpenURL(failedURL);
-
- // We might have made a page cache item, but now we're bailing out due to an error before we ever
- // transitioned to the new page (before WebFrameState == commit). The goal here is to restore any state
- // so that the existing view (that wenever got far enough to replace) can continue being used.
- invalidateCurrentItemCachedPage();
-
- // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
- // status has changed, if there was a redirect. The frame load delegate may have saved some state about
- // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
- // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
- // has ended.
- if (m_sentRedirectNotification)
- clientRedirectCancelledOrFinished(false);
- }
-
-
- loader->mainReceivedError(error, isComplete);
-}
-
-void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument,
- const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue)
-{
- FrameLoader* loader = static_cast<FrameLoader*>(argument);
- loader->continueFragmentScrollAfterNavigationPolicy(request, shouldContinue);
-}
-
-void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
-{
- // FIXME:
- // some functions check m_quickRedirectComing, and others check for
- // FrameLoadTypeRedirectWithLockedHistory.
- bool isRedirect = m_quickRedirectComing || m_policyLoadType == FrameLoadTypeRedirectWithLockedHistory;
- m_quickRedirectComing = false;
-
- if (!shouldContinue)
- return;
-
- KURL url = request.url();
-
- m_documentLoader->replaceRequestURLForAnchorScroll(url);
- if (!isRedirect && !shouldTreatURLAsSameAsCurrent(url)) {
- // NB: must happen after _setURL, since we add based on the current request.
- // Must also happen before we openURL and displace the scroll position, since
- // adding the BF item will save away scroll state.
-
- // NB2: If we were loading a long, slow doc, and the user anchor nav'ed before
- // it was done, currItem is now set the that slow doc, and prevItem is whatever was
- // before it. Adding the b/f item will bump the slow doc down to prevItem, even
- // though its load is not yet done. I think this all works out OK, for one because
- // we have already saved away the scroll and doc state for the long slow load,
- // but it's not an obvious case.
-
- addHistoryItemForFragmentScroll();
- }
-
- scrollToAnchor(url);
-
- if (!isRedirect)
- // This will clear previousItem from the rest of the frame tree that didn't
- // doing any loading. We need to make a pass on this now, since for anchor nav
- // we'll not go through a real load and reach Completed state.
- checkLoadComplete();
-
- m_client->dispatchDidChangeLocationWithinPage();
- m_client->didFinishLoad();
-}
-
-bool FrameLoader::shouldScrollToAnchor(bool isFormSubmission, FrameLoadType loadType, const KURL& url)
-{
- // Should we do anchor navigation within the existing content?
-
- // We don't do this if we are submitting a form, explicitly reloading,
- // currently displaying a frameset, or if the URL does not have a fragment.
- // These rules were originally based on what KHTML was doing in KHTMLPart::openURL.
-
- // FIXME: What about load types other than Standard and Reload?
-
- return !isFormSubmission
- && loadType != FrameLoadTypeReload
- && loadType != FrameLoadTypeSame
- && !shouldReload(this->url(), url)
- // We don't want to just scroll if a link from within a
- // frameset is trying to reload the frameset into _top.
- && !m_frame->isFrameSet();
-}
-
-void FrameLoader::opened()
-{
- if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect())
- updateHistoryForClientRedirect();
-
- if (m_documentLoader->isLoadingFromCachedPage()) {
- m_frame->document()->didRestoreFromCache();
-
- // Force a layout to update view size and thereby update scrollbars.
- m_client->forceLayout();
-
- const ResponseVector& responses = m_documentLoader->responses();
- size_t count = responses.size();
- for (size_t i = 0; i < count; i++) {
- const ResourceResponse& response = responses[i];
- // FIXME: If the WebKit client changes or cancels the request, this is not respected.
- ResourceError error;
- unsigned long identifier;
- ResourceRequest request(response.url());
- requestFromDelegate(request, identifier, error);
- // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
- // However, with today's computers and networking speeds, this won't happen in practice.
- // Could be an issue with a giant local file.
- sendRemainingDelegateMessages(identifier, response, static_cast<int>(response.expectedContentLength()), error);
- }
-
- pageCache()->remove(m_currentHistoryItem.get());
-
- m_documentLoader->setPrimaryLoadComplete(true);
-
- // FIXME: Why only this frame and not parent frames?
- checkLoadCompleteForThisFrame();
- }
-}
-
-void FrameLoader::checkNewWindowPolicy(const NavigationAction& action, const ResourceRequest& request,
- PassRefPtr<FormState> formState, const String& frameName)
-{
- m_policyCheck.set(request, formState, frameName,
- callContinueLoadAfterNewWindowPolicy, this);
- m_client->dispatchDecidePolicyForNewWindowAction(&FrameLoader::continueAfterNewWindowPolicy,
- action, request, formState, frameName);
-}
-
-void FrameLoader::continueAfterNewWindowPolicy(PolicyAction policy)
-{
- PolicyCheck check = m_policyCheck;
- m_policyCheck.clear();
-
- switch (policy) {
- case PolicyIgnore:
- check.clearRequest();
- break;
- case PolicyDownload:
- m_client->startDownload(check.request());
- check.clearRequest();
- break;
- case PolicyUse:
- break;
- }
-
- check.call(policy == PolicyUse);
-}
-
-void FrameLoader::checkNavigationPolicy(const ResourceRequest& request, DocumentLoader* loader,
- PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function, void* argument)
-{
- NavigationAction action = loader->triggeringAction();
- if (action.isEmpty()) {
- action = NavigationAction(request.url(), NavigationTypeOther);
- loader->setTriggeringAction(action);
- }
-
- // Don't ask more than once for the same request or if we are loading an empty URL.
- // This avoids confusion on the part of the client.
- if (equalIgnoringHeaderFields(request, loader->lastCheckedRequest()) || (!request.isNull() && request.url().isEmpty())) {
- function(argument, request, 0, true);
- loader->setLastCheckedRequest(request);
- return;
- }
-
- // We are always willing to show alternate content for unreachable URLs;
- // treat it like a reload so it maintains the right state for b/f list.
- if (loader->substituteData().isValid() && !loader->substituteData().failingURL().isEmpty()) {
- if (isBackForwardLoadType(m_policyLoadType))
- m_policyLoadType = FrameLoadTypeReload;
- function(argument, request, 0, true);
- return;
- }
-
- loader->setLastCheckedRequest(request);
-
- m_policyCheck.set(request, formState.get(), function, argument);
-
- m_delegateIsDecidingNavigationPolicy = true;
- m_client->dispatchDecidePolicyForNavigationAction(&FrameLoader::continueAfterNavigationPolicy,
- action, request, formState);
- m_delegateIsDecidingNavigationPolicy = false;
-}
-
-void FrameLoader::continueAfterNavigationPolicy(PolicyAction policy)
-{
- PolicyCheck check = m_policyCheck;
- m_policyCheck.clear();
-
- bool shouldContinue = policy == PolicyUse;
-
- switch (policy) {
- case PolicyIgnore:
- check.clearRequest();
- break;
- case PolicyDownload:
- m_client->startDownload(check.request());
- check.clearRequest();
- break;
- case PolicyUse: {
- ResourceRequest request(check.request());
-
- if (!m_client->canHandleRequest(request)) {
- handleUnimplementablePolicy(m_client->cannotShowURLError(check.request()));
- check.clearRequest();
- shouldContinue = false;
- }
- break;
- }
- }
-
- check.call(shouldContinue);
-}
-
-void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
- const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
-{
- FrameLoader* loader = static_cast<FrameLoader*>(argument);
- loader->continueLoadAfterNavigationPolicy(request, formState, shouldContinue);
-}
-
-void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
-{
- // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
- // nil policyDataSource because loading the alternate page will have passed
- // through this method already, nested; otherwise, policyDataSource should still be set.
- ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
-
- bool isTargetItem = m_provisionalHistoryItem ? m_provisionalHistoryItem->isTargetItem() : false;
-
- // Two reasons we can't continue:
- // 1) Navigation policy delegate said we can't so request is nil. A primary case of this
- // is the user responding Cancel to the form repost nag sheet.
- // 2) User responded Cancel to an alert popped up by the before unload event handler.
- // The "before unload" event handler runs only for the main frame.
- bool canContinue = shouldContinue && (!isLoadingMainFrame() || m_frame->shouldClose());
-
- if (!canContinue) {
- // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we
- // need to report that the client redirect was cancelled.
- if (m_quickRedirectComing)
- clientRedirectCancelledOrFinished(false);
-
- setPolicyDocumentLoader(0);
-
- // If the navigation request came from the back/forward menu, and we punt on it, we have the
- // problem that we have optimistically moved the b/f cursor already, so move it back. For sanity,
- // we only do this when punting a navigation for the target frame or top-level frame.
- if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(m_policyLoadType))
- if (Page* page = m_frame->page()) {
- Frame* mainFrame = page->mainFrame();
- if (HistoryItem* resetItem = mainFrame->loader()->m_currentHistoryItem.get())
- page->backForwardList()->goToItem(resetItem);
- }
- return;
- }
-
- FrameLoadType type = m_policyLoadType;
- stopAllLoaders();
- setProvisionalDocumentLoader(m_policyDocumentLoader.get());
- m_loadType = type;
- setState(FrameStateProvisional);
-
- setPolicyDocumentLoader(0);
-
- if (isBackForwardLoadType(type) && loadProvisionalItemFromCachedPage())
- return;
-
- if (formState)
- m_client->dispatchWillSubmitForm(&FrameLoader::continueLoadAfterWillSubmitForm, formState);
- else
- continueLoadAfterWillSubmitForm();
-}
-
-
-void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument,
- const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
-{
- FrameLoader* loader = static_cast<FrameLoader*>(argument);
- loader->continueLoadAfterNewWindowPolicy(request, formState, frameName, shouldContinue);
-}
-
-void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
- PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
-{
- if (!shouldContinue)
- return;
-
- RefPtr<Frame> frame = m_frame;
- RefPtr<Frame> mainFrame = m_client->dispatchCreatePage();
- if (!mainFrame)
- return;
-
- if (frameName != "_blank")
- mainFrame->tree()->setName(frameName);
-
- mainFrame->loader()->setOpenedByDOM();
- mainFrame->loader()->m_client->dispatchShow();
- mainFrame->loader()->setOpener(frame.get());
- mainFrame->loader()->loadWithNavigationAction(request, NavigationAction(), FrameLoadTypeStandard, formState);
-}
-
-void FrameLoader::sendRemainingDelegateMessages(unsigned long identifier, const ResourceResponse& response, int length, const ResourceError& error)
-{
- if (!response.isNull())
- dispatchDidReceiveResponse(m_documentLoader.get(), identifier, response);
-
- if (length > 0)
- dispatchDidReceiveContentLength(m_documentLoader.get(), identifier, length);
-
- if (error.isNull())
- dispatchDidFinishLoading(m_documentLoader.get(), identifier);
- else
- m_client->dispatchDidFailLoading(m_documentLoader.get(), identifier, error);
-}
-
-void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
-{
- ASSERT(!request.isNull());
-
- identifier = 0;
- if (Page* page = m_frame->page()) {
- identifier = page->progress()->createUniqueIdentifier();
- dispatchAssignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
- }
-
- ResourceRequest newRequest(request);
- dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
-
- if (newRequest.isNull())
- error = cancelledError(request);
- else
- error = ResourceError();
-
- request = newRequest;
-}
-
-void FrameLoader::loadedResourceFromMemoryCache(const CachedResource* resource)
-{
- ResourceRequest request(resource->url());
- const ResourceResponse& response = resource->response();
- int length = resource->encodedSize();
-
- if (Page* page = m_frame->page())
- page->inspectorController()->didLoadResourceFromMemoryCache(m_documentLoader.get(), request, response, length);
-
-
-#if 0
- // The following test prevents reporting a resource has been loaded from
- // the cache as CachedResource.m_sendResourceLoadCallbacks is always false.
- // Also, haveToldClientAboutLoad() and didTellClientAboutLoad() would cause
- // dispatchDidLoadResourceFromMemoryCache() to be invoked only the first
- // time the resource is loaded from the cache.
- // We want to be notified every time a resource is loaded from the cache
- // (this is needed to detect mixed-contents), so we removed it.
-
- if (!resource->sendResourceLoadCallbacks() || haveToldClientAboutLoad(resource->url()))
- return;
-#endif
-
- if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, response, length)) {
- didTellClientAboutLoad(resource->url());
- return;
- }
-
- unsigned long identifier;
- ResourceError error;
- ResourceRequest r(request);
- requestFromDelegate(r, identifier, error);
- sendRemainingDelegateMessages(identifier, response, length, error);
-
- didTellClientAboutLoad(resource->url());
-}
-
-void FrameLoader::applyUserAgent(ResourceRequest& request)
-{
- String userAgent = client()->userAgent(request.url());
- ASSERT(!userAgent.isNull());
- request.setHTTPUserAgent(userAgent);
-}
-
-bool FrameLoader::canGoBackOrForward(int distance) const
-{
- if (Page* page = m_frame->page()) {
- if (distance == 0)
- return true;
- if (distance > 0 && distance <= page->backForwardList()->forwardListCount())
- return true;
- if (distance < 0 && -distance <= page->backForwardList()->backListCount())
- return true;
- }
- return false;
-}
-
-int FrameLoader::getHistoryLength()
-{
- if (Page* page = m_frame->page())
- return page->backForwardList()->backListCount() + 1;
- return 0;
-}
-
-KURL FrameLoader::historyURL(int distance)
-{
- if (Page* page = m_frame->page()) {
- BackForwardList* list = page->backForwardList();
- HistoryItem* item = list->itemAtIndex(distance);
- if (!item) {
- if (distance > 0) {
- int forwardListCount = list->forwardListCount();
- if (forwardListCount > 0)
- item = list->itemAtIndex(forwardListCount);
- } else {
- int backListCount = list->backListCount();
- if (backListCount > 0)
- item = list->itemAtIndex(-backListCount);
- }
- }
- if (item)
- return item->url();
- }
- return KURL();
-}
-
-void FrameLoader::addHistoryItemForFragmentScroll()
-{
- addBackForwardItemClippedAtTarget(false);
-}
-
-bool FrameLoader::loadProvisionalItemFromCachedPage()
-{
- RefPtr<CachedPage> cachedPage = pageCache()->get(m_provisionalHistoryItem.get());
- if (!cachedPage || !cachedPage->document())
- return false;
- provisionalDocumentLoader()->loadFromCachedPage(cachedPage.release());
- return true;
-}
-
-void FrameLoader::cachePageForHistoryItem(HistoryItem* item)
-{
- if (Page* page = m_frame->page()) {
- RefPtr<CachedPage> cachedPage = CachedPage::create(page);
- cachedPage->setTimeStampToNow();
- cachedPage->setDocumentLoader(documentLoader());
- m_client->savePlatformDataToCachedPage(cachedPage.get());
-
- pageCache()->add(item, cachedPage.release());
- }
-}
-
-bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const
-{
- if (!m_currentHistoryItem)
- return false;
- return url == m_currentHistoryItem->url() || url == m_currentHistoryItem->originalURL();
-}
-
-PassRefPtr<HistoryItem> FrameLoader::createHistoryItem(bool useOriginal)
-{
- DocumentLoader* docLoader = documentLoader();
-
- KURL unreachableURL = docLoader ? docLoader->unreachableURL() : KURL();
-
- KURL url;
- KURL originalURL;
-
- if (!unreachableURL.isEmpty()) {
- url = unreachableURL;
- originalURL = unreachableURL;
- } else {
- originalURL = docLoader ? docLoader->originalURL() : KURL();
- if (useOriginal)
- url = originalURL;
- else if (docLoader)
- url = docLoader->requestURL();
- }
-
- LOG(History, "WebCoreHistory: Creating item for %s", url.string().ascii().data());
-
- // Frames that have never successfully loaded any content
- // may have no URL at all. Currently our history code can't
- // deal with such things, so we nip that in the bud here.
- // Later we may want to learn to live with nil for URL.
- // See bug 3368236 and related bugs for more information.
- if (url.isEmpty())
- url = blankURL();
- if (originalURL.isEmpty())
- originalURL = blankURL();
-
- Frame* parentFrame = m_frame->tree()->parent();
- String parent = parentFrame ? parentFrame->tree()->name() : "";
- String title = docLoader ? docLoader->title() : "";
-
- RefPtr<HistoryItem> item = HistoryItem::create(url, m_frame->tree()->name(), parent, title);
- item->setOriginalURLString(originalURL.string());
-
- // Save form state if this is a POST
- if (docLoader) {
- if (useOriginal)
- item->setFormInfoFromRequest(docLoader->originalRequest());
- else
- item->setFormInfoFromRequest(docLoader->request());
- }
-
- // Set the item for which we will save document state
- m_previousHistoryItem = m_currentHistoryItem;
- m_currentHistoryItem = item;
-
- return item.release();
-}
-
-void FrameLoader::addBackForwardItemClippedAtTarget(bool doClip)
-{
- Page* page = m_frame->page();
- if (!page)
- return;
-
- if (documentLoader()->urlForHistory().isEmpty())
- return;
-
- Frame* mainFrame = page->mainFrame();
- ASSERT(mainFrame);
- FrameLoader* frameLoader = mainFrame->loader();
-
- if (!frameLoader->m_didPerformFirstNavigation && page->backForwardList()->entries().size() == 1) {
- frameLoader->m_didPerformFirstNavigation = true;
- m_client->didPerformFirstNavigation();
- }
-
- RefPtr<HistoryItem> item = frameLoader->createHistoryItemTree(m_frame, doClip);
- LOG(BackForward, "WebCoreBackForward - Adding backforward item %p for frame %s", item.get(), documentLoader()->url().string().ascii().data());
- page->backForwardList()->addItem(item);
-}
-
-PassRefPtr<HistoryItem> FrameLoader::createHistoryItemTree(Frame* targetFrame, bool clipAtTarget)
-{
- RefPtr<HistoryItem> bfItem = createHistoryItem(m_frame->tree()->parent() ? true : false);
- if (m_previousHistoryItem)
- saveScrollPositionAndViewStateToItem(m_previousHistoryItem.get());
- if (!(clipAtTarget && m_frame == targetFrame)) {
- // save frame state for items that aren't loading (khtml doesn't save those)
- saveDocumentState();
- for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
- FrameLoader* childLoader = child->loader();
- bool hasChildLoaded = childLoader->frameHasLoaded();
-
- // If the child is a frame corresponding to an <object> element that never loaded,
- // we don't want to create a history item, because that causes fallback content
- // to be ignored on reload.
-
- if (!(!hasChildLoaded && childLoader->isHostedByObjectElement()))
- bfItem->addChildItem(childLoader->createHistoryItemTree(targetFrame, clipAtTarget));
- }
- }
- if (m_frame == targetFrame)
- bfItem->setIsTargetItem(true);
- return bfItem;
-}
-
-Frame* FrameLoader::findFrameForNavigation(const AtomicString& name)
-{
- Frame* frame = m_frame->tree()->find(name);
- if (shouldAllowNavigation(frame))
- return frame;
- return 0;
-}
-
-void FrameLoader::saveScrollPositionAndViewStateToItem(HistoryItem* item)
-{
- if (!item || !m_frame->view())
- return;
-
- item->setScrollPoint(IntPoint(m_frame->view()->contentsX(), m_frame->view()->contentsY()));
- // FIXME: It would be great to work out a way to put this code in WebCore instead of calling through to the client.
- m_client->saveViewStateToItem(item);
-}
-
-/*
- There is a race condition between the layout and load completion that affects restoring the scroll position.
- We try to restore the scroll position at both the first layout and upon load completion.
-
- 1) If first layout happens before the load completes, we want to restore the scroll position then so that the
- first time we draw the page is already scrolled to the right place, instead of starting at the top and later
- jumping down. It is possible that the old scroll position is past the part of the doc laid out so far, in
- which case the restore silent fails and we will fix it in when we try to restore on doc completion.
- 2) If the layout happens after the load completes, the attempt to restore at load completion time silently
- fails. We then successfully restore it when the layout happens.
-*/
-void FrameLoader::restoreScrollPositionAndViewState()
-{
- if (!m_committedFirstRealDocumentLoad)
- return;
-
- ASSERT(m_currentHistoryItem);
-
- // FIXME: As the ASSERT attests, it seems we should always have a currentItem here.
- // One counterexample is <rdar://problem/4917290>
- // For now, to cover this issue in release builds, there is no technical harm to returning
- // early and from a user standpoint - as in the above radar - the previous page load failed
- // so there *is* no scroll or view state to restore!
- if (!m_currentHistoryItem)
- return;
-
- // FIXME: It would be great to work out a way to put this code in WebCore instead of calling
- // through to the client. It's currently used only for the PDF view on Mac.
- m_client->restoreViewState();
-
- if (FrameView* view = m_frame->view())
- if (!view->wasScrolledByUser()) {
- const IntPoint& scrollPoint = m_currentHistoryItem->scrollPoint();
- view->setContentsPos(scrollPoint.x(), scrollPoint.y());
- }
-}
-
-void FrameLoader::invalidateCurrentItemCachedPage()
-{
- // When we are pre-commit, the currentItem is where the pageCache data resides
- CachedPage* cachedPage = pageCache()->get(m_currentHistoryItem.get());
-
- // FIXME: This is a grotesque hack to fix <rdar://problem/4059059> Crash in RenderFlow::detach
- // Somehow the PageState object is not properly updated, and is holding onto a stale document.
- // Both Xcode and FileMaker see this crash, Safari does not.
-
- ASSERT(!cachedPage || cachedPage->document() == m_frame->document());
- if (cachedPage && cachedPage->document() == m_frame->document()) {
- cachedPage->document()->setInPageCache(false);
- cachedPage->clear();
- }
-
- if (cachedPage)
- pageCache()->remove(m_currentHistoryItem.get());
-}
-
-void FrameLoader::saveDocumentState()
-{
- if (m_creatingInitialEmptyDocument)
- return;
-
- // For a standard page load, we will have a previous item set, which will be used to
- // store the form state. However, in some cases we will have no previous item, and
- // the current item is the right place to save the state. One example is when we
- // detach a bunch of frames because we are navigating from a site with frames to
- // another site. Another is when saving the frame state of a frame that is not the
- // target of the current navigation (if we even decide to save with that granularity).
-
- // Because of previousItem's "masking" of currentItem for this purpose, it's important
- // that previousItem be cleared at the end of a page transition. We leverage the
- // checkLoadComplete recursion to achieve this goal.
-
- HistoryItem* item = m_previousHistoryItem ? m_previousHistoryItem.get() : m_currentHistoryItem.get();
- if (!item)
- return;
-
- Document* document = m_frame->document();
- ASSERT(document);
-
- if (document && item->isCurrentDocument(document)) {
- LOG(Loading, "WebCoreLoading %s: saving form state to %p", m_frame->tree()->name().string().utf8().data(), item);
- item->setDocumentState(document->formElementsState());
- }
-}
-
-// Loads content into this frame, as specified by history item
-void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
-{
- if (!m_frame->page())
- return;
-
- KURL itemURL = item->url();
- KURL itemOriginalURL = item->originalURL();
- KURL currentURL;
- if (documentLoader())
- currentURL = documentLoader()->url();
- RefPtr<FormData> formData = item->formData();
-
- // Are we navigating to an anchor within the page?
- // Note if we have child frames we do a real reload, since the child frames might not
- // match our current frame structure, or they might not have the right content. We could
- // check for all that as an additional optimization.
- // We also do not do anchor-style navigation if we're posting a form.
-
- if (!formData && urlsMatchItem(item)) {
- // Must do this maintenance here, since we don't go through a real page reload
- saveScrollPositionAndViewStateToItem(m_currentHistoryItem.get());
-
- if (FrameView* view = m_frame->view())
- view->setWasScrolledByUser(false);
-
- m_currentHistoryItem = item;
-
- // FIXME: Form state might need to be saved here too.
-
- // We always call scrollToAnchor here, even if the URL doesn't have an
- // anchor fragment. This is so we'll keep the WebCore Frame's URL up-to-date.
- scrollToAnchor(item->url());
-
- // must do this maintenance here, since we don't go through a real page reload
- restoreScrollPositionAndViewState();
-
- // Fake the URL change by updating the data source's request. This will no longer
- // be necessary if we do the better fix described above.
- documentLoader()->replaceRequestURLForAnchorScroll(itemURL);
-
- m_client->dispatchDidChangeLocationWithinPage();
-
- // FrameLoaderClient::didFinishLoad() tells the internal load delegate the load finished with no error
- m_client->didFinishLoad();
- } else {
- // Remember this item so we can traverse any child items as child frames load
- m_provisionalHistoryItem = item;
-
- bool inPageCache = false;
-
- // Check if we'll be using the page cache. We only use the page cache
- // if one exists and it is less than _backForwardCacheExpirationInterval
- // seconds old. If the cache is expired it gets flushed here.
- if (RefPtr<CachedPage> cachedPage = pageCache()->get(item)) {
- double interval = currentTime() - cachedPage->timeStamp();
-
- // FIXME: 1800 should not be hardcoded, it should come from
- // WebKitBackForwardCacheExpirationIntervalKey in WebKit.
- // Or we should remove WebKitBackForwardCacheExpirationIntervalKey.
- if (interval <= 1800) {
- loadWithDocumentLoader(cachedPage->documentLoader(), loadType, 0);
- inPageCache = true;
- } else {
- LOG(PageCache, "Not restoring page for %s from back/forward cache because cache entry has expired", m_provisionalHistoryItem->url().string().ascii().data());
- pageCache()->remove(item);
- }
- }
-
- if (!inPageCache) {
- ResourceRequest request(itemURL);
-
- addExtraFieldsToRequest(request, true, formData);
-
- // If this was a repost that failed the page cache, we might try to repost the form.
- NavigationAction action;
- if (formData) {
-
- formData->generateFiles(m_frame->page()->chrome()->client());
-
- request.setHTTPMethod("POST");
- request.setHTTPReferrer(item->formReferrer());
- request.setHTTPBody(formData);
- request.setHTTPContentType(item->formContentType());
-
- // FIXME: Slight hack to test if the NSURL cache contains the page we're going to.
- // We want to know this before talking to the policy delegate, since it affects whether
- // we show the DoYouReallyWantToRepost nag.
- //
- // This trick has a small bug (3123893) where we might find a cache hit, but then
- // have the item vanish when we try to use it in the ensuing nav. This should be
- // extremely rare, but in that case the user will get an error on the navigation.
-
- if (ResourceHandle::willLoadFromCache(request))
- action = NavigationAction(itemURL, loadType, false);
- else {
- request.setCachePolicy(ReloadIgnoringCacheData);
- action = NavigationAction(itemURL, NavigationTypeFormResubmitted);
- }
- } else {
- switch (loadType) {
- case FrameLoadTypeReload:
- request.setCachePolicy(ReloadIgnoringCacheData);
- break;
- case FrameLoadTypeBack:
- case FrameLoadTypeForward:
- case FrameLoadTypeIndexedBackForward:
- if (itemURL.protocol() != "https")
- request.setCachePolicy(ReturnCacheDataElseLoad);
- break;
- case FrameLoadTypeStandard:
- case FrameLoadTypeRedirectWithLockedHistory:
- // no-op: leave as protocol default
- // FIXME: I wonder if we ever hit this case
- break;
- case FrameLoadTypeSame:
- case FrameLoadTypeReloadAllowingStaleData:
- default:
- ASSERT_NOT_REACHED();
- }
-
- action = NavigationAction(itemOriginalURL, loadType, false);
- }
-
- loadWithNavigationAction(request, action, loadType, 0);
- }
- }
-}
-
-// Walk the frame tree and ensure that the URLs match the URLs in the item.
-bool FrameLoader::urlsMatchItem(HistoryItem* item) const
-{
- const KURL& currentURL = documentLoader()->url();
- if (!equalIgnoringRef(currentURL, item->url()))
- return false;
-
- const HistoryItemVector& childItems = item->children();
-
- unsigned size = childItems.size();
- for (unsigned i = 0; i < size; ++i) {
- Frame* childFrame = m_frame->tree()->child(childItems[i]->target());
- if (childFrame && !childFrame->loader()->urlsMatchItem(childItems[i].get()))
- return false;
- }
-
- return true;
-}
-
-// Main funnel for navigating to a previous location (back/forward, non-search snap-back)
-// This includes recursion to handle loading into framesets properly
-void FrameLoader::goToItem(HistoryItem* targetItem, FrameLoadType type)
-{
- ASSERT(!m_frame->tree()->parent());
-
- // shouldGoToHistoryItem is a private delegate method. This is needed to fix:
- // <rdar://problem/3951283> can view pages from the back/forward cache that should be disallowed by Parental Controls
- // Ultimately, history item navigations should go through the policy delegate. That's covered in:
- // <rdar://problem/3979539> back/forward cache navigations should consult policy delegate
- Page* page = m_frame->page();
- if (!page)
- return;
- if (!m_client->shouldGoToHistoryItem(targetItem))
- return;
-
- // Set the BF cursor before commit, which lets the user quickly click back/forward again.
- // - plus, it only makes sense for the top level of the operation through the frametree,
- // as opposed to happening for some/one of the page commits that might happen soon
- BackForwardList* bfList = page->backForwardList();
- HistoryItem* currentItem = bfList->currentItem();
- bfList->goToItem(targetItem);
- recursiveGoToItem(targetItem, currentItem, type);
-}
-
-// The general idea here is to traverse the frame tree and the item tree in parallel,
-// tracking whether each frame already has the content the item requests. If there is
-// a match (by URL), we just restore scroll position and recurse. Otherwise we must
-// reload that frame, and all its kids.
-void FrameLoader::recursiveGoToItem(HistoryItem* item, HistoryItem* fromItem, FrameLoadType type)
-{
- ASSERT(item);
- ASSERT(fromItem);
-
- KURL itemURL = item->url();
- KURL currentURL;
- if (documentLoader())
- currentURL = documentLoader()->url();
-
- // Always reload the target frame of the item we're going to. This ensures that we will
- // do -some- load for the transition, which means a proper notification will be posted
- // to the app.
- // The exact URL has to match, including fragment. We want to go through the _load
- // method, even if to do a within-page navigation.
- // The current frame tree and the frame tree snapshot in the item have to match.
- if (!item->isTargetItem() &&
- itemURL == currentURL &&
- ((m_frame->tree()->name().isEmpty() && item->target().isEmpty()) || m_frame->tree()->name() == item->target()) &&
- childFramesMatchItem(item))
- {
- // This content is good, so leave it alone and look for children that need reloading
- // Save form state (works from currentItem, since prevItem is nil)
- ASSERT(!m_previousHistoryItem);
- saveDocumentState();
- saveScrollPositionAndViewStateToItem(m_currentHistoryItem.get());
-
- if (FrameView* view = m_frame->view())
- view->setWasScrolledByUser(false);
-
- m_currentHistoryItem = item;
-
- // Restore form state (works from currentItem)
- restoreDocumentState();
-
- // Restore the scroll position (we choose to do this rather than going back to the anchor point)
- restoreScrollPositionAndViewState();
-
- const HistoryItemVector& childItems = item->children();
-
- int size = childItems.size();
- for (int i = 0; i < size; ++i) {
- String childName = childItems[i]->target();
- HistoryItem* fromChildItem = fromItem->childItemWithName(childName);
- ASSERT(fromChildItem || fromItem->isTargetItem());
- Frame* childFrame = m_frame->tree()->child(childName);
- ASSERT(childFrame);
- childFrame->loader()->recursiveGoToItem(childItems[i].get(), fromChildItem, type);
- }
- } else {
- loadItem(item, type);
- }
-}
-
-// helper method that determines whether the subframes described by the item's subitems
-// match our own current frameset
-bool FrameLoader::childFramesMatchItem(HistoryItem* item) const
-{
- const HistoryItemVector& childItems = item->children();
- if (childItems.size() != m_frame->tree()->childCount())
- return false;
-
- unsigned size = childItems.size();
- for (unsigned i = 0; i < size; ++i)
- if (!m_frame->tree()->child(childItems[i]->target()))
- return false;
-
- // Found matches for all item targets
- return true;
-}
-
-// There are 3 things you might think of as "history", all of which are handled by these functions.
-//
-// 1) Back/forward: The m_currentHistoryItem is part of this mechanism.
-// 2) Global history: Handled by the client.
-// 3) Visited links: Handled by the PageGroup.
-
-void FrameLoader::updateHistoryForStandardLoad()
-{
- LOG(History, "WebCoreHistory: Updating History for Standard Load in frame %s", documentLoader()->url().string().ascii().data());
-
- Settings* settings = m_frame->settings();
- bool needPrivacy = !settings || settings->privateBrowsingEnabled();
- const KURL& historyURL = documentLoader()->urlForHistory();
-
- // If the navigation occured during load and this is a subframe, update the current
- // back/forward item rather than adding a new one and don't add the new URL to global
- // history at all. But do add it to visited links. <rdar://problem/5333496>
- bool frameNavigationDuringLoad = false;
- if (m_navigationDuringLoad) {
- HTMLFrameOwnerElement* owner = m_frame->ownerElement();
- frameNavigationDuringLoad = owner && !owner->createdByParser();
- m_navigationDuringLoad = false;
- }
-
- if (!frameNavigationDuringLoad && !documentLoader()->isClientRedirect()) {
- if (!historyURL.isEmpty()) {
- addBackForwardItemClippedAtTarget(true);
- if (!needPrivacy)
- m_client->updateGlobalHistory(historyURL);
- }
- } else if (documentLoader()->unreachableURL().isEmpty() && m_currentHistoryItem) {
- m_currentHistoryItem->setURL(documentLoader()->url());
- m_currentHistoryItem->setFormInfoFromRequest(documentLoader()->request());
- }
-
- if (!historyURL.isEmpty() && !needPrivacy) {
- if (Page* page = m_frame->page())
- page->group().addVisitedLink(historyURL);
- }
-}
-
-void FrameLoader::updateHistoryForClientRedirect()
-{
-#if !LOG_DISABLED
- if (documentLoader())
- LOG(History, "WebCoreHistory: Updating History for client redirect in frame %s", documentLoader()->title().utf8().data());
-#endif
-
- // Clear out form data so we don't try to restore it into the incoming page. Must happen after
- // webcore has closed the URL and saved away the form state.
- if (m_currentHistoryItem) {
- m_currentHistoryItem->clearDocumentState();
- m_currentHistoryItem->clearScrollPoint();
- }
-
- Settings* settings = m_frame->settings();
- bool needPrivacy = !settings || settings->privateBrowsingEnabled();
- const KURL& historyURL = documentLoader()->urlForHistory();
-
- if (!historyURL.isEmpty() && !needPrivacy) {
- if (Page* page = m_frame->page())
- page->group().addVisitedLink(historyURL);
- }
-}
-
-void FrameLoader::updateHistoryForBackForwardNavigation()
-{
-#if !LOG_DISABLED
- if (documentLoader())
- LOG(History, "WebCoreHistory: Updating History for back/forward navigation in frame %s", documentLoader()->title().utf8().data());
-#endif
-
- // Must grab the current scroll position before disturbing it
- saveScrollPositionAndViewStateToItem(m_previousHistoryItem.get());
-}
-
-void FrameLoader::updateHistoryForReload()
-{
-#if !LOG_DISABLED
- if (documentLoader())
- LOG(History, "WebCoreHistory: Updating History for reload in frame %s", documentLoader()->title().utf8().data());
-#endif
-
- if (m_currentHistoryItem) {
- pageCache()->remove(m_currentHistoryItem.get());
-
- if (loadType() == FrameLoadTypeReload)
- saveScrollPositionAndViewStateToItem(m_currentHistoryItem.get());
-
- // Sometimes loading a page again leads to a different result because of cookies. Bugzilla 4072
- if (documentLoader()->unreachableURL().isEmpty())
- m_currentHistoryItem->setURL(documentLoader()->requestURL());
- }
-}
-
-void FrameLoader::updateHistoryForRedirectWithLockedHistory()
-{
-#if !LOG_DISABLED
- if (documentLoader())
- LOG(History, "WebCoreHistory: Updating History for internal load in frame %s", documentLoader()->title().utf8().data());
-#endif
-
- Settings* settings = m_frame->settings();
- bool needPrivacy = !settings || settings->privateBrowsingEnabled();
- const KURL& historyURL = documentLoader()->urlForHistory();
-
- if (documentLoader()->isClientRedirect()) {
- if (!m_currentHistoryItem && !m_frame->tree()->parent()) {
- addBackForwardItemClippedAtTarget(true);
- if (!needPrivacy && !historyURL.isEmpty())
- m_client->updateGlobalHistory(historyURL);
- }
- if (m_currentHistoryItem) {
- m_currentHistoryItem->setURL(documentLoader()->url());
- m_currentHistoryItem->setFormInfoFromRequest(documentLoader()->request());
- }
- } else {
- Frame* parentFrame = m_frame->tree()->parent();
- if (parentFrame && parentFrame->loader()->m_currentHistoryItem)
- parentFrame->loader()->m_currentHistoryItem->addChildItem(createHistoryItem(true));
- }
-
- if (!historyURL.isEmpty() && !needPrivacy) {
- if (Page* page = m_frame->page())
- page->group().addVisitedLink(historyURL);
- }
-}
-
-void FrameLoader::updateHistoryForCommit()
-{
-#if !LOG_DISABLED
- if (documentLoader())
- LOG(History, "WebCoreHistory: Updating History for commit in frame %s", documentLoader()->title().utf8().data());
-#endif
- FrameLoadType type = loadType();
- if (isBackForwardLoadType(type) ||
- (type == FrameLoadTypeReload && !provisionalDocumentLoader()->unreachableURL().isEmpty())) {
- // Once committed, we want to use current item for saving DocState, and
- // the provisional item for restoring state.
- // Note previousItem must be set before we close the URL, which will
- // happen when the data source is made non-provisional below
- m_previousHistoryItem = m_currentHistoryItem;
- ASSERT(m_provisionalHistoryItem);
- m_currentHistoryItem = m_provisionalHistoryItem;
- m_provisionalHistoryItem = 0;
- }
-}
-
-void FrameLoader::updateHistoryForAnchorScroll()
-{
- if (m_URL.isEmpty())
- return;
-
- Settings* settings = m_frame->settings();
- if (!settings || settings->privateBrowsingEnabled())
- return;
-
- Page* page = m_frame->page();
- if (!page)
- return;
-
- page->group().addVisitedLink(m_URL);
-}
-
-// Walk the frame tree, telling all frames to save their form state into their current
-// history item.
-void FrameLoader::saveDocumentAndScrollState()
-{
- for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame)) {
- frame->loader()->saveDocumentState();
- frame->loader()->saveScrollPositionAndViewStateToItem(frame->loader()->currentHistoryItem());
- }
-}
-
-// FIXME: These 6 setter/getters are here for a dwindling number of users in WebKit, WebFrame
-// being the primary one. After they're no longer needed there, they can be removed!
-HistoryItem* FrameLoader::currentHistoryItem()
-{
- return m_currentHistoryItem.get();
-}
-
-HistoryItem* FrameLoader::previousHistoryItem()
-{
- return m_previousHistoryItem.get();
-}
-
-HistoryItem* FrameLoader::provisionalHistoryItem()
-{
- return m_provisionalHistoryItem.get();
-}
-
-void FrameLoader::setCurrentHistoryItem(PassRefPtr<HistoryItem> item)
-{
- m_currentHistoryItem = item;
-}
-
-void FrameLoader::setPreviousHistoryItem(PassRefPtr<HistoryItem> item)
-{
- m_previousHistoryItem = item;
-}
-
-void FrameLoader::setProvisionalHistoryItem(PassRefPtr<HistoryItem> item)
-{
- m_provisionalHistoryItem = item;
-}
-
-void FrameLoader::setMainDocumentError(DocumentLoader* loader, const ResourceError& error)
-{
- m_client->setMainDocumentError(loader, error);
-}
-
-void FrameLoader::mainReceivedCompleteError(DocumentLoader* loader, const ResourceError& error)
-{
- loader->setPrimaryLoadComplete(true);
- m_client->dispatchDidLoadMainResource(activeDocumentLoader());
- checkCompleted();
- if (m_frame->page())
- checkLoadComplete();
-}
-
-void FrameLoader::mainReceivedError(const ResourceError& error, bool isComplete)
-{
- activeDocumentLoader()->mainReceivedError(error, isComplete);
-}
-
-ResourceError FrameLoader::cancelledError(const ResourceRequest& request) const
-{
- ResourceError error = m_client->cancelledError(request);
- error.setIsCancellation(true);
- return error;
-}
-
-ResourceError FrameLoader::blockedError(const ResourceRequest& request) const
-{
- return m_client->blockedError(request);
-}
-
-ResourceError FrameLoader::cannotShowURLError(const ResourceRequest& request) const
-{
- return m_client->cannotShowURLError(request);
-}
-
-ResourceError FrameLoader::fileDoesNotExistError(const ResourceResponse& response) const
-{
- return m_client->fileDoesNotExistError(response);
-}
-
-void FrameLoader::didFinishLoad(ResourceLoader* loader)
-{
- if (Page* page = m_frame->page())
- page->progress()->completeProgress(loader->identifier());
- dispatchDidFinishLoading(loader->documentLoader(), loader->identifier());
-}
-
-void FrameLoader::didReceiveAuthenticationChallenge(ResourceLoader* loader, const AuthenticationChallenge& currentWebChallenge)
-{
- m_client->dispatchDidReceiveAuthenticationChallenge(loader->documentLoader(), loader->identifier(), currentWebChallenge);
-}
-
-void FrameLoader::didCancelAuthenticationChallenge(ResourceLoader* loader, const AuthenticationChallenge& currentWebChallenge)
-{
- m_client->dispatchDidCancelAuthenticationChallenge(loader->documentLoader(), loader->identifier(), currentWebChallenge);
-}
-
-PolicyCheck::PolicyCheck()
- : m_navigationFunction(0)
- , m_newWindowFunction(0)
- , m_contentFunction(0)
-{
-}
-
-void PolicyCheck::clear()
-{
- clearRequest();
- m_navigationFunction = 0;
- m_newWindowFunction = 0;
- m_contentFunction = 0;
-}
-
-void PolicyCheck::set(const ResourceRequest& request, PassRefPtr<FormState> formState,
- NavigationPolicyDecisionFunction function, void* argument)
-{
- m_request = request;
- m_formState = formState;
- m_frameName = String();
-
- m_navigationFunction = function;
- m_newWindowFunction = 0;
- m_contentFunction = 0;
- m_argument = argument;
-}
-
-void PolicyCheck::set(const ResourceRequest& request, PassRefPtr<FormState> formState,
- const String& frameName, NewWindowPolicyDecisionFunction function, void* argument)
-{
- m_request = request;
- m_formState = formState;
- m_frameName = frameName;
-
- m_navigationFunction = 0;
- m_newWindowFunction = function;
- m_contentFunction = 0;
- m_argument = argument;
-}
-
-void PolicyCheck::set(ContentPolicyDecisionFunction function, void* argument)
-{
- m_request = ResourceRequest();
- m_formState = 0;
- m_frameName = String();
-
- m_navigationFunction = 0;
- m_newWindowFunction = 0;
- m_contentFunction = function;
- m_argument = argument;
-}
-
-void PolicyCheck::call(bool shouldContinue)
-{
- if (m_navigationFunction)
- m_navigationFunction(m_argument, m_request, m_formState.get(), shouldContinue);
- if (m_newWindowFunction)
- m_newWindowFunction(m_argument, m_request, m_formState.get(), m_frameName, shouldContinue);
- ASSERT(!m_contentFunction);
-}
-
-void PolicyCheck::call(PolicyAction action)
-{
- ASSERT(!m_navigationFunction);
- ASSERT(!m_newWindowFunction);
- ASSERT(m_contentFunction);
- m_contentFunction(m_argument, action);
-}
-
-void PolicyCheck::clearRequest()
-{
- m_request = ResourceRequest();
- m_formState = 0;
- m_frameName = String();
-}
-
-void PolicyCheck::cancel()
-{
- clearRequest();
- if (m_navigationFunction)
- m_navigationFunction(m_argument, m_request, m_formState.get(), false);
- if (m_newWindowFunction)
- m_newWindowFunction(m_argument, m_request, m_formState.get(), m_frameName, false);
- if (m_contentFunction)
- m_contentFunction(m_argument, PolicyIgnore);
-}
-
-void FrameLoader::setTitle(const String& title)
-{
- documentLoader()->setTitle(title);
-}
-
-KURL FrameLoader::originalRequestURL() const
-{
- return activeDocumentLoader()->originalRequest().url();
-}
-
-String FrameLoader::referrer() const
-{
- return documentLoader()->request().httpReferrer();
-}
-
-void FrameLoader::dispatchWindowObjectAvailable()
-{
- // TODO(tc): We should also return early if we have no window shell.
- // But we can't check that until we refactor ScriptController.
- if (!m_frame->script()->isEnabled())
- return;
-
- m_client->windowObjectCleared();
-
- if (Page* page = m_frame->page()) {
- if (InspectorController* inspector = page->inspectorController())
- inspector->inspectedWindowScriptObjectCleared(m_frame);
- if (InspectorController* inspector = page->parentInspectorController())
- inspector->windowScriptObjectAvailable();
- }
-}
-
-Widget* FrameLoader::createJavaAppletWidget(const IntSize& size, Element* element, const HashMap<String, String>& args)
-{
- String baseURLString;
- Vector<String> paramNames;
- Vector<String> paramValues;
- HashMap<String, String>::const_iterator end = args.end();
- for (HashMap<String, String>::const_iterator it = args.begin(); it != end; ++it) {
- if (equalIgnoringCase(it->first, "baseurl"))
- baseURLString = it->second;
- paramNames.append(it->first);
- paramValues.append(it->second);
- }
-
- if (baseURLString.isEmpty())
- baseURLString = m_frame->document()->baseURL().string();
- KURL baseURL = completeURL(baseURLString);
-
- Widget* widget = m_client->createJavaAppletWidget(size, element, baseURL, paramNames, paramValues);
- if (widget)
- m_containsPlugIns = true;
-
- return widget;
-}
-
-void FrameLoader::didChangeTitle(DocumentLoader* loader)
-{
- m_client->didChangeTitle(loader);
-
- // The title doesn't get communicated to the WebView until we are committed.
- if (loader->isCommitted()) {
- // Must update the entries in the back-forward list too.
- if (m_currentHistoryItem)
- m_currentHistoryItem->setTitle(loader->title());
- // This must go through the WebFrame because it has the right notion of the current b/f item.
- m_client->setTitle(loader->title(), loader->urlForHistory());
- m_client->setMainFrameDocumentReady(true); // update observers with new DOMDocument
- m_client->dispatchDidReceiveTitle(loader->title());
- }
-}
-
-void FrameLoader::continueLoadWithData(SharedBuffer* buffer, const String& mimeType, const String& textEncoding, const KURL& url)
-{
- m_responseMIMEType = mimeType;
- didOpenURL(url);
-
- String encoding;
- if (m_frame)
- encoding = documentLoader()->overrideEncoding();
- bool userChosen = !encoding.isNull();
- if (encoding.isNull())
- encoding = textEncoding;
- setEncoding(encoding, userChosen);
-
- ASSERT(m_frame->document());
-
- addData(buffer->data(), buffer->size());
-}
-
-void FrameLoader::registerURLSchemeAsLocal(const String& scheme)
-{
- localSchemes().add(scheme);
-}
-
-bool FrameLoader::shouldTreatURLAsLocal(const String& url)
-{
- // This avoids an allocation of another String and the HashSet contains()
- // call for the file: and http: schemes.
- if (url.length() >= 5) {
- const UChar* s = url.characters();
- if (s[0] == 'h' && s[1] == 't' && s[2] == 't' && s[3] == 'p' && s[4] == ':')
- return false;
- if (s[0] == 'f' && s[1] == 'i' && s[2] == 'l' && s[3] == 'e' && s[4] == ':')
- return true;
- }
-
- int loc = url.find(':');
- if (loc == -1)
- return false;
-
- String scheme = url.left(loc);
- return localSchemes().contains(scheme);
-}
-
-bool FrameLoader::shouldTreatSchemeAsLocal(const String& scheme)
-{
- // This avoids an allocation of another String and the HashSet contains()
- // call for the file: and http: schemes.
- if (scheme.length() == 4) {
- const UChar* s = scheme.characters();
- if (s[0] == 'h' && s[1] == 't' && s[2] == 't' && s[3] == 'p')
- return false;
- if (s[0] == 'f' && s[1] == 'i' && s[2] == 'l' && s[3] == 'e')
- return true;
- }
-
- if (scheme.isEmpty())
- return false;
-
- return localSchemes().contains(scheme);
-}
-
-void FrameLoader::dispatchDidCommitLoad()
-{
- if (m_creatingInitialEmptyDocument)
- return;
-
-#ifndef NDEBUG
- m_didDispatchDidCommitLoad = true;
-#endif
-
- m_client->dispatchDidCommitLoad();
-
- if (Page* page = m_frame->page())
- page->inspectorController()->didCommitLoad(m_documentLoader.get());
-}
-
-void FrameLoader::dispatchAssignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
-{
- m_client->assignIdentifierToInitialRequest(identifier, loader, request);
-
- if (Page* page = m_frame->page())
- page->inspectorController()->identifierForInitialRequest(identifier, loader, request);
-}
-
-void FrameLoader::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
-{
- m_client->dispatchWillSendRequest(loader, identifier, request, redirectResponse);
-
- if (Page* page = m_frame->page())
- page->inspectorController()->willSendRequest(loader, identifier, request, redirectResponse);
-}
-
-void FrameLoader::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r)
-{
- m_client->dispatchDidReceiveResponse(loader, identifier, r);
-
- if (Page* page = m_frame->page())
- page->inspectorController()->didReceiveResponse(loader, identifier, r);
-}
-
-void FrameLoader::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int length)
-{
- m_client->dispatchDidReceiveContentLength(loader, identifier, length);
-
- if (Page* page = m_frame->page())
- page->inspectorController()->didReceiveContentLength(loader, identifier, length);
-}
-
-void FrameLoader::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier)
-{
- m_client->dispatchDidFinishLoading(loader, identifier);
-
- if (Page* page = m_frame->page())
- page->inspectorController()->didFinishLoading(loader, identifier);
-}
-
-#if USE(LOW_BANDWIDTH_DISPLAY)
-
-bool FrameLoader::addLowBandwidthDisplayRequest(CachedResource* cache)
-{
- if (m_frame->document()->inLowBandwidthDisplay() == false)
- return false;
-
- // if cache is loaded, don't add to the list, where notifyFinished() is expected.
- if (cache->isLoaded())
- return false;
-
- switch (cache->type()) {
- case CachedResource::CSSStyleSheet:
- case CachedResource::Script:
- m_needToSwitchOutLowBandwidthDisplay = true;
- m_externalRequestsInLowBandwidthDisplay.add(cache);
- cache->addClient(this);
- return true;
- case CachedResource::ImageResource:
- case CachedResource::FontResource:
-#if ENABLE(XSLT)
- case CachedResource::XSLStyleSheet:
-#endif
-#if ENABLE(XBL)
- case CachedResource::XBLStyleSheet:
-#endif
- return false;
- }
-
- ASSERT_NOT_REACHED();
- return false;
-}
-
-void FrameLoader::removeAllLowBandwidthDisplayRequests()
-{
- HashSet<CachedResource*>::iterator end = m_externalRequestsInLowBandwidthDisplay.end();
- for (HashSet<CachedResource*>::iterator it = m_externalRequestsInLowBandwidthDisplay.begin(); it != end; ++it)
- (*it)->removeClient(this);
- m_externalRequestsInLowBandwidthDisplay.clear();
-}
-
-void FrameLoader::notifyFinished(CachedResource* script)
-{
- HashSet<CachedResource*>::iterator it = m_externalRequestsInLowBandwidthDisplay.find(script);
- if (it != m_externalRequestsInLowBandwidthDisplay.end()) {
- (*it)->removeClient(this);
- m_externalRequestsInLowBandwidthDisplay.remove(it);
- switchOutLowBandwidthDisplayIfReady();
- }
-}
-
-void FrameLoader::switchOutLowBandwidthDisplayIfReady()
-{
- RefPtr<Document> oldDoc = m_frame->document();
- if (oldDoc->inLowBandwidthDisplay()) {
- if (!m_needToSwitchOutLowBandwidthDisplay) {
- // no need to switch, just reset state
- oldDoc->setLowBandwidthDisplay(false);
- removeAllLowBandwidthDisplayRequests();
- m_pendingSourceInLowBandwidthDisplay = String();
- m_finishedParsingDuringLowBandwidthDisplay = false;
- return;
- } else if (m_externalRequestsInLowBandwidthDisplay.isEmpty() ||
- m_pendingSourceInLowBandwidthDisplay.length() > cMaxPendingSourceLengthInLowBandwidthDisplay) {
- // clear the flag first
- oldDoc->setLowBandwidthDisplay(false);
-
- // similar to clear(), should be refactored to share more code
- oldDoc->cancelParsing();
- oldDoc->detach();
- if (m_frame->script()->isEnabled())
- m_frame->script()->clearWindowShell();
- if (m_frame->view())
- m_frame->view()->clear();
-
- // similar to begin(), should be refactored to share more code
- RefPtr<Document> newDoc = DOMImplementation::createDocument(m_responseMIMEType, m_frame, m_frame->inViewSourceMode());
- m_frame->setDocument(newDoc);
- newDoc->setURL(m_URL);
- if (m_decoder)
- newDoc->setDecoder(m_decoder.get());
- restoreDocumentState();
- dispatchWindowObjectAvailable();
- newDoc->implicitOpen();
-
- // swap DocLoader ownership
- DocLoader* docLoader = newDoc->docLoader();
- newDoc->setDocLoader(oldDoc->docLoader());
- newDoc->docLoader()->replaceDocument(newDoc.get());
- docLoader->replaceDocument(oldDoc.get());
- oldDoc->setDocLoader(docLoader);
-
- // drop the old doc
- oldDoc = 0;
-
- // write decoded data to the new doc, similar to write()
- if (m_pendingSourceInLowBandwidthDisplay.length()) {
- // set cachePolicy to Cache to use the loaded resource
- newDoc->docLoader()->setCachePolicy(CachePolicyCache);
- if (m_decoder->encoding().usesVisualOrdering())
- newDoc->setVisuallyOrdered();
- newDoc->recalcStyle(Node::Force);
- newDoc->tokenizer()->write(m_pendingSourceInLowBandwidthDisplay, true);
-
- if (m_finishedParsingDuringLowBandwidthDisplay)
- newDoc->finishParsing();
- }
-
- // update rendering
- newDoc->updateRendering();
-
- // reset states
- removeAllLowBandwidthDisplayRequests();
- m_pendingSourceInLowBandwidthDisplay = String();
- m_finishedParsingDuringLowBandwidthDisplay = false;
- m_needToSwitchOutLowBandwidthDisplay = false;
- }
- }
-}
-
-#endif
-
-void FrameLoader::unloadListenerChanged() {
- m_client->unloadListenerChanged();
-}
-
-} // namespace WebCore
diff --git a/webkit/pending/FrameLoader.h b/webkit/pending/FrameLoader.h
deleted file mode 100644
index d90a30f..0000000
--- a/webkit/pending/FrameLoader.h
+++ /dev/null
@@ -1,702 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FrameLoader_h
-#define FrameLoader_h
-
-#include "CachedResource.h"
-#include "CachePolicy.h"
-#include "FormState.h"
-#include "FrameLoaderTypes.h"
-#include "KURL.h"
-#include "StringHash.h"
-#include "Timer.h"
-#include <wtf/Forward.h>
-#include <wtf/HashSet.h>
-#include <wtf/HashMap.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/RefPtr.h>
-#include "ResourceRequest.h"
-#if USE(LOW_BANDWIDTH_DISPLAY)
-#include "CachedResourceClient.h"
-#endif
-
-namespace WebCore {
-
- class Archive;
- class ArchiveResource;
- class AuthenticationChallenge;
- class CachedPage;
- class Document;
- class DocumentLoader;
- class Element;
- class Event;
- class FormData;
- class Frame;
- class FrameLoaderClient;
- class HistoryItem;
- class HTMLFormElement;
- class HTMLFrameOwnerElement;
- class IconLoader;
- class IntSize;
- class NavigationAction;
- class Node;
- class Page;
- class RenderPart;
- class ResourceError;
- class ResourceLoader;
- class ResourceRequest;
- class ResourceResponse;
- class SecurityOrigin;
- class SharedBuffer;
- class SubstituteData;
- class TextResourceDecoder;
- class Widget;
-
- struct FormSubmission;
- struct FrameLoadRequest;
- struct ScheduledRedirection;
- struct WindowFeatures;
-
- bool isBackForwardLoadType(FrameLoadType);
-
- typedef void (*NavigationPolicyDecisionFunction)(void* argument,
- const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue);
- typedef void (*NewWindowPolicyDecisionFunction)(void* argument,
- const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue);
- typedef void (*ContentPolicyDecisionFunction)(void* argument, PolicyAction);
-
- class PolicyCheck {
- public:
- PolicyCheck();
-
- void clear();
- void set(const ResourceRequest&, PassRefPtr<FormState>,
- NavigationPolicyDecisionFunction, void* argument);
- void set(const ResourceRequest&, PassRefPtr<FormState>, const String& frameName,
- NewWindowPolicyDecisionFunction, void* argument);
- void set(ContentPolicyDecisionFunction, void* argument);
-
- const ResourceRequest& request() const { return m_request; }
- void clearRequest();
-
- void call(bool shouldContinue);
- void call(PolicyAction);
- void cancel();
-
- private:
- ResourceRequest m_request;
- RefPtr<FormState> m_formState;
- String m_frameName;
-
- NavigationPolicyDecisionFunction m_navigationFunction;
- NewWindowPolicyDecisionFunction m_newWindowFunction;
- ContentPolicyDecisionFunction m_contentFunction;
- void* m_argument;
- };
-
- class FrameLoader : Noncopyable
-#if USE(LOW_BANDWIDTH_DISPLAY)
- , private CachedResourceClient
-#endif
- {
- public:
- FrameLoader(Frame*, FrameLoaderClient*);
- ~FrameLoader();
-
- void init();
-
- Frame* frame() const { return m_frame; }
-
- // FIXME: This is not cool, people. We should aim to consolidate these variety of loading related methods into a smaller set,
- // and try to reuse more of the same logic by extracting common code paths.
- void prepareForLoadStart();
- void setupForReplace();
- void setupForReplaceByMIMEType(const String& newMIMEType);
-
- void loadWithDocumentLoader(DocumentLoader*, FrameLoadType, PassRefPtr<FormState>); // Calls continueLoadAfterNavigationPolicy
- void load(DocumentLoader*); // Calls loadWithDocumentLoader
-
- void loadWithNavigationAction(const ResourceRequest&, const NavigationAction&, // Calls loadWithDocumentLoader()
- FrameLoadType, PassRefPtr<FormState>);
-
- void loadPostRequest(const ResourceRequest& inRequest, const String& referrer, // Called by loadFrameRequestWithFormAndValues(), calls loadWithNavigationAction
- const String& frameName, Event* event, PassRefPtr<FormState> prpFormState);
-
- void loadURL(const KURL& newURL, const String& referrer, const String& frameName, // Called by loadFrameRequestWithFormAndValues(), calls loadWithNavigationAction or else dispatches to navigation policy delegate
- FrameLoadType, Event* event, PassRefPtr<FormState> prpFormState);
- void loadURLIntoChildFrame(const KURL&, const String& referer, Frame*);
-
- void loadFrameRequestWithFormState(const FrameLoadRequest&, bool lockHistory, Event*, PassRefPtr<FormState>);
- void loadFrameRequestWithFormAndValues(const FrameLoadRequest&, bool lockHistory, // Called by submitForm, calls loadPostRequest()
- Event*, HTMLFormElement*, const HashMap<String, String>& formValues);
-
- void load(const ResourceRequest&); // Called by WebFrame, calls (ResourceRequest, SubstituteData)
- void load(const ResourceRequest&, const SubstituteData&); // Called both by WebFrame and internally, calls (DocumentLoader*)
- void load(const ResourceRequest&, const String& frameName); // Called by WebPluginController
-
- void loadArchive(PassRefPtr<Archive> archive);
-
- // Returns true for any non-local URL. If Document parameter is supplied, its local load policy dictates,
- // otherwise if referrer is non-empty and represents a local file, then the local load is allowed.
- static bool canLoad(const KURL&, const String& referrer, const Document* theDocument = 0);
- static void reportLocalLoadFailed(Frame*, const String& url);
-
- static bool shouldHideReferrer(const KURL& url, const String& referrer);
-
- // Called by createWindow in JSDOMWindowBase.cpp, e.g. to fulfill a modal dialog creation
- Frame* createWindow(FrameLoader* frameLoaderForFrameLookup, const FrameLoadRequest&, const WindowFeatures&, bool& created);
-
- unsigned long loadResourceSynchronously(const ResourceRequest&, ResourceError&, ResourceResponse&, Vector<char>& data);
-
- bool canHandleRequest(const ResourceRequest&);
-
- // Also not cool.
- void stopAllLoaders();
- void stopForUserCancel(bool deferCheckLoadComplete = false);
-
- bool isLoadingMainResource() const { return m_isLoadingMainResource; }
- bool isLoading() const;
- bool frameHasLoaded() const;
-
- int numPendingOrLoadingRequests(bool recurse) const;
- bool isReloading() const;
- String referrer() const;
- String outgoingReferrer() const;
- void loadEmptyDocumentSynchronously();
-
- DocumentLoader* activeDocumentLoader() const;
- DocumentLoader* documentLoader() const;
- DocumentLoader* policyDocumentLoader() const;
- DocumentLoader* provisionalDocumentLoader() const;
- DocumentLoader* policyDocumentLoader();
- FrameState state() const;
- static double timeOfLastCompletedLoad();
-
- void didReceiveAuthenticationChallenge(ResourceLoader*, const AuthenticationChallenge&);
- void didCancelAuthenticationChallenge(ResourceLoader*, const AuthenticationChallenge&);
-
- void assignIdentifierToInitialRequest(unsigned long identifier, const ResourceRequest&);
- void willSendRequest(ResourceLoader*, ResourceRequest&, const ResourceResponse& redirectResponse);
- void didReceiveResponse(ResourceLoader*, const ResourceResponse&);
- void didReceiveData(ResourceLoader*, const char*, int, int lengthReceived);
- void didFinishLoad(ResourceLoader*);
- void didFailToLoad(ResourceLoader*, const ResourceError&);
- const ResourceRequest& originalRequest() const;
- const ResourceRequest& initialRequest() const;
- void receivedMainResourceError(const ResourceError&, bool isComplete);
- void receivedData(const char*, int);
-
- void handleFallbackContent();
- bool isStopping() const;
-
- void finishedLoading();
-
- ResourceError cancelledError(const ResourceRequest&) const;
- ResourceError fileDoesNotExistError(const ResourceResponse&) const;
- ResourceError blockedError(const ResourceRequest&) const;
- ResourceError cannotShowURLError(const ResourceRequest&) const;
-
- void cannotShowMIMEType(const ResourceResponse&);
- ResourceError interruptionForPolicyChangeError(const ResourceRequest&);
-
- bool isHostedByObjectElement() const;
- bool isLoadingMainFrame() const;
- bool canShowMIMEType(const String& MIMEType) const;
- bool representationExistsForURLScheme(const String& URLScheme);
- String generatedMIMETypeForURLScheme(const String& URLScheme);
-
- void notifyIconChanged();
-
- void checkNavigationPolicy(const ResourceRequest&, NavigationPolicyDecisionFunction function, void* argument);
- void checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction, void* argument);
- void cancelContentPolicyCheck();
-
- void reload();
- void reloadAllowingStaleData(const String& overrideEncoding);
-
- void didReceiveServerRedirectForProvisionalLoadForFrame();
- void finishedLoadingDocument(DocumentLoader*);
- void committedLoad(DocumentLoader*, const char*, int);
- bool isReplacing() const;
- void setReplacing();
- void revertToProvisional(DocumentLoader*);
- void setMainDocumentError(DocumentLoader*, const ResourceError&);
- void mainReceivedCompleteError(DocumentLoader*, const ResourceError&);
- bool subframeIsLoading() const;
- void willChangeTitle(DocumentLoader*);
- void didChangeTitle(DocumentLoader*);
-
- FrameLoadType loadType() const;
- FrameLoadType policyLoadType() const { return m_policyLoadType; }
-
- void didFirstLayout();
- bool firstLayoutDone() const;
-
- void clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress);
- void clientRedirected(const KURL&, double delay, double fireDate, bool lockHistory, bool isJavaScriptFormAction);
- bool shouldReload(const KURL& currentURL, const KURL& destinationURL);
-
- bool isQuickRedirectComing() const;
-
- void sendRemainingDelegateMessages(unsigned long identifier, const ResourceResponse&, int length, const ResourceError&);
- void requestFromDelegate(ResourceRequest&, unsigned long& identifier, ResourceError&);
- void loadedResourceFromMemoryCache(const CachedResource*);
-
- void recursiveCheckLoadComplete();
- void checkLoadComplete();
- void detachFromParent();
- void detachChildren();
-
- void addExtraFieldsToRequest(ResourceRequest&, bool isMainResource, bool alwaysFromRequest);
-
- FrameLoaderClient* client() const;
-
- void setDefersLoading(bool);
-
- void changeLocation(const String& url, const String& referrer, bool lockHistory = true, bool userGesture = false);
- void changeLocation(const KURL&, const String& referrer, bool lockHistory = true, bool userGesture = false);
- void urlSelected(const ResourceRequest&, const String& target, Event*, bool lockHistory, bool userGesture);
- void urlSelected(const FrameLoadRequest&, Event*, bool lockHistory);
-
- bool requestFrame(HTMLFrameOwnerElement*, const String& url, const AtomicString& frameName);
- Frame* loadSubframe(HTMLFrameOwnerElement*, const KURL&, const String& name, const String& referrer);
-
- void submitForm(const char* action, const String& url, PassRefPtr<FormData>, const String& target, const String& contentType, const String& boundary, Event*);
- void submitFormAgain();
- void submitForm(const FrameLoadRequest&, Event*);
-
- void stop();
- void stopLoading(bool sendUnload);
- bool closeURL();
-
- void didExplicitOpen();
-
- KURL iconURL();
- void commitIconURLToIconDatabase(const KURL&);
-
- KURL baseURL() const;
- String baseTarget() const;
- KURL dataURLBaseFromRequest(const ResourceRequest& request) const;
-
- bool isScheduledLocationChangePending() const { return m_scheduledRedirection && isLocationChange(*m_scheduledRedirection); }
- void scheduleHTTPRedirection(double delay, const String& url);
- void scheduleLocationChange(const String& url, const String& referrer, bool lockHistory = true, bool userGesture = false);
- void scheduleRefresh(bool userGesture = false);
- void scheduleHistoryNavigation(int steps);
-
- bool canGoBackOrForward(int distance) const;
- void goBackOrForward(int distance);
- void goToHistoryItem(HistoryItem* item);
- int getHistoryLength();
- KURL historyURL(int distance);
-
- void begin();
- void begin(const KURL&, bool dispatchWindowObjectAvailable = true, SecurityOrigin* forcedSecurityOrigin = 0);
-
- void write(const char* str, int len = -1, bool flush = false);
- void write(const String&);
- void end();
- void endIfNotLoadingMainResource();
-
- void setEncoding(const String& encoding, bool userChosen);
- String encoding() const;
-
- // Returns true if url is a JavaScript URL.
- bool executeIfJavaScriptURL(const KURL& url, bool userGesture = false, bool replaceDocument = true);
-
- // Executes a script, ignore the result. For back compability.
- void executeScript(const String& url, int baseLine, const String& script);
- void executeScript(const String& script, bool forceUserGesture = false);
-
- // Executes a script, returns results as a string, and sets succ
- // to true if no errors.
- String executeScript(const String& url, int baseLine, const String& script, bool* succ);
- String executeScript(const String& script, bool* succ, bool forceUserGesture = false);
-
- void gotoAnchor();
- bool gotoAnchor(const String& name); // returns true if the anchor was found
- void scrollToAnchor(const KURL&);
-
- void tokenizerProcessedData();
-
- void handledOnloadEvents();
- String userAgent(const KURL&) const;
-
- Widget* createJavaAppletWidget(const IntSize&, Element*, const HashMap<String, String>& args);
-
- void dispatchWindowObjectAvailable();
- void restoreDocumentState();
-
- Frame* opener();
- void setOpener(Frame*);
- bool openedByDOM() const;
- void setOpenedByDOM();
-
- void provisionalLoadStarted();
-
- bool userGestureHint();
-
- void resetMultipleFormSubmissionProtection();
- void didNotOpenURL(const KURL&);
-
- void addData(const char* bytes, int length);
-
- bool canCachePage();
-
- void checkCallImplicitClose();
- bool didOpenURL(const KURL&);
-
- void frameDetached();
-
- const KURL& url() const { return m_URL; }
-
- void updateBaseURLForEmptyDocument();
-
- void setResponseMIMEType(const String&);
- const String& responseMIMEType() const;
-
- bool containsPlugins() const;
-
- void loadDone();
- void finishedParsing();
- void checkCompleted();
- void scheduleCheckCompleted();
- void scheduleCheckLoadComplete();
-
- void clearRecordedFormValues();
- void setFormAboutToBeSubmitted(PassRefPtr<HTMLFormElement> element);
- void recordFormValue(const String& name, const String& value);
-
- bool isComplete() const;
-
- bool requestObject(RenderPart* frame, const String& url, const AtomicString& frameName,
- const String& serviceType, const Vector<String>& paramNames, const Vector<String>& paramValues);
-
- KURL completeURL(const String& url);
-
- void didTellClientAboutLoad(const String& url);
- bool haveToldClientAboutLoad(const String& url);
-
- KURL originalRequestURL() const;
-
- void cancelAndClear();
-
- void setTitle(const String&);
-
- bool shouldTreatURLAsSameAsCurrent(const KURL&) const;
-
- void commitProvisionalLoad(PassRefPtr<CachedPage>);
-
- void goToItem(HistoryItem*, FrameLoadType);
- void saveDocumentAndScrollState();
- void saveScrollPositionAndViewStateToItem(HistoryItem*);
-
- // FIXME: These accessors are here for a dwindling number of users in WebKit, WebFrame
- // being the primary one. After they're no longer needed there, they can be removed!
- HistoryItem* currentHistoryItem();
- HistoryItem* previousHistoryItem();
- HistoryItem* provisionalHistoryItem();
- void setCurrentHistoryItem(PassRefPtr<HistoryItem>);
- void setPreviousHistoryItem(PassRefPtr<HistoryItem>);
- void setProvisionalHistoryItem(PassRefPtr<HistoryItem>);
-
- void continueLoadWithData(SharedBuffer*, const String& mimeType, const String& textEncoding, const KURL&);
-
- enum LocalLoadPolicy {
- AllowLocalLoadsForAll, // No restriction on local loads.
- AllowLocalLoadsForLocalAndSubstituteData,
- AllowLocalLoadsForLocalOnly,
- };
- static void setLocalLoadPolicy(LocalLoadPolicy);
- static bool restrictAccessToLocal();
- static bool allowSubstituteDataAccessToLocal();
-
- static void registerURLSchemeAsLocal(const String& scheme);
- static bool shouldTreatURLAsLocal(const String&);
- static bool shouldTreatSchemeAsLocal(const String&);
-
-#if USE(LOW_BANDWIDTH_DISPLAY)
- bool addLowBandwidthDisplayRequest(CachedResource*);
- void needToSwitchOutLowBandwidthDisplay() { m_needToSwitchOutLowBandwidthDisplay = true; }
-
- // Client can control whether to use low bandwidth display on a per frame basis.
- // However, this should only be used for the top frame, not sub-frame.
- void setUseLowBandwidthDisplay(bool lowBandwidth) { m_useLowBandwidthDisplay = lowBandwidth; }
- bool useLowBandwidthDisplay() const { return m_useLowBandwidthDisplay; }
-#endif
-
- bool committingFirstRealLoad() const { return !m_creatingInitialEmptyDocument && !m_committedFirstRealDocumentLoad; }
-
- void iconLoadDecisionAvailable();
-
- bool shouldAllowNavigation(Frame* targetFrame) const;
- Frame* findFrameForNavigation(const AtomicString& name);
-
- void startIconLoader();
-
- void applyUserAgent(ResourceRequest& request);
-
- bool firingUnloadEvents() { return m_firingUnloadEvents; }
- void setFiringUnloadEvents(bool value) { m_firingUnloadEvents = value; }
-
- void unloadListenerChanged();
-
- private:
- PassRefPtr<HistoryItem> createHistoryItem(bool useOriginal);
- PassRefPtr<HistoryItem> createHistoryItemTree(Frame* targetFrame, bool clipAtTarget);
-
- void addBackForwardItemClippedAtTarget(bool doClip);
- void restoreScrollPositionAndViewState();
- void saveDocumentState();
- void loadItem(HistoryItem*, FrameLoadType);
- bool urlsMatchItem(HistoryItem*) const;
- void invalidateCurrentItemCachedPage();
- void recursiveGoToItem(HistoryItem*, HistoryItem*, FrameLoadType);
- bool childFramesMatchItem(HistoryItem*) const;
-
- void updateHistoryForBackForwardNavigation();
- void updateHistoryForReload();
- void updateHistoryForStandardLoad();
- void updateHistoryForRedirectWithLockedHistory();
- void updateHistoryForClientRedirect();
- void updateHistoryForCommit();
- void updateHistoryForAnchorScroll();
-
- void redirectionTimerFired(Timer<FrameLoader>*);
- void checkCompletedTimerFired(Timer<FrameLoader>*);
- void checkLoadCompleteTimerFired(Timer<FrameLoader>*);
-
- void cancelRedirection(bool newLoadInProgress = false);
-
- void started();
-
- void completed();
- void parentCompleted();
-
- bool shouldUsePlugin(const KURL&, const String& mimeType, bool hasFallback, bool& useFallback);
- bool loadPlugin(RenderPart*, const KURL&, const String& mimeType,
- const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback);
-
- bool loadProvisionalItemFromCachedPage();
- void cachePageForHistoryItem(HistoryItem*);
-
- void receivedFirstData();
-
- void updatePolicyBaseURL();
- void setPolicyBaseURL(const KURL&);
-
- // Also not cool.
- void stopLoadingSubframes();
-
- void clearProvisionalLoad();
- void markLoadComplete();
- void transitionToCommitted(PassRefPtr<CachedPage>);
- void frameLoadCompleted();
-
- void mainReceivedError(const ResourceError&, bool isComplete);
-
- void setLoadType(FrameLoadType);
-
- void checkNavigationPolicy(const ResourceRequest&, DocumentLoader*, PassRefPtr<FormState>,
- NavigationPolicyDecisionFunction, void* argument);
- void checkNewWindowPolicy(const NavigationAction&, const ResourceRequest&,
- PassRefPtr<FormState>, const String& frameName);
-
- void continueAfterNavigationPolicy(PolicyAction);
- void continueAfterNewWindowPolicy(PolicyAction);
- void continueAfterContentPolicy(PolicyAction);
- void continueLoadAfterWillSubmitForm(PolicyAction = PolicyUse);
-
- static void callContinueLoadAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue);
- void continueLoadAfterNavigationPolicy(const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue);
- static void callContinueLoadAfterNewWindowPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue);
- void continueLoadAfterNewWindowPolicy(const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue);
- static void callContinueFragmentScrollAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue);
- void continueFragmentScrollAfterNavigationPolicy(const ResourceRequest&, bool shouldContinue);
- bool shouldScrollToAnchor(bool isFormSubmission, FrameLoadType loadType, const KURL& url);
- void addHistoryItemForFragmentScroll();
-
- void stopPolicyCheck();
-
- void closeDocument();
-
- void checkLoadCompleteForThisFrame();
-
- void setDocumentLoader(DocumentLoader*);
- void setPolicyDocumentLoader(DocumentLoader*);
- void setProvisionalDocumentLoader(DocumentLoader*);
-
- void setState(FrameState);
-
- void closeOldDataSources();
- void open(CachedPage&);
- void opened();
- void updateHistoryAfterClientRedirect();
-
- void clear(bool clearWindowProperties = true, bool clearScriptObjects = true);
-
- bool shouldReloadToHandleUnreachableURL(DocumentLoader*);
- void handleUnimplementablePolicy(const ResourceError&);
-
- void scheduleRedirection(ScheduledRedirection*);
- void startRedirectionTimer();
- void stopRedirectionTimer();
-
-#if USE(LOW_BANDWIDTH_DISPLAY)
- // implementation of CachedResourceClient
- virtual void notifyFinished(CachedResource*);
-
- void removeAllLowBandwidthDisplayRequests();
- void switchOutLowBandwidthDisplayIfReady();
-#endif
-
- void dispatchDidCommitLoad();
- void dispatchAssignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&);
- void dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse);
- void dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&);
- void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int length);
- void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier);
-
- static bool isLocationChange(const ScheduledRedirection&);
-
- Frame* m_frame;
- FrameLoaderClient* m_client;
-
- FrameState m_state;
- FrameLoadType m_loadType;
-
- // Document loaders for the three phases of frame loading. Note that while
- // a new request is being loaded, the old document loader may still be referenced.
- // E.g. while a new request is in the "policy" state, the old document loader may
- // be consulted in particular as it makes sense to imply certain settings on the new loader.
- RefPtr<DocumentLoader> m_documentLoader;
- RefPtr<DocumentLoader> m_provisionalDocumentLoader;
- RefPtr<DocumentLoader> m_policyDocumentLoader;
-
- // This identifies the type of navigation action which prompted this load. Note
- // that WebKit conveys this value as the WebActionNavigationTypeKey value
- // on navigation action delegate callbacks.
- FrameLoadType m_policyLoadType;
- PolicyCheck m_policyCheck;
-
- bool m_delegateIsHandlingProvisionalLoadError;
- bool m_delegateIsDecidingNavigationPolicy;
- bool m_delegateIsHandlingUnimplementablePolicy;
-
- bool m_firstLayoutDone;
- bool m_quickRedirectComing;
- bool m_sentRedirectNotification;
- bool m_inStopAllLoaders;
- bool m_navigationDuringLoad;
-
- String m_outgoingReferrer;
-
- CachePolicy m_cachePolicy;
-
- HashSet<String> m_urlsClientKnowsAbout;
-
- OwnPtr<FormSubmission> m_deferredFormSubmission;
-
- bool m_isExecutingJavaScriptFormAction;
- bool m_isRunningScript;
-
- String m_responseMIMEType;
-
- bool m_didCallImplicitClose;
- bool m_wasUnloadEventEmitted;
- bool m_isComplete;
- bool m_isLoadingMainResource;
- bool m_firingUnloadEvents; // frame or loader is firing unload or beforeUnload events.
-
- KURL m_URL;
- KURL m_workingURL;
-
- OwnPtr<IconLoader> m_iconLoader;
- bool m_mayLoadIconLater;
-
- bool m_cancellingWithLoadInProgress;
-
- OwnPtr<ScheduledRedirection> m_scheduledRedirection;
-
- bool m_needsClear;
- bool m_receivedData;
-
- bool m_encodingWasChosenByUser;
- String m_encoding;
- RefPtr<TextResourceDecoder> m_decoder;
-
- bool m_containsPlugIns;
-
- RefPtr<HTMLFormElement> m_formAboutToBeSubmitted;
- HashMap<String, String> m_formValuesAboutToBeSubmitted;
- KURL m_submittedFormURL;
-
- Timer<FrameLoader> m_redirectionTimer;
- Timer<FrameLoader> m_checkCompletedTimer;
- Timer<FrameLoader> m_checkLoadCompleteTimer;
-
- Frame* m_opener;
- HashSet<Frame*> m_openedFrames;
-
- bool m_openedByDOM;
-
- bool m_creatingInitialEmptyDocument;
- bool m_isDisplayingInitialEmptyDocument;
- bool m_committedFirstRealDocumentLoad;
-
- RefPtr<HistoryItem> m_currentHistoryItem;
- RefPtr<HistoryItem> m_previousHistoryItem;
- RefPtr<HistoryItem> m_provisionalHistoryItem;
-
- bool m_didPerformFirstNavigation;
-
-#ifndef NDEBUG
- bool m_didDispatchDidCommitLoad;
-#endif
-
-#if USE(LOW_BANDWIDTH_DISPLAY)
- // whether to use low bandwidth dislay, set by client
- bool m_useLowBandwidthDisplay;
-
- // whether to call finishParsing() in switchOutLowBandwidthDisplayIfReady()
- bool m_finishedParsingDuringLowBandwidthDisplay;
-
- // whether to call switchOutLowBandwidthDisplayIfReady;
- // true if there is external css, javascript, or subframe/plugin
- bool m_needToSwitchOutLowBandwidthDisplay;
-
- String m_pendingSourceInLowBandwidthDisplay;
- HashSet<CachedResource*> m_externalRequestsInLowBandwidthDisplay;
-#endif
- };
-
-}
-
-#endif
diff --git a/webkit/pending/FrameLoaderClient.h b/webkit/pending/FrameLoaderClient.h
deleted file mode 100644
index 0c2ee59..0000000
--- a/webkit/pending/FrameLoaderClient.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FrameLoaderClient_h
-#define FrameLoaderClient_h
-
-#include "FrameLoaderTypes.h"
-#include <wtf/Forward.h>
-#include <wtf/Platform.h>
-#include <wtf/Vector.h>
-
-typedef class _jobject* jobject;
-
-#if PLATFORM(MAC) && !defined(__OBJC__)
-class NSCachedURLResponse;
-class NSView;
-#endif
-
-namespace WebCore {
-
- class AuthenticationChallenge;
- class CachedPage;
- class DocumentLoader;
- class Element;
- class FormState;
- class Frame;
- class FrameLoader;
- class HistoryItem;
- class HTMLFrameOwnerElement;
- class IntSize;
- class KURL;
- class NavigationAction;
- class ResourceError;
- class ResourceHandle;
- class ResourceLoader;
- class ResourceResponse;
- class SharedBuffer;
- class SubstituteData;
- class String;
- class Widget;
-
- class ResourceRequest;
-
- typedef void (FrameLoader::*FramePolicyFunction)(PolicyAction);
-
- class FrameLoaderClient {
- public:
- virtual ~FrameLoaderClient() { }
- virtual void frameLoaderDestroyed() = 0;
-
- virtual bool hasWebView() const = 0; // mainly for assertions
- virtual bool hasFrameView() const = 0; // ditto
-
- virtual bool hasHTMLView() const { return true; }
-
- virtual void makeRepresentation(DocumentLoader*) = 0;
- virtual void forceLayout() = 0;
- virtual void forceLayoutForNonHTML() = 0;
-
- virtual void setCopiesOnScroll() = 0;
-
- virtual void detachedFromParent2() = 0;
- virtual void detachedFromParent3() = 0;
- virtual void detachedFromParent4() = 0;
-
- virtual void assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&) = 0;
-
- virtual void dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse) = 0;
- virtual void dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) = 0;
- virtual void dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) = 0;
- virtual void dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&) = 0;
- virtual void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int lengthReceived) = 0;
- virtual void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier) = 0;
- virtual void dispatchDidFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError&) = 0;
- virtual bool dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length) = 0;
-
- virtual void dispatchDidHandleOnloadEvents() = 0;
- virtual void dispatchDidReceiveServerRedirectForProvisionalLoad() = 0;
- virtual void dispatchDidCancelClientRedirect() = 0;
- virtual void dispatchWillPerformClientRedirect(const KURL&, double interval, double fireDate) = 0;
- virtual void dispatchDidChangeLocationWithinPage() = 0;
- virtual void dispatchWillClose() = 0;
- virtual void dispatchDidReceiveIcon() = 0;
- virtual void dispatchDidStartProvisionalLoad() = 0;
- virtual void dispatchDidReceiveTitle(const String& title) = 0;
- virtual void dispatchDidCommitLoad() = 0;
- virtual void dispatchDidFailProvisionalLoad(const ResourceError&) = 0;
- virtual void dispatchDidFailLoad(const ResourceError&) = 0;
- virtual void dispatchDidFinishDocumentLoad() = 0;
- virtual void dispatchDidFinishLoad() = 0;
- virtual void dispatchDidFirstLayout() = 0;
-
- virtual Frame* dispatchCreatePage() = 0;
- virtual void dispatchShow() = 0;
-
- virtual void dispatchDecidePolicyForMIMEType(FramePolicyFunction, const String& MIMEType, const ResourceRequest&) = 0;
- virtual void dispatchDecidePolicyForNewWindowAction(FramePolicyFunction, const NavigationAction&, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName) = 0;
- virtual void dispatchDecidePolicyForNavigationAction(FramePolicyFunction, const NavigationAction&, const ResourceRequest&, PassRefPtr<FormState>) = 0;
- virtual void cancelPolicyCheck() = 0;
-
- virtual void dispatchUnableToImplementPolicy(const ResourceError&) = 0;
-
- virtual void dispatchWillSubmitForm(FramePolicyFunction, PassRefPtr<FormState>) = 0;
-
- virtual void dispatchDidLoadMainResource(DocumentLoader*) = 0;
- virtual void revertToProvisionalState(DocumentLoader*) = 0;
- virtual void setMainDocumentError(DocumentLoader*, const ResourceError&) = 0;
-
- // Maybe these should go into a ProgressTrackerClient some day
- virtual void willChangeEstimatedProgress() { }
- virtual void didChangeEstimatedProgress() { }
- virtual void postProgressStartedNotification() = 0;
- virtual void postProgressEstimateChangedNotification() = 0;
- virtual void postProgressFinishedNotification() = 0;
-
- virtual void setMainFrameDocumentReady(bool) = 0;
-
- virtual void startDownload(const ResourceRequest&) = 0;
-
- virtual void willChangeTitle(DocumentLoader*) = 0;
- virtual void didChangeTitle(DocumentLoader*) = 0;
-
- virtual void committedLoad(DocumentLoader*, const char*, int) = 0;
- virtual void finishedLoading(DocumentLoader*) = 0;
-
- virtual void updateGlobalHistory(const KURL&) = 0;
- virtual bool shouldGoToHistoryItem(HistoryItem*) const = 0;
-
- virtual ResourceError cancelledError(const ResourceRequest&) = 0;
- virtual ResourceError blockedError(const ResourceRequest&) = 0;
- virtual ResourceError cannotShowURLError(const ResourceRequest&) = 0;
- virtual ResourceError interruptForPolicyChangeError(const ResourceRequest&) = 0;
-
- virtual ResourceError cannotShowMIMETypeError(const ResourceResponse&) = 0;
- virtual ResourceError fileDoesNotExistError(const ResourceResponse&) = 0;
- virtual ResourceError pluginWillHandleLoadError(const ResourceResponse&) = 0;
-
- virtual bool shouldFallBack(const ResourceError&) = 0;
-
- virtual bool canHandleRequest(const ResourceRequest&) const = 0;
- virtual bool canShowMIMEType(const String& MIMEType) const = 0;
- virtual bool representationExistsForURLScheme(const String& URLScheme) const = 0;
- virtual String generatedMIMETypeForURLScheme(const String& URLScheme) const = 0;
-
- virtual void frameLoadCompleted() = 0;
- virtual void saveViewStateToItem(HistoryItem*) = 0;
- virtual void restoreViewState() = 0;
- virtual void provisionalLoadStarted() = 0;
- virtual void didFinishLoad() = 0;
- virtual void prepareForDataSourceReplacement() = 0;
-
- virtual PassRefPtr<DocumentLoader> createDocumentLoader(const ResourceRequest&, const SubstituteData&) = 0;
- virtual void setTitle(const String& title, const KURL&) = 0;
-
- virtual String userAgent(const KURL&) = 0;
-
- virtual void savePlatformDataToCachedPage(CachedPage*) = 0;
- virtual void transitionToCommittedFromCachedPage(CachedPage*) = 0;
- virtual void transitionToCommittedForNewPage() = 0;
-
- virtual bool canCachePage() const = 0;
- virtual void download(ResourceHandle*, const ResourceRequest&, const ResourceRequest&, const ResourceResponse&) = 0;
-
- virtual PassRefPtr<Frame> createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
- const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight) = 0;
- virtual Widget* createPlugin(const IntSize&, Element*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool loadManually) = 0;
- virtual void redirectDataToPlugin(Widget* pluginWidget) = 0;
-
- virtual Widget* createJavaAppletWidget(const IntSize&, Element*, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues) = 0;
-
- virtual ObjectContentType objectContentType(const KURL& url, const String& mimeType) = 0;
- virtual String overrideMediaType() const = 0;
-
- virtual void windowObjectCleared() = 0;
- virtual void didPerformFirstNavigation() const = 0; // "Navigation" here means a transition from one page to another that ends up in the back/forward list.
-
- virtual void registerForIconNotification(bool listen = true) = 0;
-
- virtual void unloadListenerChanged() = 0;
-
-#if PLATFORM(MAC)
-#if ENABLE(MAC_JAVA_BRIDGE)
- virtual jobject javaApplet(NSView*) { return 0; }
-#endif
- virtual NSCachedURLResponse* willCacheResponse(DocumentLoader*, unsigned long identifier, NSCachedURLResponse*) const = 0;
-#endif
- };
-
-} // namespace WebCore
-
-#endif // FrameLoaderClient_h