diff options
author | Ben Murdoch <benm@google.com> | 2010-05-11 18:35:50 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2010-05-14 10:23:05 +0100 |
commit | 21939df44de1705786c545cd1bf519d47250322d (patch) | |
tree | ef56c310f5c0cdc379c2abb2e212308a3281ce20 | |
parent | 4ff1d8891d520763f17675827154340c7c740f90 (diff) | |
download | external_webkit-21939df44de1705786c545cd1bf519d47250322d.zip external_webkit-21939df44de1705786c545cd1bf519d47250322d.tar.gz external_webkit-21939df44de1705786c545cd1bf519d47250322d.tar.bz2 |
Merge Webkit at r58956: Initial merge by Git.
Change-Id: I1d9fb60ea2c3f2ddc04c17a871acdb39353be228
1394 files changed, 69157 insertions, 18149 deletions
diff --git a/JavaScriptCore/API/APIShims.h b/JavaScriptCore/API/APIShims.h index 3d42ca2..892068d 100644 --- a/JavaScriptCore/API/APIShims.h +++ b/JavaScriptCore/API/APIShims.h @@ -66,7 +66,7 @@ public: // JSPropertyNameAccumulator only has a globalData. APIEntryShim(JSGlobalData* globalData, bool registerThread = true) : APIEntryShimWithoutLock(globalData, registerThread) - , m_lock(globalData->isSharedInstance ? LockForReal : SilenceAssertionsOnly) + , m_lock(globalData->isSharedInstance() ? LockForReal : SilenceAssertionsOnly) { } diff --git a/JavaScriptCore/API/JSBase.cpp b/JavaScriptCore/API/JSBase.cpp index ebfeafa..c5f1b15 100644 --- a/JavaScriptCore/API/JSBase.cpp +++ b/JavaScriptCore/API/JSBase.cpp @@ -38,6 +38,7 @@ #include <runtime/JSGlobalObject.h> #include <runtime/JSLock.h> #include <runtime/JSObject.h> +#include <wtf/text/StringHash.h> using namespace JSC; diff --git a/JavaScriptCore/API/JSCallbackObject.cpp b/JavaScriptCore/API/JSCallbackObject.cpp index 2fde0f8..b36c194 100644 --- a/JavaScriptCore/API/JSCallbackObject.cpp +++ b/JavaScriptCore/API/JSCallbackObject.cpp @@ -28,6 +28,7 @@ #include "JSCallbackObject.h" #include "Collector.h" +#include <wtf/text/StringHash.h> namespace JSC { diff --git a/JavaScriptCore/API/JSContextRef.cpp b/JavaScriptCore/API/JSContextRef.cpp index 06f9274..b97ceda 100644 --- a/JavaScriptCore/API/JSContextRef.cpp +++ b/JavaScriptCore/API/JSContextRef.cpp @@ -46,7 +46,7 @@ using namespace JSC; JSContextGroupRef JSContextGroupCreate() { initializeThreading(); - return toRef(JSGlobalData::createNonDefault(ThreadStackTypeSmall).releaseRef()); + return toRef(JSGlobalData::createContextGroup(ThreadStackTypeSmall).releaseRef()); } JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group) @@ -84,7 +84,7 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass initializeThreading(); JSLock lock(LockForReal); - RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::createNonDefault(ThreadStackTypeSmall); + RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::createContextGroup(ThreadStackTypeSmall); APIEntryShim entryShim(globalData.get(), false); diff --git a/JavaScriptCore/API/JSStringRef.h b/JavaScriptCore/API/JSStringRef.h index 92135b1..51871b1 100644 --- a/JavaScriptCore/API/JSStringRef.h +++ b/JavaScriptCore/API/JSStringRef.h @@ -38,7 +38,7 @@ extern "C" { #endif #if !defined(WIN32) && !defined(_WIN32) && !defined(__WINSCW__) \ - && !(defined(__CC_ARM) || defined(__ARMCC__)) /* RVCT */ + && !((defined(__CC_ARM) || defined(__ARMCC__)) && defined(__SYMBIAN32__)) /* RVCT */ /*! @typedef JSChar @abstract A Unicode character. diff --git a/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp b/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp index e377ea0..7e6bb63 100644 --- a/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp +++ b/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp @@ -33,6 +33,7 @@ #include "JSWeakObjectMapRefInternal.h" #include <wtf/HashMap.h> #include <wtf/RefCounted.h> +#include <wtf/text/StringHash.h> using namespace WTF; using namespace JSC; diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog index 11f02e3..eb2f97d 100644 --- a/JavaScriptCore/ChangeLog +++ b/JavaScriptCore/ChangeLog @@ -1,3 +1,1513 @@ +2010-05-06 Fumitoshi Ukai <ukai@chromium.org> + + Reviewed by Alexey Proskuryakov. + + JavaScriptCore/wtf/RandomNumber.h should provide using WTF::* + https://bugs.webkit.org/show_bug.cgi?id=38719 + + * wtf/RandomNumber.h: + Add using directives. + +2010-05-06 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Enable YARR_JIT for X86 Mac for QtWebKit + https://bugs.webkit.org/show_bug.cgi?id=38668 + + * wtf/Platform.h: + +2010-05-06 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Bug 38714 - Add result caching for Math.sin + + Math.sin is frequently called with the same operand, caching the result should + improve performance. CachedTranscendentalFunction adds a generic mechanism to + cache results for pure functions with the signature "double func(double)", and + where NaN maps to NaN. + + CachedTranscendentalFunction uses a very simple hash function designed to be + fast to execute since we cannot cache the result, and trivial to JIT generate, + should we wish to do so. + + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/CachedTranscendentalFunction.h: Added. + (JSC::CachedTranscendentalFunction::CachedTranscendentalFunction): + (JSC::CachedTranscendentalFunction::~CachedTranscendentalFunction): + (JSC::CachedTranscendentalFunction::operator()): + (JSC::CachedTranscendentalFunction::initialize): + (JSC::CachedTranscendentalFunction::hash): + * runtime/JSGlobalData.h: + * runtime/MathObject.cpp: + (JSC::mathProtoFuncSin): + * wtf/Platform.h: + +2010-05-06 Geoffrey Garen <ggaren@apple.com> + + Windows build fix. + + * bytecode/SamplingTool.cpp: + (JSC::SamplingFlags::sample): Use a cast, so Windows will be happy when + this code is enabled. + * wtf/Platform.h: Reverted last change to this file, which seems to have + been accidental. + +2010-05-06 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Add compile switch to make debugger keyword plant breakpoint instructions. + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitDebugHook): + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_debug): + * wtf/Platform.h: + +2010-05-06 Oliver Hunt <oliver@apple.com> + + Build fix + + Fix ARM builds + + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::load16): + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::load16): + +2010-05-06 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoffrey Garen. + + Improve performance of single character string compares + https://bugs.webkit.org/show_bug.cgi?id=38659 + + Add logic to the jit to identify comparisons to single character string literals + and then just perform the comparison inline, rather than ignoring the evidence + and attempting to perform an integer comparison. + + Multiple changes required -- add jnlesseq opcode, add helper function to identify + single character string constants, add a helper to load single character strings. + Then add the 32_64 and normal codepaths to the JIT. + + * assembler/MacroAssemblerX86Common.h: + (JSC::MacroAssemblerX86Common::load16): + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + * bytecode/Opcode.h: + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitJumpIfTrue): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + * jit/JIT.h: + * jit/JITArithmetic.cpp: + (JSC::JIT::emit_op_jnless): + (JSC::JIT::emitSlow_op_jnless): + (JSC::JIT::emit_op_jless): + (JSC::JIT::emitSlow_op_jless): + (JSC::JIT::emit_op_jlesseq): + (JSC::JIT::emit_op_jnlesseq): + (JSC::JIT::emitSlow_op_jlesseq): + (JSC::JIT::emitSlow_op_jnlesseq): + * jit/JITArithmetic32_64.cpp: + (JSC::JIT::emit_op_jnless): + (JSC::JIT::emitSlow_op_jnless): + (JSC::JIT::emit_op_jless): + (JSC::JIT::emitSlow_op_jless): + (JSC::JIT::emit_op_jlesseq): + (JSC::JIT::emit_op_jnlesseq): + (JSC::JIT::emitSlow_op_jlesseq): + (JSC::JIT::emitSlow_op_jnlesseq): + (JSC::JIT::emitBinaryDoubleOp): + * jit/JITInlineMethods.h: + (JSC::JIT::emitLoadCharacterString): + (JSC::JIT::isOperandConstantImmediateChar): + * jit/JSInterfaceJIT.h: + (JSC::ThunkHelpers::stringImplDataOffset): + (JSC::ThunkHelpers::jsStringLengthOffset): + (JSC::ThunkHelpers::jsStringValueOffset): + Moved from ThunkGenerators to make it possible to share. + * jit/ThunkGenerators.cpp: + +2010-05-06 Martin Robinson <mrobinson@webkit.org> + + Reviewed by Gustavo Noronha Silva. + + [GTK] Enable DOM clipboard and drag-and-drop access + https://bugs.webkit.org/show_bug.cgi?id=30623 + + Convert dragging portion of drag-and-drop to use DataObjectGtk. + + * wtf/gobject/GRefPtr.h: Add forward declarations for GObject functions. + +2010-05-06 Steve Block <steveblock@google.com> + + Reviewed by Eric Seidel. + + MAC_JAVA_BRIDGE should be renamed JAVA_BRIDGE + https://bugs.webkit.org/show_bug.cgi?id=38544 + + * wtf/Platform.h: + +2010-05-06 Adam Barth <abarth@webkit.org> + + Reviewed by Maciej Stachowiak. + + [WTFURL] Add a class to represent the segments of a URL + https://bugs.webkit.org/show_bug.cgi?id=38566 + + When paired with a string, this class represents a parsed URL. + + * wtf/url/src/URLSegments.cpp: Added. + (WTF::URLSegments::length): + (WTF::URLSegments::charactersBefore): + * wtf/url/src/URLSegments.h: Added. + (WTF::URLSegments::): + (WTF::URLSegments::URLSegments): + * wtf/url/wtfurl.gyp: + +2010-05-05 Tony Gentilcore <tonyg@chromium.org> + + Reviewed by Adam Barth. + + Adding comment with link to RefPtr documentation. + https://bugs.webkit.org/show_bug.cgi?id=38601 + + * wtf/RefPtr.h: + +2010-05-05 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Darin Adler. + + Bug 38604 - workers-gc2 crashing on Qt + + This appears to be due to a couple of issues. + (1) When the atomic string table is deleted it does not clear the 'inTable' bit + on AtomicStrings - it implicitly assumes that all AtomicStrings have already + been deleted at this point (otherwise they will crash in their destructor when + they try to remove themselves from the atomic string table). + (2) We don't fix the ordering in which WTF::WTFThreadData and + WebCore::ThreadGlobalData are destructed. + + We should make sure that ThreadGlobalData is cleaned up before worker threads + terminate and WTF::WTFThreadData is destroyed, and we should clear the inTable + bit of members on atomic string table destruction. + + WTF changes (fix issue 1, above) - ensure inTable property is cleared when the + atomic string table is destroyed (also, rename InTable to IsAtomic, to make it + clear which table we are refering to!) + + * wtf/text/AtomicString.cpp: + (WebCore::AtomicStringTable::destroy): + (WebCore::CStringTranslator::translate): + (WebCore::UCharBufferTranslator::translate): + (WebCore::HashAndCharactersTranslator::translate): + (WebCore::AtomicString::add): + * wtf/text/StringImpl.cpp: + (WebCore::StringImpl::~StringImpl): + * wtf/text/StringImpl.h: + (WebCore::StringImpl::isAtomic): + (WebCore::StringImpl::setIsAtomic): + * wtf/text/StringImplBase.h: + +2010-05-05 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoffrey Garen. + + Make Array.join specialised for actual arrays + https://bugs.webkit.org/show_bug.cgi?id=38592 + + Bring Array.join in line with the other array methods by specialising for + this === an array. + + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncJoin): + +2010-05-04 Yongjun Zhang <yongjun_zhang@apple.com> + + Reviewed by Darin Adler. + + WebKit crashes at DebuggerCallFrame::functionName() if m_callFrame is the top global callframe. + https://bugs.webkit.org/show_bug.cgi?id=38535 + + Don't call asFunction if callee is not a FunctionType to prevent assertion failure + in JSCell::isObject(). + + * debugger/DebuggerCallFrame.cpp: + (JSC::DebuggerCallFrame::functionName): + (JSC::DebuggerCallFrame::calculatedFunctionName): + +2010-05-04 Steve Falkenburg <sfalken@apple.com> + + Remove redundant exports to fix Windows build warnings. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-05-04 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Holger Freyther. + + Fix a memory leak inside the QScriptValue. + + QSciptValuePrivate::toString should release all temporary variables. + + [Qt] QScriptValue::toString have a memory leak. + https://bugs.webkit.org/show_bug.cgi?id=38112 + + * qt/api/qscriptvalue_p.h: + (QScriptValuePrivate::toString): + +2010-05-04 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Reviewed by Darin Adler. + + Does not work on SPARC because of alignment issues + https://bugs.webkit.org/show_bug.cgi?id=38455 + + Use AllocAlignmentInteger instead of void* on pageheap_memory to + avoid crashing at runtime in some architectures. Investigated by + Mike Hommey <mh@glandium.org>, change suggested by Darin Adler. + + * wtf/FastMalloc.cpp: + +2010-05-04 Adam Barth <abarth@webkit.org> + + Reviewed by Maciej Stachowiak. + + Add first WTFURL file + https://bugs.webkit.org/show_bug.cgi?id=38470 + + This class represents a component of a URL, such as the scheme or path. + Essentially, the class is an index into a string buffer. + + * wtf/url: Added. + - There was some discussion about where to put the URL library. + There are a number of reasonable options, but putting the library + in the WTF directory seems like a reasonable alternative. This + location will make more sense once WTF is moved out of + JavaScriptCore and into a top-level directory. + * wtf/url/src: Added. + - I've added this extra directory to the usual structure because we + eventually want a "public" folder that defines the public + interface to this library that clients outside of svn.webkit.org + can rely upon, much like the various subfolders of the WebKit + directory often define a public API. + * wtf/url/src/URLComponent.h: Added. + - I've added this somewhat trivial class to get the ball rolling. + (WTF::URLComponent::URLComponent): + (WTF::URLComponent::isValid): + (WTF::URLComponent::isNonempty): + (WTF::URLComponent::reset): + (WTF::URLComponent::operator==): + (WTF::URLComponent::begin): + (WTF::URLComponent::setBegin): + (WTF::URLComponent::length): + (WTF::URLComponent::setLength): + (WTF::URLComponent::end): + * wtf/url/wtfurl.gyp: Added. + - WTFURL will be an independently buildable library, hence the + beginnings of a wtfurl.gyp file. + +2010-05-03 Stephanie Lewis <slewis@apple.com> + + Reviewed by Geoff Garen. + + https://bugs.webkit.org/show_bug.cgi?id=38368 + <rdar://problem/7834433> REGRESSSION: 1.5% PLT regression due to 56028 + (return memory quicker). + Instead of returning everything but the smallest spans spread out + the spans kept over several size lists. + + * wtf/FastMalloc.cpp: + (WTF::TCMalloc_PageHeap::scavenge): + +2010-05-03 James Robinson <jamesr@chromium.org> + + Reviewed by Eric Seidel. + + Clean up a few compiler warnings + https://bugs.webkit.org/show_bug.cgi?id=38073 + + * wtf/text/StringImpl.cpp: + (WebCore::StringImpl::ascii): + +2010-05-03 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (reverting previous commit). + + Rolling out r58114 - this introduced memory leaks of + AtomicStrings then workers terminated. + + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * jit/ThunkGenerators.cpp: + (JSC::ThunkHelpers::stringImplDataOffset): + * runtime/Identifier.cpp: + (JSC::IdentifierTable::~IdentifierTable): + (JSC::IdentifierTable::add): + (JSC::IdentifierCStringTranslator::hash): + (JSC::IdentifierCStringTranslator::equal): + (JSC::IdentifierCStringTranslator::translate): + (JSC::Identifier::add): + (JSC::IdentifierUCharBufferTranslator::hash): + (JSC::IdentifierUCharBufferTranslator::equal): + (JSC::IdentifierUCharBufferTranslator::translate): + (JSC::Identifier::addSlowCase): + * runtime/Identifier.h: + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + (JSC::JSGlobalData::~JSGlobalData): + * runtime/JSGlobalData.h: + * wtf/WTFThreadData.cpp: + (WTF::WTFThreadData::WTFThreadData): + (WTF::WTFThreadData::~WTFThreadData): + * wtf/WTFThreadData.h: + (JSC::IdentifierTable::remove): + (JSC::IdentifierTable::literalTable): + (WTF::WTFThreadData::atomicStringTable): + * wtf/text/AtomicString.cpp: + (WebCore::AtomicStringTable::create): + (WebCore::AtomicStringTable::table): + (WebCore::AtomicStringTable::destroy): + (WebCore::stringTable): + (WebCore::CStringTranslator::hash): + (WebCore::CStringTranslator::equal): + (WebCore::CStringTranslator::translate): + (WebCore::operator==): + (WebCore::AtomicString::add): + (WebCore::equal): + (WebCore::UCharBufferTranslator::hash): + (WebCore::UCharBufferTranslator::equal): + (WebCore::UCharBufferTranslator::translate): + (WebCore::HashAndCharactersTranslator::hash): + (WebCore::HashAndCharactersTranslator::equal): + (WebCore::HashAndCharactersTranslator::translate): + (WebCore::AtomicString::find): + (WebCore::AtomicString::remove): + * wtf/text/AtomicStringTable.h: Removed. + * wtf/text/StringImpl.cpp: + (WebCore::StringImpl::~StringImpl): + * wtf/text/StringImpl.h: + (WebCore::StringImpl::inTable): + (WebCore::StringImpl::setInTable): + (WebCore::equal): + * wtf/text/StringImplBase.h: + (WTF::StringImplBase::StringImplBase): + +2010-05-03 Kevin Watters <kevinwatters@gmail.com> + + Reviewed by Kevin Ollivier. + + [wx] Implement scheduleDispatchFunctionsOnMainThread for wx port. + https://bugs.webkit.org/show_bug.cgi?id=38480 + + * wtf/wx/MainThreadWx.cpp: + (wxCallAfter::wxCallAfter): + (wxCallAfter::OnCallback): + (WTF::scheduleDispatchFunctionsOnMainThread): + +2010-05-03 Kevin Watters <kevinwatters@gmail.com> + + Reviewed by Kevin Ollivier. + + [wx] Build and use Mac's ComplexTextController to support complex text in wx. + https://bugs.webkit.org/show_bug.cgi?id=38482 + + * wtf/Platform.h: + +2010-05-03 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + Interpreter crashes due to incorrect refcounting of cached structures. + https://bugs.webkit.org/show_bug.cgi?id=38491 + rdar://problem/7926160 + + Make sure we ref/deref structures used for cached custom property getters + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::derefStructures): + (JSC::CodeBlock::refStructures): + +2010-05-02 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Eric Seidel. + + [Qt] Enable JIT for QtWebKit on Symbian + https://bugs.webkit.org/show_bug.cgi?id=38339 + + JIT on Symbian has been stable for quite some time, it + is time to turn it on by default. + + * wtf/Platform.h: + +2010-04-29 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Add codegen support for unsigned right shift + https://bugs.webkit.org/show_bug.cgi?id=38375 + + Expose unsigned right shift in the macro assembler, and make use of it + from the jit. Currently if the result is outside the range 0..2^31-1 + we simply fall back to the slow case, even in JSVALUE64 and JSVALUE32_64 + where technically we could still return an immediate value. + + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::urshift32): + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::urshift32): + * assembler/MacroAssemblerX86Common.h: + (JSC::MacroAssemblerX86Common::urshift32): + * assembler/X86Assembler.h: + (JSC::X86Assembler::): + (JSC::X86Assembler::shrl_i8r): + (JSC::X86Assembler::shrl_CLr): + Add unsigned right shift to the x86 assembler + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + op_rshift no longer simply get thrown to a stub function + * jit/JIT.h: + * jit/JITArithmetic.cpp: + (JSC::JIT::emit_op_urshift): + (JSC::JIT::emitSlow_op_urshift): + JSVALUE32 and JSVALUE64 implementation. Only supports + double lhs in JSVALUE64. + * jit/JITArithmetic32_64.cpp: + (JSC::JIT::emit_op_rshift): + (JSC::JIT::emitSlow_op_rshift): + (JSC::JIT::emit_op_urshift): + (JSC::JIT::emitSlow_op_urshift): + Refactor right shift code to have shared implementation between signed + and unsigned versions. + +2010-04-29 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Handle double on righthand side of a right shift + https://bugs.webkit.org/show_bug.cgi?id=38363 + + In 64-bit we support right shift of a double, and there's no + reason not to in 32-bit either. This is a 1.1% sunspider + improvement in 32bit. + + Given high performance javascript code frequently makes + use of bit operators to perform double->int conversion i'll + follow this patch up with similar patches for bitwise 'and' + and 'or'. + + * jit/JITArithmetic32_64.cpp: + (JSC::JIT::emit_op_rshift): + (JSC::JIT::emitSlow_op_rshift): + +2010-04-29 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoff Garen. + + Hoist JSVALUE32_64 arithmetic implementations into a separate file. + + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.pro: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * jit/JITArithmetic.cpp: + (JSC::JIT::emitSlow_op_jnless): + (JSC::JIT::emitSlow_op_jless): + (JSC::JIT::emitSlow_op_jnlesseq): + (JSC::JIT::emit_op_mod): + (JSC::JIT::compileBinaryArithOpSlowCase): + (JSC::JIT::emit_op_div): + (JSC::JIT::compileBinaryArithOp): + * jit/JITArithmetic32_64.cpp: Added. + (JSC::JIT::emit_op_negate): + (JSC::JIT::emitSlow_op_negate): + (JSC::JIT::emit_op_jnless): + (JSC::JIT::emitSlow_op_jnless): + (JSC::JIT::emit_op_jless): + (JSC::JIT::emitSlow_op_jless): + (JSC::JIT::emit_op_jnlesseq): + (JSC::JIT::emitSlow_op_jnlesseq): + (JSC::JIT::emit_op_lshift): + (JSC::JIT::emitSlow_op_lshift): + (JSC::JIT::emit_op_rshift): + (JSC::JIT::emitSlow_op_rshift): + (JSC::JIT::emit_op_bitand): + (JSC::JIT::emitSlow_op_bitand): + (JSC::JIT::emit_op_bitor): + (JSC::JIT::emitSlow_op_bitor): + (JSC::JIT::emit_op_bitxor): + (JSC::JIT::emitSlow_op_bitxor): + (JSC::JIT::emit_op_bitnot): + (JSC::JIT::emitSlow_op_bitnot): + (JSC::JIT::emit_op_post_inc): + (JSC::JIT::emitSlow_op_post_inc): + (JSC::JIT::emit_op_post_dec): + (JSC::JIT::emitSlow_op_post_dec): + (JSC::JIT::emit_op_pre_inc): + (JSC::JIT::emitSlow_op_pre_inc): + (JSC::JIT::emit_op_pre_dec): + (JSC::JIT::emitSlow_op_pre_dec): + (JSC::JIT::emit_op_add): + (JSC::JIT::emitAdd32Constant): + (JSC::JIT::emitSlow_op_add): + (JSC::JIT::emit_op_sub): + (JSC::JIT::emitSub32Constant): + (JSC::JIT::emitSlow_op_sub): + (JSC::JIT::emitBinaryDoubleOp): + (JSC::JIT::emit_op_mul): + (JSC::JIT::emitSlow_op_mul): + (JSC::JIT::emit_op_div): + (JSC::JIT::emitSlow_op_div): + (JSC::JIT::emit_op_mod): + (JSC::JIT::emitSlow_op_mod): + +2010-04-29 Zoltan Herczeg <zherczeg@webkit.org> + + Reviewed by Oliver Hunt + + Add sqrt() instruction support for ARM assembler (using VFP) + https://bugs.webkit.org/show_bug.cgi?id=38312 + + * assembler/ARMAssembler.h: + (JSC::ARMAssembler::): + (JSC::ARMAssembler::fsqrtd_r): + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::supportsFloatingPointSqrt): + (JSC::MacroAssemblerARM::sqrtDouble): + +2010-04-29 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Refactor qtscriptglobal.h + https://bugs.webkit.org/show_bug.cgi?id=37953 + + Use the same pattern in qtscriptglobal.h as in + qwebkitglobal.h without checking for specific OSs. + + * qt/api/qtscriptglobal.h: + +2010-04-29 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Simon Hausmann. + + Small cleanup. + + QScriptValuePrivate constructor shouldn't take QScriptEngine pointer + as a parameter, because it breaks a private / public separation rule. + QScriptEnginePrivate::get(QScriptEngine*) should return + a QScriptEnginePrivate pointer instead of a QScriptEnginePtr, it simplifies + implementation. + + [Qt] QScriptValuePrivate class needs some cleanup. + https://bugs.webkit.org/show_bug.cgi?id=37729 + + * qt/api/qscriptengine_p.h: + (QScriptEnginePrivate::get): + * qt/api/qscriptvalue.cpp: + (QScriptValue::QScriptValue): + * qt/api/qscriptvalue_p.h: + (QScriptValuePrivate::QScriptValuePrivate): + +2010-04-29 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Simon Hausmann. + + [WINCE] Export g_stackBase with JS_EXPORTDATA + https://bugs.webkit.org/show_bug.cgi?id=37437 + + Export g_stackBase with JS_EXPORTDATA as it is used by SharedTimerWince.cpp. + + * runtime/Collector.cpp: + +2010-04-28 Oliver Hunt <oliver@apple.com> + + Do an unordered compare so that we don't treat NaN incorrectly. + + RS=Gavin Barraclough + + * jit/ThunkGenerators.cpp: + (JSC::powThunkGenerator): + +2010-04-28 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Add fast paths for Math.pow and Math.sqrt + https://bugs.webkit.org/show_bug.cgi?id=38294 + + Add specialized thunks for Math.pow and Math.sqrt. + This requires adding a sqrtDouble function to the MacroAssembler + and sqrtsd to the x86 assembler. + + Math.pow is slightly more complicated, in that we have + to implement exponentiation ourselves rather than relying + on hardware support. The inline exponentiation is restricted + to positive integer exponents on a numeric base. Exponentiation + is finally performed through the "Exponentiation by Squaring" + algorithm. + + * assembler/AbstractMacroAssembler.h: + (JSC::AbstractMacroAssembler::ImmPtr::ImmPtr): + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::supportsFloatingPointSqrt): + (JSC::MacroAssemblerARM::loadDouble): + (JSC::MacroAssemblerARM::sqrtDouble): + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::supportsFloatingPointSqrt): + (JSC::MacroAssemblerARMv7::sqrtDouble): + * assembler/MacroAssemblerX86.h: + (JSC::MacroAssemblerX86::loadDouble): + (JSC::MacroAssemblerX86::supportsFloatingPointSqrt): + * assembler/MacroAssemblerX86Common.h: + (JSC::MacroAssemblerX86Common::sqrtDouble): + * assembler/MacroAssemblerX86_64.h: + (JSC::MacroAssemblerX86_64::loadDouble): + (JSC::MacroAssemblerX86_64::supportsFloatingPointSqrt): + * assembler/X86Assembler.h: + (JSC::X86Assembler::): + (JSC::X86Assembler::movsd_mr): + (JSC::X86Assembler::sqrtsd_rr): + (JSC::X86Assembler::X86InstructionFormatter::twoByteOp): + (JSC::X86Assembler::X86InstructionFormatter::memoryModRM): + * create_hash_table: + * jit/JIT.h: + * jit/JITInlineMethods.h: + * jit/JITOpcodes.cpp: + * jit/JITStubs.h: + (JSC::JITThunks::ctiNativeCallThunk): + * jit/JSInterfaceJIT.h: + (JSC::JSInterfaceJIT::emitLoadDouble): + (JSC::JSInterfaceJIT::emitJumpIfImmediateNumber): + (JSC::JSInterfaceJIT::emitJumpIfNotImmediateNumber): + (JSC::JSInterfaceJIT::emitLoadInt32): + * jit/SpecializedThunkJIT.h: + (JSC::SpecializedThunkJIT::loadDoubleArgument): + (JSC::SpecializedThunkJIT::loadInt32Argument): + (JSC::SpecializedThunkJIT::returnJSValue): + (JSC::SpecializedThunkJIT::returnDouble): + (JSC::SpecializedThunkJIT::finalize): + * jit/ThunkGenerators.cpp: + (JSC::sqrtThunkGenerator): + (JSC::powThunkGenerator): + * jit/ThunkGenerators.h: + * runtime/Executable.h: + (JSC::NativeExecutable::NativeExecutable): + * runtime/JSFunction.cpp: + (JSC::JSFunction::JSFunction): + +2010-04-28 Mike Thole <mthole@apple.com> + + Reviewed by Mark Rowe. + + Reenable WTF_USE_PROTECTION_SPACE_AUTH_CALLBACK now that an + exports file for it has been added. + + * wtf/Platform.h: + +2010-04-28 Mike Thole <mthole@apple.com> + + Build fix, not reviewed. + + * wtf/Platform.h: + Disable WTF_USE_PROTECTION_SPACE_AUTH_CALLBACK until an exports file is created. + +2010-04-28 Mike Thole <mthole@apple.com> + + Reviewed by David Kilzer. + + Add canAuthenticateAgainstProtectionSpace() to frame loader so that a protection space + can be inspected before attempting to authenticate against it + https://bugs.webkit.org/show_bug.cgi?id=38271 + + * wtf/Platform.h: Add WTF_USE_PROTECTION_SPACE_AUTH_CALLBACK define. + +2010-04-28 Darin Adler <darin@apple.com> + + Reviewed by Sam Weinig. + + Don't use CFAbsoluteTimeGetCurrent on Mac OS X, since it's just a cover + for gettimeofday anyway. + + * wtf/CurrentTime.cpp: + (WTF::currentTime): Remove the CF version of this. Change the "other POSIX" + version to pass 0 for the time zone instead of ignoring a return value. + Also get rid of unneeded type casts, since operations involving both + integers and doubles are always evaluated as doubles in C without explicit + type casting. + +2010-04-28 Darin Fisher <darin@chromium.org> + + Reviewed by David Levin. + + [Chromium] callOnMainThread should equate to MessageLoop::PostTask + https://bugs.webkit.org/show_bug.cgi?id=38276 + + * JavaScriptCore.gyp/JavaScriptCore.gyp: + * wtf/MainThread.cpp: + * wtf/chromium/ChromiumThreading.h: + * wtf/chromium/MainThreadChromium.cpp: + (WTF::initializeMainThread): + (WTF::callOnMainThread): + (WTF::callOnMainThreadAndWait): + (WTF::setMainThreadCallbacksPaused): + (WTF::isMainThread): + +2010-04-28 Simon Hausmann <simon.hausmann@nokia.com>, Kent Hansen <kent.hansen@nokia.com> + + Reviewed by Darin Adler. + + JSC's currentThreadStackBase is not reentrant on some platforms + https://bugs.webkit.org/show_bug.cgi?id=37195 + + This function needs to be reentrant to avoid memory corruption on platforms where + the implementation uses global variables. + + This patch adds a mutex lock where necessary and makes the Symbian implementation + reentrant. + + * runtime/Collector.cpp: + (JSC::currentThreadStackBaseMutex): + (JSC::currentThreadStackBase): + +2010-04-28 Thiago Macieira <thiago.macieira@nokia.com> + + Reviewed by Simon Hausmann. + + Fix compilation with gcc 3.4. + + AtomicStringImpl.h:29: error: base `WebCore::StringImpl' with only + non-default constructor in class without a constructor + + * wtf/text/AtomicStringImpl.h: + (WebCore::AtomicStringImpl::AtomicStringImpl): Provide a default constructor. + * wtf/text/StringImpl.h: Allow AtomicStringImpl to call a StringImpl constructor through a friend declaration. + +2010-04-27 Stephanie Lewis <slewis@apple.com> + + Fix Tiger build. + + * wtf/FastMalloc.cpp: + (WTF::TCMalloc_PageHeap::Carve): + +2010-04-26 Stephanie Lewis <slewis@apple.com> + + Reviewed by Geoff Garen. + + https://bugs.webkit.org/show_bug.cgi?id=38154 FastMalloc calls madvise too often. + <rdar://problem/7834433> REGRESSSION: 1.5% PLT regression due to 56028 (return memory quicker). + To save on madvise calls when recommitting memory recommit the entire span and then carve it + instead of carving the span up and only committing the part that will be used immediately. + + * wtf/FastMalloc.cpp: + (WTF::TCMalloc_PageHeap::New): + (WTF::TCMalloc_PageHeap::AllocLarge): + (WTF::TCMalloc_PageHeap::Carve): + +2010-04-26 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + Add specialized thunks for a char code related string functions + https://bugs.webkit.org/show_bug.cgi?id=38177 + + This is a simple extension to my prior patch. Basically hoist the + existing character loading logic from the charCodeAt thunk and into + a helper function, then add a helper to load strings from the small + string cache. This allows trivial implementations of fromCharCode + and charAt. + + * create_hash_table: + * jit/SpecializedThunkJIT.h: + (JSC::SpecializedThunkJIT::returnJSCell): + (JSC::SpecializedThunkJIT::tagReturnAsJSCell): + * jit/ThunkGenerators.cpp: + (JSC::stringCharLoad): + (JSC::charToString): + (JSC::charCodeAtThunkGenerator): + (JSC::charAtThunkGenerator): + (JSC::fromCharCodeThunkGenerator): + * jit/ThunkGenerators.h: + * runtime/SmallStrings.h: + (JSC::SmallStrings::singleCharacterStrings): + * runtime/StringConstructor.cpp: + (JSC::StringConstructor::StringConstructor): + +2010-04-27 Thomas Zander <t.zander@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Fix the build on Symbian on Linux using the Makefile based mkspec + + * JavaScriptCore.pri: It is necessary to specify the library search path + when linking against JavaScriptCore. + +2010-04-21 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Simon Hausmann. + + Compile fix for Visual Studio 2010 + https://bugs.webkit.org/show_bug.cgi?id=37867 + + Patch by Prasanth Ullattil <prasanth.ullattil@nokia.com> + + * runtime/Structure.cpp: + (JSC::Structure::transitionTableAdd): + * wtf/MathExtras.h: + * wtf/Platform.h: + +2010-04-27 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Simon Hausmann. + + Rename COMPILER(MSVC7) to COMPILER(MSVC7_OR_LOWER) + + * config.h: + (JSC::Structure::transitionTableAdd): + * wtf/Assertions.h: + * wtf/Atomics.h: + * wtf/CurrentTime.h: + (WTF::getLocalTime): + * wtf/Platform.h: + * wtf/StaticConstructors.h: + * wtf/StringExtras.h: + * wtf/Vector.h: + (WTF::::append): + +2010-04-15 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Tor Arne Vestbø. + + [Qt] Fix Mac build break. + + https://bugs.webkit.org/show_bug.cgi?id=37867 + - Make sure JavaScriptCore's debug_and_release config follows that + of WebCore. + - Use different name for JavaScriptCore target in debug and release + since they might be written in the same path at the same time on + parallel builds + - Consolidate the DESTDIR determination logic in JavaScriptCore.pri + + * JavaScriptCore.pri: + * JavaScriptCore.pro: + +2010-04-21 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Make sure WebKit is not compiled using C++0x. + https://bugs.webkit.org/show_bug.cgi?id=37867 + + As the rest of Qt compiles in the C++0x mode, people might start + compiling it in this mode. WebKit don't support this yet. + + Patch by Thiago Macieira <thiago.macieira@nokia.com> + + * JavaScriptCore.pro: + +2010-04-26 Oliver Hunt <oliver@apple.com> + + Fix windows + + * jit/SpecializedThunkJIT.h: + (JSC::SpecializedThunkJIT::argumentToVirtualRegister): + +2010-04-26 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Need to support more efficient dispatch of lightweight builtins + https://bugs.webkit.org/show_bug.cgi?id=38155 + + The problem with calling lightweight builtins is that marshalling + the call from the nitro calling convention to the system calling + convention is very expensive relative to the cost of the actually + evaluating the function. To work around this problem this patch + adds the ability to define a custom thunk for a builtin. + + This allows us to use high performance custom implementations of + the common and sensible versions of simple builtins. This patch + includes a simple (use of which is currently hardcoded) thunk for + charCodeAt. + + This adds a JSInterfaceJIT subclass called SpecializedThunkJIT + that has helper functions to remove (or at least reduce) the need + to have separate thunk implementations for each JSValue encoding. + + * GNUmakefile.am: + * JavaScriptCore.pro: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + Many project file updates + + * create_hash_table: + Add thunk generation callbacks to the hash tables, currently + we hardcode the script to only support charCodeAt + + * jit/JITStubCall.h: + * jit/JITStubs.cpp: + (JSC::JITThunks::~JITThunks): + (JSC::JITThunks::specializedThunk): + * jit/JITStubs.h: + * jit/SpecializedThunkJIT.h: Added. + (JSC::SpecializedThunkJIT::SpecializedThunkJIT): + (JSC::SpecializedThunkJIT::loadCellArgument): + (JSC::SpecializedThunkJIT::loadJSStringArgument): + (JSC::SpecializedThunkJIT::loadInt32Argument): + (JSC::SpecializedThunkJIT::appendFailure): + (JSC::SpecializedThunkJIT::returnInt32): + (JSC::SpecializedThunkJIT::finalize): + (JSC::SpecializedThunkJIT::argumentToVirtualRegister): + (JSC::SpecializedThunkJIT::tagReturnAsInt32): + * jit/ThunkGenerators.cpp: Added. + (JSC::ThunkHelpers::stringImplDataOffset): + (JSC::ThunkHelpers::jsStringLengthOffset): + (JSC::ThunkHelpers::jsStringValueOffset): + (JSC::charCodeAtThunkGenerator): + * jit/ThunkGenerators.h: Added. + * runtime/Executable.h: + (JSC::NativeExecutable::NativeExecutable): + * runtime/JSFunction.cpp: + (JSC::JSFunction::JSFunction): + * runtime/JSFunction.h: + * runtime/JSGlobalData.h: + (JSC::JSGlobalData::getThunk): + * runtime/JSString.h: + (JSC::): + * runtime/JSValue.h: + Protect some of the JSVALUE32 and JSVALUE32_64 only constants + and function behind appropriate USE() guards to make it harder + to use the wrong flags for the target build. + * runtime/Lookup.cpp: + (JSC::HashTable::createTable): + (JSC::setUpStaticFunctionSlot): + * runtime/Lookup.h: + (JSC::HashEntry::initialize): + (JSC::HashEntry::generator): + (JSC::HashEntry::): + Make the lookup tables use a specialized thunkGenerator + if present + * wtf/text/StringImpl.h: + +2010-04-26 Oliver Hunt <oliver@apple.com> + + Build fix + + * runtime/JSImmediate.h: + * runtime/JSValue.h: + +2010-04-26 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Factor some basic JS interface logic out of JIT and into a superclass + https://bugs.webkit.org/show_bug.cgi?id=38163 + + Create JSInterfaceJIT to hold some common low level functions for + interacting with the JS RegisterFile. Doing this separately from + https://bugs.webkit.org/show_bug.cgi?id=38155 to ease reviewing. + + * JavaScriptCore.xcodeproj/project.pbxproj: + * jit/JIT.h: + * jit/JITInlineMethods.h: + (JSC::JIT::emitJumpSlowCaseIfNotJSCell): + * jit/JSInterfaceJIT.h: Added. + (JSC::JSInterfaceJIT::emitLoadJSCell): + (JSC::JSInterfaceJIT::emitJumpIfNotJSCell): + (JSC::JSInterfaceJIT::emitLoadInt32): + (JSC::JSInterfaceJIT::tagFor): + (JSC::JSInterfaceJIT::payloadFor): + (JSC::JSInterfaceJIT::addressFor): + +2010-04-26 Sam Weinig <sam@webkit.org> + + Fix Tiger build. + + * wtf/mac/MainThreadMac.mm: + (WTF::isMainThread): + +2010-04-26 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + <rdar://problem/7766413> + + Fixed a crash seen when using the JavaScriptCore API with WebKit. + + No layout test because DumpRenderTree doesn't use the JavaScriptCore API + in this way. + + * interpreter/RegisterFile.cpp: + (JSC::RegisterFile::setGlobalObject): + (JSC::RegisterFile::clearGlobalObject): + (JSC::RegisterFile::globalObject): + * interpreter/RegisterFile.h: + (JSC::RegisterFile::RegisterFile): Use WeakGCPtr for managing m_globalObject, + since it's a weak pointer. (We never noticed this error before because, + in WebKit, global objects always have a self-reference in a global variable, + so marking the register file's global variables would keep m_globalObject + alive. In the JavaScriptCore API, you can allocate a global object with + no self-reference.) + + * runtime/JSActivation.h: Removed unneeded #include. + + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::~JSGlobalObject): Don't use ==, since a weak + pointer is 0 when the object it points to runs its destructor. + + * runtime/WeakGCPtr.h: + (JSC::WeakGCPtr::clear): Changed to return a bool indicating whether the + clear actually happened. + (JSC::WeakGCPtr::assign): Changed to forbid assignment of 0 as a shorthand + for calling clear(). A client should never clear by assigning 0, since + clear() should be conditional on whether the object doing the clearing + is still pointed to by the weak pointer. (Otherwise, a zombie object might + clear a pointer to a new, valid object.) + +2010-04-25 Sam Weinig <sam@webkit.org> + + Reviewed by Maciej Stachowiak. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38097 + Disentangle initializing the main thread from initializing threading + + This is the first step in getting rid of the WEB_THREAD #define and + paving the way to allowing mac both WebKit and WebKit2 to use the same + WebCore. + + * JavaScriptCore.exp: Export initializeMainThread and initializeMainThreadToProcessMainThread. + * JavaScriptCore.xcodeproj/project.pbxproj: Sort files. + + * wtf/MainThread.cpp: + (WTF::mainThreadInitializationMutex): + (WTF::mainThreadFunctionQueueMutex): + (WTF::initializeMainThread): + (WTF::deprecatedInitializeMainThread): + * wtf/MainThread.h: + Added Mac only initializeMainThreadToProcessMainThread which sets up callOnMainThread + and isMainThead calls to assume that WebCore's main thread is also the + process's main thread. Since it is possible that both initializeMainThread + and initializeMainThreadToProcessMainThread could be called, the first one called + wins (either will work). + + * wtf/Threading.h: Moved to top of file. + + * wtf/ThreadingPthreads.cpp: + (WTF::initializeThreading): Remove call to initializeMainThread. + * wtf/ThreadingWin.cpp: + (WTF::initializeThreading): Ditto. + * wtf/gtk/ThreadingGtk.cpp: + (WTF::initializeThreading): Ditto. + + * wtf/mac/MainThreadMac.mm: + (WTF::initializeMainThreadPlatform): + (WTF::initializeMainThreadToProcessMainThread): + (WTF::scheduleDispatchFunctionsOnMainThread): + (WTF::isMainThread): + Add runtime switch between the old behavior of using the system's main + thread and a stored pointer to the main thread. Tiger always uses the + system's main thread. + + * wtf/qt/ThreadingQt.cpp: + (WTF::initializeThreading): Remove call to initializeMainThread. + * wtf/win/MainThreadWin.cpp: + (WTF::initializeMainThreadPlatform): Add call to initializeCurrentThreadInternal + removed from initializeThreading. + +2010-04-26 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + Fix a memory leak in the QScriptString. + + QScriptStringPrivate's constructor shouldn't call JSStringRetain as + QScriptConverter implicitly pass a JSStringRef ownership. + + [Qt] QScriptStringPrivate c'tor problem + https://bugs.webkit.org/show_bug.cgi?id=38110 + + * qt/api/qscriptstring_p.h: + (QScriptStringPrivate::QScriptStringPrivate): + +2010-04-24 Darin Adler <darin@apple.com> + + Reviewed by Dan Bernstein. + + REGRESSION (r56560): Crash in parseFloat if passed invalid UTF-16 data + https://bugs.webkit.org/show_bug.cgi?id=38083 + rdar://problem/7901044 + + Tests: fast/js/ToNumber.html + fast/js/parseFloat.html + + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::parseInt): Added a FIXME comment about a problem I noticed. + (JSC::parseFloat): Added a FIXME comment about a problem I noticed; + covered by test cases in the test I added. + * runtime/UString.cpp: + (JSC::UString::toDouble): Added FIXME comments about two problems I + noticed; covered by test cases in the tests I added. Added a return + statement so we don't crash when illegal UTF-16 sequences are present. + +2010-04-24 Anton Muhin <antonm@chromium.org> + + Reviewed by Darin Adler. + + Allow to construct HashTraits<WebCore::QualifiedName>::constructDeletedValue + + Former implementation attempted to use AtomicString(HashTableDeletedValue) + however those values cannot be used that way: one cannot construct + QualifiedNameImpl out of such AtomicString as we'll try to lookup this string + in the table, for example. + https://bugs.webkit.org/show_bug.cgi?id=37722 + + * wtf/RefPtr.h: expose hash table deleted value + +2010-04-23 Sam Weinig <sam@webkit.org> + + Reviewed by David Levin. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38060 + Split up Threading.h + + Move bits for of Threading.h into 3 new files. + - Atomics.h for atomic operations. + - ThreadSafeShared.h for the ThreadSafeShared class. + - ThreadingPrimitives.h for the primitives and platform types. + + Basic threading operations (creation, etc.) remain in Threading.h. + + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * wtf/Atomics.h: Copied from wtf/Threading.h. + * wtf/ThreadSafeShared.h: Copied from wtf/Threading.h. + * wtf/Threading.h: + * wtf/ThreadingPrimitives.h: Copied from wtf/Threading.h. + +2010-04-23 Sam Weinig <sam@webkit.org> + + Fix Qt build. + + * wtf/qt/MainThreadQt.cpp: #include <QThread> + +2010-04-22 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38022 + Move isMainThread predicate function to MainThread.h + + * wtf/MainThread.cpp: + (WTF::initializeMainThread): + (WTF::isMainThread): + * wtf/MainThread.h: + * wtf/Threading.h: + * wtf/ThreadingPthreads.cpp: + (WTF::initializeThreading): + * wtf/ThreadingWin.cpp: + (WTF::initializeThreading): + * wtf/gtk/ThreadingGtk.cpp: + (WTF::initializeThreading): + * wtf/mac/MainThreadMac.mm: + (WTF::initializeMainThreadPlatform): + (WTF::isMainThread): + * wtf/qt/MainThreadQt.cpp: + (WTF::isMainThread): + * wtf/qt/ThreadingQt.cpp: + (WTF::initializeThreading): + * wtf/text/AtomicString.cpp: + +2010-04-23 Gabor Rapcsanyi <rgabor@inf.u-szeged.hu> + + Reviewed by Laszlo Gombos. + + Add RVCT support for Linux + + Developed in cooperation with Gabor Loki. + + * API/JSStringRef.h: + * jit/ExecutableAllocator.h: + * jit/ExecutableAllocatorPosix.cpp: + (JSC::ExecutableAllocator::cacheFlush): + * jit/JITStubs.cpp: + * wtf/MathExtras.h: + * wtf/unicode/qt4/UnicodeQt4.h: + +2010-04-23 Patrick Gansterer <paroga@paroga.com> + + Reviewed by Laszlo Gombos. + + [WIN] Move OwnPtrWin.cpp into platform specific folder. + https://bugs.webkit.org/show_bug.cgi?id=38042 + + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * wtf/OwnPtrWin.cpp: Removed. + * wtf/win/OwnPtrWin.cpp: Copied from JavaScriptCore/wtf/OwnPtrWin.cpp. + +2010-04-23 Patrick Gansterer <paroga@paroga.com> + + Reviewed by Laszlo Gombos. + + [BREWMP] Move OwnPtrBrew.cpp into platform specific folder. + https://bugs.webkit.org/show_bug.cgi?id=38042 + + * wtf/OwnPtrBrew.cpp: Removed. + * wtf/brew/OwnPtrBrew.cpp: Copied from JavaScriptCore/wtf/OwnPtrBrew.cpp. + +2010-04-22 Steve Block <steveblock@google.com> + + Reviewed by Adam Barth. + + Update Android to use isfinite, isinf, isnan and signbit from namespace std. + https://bugs.webkit.org/show_bug.cgi?id=37948 + + * wtf/MathExtras.h: + +2010-04-22 Fumitoshi Ukai <ukai@chromium.org> + + Unreviewed build fix. + + * wtf/MD5.cpp: fix include path of CString.h + +2010-04-22 Fumitoshi Ukai <ukai@chromium.org> + + Reviewed by Adam Barth. + + MD5 is required for WebSocket new protocol implementation + https://bugs.webkit.org/show_bug.cgi?id=37913 + + * GNUmakefile.am: + * JavaScriptCore.exp: + * JavaScriptCore.gypi: + * JavaScriptCore.pro: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * wtf/MD5.cpp: Added. + * wtf/MD5.h: Added. + +2010-04-22 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (build fix). + Errk, accidentally committed commenting out two ASSERTs! reverting. + + * runtime/Collector.cpp: + (JSC::Heap::protect): + (JSC::Heap::unprotect): + +2010-04-22 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + https://bugs.webkit.org/show_bug.cgi?id=38006 + Change lifetime of JSC::IdentifierTables used by WebCores to match AtomicStringTable + + Presently JSC's IdentifierTables are owned by the JSGlobalData. For + JSGlobalData objects created via the API this should continue to be the case, + but for the JSGlobalData objects used by WebCore (the main thread's common + global data, and those for workers) use a IdentifierTable provided (and owned) + by wtfThreadData. This allow the lifetime of these IdentifierTable to match + those of the corresponding AtomicStringTables. + + * API/APIShims.h: + (JSC::APIEntryShim::APIEntryShim): + * API/JSContextRef.cpp: + (JSContextGroupCreate): + * runtime/Collector.cpp: + (JSC::Heap::protect): + (JSC::Heap::unprotect): + (JSC::Heap::markRoots): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + (JSC::JSGlobalData::~JSGlobalData): + (JSC::JSGlobalData::createContextGroup): + (JSC::JSGlobalData::create): + (JSC::JSGlobalData::sharedInstance): + * runtime/JSGlobalData.h: + (JSC::JSGlobalData::): + (JSC::JSGlobalData::isSharedInstance): + * runtime/JSLock.cpp: + (JSC::JSLock::JSLock): + (JSC::JSLock::lock): + (JSC::JSLock::unlock): + (JSC::JSLock::DropAllLocks::DropAllLocks): + * wtf/WTFThreadData.cpp: + (WTF::WTFThreadData::WTFThreadData): + (WTF::WTFThreadData::~WTFThreadData): + +2010-04-22 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r58110. + http://trac.webkit.org/changeset/58110 + https://bugs.webkit.org/show_bug.cgi?id=38007 + + Caused an internal compiler error on Qt (Requested by abarth + on #webkit). + + * wtf/MathExtras.h: + +2010-04-22 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (windows build fix). + + * API/JSWeakObjectMapRefPrivate.cpp: + +2010-04-22 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (windows build fix). + + * API/JSBase.cpp: + * API/JSCallbackObject.cpp: + +2010-04-22 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + https://bugs.webkit.org/show_bug.cgi?id=37978 + Unify JSC::IdentifierTable and WebCore::AtomicStringTable implementations. + + These two classes both implement a HashSet of uniqued StringImpls, with + translator classes to avoid unnecessary object creation. The only difference + between the classes is which flag (isIdentifier or inTable) is set. + Combine the two classes using a template predicated on which flag to use. + + New class AtomicStringTable created, containing all the goodness from + IdentifierTable & AtomicStringTable, expect for Identifier's literalTable, + which has been moved onto JSGlobalData. Removed duplicate string translator + classes. Renamed StringImpl's inTable flag to more explicit 'isAtomic', + and set this on the empty string (which matches Identifier behaviour, and + removes a redundant check for zero-length). + + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/Identifier.cpp: + (JSC::createLiteralTable): + (JSC::deleteLiteralTable): + (JSC::Identifier::add): + (JSC::Identifier::addSlowCase): + * runtime/Identifier.h: + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + (JSC::JSGlobalData::~JSGlobalData): + * runtime/JSGlobalData.h: + * wtf/WTFThreadData.cpp: + (WTF::WTFThreadData::WTFThreadData): + (WTF::WTFThreadData::~WTFThreadData): + * wtf/WTFThreadData.h: + (WTF::WTFThreadData::atomicStringTable): + * wtf/text/AtomicString.cpp: + (WebCore::table): + (WebCore::operator==): + (WebCore::AtomicString::add): + (WebCore::AtomicString::find): + (WebCore::AtomicString::remove): + * wtf/text/AtomicStringTable.h: Added. + (WTF::CStringTranslator::hash): + (WTF::CStringTranslator::equal): + (WTF::CStringTranslator::translate): + (WTF::UCharBufferTranslator::hash): + (WTF::UCharBufferTranslator::equal): + (WTF::UCharBufferTranslator::translate): + (WTF::HashAndCharactersTranslator::hash): + (WTF::HashAndCharactersTranslator::equal): + (WTF::HashAndCharactersTranslator::translate): + (WTF::IdentifierOrAtomicStringTable::remove): + (WTF::::~IdentifierOrAtomicStringTable): + (WTF::::add): + (WTF::::find): + * wtf/text/StringImpl.cpp: + (WebCore::StringImpl::~StringImpl): + * wtf/text/StringImpl.h: + (WebCore::StringImpl::isAtomic): + (WebCore::StringImpl::setIsAtomic): + (WebCore::equal): + * wtf/text/StringImplBase.h: + (WTF::StringImplBase::StringImplBase): + +2010-04-22 Steve Block <steveblock@google.com> + + Reviewed by Adam Barth. + + Update Android to use isfinite, isinf, isnan and signbit from namespace std. + https://bugs.webkit.org/show_bug.cgi?id=37948 + + * wtf/MathExtras.h: + +2010-04-22 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Remove dependency of JSC to QtGui + https://bugs.webkit.org/show_bug.cgi?id=37867 + + The patch also make sure that hal.h is in the include path on Symbian. + The dependency to QtGui took care of that before. + + Patch by Thiago Macieira <thiago.macieira@nokia.com> + and Rohan McGovern <rohan.mcgovern@nokia.com> + + * JavaScriptCore.pri: + * JavaScriptCore.pro: + +2010-04-22 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Tor Arne Vestbø. + + [Qt] Corrects symbols visibility for JavaScriptCore. + + https://bugs.webkit.org/show_bug.cgi?id=37867 + + * JavaScriptCore.pro: + +2010-04-22 Gabor Loki <loki@webkit.org> + + Reviewed by Gavin Barraclough. + + Use BLX and BX to keep happy the return stack predictor above ARMv4 + https://bugs.webkit.org/show_bug.cgi?id=37862 + + Inspired by Jacob Bramley's patch from JaegerMonkey + + * assembler/ARMAssembler.cpp: + (JSC::ARMAssembler::executableCopy): + * assembler/ARMAssembler.h: + (JSC::ARMAssembler::): + (JSC::ARMAssembler::bx): + (JSC::ARMAssembler::blx): + (JSC::ARMAssembler::loadBranchTarget): + (JSC::ARMAssembler::jmp): + (JSC::ARMAssembler::getLdrImmAddress): + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::jump): + (JSC::MacroAssemblerARM::nearCall): + (JSC::MacroAssemblerARM::call): + (JSC::MacroAssemblerARM::ret): + (JSC::MacroAssemblerARM::prepareCall): + (JSC::MacroAssemblerARM::call32): + +2010-04-21 Andy Estes <aestes@apple.com> + + Rubber stamped by Mark Rowe. + + Export WTF::deleteOwnedPtr(HFONT). + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + 2010-04-21 Gavin Barraclough <barraclough@apple.com> Rubber Stamped by Oliver Hunt. diff --git a/JavaScriptCore/Configurations/Version.xcconfig b/JavaScriptCore/Configurations/Version.xcconfig index 6aeb263..cc5943e 100644 --- a/JavaScriptCore/Configurations/Version.xcconfig +++ b/JavaScriptCore/Configurations/Version.xcconfig @@ -22,7 +22,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAJOR_VERSION = 533; -MINOR_VERSION = 6; +MINOR_VERSION = 9; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/JavaScriptCore/GNUmakefile.am b/JavaScriptCore/GNUmakefile.am index 2d024c1..d3ca76c 100644 --- a/JavaScriptCore/GNUmakefile.am +++ b/JavaScriptCore/GNUmakefile.am @@ -89,12 +89,17 @@ javascriptcore_sources += \ JavaScriptCore/jit/JITPropertyAccess.cpp \ JavaScriptCore/jit/JITPropertyAccess32_64.cpp \ JavaScriptCore/jit/JITArithmetic.cpp \ + JavaScriptCore/jit/JITArithmetic32_64.cpp \ JavaScriptCore/jit/ExecutableAllocator.cpp \ JavaScriptCore/jit/JIT.h \ JavaScriptCore/jit/JITInlineMethods.h \ JavaScriptCore/jit/JITStubs.cpp \ JavaScriptCore/jit/JITStubs.h \ JavaScriptCore/jit/JITStubCall.h \ + JavaScriptCore/jit/JSInterfaceJIT.h \ + JavaScriptCore/jit/SpecializedThunkJIT.h \ + JavaScriptCore/jit/ThunkGenerators.cpp \ + JavaScriptCore/jit/ThunkGenerators.h \ JavaScriptCore/bytecode/StructureStubInfo.cpp \ JavaScriptCore/bytecode/StructureStubInfo.h \ JavaScriptCore/bytecode/CodeBlock.cpp \ @@ -224,6 +229,7 @@ javascriptcore_sources += \ JavaScriptCore/wtf/AlwaysInline.h \ JavaScriptCore/wtf/Assertions.cpp \ JavaScriptCore/wtf/Assertions.h \ + JavaScriptCore/wtf/Atomics.h \ JavaScriptCore/wtf/ByteArray.cpp \ JavaScriptCore/wtf/ByteArray.h \ JavaScriptCore/wtf/CrossThreadRefCounted.h \ @@ -246,6 +252,8 @@ javascriptcore_sources += \ JavaScriptCore/wtf/ListHashSet.h \ JavaScriptCore/wtf/ListRefPtr.h \ JavaScriptCore/wtf/Locker.h \ + JavaScriptCore/wtf/MD5.cpp \ + JavaScriptCore/wtf/MD5.h \ JavaScriptCore/wtf/MainThread.cpp \ JavaScriptCore/wtf/MainThread.h \ JavaScriptCore/wtf/MathExtras.h \ @@ -281,7 +289,9 @@ javascriptcore_sources += \ JavaScriptCore/wtf/ThreadIdentifierDataPthreads.h \ JavaScriptCore/wtf/Threading.cpp \ JavaScriptCore/wtf/Threading.h \ + JavaScriptCore/wtf/ThreadingPrimitives.h \ JavaScriptCore/wtf/ThreadingPthreads.cpp \ + JavaScriptCore/wtf/ThreadSafeShared.h \ JavaScriptCore/wtf/ThreadSpecific.h \ JavaScriptCore/wtf/TypeTraits.cpp \ JavaScriptCore/wtf/TypeTraits.h \ diff --git a/JavaScriptCore/JavaScriptCore.exp b/JavaScriptCore/JavaScriptCore.exp index e8e34ee..c08b54d 100644 --- a/JavaScriptCore/JavaScriptCore.exp +++ b/JavaScriptCore/JavaScriptCore.exp @@ -331,6 +331,7 @@ __ZN3WTF18dateToDaysFrom1970Eiii __ZN3WTF18monthFromDayInYearEib __ZN3WTF19initializeThreadingEv __ZN3WTF20fastMallocStatisticsEv +__ZN3WTF20initializeMainThreadEv __ZN3WTF21RefCountedLeakCounter16suppressMessagesEPKc __ZN3WTF21RefCountedLeakCounter24cancelMessageSuppressionEPKc __ZN3WTF21RefCountedLeakCounter9decrementEv @@ -346,6 +347,10 @@ __ZN3WTF32doubleToStringInJavaScriptFormatEdPcPj __ZN3WTF36lockAtomicallyInitializedStaticMutexEv __ZN3WTF37parseDateFromNullTerminatedCharactersEPKc __ZN3WTF38unlockAtomicallyInitializedStaticMutexEv +__ZN3WTF39initializeMainThreadToProcessMainThreadEv +__ZN3WTF3MD58addBytesEPKhm +__ZN3WTF3MD58checksumEv +__ZN3WTF3MD5C1Ev __ZN3WTF5Mutex4lockEv __ZN3WTF5Mutex6unlockEv __ZN3WTF5Mutex7tryLockEv diff --git a/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp b/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp index b2ccf1a..9e014dd 100644 --- a/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp +++ b/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp @@ -117,6 +117,7 @@ ['exclude', '/(gtk|glib|gobject)/.*\\.(cpp|h)$'], ['exclude', '(Default|Gtk|Mac|None|Qt|Win|Wx)\\.(cpp|mm)$'], ['exclude', 'wtf/CurrentTime\\.cpp$'], + ['exclude', 'wtf/MainThread.cpp$'], ['exclude', 'wtf/TC.*\\.(cpp|h)$'], ], 'direct_dependent_settings': { diff --git a/JavaScriptCore/JavaScriptCore.gypi b/JavaScriptCore/JavaScriptCore.gypi index ad2d09e..0e9774b 100644 --- a/JavaScriptCore/JavaScriptCore.gypi +++ b/JavaScriptCore/JavaScriptCore.gypi @@ -115,6 +115,7 @@ 'jit/JIT.cpp', 'jit/JIT.h', 'jit/JITArithmetic.cpp', + 'jit/JITArithmetic32_64.cpp', 'jit/JITCall.cpp', 'jit/JITCode.h', 'jit/JITInlineMethods.h', @@ -336,6 +337,7 @@ 'wtf/ASCIICType.h', 'wtf/Assertions.cpp', 'wtf/Assertions.h', + 'wtf/Atomics.h', 'wtf/AVLTree.h', 'wtf/ByteArray.cpp', 'wtf/ByteArray.h', @@ -370,6 +372,8 @@ 'wtf/ListHashSet.h', 'wtf/ListRefPtr.h', 'wtf/Locker.h', + 'wtf/MD5.cpp', + 'wtf/MD5.h', 'wtf/MainThread.cpp', 'wtf/MainThread.h', 'wtf/MallocZoneSupport.h', @@ -381,7 +385,6 @@ 'wtf/OwnFastMallocPtr.h', 'wtf/OwnPtr.h', 'wtf/OwnPtrCommon.h', - 'wtf/OwnPtrWin.cpp', 'wtf/PassOwnPtr.h', 'wtf/PassRefPtr.h', 'wtf/Platform.h', @@ -413,8 +416,10 @@ 'wtf/Threading.cpp', 'wtf/Threading.h', 'wtf/ThreadingNone.cpp', + 'wtf/ThreadingPrimitives.h', 'wtf/ThreadingPthreads.cpp', 'wtf/ThreadingWin.cpp', + 'wtf/ThreadSafeShared.h', 'wtf/ThreadSpecific.h', 'wtf/ThreadSpecificWin.cpp', 'wtf/TypeTraits.cpp', @@ -448,6 +453,7 @@ 'wtf/WTFThreadData.cpp', 'wtf/WTFThreadData.h', 'wtf/win/MainThreadWin.cpp', + 'wtf/win/OwnPtrWin.cpp', 'wtf/wx/MainThreadWx.cpp', 'yarr/RegexCompiler.cpp', 'yarr/RegexCompiler.h', diff --git a/JavaScriptCore/JavaScriptCore.pri b/JavaScriptCore/JavaScriptCore.pri index 24c8ce5..de5505f 100644 --- a/JavaScriptCore/JavaScriptCore.pri +++ b/JavaScriptCore/JavaScriptCore.pri @@ -1,7 +1,14 @@ # JavaScriptCore - Qt4 build info VPATH += $$PWD -JAVASCRIPTCORE_TARGET = jscore - +CONFIG(debug, debug|release) { + # Output in JavaScriptCore/<config> + JAVASCRIPTCORE_DESTDIR = debug + # Use a config-specific target to prevent parallel builds file clashes on Mac + JAVASCRIPTCORE_TARGET = jscored +} else { + JAVASCRIPTCORE_DESTDIR = release + JAVASCRIPTCORE_TARGET = jscore +} CONFIG(standalone_package) { isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = $$PWD/generated } else { @@ -14,6 +21,8 @@ symbian: { # Need to guarantee this comes before system includes of /epoc32/include MMP_RULES += "USERINCLUDE ../JavaScriptCore/profiler" LIBS += -lhal + # For hal.h + INCLUDEPATH *= $$MW_LAYER_SYSTEMINCLUDE } INCLUDEPATH = \ @@ -63,9 +72,8 @@ wince* { defineTest(addJavaScriptCoreLib) { - pathToJavaScriptCoreOutput = $$ARGS - CONFIG(debug_and_release):CONFIG(debug, debug|release): pathToJavaScriptCoreOutput = $$pathToJavaScriptCoreOutput/debug - CONFIG(debug_and_release):CONFIG(release, debug|release): pathToJavaScriptCoreOutput = $$pathToJavaScriptCoreOutput/release + # Argument is the relative path to JavaScriptCore.pro's qmake output + pathToJavaScriptCoreOutput = $$ARGS/$$JAVASCRIPTCORE_DESTDIR win32-msvc*|wince* { LIBS += -L$$pathToJavaScriptCoreOutput @@ -73,6 +81,9 @@ defineTest(addJavaScriptCoreLib) { POST_TARGETDEPS += $${pathToJavaScriptCoreOutput}$${QMAKE_DIR_SEP}$${JAVASCRIPTCORE_TARGET}.lib } else:symbian { LIBS += -l$${JAVASCRIPTCORE_TARGET}.lib + # The default symbian build system does not use library paths at all. However when building with + # qmake's symbian makespec that uses Makefiles + QMAKE_LIBDIR += $$pathToJavaScriptCoreOutput POST_TARGETDEPS += $${pathToJavaScriptCoreOutput}$${QMAKE_DIR_SEP}$${JAVASCRIPTCORE_TARGET}.lib } else { # Make sure jscore will be early in the list of libraries to workaround a bug in MinGW diff --git a/JavaScriptCore/JavaScriptCore.pro b/JavaScriptCore/JavaScriptCore.pro index f33be05..fc242cf 100644 --- a/JavaScriptCore/JavaScriptCore.pro +++ b/JavaScriptCore/JavaScriptCore.pro @@ -8,16 +8,19 @@ CONFIG += staticlib # Don't use JavaScriptCore as the target name. qmake would create a JavaScriptCore.vcproj for msvc # which already exists as a directory TARGET = $$JAVASCRIPTCORE_TARGET +DESTDIR = $$JAVASCRIPTCORE_DESTDIR QT += core +QT -= gui CONFIG += depend_includepath contains(QT_CONFIG, embedded):CONFIG += embedded -CONFIG(debug_and_release):CONFIG(debug, debug|release): DESTDIR = debug -CONFIG(debug_and_release):CONFIG(release, debug|release): DESTDIR = release - -!CONFIG(QTDIR_build) { +CONFIG(QTDIR_build) { + # Make sure we compile both debug and release on mac when inside Qt. + # This line was extracted from qbase.pri instead of including the whole file + win32|mac:!macx-xcode:CONFIG += debug_and_release +} else { CONFIG(debug, debug|release) { OBJECTS_DIR = obj/debug } else { # Release @@ -27,6 +30,12 @@ CONFIG(debug_and_release):CONFIG(release, debug|release): DESTDIR = release mac:contains(QT_CONFIG, qt_framework):!CONFIG(webkit_no_framework):!build_pass:CONFIG += build_all } +# WebCore adds these config only when in a standalone build. +# qbase.pri takes care of that when in a QTDIR_build +# Here we add the config for both cases since we don't include qbase.pri +contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols +unix:contains(QT_CONFIG, reduce_relocations):CONFIG += bsymbolic_functions + CONFIG(QTDIR_build) { # Remove the following 2 lines if you want debug information in JavaScriptCore CONFIG -= separate_debug_info @@ -90,12 +99,14 @@ SOURCES += \ jit/ExecutableAllocatorWin.cpp \ jit/ExecutableAllocator.cpp \ jit/JITArithmetic.cpp \ + jit/JITArithmetic32_64.cpp \ jit/JITCall.cpp \ jit/JIT.cpp \ jit/JITOpcodes.cpp \ jit/JITPropertyAccess.cpp \ jit/JITPropertyAccess32_64.cpp \ jit/JITStubs.cpp \ + jit/ThunkGenerators.cpp \ parser/Lexer.cpp \ parser/Nodes.cpp \ parser/ParserArena.cpp \ @@ -194,6 +205,7 @@ SOURCES += \ wtf/dtoa.cpp \ wtf/FastMalloc.cpp \ wtf/HashTable.cpp \ + wtf/MD5.cpp \ wtf/MainThread.cpp \ wtf/qt/MainThreadQt.cpp \ wtf/qt/StringQt.cpp \ @@ -223,3 +235,6 @@ SOURCES += \ !contains(DEFINES, USE_SYSTEM_MALLOC) { SOURCES += wtf/TCSystemAlloc.cpp } + +# Disable C++0x mode in JSC for those who enabled it in their Qt's mkspec +*-g++*:QMAKE_CXXFLAGS -= -std=c++0x -std=gnu++0x diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def index 76f2fa7..faa1d01 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def @@ -11,6 +11,7 @@ EXPORTS ??0JSArray@JSC@@QAE@V?$NonNullPassRefPtr@VStructure@JSC@@@WTF@@ABVArgList@1@@Z ??0JSByteArray@JSC@@QAE@PAVExecState@1@V?$NonNullPassRefPtr@VStructure@JSC@@@WTF@@PAVByteArray@4@PBUClassInfo@1@@Z ??0JSFunction@JSC@@QAE@PAVExecState@1@V?$NonNullPassRefPtr@VStructure@JSC@@@WTF@@HABVIdentifier@1@P6I?AVJSValue@1@0PAVJSObject@1@V61@ABVArgList@1@@Z@Z + ??0MD5@WTF@@QAE@XZ ??0Mutex@WTF@@QAE@XZ ??0PrototypeFunction@JSC@@QAE@PAVExecState@1@HABVIdentifier@1@P6I?AVJSValue@1@0PAVJSObject@1@V41@ABVArgList@1@@Z@Z ??0PrototypeFunction@JSC@@QAE@PAVExecState@1@V?$NonNullPassRefPtr@VStructure@JSC@@@WTF@@HABVIdentifier@1@P6I?AVJSValue@1@0PAVJSObject@1@V61@ABVArgList@1@@Z@Z @@ -54,6 +55,7 @@ EXPORTS ?add@AtomicString@WebCore@@CA?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@PB_WII@Z ?add@Identifier@JSC@@SA?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@PAVExecState@2@PBD@Z ?add@PropertyNameArray@JSC@@QAEXPAVStringImpl@WebCore@@@Z + ?addBytes@MD5@WTF@@QAEXPBEI@Z ?addPropertyTransition@Structure@JSC@@SA?AV?$PassRefPtr@VStructure@JSC@@@WTF@@PAV12@ABVIdentifier@2@IPAVJSCell@2@AAI@Z ?addPropertyTransitionToExistingStructure@Structure@JSC@@SA?AV?$PassRefPtr@VStructure@JSC@@@WTF@@PAV12@ABVIdentifier@2@IPAVJSCell@2@AAI@Z ?addPropertyWithoutTransition@Structure@JSC@@QAEIABVIdentifier@2@IPAVJSCell@2@@Z @@ -86,12 +88,12 @@ EXPORTS ?checkCurrentIdentifierTable@Identifier@JSC@@CAXPAVExecState@2@@Z ?checkCurrentIdentifierTable@Identifier@JSC@@CAXPAVJSGlobalData@2@@Z ?checkSyntax@JSC@@YA?AVCompletion@1@PAVExecState@1@ABVSourceCode@1@@Z + ?checksum@MD5@WTF@@QAE?AV?$Vector@E$0BA@@2@XZ ?classInfo@InternalFunction@JSC@@UBEPBUClassInfo@2@XZ ?classInfo@JSCell@JSC@@UBEPBUClassInfo@2@XZ ?className@JSObject@JSC@@UBE?AVUString@2@XZ ?collate@Collator@WTF@@QBE?AW4Result@12@PB_WI0I@Z ?collectAllGarbage@Heap@JSC@@QAEXXZ - ?commentAtom@WebCore@@3VAtomicString@1@B ?configurable@PropertyDescriptor@JSC@@QBE_NXZ ?construct@JSC@@YAPAVJSObject@1@PAVExecState@1@VJSValue@1@W4ConstructType@1@ABTConstructData@1@ABVArgList@1@@Z ?constructArray@JSC@@YAPAVJSArray@1@PAVExecState@1@ABVArgList@1@@Z @@ -138,6 +140,7 @@ EXPORTS ?defineSetter@JSObject@JSC@@UAEXPAVExecState@2@ABVIdentifier@2@PAV12@I@Z ?deleteOwnedPtr@WTF@@YAXPAUHBITMAP__@@@Z ?deleteOwnedPtr@WTF@@YAXPAUHDC__@@@Z + ?deleteOwnedPtr@WTF@@YAXPAUHFONT__@@@Z ?deleteOwnedPtr@WTF@@YAXPAUHRGN__@@@Z ?deleteProperty@JSCell@JSC@@UAE_NPAVExecState@2@ABVIdentifier@2@@Z ?deleteProperty@JSCell@JSC@@UAE_NPAVExecState@2@I@Z @@ -156,7 +159,6 @@ EXPORTS ?doubleToStringInJavaScriptFormat@WTF@@YAXNQADPAI@Z ?dumpSampleData@JSGlobalData@JSC@@QAEXPAVExecState@2@@Z ?empty@StringImpl@WebCore@@SAPAV12@XZ - ?emptyAtom@WebCore@@3VAtomicString@1@B ?endsWith@StringImpl@WebCore@@QAE_NPAV12@_N@Z ?enumerable@PropertyDescriptor@JSC@@QBE_NXZ ?equal@Identifier@JSC@@SA_NPBVStringImpl@WebCore@@PBD@Z @@ -273,7 +275,6 @@ EXPORTS ?name@InternalFunction@JSC@@QAEABVUString@2@PAVExecState@2@@Z ?newUninitialized@CString@WTF@@SA?AV12@IAAPAD@Z ?nonInlineNaN@JSC@@YANXZ - ?nullAtom@WebCore@@3VAtomicString@1@B ?number@String@WebCore@@SA?AV12@G@Z ?number@String@WebCore@@SA?AV12@H@Z ?number@String@WebCore@@SA?AV12@I@Z @@ -346,11 +347,9 @@ EXPORTS ?split@String@WebCore@@QBEXABV12@_NAAV?$Vector@VString@WebCore@@$0A@@WTF@@@Z ?split@String@WebCore@@QBEX_WAAV?$Vector@VString@WebCore@@$0A@@WTF@@@Z ?split@String@WebCore@@QBEX_W_NAAV?$Vector@VString@WebCore@@$0A@@WTF@@@Z - ?starAtom@WebCore@@3VAtomicString@1@B ?startIgnoringLeaks@Structure@JSC@@SAXXZ ?startProfiling@Profiler@JSC@@QAEXPAVExecState@2@ABVUString@2@@Z ?startSampling@JSGlobalData@JSC@@QAEXXZ - ?staticData@WTFThreadData@WTF@@0PAV?$ThreadSpecific@VWTFThreadData@WTF@@@2@A ?stopIgnoringLeaks@Structure@JSC@@SAXXZ ?stopProfiling@Profiler@JSC@@QAE?AV?$PassRefPtr@VProfile@JSC@@@WTF@@PAVExecState@2@ABVUString@2@@Z ?stopSampling@JSGlobalData@JSC@@QAEXXZ @@ -361,7 +360,6 @@ EXPORTS ?substring@StringImpl@WebCore@@QAE?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@II@Z ?symbolTableGet@JSVariableObject@JSC@@IAE_NABVIdentifier@2@AAVPropertyDescriptor@2@@Z ?synthesizePrototype@JSValue@JSC@@ABEPAVJSObject@2@PAVExecState@2@@Z - ?textAtom@WebCore@@3VAtomicString@1@B ?thisObject@DebuggerCallFrame@JSC@@QBEPAVJSObject@2@XZ ?threadsafeCopy@String@WebCore@@QBE?AV12@XZ ?throwError@JSC@@YAPAVJSObject@1@PAVExecState@1@W4ErrorType@1@@Z @@ -420,8 +418,6 @@ EXPORTS ?wait@ThreadCondition@WTF@@QAEXAAVMutex@2@@Z ?waitForThreadCompletion@WTF@@YAHIPAPAX@Z ?writable@PropertyDescriptor@JSC@@QBE_NXZ - ?xmlAtom@WebCore@@3VAtomicString@1@B - ?xmlnsAtom@WebCore@@3VAtomicString@1@B WTFLog WTFLogVerbose WTFReportArgumentAssertionFailure diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj index 158621a..dddf194 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj @@ -1669,6 +1669,10 @@ >
</File>
<File
+ RelativePath="..\..\jit\JITArithmetic32_64.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\jit\JITCall.cpp"
>
</File>
@@ -1704,6 +1708,22 @@ RelativePath="..\..\jit\JITStubs.h"
>
</File>
+ <File
+ RelativePath="..\..\jit\JSInterfaceJIT.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\jit\SpecializedThunkJIT.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\jit\ThunkGenerators.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\jit\ThunkGenerators.h"
+ >
+ </File>
</Filter>
<Filter
Name="Resources"
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj b/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj index 0145311..d094643 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj +++ b/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj @@ -239,6 +239,10 @@ RelativePath="..\..\wtf\win\MainThreadWin.cpp"
>
</File>
+ <File
+ RelativePath="..\..\wtf\win\OwnPtrWin.cpp"
+ >
+ </File>
</Filter>
<File
RelativePath="..\..\wtf\AlwaysInline.h"
@@ -257,6 +261,10 @@ >
</File>
<File
+ RelativePath="..\..\wtf\Atomics.h"
+ >
+ </File>
+ <File
RelativePath="..\..\wtf\ByteArray.cpp"
>
</File>
@@ -373,6 +381,14 @@ >
</File>
<File
+ RelativePath="..\..\wtf\MD5.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\MD5.h"
+ >
+ </File>
+ <File
RelativePath="..\..\wtf\MainThread.cpp"
>
</File>
@@ -413,10 +429,6 @@ >
</File>
<File
- RelativePath="..\..\wtf\OwnPtrWin.cpp"
- >
- </File>
- <File
RelativePath="..\..\wtf\PassOwnPtr.h"
>
</File>
@@ -505,10 +517,18 @@ >
</File>
<File
+ RelativePath="..\..\wtf\ThreadingPrimitives.h"
+ >
+ </File>
+ <File
RelativePath="..\..\wtf\ThreadingWin.cpp"
>
</File>
<File
+ RelativePath="..\..\wtf\ThreadSafeShared.h"
+ >
+ </File>
+ <File
RelativePath="..\..\wtf\ThreadSpecific.h"
>
</File>
diff --git a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index 9dff7ef..2c99612 100644 --- a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -176,6 +176,8 @@ 41359CF70FDD89CB00206180 /* DateMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 41359CF50FDD89CB00206180 /* DateMath.h */; settings = {ATTRIBUTES = (Private, ); }; }; 4409D8470FAF80A200523B87 /* OwnPtrCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 440B7AED0FAF7FCB0073323E /* OwnPtrCommon.h */; settings = {ATTRIBUTES = (Private, ); }; }; 44DD48530FAEA85000D6B4EB /* PassOwnPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 44DD48520FAEA85000D6B4EB /* PassOwnPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 511FC4C9117EE28700425272 /* MD5.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 511FC4C7117EE23D00425272 /* MD5.cpp */; }; + 511FC4CB117EE2A800425272 /* MD5.h in Headers */ = {isa = PBXBuildFile; fileRef = 511FC4CA117EE2A800425272 /* MD5.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5D53726F0E1C54880021E549 /* Tracing.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D53726E0E1C54880021E549 /* Tracing.h */; }; 5D5D8AB60E0D0A7200F9C692 /* jsc in Copy Into Framework */ = {isa = PBXBuildFile; fileRef = 932F5BE10822A1C700736975 /* jsc */; }; 5D5D8AD10E0D0EBE00F9C692 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; }; @@ -209,6 +211,7 @@ 868BFA60117D048200B908B1 /* StaticConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA5F117D048200B908B1 /* StaticConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; }; 8698B86910D44D9400D8D01B /* StringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 8698B86810D44D9400D8D01B /* StringBuilder.h */; settings = {ATTRIBUTES = (Private, ); }; }; 8698BB3910D86BAF00D8D01B /* UStringImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 8698BB3710D86BAF00D8D01B /* UStringImpl.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 869D04AF1193B54D00803475 /* CachedTranscendentalFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 869D04AE1193B54D00803475 /* CachedTranscendentalFunction.h */; settings = {ATTRIBUTES = (Private, ); }; }; 869EBCB70E8C6D4A008722CC /* ResultType.h in Headers */ = {isa = PBXBuildFile; fileRef = 869EBCB60E8C6D4A008722CC /* ResultType.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86A90ED00EE7D51F00AB350D /* JITArithmetic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */; }; 86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */; }; @@ -288,11 +291,16 @@ A72701B90DADE94900E548D7 /* ExceptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A72701B30DADE94900E548D7 /* ExceptionHelpers.h */; }; A727FF6B0DA3092200E548D7 /* JSPropertyNameIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */; }; A7280A2811557E3000D56957 /* JSObjectRefPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A79EDB0811531CD60019E912 /* JSObjectRefPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A7386554118697B400540279 /* SpecializedThunkJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = A7386551118697B400540279 /* SpecializedThunkJIT.h */; }; + A7386555118697B400540279 /* ThunkGenerators.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7386552118697B400540279 /* ThunkGenerators.cpp */; }; + A7386556118697B400540279 /* ThunkGenerators.h in Headers */ = {isa = PBXBuildFile; fileRef = A7386553118697B400540279 /* ThunkGenerators.h */; settings = {ATTRIBUTES = (Private, ); }; }; A7482B9311671147003B0712 /* JSWeakObjectMapRefPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A7482B791166CDEA003B0712 /* JSWeakObjectMapRefPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; A7482B9411671147003B0712 /* JSWeakObjectMapRefPrivate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7482B7A1166CDEA003B0712 /* JSWeakObjectMapRefPrivate.cpp */; }; A7482E93116A7CAD003B0712 /* JSWeakObjectMapRefInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = A7482E37116A697B003B0712 /* JSWeakObjectMapRefInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; A74B3499102A5F8E0032AB98 /* MarkStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A74B3498102A5F8E0032AB98 /* MarkStack.cpp */; }; + A75706DE118A2BCF0057F88F /* JITArithmetic32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */; }; A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = A76C51741182748D00715B05 /* JSInterfaceJIT.h */; }; A76EE6590FAE59D5003F069A /* NativeFunctionWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = A76EE6580FAE59D5003F069A /* NativeFunctionWrapper.h */; settings = {ATTRIBUTES = (Private, ); }; }; A7795590101A74D500114E55 /* MarkStack.h in Headers */ = {isa = PBXBuildFile; fileRef = A779558F101A74D500114E55 /* MarkStack.h */; settings = {ATTRIBUTES = (Private, ); }; }; A782F1A50EEC9FA20036273F /* ExecutableAllocatorPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A782F1A40EEC9FA20036273F /* ExecutableAllocatorPosix.cpp */; }; @@ -458,6 +466,9 @@ BC3046070E1F497F003232CF /* Error.h in Headers */ = {isa = PBXBuildFile; fileRef = BC3046060E1F497F003232CF /* Error.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC3135640F302FA3003DFD3A /* DebuggerActivation.h in Headers */ = {isa = PBXBuildFile; fileRef = BC3135620F302FA3003DFD3A /* DebuggerActivation.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC3135650F302FA3003DFD3A /* DebuggerActivation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC3135630F302FA3003DFD3A /* DebuggerActivation.cpp */; }; + BC5F7BBE11823B590052C02C /* Atomics.h in Headers */ = {isa = PBXBuildFile; fileRef = BC5F7BBB11823B590052C02C /* Atomics.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BC5F7BBF11823B590052C02C /* ThreadingPrimitives.h in Headers */ = {isa = PBXBuildFile; fileRef = BC5F7BBC11823B590052C02C /* ThreadingPrimitives.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BC5F7BC011823B590052C02C /* ThreadSafeShared.h in Headers */ = {isa = PBXBuildFile; fileRef = BC5F7BBD11823B590052C02C /* ThreadSafeShared.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC6AAAE50E1F426500AD87D8 /* ClassInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC756FC90E2031B200DE7D12 /* JSGlobalObjectFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = BC756FC70E2031B200DE7D12 /* JSGlobalObjectFunctions.h */; }; BC7F8FB90E19D1C3008632C0 /* JSNumberCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7F8FB80E19D1C3008632C0 /* JSNumberCell.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -671,6 +682,8 @@ 449097EE0F8F81B50076A327 /* FeatureDefines.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = FeatureDefines.xcconfig; sourceTree = "<group>"; }; 44DD48520FAEA85000D6B4EB /* PassOwnPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PassOwnPtr.h; sourceTree = "<group>"; }; 45E12D8806A49B0F00E9DF84 /* jsc.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = jsc.cpp; sourceTree = "<group>"; tabWidth = 4; }; + 511FC4C7117EE23D00425272 /* MD5.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MD5.cpp; sourceTree = "<group>"; }; + 511FC4CA117EE2A800425272 /* MD5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MD5.h; sourceTree = "<group>"; }; 5186111D0CC824830081412B /* Deque.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Deque.h; sourceTree = "<group>"; }; 51F0EB6105C86C6B00E6DF1B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; }; 51F0EC0705C86C9A00E6DF1B /* libobjc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libobjc.dylib; path = /usr/lib/libobjc.dylib; sourceTree = "<absolute>"; }; @@ -751,6 +764,7 @@ 868BFA5F117D048200B908B1 /* StaticConstructors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StaticConstructors.h; sourceTree = "<group>"; }; 8698B86810D44D9400D8D01B /* StringBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringBuilder.h; sourceTree = "<group>"; }; 8698BB3710D86BAF00D8D01B /* UStringImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UStringImpl.h; sourceTree = "<group>"; }; + 869D04AE1193B54D00803475 /* CachedTranscendentalFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedTranscendentalFunction.h; sourceTree = "<group>"; }; 869EBCB60E8C6D4A008722CC /* ResultType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResultType.h; sourceTree = "<group>"; }; 86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITArithmetic.cpp; sourceTree = "<group>"; }; 86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMv7Assembler.h; sourceTree = "<group>"; }; @@ -862,10 +876,15 @@ A72701B30DADE94900E548D7 /* ExceptionHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExceptionHelpers.h; sourceTree = "<group>"; }; A727FF650DA3053B00E548D7 /* JSPropertyNameIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameIterator.h; sourceTree = "<group>"; }; A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameIterator.cpp; sourceTree = "<group>"; }; + A7386551118697B400540279 /* SpecializedThunkJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpecializedThunkJIT.h; sourceTree = "<group>"; }; + A7386552118697B400540279 /* ThunkGenerators.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThunkGenerators.cpp; sourceTree = "<group>"; }; + A7386553118697B400540279 /* ThunkGenerators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThunkGenerators.h; sourceTree = "<group>"; }; A7482B791166CDEA003B0712 /* JSWeakObjectMapRefPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWeakObjectMapRefPrivate.h; sourceTree = "<group>"; }; A7482B7A1166CDEA003B0712 /* JSWeakObjectMapRefPrivate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWeakObjectMapRefPrivate.cpp; sourceTree = "<group>"; }; A7482E37116A697B003B0712 /* JSWeakObjectMapRefInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWeakObjectMapRefInternal.h; sourceTree = "<group>"; }; A74B3498102A5F8E0032AB98 /* MarkStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkStack.cpp; sourceTree = "<group>"; }; + A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITArithmetic32_64.cpp; sourceTree = "<group>"; }; + A76C51741182748D00715B05 /* JSInterfaceJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSInterfaceJIT.h; sourceTree = "<group>"; }; A76EE6580FAE59D5003F069A /* NativeFunctionWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeFunctionWrapper.h; sourceTree = "<group>"; }; A779558F101A74D500114E55 /* MarkStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkStack.h; sourceTree = "<group>"; }; A782F1A40EEC9FA20036273F /* ExecutableAllocatorPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocatorPosix.cpp; sourceTree = "<group>"; }; @@ -950,6 +969,9 @@ BC3135630F302FA3003DFD3A /* DebuggerActivation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DebuggerActivation.cpp; sourceTree = "<group>"; }; BC337BDE0E1AF0B80076918A /* GetterSetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetterSetter.h; sourceTree = "<group>"; }; BC337BEA0E1B00CB0076918A /* Error.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Error.cpp; sourceTree = "<group>"; }; + BC5F7BBB11823B590052C02C /* Atomics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Atomics.h; sourceTree = "<group>"; }; + BC5F7BBC11823B590052C02C /* ThreadingPrimitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadingPrimitives.h; sourceTree = "<group>"; }; + BC5F7BBD11823B590052C02C /* ThreadSafeShared.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadSafeShared.h; sourceTree = "<group>"; }; BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClassInfo.h; sourceTree = "<group>"; }; BC756FC60E2031B200DE7D12 /* JSGlobalObjectFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalObjectFunctions.cpp; sourceTree = "<group>"; }; BC756FC70E2031B200DE7D12 /* JSGlobalObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObjectFunctions.h; sourceTree = "<group>"; }; @@ -1192,6 +1214,9 @@ 1429D92C0ED22D7000B89619 /* jit */ = { isa = PBXGroup; children = ( + A7386551118697B400540279 /* SpecializedThunkJIT.h */, + A7386552118697B400540279 /* ThunkGenerators.cpp */, + A7386553118697B400540279 /* ThunkGenerators.h */, A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */, A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */, 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */, @@ -1200,6 +1225,7 @@ 1429D92D0ED22D7000B89619 /* JIT.cpp */, 1429D92E0ED22D7000B89619 /* JIT.h */, 86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */, + A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */, 86CC85A20EE79B7400288682 /* JITCall.cpp */, 86CCEFDD0F413F8900FD7F9E /* JITCode.h */, 86CC85A00EE79A4700288682 /* JITInlineMethods.h */, @@ -1209,6 +1235,7 @@ 960626950FB8EC02009798AB /* JITStubCall.h */, 14A23D6C0F4E19CE0023CDAD /* JITStubs.cpp */, 14A6581A0F4E36F4000150FD /* JITStubs.h */, + A76C51741182748D00715B05 /* JSInterfaceJIT.h */, ); path = jit; sourceTree = "<group>"; @@ -1340,6 +1367,7 @@ 938C4F690CA06BC700D9310A /* ASCIICType.h */, 65E217B808E7EECC0023E5F6 /* Assertions.cpp */, 65E217B708E7EECC0023E5F6 /* Assertions.h */, + BC5F7BBB11823B590052C02C /* Atomics.h */, E1A596370DE3E1C300C17E37 /* AVLTree.h */, A7A1F7AA0F252B3C00E184E2 /* ByteArray.cpp */, A7A1F7AB0F252B3C00E184E2 /* ByteArray.h */, @@ -1372,6 +1400,8 @@ 06D358A30DAAD9C4003B174E /* MainThread.h */, 5DBD18AF0C5401A700C15EAE /* MallocZoneSupport.h */, BCF6553B0A2048DE0038A194 /* MathExtras.h */, + 511FC4C7117EE23D00425272 /* MD5.cpp */, + 511FC4CA117EE2A800425272 /* MD5.h */, E1EE798B0D6CA53D00FEA3BA /* MessageQueue.h */, 9303F5690991190000AD71B8 /* Noncopyable.h */, C0A2723F0E509F1E00E96E15 /* NotFound.h */, @@ -1406,7 +1436,9 @@ 18BAB52810DADFCD000D945B /* ThreadIdentifierDataPthreads.h */, 5D6A566A0F05995500266145 /* Threading.cpp */, E1EE79220D6C95CD00FEA3BA /* Threading.h */, + BC5F7BBC11823B590052C02C /* ThreadingPrimitives.h */, E1EE793C0D6C9B9200FEA3BA /* ThreadingPthreads.cpp */, + BC5F7BBD11823B590052C02C /* ThreadSafeShared.h */, E1B7C8BD0DA3A3360074B0DC /* ThreadSpecific.h */, 0B330C260F38C62300692DE3 /* TypeTraits.cpp */, 0B4D7E620F319AC800AD7E58 /* TypeTraits.h */, @@ -1493,6 +1525,7 @@ 704FD35305697E6D003DBED9 /* BooleanObject.h */, BC7952340E15EB5600A898AB /* BooleanPrototype.cpp */, BC7952350E15EB5600A898AB /* BooleanPrototype.h */, + 869D04AE1193B54D00803475 /* CachedTranscendentalFunction.h */, BCA62DFE0E2826230004F30D /* CallData.cpp */, 145C507F0D9DF63B0088F6B9 /* CallData.h */, BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */, @@ -2089,6 +2122,14 @@ 86B99AB9117E391E00DF5A90 /* RopeImpl.h in Headers */, 86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */, 86B99AE4117E578100DF5A90 /* StringImplBase.h in Headers */, + 511FC4CB117EE2A800425272 /* MD5.h in Headers */, + BC5F7BBE11823B590052C02C /* Atomics.h in Headers */, + BC5F7BBF11823B590052C02C /* ThreadingPrimitives.h in Headers */, + BC5F7BC011823B590052C02C /* ThreadSafeShared.h in Headers */, + A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */, + A7386554118697B400540279 /* SpecializedThunkJIT.h in Headers */, + A7386556118697B400540279 /* ThunkGenerators.h in Headers */, + 869D04AF1193B54D00803475 /* CachedTranscendentalFunction.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2536,6 +2577,9 @@ 868BFA0E117CEFD100B908B1 /* StringImpl.cpp in Sources */, 868BFA17117CF19900B908B1 /* WTFString.cpp in Sources */, 86B99AB8117E391E00DF5A90 /* RopeImpl.cpp in Sources */, + 511FC4C9117EE28700425272 /* MD5.cpp in Sources */, + A7386555118697B400540279 /* ThunkGenerators.cpp in Sources */, + A75706DE118A2BCF0057F88F /* JITArithmetic32_64.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/JavaScriptCore/assembler/ARMAssembler.cpp b/JavaScriptCore/assembler/ARMAssembler.cpp index 7393aa1..a181b7e 100644 --- a/JavaScriptCore/assembler/ARMAssembler.cpp +++ b/JavaScriptCore/assembler/ARMAssembler.cpp @@ -357,7 +357,7 @@ void* ARMAssembler::executableCopy(ExecutablePool* allocator) int pos = (*iter) & (~0x1); ARMWord* ldrAddr = reinterpret_cast<ARMWord*>(data + pos); ARMWord* addr = getLdrImmAddress(ldrAddr); - if (*addr != 0xffffffff) { + if (*addr != InvalidBranchTarget) { if (!(*iter & 1)) { int diff = reinterpret_cast<ARMWord*>(data + *addr) - (ldrAddr + DefaultPrefetching); diff --git a/JavaScriptCore/assembler/ARMAssembler.h b/JavaScriptCore/assembler/ARMAssembler.h index f93db68..2ca0949 100644 --- a/JavaScriptCore/assembler/ARMAssembler.h +++ b/JavaScriptCore/assembler/ARMAssembler.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 University of Szeged + * Copyright (C) 2009, 2010 University of Szeged * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -123,6 +123,7 @@ namespace JSC { FSUBD = 0x0e300b40, FMULD = 0x0e200b00, FCMPD = 0x0eb40b40, + FSQRTD = 0x0eb10bc0, DTR = 0x05000000, LDRH = 0x00100090, STRH = 0x00000090, @@ -131,6 +132,9 @@ namespace JSC { FDTR = 0x0d000b00, B = 0x0a000000, BL = 0x0b000000, +#if WTF_ARM_ARCH_AT_LEAST(5) || defined(__ARM_ARCH_4T__) + BX = 0x012fff10, +#endif FMSR = 0x0e000a10, FMRS = 0x0e100a10, FSITOD = 0x0eb80bc0, @@ -139,6 +143,7 @@ namespace JSC { #if WTF_ARM_ARCH_AT_LEAST(5) CLZ = 0x016f0f10, BKPT = 0xe120070, + BLX = 0x012fff30, #endif #if WTF_ARM_ARCH_AT_LEAST(7) MOVW = 0x03000000, @@ -182,6 +187,7 @@ namespace JSC { }; static const ARMWord INVALID_IMM = 0xf0000000; + static const ARMWord InvalidBranchTarget = 0xffffffff; static const int DefaultPrefetching = 2; class JmpSrc { @@ -421,6 +427,11 @@ namespace JSC { emitInst(static_cast<ARMWord>(cc) | FCMPD, dd, 0, dm); } + void fsqrtd_r(int dd, int dm, Condition cc = AL) + { + emitInst(static_cast<ARMWord>(cc) | FSQRTD, dd, 0, dm); + } + void ldr_imm(int rd, ARMWord imm, Condition cc = AL) { m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | DTR | DT_LOAD | DT_UP | RN(ARMRegisters::pc) | RD(rd), imm, true); @@ -547,6 +558,30 @@ namespace JSC { #endif } + void bx(int rm, Condition cc = AL) + { +#if WTF_ARM_ARCH_AT_LEAST(5) || defined(__ARM_ARCH_4T__) + emitInst(static_cast<ARMWord>(cc) | BX, 0, 0, RM(rm)); +#else + mov_r(ARMRegisters::pc, RM(rm), cc); +#endif + } + + JmpSrc blx(int rm, Condition cc = AL) + { +#if WTF_ARM_ARCH_AT_LEAST(5) + int s = m_buffer.uncheckedSize(); + emitInst(static_cast<ARMWord>(cc) | BLX, 0, 0, RM(rm)); +#else + ASSERT(rm != 14); + ensureSpace(2 * sizeof(ARMWord), 0); + mov_r(ARMRegisters::lr, ARMRegisters::pc, cc); + int s = m_buffer.uncheckedSize(); + bx(rm, cc); +#endif + return JmpSrc(s); + } + static ARMWord lsl(int reg, ARMWord value) { ASSERT(reg <= ARMRegisters::pc); @@ -619,21 +654,34 @@ namespace JSC { return label(); } - JmpSrc jmp(Condition cc = AL, int useConstantPool = 0) + JmpSrc loadBranchTarget(int rd, Condition cc = AL, int useConstantPool = 0) { ensureSpace(sizeof(ARMWord), sizeof(ARMWord)); int s = m_buffer.uncheckedSize(); - ldr_un_imm(ARMRegisters::pc, 0xffffffff, cc); + ldr_un_imm(rd, InvalidBranchTarget, cc); m_jumps.append(s | (useConstantPool & 0x1)); return JmpSrc(s); } + JmpSrc jmp(Condition cc = AL, int useConstantPool = 0) + { + return loadBranchTarget(ARMRegisters::pc, cc, useConstantPool); + } + void* executableCopy(ExecutablePool* allocator); // Patching helpers static ARMWord* getLdrImmAddress(ARMWord* insn) { +#if WTF_ARM_ARCH_AT_LEAST(5) + // Check for call + if ((*insn & 0x0f7f0000) != 0x051f0000) { + // Must be BLX + ASSERT((*insn & 0x012fff30) == 0x012fff30); + insn--; + } +#endif // Must be an ldr ..., [pc +/- imm] ASSERT((*insn & 0x0f7f0000) == 0x051f0000); diff --git a/JavaScriptCore/assembler/AbstractMacroAssembler.h b/JavaScriptCore/assembler/AbstractMacroAssembler.h index f96e34a..1c7f269 100644 --- a/JavaScriptCore/assembler/AbstractMacroAssembler.h +++ b/JavaScriptCore/assembler/AbstractMacroAssembler.h @@ -160,7 +160,7 @@ public: // in a class requiring explicit construction in order to differentiate // from pointers used as absolute addresses to memory operations struct ImmPtr { - explicit ImmPtr(void* value) + explicit ImmPtr(const void* value) : m_value(value) { } @@ -170,7 +170,7 @@ public: return reinterpret_cast<intptr_t>(m_value); } - void* m_value; + const void* m_value; }; // Imm32: diff --git a/JavaScriptCore/assembler/MacroAssemblerARM.h b/JavaScriptCore/assembler/MacroAssemblerARM.h index 52c4fa2..40d2e4a 100644 --- a/JavaScriptCore/assembler/MacroAssemblerARM.h +++ b/JavaScriptCore/assembler/MacroAssemblerARM.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 Apple Inc. - * Copyright (C) 2009 University of Szeged + * Copyright (C) 2009, 2010 University of Szeged * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -178,6 +178,20 @@ public: { m_assembler.movs_r(dest, m_assembler.asr(dest, imm.m_value & 0x1f)); } + + void urshift32(RegisterID shift_amount, RegisterID dest) + { + ARMWord w = ARMAssembler::getOp2(0x1f); + ASSERT(w != ARMAssembler::INVALID_IMM); + m_assembler.and_r(ARMRegisters::S0, shift_amount, w); + + m_assembler.movs_r(dest, m_assembler.lsr_r(dest, ARMRegisters::S0)); + } + + void urshift32(Imm32 imm, RegisterID dest) + { + m_assembler.movs_r(dest, m_assembler.lsr(dest, imm.m_value & 0x1f)); + } void sub32(RegisterID src, RegisterID dest) { @@ -259,6 +273,14 @@ public: else m_assembler.ldrh_d(dest, ARMRegisters::S0, ARMAssembler::getOp2Byte(-address.offset)); } + + void load16(ImplicitAddress address, RegisterID dest) + { + if (address.offset >= 0) + m_assembler.ldrh_u(dest, address.base, ARMAssembler::getOp2Byte(address.offset)); + else + m_assembler.ldrh_d(dest, address.base, ARMAssembler::getOp2Byte(-address.offset)); + } DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address) { @@ -474,7 +496,7 @@ public: void jump(RegisterID target) { - move(target, ARMRegisters::pc); + m_assembler.bx(target); } void jump(Address address) @@ -566,14 +588,19 @@ public: Call nearCall() { +#if WTF_ARM_ARCH_AT_LEAST(5) + ensureSpace(2 * sizeof(ARMWord), sizeof(ARMWord)); + m_assembler.loadBranchTarget(ARMRegisters::S1, ARMAssembler::AL, true); + return Call(m_assembler.blx(ARMRegisters::S1), Call::LinkableNear); +#else prepareCall(); return Call(m_assembler.jmp(ARMAssembler::AL, true), Call::LinkableNear); +#endif } Call call(RegisterID target) { - prepareCall(); - move(ARMRegisters::pc, target); + m_assembler.blx(target); JmpSrc jmpSrc; return Call(jmpSrc, Call::None); } @@ -585,7 +612,7 @@ public: void ret() { - m_assembler.mov_r(ARMRegisters::pc, linkRegister); + m_assembler.bx(linkRegister); } void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest) @@ -681,8 +708,14 @@ public: Call call() { +#if WTF_ARM_ARCH_AT_LEAST(5) + ensureSpace(2 * sizeof(ARMWord), sizeof(ARMWord)); + m_assembler.loadBranchTarget(ARMRegisters::S1, ARMAssembler::AL, true); + return Call(m_assembler.blx(ARMRegisters::S1), Call::Linkable); +#else prepareCall(); return Call(m_assembler.jmp(ARMAssembler::AL, true), Call::Linkable); +#endif } Call tailRecursiveCall() @@ -740,12 +773,17 @@ public: return false; } + bool supportsFloatingPointSqrt() const + { + return s_isVFPPresent; + } + void loadDouble(ImplicitAddress address, FPRegisterID dest) { m_assembler.doubleTransfer(true, dest, address.base, address.offset); } - void loadDouble(void* address, FPRegisterID dest) + void loadDouble(const void* address, FPRegisterID dest) { m_assembler.ldr_un_imm(ARMRegisters::S0, (ARMWord)address); m_assembler.fdtr_u(true, dest, ARMRegisters::S0, 0); @@ -801,6 +839,11 @@ public: mulDouble(ARMRegisters::SD0, dest); } + void sqrtDouble(FPRegisterID src, FPRegisterID dest) + { + m_assembler.fsqrtd_r(dest, src); + } + void convertInt32ToDouble(RegisterID src, FPRegisterID dest) { m_assembler.fmsr_r(dest, src); @@ -886,44 +929,56 @@ protected: void prepareCall() { +#if WTF_ARM_ARCH_VERSION < 5 ensureSpace(2 * sizeof(ARMWord), sizeof(ARMWord)); m_assembler.mov_r(linkRegister, ARMRegisters::pc); +#endif } void call32(RegisterID base, int32_t offset) { +#if WTF_ARM_ARCH_AT_LEAST(5) + int targetReg = ARMRegisters::S1; +#else + int targetReg = ARMRegisters::pc; +#endif + int tmpReg = ARMRegisters::S1; + if (base == ARMRegisters::sp) offset += 4; if (offset >= 0) { if (offset <= 0xfff) { prepareCall(); - m_assembler.dtr_u(true, ARMRegisters::pc, base, offset); + m_assembler.dtr_u(true, targetReg, base, offset); } else if (offset <= 0xfffff) { - m_assembler.add_r(ARMRegisters::S0, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8)); + m_assembler.add_r(tmpReg, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8)); prepareCall(); - m_assembler.dtr_u(true, ARMRegisters::pc, ARMRegisters::S0, offset & 0xfff); + m_assembler.dtr_u(true, targetReg, tmpReg, offset & 0xfff); } else { - ARMWord reg = m_assembler.getImm(offset, ARMRegisters::S0); + ARMWord reg = m_assembler.getImm(offset, tmpReg); prepareCall(); - m_assembler.dtr_ur(true, ARMRegisters::pc, base, reg); + m_assembler.dtr_ur(true, targetReg, base, reg); } } else { offset = -offset; if (offset <= 0xfff) { prepareCall(); - m_assembler.dtr_d(true, ARMRegisters::pc, base, offset); + m_assembler.dtr_d(true, targetReg, base, offset); } else if (offset <= 0xfffff) { - m_assembler.sub_r(ARMRegisters::S0, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8)); + m_assembler.sub_r(tmpReg, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8)); prepareCall(); - m_assembler.dtr_d(true, ARMRegisters::pc, ARMRegisters::S0, offset & 0xfff); + m_assembler.dtr_d(true, targetReg, tmpReg, offset & 0xfff); } else { - ARMWord reg = m_assembler.getImm(offset, ARMRegisters::S0); + ARMWord reg = m_assembler.getImm(offset, tmpReg); prepareCall(); - m_assembler.dtr_dr(true, ARMRegisters::pc, base, reg); + m_assembler.dtr_dr(true, targetReg, base, reg); } } +#if WTF_ARM_ARCH_AT_LEAST(5) + m_assembler.blx(targetReg); +#endif } private: diff --git a/JavaScriptCore/assembler/MacroAssemblerARMv7.h b/JavaScriptCore/assembler/MacroAssemblerARMv7.h index 3d08f0e..31a68d9 100644 --- a/JavaScriptCore/assembler/MacroAssemblerARMv7.h +++ b/JavaScriptCore/assembler/MacroAssemblerARMv7.h @@ -257,6 +257,21 @@ public: { m_assembler.asr(dest, dest, imm.m_value & 0x1f); } + + void urshift32(RegisterID shift_amount, RegisterID dest) + { + // Clamp the shift to the range 0..31 + ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f); + ASSERT(armImm.isValid()); + m_assembler.ARM_and(dataTempRegister, shift_amount, armImm); + + m_assembler.lsr(dest, dest, dataTempRegister); + } + + void urshift32(Imm32 imm, RegisterID dest) + { + m_assembler.lsr(dest, dest, imm.m_value & 0x1f); + } void sub32(RegisterID src, RegisterID dest) { @@ -441,6 +456,11 @@ public: { m_assembler.ldrh(dest, makeBaseIndexBase(address), address.index, address.scale); } + + void load16(ImplicitAddress address, RegisterID dest) + { + m_assembler.ldrh(dest, address.base, address.offset); + } DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address) { @@ -494,6 +514,11 @@ public: // In short, FIXME:. bool supportsFloatingPointTruncate() const { return false; } + bool supportsFloatingPointSqrt() const + { + return false; + } + void loadDouble(ImplicitAddress address, FPRegisterID dest) { RegisterID base = address.base; @@ -557,6 +582,11 @@ public: mulDouble(fpTempRegister, dest); } + void sqrtDouble(FPRegisterID, FPRegisterID) + { + ASSERT_NOT_REACHED(); + } + void convertInt32ToDouble(RegisterID src, FPRegisterID dest) { m_assembler.vmov(fpTempRegister, src); diff --git a/JavaScriptCore/assembler/MacroAssemblerX86.h b/JavaScriptCore/assembler/MacroAssemblerX86.h index 0366541..0918996 100644 --- a/JavaScriptCore/assembler/MacroAssemblerX86.h +++ b/JavaScriptCore/assembler/MacroAssemblerX86.h @@ -87,7 +87,7 @@ public: m_assembler.movl_mr(address, dest); } - void loadDouble(void* address, FPRegisterID dest) + void loadDouble(const void* address, FPRegisterID dest) { ASSERT(isSSE2Present()); m_assembler.movsd_mr(address, dest); @@ -172,6 +172,7 @@ public: bool supportsFloatingPoint() const { return m_isSSE2Present; } // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate() bool supportsFloatingPointTruncate() const { return m_isSSE2Present; } + bool supportsFloatingPointSqrt() const { return m_isSSE2Present; } private: const bool m_isSSE2Present; diff --git a/JavaScriptCore/assembler/MacroAssemblerX86Common.h b/JavaScriptCore/assembler/MacroAssemblerX86Common.h index 27c2f15..7296193 100644 --- a/JavaScriptCore/assembler/MacroAssemblerX86Common.h +++ b/JavaScriptCore/assembler/MacroAssemblerX86Common.h @@ -249,6 +249,33 @@ public: { m_assembler.sarl_i8r(imm.m_value, dest); } + + void urshift32(RegisterID shift_amount, RegisterID dest) + { + // On x86 we can only shift by ecx; if asked to shift by another register we'll + // need rejig the shift amount into ecx first, and restore the registers afterwards. + if (shift_amount != X86Registers::ecx) { + swap(shift_amount, X86Registers::ecx); + + // E.g. transform "shrl %eax, %eax" -> "xchgl %eax, %ecx; shrl %ecx, %ecx; xchgl %eax, %ecx" + if (dest == shift_amount) + m_assembler.shrl_CLr(X86Registers::ecx); + // E.g. transform "shrl %eax, %ecx" -> "xchgl %eax, %ecx; shrl %ecx, %eax; xchgl %eax, %ecx" + else if (dest == X86Registers::ecx) + m_assembler.shrl_CLr(shift_amount); + // E.g. transform "shrl %eax, %ebx" -> "xchgl %eax, %ecx; shrl %ecx, %ebx; xchgl %eax, %ecx" + else + m_assembler.shrl_CLr(dest); + + swap(shift_amount, X86Registers::ecx); + } else + m_assembler.shrl_CLr(dest); + } + + void urshift32(Imm32 imm, RegisterID dest) + { + m_assembler.shrl_i8r(imm.m_value, dest); + } void sub32(RegisterID src, RegisterID dest) { @@ -301,6 +328,10 @@ public: m_assembler.xorl_mr(src.offset, src.base, dest); } + void sqrtDouble(FPRegisterID src, FPRegisterID dst) + { + m_assembler.sqrtsd_rr(src, dst); + } // Memory access operations: // @@ -334,6 +365,11 @@ public: { m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest); } + + void load16(Address address, RegisterID dest) + { + m_assembler.movzwl_mr(address.offset, address.base, dest); + } DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address) { diff --git a/JavaScriptCore/assembler/MacroAssemblerX86_64.h b/JavaScriptCore/assembler/MacroAssemblerX86_64.h index 339eaa4..168c93f 100644 --- a/JavaScriptCore/assembler/MacroAssemblerX86_64.h +++ b/JavaScriptCore/assembler/MacroAssemblerX86_64.h @@ -86,7 +86,7 @@ public: } } - void loadDouble(void* address, FPRegisterID dest) + void loadDouble(const void* address, FPRegisterID dest) { move(ImmPtr(address), scratchRegister); loadDouble(scratchRegister, dest); @@ -427,6 +427,7 @@ public: bool supportsFloatingPoint() const { return true; } // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate() bool supportsFloatingPointTruncate() const { return true; } + bool supportsFloatingPointSqrt() const { return true; } private: friend class LinkBuffer; diff --git a/JavaScriptCore/assembler/X86Assembler.h b/JavaScriptCore/assembler/X86Assembler.h index 14a02f7..20d72f5 100644 --- a/JavaScriptCore/assembler/X86Assembler.h +++ b/JavaScriptCore/assembler/X86Assembler.h @@ -167,6 +167,7 @@ private: OP2_MULSD_VsdWsd = 0x59, OP2_SUBSD_VsdWsd = 0x5C, OP2_DIVSD_VsdWsd = 0x5E, + OP2_SQRTSD_VsdWsd = 0x51, OP2_XORPD_VpdWpd = 0x57, OP2_MOVD_VdEd = 0x6E, OP2_MOVD_EdVd = 0x7E, @@ -200,6 +201,7 @@ private: GROUP1A_OP_POP = 0, GROUP2_OP_SHL = 4, + GROUP2_OP_SHR = 5, GROUP2_OP_SAR = 7, GROUP3_OP_TEST = 0, @@ -672,6 +674,21 @@ public: { m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst); } + + void shrl_i8r(int imm, RegisterID dst) + { + if (imm == 1) + m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SHR, dst); + else { + m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SHR, dst); + m_formatter.immediate8(imm); + } + } + + void shrl_CLr(RegisterID dst) + { + m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHR, dst); + } void shll_i8r(int imm, RegisterID dst) { @@ -1393,7 +1410,7 @@ public: } #if !CPU(X86_64) - void movsd_mr(void* address, XMMRegisterID dst) + void movsd_mr(const void* address, XMMRegisterID dst) { m_formatter.prefix(PRE_SSE_F2); m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, address); @@ -1461,6 +1478,12 @@ public: m_formatter.twoByteOp(OP2_XORPD_VpdWpd, (RegisterID)dst, (RegisterID)src); } + void sqrtsd_rr(XMMRegisterID src, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F2); + m_formatter.twoByteOp(OP2_SQRTSD_VsdWsd, (RegisterID)dst, (RegisterID)src); + } + // Misc instructions: void int3() @@ -1746,7 +1769,7 @@ private: } #if !CPU(X86_64) - void twoByteOp(TwoByteOpcodeID opcode, int reg, void* address) + void twoByteOp(TwoByteOpcodeID opcode, int reg, const void* address) { m_buffer.ensureSpace(maxInstructionSize); m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); @@ -2057,7 +2080,7 @@ private: } #if !CPU(X86_64) - void memoryModRM(int reg, void* address) + void memoryModRM(int reg, const void* address) { // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32! putModRm(ModRmMemoryNoDisp, reg, noBase); diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp index 8e77e12..d56d328 100644 --- a/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/JavaScriptCore/bytecode/CodeBlock.cpp @@ -931,6 +931,13 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& printf("[%4d] jless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); break; } + case op_jlesseq: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int offset = (++it)->u.operand; + printf("[%4d] jlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + break; + } case op_loop_if_lesseq: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; @@ -1366,12 +1373,12 @@ void CodeBlock::derefStructures(Instruction* vPC) const vPC[4].u.structure->deref(); return; } - if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto)) { + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto)) { vPC[4].u.structure->deref(); vPC[5].u.structure->deref(); return; } - if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain)) { + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) { vPC[4].u.structure->deref(); vPC[5].u.structureChain->deref(); return; @@ -1394,7 +1401,9 @@ void CodeBlock::derefStructures(Instruction* vPC) const if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list)) || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list)) || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto_list)) - || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self_list))) { + || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self_list)) + || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto_list)) + || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self_list))) { PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures; polymorphicStructures->derefStructures(vPC[5].u.operand); delete polymorphicStructures; @@ -1413,12 +1422,12 @@ void CodeBlock::refStructures(Instruction* vPC) const vPC[4].u.structure->ref(); return; } - if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto)) { + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto)) { vPC[4].u.structure->ref(); vPC[5].u.structure->ref(); return; } - if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain)) { + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) { vPC[4].u.structure->ref(); vPC[5].u.structureChain->ref(); return; diff --git a/JavaScriptCore/bytecode/Opcode.h b/JavaScriptCore/bytecode/Opcode.h index 0a7f3fa..b5a8c2d 100644 --- a/JavaScriptCore/bytecode/Opcode.h +++ b/JavaScriptCore/bytecode/Opcode.h @@ -138,6 +138,7 @@ namespace JSC { macro(op_jnless, 4) \ macro(op_jnlesseq, 4) \ macro(op_jless, 4) \ + macro(op_jlesseq, 4) \ macro(op_jmp_scopes, 3) \ macro(op_loop, 2) \ macro(op_loop_if_true, 3) \ diff --git a/JavaScriptCore/bytecode/SamplingTool.cpp b/JavaScriptCore/bytecode/SamplingTool.cpp index 8522e45..7191e38 100644 --- a/JavaScriptCore/bytecode/SamplingTool.cpp +++ b/JavaScriptCore/bytecode/SamplingTool.cpp @@ -43,7 +43,7 @@ namespace JSC { void SamplingFlags::sample() { - uint32_t mask = 1 << 31; + uint32_t mask = static_cast<uint32_t>(1 << 31); unsigned index; for (index = 0; index < 32; ++index) { diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index aa5c5f9..db79d67 100644 --- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -635,7 +635,7 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar instructions().append(target->bind(begin, instructions().size())); return target; } - } else if (m_lastOpcodeID == op_lesseq && !target->isForward()) { + } else if (m_lastOpcodeID == op_lesseq) { int dstIndex; int src1Index; int src2Index; @@ -646,7 +646,7 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar rewindBinaryOp(); size_t begin = instructions().size(); - emitOpcode(op_loop_if_lesseq); + emitOpcode(target->isForward() ? op_jlesseq : op_loop_if_lesseq); instructions().append(src1Index); instructions().append(src2Index); instructions().append(target->bind(begin, instructions().size())); @@ -1631,8 +1631,13 @@ void BytecodeGenerator::emitPopScope() void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine) { +#if ENABLE(DEBUG_WITH_BREAKPOINT) + if (debugHookID != DidReachBreakpoint) + return; +#else if (!m_shouldEmitDebugHooks) return; +#endif emitOpcode(op_debug); instructions().append(debugHookID); instructions().append(firstLine); diff --git a/JavaScriptCore/config.h b/JavaScriptCore/config.h index 791564a..9810885 100644 --- a/JavaScriptCore/config.h +++ b/JavaScriptCore/config.h @@ -44,7 +44,7 @@ #define max max #define min min -#if !COMPILER(MSVC7) && !OS(WINCE) +#if !COMPILER(MSVC7_OR_LOWER) && !OS(WINCE) // We need to define this before the first #include of stdlib.h or it won't contain rand_s. #ifndef _CRT_RAND_S #define _CRT_RAND_S diff --git a/JavaScriptCore/create_hash_table b/JavaScriptCore/create_hash_table index 77463fb..6078f97 100755 --- a/JavaScriptCore/create_hash_table +++ b/JavaScriptCore/create_hash_table @@ -247,6 +247,11 @@ sub output() { print "\nnamespace JSC {\n"; } my $count = scalar @keys + 1; + print "#if ENABLE(JIT)\n"; + print "#define THUNK_GENERATOR(generator) , generator\n"; + print "#else\n"; + print "#define THUNK_GENERATOR(generator)\n"; + print "#endif\n"; print "\nstatic const struct HashTableValue ${nameEntries}\[$count\] = {\n"; my $i = 0; foreach my $key (@keys) { @@ -266,11 +271,25 @@ sub output() { $firstValue = $values[$i]{"value"}; $secondValue = "0"; } - print " { \"$key\", $attrs[$i], (intptr_t)" . $castStr . "($firstValue), (intptr_t)$secondValue },\n"; + my $thunkGenerator = "0"; + if ($key eq "charCodeAt") { + $thunkGenerator = "charCodeAtThunkGenerator"; + } + if ($key eq "charAt") { + $thunkGenerator = "charAtThunkGenerator"; + } + if ($key eq "sqrt") { + $thunkGenerator = "sqrtThunkGenerator"; + } + if ($key eq "pow") { + $thunkGenerator = "powThunkGenerator"; + } + print " { \"$key\", $attrs[$i], (intptr_t)" . $castStr . "($firstValue), (intptr_t)$secondValue THUNK_GENERATOR($thunkGenerator) },\n"; $i++; } - print " { 0, 0, 0, 0 }\n"; + print " { 0, 0, 0, 0 THUNK_GENERATOR(0) }\n"; print "};\n\n"; + print "#undef THUNK_GENERATOR\n"; print "extern JSC_CONST_HASHTABLE HashTable $name =\n"; print " \{ $compactSize, $compactHashSizeMask, $nameEntries, 0 \};\n"; print "} // namespace\n"; diff --git a/JavaScriptCore/debugger/DebuggerCallFrame.cpp b/JavaScriptCore/debugger/DebuggerCallFrame.cpp index 05a385d..a734b1d 100644 --- a/JavaScriptCore/debugger/DebuggerCallFrame.cpp +++ b/JavaScriptCore/debugger/DebuggerCallFrame.cpp @@ -41,6 +41,9 @@ const UString* DebuggerCallFrame::functionName() const if (!m_callFrame->codeBlock()) return 0; + if (!m_callFrame->callee()) + return 0; + JSFunction* function = asFunction(m_callFrame->callee()); if (!function) return 0; @@ -51,7 +54,10 @@ UString DebuggerCallFrame::calculatedFunctionName() const { if (!m_callFrame->codeBlock()) return UString(); - + + if (!m_callFrame->callee()) + return UString(); + JSFunction* function = asFunction(m_callFrame->callee()); if (!function) return UString(); diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp index 40f6458..e53f236 100644 --- a/JavaScriptCore/interpreter/Interpreter.cpp +++ b/JavaScriptCore/interpreter/Interpreter.cpp @@ -3211,6 +3211,29 @@ skip_id_custom_self: vPC += OPCODE_LENGTH(op_jnlesseq); NEXT_INSTRUCTION(); } + DEFINE_OPCODE(op_jlesseq) { + /* jlesseq src1(r) src2(r) target(offset) + + Checks whether register src1 is less than or equal to + register src2, as with the ECMAScript '<=' operator, + and then jumps to offset target from the current instruction, + if and only if the result of the comparison is true. + */ + JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue(); + int target = vPC[3].u.operand; + + bool result = jsLessEq(callFrame, src1, src2); + CHECK_FOR_EXCEPTION(); + + if (result) { + vPC += target; + NEXT_INSTRUCTION(); + } + + vPC += OPCODE_LENGTH(op_jlesseq); + NEXT_INSTRUCTION(); + } DEFINE_OPCODE(op_switch_imm) { /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r) diff --git a/JavaScriptCore/interpreter/RegisterFile.cpp b/JavaScriptCore/interpreter/RegisterFile.cpp index 510effe..63ea5b3 100644 --- a/JavaScriptCore/interpreter/RegisterFile.cpp +++ b/JavaScriptCore/interpreter/RegisterFile.cpp @@ -29,6 +29,8 @@ #include "config.h" #include "RegisterFile.h" +#include "JSGlobalObject.h" + namespace JSC { RegisterFile::~RegisterFile() @@ -56,4 +58,19 @@ void RegisterFile::releaseExcessCapacity() m_maxUsed = m_start; } +void RegisterFile::setGlobalObject(JSGlobalObject* globalObject) +{ + m_globalObject = globalObject; +} + +bool RegisterFile::clearGlobalObject(JSGlobalObject* globalObject) +{ + return m_globalObject.clear(globalObject); +} + +JSGlobalObject* RegisterFile::globalObject() +{ + return m_globalObject.get(); +} + } // namespace JSC diff --git a/JavaScriptCore/interpreter/RegisterFile.h b/JavaScriptCore/interpreter/RegisterFile.h index 1fc4f82..def9e25 100644 --- a/JavaScriptCore/interpreter/RegisterFile.h +++ b/JavaScriptCore/interpreter/RegisterFile.h @@ -32,6 +32,7 @@ #include "Collector.h" #include "ExecutableAllocator.h" #include "Register.h" +#include "WeakGCPtr.h" #include <stdio.h> #include <wtf/Noncopyable.h> #include <wtf/VMTags.h> @@ -124,8 +125,9 @@ namespace JSC { Register* end() const { return m_end; } size_t size() const { return m_end - m_start; } - void setGlobalObject(JSGlobalObject* globalObject) { m_globalObject = globalObject; } - JSGlobalObject* globalObject() { return m_globalObject; } + void setGlobalObject(JSGlobalObject*); + bool clearGlobalObject(JSGlobalObject*); + JSGlobalObject* globalObject(); bool grow(Register* newEnd); void shrink(Register* newEnd); @@ -153,7 +155,7 @@ namespace JSC { Register* m_commitEnd; #endif - JSGlobalObject* m_globalObject; // The global object whose vars are currently stored in the register file. + WeakGCPtr<JSGlobalObject> m_globalObject; // The global object whose vars are currently stored in the register file. }; // FIXME: Add a generic getpagesize() to WTF, then move this function to WTF as well. @@ -166,7 +168,6 @@ namespace JSC { , m_end(0) , m_max(0) , m_buffer(0) - , m_globalObject(0) { // Verify that our values will play nice with mmap and VirtualAlloc. ASSERT(isPageAligned(maxGlobals)); diff --git a/JavaScriptCore/jit/ExecutableAllocator.h b/JavaScriptCore/jit/ExecutableAllocator.h index 8f46dee..610b788 100644 --- a/JavaScriptCore/jit/ExecutableAllocator.h +++ b/JavaScriptCore/jit/ExecutableAllocator.h @@ -247,7 +247,9 @@ public: { User::IMB_Range(code, static_cast<char*>(code) + size); } -#elif CPU(ARM_TRADITIONAL) && OS(LINUX) +#elif CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(RVCT) + static __asm void cacheFlush(void* code, size_t size); +#elif CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(GCC) static void cacheFlush(void* code, size_t size) { asm volatile ( diff --git a/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp b/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp index 06375ad..eee8a7e 100644 --- a/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp +++ b/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp @@ -80,6 +80,21 @@ void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSe } #endif +#if CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(RVCT) +__asm void ExecutableAllocator::cacheFlush(void* code, size_t size) +{ + ARM + push {r7} + add r1, r1, r0 + mov r7, #0xf0000 + add r7, r7, #0x2 + mov r2, #0x0 + svc #0x0 + pop {r7} + bx lr +} +#endif + } #endif // HAVE(ASSEMBLER) diff --git a/JavaScriptCore/jit/JIT.cpp b/JavaScriptCore/jit/JIT.cpp index ec23d8c..f7b06a0 100644 --- a/JavaScriptCore/jit/JIT.cpp +++ b/JavaScriptCore/jit/JIT.cpp @@ -200,7 +200,6 @@ void JIT::privateCompileMainPass() DEFINE_BINARY_OP(op_in) DEFINE_BINARY_OP(op_less) DEFINE_BINARY_OP(op_lesseq) - DEFINE_BINARY_OP(op_urshift) DEFINE_UNARY_OP(op_is_boolean) DEFINE_UNARY_OP(op_is_function) DEFINE_UNARY_OP(op_is_number) @@ -251,6 +250,7 @@ void JIT::privateCompileMainPass() DEFINE_OP(op_jneq_ptr) DEFINE_OP(op_jnless) DEFINE_OP(op_jless) + DEFINE_OP(op_jlesseq) DEFINE_OP(op_jnlesseq) DEFINE_OP(op_jsr) DEFINE_OP(op_jtrue) @@ -301,6 +301,7 @@ void JIT::privateCompileMainPass() DEFINE_OP(op_resolve_with_base) DEFINE_OP(op_ret) DEFINE_OP(op_rshift) + DEFINE_OP(op_urshift) DEFINE_OP(op_sret) DEFINE_OP(op_strcat) DEFINE_OP(op_stricteq) @@ -401,6 +402,7 @@ void JIT::privateCompileSlowCases() DEFINE_SLOWCASE_OP(op_jfalse) DEFINE_SLOWCASE_OP(op_jnless) DEFINE_SLOWCASE_OP(op_jless) + DEFINE_SLOWCASE_OP(op_jlesseq) DEFINE_SLOWCASE_OP(op_jnlesseq) DEFINE_SLOWCASE_OP(op_jtrue) DEFINE_SLOWCASE_OP(op_loop_if_less) @@ -427,6 +429,7 @@ void JIT::privateCompileSlowCases() DEFINE_SLOWCASE_OP(op_resolve_global) #endif DEFINE_SLOWCASE_OP(op_rshift) + DEFINE_SLOWCASE_OP(op_urshift) DEFINE_SLOWCASE_OP(op_stricteq) DEFINE_SLOWCASE_OP(op_sub) DEFINE_SLOWCASE_OP(op_to_jsnumber) diff --git a/JavaScriptCore/jit/JIT.h b/JavaScriptCore/jit/JIT.h index e757112..a7e8890 100644 --- a/JavaScriptCore/jit/JIT.h +++ b/JavaScriptCore/jit/JIT.h @@ -40,15 +40,10 @@ #include "CodeBlock.h" #include "Interpreter.h" -#include "JITCode.h" -#include "JITStubs.h" +#include "JSInterfaceJIT.h" #include "Opcode.h" -#include "RegisterFile.h" -#include "MacroAssembler.h" #include "Profiler.h" #include <bytecode/SamplingTool.h> -#include <wtf/AlwaysInline.h> -#include <wtf/Vector.h> namespace JSC { @@ -170,128 +165,13 @@ namespace JSC { void ctiPatchCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, MacroAssemblerCodePtr newCalleeFunction); void ctiPatchCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, FunctionPtr newCalleeFunction); - class JIT : private MacroAssembler { + class JIT : private JSInterfaceJIT { friend class JITStubCall; using MacroAssembler::Jump; using MacroAssembler::JumpList; using MacroAssembler::Label; - // NOTES: - // - // regT0 has two special meanings. The return value from a stub - // call will always be in regT0, and by default (unless - // a register is specified) emitPutVirtualRegister() will store - // the value from regT0. - // - // regT3 is required to be callee-preserved. - // - // tempRegister2 is has no such dependencies. It is important that - // on x86/x86-64 it is ecx for performance reasons, since the - // MacroAssembler will need to plant register swaps if it is not - - // however the code will still function correctly. -#if CPU(X86_64) - static const RegisterID returnValueRegister = X86Registers::eax; - static const RegisterID cachedResultRegister = X86Registers::eax; - static const RegisterID firstArgumentRegister = X86Registers::edi; - - static const RegisterID timeoutCheckRegister = X86Registers::r12; - static const RegisterID callFrameRegister = X86Registers::r13; - static const RegisterID tagTypeNumberRegister = X86Registers::r14; - static const RegisterID tagMaskRegister = X86Registers::r15; - - static const RegisterID regT0 = X86Registers::eax; - static const RegisterID regT1 = X86Registers::edx; - static const RegisterID regT2 = X86Registers::ecx; - static const RegisterID regT3 = X86Registers::ebx; - - static const FPRegisterID fpRegT0 = X86Registers::xmm0; - static const FPRegisterID fpRegT1 = X86Registers::xmm1; - static const FPRegisterID fpRegT2 = X86Registers::xmm2; -#elif CPU(X86) - static const RegisterID returnValueRegister = X86Registers::eax; - static const RegisterID cachedResultRegister = X86Registers::eax; - // On x86 we always use fastcall conventions = but on - // OS X if might make more sense to just use regparm. - static const RegisterID firstArgumentRegister = X86Registers::ecx; - - static const RegisterID timeoutCheckRegister = X86Registers::esi; - static const RegisterID callFrameRegister = X86Registers::edi; - - static const RegisterID regT0 = X86Registers::eax; - static const RegisterID regT1 = X86Registers::edx; - static const RegisterID regT2 = X86Registers::ecx; - static const RegisterID regT3 = X86Registers::ebx; - - static const FPRegisterID fpRegT0 = X86Registers::xmm0; - static const FPRegisterID fpRegT1 = X86Registers::xmm1; - static const FPRegisterID fpRegT2 = X86Registers::xmm2; -#elif CPU(ARM_THUMB2) - static const RegisterID returnValueRegister = ARMRegisters::r0; - static const RegisterID cachedResultRegister = ARMRegisters::r0; - static const RegisterID firstArgumentRegister = ARMRegisters::r0; - - static const RegisterID regT0 = ARMRegisters::r0; - static const RegisterID regT1 = ARMRegisters::r1; - static const RegisterID regT2 = ARMRegisters::r2; - static const RegisterID regT3 = ARMRegisters::r4; - - static const RegisterID callFrameRegister = ARMRegisters::r5; - static const RegisterID timeoutCheckRegister = ARMRegisters::r6; - - static const FPRegisterID fpRegT0 = ARMRegisters::d0; - static const FPRegisterID fpRegT1 = ARMRegisters::d1; - static const FPRegisterID fpRegT2 = ARMRegisters::d2; -#elif CPU(ARM_TRADITIONAL) - static const RegisterID returnValueRegister = ARMRegisters::r0; - static const RegisterID cachedResultRegister = ARMRegisters::r0; - static const RegisterID firstArgumentRegister = ARMRegisters::r0; - - static const RegisterID timeoutCheckRegister = ARMRegisters::r5; - static const RegisterID callFrameRegister = ARMRegisters::r4; - - static const RegisterID regT0 = ARMRegisters::r0; - static const RegisterID regT1 = ARMRegisters::r1; - static const RegisterID regT2 = ARMRegisters::r2; - // Callee preserved - static const RegisterID regT3 = ARMRegisters::r7; - - static const RegisterID regS0 = ARMRegisters::S0; - // Callee preserved - static const RegisterID regS1 = ARMRegisters::S1; - - static const RegisterID regStackPtr = ARMRegisters::sp; - static const RegisterID regLink = ARMRegisters::lr; - - static const FPRegisterID fpRegT0 = ARMRegisters::d0; - static const FPRegisterID fpRegT1 = ARMRegisters::d1; - static const FPRegisterID fpRegT2 = ARMRegisters::d2; -#elif CPU(MIPS) - static const RegisterID returnValueRegister = MIPSRegisters::v0; - static const RegisterID cachedResultRegister = MIPSRegisters::v0; - static const RegisterID firstArgumentRegister = MIPSRegisters::a0; - - // regT0 must be v0 for returning a 32-bit value. - static const RegisterID regT0 = MIPSRegisters::v0; - - // regT1 must be v1 for returning a pair of 32-bit value. - static const RegisterID regT1 = MIPSRegisters::v1; - - static const RegisterID regT2 = MIPSRegisters::t4; - - // regT3 must be saved in the callee, so use an S register. - static const RegisterID regT3 = MIPSRegisters::s2; - - static const RegisterID callFrameRegister = MIPSRegisters::s0; - static const RegisterID timeoutCheckRegister = MIPSRegisters::s1; - - static const FPRegisterID fpRegT0 = MIPSRegisters::f4; - static const FPRegisterID fpRegT1 = MIPSRegisters::f6; - static const FPRegisterID fpRegT2 = MIPSRegisters::f8; -#else - #error "JIT not supported on this platform." -#endif - static const int patchGetByIdDefaultStructure = -1; // Magic number - initial offset cannot be representable as a signed 8bit value, or the X86Assembler // will compress the displacement, and we may not be able to fit a patched offset. @@ -405,14 +285,9 @@ namespace JSC { void emitLoadDouble(unsigned index, FPRegisterID value); void emitLoadInt32ToDouble(unsigned index, FPRegisterID value); - Address addressFor(unsigned index, RegisterID base = callFrameRegister); - void testPrototype(Structure*, JumpList& failureCases); #if USE(JSVALUE32_64) - Address tagFor(unsigned index, RegisterID base = callFrameRegister); - Address payloadFor(unsigned index, RegisterID base = callFrameRegister); - bool getOperandConstantImmediateInt(unsigned op1, unsigned op2, unsigned& op, int32_t& constant); void emitLoadTag(unsigned index, RegisterID tag); @@ -549,8 +424,6 @@ namespace JSC { void emitJumpSlowCaseIfNotJSCell(RegisterID); void emitJumpSlowCaseIfNotJSCell(RegisterID, int VReg); #if USE(JSVALUE64) - JIT::Jump emitJumpIfImmediateNumber(RegisterID); - JIT::Jump emitJumpIfNotImmediateNumber(RegisterID); #else JIT::Jump emitJumpIfImmediateNumber(RegisterID reg) { @@ -799,6 +672,7 @@ namespace JSC { void emit_op_jneq_ptr(Instruction*); void emit_op_jnless(Instruction*); void emit_op_jless(Instruction*); + void emit_op_jlesseq(Instruction*, bool invert = false); void emit_op_jnlesseq(Instruction*); void emit_op_jsr(Instruction*); void emit_op_jtrue(Instruction*); @@ -861,6 +735,7 @@ namespace JSC { void emit_op_to_jsnumber(Instruction*); void emit_op_to_primitive(Instruction*); void emit_op_unexpected_load(Instruction*); + void emit_op_urshift(Instruction*); #if ENABLE(JIT_OPTIMIZE_MOD) void softModulo(); #endif @@ -885,6 +760,7 @@ namespace JSC { void emitSlow_op_jfalse(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_jnless(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_jless(Instruction*, Vector<SlowCaseEntry>::iterator&); + void emitSlow_op_jlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&, bool invert = false); void emitSlow_op_jnlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_jtrue(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_loop_if_less(Instruction*, Vector<SlowCaseEntry>::iterator&); @@ -911,6 +787,11 @@ namespace JSC { void emitSlow_op_sub(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_to_jsnumber(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_to_primitive(Instruction*, Vector<SlowCaseEntry>::iterator&); + void emitSlow_op_urshift(Instruction*, Vector<SlowCaseEntry>::iterator&); + + + void emitRightShift(Instruction*, bool isUnsigned); + void emitRightShiftSlowCase(Instruction*, Vector<SlowCaseEntry>::iterator&, bool isUnsigned); /* These functions are deprecated: Please use JITStubCall instead. */ void emitPutJITStubArg(RegisterID src, unsigned argumentNumber); @@ -933,6 +814,7 @@ namespace JSC { JSValue getConstantOperand(unsigned src); bool isOperandConstantImmediateInt(unsigned src); + bool isOperandConstantImmediateChar(unsigned src); Jump getSlowCase(Vector<SlowCaseEntry>::iterator& iter) { @@ -956,6 +838,9 @@ namespace JSC { void restoreReturnAddressBeforeReturn(RegisterID); void restoreReturnAddressBeforeReturn(Address); + // Loads the character value of a single character string into dst. + void emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures); + void emitTimeoutCheck(); #ifndef NDEBUG void printBytecodeOperandTypes(unsigned src1, unsigned src2); diff --git a/JavaScriptCore/jit/JITArithmetic.cpp b/JavaScriptCore/jit/JITArithmetic.cpp index 2e1ff40..e5a4620 100644 --- a/JavaScriptCore/jit/JITArithmetic.cpp +++ b/JavaScriptCore/jit/JITArithmetic.cpp @@ -20,7 +20,7 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" @@ -46,1187 +46,7 @@ using namespace std; namespace JSC { -#if USE(JSVALUE32_64) - -void JIT::emit_op_negate(Instruction* currentInstruction) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned src = currentInstruction[2].u.operand; - - emitLoad(src, regT1, regT0); - - Jump srcNotInt = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); - addSlowCase(branchTest32(Zero, regT0, Imm32(0x7fffffff))); - neg32(regT0); - emitStoreInt32(dst, regT0, (dst == src)); - - Jump end = jump(); - - srcNotInt.link(this); - addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); - - xor32(Imm32(1 << 31), regT1); - store32(regT1, tagFor(dst)); - if (dst != src) - store32(regT0, payloadFor(dst)); - - end.link(this); -} - -void JIT::emitSlow_op_negate(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned dst = currentInstruction[1].u.operand; - - linkSlowCase(iter); // 0x7fffffff check - linkSlowCase(iter); // double check - - JITStubCall stubCall(this, cti_op_negate); - stubCall.addArgument(regT1, regT0); - stubCall.call(dst); -} - -void JIT::emit_op_jnless(Instruction* currentInstruction) -{ - unsigned op1 = currentInstruction[1].u.operand; - unsigned op2 = currentInstruction[2].u.operand; - unsigned target = currentInstruction[3].u.operand; - - JumpList notInt32Op1; - JumpList notInt32Op2; - - // Int32 less. - if (isOperandConstantImmediateInt(op1)) { - emitLoad(op2, regT3, regT2); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - addJump(branch32(LessThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target); - } else if (isOperandConstantImmediateInt(op2)) { - emitLoad(op1, regT1, regT0); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target); - } else { - emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - addJump(branch32(GreaterThanOrEqual, regT0, regT2), target); - } - - if (!supportsFloatingPoint()) { - addSlowCase(notInt32Op1); - addSlowCase(notInt32Op2); - return; - } - Jump end = jump(); - - // Double less. - emitBinaryDoubleOp(op_jnless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)); - end.link(this); -} - -void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned op1 = currentInstruction[1].u.operand; - unsigned op2 = currentInstruction[2].u.operand; - unsigned target = currentInstruction[3].u.operand; - - if (!supportsFloatingPoint()) { - if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // int32 check - } else { - if (!isOperandConstantImmediateInt(op1)) { - linkSlowCase(iter); // double check - linkSlowCase(iter); // int32 check - } - if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)) - linkSlowCase(iter); // double check - } - - JITStubCall stubCall(this, cti_op_jless); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(); - emitJumpSlowToHot(branchTest32(Zero, regT0), target); -} - -void JIT::emit_op_jless(Instruction* currentInstruction) -{ - unsigned op1 = currentInstruction[1].u.operand; - unsigned op2 = currentInstruction[2].u.operand; - unsigned target = currentInstruction[3].u.operand; - - JumpList notInt32Op1; - JumpList notInt32Op2; - - // Int32 less. - if (isOperandConstantImmediateInt(op1)) { - emitLoad(op2, regT3, regT2); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - addJump(branch32(GreaterThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target); - } else if (isOperandConstantImmediateInt(op2)) { - emitLoad(op1, regT1, regT0); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addJump(branch32(LessThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target); - } else { - emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - addJump(branch32(LessThan, regT0, regT2), target); - } - - if (!supportsFloatingPoint()) { - addSlowCase(notInt32Op1); - addSlowCase(notInt32Op2); - return; - } - Jump end = jump(); - - // Double less. - emitBinaryDoubleOp(op_jless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)); - end.link(this); -} - -void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned op1 = currentInstruction[1].u.operand; - unsigned op2 = currentInstruction[2].u.operand; - unsigned target = currentInstruction[3].u.operand; - - if (!supportsFloatingPoint()) { - if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // int32 check - } else { - if (!isOperandConstantImmediateInt(op1)) { - linkSlowCase(iter); // double check - linkSlowCase(iter); // int32 check - } - if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)) - linkSlowCase(iter); // double check - } - - JITStubCall stubCall(this, cti_op_jless); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(); - emitJumpSlowToHot(branchTest32(NonZero, regT0), target); -} - -void JIT::emit_op_jnlesseq(Instruction* currentInstruction) -{ - unsigned op1 = currentInstruction[1].u.operand; - unsigned op2 = currentInstruction[2].u.operand; - unsigned target = currentInstruction[3].u.operand; - - JumpList notInt32Op1; - JumpList notInt32Op2; - - // Int32 less. - if (isOperandConstantImmediateInt(op1)) { - emitLoad(op2, regT3, regT2); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - addJump(branch32(LessThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target); - } else if (isOperandConstantImmediateInt(op2)) { - emitLoad(op1, regT1, regT0); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addJump(branch32(GreaterThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target); - } else { - emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - addJump(branch32(GreaterThan, regT0, regT2), target); - } - - if (!supportsFloatingPoint()) { - addSlowCase(notInt32Op1); - addSlowCase(notInt32Op2); - return; - } - Jump end = jump(); - - // Double less. - emitBinaryDoubleOp(op_jnlesseq, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)); - end.link(this); -} - -void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned op1 = currentInstruction[1].u.operand; - unsigned op2 = currentInstruction[2].u.operand; - unsigned target = currentInstruction[3].u.operand; - - if (!supportsFloatingPoint()) { - if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // int32 check - } else { - if (!isOperandConstantImmediateInt(op1)) { - linkSlowCase(iter); // double check - linkSlowCase(iter); // int32 check - } - if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)) - linkSlowCase(iter); // double check - } - - JITStubCall stubCall(this, cti_op_jlesseq); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(); - emitJumpSlowToHot(branchTest32(Zero, regT0), target); -} - -// LeftShift (<<) - -void JIT::emit_op_lshift(Instruction* currentInstruction) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - - if (isOperandConstantImmediateInt(op2)) { - emitLoad(op1, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - lshift32(Imm32(getConstantOperand(op2).asInt32()), regT0); - emitStoreInt32(dst, regT0, dst == op1); - return; - } - - emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - if (!isOperandConstantImmediateInt(op1)) - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - lshift32(regT2, regT0); - emitStoreInt32(dst, regT0, dst == op1 || dst == op2); -} - -void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - - if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // int32 check - - JITStubCall stubCall(this, cti_op_lshift); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(dst); -} - -// RightShift (>>) - -void JIT::emit_op_rshift(Instruction* currentInstruction) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - - if (isOperandConstantImmediateInt(op2)) { - emitLoad(op1, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - rshift32(Imm32(getConstantOperand(op2).asInt32()), regT0); - emitStoreInt32(dst, regT0, dst == op1); - return; - } - - emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - if (!isOperandConstantImmediateInt(op1)) - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - rshift32(regT2, regT0); - emitStoreInt32(dst, regT0, dst == op1 || dst == op2); -} - -void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - - if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // int32 check - - JITStubCall stubCall(this, cti_op_rshift); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(dst); -} - -// BitAnd (&) - -void JIT::emit_op_bitand(Instruction* currentInstruction) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - - unsigned op; - int32_t constant; - if (getOperandConstantImmediateInt(op1, op2, op, constant)) { - emitLoad(op, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - and32(Imm32(constant), regT0); - emitStoreInt32(dst, regT0, (op == dst)); - return; - } - - emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - and32(regT2, regT0); - emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); -} - -void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - - if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // int32 check - - JITStubCall stubCall(this, cti_op_bitand); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(dst); -} - -// BitOr (|) - -void JIT::emit_op_bitor(Instruction* currentInstruction) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - - unsigned op; - int32_t constant; - if (getOperandConstantImmediateInt(op1, op2, op, constant)) { - emitLoad(op, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - or32(Imm32(constant), regT0); - emitStoreInt32(dst, regT0, (op == dst)); - return; - } - - emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - or32(regT2, regT0); - emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); -} - -void JIT::emitSlow_op_bitor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - - if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // int32 check - - JITStubCall stubCall(this, cti_op_bitor); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(dst); -} - -// BitXor (^) - -void JIT::emit_op_bitxor(Instruction* currentInstruction) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - - unsigned op; - int32_t constant; - if (getOperandConstantImmediateInt(op1, op2, op, constant)) { - emitLoad(op, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - xor32(Imm32(constant), regT0); - emitStoreInt32(dst, regT0, (op == dst)); - return; - } - - emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - xor32(regT2, regT0); - emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); -} - -void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - - if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // int32 check - - JITStubCall stubCall(this, cti_op_bitxor); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(dst); -} - -// BitNot (~) - -void JIT::emit_op_bitnot(Instruction* currentInstruction) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned src = currentInstruction[2].u.operand; - - emitLoad(src, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - - not32(regT0); - emitStoreInt32(dst, regT0, (dst == src)); -} - -void JIT::emitSlow_op_bitnot(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned dst = currentInstruction[1].u.operand; - - linkSlowCase(iter); // int32 check - - JITStubCall stubCall(this, cti_op_bitnot); - stubCall.addArgument(regT1, regT0); - stubCall.call(dst); -} - -// PostInc (i++) - -void JIT::emit_op_post_inc(Instruction* currentInstruction) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned srcDst = currentInstruction[2].u.operand; - - emitLoad(srcDst, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - - if (dst == srcDst) // x = x++ is a noop for ints. - return; - - emitStoreInt32(dst, regT0); - - addSlowCase(branchAdd32(Overflow, Imm32(1), regT0)); - emitStoreInt32(srcDst, regT0, true); -} - -void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned srcDst = currentInstruction[2].u.operand; - - linkSlowCase(iter); // int32 check - if (dst != srcDst) - linkSlowCase(iter); // overflow check - - JITStubCall stubCall(this, cti_op_post_inc); - stubCall.addArgument(srcDst); - stubCall.addArgument(Imm32(srcDst)); - stubCall.call(dst); -} - -// PostDec (i--) - -void JIT::emit_op_post_dec(Instruction* currentInstruction) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned srcDst = currentInstruction[2].u.operand; - - emitLoad(srcDst, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - - if (dst == srcDst) // x = x-- is a noop for ints. - return; - - emitStoreInt32(dst, regT0); - - addSlowCase(branchSub32(Overflow, Imm32(1), regT0)); - emitStoreInt32(srcDst, regT0, true); -} - -void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned srcDst = currentInstruction[2].u.operand; - - linkSlowCase(iter); // int32 check - if (dst != srcDst) - linkSlowCase(iter); // overflow check - - JITStubCall stubCall(this, cti_op_post_dec); - stubCall.addArgument(srcDst); - stubCall.addArgument(Imm32(srcDst)); - stubCall.call(dst); -} - -// PreInc (++i) - -void JIT::emit_op_pre_inc(Instruction* currentInstruction) -{ - unsigned srcDst = currentInstruction[1].u.operand; - - emitLoad(srcDst, regT1, regT0); - - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branchAdd32(Overflow, Imm32(1), regT0)); - emitStoreInt32(srcDst, regT0, true); -} - -void JIT::emitSlow_op_pre_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned srcDst = currentInstruction[1].u.operand; - - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // overflow check - - JITStubCall stubCall(this, cti_op_pre_inc); - stubCall.addArgument(srcDst); - stubCall.call(srcDst); -} - -// PreDec (--i) - -void JIT::emit_op_pre_dec(Instruction* currentInstruction) -{ - unsigned srcDst = currentInstruction[1].u.operand; - - emitLoad(srcDst, regT1, regT0); - - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branchSub32(Overflow, Imm32(1), regT0)); - emitStoreInt32(srcDst, regT0, true); -} - -void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned srcDst = currentInstruction[1].u.operand; - - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // overflow check - - JITStubCall stubCall(this, cti_op_pre_dec); - stubCall.addArgument(srcDst); - stubCall.call(srcDst); -} - -// Addition (+) - -void JIT::emit_op_add(Instruction* currentInstruction) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); - - if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) { - JITStubCall stubCall(this, cti_op_add); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(dst); - return; - } - - JumpList notInt32Op1; - JumpList notInt32Op2; - - unsigned op; - int32_t constant; - if (getOperandConstantImmediateInt(op1, op2, op, constant)) { - emitAdd32Constant(dst, op, constant, op == op1 ? types.first() : types.second()); - return; - } - - emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - - // Int32 case. - addSlowCase(branchAdd32(Overflow, regT2, regT0)); - emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); - - if (!supportsFloatingPoint()) { - addSlowCase(notInt32Op1); - addSlowCase(notInt32Op2); - return; - } - Jump end = jump(); - - // Double case. - emitBinaryDoubleOp(op_add, dst, op1, op2, types, notInt32Op1, notInt32Op2); - end.link(this); -} - -void JIT::emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType) -{ - // Int32 case. - emitLoad(op, regT1, regT0); - Jump notInt32 = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); - addSlowCase(branchAdd32(Overflow, Imm32(constant), regT0)); - emitStoreInt32(dst, regT0, (op == dst)); - - // Double case. - if (!supportsFloatingPoint()) { - addSlowCase(notInt32); - return; - } - Jump end = jump(); - - notInt32.link(this); - if (!opType.definitelyIsNumber()) - addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); - move(Imm32(constant), regT2); - convertInt32ToDouble(regT2, fpRegT0); - emitLoadDouble(op, fpRegT1); - addDouble(fpRegT1, fpRegT0); - emitStoreDouble(dst, fpRegT0); - - end.link(this); -} - -void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); - - if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) - return; - - unsigned op; - int32_t constant; - if (getOperandConstantImmediateInt(op1, op2, op, constant)) { - linkSlowCase(iter); // overflow check - - if (!supportsFloatingPoint()) - linkSlowCase(iter); // non-sse case - else { - ResultType opType = op == op1 ? types.first() : types.second(); - if (!opType.definitelyIsNumber()) - linkSlowCase(iter); // double check - } - } else { - linkSlowCase(iter); // overflow check - - if (!supportsFloatingPoint()) { - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // int32 check - } else { - if (!types.first().definitelyIsNumber()) - linkSlowCase(iter); // double check - - if (!types.second().definitelyIsNumber()) { - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // double check - } - } - } - - JITStubCall stubCall(this, cti_op_add); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(dst); -} - -// Subtraction (-) - -void JIT::emit_op_sub(Instruction* currentInstruction) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); - - JumpList notInt32Op1; - JumpList notInt32Op2; - - if (isOperandConstantImmediateInt(op2)) { - emitSub32Constant(dst, op1, getConstantOperand(op2).asInt32(), types.first()); - return; - } - - emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - - // Int32 case. - addSlowCase(branchSub32(Overflow, regT2, regT0)); - emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); - - if (!supportsFloatingPoint()) { - addSlowCase(notInt32Op1); - addSlowCase(notInt32Op2); - return; - } - Jump end = jump(); - - // Double case. - emitBinaryDoubleOp(op_sub, dst, op1, op2, types, notInt32Op1, notInt32Op2); - end.link(this); -} - -void JIT::emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType) -{ - // Int32 case. - emitLoad(op, regT1, regT0); - Jump notInt32 = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); - addSlowCase(branchSub32(Overflow, Imm32(constant), regT0)); - emitStoreInt32(dst, regT0, (op == dst)); - - // Double case. - if (!supportsFloatingPoint()) { - addSlowCase(notInt32); - return; - } - Jump end = jump(); - - notInt32.link(this); - if (!opType.definitelyIsNumber()) - addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); - move(Imm32(constant), regT2); - convertInt32ToDouble(regT2, fpRegT0); - emitLoadDouble(op, fpRegT1); - subDouble(fpRegT0, fpRegT1); - emitStoreDouble(dst, fpRegT1); - - end.link(this); -} - -void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); - - if (isOperandConstantImmediateInt(op2)) { - linkSlowCase(iter); // overflow check - - if (!supportsFloatingPoint() || !types.first().definitelyIsNumber()) - linkSlowCase(iter); // int32 or double check - } else { - linkSlowCase(iter); // overflow check - - if (!supportsFloatingPoint()) { - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // int32 check - } else { - if (!types.first().definitelyIsNumber()) - linkSlowCase(iter); // double check - - if (!types.second().definitelyIsNumber()) { - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // double check - } - } - } - - JITStubCall stubCall(this, cti_op_sub); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(dst); -} - -void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsigned op2, OperandTypes types, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters, bool op2IsInRegisters) -{ - JumpList end; - - if (!notInt32Op1.empty()) { - // Double case 1: Op1 is not int32; Op2 is unknown. - notInt32Op1.link(this); - - ASSERT(op1IsInRegisters); - - // Verify Op1 is double. - if (!types.first().definitelyIsNumber()) - addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); - - if (!op2IsInRegisters) - emitLoad(op2, regT3, regT2); - - Jump doubleOp2 = branch32(Below, regT3, Imm32(JSValue::LowestTag)); - - if (!types.second().definitelyIsNumber()) - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - - convertInt32ToDouble(regT2, fpRegT0); - Jump doTheMath = jump(); - - // Load Op2 as double into double register. - doubleOp2.link(this); - emitLoadDouble(op2, fpRegT0); - - // Do the math. - doTheMath.link(this); - switch (opcodeID) { - case op_mul: - emitLoadDouble(op1, fpRegT2); - mulDouble(fpRegT2, fpRegT0); - emitStoreDouble(dst, fpRegT0); - break; - case op_add: - emitLoadDouble(op1, fpRegT2); - addDouble(fpRegT2, fpRegT0); - emitStoreDouble(dst, fpRegT0); - break; - case op_sub: - emitLoadDouble(op1, fpRegT1); - subDouble(fpRegT0, fpRegT1); - emitStoreDouble(dst, fpRegT1); - break; - case op_div: - emitLoadDouble(op1, fpRegT1); - divDouble(fpRegT0, fpRegT1); - emitStoreDouble(dst, fpRegT1); - break; - case op_jnless: - emitLoadDouble(op1, fpRegT2); - addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT0, fpRegT2), dst); - break; - case op_jless: - emitLoadDouble(op1, fpRegT2); - addJump(branchDouble(DoubleLessThan, fpRegT2, fpRegT0), dst); - break; - case op_jnlesseq: - emitLoadDouble(op1, fpRegT2); - addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT0, fpRegT2), dst); - break; - default: - ASSERT_NOT_REACHED(); - } - - if (!notInt32Op2.empty()) - end.append(jump()); - } - - if (!notInt32Op2.empty()) { - // Double case 2: Op1 is int32; Op2 is not int32. - notInt32Op2.link(this); - - ASSERT(op2IsInRegisters); - - if (!op1IsInRegisters) - emitLoadPayload(op1, regT0); - - convertInt32ToDouble(regT0, fpRegT0); - - // Verify op2 is double. - if (!types.second().definitelyIsNumber()) - addSlowCase(branch32(Above, regT3, Imm32(JSValue::LowestTag))); - - // Do the math. - switch (opcodeID) { - case op_mul: - emitLoadDouble(op2, fpRegT2); - mulDouble(fpRegT2, fpRegT0); - emitStoreDouble(dst, fpRegT0); - break; - case op_add: - emitLoadDouble(op2, fpRegT2); - addDouble(fpRegT2, fpRegT0); - emitStoreDouble(dst, fpRegT0); - break; - case op_sub: - emitLoadDouble(op2, fpRegT2); - subDouble(fpRegT2, fpRegT0); - emitStoreDouble(dst, fpRegT0); - break; - case op_div: - emitLoadDouble(op2, fpRegT2); - divDouble(fpRegT2, fpRegT0); - emitStoreDouble(dst, fpRegT0); - break; - case op_jnless: - emitLoadDouble(op2, fpRegT1); - addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), dst); - break; - case op_jless: - emitLoadDouble(op2, fpRegT1); - addJump(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), dst); - break; - case op_jnlesseq: - emitLoadDouble(op2, fpRegT1); - addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), dst); - break; - default: - ASSERT_NOT_REACHED(); - } - } - - end.link(this); -} - -// Multiplication (*) - -void JIT::emit_op_mul(Instruction* currentInstruction) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); - - JumpList notInt32Op1; - JumpList notInt32Op2; - - emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - - // Int32 case. - move(regT0, regT3); - addSlowCase(branchMul32(Overflow, regT2, regT0)); - addSlowCase(branchTest32(Zero, regT0)); - emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); - - if (!supportsFloatingPoint()) { - addSlowCase(notInt32Op1); - addSlowCase(notInt32Op2); - return; - } - Jump end = jump(); - - // Double case. - emitBinaryDoubleOp(op_mul, dst, op1, op2, types, notInt32Op1, notInt32Op2); - end.link(this); -} - -void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); - - Jump overflow = getSlowCase(iter); // overflow check - linkSlowCase(iter); // zero result check - - Jump negZero = branchOr32(Signed, regT2, regT3); - emitStoreInt32(dst, Imm32(0), (op1 == dst || op2 == dst)); - - emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_mul)); - - negZero.link(this); - overflow.link(this); - - if (!supportsFloatingPoint()) { - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // int32 check - } - - if (supportsFloatingPoint()) { - if (!types.first().definitelyIsNumber()) - linkSlowCase(iter); // double check - - if (!types.second().definitelyIsNumber()) { - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // double check - } - } - - Label jitStubCall(this); - JITStubCall stubCall(this, cti_op_mul); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(dst); -} - -// Division (/) - -void JIT::emit_op_div(Instruction* currentInstruction) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); - - if (!supportsFloatingPoint()) { - addSlowCase(jump()); - return; - } - - // Int32 divide. - JumpList notInt32Op1; - JumpList notInt32Op2; - - JumpList end; - - emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - - convertInt32ToDouble(regT0, fpRegT0); - convertInt32ToDouble(regT2, fpRegT1); - divDouble(fpRegT1, fpRegT0); - - JumpList doubleResult; - branchConvertDoubleToInt32(fpRegT0, regT0, doubleResult, fpRegT1); - - // Int32 result. - emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); - end.append(jump()); - - // Double result. - doubleResult.link(this); - emitStoreDouble(dst, fpRegT0); - end.append(jump()); - - // Double divide. - emitBinaryDoubleOp(op_div, dst, op1, op2, types, notInt32Op1, notInt32Op2); - end.link(this); -} - -void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); - - if (!supportsFloatingPoint()) - linkSlowCase(iter); - else { - if (!types.first().definitelyIsNumber()) - linkSlowCase(iter); // double check - - if (!types.second().definitelyIsNumber()) { - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // double check - } - } - - JITStubCall stubCall(this, cti_op_div); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(dst); -} - -// Mod (%) - -/* ------------------------------ BEGIN: OP_MOD ------------------------------ */ - -#if CPU(X86) || CPU(X86_64) - -void JIT::emit_op_mod(Instruction* currentInstruction) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - - if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) { - emitLoad(op1, X86Registers::edx, X86Registers::eax); - move(Imm32(getConstantOperand(op2).asInt32()), X86Registers::ecx); - addSlowCase(branch32(NotEqual, X86Registers::edx, Imm32(JSValue::Int32Tag))); - if (getConstantOperand(op2).asInt32() == -1) - addSlowCase(branch32(Equal, X86Registers::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC - } else { - emitLoad2(op1, X86Registers::edx, X86Registers::eax, op2, X86Registers::ebx, X86Registers::ecx); - addSlowCase(branch32(NotEqual, X86Registers::edx, Imm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, X86Registers::ebx, Imm32(JSValue::Int32Tag))); - - addSlowCase(branch32(Equal, X86Registers::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC - addSlowCase(branch32(Equal, X86Registers::ecx, Imm32(0))); // divide by 0 - } - - move(X86Registers::eax, X86Registers::ebx); // Save dividend payload, in case of 0. - m_assembler.cdq(); - m_assembler.idivl_r(X86Registers::ecx); - - // If the remainder is zero and the dividend is negative, the result is -0. - Jump storeResult1 = branchTest32(NonZero, X86Registers::edx); - Jump storeResult2 = branchTest32(Zero, X86Registers::ebx, Imm32(0x80000000)); // not negative - emitStore(dst, jsNumber(m_globalData, -0.0)); - Jump end = jump(); - - storeResult1.link(this); - storeResult2.link(this); - emitStoreInt32(dst, X86Registers::edx, (op1 == dst || op2 == dst)); - end.link(this); -} - -void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - - if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) { - linkSlowCase(iter); // int32 check - if (getConstantOperand(op2).asInt32() == -1) - linkSlowCase(iter); // 0x80000000 check - } else { - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // 0 check - linkSlowCase(iter); // 0x80000000 check - } - - JITStubCall stubCall(this, cti_op_mod); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(dst); -} - -#else // CPU(X86) || CPU(X86_64) - -void JIT::emit_op_mod(Instruction* currentInstruction) -{ - unsigned dst = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - -#if ENABLE(JIT_OPTIMIZE_MOD) - emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - - addSlowCase(branch32(Equal, regT2, Imm32(0))); - - emitNakedCall(m_globalData->jitStubs.ctiSoftModulo()); - - emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); -#else - JITStubCall stubCall(this, cti_op_mod); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(dst); -#endif -} - -void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ -#if ENABLE(JIT_OPTIMIZE_MOD) - unsigned result = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - linkSlowCase(iter); - linkSlowCase(iter); - linkSlowCase(iter); - JITStubCall stubCall(this, cti_op_mod); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(result); -#else - ASSERT_NOT_REACHED(); -#endif -} - -#endif // CPU(X86) || CPU(X86_64) - -/* ------------------------------ END: OP_MOD ------------------------------ */ - -#else // USE(JSVALUE32_64) +#if !USE(JSVALUE32_64) void JIT::emit_op_lshift(Instruction* currentInstruction) { @@ -1367,6 +187,118 @@ void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEnt stubCall.call(result); } +void JIT::emit_op_urshift(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + // Slow case of urshift makes assumptions about what registers hold the + // shift arguments, so any changes must be updated there as well. + if (isOperandConstantImmediateInt(op2)) { + emitGetVirtualRegister(op1, regT0); + emitJumpSlowCaseIfNotImmediateInteger(regT0); + emitFastArithImmToInt(regT0); + int shift = getConstantOperand(op2).asInt32(); + if (shift) + urshift32(Imm32(shift & 0x1f), regT0); + // unsigned shift < 0 or shift = k*2^32 may result in (essentially) + // a toUint conversion, which can result in a value we can represent + // as an immediate int. + if (shift < 0 || !(shift & 31)) + addSlowCase(branch32(LessThan, regT0, Imm32(0))); +#if USE(JSVALUE32) + addSlowCase(branchAdd32(Overflow, regT0, regT0)); + signExtend32ToPtr(regT0, regT0); +#endif + emitFastArithReTagImmediate(regT0, regT0); + emitPutVirtualRegister(dst, regT0); + return; + } + emitGetVirtualRegisters(op1, regT0, op2, regT1); + if (!isOperandConstantImmediateInt(op1)) + emitJumpSlowCaseIfNotImmediateInteger(regT0); + emitJumpSlowCaseIfNotImmediateInteger(regT1); + emitFastArithImmToInt(regT0); + emitFastArithImmToInt(regT1); + urshift32(regT1, regT0); + addSlowCase(branch32(LessThan, regT0, Imm32(0))); +#if USE(JSVALUE32) + addSlowCase(branchAdd32(Overflow, regT0, regT0)); + signExtend32ToPtr(regT0, regT0); +#endif + emitFastArithReTagImmediate(regT0, regT0); + emitPutVirtualRegister(dst, regT0); +} + +void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + if (isOperandConstantImmediateInt(op2)) { + int shift = getConstantOperand(op2).asInt32(); + // op1 = regT0 + linkSlowCase(iter); // int32 check +#if USE(JSVALUE64) + if (supportsFloatingPointTruncate()) { + JumpList failures; + failures.append(emitJumpIfNotImmediateNumber(regT0)); // op1 is not a double + addPtr(tagTypeNumberRegister, regT0); + movePtrToDouble(regT0, fpRegT0); + failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0)); + if (shift) + urshift32(Imm32(shift & 0x1f), regT0); + if (shift < 0 || !(shift & 31)) + failures.append(branch32(LessThan, regT0, Imm32(0))); + emitFastArithReTagImmediate(regT0, regT0); + emitPutVirtualRegister(dst, regT0); + emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift)); + failures.link(this); + } +#endif // JSVALUE64 + if (shift < 0 || !(shift & 31)) + linkSlowCase(iter); // failed to box in hot path +#if USE(JSVALUE32) + linkSlowCase(iter); // Couldn't box result +#endif + } else { + // op1 = regT0 + // op2 = regT1 + if (!isOperandConstantImmediateInt(op1)) { + linkSlowCase(iter); // int32 check -- op1 is not an int +#if USE(JSVALUE64) + if (supportsFloatingPointTruncate()) { + JumpList failures; + failures.append(emitJumpIfNotImmediateNumber(regT0)); // op1 is not a double + addPtr(tagTypeNumberRegister, regT0); + movePtrToDouble(regT0, fpRegT0); + failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0)); + failures.append(emitJumpIfNotImmediateInteger(regT1)); // op2 is not an int + emitFastArithImmToInt(regT1); + urshift32(regT1, regT0); + failures.append(branch32(LessThan, regT0, Imm32(0))); + emitFastArithReTagImmediate(regT0, regT0); + emitPutVirtualRegister(dst, regT0); + emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift)); + failures.link(this); + } +#endif + } + + linkSlowCase(iter); // int32 check - op2 is not an int + linkSlowCase(iter); // Can't represent unsigned result as an immediate +#if USE(JSVALUE32) + linkSlowCase(iter); // Couldn't box result +#endif + } + + JITStubCall stubCall(this, cti_op_urshift); + stubCall.addArgument(op1, regT0); + stubCall.addArgument(op2, regT1); + stubCall.call(dst); +} + void JIT::emit_op_jnless(Instruction* currentInstruction) { unsigned op1 = currentInstruction[1].u.operand; @@ -1378,6 +310,24 @@ void JIT::emit_op_jnless(Instruction* currentInstruction) // - constant int immediate to int immediate // - int immediate to int immediate + if (isOperandConstantImmediateChar(op1)) { + emitGetVirtualRegister(op2, regT0); + addSlowCase(emitJumpIfNotJSCell(regT0)); + JumpList failures; + emitLoadCharacterString(regT0, regT0, failures); + addSlowCase(failures); + addJump(branch32(LessThanOrEqual, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target); + return; + } + if (isOperandConstantImmediateChar(op2)) { + emitGetVirtualRegister(op1, regT0); + addSlowCase(emitJumpIfNotJSCell(regT0)); + JumpList failures; + emitLoadCharacterString(regT0, regT0, failures); + addSlowCase(failures); + addJump(branch32(GreaterThanOrEqual, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target); + return; + } if (isOperandConstantImmediateInt(op2)) { emitGetVirtualRegister(op1, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); @@ -1415,6 +365,18 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt // - floating-point number to constant int immediate // - constant int immediate to floating-point number // - floating-point number to floating-point number. + if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) { + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + JITStubCall stubCall(this, cti_op_jlesseq); + stubCall.addArgument(op1, regT0); + stubCall.addArgument(op2, regT1); + stubCall.call(); + emitJumpSlowToHot(branchTest32(Zero, regT0), target); + return; + } if (isOperandConstantImmediateInt(op2)) { linkSlowCase(iter); @@ -1432,9 +394,9 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get()); loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); #endif - + int32_t op2imm = getConstantOperand(op2).asInt32();; - + move(Imm32(op2imm), regT1); convertInt32ToDouble(regT1, fpRegT1); @@ -1469,13 +431,13 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt Jump fail1; if (!m_codeBlock->isKnownNotImmediate(op2)) fail1 = emitJumpIfNotJSCell(regT1); - + Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get()); loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); #endif - + int32_t op1imm = getConstantOperand(op1).asInt32();; - + move(Imm32(op1imm), regT0); convertInt32ToDouble(regT0, fpRegT0); @@ -1563,6 +525,24 @@ void JIT::emit_op_jless(Instruction* currentInstruction) // - constant int immediate to int immediate // - int immediate to int immediate + if (isOperandConstantImmediateChar(op1)) { + emitGetVirtualRegister(op2, regT0); + addSlowCase(emitJumpIfNotJSCell(regT0)); + JumpList failures; + emitLoadCharacterString(regT0, regT0, failures); + addSlowCase(failures); + addJump(branch32(GreaterThan, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target); + return; + } + if (isOperandConstantImmediateChar(op2)) { + emitGetVirtualRegister(op1, regT0); + addSlowCase(emitJumpIfNotJSCell(regT0)); + JumpList failures; + emitLoadCharacterString(regT0, regT0, failures); + addSlowCase(failures); + addJump(branch32(LessThan, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target); + return; + } if (isOperandConstantImmediateInt(op2)) { emitGetVirtualRegister(op1, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); @@ -1600,6 +580,18 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr // - floating-point number to constant int immediate // - constant int immediate to floating-point number // - floating-point number to floating-point number. + if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) { + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + JITStubCall stubCall(this, cti_op_jlesseq); + stubCall.addArgument(op1, regT0); + stubCall.addArgument(op2, regT1); + stubCall.call(); + emitJumpSlowToHot(branchTest32(NonZero, regT0), target); + return; + } if (isOperandConstantImmediateInt(op2)) { linkSlowCase(iter); @@ -1617,9 +609,9 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get()); loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); #endif - + int32_t op2imm = getConstantOperand(op2).asInt32(); - + move(Imm32(op2imm), regT1); convertInt32ToDouble(regT1, fpRegT1); @@ -1654,13 +646,13 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr Jump fail1; if (!m_codeBlock->isKnownNotImmediate(op2)) fail1 = emitJumpIfNotJSCell(regT1); - + Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get()); loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); #endif - + int32_t op1imm = getConstantOperand(op1).asInt32(); - + move(Imm32(op1imm), regT0); convertInt32ToDouble(regT0, fpRegT0); @@ -1737,7 +729,7 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr } } -void JIT::emit_op_jnlesseq(Instruction* currentInstruction) +void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert) { unsigned op1 = currentInstruction[1].u.operand; unsigned op2 = currentInstruction[2].u.operand; @@ -1748,6 +740,24 @@ void JIT::emit_op_jnlesseq(Instruction* currentInstruction) // - constant int immediate to int immediate // - int immediate to int immediate + if (isOperandConstantImmediateChar(op1)) { + emitGetVirtualRegister(op2, regT0); + addSlowCase(emitJumpIfNotJSCell(regT0)); + JumpList failures; + emitLoadCharacterString(regT0, regT0, failures); + addSlowCase(failures); + addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target); + return; + } + if (isOperandConstantImmediateChar(op2)) { + emitGetVirtualRegister(op1, regT0); + addSlowCase(emitJumpIfNotJSCell(regT0)); + JumpList failures; + emitLoadCharacterString(regT0, regT0, failures); + addSlowCase(failures); + addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target); + return; + } if (isOperandConstantImmediateInt(op2)) { emitGetVirtualRegister(op1, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); @@ -1756,7 +766,7 @@ void JIT::emit_op_jnlesseq(Instruction* currentInstruction) #else int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); #endif - addJump(branch32(GreaterThan, regT0, Imm32(op2imm)), target); + addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(op2imm)), target); } else if (isOperandConstantImmediateInt(op1)) { emitGetVirtualRegister(op2, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT1); @@ -1765,17 +775,17 @@ void JIT::emit_op_jnlesseq(Instruction* currentInstruction) #else int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1))); #endif - addJump(branch32(LessThan, regT1, Imm32(op1imm)), target); + addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT1, Imm32(op1imm)), target); } else { emitGetVirtualRegisters(op1, regT0, op2, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT0); emitJumpSlowCaseIfNotImmediateInteger(regT1); - addJump(branch32(GreaterThan, regT0, regT1), target); + addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, regT1), target); } } -void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter, bool invert) { unsigned op1 = currentInstruction[1].u.operand; unsigned op2 = currentInstruction[2].u.operand; @@ -1786,6 +796,19 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE // - constant int immediate to floating-point number // - floating-point number to floating-point number. + if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) { + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + JITStubCall stubCall(this, cti_op_jlesseq); + stubCall.addArgument(op1, regT0); + stubCall.addArgument(op2, regT1); + stubCall.call(); + emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target); + return; + } + if (isOperandConstantImmediateInt(op2)) { linkSlowCase(iter); @@ -1802,13 +825,13 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get()); loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); #endif - + int32_t op2imm = getConstantOperand(op2).asInt32();; - + move(Imm32(op2imm), regT1); convertInt32ToDouble(regT1, fpRegT1); - emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target); + emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target); emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq)); @@ -1825,7 +848,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE stubCall.addArgument(regT0); stubCall.addArgument(op2, regT2); stubCall.call(); - emitJumpSlowToHot(branchTest32(Zero, regT0), target); + emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target); } else if (isOperandConstantImmediateInt(op1)) { linkSlowCase(iter); @@ -1839,17 +862,17 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE Jump fail1; if (!m_codeBlock->isKnownNotImmediate(op2)) fail1 = emitJumpIfNotJSCell(regT1); - + Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get()); loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); #endif - + int32_t op1imm = getConstantOperand(op1).asInt32();; - + move(Imm32(op1imm), regT0); convertInt32ToDouble(regT0, fpRegT0); - emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target); + emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target); emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq)); @@ -1866,7 +889,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE stubCall.addArgument(op1, regT2); stubCall.addArgument(regT1); stubCall.call(); - emitJumpSlowToHot(branchTest32(Zero, regT0), target); + emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target); } else { linkSlowCase(iter); @@ -1895,7 +918,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); #endif - emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target); + emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target); emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq)); @@ -1918,10 +941,20 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE stubCall.addArgument(regT0); stubCall.addArgument(regT1); stubCall.call(); - emitJumpSlowToHot(branchTest32(Zero, regT0), target); + emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target); } } +void JIT::emit_op_jnlesseq(Instruction* currentInstruction) +{ + emit_op_jlesseq(currentInstruction, true); +} + +void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + emitSlow_op_jlesseq(currentInstruction, iter, true); +} + void JIT::emit_op_bitand(Instruction* currentInstruction) { unsigned result = currentInstruction[1].u.operand; @@ -2164,11 +1197,11 @@ void JIT::emit_op_mod(Instruction* currentInstruction) unsigned op1 = currentInstruction[2].u.operand; unsigned op2 = currentInstruction[3].u.operand; -#if ENABLE(JIT_OPTIMIZE_MOD) +#if ENABLE(JIT_OPTIMIZE_MOD) emitGetVirtualRegisters(op1, regT0, op2, regT2); emitJumpSlowCaseIfNotImmediateInteger(regT0); emitJumpSlowCaseIfNotImmediateInteger(regT2); - + addSlowCase(branch32(Equal, regT2, Imm32(1))); emitNakedCall(m_globalData->jitStubs.ctiSoftModulo()); @@ -2229,7 +1262,7 @@ void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>: { // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset. COMPILE_ASSERT(((JSImmediate::TagTypeNumber + JSImmediate::DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0); - + Jump notImm1; Jump notImm2; if (op1HasImmediateIntFastCase) { @@ -2422,7 +1455,7 @@ void JIT::emit_op_div(Instruction* currentInstruction) movePtrToDouble(regT0, fpRegT0); skipDoubleLoad.link(this); } - + if (isOperandConstantImmediateDouble(op2)) { emitGetVirtualRegister(op2, regT1); addPtr(tagTypeNumberRegister, regT1); @@ -2535,7 +1568,7 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, u op1imm.link(this); emitFastArithImmToInt(regT0); convertInt32ToDouble(regT0, fpRegT0); - // (1c) + // (1c) loadedDouble.link(this); if (opcodeID == op_add) addDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); @@ -2581,7 +1614,7 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, u op2imm.link(this); emitFastArithImmToInt(regT1); convertInt32ToDouble(regT1, fpRegT1); - // (1c) + // (1c) loadedDouble.link(this); loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); if (opcodeID == op_add) @@ -2622,7 +1655,7 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, u Jump op2NonZero = branchTest32(NonZero, regT1); op1Zero.link(this); // if either input is zero, add the two together, and check if the result is < 0. - // If it is, we have a problem (N < 0), (N * 0) == -0, not representatble as a JSImmediate. + // If it is, we have a problem (N < 0), (N * 0) == -0, not representatble as a JSImmediate. move(regT0, regT2); addSlowCase(branchAdd32(Signed, regT1, regT2)); // Skip the above check if neither input is zero @@ -2801,7 +1834,7 @@ void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry> /* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */ -#endif // USE(JSVALUE32_64) +#endif // !USE(JSVALUE32_64) } // namespace JSC diff --git a/JavaScriptCore/jit/JITArithmetic32_64.cpp b/JavaScriptCore/jit/JITArithmetic32_64.cpp new file mode 100644 index 0000000..962c066 --- /dev/null +++ b/JavaScriptCore/jit/JITArithmetic32_64.cpp @@ -0,0 +1,1411 @@ +/* +* Copyright (C) 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 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 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 "JIT.h" + +#if ENABLE(JIT) + +#include "CodeBlock.h" +#include "JITInlineMethods.h" +#include "JITStubCall.h" +#include "JITStubs.h" +#include "JSArray.h" +#include "JSFunction.h" +#include "Interpreter.h" +#include "ResultType.h" +#include "SamplingTool.h" + +#ifndef NDEBUG +#include <stdio.h> +#endif + +using namespace std; + +namespace JSC { + +#if USE(JSVALUE32_64) + +void JIT::emit_op_negate(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned src = currentInstruction[2].u.operand; + + emitLoad(src, regT1, regT0); + + Jump srcNotInt = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); + addSlowCase(branchTest32(Zero, regT0, Imm32(0x7fffffff))); + neg32(regT0); + emitStoreInt32(dst, regT0, (dst == src)); + + Jump end = jump(); + + srcNotInt.link(this); + addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); + + xor32(Imm32(1 << 31), regT1); + store32(regT1, tagFor(dst)); + if (dst != src) + store32(regT0, payloadFor(dst)); + + end.link(this); +} + +void JIT::emitSlow_op_negate(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + + linkSlowCase(iter); // 0x7fffffff check + linkSlowCase(iter); // double check + + JITStubCall stubCall(this, cti_op_negate); + stubCall.addArgument(regT1, regT0); + stubCall.call(dst); +} + +void JIT::emit_op_jnless(Instruction* currentInstruction) +{ + unsigned op1 = currentInstruction[1].u.operand; + unsigned op2 = currentInstruction[2].u.operand; + unsigned target = currentInstruction[3].u.operand; + + JumpList notInt32Op1; + JumpList notInt32Op2; + + // Character less. + if (isOperandConstantImmediateChar(op1)) { + emitLoad(op2, regT1, regT0); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); + JumpList failures; + emitLoadCharacterString(regT0, regT0, failures); + addSlowCase(failures); + addJump(branch32(LessThanOrEqual, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target); + return; + } + if (isOperandConstantImmediateChar(op2)) { + emitLoad(op1, regT1, regT0); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); + JumpList failures; + emitLoadCharacterString(regT0, regT0, failures); + addSlowCase(failures); + addJump(branch32(GreaterThanOrEqual, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target); + return; + } + if (isOperandConstantImmediateInt(op1)) { + // Int32 less. + emitLoad(op2, regT3, regT2); + notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addJump(branch32(LessThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target); + } else if (isOperandConstantImmediateInt(op2)) { + emitLoad(op1, regT1, regT0); + notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target); + } else { + emitLoad2(op1, regT1, regT0, op2, regT3, regT2); + notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addJump(branch32(GreaterThanOrEqual, regT0, regT2), target); + } + + if (!supportsFloatingPoint()) { + addSlowCase(notInt32Op1); + addSlowCase(notInt32Op2); + return; + } + Jump end = jump(); + + // Double less. + emitBinaryDoubleOp(op_jnless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)); + end.link(this); +} + +void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned op1 = currentInstruction[1].u.operand; + unsigned op2 = currentInstruction[2].u.operand; + unsigned target = currentInstruction[3].u.operand; + + if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) { + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + } else { + if (!supportsFloatingPoint()) { + if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // int32 check + } else { + if (!isOperandConstantImmediateInt(op1)) { + linkSlowCase(iter); // double check + linkSlowCase(iter); // int32 check + } + if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)) + linkSlowCase(iter); // double check + } + } + + JITStubCall stubCall(this, cti_op_jless); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(); + emitJumpSlowToHot(branchTest32(Zero, regT0), target); +} + +void JIT::emit_op_jless(Instruction* currentInstruction) +{ + unsigned op1 = currentInstruction[1].u.operand; + unsigned op2 = currentInstruction[2].u.operand; + unsigned target = currentInstruction[3].u.operand; + + JumpList notInt32Op1; + JumpList notInt32Op2; + + // Character less. + if (isOperandConstantImmediateChar(op1)) { + emitLoad(op2, regT1, regT0); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); + JumpList failures; + emitLoadCharacterString(regT0, regT0, failures); + addSlowCase(failures); + addJump(branch32(GreaterThan, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target); + return; + } + if (isOperandConstantImmediateChar(op2)) { + emitLoad(op1, regT1, regT0); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); + JumpList failures; + emitLoadCharacterString(regT0, regT0, failures); + addSlowCase(failures); + addJump(branch32(LessThan, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target); + return; + } + if (isOperandConstantImmediateInt(op1)) { + emitLoad(op2, regT3, regT2); + notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addJump(branch32(GreaterThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target); + } else if (isOperandConstantImmediateInt(op2)) { + emitLoad(op1, regT1, regT0); + notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addJump(branch32(LessThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target); + } else { + emitLoad2(op1, regT1, regT0, op2, regT3, regT2); + notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addJump(branch32(LessThan, regT0, regT2), target); + } + + if (!supportsFloatingPoint()) { + addSlowCase(notInt32Op1); + addSlowCase(notInt32Op2); + return; + } + Jump end = jump(); + + // Double less. + emitBinaryDoubleOp(op_jless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)); + end.link(this); +} + +void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned op1 = currentInstruction[1].u.operand; + unsigned op2 = currentInstruction[2].u.operand; + unsigned target = currentInstruction[3].u.operand; + + if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) { + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + } else { + if (!supportsFloatingPoint()) { + if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // int32 check + } else { + if (!isOperandConstantImmediateInt(op1)) { + linkSlowCase(iter); // double check + linkSlowCase(iter); // int32 check + } + if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)) + linkSlowCase(iter); // double check + } + } + JITStubCall stubCall(this, cti_op_jless); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(); + emitJumpSlowToHot(branchTest32(NonZero, regT0), target); +} + +void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert) +{ + unsigned op1 = currentInstruction[1].u.operand; + unsigned op2 = currentInstruction[2].u.operand; + unsigned target = currentInstruction[3].u.operand; + + JumpList notInt32Op1; + JumpList notInt32Op2; + + // Character less. + if (isOperandConstantImmediateChar(op1)) { + emitLoad(op2, regT1, regT0); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); + JumpList failures; + emitLoadCharacterString(regT0, regT0, failures); + addSlowCase(failures); + addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target); + return; + } + if (isOperandConstantImmediateChar(op2)) { + emitLoad(op1, regT1, regT0); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); + JumpList failures; + emitLoadCharacterString(regT0, regT0, failures); + addSlowCase(failures); + addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target); + return; + } + if (isOperandConstantImmediateInt(op1)) { + emitLoad(op2, regT3, regT2); + notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addJump(branch32(invert ? LessThan : GreaterThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target); + } else if (isOperandConstantImmediateInt(op2)) { + emitLoad(op1, regT1, regT0); + notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target); + } else { + emitLoad2(op1, regT1, regT0, op2, regT3, regT2); + notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, regT2), target); + } + + if (!supportsFloatingPoint()) { + addSlowCase(notInt32Op1); + addSlowCase(notInt32Op2); + return; + } + Jump end = jump(); + + // Double less. + emitBinaryDoubleOp(invert ? op_jnlesseq : op_jlesseq, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)); + end.link(this); +} + +void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter, bool invert) +{ + unsigned op1 = currentInstruction[1].u.operand; + unsigned op2 = currentInstruction[2].u.operand; + unsigned target = currentInstruction[3].u.operand; + + if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) { + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + } else { + if (!supportsFloatingPoint()) { + if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // int32 check + } else { + if (!isOperandConstantImmediateInt(op1)) { + linkSlowCase(iter); // double check + linkSlowCase(iter); // int32 check + } + if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)) + linkSlowCase(iter); // double check + } + } + + JITStubCall stubCall(this, cti_op_jlesseq); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(); + emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target); +} + +void JIT::emit_op_jnlesseq(Instruction* currentInstruction) +{ + emit_op_jlesseq(currentInstruction, true); +} + +void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + emitSlow_op_jlesseq(currentInstruction, iter, true); +} + +// LeftShift (<<) + +void JIT::emit_op_lshift(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + if (isOperandConstantImmediateInt(op2)) { + emitLoad(op1, regT1, regT0); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + lshift32(Imm32(getConstantOperand(op2).asInt32()), regT0); + emitStoreInt32(dst, regT0, dst == op1); + return; + } + + emitLoad2(op1, regT1, regT0, op2, regT3, regT2); + if (!isOperandConstantImmediateInt(op1)) + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + lshift32(regT2, regT0); + emitStoreInt32(dst, regT0, dst == op1 || dst == op2); +} + +void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // int32 check + + JITStubCall stubCall(this, cti_op_lshift); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(dst); +} + +// RightShift (>>) and UnsignedRightShift (>>>) helper + +void JIT::emitRightShift(Instruction* currentInstruction, bool isUnsigned) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + // Slow case of rshift makes assumptions about what registers hold the + // shift arguments, so any changes must be updated there as well. + if (isOperandConstantImmediateInt(op2)) { + emitLoad(op1, regT1, regT0); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + int shift = getConstantOperand(op2).asInt32(); + if (isUnsigned) { + if (shift) + urshift32(Imm32(shift & 0x1f), regT0); + // unsigned shift < 0 or shift = k*2^32 may result in (essentially) + // a toUint conversion, which can result in a value we can represent + // as an immediate int. + if (shift < 0 || !(shift & 31)) + addSlowCase(branch32(LessThan, regT0, Imm32(0))); + } else if (shift) { // signed right shift by zero is simply toInt conversion + rshift32(Imm32(shift & 0x1f), regT0); + } + emitStoreInt32(dst, regT0, dst == op1); + return; + } + + emitLoad2(op1, regT1, regT0, op2, regT3, regT2); + if (!isOperandConstantImmediateInt(op1)) + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + if (isUnsigned) { + urshift32(regT2, regT0); + addSlowCase(branch32(LessThan, regT0, Imm32(0))); + } else + rshift32(regT2, regT0); + emitStoreInt32(dst, regT0, dst == op1 || dst == op2); +} + +void JIT::emitRightShiftSlowCase(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter, bool isUnsigned) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + if (isOperandConstantImmediateInt(op2)) { + int shift = getConstantOperand(op2).asInt32(); + // op1 = regT1:regT0 + linkSlowCase(iter); // int32 check + if (supportsFloatingPointTruncate()) { + JumpList failures; + failures.append(branch32(AboveOrEqual, regT1, Imm32(JSValue::LowestTag))); + emitLoadDouble(op1, fpRegT0); + failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0)); + if (isUnsigned) { + if (shift) + urshift32(Imm32(shift & 0x1f), regT0); + if (shift < 0 || !(shift & 31)) + failures.append(branch32(LessThan, regT0, Imm32(0))); + } else if (shift) + rshift32(Imm32(shift & 0x1f), regT0); + emitStoreInt32(dst, regT0, dst == op1 || dst == op2); + emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift)); + failures.link(this); + } + if (isUnsigned && (shift < 0 || !(shift & 31))) + linkSlowCase(iter); // failed to box in hot path + } else { + // op1 = regT1:regT0 + // op2 = regT3:regT2 + if (!isOperandConstantImmediateInt(op1)) { + linkSlowCase(iter); // int32 check -- op1 is not an int + if (supportsFloatingPointTruncate()) { + Jump notDouble = branch32(Above, regT1, Imm32(JSValue::LowestTag)); // op1 is not a double + emitLoadDouble(op1, fpRegT0); + Jump notInt = branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)); // op2 is not an int + Jump cantTruncate = branchTruncateDoubleToInt32(fpRegT0, regT0); + if (isUnsigned) + urshift32(regT2, regT0); + else + rshift32(regT2, regT0); + emitStoreInt32(dst, regT0, dst == op1 || dst == op2); + emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift)); + notDouble.link(this); + notInt.link(this); + cantTruncate.link(this); + } + } + + linkSlowCase(iter); // int32 check - op2 is not an int + if (isUnsigned) + linkSlowCase(iter); // Can't represent unsigned result as an immediate + } + + JITStubCall stubCall(this, isUnsigned ? cti_op_urshift : cti_op_rshift); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(dst); +} + +// RightShift (>>) + +void JIT::emit_op_rshift(Instruction* currentInstruction) +{ + emitRightShift(currentInstruction, false); +} + +void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + emitRightShiftSlowCase(currentInstruction, iter, false); +} + +// UnsignedRightShift (>>>) + +void JIT::emit_op_urshift(Instruction* currentInstruction) +{ + emitRightShift(currentInstruction, true); +} + +void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + emitRightShiftSlowCase(currentInstruction, iter, true); +} + +// BitAnd (&) + +void JIT::emit_op_bitand(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + unsigned op; + int32_t constant; + if (getOperandConstantImmediateInt(op1, op2, op, constant)) { + emitLoad(op, regT1, regT0); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + and32(Imm32(constant), regT0); + emitStoreInt32(dst, regT0, (op == dst)); + return; + } + + emitLoad2(op1, regT1, regT0, op2, regT3, regT2); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + and32(regT2, regT0); + emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); +} + +void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // int32 check + + JITStubCall stubCall(this, cti_op_bitand); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(dst); +} + +// BitOr (|) + +void JIT::emit_op_bitor(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + unsigned op; + int32_t constant; + if (getOperandConstantImmediateInt(op1, op2, op, constant)) { + emitLoad(op, regT1, regT0); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + or32(Imm32(constant), regT0); + emitStoreInt32(dst, regT0, (op == dst)); + return; + } + + emitLoad2(op1, regT1, regT0, op2, regT3, regT2); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + or32(regT2, regT0); + emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); +} + +void JIT::emitSlow_op_bitor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // int32 check + + JITStubCall stubCall(this, cti_op_bitor); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(dst); +} + +// BitXor (^) + +void JIT::emit_op_bitxor(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + unsigned op; + int32_t constant; + if (getOperandConstantImmediateInt(op1, op2, op, constant)) { + emitLoad(op, regT1, regT0); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + xor32(Imm32(constant), regT0); + emitStoreInt32(dst, regT0, (op == dst)); + return; + } + + emitLoad2(op1, regT1, regT0, op2, regT3, regT2); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + xor32(regT2, regT0); + emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); +} + +void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // int32 check + + JITStubCall stubCall(this, cti_op_bitxor); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(dst); +} + +// BitNot (~) + +void JIT::emit_op_bitnot(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned src = currentInstruction[2].u.operand; + + emitLoad(src, regT1, regT0); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + + not32(regT0); + emitStoreInt32(dst, regT0, (dst == src)); +} + +void JIT::emitSlow_op_bitnot(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + + linkSlowCase(iter); // int32 check + + JITStubCall stubCall(this, cti_op_bitnot); + stubCall.addArgument(regT1, regT0); + stubCall.call(dst); +} + +// PostInc (i++) + +void JIT::emit_op_post_inc(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned srcDst = currentInstruction[2].u.operand; + + emitLoad(srcDst, regT1, regT0); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + + if (dst == srcDst) // x = x++ is a noop for ints. + return; + + emitStoreInt32(dst, regT0); + + addSlowCase(branchAdd32(Overflow, Imm32(1), regT0)); + emitStoreInt32(srcDst, regT0, true); +} + +void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned srcDst = currentInstruction[2].u.operand; + + linkSlowCase(iter); // int32 check + if (dst != srcDst) + linkSlowCase(iter); // overflow check + + JITStubCall stubCall(this, cti_op_post_inc); + stubCall.addArgument(srcDst); + stubCall.addArgument(Imm32(srcDst)); + stubCall.call(dst); +} + +// PostDec (i--) + +void JIT::emit_op_post_dec(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned srcDst = currentInstruction[2].u.operand; + + emitLoad(srcDst, regT1, regT0); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + + if (dst == srcDst) // x = x-- is a noop for ints. + return; + + emitStoreInt32(dst, regT0); + + addSlowCase(branchSub32(Overflow, Imm32(1), regT0)); + emitStoreInt32(srcDst, regT0, true); +} + +void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned srcDst = currentInstruction[2].u.operand; + + linkSlowCase(iter); // int32 check + if (dst != srcDst) + linkSlowCase(iter); // overflow check + + JITStubCall stubCall(this, cti_op_post_dec); + stubCall.addArgument(srcDst); + stubCall.addArgument(Imm32(srcDst)); + stubCall.call(dst); +} + +// PreInc (++i) + +void JIT::emit_op_pre_inc(Instruction* currentInstruction) +{ + unsigned srcDst = currentInstruction[1].u.operand; + + emitLoad(srcDst, regT1, regT0); + + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branchAdd32(Overflow, Imm32(1), regT0)); + emitStoreInt32(srcDst, regT0, true); +} + +void JIT::emitSlow_op_pre_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned srcDst = currentInstruction[1].u.operand; + + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // overflow check + + JITStubCall stubCall(this, cti_op_pre_inc); + stubCall.addArgument(srcDst); + stubCall.call(srcDst); +} + +// PreDec (--i) + +void JIT::emit_op_pre_dec(Instruction* currentInstruction) +{ + unsigned srcDst = currentInstruction[1].u.operand; + + emitLoad(srcDst, regT1, regT0); + + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branchSub32(Overflow, Imm32(1), regT0)); + emitStoreInt32(srcDst, regT0, true); +} + +void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned srcDst = currentInstruction[1].u.operand; + + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // overflow check + + JITStubCall stubCall(this, cti_op_pre_dec); + stubCall.addArgument(srcDst); + stubCall.call(srcDst); +} + +// Addition (+) + +void JIT::emit_op_add(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); + + if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) { + JITStubCall stubCall(this, cti_op_add); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(dst); + return; + } + + JumpList notInt32Op1; + JumpList notInt32Op2; + + unsigned op; + int32_t constant; + if (getOperandConstantImmediateInt(op1, op2, op, constant)) { + emitAdd32Constant(dst, op, constant, op == op1 ? types.first() : types.second()); + return; + } + + emitLoad2(op1, regT1, regT0, op2, regT3, regT2); + notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + + // Int32 case. + addSlowCase(branchAdd32(Overflow, regT2, regT0)); + emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); + + if (!supportsFloatingPoint()) { + addSlowCase(notInt32Op1); + addSlowCase(notInt32Op2); + return; + } + Jump end = jump(); + + // Double case. + emitBinaryDoubleOp(op_add, dst, op1, op2, types, notInt32Op1, notInt32Op2); + end.link(this); +} + +void JIT::emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType) +{ + // Int32 case. + emitLoad(op, regT1, regT0); + Jump notInt32 = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); + addSlowCase(branchAdd32(Overflow, Imm32(constant), regT0)); + emitStoreInt32(dst, regT0, (op == dst)); + + // Double case. + if (!supportsFloatingPoint()) { + addSlowCase(notInt32); + return; + } + Jump end = jump(); + + notInt32.link(this); + if (!opType.definitelyIsNumber()) + addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); + move(Imm32(constant), regT2); + convertInt32ToDouble(regT2, fpRegT0); + emitLoadDouble(op, fpRegT1); + addDouble(fpRegT1, fpRegT0); + emitStoreDouble(dst, fpRegT0); + + end.link(this); +} + +void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); + + if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) + return; + + unsigned op; + int32_t constant; + if (getOperandConstantImmediateInt(op1, op2, op, constant)) { + linkSlowCase(iter); // overflow check + + if (!supportsFloatingPoint()) + linkSlowCase(iter); // non-sse case + else { + ResultType opType = op == op1 ? types.first() : types.second(); + if (!opType.definitelyIsNumber()) + linkSlowCase(iter); // double check + } + } else { + linkSlowCase(iter); // overflow check + + if (!supportsFloatingPoint()) { + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // int32 check + } else { + if (!types.first().definitelyIsNumber()) + linkSlowCase(iter); // double check + + if (!types.second().definitelyIsNumber()) { + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // double check + } + } + } + + JITStubCall stubCall(this, cti_op_add); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(dst); +} + +// Subtraction (-) + +void JIT::emit_op_sub(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); + + JumpList notInt32Op1; + JumpList notInt32Op2; + + if (isOperandConstantImmediateInt(op2)) { + emitSub32Constant(dst, op1, getConstantOperand(op2).asInt32(), types.first()); + return; + } + + emitLoad2(op1, regT1, regT0, op2, regT3, regT2); + notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + + // Int32 case. + addSlowCase(branchSub32(Overflow, regT2, regT0)); + emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); + + if (!supportsFloatingPoint()) { + addSlowCase(notInt32Op1); + addSlowCase(notInt32Op2); + return; + } + Jump end = jump(); + + // Double case. + emitBinaryDoubleOp(op_sub, dst, op1, op2, types, notInt32Op1, notInt32Op2); + end.link(this); +} + +void JIT::emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType) +{ + // Int32 case. + emitLoad(op, regT1, regT0); + Jump notInt32 = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); + addSlowCase(branchSub32(Overflow, Imm32(constant), regT0)); + emitStoreInt32(dst, regT0, (op == dst)); + + // Double case. + if (!supportsFloatingPoint()) { + addSlowCase(notInt32); + return; + } + Jump end = jump(); + + notInt32.link(this); + if (!opType.definitelyIsNumber()) + addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); + move(Imm32(constant), regT2); + convertInt32ToDouble(regT2, fpRegT0); + emitLoadDouble(op, fpRegT1); + subDouble(fpRegT0, fpRegT1); + emitStoreDouble(dst, fpRegT1); + + end.link(this); +} + +void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); + + if (isOperandConstantImmediateInt(op2)) { + linkSlowCase(iter); // overflow check + + if (!supportsFloatingPoint() || !types.first().definitelyIsNumber()) + linkSlowCase(iter); // int32 or double check + } else { + linkSlowCase(iter); // overflow check + + if (!supportsFloatingPoint()) { + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // int32 check + } else { + if (!types.first().definitelyIsNumber()) + linkSlowCase(iter); // double check + + if (!types.second().definitelyIsNumber()) { + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // double check + } + } + } + + JITStubCall stubCall(this, cti_op_sub); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(dst); +} + +void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsigned op2, OperandTypes types, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters, bool op2IsInRegisters) +{ + JumpList end; + + if (!notInt32Op1.empty()) { + // Double case 1: Op1 is not int32; Op2 is unknown. + notInt32Op1.link(this); + + ASSERT(op1IsInRegisters); + + // Verify Op1 is double. + if (!types.first().definitelyIsNumber()) + addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); + + if (!op2IsInRegisters) + emitLoad(op2, regT3, regT2); + + Jump doubleOp2 = branch32(Below, regT3, Imm32(JSValue::LowestTag)); + + if (!types.second().definitelyIsNumber()) + addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + + convertInt32ToDouble(regT2, fpRegT0); + Jump doTheMath = jump(); + + // Load Op2 as double into double register. + doubleOp2.link(this); + emitLoadDouble(op2, fpRegT0); + + // Do the math. + doTheMath.link(this); + switch (opcodeID) { + case op_mul: + emitLoadDouble(op1, fpRegT2); + mulDouble(fpRegT2, fpRegT0); + emitStoreDouble(dst, fpRegT0); + break; + case op_add: + emitLoadDouble(op1, fpRegT2); + addDouble(fpRegT2, fpRegT0); + emitStoreDouble(dst, fpRegT0); + break; + case op_sub: + emitLoadDouble(op1, fpRegT1); + subDouble(fpRegT0, fpRegT1); + emitStoreDouble(dst, fpRegT1); + break; + case op_div: + emitLoadDouble(op1, fpRegT1); + divDouble(fpRegT0, fpRegT1); + emitStoreDouble(dst, fpRegT1); + break; + case op_jnless: + emitLoadDouble(op1, fpRegT2); + addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT0, fpRegT2), dst); + break; + case op_jless: + emitLoadDouble(op1, fpRegT2); + addJump(branchDouble(DoubleLessThan, fpRegT2, fpRegT0), dst); + break; + case op_jlesseq: + emitLoadDouble(op1, fpRegT2); + addJump(branchDouble(DoubleLessThanOrEqual, fpRegT2, fpRegT0), dst); + break; + case op_jnlesseq: + emitLoadDouble(op1, fpRegT2); + addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT0, fpRegT2), dst); + break; + default: + ASSERT_NOT_REACHED(); + } + + if (!notInt32Op2.empty()) + end.append(jump()); + } + + if (!notInt32Op2.empty()) { + // Double case 2: Op1 is int32; Op2 is not int32. + notInt32Op2.link(this); + + ASSERT(op2IsInRegisters); + + if (!op1IsInRegisters) + emitLoadPayload(op1, regT0); + + convertInt32ToDouble(regT0, fpRegT0); + + // Verify op2 is double. + if (!types.second().definitelyIsNumber()) + addSlowCase(branch32(Above, regT3, Imm32(JSValue::LowestTag))); + + // Do the math. + switch (opcodeID) { + case op_mul: + emitLoadDouble(op2, fpRegT2); + mulDouble(fpRegT2, fpRegT0); + emitStoreDouble(dst, fpRegT0); + break; + case op_add: + emitLoadDouble(op2, fpRegT2); + addDouble(fpRegT2, fpRegT0); + emitStoreDouble(dst, fpRegT0); + break; + case op_sub: + emitLoadDouble(op2, fpRegT2); + subDouble(fpRegT2, fpRegT0); + emitStoreDouble(dst, fpRegT0); + break; + case op_div: + emitLoadDouble(op2, fpRegT2); + divDouble(fpRegT2, fpRegT0); + emitStoreDouble(dst, fpRegT0); + break; + case op_jnless: + emitLoadDouble(op2, fpRegT1); + addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), dst); + break; + case op_jless: + emitLoadDouble(op2, fpRegT1); + addJump(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), dst); + break; + case op_jnlesseq: + emitLoadDouble(op2, fpRegT1); + addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), dst); + break; + case op_jlesseq: + emitLoadDouble(op2, fpRegT1); + addJump(branchDouble(DoubleLessThanOrEqual, fpRegT1, fpRegT0), dst); + break; + default: + ASSERT_NOT_REACHED(); + } + } + + end.link(this); +} + +// Multiplication (*) + +void JIT::emit_op_mul(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); + + JumpList notInt32Op1; + JumpList notInt32Op2; + + emitLoad2(op1, regT1, regT0, op2, regT3, regT2); + notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + + // Int32 case. + move(regT0, regT3); + addSlowCase(branchMul32(Overflow, regT2, regT0)); + addSlowCase(branchTest32(Zero, regT0)); + emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); + + if (!supportsFloatingPoint()) { + addSlowCase(notInt32Op1); + addSlowCase(notInt32Op2); + return; + } + Jump end = jump(); + + // Double case. + emitBinaryDoubleOp(op_mul, dst, op1, op2, types, notInt32Op1, notInt32Op2); + end.link(this); +} + +void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); + + Jump overflow = getSlowCase(iter); // overflow check + linkSlowCase(iter); // zero result check + + Jump negZero = branchOr32(Signed, regT2, regT3); + emitStoreInt32(dst, Imm32(0), (op1 == dst || op2 == dst)); + + emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_mul)); + + negZero.link(this); + overflow.link(this); + + if (!supportsFloatingPoint()) { + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // int32 check + } + + if (supportsFloatingPoint()) { + if (!types.first().definitelyIsNumber()) + linkSlowCase(iter); // double check + + if (!types.second().definitelyIsNumber()) { + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // double check + } + } + + Label jitStubCall(this); + JITStubCall stubCall(this, cti_op_mul); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(dst); +} + +// Division (/) + +void JIT::emit_op_div(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); + + if (!supportsFloatingPoint()) { + addSlowCase(jump()); + return; + } + + // Int32 divide. + JumpList notInt32Op1; + JumpList notInt32Op2; + + JumpList end; + + emitLoad2(op1, regT1, regT0, op2, regT3, regT2); + + notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + + convertInt32ToDouble(regT0, fpRegT0); + convertInt32ToDouble(regT2, fpRegT1); + divDouble(fpRegT1, fpRegT0); + + JumpList doubleResult; + branchConvertDoubleToInt32(fpRegT0, regT0, doubleResult, fpRegT1); + + // Int32 result. + emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); + end.append(jump()); + + // Double result. + doubleResult.link(this); + emitStoreDouble(dst, fpRegT0); + end.append(jump()); + + // Double divide. + emitBinaryDoubleOp(op_div, dst, op1, op2, types, notInt32Op1, notInt32Op2); + end.link(this); +} + +void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); + + if (!supportsFloatingPoint()) + linkSlowCase(iter); + else { + if (!types.first().definitelyIsNumber()) + linkSlowCase(iter); // double check + + if (!types.second().definitelyIsNumber()) { + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // double check + } + } + + JITStubCall stubCall(this, cti_op_div); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(dst); +} + +// Mod (%) + +/* ------------------------------ BEGIN: OP_MOD ------------------------------ */ + +#if CPU(X86) || CPU(X86_64) + +void JIT::emit_op_mod(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) { + emitLoad(op1, X86Registers::edx, X86Registers::eax); + move(Imm32(getConstantOperand(op2).asInt32()), X86Registers::ecx); + addSlowCase(branch32(NotEqual, X86Registers::edx, Imm32(JSValue::Int32Tag))); + if (getConstantOperand(op2).asInt32() == -1) + addSlowCase(branch32(Equal, X86Registers::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC + } else { + emitLoad2(op1, X86Registers::edx, X86Registers::eax, op2, X86Registers::ebx, X86Registers::ecx); + addSlowCase(branch32(NotEqual, X86Registers::edx, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, X86Registers::ebx, Imm32(JSValue::Int32Tag))); + + addSlowCase(branch32(Equal, X86Registers::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC + addSlowCase(branch32(Equal, X86Registers::ecx, Imm32(0))); // divide by 0 + } + + move(X86Registers::eax, X86Registers::ebx); // Save dividend payload, in case of 0. + m_assembler.cdq(); + m_assembler.idivl_r(X86Registers::ecx); + + // If the remainder is zero and the dividend is negative, the result is -0. + Jump storeResult1 = branchTest32(NonZero, X86Registers::edx); + Jump storeResult2 = branchTest32(Zero, X86Registers::ebx, Imm32(0x80000000)); // not negative + emitStore(dst, jsNumber(m_globalData, -0.0)); + Jump end = jump(); + + storeResult1.link(this); + storeResult2.link(this); + emitStoreInt32(dst, X86Registers::edx, (op1 == dst || op2 == dst)); + end.link(this); +} + +void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + + if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) { + linkSlowCase(iter); // int32 check + if (getConstantOperand(op2).asInt32() == -1) + linkSlowCase(iter); // 0x80000000 check + } else { + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // 0 check + linkSlowCase(iter); // 0x80000000 check + } + + JITStubCall stubCall(this, cti_op_mod); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(dst); +} + +#else // CPU(X86) || CPU(X86_64) + +void JIT::emit_op_mod(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + +#if ENABLE(JIT_OPTIMIZE_MOD) + emitLoad2(op1, regT1, regT0, op2, regT3, regT2); + addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + + addSlowCase(branch32(Equal, regT2, Imm32(0))); + + emitNakedCall(m_globalData->jitStubs.ctiSoftModulo()); + + emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); +#else + JITStubCall stubCall(this, cti_op_mod); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(dst); +#endif +} + +void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ +#if ENABLE(JIT_OPTIMIZE_MOD) + unsigned result = currentInstruction[1].u.operand; + unsigned op1 = currentInstruction[2].u.operand; + unsigned op2 = currentInstruction[3].u.operand; + linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); + JITStubCall stubCall(this, cti_op_mod); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(result); +#else + ASSERT_NOT_REACHED(); +#endif +} + +#endif // CPU(X86) || CPU(X86_64) + +/* ------------------------------ END: OP_MOD ------------------------------ */ + +#endif // USE(JSVALUE32_64) + +} + +#endif // ENABLE(JIT) diff --git a/JavaScriptCore/jit/JITInlineMethods.h b/JavaScriptCore/jit/JITInlineMethods.h index 96a2e5b..892ab36 100644 --- a/JavaScriptCore/jit/JITInlineMethods.h +++ b/JavaScriptCore/jit/JITInlineMethods.h @@ -93,6 +93,16 @@ ALWAYS_INLINE void JIT::emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHea #endif } +ALWAYS_INLINE void JIT::emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures) +{ + failures.append(branchPtr(NotEqual, Address(src), ImmPtr(m_globalData->jsStringVPtr))); + failures.append(branchTest32(NonZero, Address(src, OBJECT_OFFSETOF(JSString, m_fiberCount)))); + failures.append(branch32(NotEqual, MacroAssembler::Address(src, ThunkHelpers::jsStringLengthOffset()), Imm32(1))); + loadPtr(MacroAssembler::Address(src, ThunkHelpers::jsStringValueOffset()), dst); + loadPtr(MacroAssembler::Address(dst, ThunkHelpers::stringImplDataOffset()), dst); + load16(MacroAssembler::Address(dst, 0), dst); +} + ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader32(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from) { load32(Address(from, entry * sizeof(Register)), to); @@ -323,23 +333,13 @@ ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock) #endif #endif -inline JIT::Address JIT::addressFor(unsigned index, RegisterID base) +ALWAYS_INLINE bool JIT::isOperandConstantImmediateChar(unsigned src) { - return Address(base, (index * sizeof(Register))); + return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isString() && asString(getConstantOperand(src).asCell())->length() == 1; } #if USE(JSVALUE32_64) -inline JIT::Address JIT::tagFor(unsigned index, RegisterID base) -{ - return Address(base, (index * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); -} - -inline JIT::Address JIT::payloadFor(unsigned index, RegisterID base) -{ - return Address(base, (index * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); -} - inline void JIT::emitLoadTag(unsigned index, RegisterID tag) { RegisterID mappedTag; @@ -560,7 +560,7 @@ inline bool JIT::getMappedTag(unsigned virtualRegisterIndex, RegisterID& tag) inline void JIT::emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex) { if (!m_codeBlock->isKnownNotImmediate(virtualRegisterIndex)) - addSlowCase(branch32(NotEqual, tagFor(virtualRegisterIndex), Imm32(JSValue::CellTag))); + addSlowCase(emitJumpIfNotJSCell(virtualRegisterIndex)); } inline void JIT::emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex, RegisterID tag) @@ -737,14 +737,6 @@ ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg, int vReg) } #if USE(JSVALUE64) -ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateNumber(RegisterID reg) -{ - return branchTestPtr(NonZero, reg, tagTypeNumberRegister); -} -ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateNumber(RegisterID reg) -{ - return branchTestPtr(Zero, reg, tagTypeNumberRegister); -} inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value) { diff --git a/JavaScriptCore/jit/JITOpcodes.cpp b/JavaScriptCore/jit/JITOpcodes.cpp index 0dd6a40..2ad79c6 100644 --- a/JavaScriptCore/jit/JITOpcodes.cpp +++ b/JavaScriptCore/jit/JITOpcodes.cpp @@ -400,7 +400,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable *executablePool = finalCode.m_executablePool; trampolines->ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin); - trampolines->ctiNativeCallThunk = trampolineAt(finalCode, nativeCallThunk); + trampolines->ctiNativeCallThunk = adoptRef(new NativeExecutable(JITCode(JITCode::HostFunction(trampolineAt(finalCode, nativeCallThunk))))); #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) trampolines->ctiStringLengthTrampoline = trampolineAt(finalCode, stringLengthBegin); #else @@ -1430,11 +1430,16 @@ void JIT::emit_op_new_error(Instruction* currentInstruction) void JIT::emit_op_debug(Instruction* currentInstruction) { +#if ENABLE(DEBUG_WITH_BREAKPOINT) + UNUSED_PARAM(currentInstruction); + breakpoint(); +#else JITStubCall stubCall(this, cti_op_debug); stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); stubCall.call(); +#endif } @@ -1937,7 +1942,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable trampolines->ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin); trampolines->ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin); - trampolines->ctiNativeCallThunk = trampolineAt(finalCode, nativeCallThunk); + trampolines->ctiNativeCallThunk = adoptRef(new NativeExecutable(JITCode(JITCode::HostFunction(trampolineAt(finalCode, nativeCallThunk))))); #if ENABLE(JIT_OPTIMIZE_MOD) trampolines->ctiSoftModulo = trampolineAt(finalCode, softModBegin); #endif @@ -2721,11 +2726,16 @@ void JIT::emit_op_new_error(Instruction* currentInstruction) void JIT::emit_op_debug(Instruction* currentInstruction) { +#if ENABLE(DEBUG_WITH_BREAKPOINT) + UNUSED_PARAM(currentInstruction); + breakpoint(); +#else JITStubCall stubCall(this, cti_op_debug); stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); stubCall.call(); +#endif } void JIT::emit_op_eq_null(Instruction* currentInstruction) diff --git a/JavaScriptCore/jit/JITStubCall.h b/JavaScriptCore/jit/JITStubCall.h index cfbd7dc..70d2893 100644 --- a/JavaScriptCore/jit/JITStubCall.h +++ b/JavaScriptCore/jit/JITStubCall.h @@ -116,13 +116,15 @@ namespace JSC { m_jit->poke(argument, m_stackIndex); m_stackIndex += stackIndexStep; } - + +#if USE(JSVALUE32_64) void addArgument(const JSValue& value) { m_jit->poke(JIT::Imm32(value.payload()), m_stackIndex); m_jit->poke(JIT::Imm32(value.tag()), m_stackIndex + 1); m_stackIndex += stackIndexStep; } +#endif void addArgument(JIT::RegisterID tag, JIT::RegisterID payload) { diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp index c32f2ce..ebd26bb 100644 --- a/JavaScriptCore/jit/JITStubs.cpp +++ b/JavaScriptCore/jit/JITStubs.cpp @@ -578,6 +578,9 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" #elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL) +#define THUNK_RETURN_ADDRESS_OFFSET 32 +#define PRESERVEDR4_OFFSET 36 + __asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, JSValue*, Profiler**, JSGlobalData*) { ARM @@ -835,6 +838,10 @@ JITThunks::JITThunks(JSGlobalData* globalData) #endif } +JITThunks::~JITThunks() +{ +} + #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo) @@ -3300,6 +3307,15 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, to_object) return JSValue::encode(stackFrame.args[0].jsValue().toObject(callFrame)); } +NativeExecutable* JITThunks::specializedThunk(JSGlobalData* globalData, ThunkGenerator generator) +{ + std::pair<ThunkMap::iterator, bool> entry = m_thunkMap.add(generator, 0); + if (!entry.second) + return entry.first->second.get(); + entry.first->second = generator(globalData, m_executablePool.get()); + return entry.first->second.get(); +} + } // namespace JSC #endif // ENABLE(JIT) diff --git a/JavaScriptCore/jit/JITStubs.h b/JavaScriptCore/jit/JITStubs.h index f419c8c..fe4bcfb 100644 --- a/JavaScriptCore/jit/JITStubs.h +++ b/JavaScriptCore/jit/JITStubs.h @@ -31,6 +31,8 @@ #include "MacroAssemblerCodeRef.h" #include "Register.h" +#include "ThunkGenerators.h" +#include <wtf/HashMap.h> #if ENABLE(JIT) @@ -43,16 +45,16 @@ namespace JSC { class FunctionExecutable; class Identifier; class JSGlobalData; - class JSGlobalData; + class JSGlobalObject; class JSObject; class JSPropertyNameIterator; class JSValue; class JSValueEncodedAsPointer; + class NativeExecutable; class Profiler; class PropertySlot; class PutPropertySlot; class RegisterFile; - class JSGlobalObject; class RegExp; union JITStubArg { @@ -77,7 +79,7 @@ namespace JSC { MacroAssemblerCodePtr ctiStringLengthTrampoline; MacroAssemblerCodePtr ctiVirtualCallLink; MacroAssemblerCodePtr ctiVirtualCall; - MacroAssemblerCodePtr ctiNativeCallThunk; + RefPtr<NativeExecutable> ctiNativeCallThunk; MacroAssemblerCodePtr ctiSoftModulo; }; @@ -265,6 +267,7 @@ namespace JSC { class JITThunks { public: JITThunks(JSGlobalData*); + ~JITThunks(); static void tryCacheGetByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot&, StructureStubInfo* stubInfo); static void tryCachePutByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot&, StructureStubInfo* stubInfo); @@ -272,10 +275,13 @@ namespace JSC { MacroAssemblerCodePtr ctiStringLengthTrampoline() { return m_trampolineStructure.ctiStringLengthTrampoline; } MacroAssemblerCodePtr ctiVirtualCallLink() { return m_trampolineStructure.ctiVirtualCallLink; } MacroAssemblerCodePtr ctiVirtualCall() { return m_trampolineStructure.ctiVirtualCall; } - MacroAssemblerCodePtr ctiNativeCallThunk() { return m_trampolineStructure.ctiNativeCallThunk; } + NativeExecutable* ctiNativeCallThunk() { return m_trampolineStructure.ctiNativeCallThunk.get(); } MacroAssemblerCodePtr ctiSoftModulo() { return m_trampolineStructure.ctiSoftModulo; } + NativeExecutable* specializedThunk(JSGlobalData* globalData, ThunkGenerator generator); private: + typedef HashMap<ThunkGenerator, RefPtr<NativeExecutable> > ThunkMap; + ThunkMap m_thunkMap; RefPtr<ExecutablePool> m_executablePool; TrampolineStructure m_trampolineStructure; diff --git a/JavaScriptCore/jit/JSInterfaceJIT.h b/JavaScriptCore/jit/JSInterfaceJIT.h new file mode 100644 index 0000000..2cd0e33 --- /dev/null +++ b/JavaScriptCore/jit/JSInterfaceJIT.h @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2010 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 INC. 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 INC. 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 JSInterfaceJIT_h +#define JSInterfaceJIT_h + +#include "JITCode.h" +#include "JITStubs.h" +#include "JSImmediate.h" +#include "MacroAssembler.h" +#include "RegisterFile.h" +#include <wtf/AlwaysInline.h> +#include <wtf/Vector.h> + +namespace JSC { + class JSInterfaceJIT : public MacroAssembler { + public: + // NOTES: + // + // regT0 has two special meanings. The return value from a stub + // call will always be in regT0, and by default (unless + // a register is specified) emitPutVirtualRegister() will store + // the value from regT0. + // + // regT3 is required to be callee-preserved. + // + // tempRegister2 is has no such dependencies. It is important that + // on x86/x86-64 it is ecx for performance reasons, since the + // MacroAssembler will need to plant register swaps if it is not - + // however the code will still function correctly. +#if CPU(X86_64) + static const RegisterID returnValueRegister = X86Registers::eax; + static const RegisterID cachedResultRegister = X86Registers::eax; + static const RegisterID firstArgumentRegister = X86Registers::edi; + + static const RegisterID timeoutCheckRegister = X86Registers::r12; + static const RegisterID callFrameRegister = X86Registers::r13; + static const RegisterID tagTypeNumberRegister = X86Registers::r14; + static const RegisterID tagMaskRegister = X86Registers::r15; + + static const RegisterID regT0 = X86Registers::eax; + static const RegisterID regT1 = X86Registers::edx; + static const RegisterID regT2 = X86Registers::ecx; + static const RegisterID regT3 = X86Registers::ebx; + + static const FPRegisterID fpRegT0 = X86Registers::xmm0; + static const FPRegisterID fpRegT1 = X86Registers::xmm1; + static const FPRegisterID fpRegT2 = X86Registers::xmm2; + static const FPRegisterID fpRegT3 = X86Registers::xmm3; +#elif CPU(X86) + static const RegisterID returnValueRegister = X86Registers::eax; + static const RegisterID cachedResultRegister = X86Registers::eax; + // On x86 we always use fastcall conventions = but on + // OS X if might make more sense to just use regparm. + static const RegisterID firstArgumentRegister = X86Registers::ecx; + + static const RegisterID timeoutCheckRegister = X86Registers::esi; + static const RegisterID callFrameRegister = X86Registers::edi; + + static const RegisterID regT0 = X86Registers::eax; + static const RegisterID regT1 = X86Registers::edx; + static const RegisterID regT2 = X86Registers::ecx; + static const RegisterID regT3 = X86Registers::ebx; + + static const FPRegisterID fpRegT0 = X86Registers::xmm0; + static const FPRegisterID fpRegT1 = X86Registers::xmm1; + static const FPRegisterID fpRegT2 = X86Registers::xmm2; + static const FPRegisterID fpRegT3 = X86Registers::xmm3; +#elif CPU(ARM_THUMB2) + static const RegisterID returnValueRegister = ARMRegisters::r0; + static const RegisterID cachedResultRegister = ARMRegisters::r0; + static const RegisterID firstArgumentRegister = ARMRegisters::r0; + + static const RegisterID regT0 = ARMRegisters::r0; + static const RegisterID regT1 = ARMRegisters::r1; + static const RegisterID regT2 = ARMRegisters::r2; + static const RegisterID regT3 = ARMRegisters::r4; + + static const RegisterID callFrameRegister = ARMRegisters::r5; + static const RegisterID timeoutCheckRegister = ARMRegisters::r6; + + static const FPRegisterID fpRegT0 = ARMRegisters::d0; + static const FPRegisterID fpRegT1 = ARMRegisters::d1; + static const FPRegisterID fpRegT2 = ARMRegisters::d2; + static const FPRegisterID fpRegT3 = ARMRegisters::d3; +#elif CPU(ARM_TRADITIONAL) + static const RegisterID returnValueRegister = ARMRegisters::r0; + static const RegisterID cachedResultRegister = ARMRegisters::r0; + static const RegisterID firstArgumentRegister = ARMRegisters::r0; + + static const RegisterID timeoutCheckRegister = ARMRegisters::r5; + static const RegisterID callFrameRegister = ARMRegisters::r4; + + static const RegisterID regT0 = ARMRegisters::r0; + static const RegisterID regT1 = ARMRegisters::r1; + static const RegisterID regT2 = ARMRegisters::r2; + // Callee preserved + static const RegisterID regT3 = ARMRegisters::r7; + + static const RegisterID regS0 = ARMRegisters::S0; + // Callee preserved + static const RegisterID regS1 = ARMRegisters::S1; + + static const RegisterID regStackPtr = ARMRegisters::sp; + static const RegisterID regLink = ARMRegisters::lr; + + static const FPRegisterID fpRegT0 = ARMRegisters::d0; + static const FPRegisterID fpRegT1 = ARMRegisters::d1; + static const FPRegisterID fpRegT2 = ARMRegisters::d2; + static const FPRegisterID fpRegT3 = ARMRegisters::d3; +#elif CPU(MIPS) + static const RegisterID returnValueRegister = MIPSRegisters::v0; + static const RegisterID cachedResultRegister = MIPSRegisters::v0; + static const RegisterID firstArgumentRegister = MIPSRegisters::a0; + + // regT0 must be v0 for returning a 32-bit value. + static const RegisterID regT0 = MIPSRegisters::v0; + + // regT1 must be v1 for returning a pair of 32-bit value. + static const RegisterID regT1 = MIPSRegisters::v1; + + static const RegisterID regT2 = MIPSRegisters::t4; + + // regT3 must be saved in the callee, so use an S register. + static const RegisterID regT3 = MIPSRegisters::s2; + + static const RegisterID callFrameRegister = MIPSRegisters::s0; + static const RegisterID timeoutCheckRegister = MIPSRegisters::s1; + + static const FPRegisterID fpRegT0 = MIPSRegisters::f4; + static const FPRegisterID fpRegT1 = MIPSRegisters::f6; + static const FPRegisterID fpRegT2 = MIPSRegisters::f8; + static const FPRegisterID fpRegT2 = MIPSRegisters::f10; +#else +#error "JIT not supported on this platform." +#endif + + inline Jump emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID payload); + inline Jump emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst); + inline Jump emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch); + +#if USE(JSVALUE32_64) + inline Jump emitJumpIfNotJSCell(unsigned virtualRegisterIndex); + inline Address tagFor(unsigned index, RegisterID base = callFrameRegister); +#endif + +#if USE(JSVALUE32) || USE(JSVALUE64) + Jump emitJumpIfImmediateNumber(RegisterID reg); + Jump emitJumpIfNotImmediateNumber(RegisterID reg); +#endif + + inline Address payloadFor(unsigned index, RegisterID base = callFrameRegister); + inline Address addressFor(unsigned index, RegisterID base = callFrameRegister); + }; + + struct ThunkHelpers { + static unsigned stringImplDataOffset() { return WebCore::StringImpl::dataOffset(); } + static unsigned jsStringLengthOffset() { return OBJECT_OFFSETOF(JSString, m_length); } + static unsigned jsStringValueOffset() { return OBJECT_OFFSETOF(JSString, m_value); } + }; + +#if USE(JSVALUE32_64) + inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID payload) + { + loadPtr(payloadFor(virtualRegisterIndex), payload); + return emitJumpIfNotJSCell(virtualRegisterIndex); + } + + inline JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotJSCell(unsigned virtualRegisterIndex) + { + return branch32(NotEqual, tagFor(virtualRegisterIndex), Imm32(JSValue::CellTag)); + } + + inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst) + { + loadPtr(payloadFor(virtualRegisterIndex), dst); + return branch32(NotEqual, tagFor(virtualRegisterIndex), Imm32(JSValue::Int32Tag)); + } + + inline JSInterfaceJIT::Address JSInterfaceJIT::tagFor(unsigned index, RegisterID base) + { + return Address(base, (index * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); + } + + inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(unsigned index, RegisterID base) + { + return Address(base, (index * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); + } + + inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch) + { + loadPtr(tagFor(virtualRegisterIndex), scratch); + Jump isDouble = branch32(Below, scratch, Imm32(JSValue::LowestTag)); + Jump notInt = branch32(NotEqual, scratch, Imm32(JSValue::Int32Tag)); + loadPtr(payloadFor(virtualRegisterIndex), scratch); + convertInt32ToDouble(scratch, dst); + Jump done = jump(); + isDouble.link(this); + loadDouble(addressFor(virtualRegisterIndex), dst); + done.link(this); + return notInt; + } +#endif + +#if USE(JSVALUE64) + ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfImmediateNumber(RegisterID reg) + { + return branchTestPtr(NonZero, reg, tagTypeNumberRegister); + } + ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotImmediateNumber(RegisterID reg) + { + return branchTestPtr(Zero, reg, tagTypeNumberRegister); + } + inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID dst) + { + loadPtr(addressFor(virtualRegisterIndex), dst); + return branchTestPtr(NonZero, dst, tagMaskRegister); + } + + inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst) + { + loadPtr(addressFor(virtualRegisterIndex), dst); + Jump result = branchPtr(Below, dst, tagTypeNumberRegister); + zeroExtend32ToPtr(dst, dst); + return result; + } + + inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch) + { + loadPtr(addressFor(virtualRegisterIndex), scratch); + Jump notNumber = emitJumpIfNotImmediateNumber(scratch); + Jump notInt = branchPtr(Below, scratch, tagTypeNumberRegister); + convertInt32ToDouble(scratch, dst); + Jump done = jump(); + notInt.link(this); + addPtr(tagTypeNumberRegister, scratch); + movePtrToDouble(scratch, dst); + done.link(this); + return notNumber; + } + +#endif + +#if USE(JSVALUE32) + inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID dst) + { + loadPtr(addressFor(virtualRegisterIndex), dst); + return branchTest32(NonZero, dst, Imm32(JSImmediate::TagMask)); + } + + inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst) + { + loadPtr(addressFor(virtualRegisterIndex), dst); + Jump result = branchTest32(Zero, dst, Imm32(JSImmediate::TagTypeNumber)); + rshift32(Imm32(JSImmediate::IntegerPayloadShift), dst); + return result; + } + + inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned, FPRegisterID, RegisterID) + { + ASSERT_NOT_REACHED(); + return jump(); + } +#endif + +#if !USE(JSVALUE32_64) + inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(unsigned index, RegisterID base) + { + return addressFor(index, base); + } +#endif + + inline JSInterfaceJIT::Address JSInterfaceJIT::addressFor(unsigned index, RegisterID base) + { + return Address(base, (index * sizeof(Register))); + } + +} + +#endif // JSInterfaceJIT_h diff --git a/JavaScriptCore/jit/SpecializedThunkJIT.h b/JavaScriptCore/jit/SpecializedThunkJIT.h new file mode 100644 index 0000000..e41411d --- /dev/null +++ b/JavaScriptCore/jit/SpecializedThunkJIT.h @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2010 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 INC. 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 INC. 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 SpecializedThunkJIT_h +#define SpecializedThunkJIT_h + +#if ENABLE(JIT) + +#include "Executable.h" +#include "JSInterfaceJIT.h" +#include "LinkBuffer.h" + +namespace JSC { + + class SpecializedThunkJIT : public JSInterfaceJIT { + public: + static const int ThisArgument = -1; + SpecializedThunkJIT(int expectedArgCount, JSGlobalData* globalData, ExecutablePool* pool) + : m_expectedArgCount(expectedArgCount) + , m_globalData(globalData) + , m_pool(pool) + { + // Check that we have the expected number of arguments + m_failures.append(branch32(NotEqual, Address(callFrameRegister, RegisterFile::ArgumentCount * (int)sizeof(Register)), Imm32(expectedArgCount + 1))); + } + + void loadDoubleArgument(int argument, FPRegisterID dst, RegisterID scratch) + { + unsigned src = argumentToVirtualRegister(argument); + m_failures.append(emitLoadDouble(src, dst, scratch)); + } + + void loadCellArgument(int argument, RegisterID dst) + { + unsigned src = argumentToVirtualRegister(argument); + m_failures.append(emitLoadJSCell(src, dst)); + } + + void loadJSStringArgument(int argument, RegisterID dst) + { + loadCellArgument(argument, dst); + m_failures.append(branchPtr(NotEqual, Address(dst, 0), ImmPtr(m_globalData->jsStringVPtr))); + m_failures.append(branchTest32(NonZero, Address(dst, OBJECT_OFFSETOF(JSString, m_fiberCount)))); + } + + void loadInt32Argument(int argument, RegisterID dst, Jump& failTarget) + { + unsigned src = argumentToVirtualRegister(argument); + failTarget = emitLoadInt32(src, dst); + } + + void loadInt32Argument(int argument, RegisterID dst) + { + Jump conversionFailed; + loadInt32Argument(argument, dst, conversionFailed); + m_failures.append(conversionFailed); + } + + void appendFailure(const Jump& failure) + { + m_failures.append(failure); + } + + void returnJSValue(RegisterID src) + { + if (src != regT0) + move(src, regT0); + loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister); + ret(); + } + + void returnDouble(FPRegisterID src) + { +#if USE(JSVALUE64) + moveDoubleToPtr(src, regT0); + subPtr(tagTypeNumberRegister, regT0); +#elif USE(JSVALUE32_64) + storeDouble(src, Address(stackPointerRegister, -(int)sizeof(double))); + loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.tag) - sizeof(double)), regT1); + loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.payload) - sizeof(double)), regT0); +#else + UNUSED_PARAM(src); + ASSERT_NOT_REACHED(); + m_failures.append(jump()); +#endif + loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister); + ret(); + } + + void returnInt32(RegisterID src) + { + if (src != regT0) + move(src, regT0); + tagReturnAsInt32(); + loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister); + ret(); + } + + void returnJSCell(RegisterID src) + { + if (src != regT0) + move(src, regT0); + tagReturnAsJSCell(); + loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister); + ret(); + } + + PassRefPtr<NativeExecutable> finalize() + { + LinkBuffer patchBuffer(this, m_pool.get()); + patchBuffer.link(m_failures, CodeLocationLabel(m_globalData->jitStubs.ctiNativeCallThunk()->generatedJITCode().addressForCall())); + return adoptRef(new NativeExecutable(patchBuffer.finalizeCode())); + } + + private: + int argumentToVirtualRegister(unsigned argument) + { + return -static_cast<int>(RegisterFile::CallFrameHeaderSize + (m_expectedArgCount - argument)); + } + + void tagReturnAsInt32() + { +#if USE(JSVALUE64) + orPtr(tagTypeNumberRegister, regT0); +#elif USE(JSVALUE32_64) + move(Imm32(JSValue::Int32Tag), regT1); +#else + signExtend32ToPtr(regT0, regT0); + // If we can't tag the result, give up and jump to the slow case + m_failures.append(branchAddPtr(Overflow, regT0, regT0)); + addPtr(Imm32(JSImmediate::TagTypeNumber), regT0); +#endif + } + + void tagReturnAsJSCell() + { +#if USE(JSVALUE32_64) + move(Imm32(JSValue::CellTag), regT1); +#endif + } + + int m_expectedArgCount; + JSGlobalData* m_globalData; + RefPtr<ExecutablePool> m_pool; + MacroAssembler::JumpList m_failures; + }; + +} + +#endif // ENABLE(JIT) + +#endif // SpecializedThunkJIT_h diff --git a/JavaScriptCore/jit/ThunkGenerators.cpp b/JavaScriptCore/jit/ThunkGenerators.cpp new file mode 100644 index 0000000..c625c3d --- /dev/null +++ b/JavaScriptCore/jit/ThunkGenerators.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2010 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 INC. 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 INC. 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 "ThunkGenerators.h" +#include <wtf/text/StringImpl.h> + +#include "SpecializedThunkJIT.h" + +#if ENABLE(JIT) + +namespace JSC { + +static void stringCharLoad(SpecializedThunkJIT& jit) +{ + // load string + jit.loadJSStringArgument(SpecializedThunkJIT::ThisArgument, SpecializedThunkJIT::regT0); + // regT0 now contains this, and is a non-rope JSString* + + // Load string length to regT2, and start the process of loading the data pointer into regT0 + jit.load32(MacroAssembler::Address(SpecializedThunkJIT::regT0, ThunkHelpers::jsStringLengthOffset()), SpecializedThunkJIT::regT2); + jit.loadPtr(MacroAssembler::Address(SpecializedThunkJIT::regT0, ThunkHelpers::jsStringValueOffset()), SpecializedThunkJIT::regT0); + jit.loadPtr(MacroAssembler::Address(SpecializedThunkJIT::regT0, ThunkHelpers::stringImplDataOffset()), SpecializedThunkJIT::regT0); + + // load index + jit.loadInt32Argument(0, SpecializedThunkJIT::regT1); // regT1 contains the index + + // Do an unsigned compare to simultaneously filter negative indices as well as indices that are too large + jit.appendFailure(jit.branch32(MacroAssembler::AboveOrEqual, SpecializedThunkJIT::regT1, SpecializedThunkJIT::regT2)); + + // Load the character + jit.load16(MacroAssembler::BaseIndex(SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1, MacroAssembler::TimesTwo, 0), SpecializedThunkJIT::regT0); +} + +static void charToString(SpecializedThunkJIT& jit, JSGlobalData* globalData, MacroAssembler::RegisterID src, MacroAssembler::RegisterID dst, MacroAssembler::RegisterID scratch) +{ + jit.appendFailure(jit.branch32(MacroAssembler::AboveOrEqual, src, MacroAssembler::Imm32(0x100))); + jit.move(MacroAssembler::ImmPtr(globalData->smallStrings.singleCharacterStrings()), scratch); + jit.loadPtr(MacroAssembler::BaseIndex(scratch, src, MacroAssembler::ScalePtr, 0), dst); + jit.appendFailure(jit.branchTestPtr(MacroAssembler::Zero, dst)); +} + +PassRefPtr<NativeExecutable> charCodeAtThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) +{ + SpecializedThunkJIT jit(1, globalData, pool); + stringCharLoad(jit); + jit.returnInt32(SpecializedThunkJIT::regT0); + return jit.finalize(); +} + +PassRefPtr<NativeExecutable> charAtThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) +{ + SpecializedThunkJIT jit(1, globalData, pool); + stringCharLoad(jit); + charToString(jit, globalData, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1); + jit.returnJSCell(SpecializedThunkJIT::regT0); + return jit.finalize(); +} + +PassRefPtr<NativeExecutable> fromCharCodeThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) +{ + SpecializedThunkJIT jit(1, globalData, pool); + // load char code + jit.loadInt32Argument(0, SpecializedThunkJIT::regT0); + charToString(jit, globalData, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1); + jit.returnJSCell(SpecializedThunkJIT::regT0); + return jit.finalize(); +} + +PassRefPtr<NativeExecutable> sqrtThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) +{ +#if USE(JSVALUE64) || USE(JSVALUE32_64) + SpecializedThunkJIT jit(1, globalData, pool); + if (!jit.supportsFloatingPointSqrt()) + return globalData->jitStubs.ctiNativeCallThunk(); + + jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); + jit.sqrtDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0); + jit.returnDouble(SpecializedThunkJIT::fpRegT0); + return jit.finalize(); +#else + UNUSED_PARAM(pool); + return globalData->jitStubs.ctiNativeCallThunk(); +#endif +} + +static const double oneConstant = 1.0; +static const double negativeHalfConstant = -0.5; + +PassRefPtr<NativeExecutable> powThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) +{ +#if USE(JSVALUE64) || USE(JSVALUE32_64) + SpecializedThunkJIT jit(2, globalData, pool); + if (!jit.supportsFloatingPoint()) + return globalData->jitStubs.ctiNativeCallThunk(); + + jit.loadDouble(&oneConstant, SpecializedThunkJIT::fpRegT1); + jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); + MacroAssembler::Jump nonIntExponent; + jit.loadInt32Argument(1, SpecializedThunkJIT::regT0, nonIntExponent); + jit.appendFailure(jit.branch32(MacroAssembler::LessThan, SpecializedThunkJIT::regT0, MacroAssembler::Imm32(0))); + + MacroAssembler::Jump exponentIsZero = jit.branchTest32(MacroAssembler::Zero, SpecializedThunkJIT::regT0); + MacroAssembler::Label startLoop(jit.label()); + + MacroAssembler::Jump exponentIsEven = jit.branchTest32(MacroAssembler::Zero, SpecializedThunkJIT::regT0, MacroAssembler::Imm32(1)); + jit.mulDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1); + exponentIsEven.link(&jit); + jit.mulDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0); + jit.rshift32(MacroAssembler::Imm32(1), SpecializedThunkJIT::regT0); + jit.branchTest32(MacroAssembler::NonZero, SpecializedThunkJIT::regT0).linkTo(startLoop, &jit); + + exponentIsZero.link(&jit); + jit.returnDouble(SpecializedThunkJIT::fpRegT1); + + if (jit.supportsFloatingPointSqrt()) { + nonIntExponent.link(&jit); + jit.loadDouble(&negativeHalfConstant, SpecializedThunkJIT::fpRegT3); + jit.loadDoubleArgument(1, SpecializedThunkJIT::fpRegT2, SpecializedThunkJIT::regT0); + jit.appendFailure(jit.branchDouble(MacroAssembler::DoubleLessThanOrEqual, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1)); + jit.appendFailure(jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, SpecializedThunkJIT::fpRegT2, SpecializedThunkJIT::fpRegT3)); + jit.sqrtDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0); + jit.divDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1); + jit.returnDouble(SpecializedThunkJIT::fpRegT1); + } else + jit.appendFailure(nonIntExponent); + + return jit.finalize(); +#else + UNUSED_PARAM(pool); + return globalData->jitStubs.ctiNativeCallThunk(); +#endif +} + +} + +#endif // ENABLE(JIT) diff --git a/JavaScriptCore/jit/ThunkGenerators.h b/JavaScriptCore/jit/ThunkGenerators.h new file mode 100644 index 0000000..c3374f2 --- /dev/null +++ b/JavaScriptCore/jit/ThunkGenerators.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2010 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 INC. 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 INC. 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 ThunkGenerators_h +#define ThunkGenerators_h + +#if ENABLE(JIT) +#include <wtf/PassRefPtr.h> + +namespace JSC { + class ExecutablePool; + class JSGlobalData; + class NativeExecutable; + + typedef PassRefPtr<NativeExecutable> (*ThunkGenerator)(JSGlobalData*, ExecutablePool*); + PassRefPtr<NativeExecutable> charCodeAtThunkGenerator(JSGlobalData*, ExecutablePool*); + PassRefPtr<NativeExecutable> charAtThunkGenerator(JSGlobalData*, ExecutablePool*); + PassRefPtr<NativeExecutable> fromCharCodeThunkGenerator(JSGlobalData*, ExecutablePool*); + PassRefPtr<NativeExecutable> sqrtThunkGenerator(JSGlobalData*, ExecutablePool*); + PassRefPtr<NativeExecutable> powThunkGenerator(JSGlobalData*, ExecutablePool*); +} +#endif + +#endif // ThunkGenerator_h diff --git a/JavaScriptCore/qt/api/qscriptengine_p.h b/JavaScriptCore/qt/api/qscriptengine_p.h index 2bda68e..c6c64dd 100644 --- a/JavaScriptCore/qt/api/qscriptengine_p.h +++ b/JavaScriptCore/qt/api/qscriptengine_p.h @@ -35,7 +35,7 @@ class QScriptSyntaxCheckResultPrivate; class QScriptEnginePrivate : public QSharedData { public: - static QScriptEnginePtr get(const QScriptEngine* q) { Q_ASSERT(q); return q->d_ptr; } + static QScriptEnginePrivate* get(const QScriptEngine* q) { Q_ASSERT(q); return q->d_ptr.data(); } static QScriptEngine* get(const QScriptEnginePrivate* d) { Q_ASSERT(d); return d->q_ptr; } QScriptEnginePrivate(const QScriptEngine*); diff --git a/JavaScriptCore/qt/api/qscriptstring_p.h b/JavaScriptCore/qt/api/qscriptstring_p.h index f4fd117..d4fc88e 100644 --- a/JavaScriptCore/qt/api/qscriptstring_p.h +++ b/JavaScriptCore/qt/api/qscriptstring_p.h @@ -56,7 +56,7 @@ QScriptStringPrivate::QScriptStringPrivate() {} QScriptStringPrivate::QScriptStringPrivate(const QString& qtstring) - : m_string(JSStringRetain(QScriptConverter::toString(qtstring))) + : m_string(QScriptConverter::toString(qtstring)) {} QScriptStringPrivate::~QScriptStringPrivate() diff --git a/JavaScriptCore/qt/api/qscriptvalue.cpp b/JavaScriptCore/qt/api/qscriptvalue.cpp index 127fe04..f692817 100644 --- a/JavaScriptCore/qt/api/qscriptvalue.cpp +++ b/JavaScriptCore/qt/api/qscriptvalue.cpp @@ -115,8 +115,11 @@ QScriptValue::QScriptValue(QScriptValuePrivate* d) registers it with the script \a engine. */ QScriptValue::QScriptValue(QScriptEngine* engine, bool value) - : d_ptr(new QScriptValuePrivate(engine, value)) { + if (engine) + d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value); + else + d_ptr = new QScriptValuePrivate(value); } /*! @@ -126,8 +129,11 @@ QScriptValue::QScriptValue(QScriptEngine* engine, bool value) registers it with the script \a engine. */ QScriptValue::QScriptValue(QScriptEngine* engine, int value) - : d_ptr(new QScriptValuePrivate(engine, value)) { + if (engine) + d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value); + else + d_ptr = new QScriptValuePrivate(value); } /*! @@ -137,8 +143,11 @@ QScriptValue::QScriptValue(QScriptEngine* engine, int value) registers it with the script \a engine. */ QScriptValue::QScriptValue(QScriptEngine* engine, uint value) - : d_ptr(new QScriptValuePrivate(engine, value)) { + if (engine) + d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value); + else + d_ptr = new QScriptValuePrivate(value); } /*! @@ -148,8 +157,11 @@ QScriptValue::QScriptValue(QScriptEngine* engine, uint value) registers it with the script \a engine. */ QScriptValue::QScriptValue(QScriptEngine* engine, qsreal value) - : d_ptr(new QScriptValuePrivate(engine, value)) { + if (engine) + d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value); + else + d_ptr = new QScriptValuePrivate(value); } /*! @@ -159,8 +171,11 @@ QScriptValue::QScriptValue(QScriptEngine* engine, qsreal value) registers it with the script \a engine. */ QScriptValue::QScriptValue(QScriptEngine* engine, const QString& value) - : d_ptr(new QScriptValuePrivate(engine, value)) { + if (engine) + d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value); + else + d_ptr = new QScriptValuePrivate(value); } /*! @@ -170,8 +185,11 @@ QScriptValue::QScriptValue(QScriptEngine* engine, const QString& value) registers it with the script \a engine. */ QScriptValue::QScriptValue(QScriptEngine* engine, const char* value) - : d_ptr(new QScriptValuePrivate(engine, QString::fromUtf8(value))) { + if (engine) + d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), QString::fromUtf8(value)); + else + d_ptr = new QScriptValuePrivate(QString::fromUtf8(value)); } /*! @@ -181,8 +199,11 @@ QScriptValue::QScriptValue(QScriptEngine* engine, const char* value) registers it with the script \a engine. */ QScriptValue::QScriptValue(QScriptEngine* engine, SpecialValue value) - : d_ptr(new QScriptValuePrivate(engine, value)) { + if (engine) + d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value); + else + d_ptr = new QScriptValuePrivate(value); } /*! diff --git a/JavaScriptCore/qt/api/qscriptvalue_p.h b/JavaScriptCore/qt/api/qscriptvalue_p.h index 830b38e..03e8621 100644 --- a/JavaScriptCore/qt/api/qscriptvalue_p.h +++ b/JavaScriptCore/qt/api/qscriptvalue_p.h @@ -24,6 +24,7 @@ #include "qscriptengine_p.h" #include "qscriptvalue.h" #include <JavaScriptCore/JavaScript.h> +#include <JavaScriptCore/JSRetainPtr.h> #include <QtCore/qmath.h> #include <QtCore/qnumeric.h> #include <QtCore/qshareddata.h> @@ -76,12 +77,12 @@ public: inline QScriptValuePrivate(qsreal number); inline QScriptValuePrivate(QScriptValue::SpecialValue value); - inline QScriptValuePrivate(const QScriptEngine* engine, bool value); - inline QScriptValuePrivate(const QScriptEngine* engine, int value); - inline QScriptValuePrivate(const QScriptEngine* engine, uint value); - inline QScriptValuePrivate(const QScriptEngine* engine, qsreal value); - inline QScriptValuePrivate(const QScriptEngine* engine, const QString& value); - inline QScriptValuePrivate(const QScriptEngine* engine, QScriptValue::SpecialValue value); + inline QScriptValuePrivate(const QScriptEnginePrivate* engine, bool value); + inline QScriptValuePrivate(const QScriptEnginePrivate* engine, int value); + inline QScriptValuePrivate(const QScriptEnginePrivate* engine, uint value); + inline QScriptValuePrivate(const QScriptEnginePrivate* engine, qsreal value); + inline QScriptValuePrivate(const QScriptEnginePrivate* engine, const QString& value); + inline QScriptValuePrivate(const QScriptEnginePrivate* engine, QScriptValue::SpecialValue value); inline QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value); inline QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value, JSObjectRef object); @@ -209,94 +210,58 @@ QScriptValuePrivate::QScriptValuePrivate(QScriptValue::SpecialValue value) { } -QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, bool value) +QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, bool value) : m_state(JSPrimitive) + , m_engine(const_cast<QScriptEnginePrivate*>(engine)) + , m_value(engine->makeJSValue(value)) { - if (!engine) { - // slower path reinitialization - m_state = CBool; - m_number = value; - m_value = 0; - } else { - m_engine = QScriptEnginePrivate::get(engine); - m_value = m_engine->makeJSValue(value); - JSValueProtect(context(), m_value); - } + Q_ASSERT(engine); + JSValueProtect(context(), m_value); } -QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, int value) +QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, int value) : m_state(JSPrimitive) + , m_engine(const_cast<QScriptEnginePrivate*>(engine)) + , m_value(m_engine->makeJSValue(value)) { - if (!engine) { - // slower path reinitialization - m_state = CNumber; - m_number = value; - m_value = 0; - } else { - m_engine = QScriptEnginePrivate::get(engine); - m_value = m_engine->makeJSValue(value); - JSValueProtect(context(), m_value); - } + Q_ASSERT(engine); + JSValueProtect(context(), m_value); } -QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, uint value) +QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, uint value) : m_state(JSPrimitive) + , m_engine(const_cast<QScriptEnginePrivate*>(engine)) + , m_value(m_engine->makeJSValue(value)) { - if (!engine) { - // slower path reinitialization - m_state = CNumber; - m_number = value; - m_value = 0; - } else { - m_engine = QScriptEnginePrivate::get(engine); - m_value = m_engine->makeJSValue(value); - JSValueProtect(context(), m_value); - } + Q_ASSERT(engine); + JSValueProtect(context(), m_value); } -QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, qsreal value) +QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, qsreal value) : m_state(JSPrimitive) + , m_engine(const_cast<QScriptEnginePrivate*>(engine)) + , m_value(m_engine->makeJSValue(value)) { - if (!engine) { - // slower path reinitialization - m_state = CNumber; - m_number = value; - m_value = 0; - } else { - m_engine = QScriptEnginePrivate::get(engine); - m_value = m_engine->makeJSValue(value); - JSValueProtect(context(), m_value); - } + Q_ASSERT(engine); + JSValueProtect(context(), m_value); } -QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, const QString& value) +QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, const QString& value) : m_state(JSPrimitive) + , m_engine(const_cast<QScriptEnginePrivate*>(engine)) + , m_value(m_engine->makeJSValue(value)) { - if (!engine) { - // slower path reinitialization - m_state = CString; - m_string = value; - m_value = 0; - } else { - m_engine = QScriptEnginePrivate::get(engine); - m_value = m_engine->makeJSValue(value); - JSValueProtect(context(), m_value); - } + Q_ASSERT(engine); + JSValueProtect(context(), m_value); } -QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, QScriptValue::SpecialValue value) +QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, QScriptValue::SpecialValue value) : m_state(JSPrimitive) + , m_engine(const_cast<QScriptEnginePrivate*>(engine)) + , m_value(m_engine->makeJSValue(value)) { - if (!engine) { - // slower path reinitialization - m_state = CSpecial; - m_number = value; - m_value = 0; - } else { - m_engine = QScriptEnginePrivate::get(engine); - m_value = m_engine->makeJSValue(value); - JSValueProtect(context(), m_value); - } + Q_ASSERT(engine); + JSValueProtect(context(), m_value); } QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value) @@ -305,6 +270,7 @@ QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSV , m_value(value) { Q_ASSERT(engine); + Q_ASSERT(value); JSValueProtect(context(), m_value); } @@ -315,6 +281,8 @@ QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSV , m_object(object) { Q_ASSERT(engine); + Q_ASSERT(value); + Q_ASSERT(object); JSValueProtect(context(), m_value); } @@ -457,7 +425,8 @@ QString QScriptValuePrivate::toString() const case JSValue: case JSPrimitive: case JSObject: - return QScriptConverter::toString(JSValueToStringCopy(context(), value(), /* exception */ 0)); + JSRetainPtr<JSStringRef> ptr(Adopt, JSValueToStringCopy(context(), value(), /* exception */ 0)); + return QScriptConverter::toString(ptr.get()); } Q_ASSERT_X(false, "toString()", "Not all states are included in the previous switch statement."); diff --git a/JavaScriptCore/qt/api/qtscriptglobal.h b/JavaScriptCore/qt/api/qtscriptglobal.h index 29749c0..efdfc50 100644 --- a/JavaScriptCore/qt/api/qtscriptglobal.h +++ b/JavaScriptCore/qt/api/qtscriptglobal.h @@ -22,23 +22,22 @@ #include <QtCore/qglobal.h> -#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) -# if defined(QT_NODLL) -# elif defined(QT_MAKEDLL) /* create a Qt DLL library */ -# if defined(QT_BUILD_JAVASCRIPT_LIB) -# define Q_JAVASCRIPT_EXPORT Q_DECL_EXPORT -# else -# define Q_JAVASCRIPT_EXPORT Q_DECL_IMPORT -# endif -# elif defined(QT_DLL) /* use a Qt DLL library */ -# define Q_JAVASCRIPT_EXPORT +#if defined(QT_MAKEDLL) /* create a Qt DLL library */ +# if defined(QT_BUILD_JAVASCRIPT_LIB) +# define Q_JAVASCRIPT_EXPORT Q_DECL_EXPORT +# else +# define Q_JAVASCRIPT_EXPORT Q_DECL_IMPORT # endif +#elif defined(QT_DLL) /* use a Qt DLL library */ +# define Q_JAVASCRIPT_EXPORT #endif -#if defined(QT_SHARED) -# define Q_JAVASCRIPT_EXPORT Q_DECL_EXPORT -#else -# define Q_JAVASCRIPT_EXPORT +#if !defined(Q_JAVASCRIPT_EXPORT) +# if defined(QT_SHARED) +# define Q_JAVASCRIPT_EXPORT Q_DECL_EXPORT +# else +# define Q_JAVASCRIPT_EXPORT +# endif #endif #endif diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp index bd14e64..4c4eb48 100644 --- a/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -268,7 +268,24 @@ JSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue thi separator = args.at(0).toString(exec); unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - for (unsigned k = 0; k < length; k++) { + unsigned k = 0; + if (isJSArray(&exec->globalData(), thisObj)) { + JSArray* array = asArray(thisObj); + for (; k < length; k++) { + if (!array->canGetIndex(k)) + break; + if (k >= 1) { + if (separator.isNull()) + strBuffer.append(','); + else + strBuffer.append(separator); + } + JSValue element = array->getIndex(k); + if (!element.isUndefinedOrNull()) + strBuffer.append(element.toString(exec)); + } + } + for (; k < length; k++) { if (k >= 1) { if (separator.isNull()) strBuffer.append(','); diff --git a/JavaScriptCore/runtime/CachedTranscendentalFunction.h b/JavaScriptCore/runtime/CachedTranscendentalFunction.h new file mode 100644 index 0000000..04f7f62 --- /dev/null +++ b/JavaScriptCore/runtime/CachedTranscendentalFunction.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2010 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 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 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 CachedTranscendentalFunction_h +#define CachedTranscendentalFunction_h + +#include "JSValue.h" + +namespace JSC { + +extern const double NaN; + +typedef double (*TranscendentalFunctionPtr)(double); + +// CachedTranscendentalFunction provides a generic mechanism to cache results +// for pure functions with the signature "double func(double)", and where NaN +// maps to NaN. +template<TranscendentalFunctionPtr orignalFunction> +class CachedTranscendentalFunction { + struct CacheEntry { + double operand; + double result; + }; + +public: + CachedTranscendentalFunction() + : m_cache(0) + { + } + + ~CachedTranscendentalFunction() + { + if (m_cache) + fastFree(m_cache); + } + + JSValue operator() (ExecState* exec, double operand) + { + if (UNLIKELY(!m_cache)) + initialize(); + CacheEntry* entry = &m_cache[hash(operand)]; + + if (entry->operand == operand) + return jsDoubleNumber(exec, entry->result); + double result = orignalFunction(operand); + entry->operand = operand; + entry->result = result; + return jsDoubleNumber(exec, result); + } + +private: + void initialize() + { + // Lazily allocate the table, populate with NaN->NaN mapping. + m_cache = static_cast<CacheEntry*>(fastMalloc(s_cacheSize * sizeof(CacheEntry))); + for (unsigned x = 0; x < s_cacheSize; ++x) { + m_cache[x].operand = NaN; + m_cache[x].result = NaN; + } + } + + static unsigned hash(double d) + { + union doubleAndUInt64 { + double d; + uint32_t is[2]; + } u; + u.d = d; + + unsigned x = u.is[0] ^ u.is[1]; + x = (x >> 20) ^ (x >> 8); + return x & (s_cacheSize - 1); + } + + static const unsigned s_cacheSize = 0x1000; + CacheEntry* m_cache; +}; + +} + +#endif // CachedTranscendentalFunction_h diff --git a/JavaScriptCore/runtime/Collector.cpp b/JavaScriptCore/runtime/Collector.cpp index 9b72755..05f2bb5 100644 --- a/JavaScriptCore/runtime/Collector.cpp +++ b/JavaScriptCore/runtime/Collector.cpp @@ -449,7 +449,7 @@ void Heap::shrinkBlocks(size_t neededBlocks) } #if OS(WINCE) -void* g_stackBase = 0; +JS_EXPORTDATA void* g_stackBase = 0; inline bool isPageWritable(void* page) { @@ -558,6 +558,8 @@ static inline void* currentThreadStackBase() PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb()); return reinterpret_cast<void*>(pTib->StackBase); #elif OS(QNX) + AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); + MutexLocker locker(mutex); return currentThreadStackBaseQNX(); #elif OS(SOLARIS) stack_t s; @@ -569,19 +571,17 @@ static inline void* currentThreadStackBase() pthread_stackseg_np(thread, &stack); return stack.ss_sp; #elif OS(SYMBIAN) - static void* stackBase = 0; - if (stackBase == 0) { - TThreadStackInfo info; - RThread thread; - thread.StackInfo(info); - stackBase = (void*)info.iBase; - } - return (void*)stackBase; + TThreadStackInfo info; + RThread thread; + thread.StackInfo(info); + return (void*)info.iBase; #elif OS(HAIKU) thread_info threadInfo; get_thread_info(find_thread(NULL), &threadInfo); return threadInfo.stack_end; #elif OS(UNIX) + AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); + MutexLocker locker(mutex); static void* stackBase = 0; static size_t stackSize = 0; static pthread_t stackThread; @@ -604,6 +604,8 @@ static inline void* currentThreadStackBase() } return static_cast<char*>(stackBase) + stackSize; #elif OS(WINCE) + AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); + MutexLocker locker(mutex); if (g_stackBase) return g_stackBase; else { @@ -972,7 +974,7 @@ void Heap::markStackObjectsConservatively(MarkStack& markStack) void Heap::protect(JSValue k) { ASSERT(k); - ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance); + ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance()); if (!k.isCell()) return; @@ -983,7 +985,7 @@ void Heap::protect(JSValue k) bool Heap::unprotect(JSValue k) { ASSERT(k); - ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance); + ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance()); if (!k.isCell()) return false; @@ -1064,7 +1066,7 @@ void Heap::sweep() void Heap::markRoots() { #ifndef NDEBUG - if (m_globalData->isSharedInstance) { + if (m_globalData->isSharedInstance()) { ASSERT(JSLock::lockCount() > 0); ASSERT(JSLock::currentThreadIsHoldingLock()); } diff --git a/JavaScriptCore/runtime/Executable.h b/JavaScriptCore/runtime/Executable.h index f74abe9..ac691e4 100644 --- a/JavaScriptCore/runtime/Executable.h +++ b/JavaScriptCore/runtime/Executable.h @@ -85,7 +85,12 @@ namespace JSC { NativeExecutable(ExecState* exec) : ExecutableBase(NUM_PARAMETERS_IS_HOST) { - m_jitCode = JITCode(JITCode::HostFunction(exec->globalData().jitStubs.ctiNativeCallThunk())); + m_jitCode = exec->globalData().jitStubs.ctiNativeCallThunk()->m_jitCode; + } + NativeExecutable(JITCode thunk) + : ExecutableBase(NUM_PARAMETERS_IS_HOST) + { + m_jitCode = thunk; } ~NativeExecutable(); diff --git a/JavaScriptCore/runtime/JSActivation.h b/JavaScriptCore/runtime/JSActivation.h index 91c960c..ece8753 100644 --- a/JavaScriptCore/runtime/JSActivation.h +++ b/JavaScriptCore/runtime/JSActivation.h @@ -31,7 +31,6 @@ #include "CodeBlock.h" #include "JSVariableObject.h" -#include "RegisterFile.h" #include "SymbolTable.h" #include "Nodes.h" diff --git a/JavaScriptCore/runtime/JSFunction.cpp b/JavaScriptCore/runtime/JSFunction.cpp index cba6795..5b73642 100644 --- a/JavaScriptCore/runtime/JSFunction.cpp +++ b/JavaScriptCore/runtime/JSFunction.cpp @@ -56,10 +56,27 @@ JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure) { } +JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeExecutable* thunk, NativeFunction func) + : Base(&exec->globalData(), structure, name) +#if ENABLE(JIT) + , m_executable(thunk) +#endif +{ +#if ENABLE(JIT) + setNativeFunction(func); + putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum); +#else + UNUSED_PARAM(thunk); + UNUSED_PARAM(length); + UNUSED_PARAM(func); + ASSERT_NOT_REACHED(); +#endif +} + JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func) : Base(&exec->globalData(), structure, name) #if ENABLE(JIT) - , m_executable(adoptRef(new NativeExecutable(exec))) + , m_executable(exec->globalData().jitStubs.ctiNativeCallThunk()) #endif { #if ENABLE(JIT) diff --git a/JavaScriptCore/runtime/JSFunction.h b/JavaScriptCore/runtime/JSFunction.h index afa24a8..301b908 100644 --- a/JavaScriptCore/runtime/JSFunction.h +++ b/JavaScriptCore/runtime/JSFunction.h @@ -33,6 +33,7 @@ namespace JSC { class FunctionPrototype; class JSActivation; class JSGlobalObject; + class NativeExecutable; class JSFunction : public InternalFunction { friend class JIT; @@ -42,6 +43,7 @@ namespace JSC { public: JSFunction(ExecState*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeFunction); + JSFunction(ExecState*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeExecutable*, NativeFunction); JSFunction(ExecState*, NonNullPassRefPtr<FunctionExecutable>, ScopeChainNode*); virtual ~JSFunction(); diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp index 2948d1c..12fa2be 100644 --- a/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/JavaScriptCore/runtime/JSGlobalData.cpp @@ -103,8 +103,8 @@ void JSGlobalData::storeVPtrs() jsFunction->~JSCell(); } -JSGlobalData::JSGlobalData(bool isShared, ThreadStackType threadStackType) - : isSharedInstance(isShared) +JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType) + : globalDataType(globalDataType) , clientData(0) , arrayTable(fastNew<HashTable>(JSC::arrayTable)) , dateTable(fastNew<HashTable>(JSC::dateTable)) @@ -128,7 +128,7 @@ JSGlobalData::JSGlobalData(bool isShared, ThreadStackType threadStackType) #if USE(JSVALUE32) , numberStructure(JSNumberCell::createStructure(jsNull())) #endif - , identifierTable(createIdentifierTable()) + , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable()) , propertyNames(new CommonIdentifiers(this)) , emptyList(new MarkedArgumentBuffer) , lexer(new Lexer(this)) @@ -192,21 +192,20 @@ JSGlobalData::~JSGlobalData() delete emptyList; delete propertyNames; - deleteIdentifierTable(identifierTable); + if (globalDataType != Default) + deleteIdentifierTable(identifierTable); delete clientData; } -PassRefPtr<JSGlobalData> JSGlobalData::createNonDefault(ThreadStackType type) +PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type) { - return adoptRef(new JSGlobalData(false, type)); + return adoptRef(new JSGlobalData(APIContextGroup, type)); } PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type) { - JSGlobalData* globalData = new JSGlobalData(false, type); - wtfThreadData().initializeIdentifierTable(globalData->identifierTable); - return adoptRef(globalData); + return adoptRef(new JSGlobalData(Default, type)); } PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type) @@ -226,7 +225,7 @@ JSGlobalData& JSGlobalData::sharedInstance() { JSGlobalData*& instance = sharedInstanceInternal(); if (!instance) { - instance = new JSGlobalData(true, ThreadStackTypeSmall); + instance = new JSGlobalData(APIShared, ThreadStackTypeSmall); #if ENABLE(JSC_MULTIPLE_THREADS) instance->makeUsableFromMultipleThreads(); #endif diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h index a90bf2c..711e148 100644 --- a/JavaScriptCore/runtime/JSGlobalData.h +++ b/JavaScriptCore/runtime/JSGlobalData.h @@ -29,6 +29,7 @@ #ifndef JSGlobalData_h #define JSGlobalData_h +#include "CachedTranscendentalFunction.h" #include "Collector.h" #include "DateInstanceCache.h" #include "ExecutableAllocator.h" @@ -91,16 +92,27 @@ namespace JSC { class JSGlobalData : public RefCounted<JSGlobalData> { public: + // WebCore has a one-to-one mapping of threads to JSGlobalDatas; + // either create() or createLeaked() should only be called once + // on a thread, this is the 'default' JSGlobalData (it uses the + // thread's default string uniquing table from wtfThreadData). + // API contexts created using the new context group aware interface + // create APIContextGroup objects which require less locking of JSC + // than the old singleton APIShared JSGlobalData created for use by + // the original API. + enum GlobalDataType { Default, APIContextGroup, APIShared }; + struct ClientData { virtual ~ClientData() = 0; }; + bool isSharedInstance() { return globalDataType == APIShared; } static bool sharedInstanceExists(); static JSGlobalData& sharedInstance(); static PassRefPtr<JSGlobalData> create(ThreadStackType); static PassRefPtr<JSGlobalData> createLeaked(ThreadStackType); - static PassRefPtr<JSGlobalData> createNonDefault(ThreadStackType); + static PassRefPtr<JSGlobalData> createContextGroup(ThreadStackType); ~JSGlobalData(); #if ENABLE(JSC_MULTIPLE_THREADS) @@ -108,7 +120,7 @@ namespace JSC { void makeUsableFromMultipleThreads() { heap.makeUsableFromMultipleThreads(); } #endif - bool isSharedInstance; + GlobalDataType globalDataType; ClientData* clientData; const HashTable* arrayTable; @@ -158,6 +170,10 @@ namespace JSC { Interpreter* interpreter; #if ENABLE(JIT) JITThunks jitStubs; + NativeExecutable* getThunk(ThunkGenerator generator) + { + return jitStubs.specializedThunk(this, generator); + } #endif TimeoutChecker timeoutChecker; Terminator terminator; @@ -197,17 +213,19 @@ namespace JSC { ThreadIdentifier exclusiveThread; #endif + CachedTranscendentalFunction<sin> cachedSin; + void resetDateCache(); void startSampling(); void stopSampling(); void dumpSampleData(ExecState* exec); private: - JSGlobalData(bool isShared, ThreadStackType); + JSGlobalData(GlobalDataType, ThreadStackType); static JSGlobalData*& sharedInstanceInternal(); void createNativeThunk(); }; - + } // namespace JSC #endif // JSGlobalData_h diff --git a/JavaScriptCore/runtime/JSGlobalObject.cpp b/JavaScriptCore/runtime/JSGlobalObject.cpp index 86690bd..7568ffd 100644 --- a/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -117,10 +117,8 @@ JSGlobalObject::~JSGlobalObject() (*it)->clearGlobalObject(); RegisterFile& registerFile = globalData()->interpreter->registerFile(); - if (registerFile.globalObject() == this) { - registerFile.setGlobalObject(0); + if (registerFile.clearGlobalObject(this)) registerFile.setNumGlobals(0); - } d()->destructor(d()); } diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index 5b6369a..5da5194 100644 --- a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -241,6 +241,7 @@ static double parseInt(const UString& s, int radix) } if (number >= mantissaOverflowLowerBound) { + // FIXME: It is incorrect to use UString::ascii() here because it's not thread-safe. if (radix == 10) number = WTF::strtod(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), 0); else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32) @@ -269,6 +270,8 @@ static double parseFloat(const UString& s) if (length - p >= 2 && data[p] == '0' && (data[p + 1] == 'x' || data[p + 1] == 'X')) return 0; + // FIXME: UString::toDouble will ignore leading ASCII spaces, but we need to ignore + // other StrWhiteSpaceChar values as well. return s.toDouble(true /*tolerant*/, false /* NaN for empty string */); } diff --git a/JavaScriptCore/runtime/JSImmediate.h b/JavaScriptCore/runtime/JSImmediate.h index 0f54f60..9127b6a 100644 --- a/JavaScriptCore/runtime/JSImmediate.h +++ b/JavaScriptCore/runtime/JSImmediate.h @@ -136,6 +136,8 @@ namespace JSC { friend class JIT; friend class JSValue; friend class JSFastMath; + friend class JSInterfaceJIT; + friend class SpecializedThunkJIT; friend JSValue jsNumber(ExecState* exec, double d); friend JSValue jsNumber(ExecState*, char i); friend JSValue jsNumber(ExecState*, unsigned char i); @@ -164,7 +166,7 @@ namespace JSC { // This value is 2^48, used to encode doubles such that the encoded value will begin // with a 16-bit pattern within the range 0x0001..0xFFFE. static const intptr_t DoubleEncodeOffset = 0x1000000000000ll; -#else +#elif USE(JSVALUE32) static const intptr_t TagTypeNumber = 0x1; // bottom bit set indicates integer, this dominates the following bit #endif static const intptr_t TagBitTypeOther = 0x2; // second bit set indicates immediate other than an integer diff --git a/JavaScriptCore/runtime/JSLock.cpp b/JavaScriptCore/runtime/JSLock.cpp index 8f056c8..a1cffbd 100644 --- a/JavaScriptCore/runtime/JSLock.cpp +++ b/JavaScriptCore/runtime/JSLock.cpp @@ -60,7 +60,7 @@ static void setLockCount(intptr_t count) } JSLock::JSLock(ExecState* exec) - : m_lockBehavior(exec->globalData().isSharedInstance ? LockForReal : SilenceAssertionsOnly) + : m_lockBehavior(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly) { lock(m_lockBehavior); } @@ -105,12 +105,12 @@ void JSLock::unlock(JSLockBehavior lockBehavior) void JSLock::lock(ExecState* exec) { - lock(exec->globalData().isSharedInstance ? LockForReal : SilenceAssertionsOnly); + lock(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly); } void JSLock::unlock(ExecState* exec) { - unlock(exec->globalData().isSharedInstance ? LockForReal : SilenceAssertionsOnly); + unlock(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly); } bool JSLock::currentThreadIsHoldingLock() @@ -162,7 +162,7 @@ bool JSLock::currentThreadIsHoldingLock() static unsigned lockDropDepth = 0; JSLock::DropAllLocks::DropAllLocks(ExecState* exec) - : m_lockBehavior(exec->globalData().isSharedInstance ? LockForReal : SilenceAssertionsOnly) + : m_lockBehavior(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly) { pthread_once(&createJSLockCountOnce, createJSLockCount); diff --git a/JavaScriptCore/runtime/JSString.h b/JavaScriptCore/runtime/JSString.h index b1dccfa..85d3c8e 100644 --- a/JavaScriptCore/runtime/JSString.h +++ b/JavaScriptCore/runtime/JSString.h @@ -66,6 +66,8 @@ namespace JSC { public: friend class JIT; friend class JSGlobalData; + friend class SpecializedThunkJIT; + friend struct ThunkHelpers; class RopeBuilder { public: diff --git a/JavaScriptCore/runtime/JSValue.h b/JavaScriptCore/runtime/JSValue.h index b37adc0..bcf82ee 100644 --- a/JavaScriptCore/runtime/JSValue.h +++ b/JavaScriptCore/runtime/JSValue.h @@ -66,6 +66,8 @@ namespace JSC { friend class JIT; friend class JITStubs; friend class JITStubCall; + friend class JSInterfaceJIT; + friend class SpecializedThunkJIT; public: static EncodedJSValue encode(JSValue value); @@ -214,6 +216,10 @@ namespace JSC { JSObject* toObjectSlowCase(ExecState*) const; JSObject* toThisObjectSlowCase(ExecState*) const; + JSObject* synthesizePrototype(ExecState*) const; + JSObject* synthesizeObject(ExecState*) const; + +#if USE(JSVALUE32_64) enum { Int32Tag = 0xffffffff }; enum { CellTag = 0xfffffffe }; enum { TrueTag = 0xfffffffd }; @@ -222,16 +228,12 @@ namespace JSC { enum { UndefinedTag = 0xfffffffa }; enum { EmptyValueTag = 0xfffffff9 }; enum { DeletedValueTag = 0xfffffff8 }; - + enum { LowestTag = DeletedValueTag }; - + uint32_t tag() const; int32_t payload() const; - JSObject* synthesizePrototype(ExecState*) const; - JSObject* synthesizeObject(ExecState*) const; - -#if USE(JSVALUE32_64) union { EncodedJSValue asEncodedJSValue; double asDouble; diff --git a/JavaScriptCore/runtime/Lookup.cpp b/JavaScriptCore/runtime/Lookup.cpp index 4e9e086..0042e4d 100644 --- a/JavaScriptCore/runtime/Lookup.cpp +++ b/JavaScriptCore/runtime/Lookup.cpp @@ -46,7 +46,11 @@ void HashTable::createTable(JSGlobalData* globalData) const entry = entry->next(); } - entry->initialize(identifier, values[i].attributes, values[i].value1, values[i].value2); + entry->initialize(identifier, values[i].attributes, values[i].value1, values[i].value2 +#if ENABLE(JIT) + , values[i].generator +#endif + ); } table = entries; } @@ -70,7 +74,13 @@ void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* JSValue* location = thisObj->getDirectLocation(propertyName); if (!location) { - InternalFunction* function = new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), entry->functionLength(), propertyName, entry->function()); + InternalFunction* function; +#if ENABLE(JIT) + if (entry->generator()) + function = new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), entry->functionLength(), propertyName, exec->globalData().getThunk(entry->generator()), entry->function()); + else +#endif + function = new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), entry->functionLength(), propertyName, entry->function()); thisObj->putDirectFunction(propertyName, function, entry->attributes()); location = thisObj->getDirectLocation(propertyName); diff --git a/JavaScriptCore/runtime/Lookup.h b/JavaScriptCore/runtime/Lookup.h index 995aeee..dd36400 100644 --- a/JavaScriptCore/runtime/Lookup.h +++ b/JavaScriptCore/runtime/Lookup.h @@ -37,13 +37,15 @@ #endif namespace JSC { - // Hash table generated by the create_hash_table script. struct HashTableValue { const char* key; // property name unsigned char attributes; // JSObject attributes intptr_t value1; intptr_t value2; +#if ENABLE(JIT) + ThunkGenerator generator; +#endif }; // FIXME: There is no reason this get function can't be simpler. @@ -53,12 +55,19 @@ namespace JSC { class HashEntry : public FastAllocBase { public: - void initialize(UString::Rep* key, unsigned char attributes, intptr_t v1, intptr_t v2) + void initialize(UString::Rep* key, unsigned char attributes, intptr_t v1, intptr_t v2 +#if ENABLE(JIT) + , ThunkGenerator generator = 0 +#endif + ) { m_key = key; m_attributes = attributes; m_u.store.value1 = v1; m_u.store.value2 = v2; +#if ENABLE(JIT) + m_u.function.generator = generator; +#endif m_next = 0; } @@ -67,6 +76,9 @@ namespace JSC { unsigned char attributes() const { return m_attributes; } +#if ENABLE(JIT) + ThunkGenerator generator() const { ASSERT(m_attributes & Function); return m_u.function.generator; } +#endif NativeFunction function() const { ASSERT(m_attributes & Function); return m_u.function.functionValue; } unsigned char functionLength() const { ASSERT(m_attributes & Function); return static_cast<unsigned char>(m_u.function.length); } @@ -90,6 +102,9 @@ namespace JSC { struct { NativeFunction functionValue; intptr_t length; // number of arguments for function +#if ENABLE(JIT) + ThunkGenerator generator; +#endif } function; struct { GetFunction get; diff --git a/JavaScriptCore/runtime/MathObject.cpp b/JavaScriptCore/runtime/MathObject.cpp index 16d32a0..1e28dfa 100644 --- a/JavaScriptCore/runtime/MathObject.cpp +++ b/JavaScriptCore/runtime/MathObject.cpp @@ -223,7 +223,7 @@ JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec, JSObject*, JSValue, co JSValue JSC_HOST_CALL mathProtoFuncSin(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsDoubleNumber(exec, sin(args.at(0).toNumber(exec))); + return exec->globalData().cachedSin(exec, args.at(0).toNumber(exec)); } JSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValue, const ArgList& args) diff --git a/JavaScriptCore/runtime/SmallStrings.h b/JavaScriptCore/runtime/SmallStrings.h index cc11d0a..bc337c9 100644 --- a/JavaScriptCore/runtime/SmallStrings.h +++ b/JavaScriptCore/runtime/SmallStrings.h @@ -60,7 +60,9 @@ namespace JSC { void clear(); unsigned count() const; - +#if ENABLE(JIT) + JSString** singleCharacterStrings() { return m_singleCharacterStrings; } +#endif private: void createEmptyString(JSGlobalData*); void createSingleCharacterString(JSGlobalData*, unsigned char); diff --git a/JavaScriptCore/runtime/StringConstructor.cpp b/JavaScriptCore/runtime/StringConstructor.cpp index c7b62bf..42f98c3 100644 --- a/JavaScriptCore/runtime/StringConstructor.cpp +++ b/JavaScriptCore/runtime/StringConstructor.cpp @@ -54,8 +54,11 @@ StringConstructor::StringConstructor(ExecState* exec, NonNullPassRefPtr<Structur putDirectWithoutTransition(exec->propertyNames().prototype, stringPrototype, ReadOnly | DontEnum | DontDelete); // ECMA 15.5.3.2 fromCharCode() +#if ENABLE(JIT) + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().fromCharCode, exec->globalData().getThunk(fromCharCodeThunkGenerator), stringFromCharCode), DontEnum); +#else putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().fromCharCode, stringFromCharCode), DontEnum); - +#endif // no. of arguments for constructor putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete); } diff --git a/JavaScriptCore/runtime/Structure.cpp b/JavaScriptCore/runtime/Structure.cpp index 6f23c7d..6d13f4b 100644 --- a/JavaScriptCore/runtime/Structure.cpp +++ b/JavaScriptCore/runtime/Structure.cpp @@ -168,14 +168,14 @@ inline void Structure::transitionTableAdd(const StructureTransitionTableHash::Ke if (!specificValue) { TransitionTable::iterator find = transitionTable()->find(key); if (find == transitionTable()->end()) - transitionTable()->add(key, Transition(structure, 0)); + transitionTable()->add(key, Transition(structure, static_cast<Structure*>(0))); else find->second.first = structure; } else { // If we're adding a transition to a specific value, then there cannot be // an existing transition ASSERT(!transitionTable()->contains(key)); - transitionTable()->add(key, Transition(0, structure)); + transitionTable()->add(key, Transition(static_cast<Structure*>(0), structure)); } } diff --git a/JavaScriptCore/runtime/UString.cpp b/JavaScriptCore/runtime/UString.cpp index ce91040..6b16274 100644 --- a/JavaScriptCore/runtime/UString.cpp +++ b/JavaScriptCore/runtime/UString.cpp @@ -254,7 +254,15 @@ double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) co return NaN; } + // FIXME: If tolerateTrailingJunk is true, then we want to tolerate junk + // after the number, even if it contains invalid UTF-16 sequences. So we + // shouldn't use the UTF8String function, which returns null when it + // encounters invalid UTF-16. Further, we have no need to convert the + // non-ASCII characters to UTF-8, so the UTF8String does quite a bit of + // unnecessary work. CString s = UTF8String(); + if (s.isNull()) + return NaN; const char* c = s.data(); // skip leading white space @@ -318,6 +326,7 @@ double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) co while (isASCIISpace(*c)) c++; // don't allow anything after - unless tolerant=true + // FIXME: If string contains a U+0000 character, then this check is incorrect. if (!tolerateTrailingJunk && *c != '\0') d = NaN; diff --git a/JavaScriptCore/runtime/WeakGCPtr.h b/JavaScriptCore/runtime/WeakGCPtr.h index 5f58374..9dce858 100644 --- a/JavaScriptCore/runtime/WeakGCPtr.h +++ b/JavaScriptCore/runtime/WeakGCPtr.h @@ -44,10 +44,13 @@ public: return m_ptr; } - void clear(JSCell* ptr) + bool clear(JSCell* ptr) { - if (ptr == m_ptr) + if (ptr == m_ptr) { m_ptr = 0; + return true; + } + return false; } T& operator*() const { return *get(); } @@ -72,8 +75,8 @@ public: private: void assign(T* ptr) { - if (ptr) - Heap::markCell(ptr); + ASSERT(ptr); + Heap::markCell(ptr); m_ptr = ptr; } diff --git a/JavaScriptCore/wtf/Assertions.h b/JavaScriptCore/wtf/Assertions.h index df8646f..d26b939 100644 --- a/JavaScriptCore/wtf/Assertions.h +++ b/JavaScriptCore/wtf/Assertions.h @@ -62,7 +62,7 @@ #define ASSERTIONS_DISABLED_DEFAULT 0 #endif -#if COMPILER(MSVC7) || COMPILER(WINSCW) +#if COMPILER(MSVC7_OR_LOWER) || COMPILER(WINSCW) #define HAVE_VARIADIC_MACRO 0 #else #define HAVE_VARIADIC_MACRO 1 @@ -224,7 +224,7 @@ while (0) /* ASSERT_WITH_MESSAGE */ -#if COMPILER(MSVC7) +#if COMPILER(MSVC7_OR_LOWER) #define ASSERT_WITH_MESSAGE(assertion) ((void)0) #elif COMPILER(WINSCW) #define ASSERT_WITH_MESSAGE(assertion, arg...) ((void)0) @@ -264,7 +264,7 @@ while (0) /* FATAL */ -#if COMPILER(MSVC7) +#if COMPILER(MSVC7_OR_LOWER) #define FATAL() ((void)0) #elif COMPILER(WINSCW) #define FATAL(arg...) ((void)0) @@ -279,7 +279,7 @@ while (0) /* LOG_ERROR */ -#if COMPILER(MSVC7) +#if COMPILER(MSVC7_OR_LOWER) #define LOG_ERROR() ((void)0) #elif COMPILER(WINSCW) #define LOG_ERROR(arg...) ((void)0) @@ -291,7 +291,7 @@ while (0) /* LOG */ -#if COMPILER(MSVC7) +#if COMPILER(MSVC7_OR_LOWER) #define LOG() ((void)0) #elif COMPILER(WINSCW) #define LOG(arg...) ((void)0) @@ -305,7 +305,7 @@ while (0) /* LOG_VERBOSE */ -#if COMPILER(MSVC7) +#if COMPILER(MSVC7_OR_LOWER) #define LOG_VERBOSE(channel) ((void)0) #elif COMPILER(WINSCW) #define LOG_VERBOSE(channel, arg...) ((void)0) diff --git a/JavaScriptCore/wtf/Atomics.h b/JavaScriptCore/wtf/Atomics.h new file mode 100644 index 0000000..1d190a3 --- /dev/null +++ b/JavaScriptCore/wtf/Atomics.h @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.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. + * + * + * Note: The implementations of InterlockedIncrement and InterlockedDecrement are based + * on atomic_increment and atomic_exchange_and_add from the Boost C++ Library. The license + * is virtually identical to the Apple license above but is included here for completeness. + * + * Boost Software License - Version 1.0 - August 17th, 2003 + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef Atomics_h +#define Atomics_h + +#include "Platform.h" + +#if OS(WINDOWS) +#include <windows.h> +#elif OS(DARWIN) +#include <libkern/OSAtomic.h> +#elif OS(ANDROID) +#include <cutils/atomic.h> +#elif COMPILER(GCC) && !OS(SYMBIAN) +#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) +#include <ext/atomicity.h> +#else +#include <bits/atomicity.h> +#endif +#endif + +namespace WTF { + +#if OS(WINDOWS) +#define WTF_USE_LOCKFREE_THREADSAFESHARED 1 + +#if COMPILER(MINGW) || COMPILER(MSVC7_OR_LOWER) || OS(WINCE) +inline int atomicIncrement(int* addend) { return InterlockedIncrement(reinterpret_cast<long*>(addend)); } +inline int atomicDecrement(int* addend) { return InterlockedDecrement(reinterpret_cast<long*>(addend)); } +#else +inline int atomicIncrement(int volatile* addend) { return InterlockedIncrement(reinterpret_cast<long volatile*>(addend)); } +inline int atomicDecrement(int volatile* addend) { return InterlockedDecrement(reinterpret_cast<long volatile*>(addend)); } +#endif + +#elif OS(DARWIN) +#define WTF_USE_LOCKFREE_THREADSAFESHARED 1 + +inline int atomicIncrement(int volatile* addend) { return OSAtomicIncrement32Barrier(const_cast<int*>(addend)); } +inline int atomicDecrement(int volatile* addend) { return OSAtomicDecrement32Barrier(const_cast<int*>(addend)); } + +#elif OS(ANDROID) + +inline int atomicIncrement(int volatile* addend) { return android_atomic_inc(addend); } +inline int atomicDecrement(int volatile* addend) { return android_atomic_dec(addend); } + +#elif COMPILER(GCC) && !CPU(SPARC64) && !OS(SYMBIAN) // sizeof(_Atomic_word) != sizeof(int) on sparc64 gcc +#define WTF_USE_LOCKFREE_THREADSAFESHARED 1 + +inline int atomicIncrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, 1) + 1; } +inline int atomicDecrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, -1) - 1; } + +#endif + +} // namespace WTF + +#if USE(LOCKFREE_THREADSAFESHARED) +using WTF::atomicDecrement; +using WTF::atomicIncrement; +#endif + +#endif // Atomics_h diff --git a/JavaScriptCore/wtf/CurrentTime.cpp b/JavaScriptCore/wtf/CurrentTime.cpp index 30ca7c3..08fffa2 100644 --- a/JavaScriptCore/wtf/CurrentTime.cpp +++ b/JavaScriptCore/wtf/CurrentTime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006, 2010 Apple Inc. All rights reserved. * Copyright (C) 2008 Google Inc. All rights reserved. * Copyright (C) 2007-2009 Torch Mobile, Inc. * @@ -53,15 +53,13 @@ extern "C" time_t mktime(struct tm *t); #endif #endif -#elif PLATFORM(CF) -#include <CoreFoundation/CFDate.h> #elif PLATFORM(GTK) #include <glib.h> #elif PLATFORM(WX) #include <wx/datetime.h> #elif PLATFORM(BREWMP) #include <AEEStdLib.h> -#else // Posix systems relying on the gettimeofday() +#else #include <sys/time.h> #endif @@ -251,13 +249,6 @@ double currentTime() #endif // USE(QUERY_PERFORMANCE_COUNTER) -#elif PLATFORM(CF) - -double currentTime() -{ - return CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970; -} - #elif PLATFORM(GTK) // Note: GTK on Windows will pick up the PLATFORM(WIN) implementation above which provides @@ -293,15 +284,13 @@ double currentTime() return static_cast<double>(diffSeconds + GETUTCSECONDS() + ((GETTIMEMS() % 1000) / msPerSecond)); } -#else // Other Posix systems rely on the gettimeofday(). +#else double currentTime() { struct timeval now; - struct timezone zone; - - gettimeofday(&now, &zone); - return static_cast<double>(now.tv_sec) + (double)(now.tv_usec / 1000000.0); + gettimeofday(&now, 0); + return now.tv_sec + now.tv_usec / 1000000.0; } #endif diff --git a/JavaScriptCore/wtf/CurrentTime.h b/JavaScriptCore/wtf/CurrentTime.h index 033448f..dcb1f6c 100644 --- a/JavaScriptCore/wtf/CurrentTime.h +++ b/JavaScriptCore/wtf/CurrentTime.h @@ -49,7 +49,7 @@ namespace WTF { inline void getLocalTime(const time_t* localTime, struct tm* localTM) { - #if COMPILER(MSVC7) || COMPILER(MINGW) || OS(WINCE) + #if COMPILER(MSVC7_OR_LOWER) || COMPILER(MINGW) || OS(WINCE) *localTM = *localtime(localTime); #elif COMPILER(MSVC) localtime_s(localTM, localTime); diff --git a/JavaScriptCore/wtf/FastMalloc.cpp b/JavaScriptCore/wtf/FastMalloc.cpp index 7824159..9dfbc6b 100644 --- a/JavaScriptCore/wtf/FastMalloc.cpp +++ b/JavaScriptCore/wtf/FastMalloc.cpp @@ -1273,8 +1273,12 @@ static const int kScavengeDelayInSeconds = 2; // scavenge. static const float kScavengePercentage = .5f; -// Number of free committed pages that we want to keep around. -static const size_t kMinimumFreeCommittedPageCount = 512; +// number of span lists to keep spans in when memory is returned. +static const int kMinSpanListsWithSpans = 32; + +// Number of free committed pages that we want to keep around. The minimum number of pages used when there +// is 1 span in each of the first kMinSpanListsWithSpans spanlists. Currently 528 pages. +static const size_t kMinimumFreeCommittedPageCount = kMinSpanListsWithSpans * ((1.0f+kMinSpanListsWithSpans) / 2.0f); #endif @@ -1534,20 +1538,25 @@ void TCMalloc_PageHeap::scavenge() size_t pagesToRelease = min_free_committed_pages_since_last_scavenge_ * kScavengePercentage; size_t targetPageCount = std::max<size_t>(kMinimumFreeCommittedPageCount, free_committed_pages_ - pagesToRelease); - for (int i = kMaxPages; i >= 0 && free_committed_pages_ > targetPageCount; i--) { - SpanList* slist = (static_cast<size_t>(i) == kMaxPages) ? &large_ : &free_[i]; - while (!DLL_IsEmpty(&slist->normal) && free_committed_pages_ > targetPageCount) { - Span* s = slist->normal.prev; - DLL_Remove(s); - ASSERT(!s->decommitted); - if (!s->decommitted) { - TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift), - static_cast<size_t>(s->length << kPageShift)); - ASSERT(free_committed_pages_ >= s->length); - free_committed_pages_ -= s->length; - s->decommitted = true; + while (free_committed_pages_ > targetPageCount) { + for (int i = kMaxPages; i > 0 && free_committed_pages_ >= targetPageCount; i--) { + SpanList* slist = (static_cast<size_t>(i) == kMaxPages) ? &large_ : &free_[i]; + // If the span size is bigger than kMinSpanListsWithSpans pages return all the spans in the list, else return all but 1 span. + // Return only 50% of a spanlist at a time so spans of size 1 are not the only ones left. + size_t numSpansToReturn = (i > kMinSpanListsWithSpans) ? DLL_Length(&slist->normal) : static_cast<size_t>(.5 * DLL_Length(&slist->normal)); + for (int j = 0; static_cast<size_t>(j) < numSpansToReturn && !DLL_IsEmpty(&slist->normal) && free_committed_pages_ > targetPageCount; j++) { + Span* s = slist->normal.prev; + DLL_Remove(s); + ASSERT(!s->decommitted); + if (!s->decommitted) { + TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift), + static_cast<size_t>(s->length << kPageShift)); + ASSERT(free_committed_pages_ >= s->length); + free_committed_pages_ -= s->length; + s->decommitted = true; + } + DLL_Prepend(&slist->returned, s); } - DLL_Prepend(&slist->returned, s); } } @@ -1583,19 +1592,13 @@ inline Span* TCMalloc_PageHeap::New(Length n) { Span* result = ll->next; Carve(result, n, released); - if (result->decommitted) { - TCMalloc_SystemCommit(reinterpret_cast<void*>(result->start << kPageShift), static_cast<size_t>(n << kPageShift)); - result->decommitted = false; - } #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - else { - // The newly allocated memory is from a span that's in the normal span list (already committed). Update the - // free committed pages count. - ASSERT(free_committed_pages_ >= n); - free_committed_pages_ -= n; - if (free_committed_pages_ < min_free_committed_pages_since_last_scavenge_) - min_free_committed_pages_since_last_scavenge_ = free_committed_pages_; - } + // The newly allocated memory is from a span that's in the normal span list (already committed). Update the + // free committed pages count. + ASSERT(free_committed_pages_ >= n); + free_committed_pages_ -= n; + if (free_committed_pages_ < min_free_committed_pages_since_last_scavenge_) + min_free_committed_pages_since_last_scavenge_ = free_committed_pages_; #endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY ASSERT(Check()); free_pages_ -= n; @@ -1653,19 +1656,13 @@ Span* TCMalloc_PageHeap::AllocLarge(Length n) { if (best != NULL) { Carve(best, n, from_released); - if (best->decommitted) { - TCMalloc_SystemCommit(reinterpret_cast<void*>(best->start << kPageShift), static_cast<size_t>(n << kPageShift)); - best->decommitted = false; - } #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - else { - // The newly allocated memory is from a span that's in the normal span list (already committed). Update the - // free committed pages count. - ASSERT(free_committed_pages_ >= n); - free_committed_pages_ -= n; - if (free_committed_pages_ < min_free_committed_pages_since_last_scavenge_) - min_free_committed_pages_since_last_scavenge_ = free_committed_pages_; - } + // The newly allocated memory is from a span that's in the normal span list (already committed). Update the + // free committed pages count. + ASSERT(free_committed_pages_ >= n); + free_committed_pages_ -= n; + if (free_committed_pages_ < min_free_committed_pages_since_last_scavenge_) + min_free_committed_pages_since_last_scavenge_ = free_committed_pages_; #endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY ASSERT(Check()); free_pages_ -= n; @@ -1691,29 +1688,34 @@ Span* TCMalloc_PageHeap::Split(Span* span, Length n) { return leftover; } -static ALWAYS_INLINE void propagateDecommittedState(Span* destination, Span* source) -{ - destination->decommitted = source->decommitted; -} - inline void TCMalloc_PageHeap::Carve(Span* span, Length n, bool released) { ASSERT(n > 0); DLL_Remove(span); span->free = 0; Event(span, 'A', n); + if (released) { + // If the span chosen to carve from is decommited, commit the entire span at once to avoid committing spans 1 page at a time. + ASSERT(span->decommitted); + TCMalloc_SystemCommit(reinterpret_cast<void*>(span->start << kPageShift), static_cast<size_t>(span->length << kPageShift)); + span->decommitted = false; +#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY + free_committed_pages_ += span->length; +#endif + } + const int extra = static_cast<int>(span->length - n); ASSERT(extra >= 0); if (extra > 0) { Span* leftover = NewSpan(span->start + n, extra); leftover->free = 1; - propagateDecommittedState(leftover, span); + leftover->decommitted = false; Event(leftover, 'S', extra); RecordSpan(leftover); // Place leftover span on appropriate free list SpanList* listpair = (static_cast<size_t>(extra) < kMaxPages) ? &free_[extra] : &large_; - Span* dst = released ? &listpair->returned : &listpair->normal; + Span* dst = &listpair->normal; DLL_Prepend(dst, leftover); span->length = n; @@ -2336,7 +2338,7 @@ static TCMalloc_Central_FreeListPadded central_cache[kNumClasses]; // Page-level allocator static SpinLock pageheap_lock = SPINLOCK_INITIALIZER; -static void* pageheap_memory[(sizeof(TCMalloc_PageHeap) + sizeof(void*) - 1) / sizeof(void*)]; +static AllocAlignmentInteger pageheap_memory[(sizeof(TCMalloc_PageHeap) + sizeof(AllocAlignmentInteger) - 1) / sizeof(AllocAlignmentInteger)]; static bool phinited = false; // Avoid extra level of indirection by making "pageheap" be just an alias diff --git a/JavaScriptCore/wtf/MD5.cpp b/JavaScriptCore/wtf/MD5.cpp new file mode 100644 index 0000000..cd1837a --- /dev/null +++ b/JavaScriptCore/wtf/MD5.cpp @@ -0,0 +1,304 @@ +// The original file was copied from sqlite, and was in the public domain. +// Modifications Copyright 2006 Google Inc. All Rights Reserved +/* + * Copyright (C) 2010 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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. + */ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, construct an + * MD5 instance, call addBytes as needed on buffers full of bytes, + * and then call checksum, which will fill a supplied 16-byte array + * with the digest. + */ + +#include "config.h" +#include "MD5.h" + +#include "Assertions.h" +#ifndef NDEBUG +#include "StringExtras.h" +#include "text/CString.h" +#endif + +namespace WTF { + +#ifdef NDEBUG +static inline void testMD5() { } +#else +// MD5 test case. +static bool isTestMD5Done; + +static void expectMD5(CString input, CString expected) +{ + MD5 md5; + md5.addBytes(reinterpret_cast<const uint8_t*>(input.data()), input.length()); + Vector<uint8_t, 16> digest = md5.checksum(); + char* buf = 0; + CString actual = CString::newUninitialized(32, buf); + for (size_t i = 0; i < 16; i++) { + snprintf(buf, 3, "%02x", digest.at(i)); + buf += 2; + } + ASSERT_WITH_MESSAGE(actual == expected, "input:%s[%d] actual:%s expected:%s", input.data(), input.length(), actual.data(), expected.data()); +} + +static void testMD5() +{ + if (isTestMD5Done) + return; + isTestMD5Done = true; + + // MD5 Test suite from http://www.ietf.org/rfc/rfc1321.txt + expectMD5("", "d41d8cd98f00b204e9800998ecf8427e"); + expectMD5("a", "0cc175b9c0f1b6a831c399e269772661"); + expectMD5("abc", "900150983cd24fb0d6963f7d28e17f72"); + expectMD5("message digest", "f96b697d7cb7938d525a2f31aaf161d0"); + expectMD5("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b"); + expectMD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "d174ab98d277d9f5a5611c2c9f419d9f"); + expectMD5("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a"); +} +#endif + +// Note: this code is harmless on little-endian machines. + +static void reverseBytes(uint8_t* buf, unsigned longs) +{ + ASSERT(longs > 0); + do { + uint32_t t = static_cast<uint32_t>(buf[3] << 8 | buf[2]) << 16 | buf[1] << 8 | buf[0]; + ASSERT_WITH_MESSAGE(!(reinterpret_cast<uintptr_t>(buf) % sizeof(t)), "alignment error of buf"); + *reinterpret_cast<uint32_t *>(buf) = t; + buf += 4; + } while (--longs); +} + +// The four core functions. +// F1 is originally defined as (x & y | ~x & z), but optimized somewhat: 4 bit ops -> 3 bit ops. +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +// This is the central step in the MD5 algorithm. +#define MD5STEP(f, w, x, y, z, data, s) \ + (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x) + +static void MD5Transform(uint32_t buf[4], const uint32_t in[16]) +{ + uint32_t a = buf[0]; + uint32_t b = buf[1]; + uint32_t c = buf[2]; + uint32_t d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +MD5::MD5() +{ + testMD5(); + m_buf[0] = 0x67452301; + m_buf[1] = 0xefcdab89; + m_buf[2] = 0x98badcfe; + m_buf[3] = 0x10325476; + m_bits[0] = 0; + m_bits[1] = 0; + memset(m_in, 0, sizeof(m_in)); + ASSERT_WITH_MESSAGE(!(reinterpret_cast<uintptr_t>(m_in) % sizeof(uint32_t)), "alignment error of m_in"); +} + +void MD5::addBytes(const uint8_t* input, size_t length) +{ + const uint8_t* buf = input; + + // Update bitcount + uint32_t t = m_bits[0]; + m_bits[0] = t + (length << 3); + if (m_bits[0] < t) + m_bits[1]++; // Carry from low to high + m_bits[1] += length >> 29; + + t = (t >> 3) & 0x3f; // Bytes already in shsInfo->data + + // Handle any leading odd-sized chunks + + if (t) { + uint8_t* p = m_in + t; + + t = 64 - t; + if (length < t) { + memcpy(p, buf, length); + return; + } + memcpy(p, buf, t); + reverseBytes(m_in, 16); + MD5Transform(m_buf, reinterpret_cast<uint32_t*>(m_in)); // m_in is 4-byte aligned. + buf += t; + length -= t; + } + + // Process data in 64-byte chunks + + while (length >= 64) { + memcpy(m_in, buf, 64); + reverseBytes(m_in, 16); + MD5Transform(m_buf, reinterpret_cast<uint32_t*>(m_in)); // m_in is 4-byte aligned. + buf += 64; + length -= 64; + } + + // Handle any remaining bytes of data. + memcpy(m_in, buf, length); +} + +Vector<uint8_t, 16> MD5::checksum() +{ + // Compute number of bytes mod 64 + unsigned count = (m_bits[0] >> 3) & 0x3F; + + // Set the first char of padding to 0x80. This is safe since there is + // always at least one byte free + uint8_t* p = m_in + count; + *p++ = 0x80; + + // Bytes of padding needed to make 64 bytes + count = 64 - 1 - count; + + // Pad out to 56 mod 64 + if (count < 8) { + // Two lots of padding: Pad the first block to 64 bytes + memset(p, 0, count); + reverseBytes(m_in, 16); + MD5Transform(m_buf, reinterpret_cast<uint32_t *>(m_in)); // m_in is 4-byte aligned. + + // Now fill the next block with 56 bytes + memset(m_in, 0, 56); + } else { + // Pad block to 56 bytes + memset(p, 0, count - 8); + } + reverseBytes(m_in, 14); + + // Append length in bits and transform + // m_in is 4-byte aligned. + (reinterpret_cast<uint32_t*>(m_in))[14] = m_bits[0]; + (reinterpret_cast<uint32_t*>(m_in))[15] = m_bits[1]; + + MD5Transform(m_buf, reinterpret_cast<uint32_t*>(m_in)); + reverseBytes(reinterpret_cast<uint8_t*>(m_buf), 4); + Vector<uint8_t, 16> digest; + digest.append(reinterpret_cast<uint8_t*>(m_buf), 16); + + // In case it's sensitive + memset(m_buf, 0, sizeof(m_buf)); + memset(m_bits, 0, sizeof(m_bits)); + memset(m_in, 0, sizeof(m_in)); + return digest; +} + +} // namespace WTF diff --git a/WebCore/bindings/js/JSDatabaseCallback.h b/JavaScriptCore/wtf/MD5.h index 752a2c3..8ebfc45 100644 --- a/WebCore/bindings/js/JSDatabaseCallback.h +++ b/JavaScriptCore/wtf/MD5.h @@ -28,39 +28,34 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSDatabaseCallback_h -#define JSDatabaseCallback_h +#ifndef WTF_MD5_h +#define WTF_MD5_h -#if ENABLE(DATABASE) +#include <wtf/Vector.h> -#include "DatabaseCallback.h" -#include "JSCallbackData.h" -#include <wtf/Forward.h> +namespace WTF { -namespace WebCore { - -class ScriptExecutionContext; - -class JSDatabaseCallback : public DatabaseCallback { +class MD5 { public: - static PassRefPtr<JSDatabaseCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject) + MD5(); + + void addBytes(const Vector<uint8_t>& input) { - return adoptRef(new JSDatabaseCallback(callback, globalObject)); + addBytes(input.data(), input.size()); } + void addBytes(const uint8_t* input, size_t length); - virtual ~JSDatabaseCallback(); - - virtual void handleEvent(ScriptExecutionContext*, Database*); + // checksum has a side effect of resetting the state of the object. + Vector<uint8_t, 16> checksum(); private: - JSDatabaseCallback(JSC::JSObject* callback, JSDOMGlobalObject*); - - JSCallbackData* m_data; - RefPtr<DOMWrapperWorld> m_isolatedWorld; + uint32_t m_buf[4]; + uint32_t m_bits[2]; + uint8_t m_in[64]; }; -} +} // namespace WTF -#endif // ENABLE(DATABASE) +using WTF::MD5; -#endif // JSDatabaseCallback_h +#endif // WTF_MD5_h diff --git a/JavaScriptCore/wtf/MainThread.cpp b/JavaScriptCore/wtf/MainThread.cpp index 40a4ae5..a041bb2 100644 --- a/JavaScriptCore/wtf/MainThread.cpp +++ b/JavaScriptCore/wtf/MainThread.cpp @@ -29,11 +29,15 @@ #include "config.h" #include "MainThread.h" -#include "StdLibExtras.h" #include "CurrentTime.h" #include "Deque.h" +#include "StdLibExtras.h" #include "Threading.h" +#if PLATFORM(CHROMIUM) +#error Chromium uses a different main thread implementation +#endif + namespace WTF { struct FunctionWithContext { @@ -52,8 +56,11 @@ struct FunctionWithContext { typedef Deque<FunctionWithContext> FunctionQueue; static bool callbacksPaused; // This global variable is only accessed from main thread. +#if !PLATFORM(MAC) && !PLATFORM(QT) +static ThreadIdentifier mainThreadIdentifier; +#endif -Mutex& mainThreadFunctionQueueMutex() +static Mutex& mainThreadFunctionQueueMutex() { DEFINE_STATIC_LOCAL(Mutex, staticMutex, ()); return staticMutex; @@ -65,12 +72,51 @@ static FunctionQueue& functionQueue() return staticFunctionQueue; } + +#if !PLATFORM(MAC) + void initializeMainThread() { + static bool initializedMainThread; + if (initializedMainThread) + return; + initializedMainThread = true; + +#if !PLATFORM(QT) + mainThreadIdentifier = currentThread(); +#endif + + mainThreadFunctionQueueMutex(); + initializeMainThreadPlatform(); +} + +#else + +static pthread_once_t initializeMainThreadKeyOnce = PTHREAD_ONCE_INIT; + +static void initializeMainThreadOnce() +{ mainThreadFunctionQueueMutex(); initializeMainThreadPlatform(); } +void initializeMainThread() +{ + pthread_once(&initializeMainThreadKeyOnce, initializeMainThreadOnce); +} + +static void initializeMainThreadToProcessMainThreadOnce() +{ + mainThreadFunctionQueueMutex(); + initializeMainThreadToProcessMainThreadPlatform(); +} + +void initializeMainThreadToProcessMainThread() +{ + pthread_once(&initializeMainThreadKeyOnce, initializeMainThreadToProcessMainThreadOnce); +} +#endif + // 0.1 sec delays in UI is approximate threshold when they become noticeable. Have a limit that's half of that. static const double maxRunLoopSuspensionTime = 0.05; @@ -152,4 +198,11 @@ void setMainThreadCallbacksPaused(bool paused) scheduleDispatchFunctionsOnMainThread(); } +#if !PLATFORM(MAC) && !PLATFORM(QT) +bool isMainThread() +{ + return currentThread() == mainThreadIdentifier; +} +#endif + } // namespace WTF diff --git a/JavaScriptCore/wtf/MainThread.h b/JavaScriptCore/wtf/MainThread.h index 8c0275b..d037d0b 100644 --- a/JavaScriptCore/wtf/MainThread.h +++ b/JavaScriptCore/wtf/MainThread.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) * * Redistribution and use in source and binary forms, with or without @@ -30,32 +30,40 @@ #ifndef MainThread_h #define MainThread_h -namespace WTF { +#include <stdint.h> -class Mutex; +namespace WTF { +typedef uint32_t ThreadIdentifier; typedef void MainThreadFunction(void*); -void callOnMainThread(MainThreadFunction*, void* context); +// Must be called from the main thread. +void initializeMainThread(); -// Blocks the thread until the call finishes on the main thread. Misusing this can easily cause deadlocks. +void callOnMainThread(MainThreadFunction*, void* context); void callOnMainThreadAndWait(MainThreadFunction*, void* context); - void setMainThreadCallbacksPaused(bool paused); -// Must be called from the main thread (Darwin is an exception to this rule). -void initializeMainThread(); +bool isMainThread(); -// These functions are internal to the callOnMainThread implementation. +// NOTE: these functions are internal to the callOnMainThread implementation. void initializeMainThreadPlatform(); void scheduleDispatchFunctionsOnMainThread(); -Mutex& mainThreadFunctionQueueMutex(); void dispatchFunctionsFromMainThread(); +#if PLATFORM(MAC) +// This version of initializeMainThread sets up the main thread as corresponding +// to the process's main thread, and not necessarily the thread that calls this +// function. It should only be used as a legacy aid for Mac WebKit. +void initializeMainThreadToProcessMainThread(); +void initializeMainThreadToProcessMainThreadPlatform(); +#endif + } // namespace WTF using WTF::callOnMainThread; using WTF::callOnMainThreadAndWait; using WTF::setMainThreadCallbacksPaused; +using WTF::isMainThread; #endif // MainThread_h diff --git a/JavaScriptCore/wtf/MathExtras.h b/JavaScriptCore/wtf/MathExtras.h index ac9bf60..25e724a 100644 --- a/JavaScriptCore/wtf/MathExtras.h +++ b/JavaScriptCore/wtf/MathExtras.h @@ -122,8 +122,10 @@ inline double trunc(double num) { return num > 0 ? floor(num) : ceil(num); } #endif #if COMPILER(MSVC) - +// The 64bit version of abs() is already defined in stdlib.h which comes with VC10 +#if COMPILER(MSVC9_OR_LOWER) inline long long abs(long long num) { return _abs64(num); } +#endif inline bool isinf(double num) { return !_finite(num) && !_isnan(num); } inline bool isnan(double num) { return !!_isnan(num); } @@ -188,7 +190,11 @@ inline float deg2turn(float d) { return d / 360.0f; } inline float rad2grad(float r) { return r * 200.0f / piFloat; } inline float grad2rad(float g) { return g * piFloat / 200.0f; } +<<<<<<< HEAD:JavaScriptCore/wtf/MathExtras.h #if !COMPILER(MSVC) && !COMPILER(RVCT) && !COMPILER(WINSCW) +======= +#if !COMPILER(MSVC) && !COMPILER(WINSCW) && !(COMPILER(RVCT) && OS(SYMBIAN)) +>>>>>>> webkit.org at r58956:JavaScriptCore/wtf/MathExtras.h using std::isfinite; using std::isinf; using std::isnan; diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h index 405d3e7..f667b9a 100644 --- a/JavaScriptCore/wtf/Platform.h +++ b/JavaScriptCore/wtf/Platform.h @@ -58,11 +58,14 @@ /* ==== COMPILER() - the compiler being used to build the project ==== */ /* COMPILER(MSVC) Microsoft Visual C++ */ -/* COMPILER(MSVC7) Microsoft Visual C++ v7 or lower*/ +/* COMPILER(MSVC7_OR_LOWER) Microsoft Visual C++ 2003 or lower*/ +/* COMPILER(MSVC9_OR_LOWER) Microsoft Visual C++ 2008 or lower*/ #if defined(_MSC_VER) #define WTF_COMPILER_MSVC 1 #if _MSC_VER < 1400 -#define WTF_COMPILER_MSVC7 1 +#define WTF_COMPILER_MSVC7_OR_LOWER 1 +#elif _MSC_VER < 1600 +#define WTF_COMPILER_MSVC9_OR_LOWER 1 #endif #endif @@ -584,8 +587,8 @@ #if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_TIGER) && CPU(X86_64) #define WTF_USE_PLUGIN_HOST_PROCESS 1 #endif -#if !defined(ENABLE_MAC_JAVA_BRIDGE) -#define ENABLE_MAC_JAVA_BRIDGE 1 +#if !defined(ENABLE_JAVA_BRIDGE) +#define ENABLE_JAVA_BRIDGE 1 #endif #if !defined(ENABLE_DASHBOARD_SUPPORT) #define ENABLE_DASHBOARD_SUPPORT 1 @@ -616,7 +619,7 @@ #define ENABLE_GEOLOCATION 1 #define ENABLE_ICONDATABASE 0 #define ENABLE_INSPECTOR 0 -#define ENABLE_MAC_JAVA_BRIDGE 0 +#define ENABLE_JAVA_BRIDGE 0 #define ENABLE_NETSCAPE_PLUGIN_API 0 #define ENABLE_ORIENTATION_EVENTS 1 #define ENABLE_REPAINT_THROTTLING 1 @@ -630,7 +633,7 @@ #define WTF_USE_PTHREADS 1 #define WTF_PLATFORM_SKIA 1 #define USE_SYSTEM_MALLOC 1 -#define ENABLE_MAC_JAVA_BRIDGE 1 +#define ENABLE_JAVA_BRIDGE 1 #define LOG_DISABLED 1 /* Prevents Webkit from drawing the caret in textfields and textareas This prevents unnecessary invals. */ @@ -648,6 +651,11 @@ #define ENABLE_GLOBAL_FASTMALLOC_NEW 0 #if OS(DARWIN) #define WTF_PLATFORM_CF 1 +#ifndef BUILDING_ON_TIGER +#define WTF_USE_CORE_TEXT 1 +#else +#define WTF_USE_ATSUI 1 +#endif #endif #endif @@ -828,8 +836,8 @@ #define ENABLE_INSPECTOR 1 #endif -#if !defined(ENABLE_MAC_JAVA_BRIDGE) -#define ENABLE_MAC_JAVA_BRIDGE 0 +#if !defined(ENABLE_JAVA_BRIDGE) +#define ENABLE_JAVA_BRIDGE 0 #endif #if !defined(ENABLE_NETSCAPE_PLUGIN_API) @@ -852,6 +860,7 @@ #define ENABLE_GLOBAL_FASTMALLOC_NEW 1 #endif +#define ENABLE_DEBUG_WITH_BREAKPOINT 0 #define ENABLE_SAMPLING_COUNTERS 0 #define ENABLE_SAMPLING_FLAGS 0 #define ENABLE_OPCODE_SAMPLING 0 @@ -955,6 +964,8 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #define ENABLE_JIT 1 #elif CPU(ARM_TRADITIONAL) && OS(LINUX) #define ENABLE_JIT 1 +#elif CPU(ARM_TRADITIONAL) && OS(SYMBIAN) && COMPILER(RVCT) + #define ENABLE_JIT 1 #elif CPU(MIPS) && OS(LINUX) #define ENABLE_JIT 1 #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 0 @@ -1027,7 +1038,10 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ || (CPU(X86) && OS(LINUX) && GCC_VERSION >= 40100) \ || (CPU(X86_64) && OS(LINUX) && GCC_VERSION >= 40100) \ || (CPU(ARM_TRADITIONAL) && OS(LINUX)) \ - || (CPU(MIPS) && OS(LINUX)) + || (CPU(ARM_TRADITIONAL) && OS(SYMBIAN) && COMPILER(RVCT)) \ + || (CPU(MIPS) && OS(LINUX)) \ + || (CPU(X86) && OS(DARWIN)) \ + || (CPU(X86_64) && OS(DARWIN)) #define ENABLE_YARR 1 #define ENABLE_YARR_JIT 1 #endif @@ -1092,6 +1106,10 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #endif #endif +#if (PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)) || PLATFORM(IPHONE) +#define WTF_USE_PROTECTION_SPACE_AUTH_CALLBACK 1 +#endif + #if COMPILER(GCC) #define WARN_UNUSED_RETURN __attribute__ ((warn_unused_result)) #else diff --git a/JavaScriptCore/wtf/RandomNumber.h b/JavaScriptCore/wtf/RandomNumber.h index fe1687c..e54e9ae 100644 --- a/JavaScriptCore/wtf/RandomNumber.h +++ b/JavaScriptCore/wtf/RandomNumber.h @@ -39,4 +39,7 @@ namespace WTF { } +using WTF::randomNumber; +using WTF::weakRandomNumber; + #endif diff --git a/JavaScriptCore/wtf/RefPtr.h b/JavaScriptCore/wtf/RefPtr.h index 84e841c..eed7933 100644 --- a/JavaScriptCore/wtf/RefPtr.h +++ b/JavaScriptCore/wtf/RefPtr.h @@ -18,6 +18,8 @@ * */ +// RefPtr and PassRefPtr are documented at http://webkit.org/coding/RefPtr.html + #ifndef WTF_RefPtr_h #define WTF_RefPtr_h @@ -79,9 +81,9 @@ namespace WTF { void swap(RefPtr&); - private: static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); } + private: T* m_ptr; }; diff --git a/JavaScriptCore/wtf/StaticConstructors.h b/JavaScriptCore/wtf/StaticConstructors.h index 97af339..8b2df9d 100644 --- a/JavaScriptCore/wtf/StaticConstructors.h +++ b/JavaScriptCore/wtf/StaticConstructors.h @@ -51,7 +51,7 @@ #ifndef SKIP_STATIC_CONSTRUCTORS_ON_GCC // Define an global in the normal way. -#if COMPILER(MSVC7) +#if COMPILER(MSVC7_OR_LOWER) #define DEFINE_GLOBAL(type, name) \ const type name; #elif COMPILER(WINSCW) @@ -65,7 +65,7 @@ #else // Define an correctly-sized array of pointers to avoid static initialization. // Use an array of pointers instead of an array of char in case there is some alignment issue. -#if COMPILER(MSVC7) +#if COMPILER(MSVC7_OR_LOWER) #define DEFINE_GLOBAL(type, name) \ void * name[(sizeof(type) + sizeof(void *) - 1) / sizeof(void *)]; #elif COMPILER(WINSCW) diff --git a/JavaScriptCore/wtf/StringExtras.h b/JavaScriptCore/wtf/StringExtras.h index b1ec09f..28e80b8 100644 --- a/JavaScriptCore/wtf/StringExtras.h +++ b/JavaScriptCore/wtf/StringExtras.h @@ -46,7 +46,7 @@ inline int snprintf(char* buffer, size_t count, const char* format, ...) return result; } -#if COMPILER(MSVC7) || OS(WINCE) +#if COMPILER(MSVC7_OR_LOWER) || OS(WINCE) inline int vsnprintf(char* buffer, size_t count, const char* format, va_list args) { diff --git a/JavaScriptCore/wtf/ThreadSafeShared.h b/JavaScriptCore/wtf/ThreadSafeShared.h new file mode 100644 index 0000000..688747e --- /dev/null +++ b/JavaScriptCore/wtf/ThreadSafeShared.h @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.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. + * + * + * Note: The implementations of InterlockedIncrement and InterlockedDecrement are based + * on atomic_increment and atomic_exchange_and_add from the Boost C++ Library. The license + * is virtually identical to the Apple license above but is included here for completeness. + * + * Boost Software License - Version 1.0 - August 17th, 2003 + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef ThreadSafeShared_h +#define ThreadSafeShared_h + +#include "Platform.h" + +#include <wtf/Atomics.h> +#include <wtf/Noncopyable.h> +#include <wtf/ThreadingPrimitives.h> + +namespace WTF { + +class ThreadSafeSharedBase : public Noncopyable { +public: + ThreadSafeSharedBase(int initialRefCount = 1) + : m_refCount(initialRefCount) + { + } + + void ref() + { +#if USE(LOCKFREE_THREADSAFESHARED) + atomicIncrement(&m_refCount); +#else + MutexLocker locker(m_mutex); + ++m_refCount; +#endif + } + + bool hasOneRef() + { + return refCount() == 1; + } + + int refCount() const + { +#if !USE(LOCKFREE_THREADSAFESHARED) + MutexLocker locker(m_mutex); +#endif + return static_cast<int const volatile &>(m_refCount); + } + +protected: + // Returns whether the pointer should be freed or not. + bool derefBase() + { +#if USE(LOCKFREE_THREADSAFESHARED) + if (atomicDecrement(&m_refCount) <= 0) + return true; +#else + int refCount; + { + MutexLocker locker(m_mutex); + --m_refCount; + refCount = m_refCount; + } + if (refCount <= 0) + return true; +#endif + return false; + } + +private: + template<class T> + friend class CrossThreadRefCounted; + + int m_refCount; +#if !USE(LOCKFREE_THREADSAFESHARED) + mutable Mutex m_mutex; +#endif +}; + +template<class T> class ThreadSafeShared : public ThreadSafeSharedBase { +public: + ThreadSafeShared(int initialRefCount = 1) + : ThreadSafeSharedBase(initialRefCount) + { + } + + void deref() + { + if (derefBase()) + delete static_cast<T*>(this); + } +}; + +} // namespace WTF + +using WTF::ThreadSafeShared; + +#endif // ThreadSafeShared_h diff --git a/JavaScriptCore/wtf/Threading.h b/JavaScriptCore/wtf/Threading.h index 768aecf..415a8fc 100644 --- a/JavaScriptCore/wtf/Threading.h +++ b/JavaScriptCore/wtf/Threading.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) * * Redistribution and use in source and binary forms, with or without @@ -61,45 +61,14 @@ #include "Platform.h" -#if OS(WINCE) -#include <windows.h> -#endif - +#include <stdint.h> #include <wtf/Assertions.h> +#include <wtf/Atomics.h> #include <wtf/Locker.h> +#include <wtf/MainThread.h> #include <wtf/Noncopyable.h> - -#if OS(WINDOWS) && !OS(WINCE) -#include <windows.h> -#elif OS(DARWIN) -#include <libkern/OSAtomic.h> -#elif OS(ANDROID) -#include <cutils/atomic.h> -#elif COMPILER(GCC) && !OS(SYMBIAN) -#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) -#include <ext/atomicity.h> -#else -#include <bits/atomicity.h> -#endif -#endif - -#if USE(PTHREADS) -#include <pthread.h> -#elif PLATFORM(GTK) -#include "GOwnPtr.h" -typedef struct _GMutex GMutex; -typedef struct _GCond GCond; -#endif - -#if PLATFORM(QT) -#include <qglobal.h> -QT_BEGIN_NAMESPACE -class QMutex; -class QWaitCondition; -QT_END_NAMESPACE -#endif - -#include <stdint.h> +#include <wtf/ThreadSafeShared.h> +#include <wtf/ThreadingPrimitives.h> // For portability, we do not use thread-safe statics natively supported by some compilers (e.g. gcc). #define AtomicallyInitializedStatic(T, name) \ @@ -112,6 +81,11 @@ namespace WTF { typedef uint32_t ThreadIdentifier; typedef void* (*ThreadFunction)(void* argument); +// This function must be called from the main thread. It is safe to call it repeatedly. +// Darwin is an exception to this rule: it is OK to call it from any thread, the only +// requirement is that the calls are not reentrant. +void initializeThreading(); + // Returns 0 if thread creation failed. // The thread name must be a literal since on some platforms it's passed in to the thread. ThreadIdentifier createThread(ThreadFunction, void*, const char* threadName); @@ -124,226 +98,18 @@ ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char* threadN void initializeCurrentThreadInternal(const char* threadName); ThreadIdentifier currentThread(); -bool isMainThread(); int waitForThreadCompletion(ThreadIdentifier, void**); void detachThread(ThreadIdentifier); -#if USE(PTHREADS) -typedef pthread_mutex_t PlatformMutex; -#if HAVE(PTHREAD_RWLOCK) -typedef pthread_rwlock_t PlatformReadWriteLock; -#else -typedef void* PlatformReadWriteLock; -#endif -typedef pthread_cond_t PlatformCondition; -#elif PLATFORM(GTK) -typedef GOwnPtr<GMutex> PlatformMutex; -typedef void* PlatformReadWriteLock; // FIXME: Implement. -typedef GOwnPtr<GCond> PlatformCondition; -#elif PLATFORM(QT) -typedef QT_PREPEND_NAMESPACE(QMutex)* PlatformMutex; -typedef void* PlatformReadWriteLock; // FIXME: Implement. -typedef QT_PREPEND_NAMESPACE(QWaitCondition)* PlatformCondition; -#elif OS(WINDOWS) -struct PlatformMutex { - CRITICAL_SECTION m_internalMutex; - size_t m_recursionCount; -}; -typedef void* PlatformReadWriteLock; // FIXME: Implement. -struct PlatformCondition { - size_t m_waitersGone; - size_t m_waitersBlocked; - size_t m_waitersToUnblock; - HANDLE m_blockLock; - HANDLE m_blockQueue; - HANDLE m_unblockLock; - - bool timedWait(PlatformMutex&, DWORD durationMilliseconds); - void signal(bool unblockAll); -}; -#else -typedef void* PlatformMutex; -typedef void* PlatformReadWriteLock; -typedef void* PlatformCondition; -#endif - -class Mutex : public Noncopyable { -public: - Mutex(); - ~Mutex(); - - void lock(); - bool tryLock(); - void unlock(); - -public: - PlatformMutex& impl() { return m_mutex; } -private: - PlatformMutex m_mutex; -}; - -typedef Locker<Mutex> MutexLocker; - -class ReadWriteLock : public Noncopyable { -public: - ReadWriteLock(); - ~ReadWriteLock(); - - void readLock(); - bool tryReadLock(); - - void writeLock(); - bool tryWriteLock(); - - void unlock(); - -private: - PlatformReadWriteLock m_readWriteLock; -}; - -class ThreadCondition : public Noncopyable { -public: - ThreadCondition(); - ~ThreadCondition(); - - void wait(Mutex& mutex); - // Returns true if the condition was signaled before absoluteTime, false if the absoluteTime was reached or is in the past. - // The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the same time zone as WTF::currentTime(). - bool timedWait(Mutex&, double absoluteTime); - void signal(); - void broadcast(); - -private: - PlatformCondition m_condition; -}; - -#if OS(WINDOWS) -#define WTF_USE_LOCKFREE_THREADSAFESHARED 1 - -#if COMPILER(MINGW) || COMPILER(MSVC7) || OS(WINCE) -inline int atomicIncrement(int* addend) { return InterlockedIncrement(reinterpret_cast<long*>(addend)); } -inline int atomicDecrement(int* addend) { return InterlockedDecrement(reinterpret_cast<long*>(addend)); } -#else -inline int atomicIncrement(int volatile* addend) { return InterlockedIncrement(reinterpret_cast<long volatile*>(addend)); } -inline int atomicDecrement(int volatile* addend) { return InterlockedDecrement(reinterpret_cast<long volatile*>(addend)); } -#endif - -#elif OS(DARWIN) -#define WTF_USE_LOCKFREE_THREADSAFESHARED 1 - -inline int atomicIncrement(int volatile* addend) { return OSAtomicIncrement32Barrier(const_cast<int*>(addend)); } -inline int atomicDecrement(int volatile* addend) { return OSAtomicDecrement32Barrier(const_cast<int*>(addend)); } - -#elif OS(ANDROID) - -inline int atomicIncrement(int volatile* addend) { return android_atomic_inc(addend); } -inline int atomicDecrement(int volatile* addend) { return android_atomic_dec(addend); } - -#elif COMPILER(GCC) && !CPU(SPARC64) && !OS(SYMBIAN) // sizeof(_Atomic_word) != sizeof(int) on sparc64 gcc -#define WTF_USE_LOCKFREE_THREADSAFESHARED 1 - -inline int atomicIncrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, 1) + 1; } -inline int atomicDecrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, -1) - 1; } - -#endif - -class ThreadSafeSharedBase : public Noncopyable { -public: - ThreadSafeSharedBase(int initialRefCount = 1) - : m_refCount(initialRefCount) - { - } - - void ref() - { -#if USE(LOCKFREE_THREADSAFESHARED) - atomicIncrement(&m_refCount); -#else - MutexLocker locker(m_mutex); - ++m_refCount; -#endif - } - - bool hasOneRef() - { - return refCount() == 1; - } - - int refCount() const - { -#if !USE(LOCKFREE_THREADSAFESHARED) - MutexLocker locker(m_mutex); -#endif - return static_cast<int const volatile &>(m_refCount); - } - -protected: - // Returns whether the pointer should be freed or not. - bool derefBase() - { -#if USE(LOCKFREE_THREADSAFESHARED) - if (atomicDecrement(&m_refCount) <= 0) - return true; -#else - int refCount; - { - MutexLocker locker(m_mutex); - --m_refCount; - refCount = m_refCount; - } - if (refCount <= 0) - return true; -#endif - return false; - } - -private: - template<class T> - friend class CrossThreadRefCounted; - - int m_refCount; -#if !USE(LOCKFREE_THREADSAFESHARED) - mutable Mutex m_mutex; -#endif -}; - -template<class T> class ThreadSafeShared : public ThreadSafeSharedBase { -public: - ThreadSafeShared(int initialRefCount = 1) - : ThreadSafeSharedBase(initialRefCount) - { - } - - void deref() - { - if (derefBase()) - delete static_cast<T*>(this); - } -}; - -// This function must be called from the main thread. It is safe to call it repeatedly. -// Darwin is an exception to this rule: it is OK to call it from any thread, the only requirement is that the calls are not reentrant. -void initializeThreading(); void lockAtomicallyInitializedStaticMutex(); void unlockAtomicallyInitializedStaticMutex(); } // namespace WTF -using WTF::Mutex; -using WTF::MutexLocker; -using WTF::ThreadCondition; using WTF::ThreadIdentifier; -using WTF::ThreadSafeShared; - -#if USE(LOCKFREE_THREADSAFESHARED) -using WTF::atomicDecrement; -using WTF::atomicIncrement; -#endif - using WTF::createThread; using WTF::currentThread; -using WTF::isMainThread; using WTF::detachThread; using WTF::waitForThreadCompletion; diff --git a/JavaScriptCore/wtf/ThreadingPrimitives.h b/JavaScriptCore/wtf/ThreadingPrimitives.h new file mode 100644 index 0000000..66801c0 --- /dev/null +++ b/JavaScriptCore/wtf/ThreadingPrimitives.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.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. + * + */ + +#ifndef ThreadingPrimitives_h +#define ThreadingPrimitives_h + +#include "Platform.h" + +#include <wtf/Assertions.h> +#include <wtf/Locker.h> +#include <wtf/Noncopyable.h> + +#if OS(WINDOWS) +#include <windows.h> +#endif + +#if USE(PTHREADS) +#include <pthread.h> +#elif PLATFORM(GTK) +#include "GOwnPtr.h" +typedef struct _GMutex GMutex; +typedef struct _GCond GCond; +#endif + +#if PLATFORM(QT) +#include <qglobal.h> +QT_BEGIN_NAMESPACE +class QMutex; +class QWaitCondition; +QT_END_NAMESPACE +#endif + +namespace WTF { + +#if USE(PTHREADS) +typedef pthread_mutex_t PlatformMutex; +#if HAVE(PTHREAD_RWLOCK) +typedef pthread_rwlock_t PlatformReadWriteLock; +#else +typedef void* PlatformReadWriteLock; +#endif +typedef pthread_cond_t PlatformCondition; +#elif PLATFORM(GTK) +typedef GOwnPtr<GMutex> PlatformMutex; +typedef void* PlatformReadWriteLock; // FIXME: Implement. +typedef GOwnPtr<GCond> PlatformCondition; +#elif PLATFORM(QT) +typedef QT_PREPEND_NAMESPACE(QMutex)* PlatformMutex; +typedef void* PlatformReadWriteLock; // FIXME: Implement. +typedef QT_PREPEND_NAMESPACE(QWaitCondition)* PlatformCondition; +#elif OS(WINDOWS) +struct PlatformMutex { + CRITICAL_SECTION m_internalMutex; + size_t m_recursionCount; +}; +typedef void* PlatformReadWriteLock; // FIXME: Implement. +struct PlatformCondition { + size_t m_waitersGone; + size_t m_waitersBlocked; + size_t m_waitersToUnblock; + HANDLE m_blockLock; + HANDLE m_blockQueue; + HANDLE m_unblockLock; + + bool timedWait(PlatformMutex&, DWORD durationMilliseconds); + void signal(bool unblockAll); +}; +#else +typedef void* PlatformMutex; +typedef void* PlatformReadWriteLock; +typedef void* PlatformCondition; +#endif + +class Mutex : public Noncopyable { +public: + Mutex(); + ~Mutex(); + + void lock(); + bool tryLock(); + void unlock(); + +public: + PlatformMutex& impl() { return m_mutex; } +private: + PlatformMutex m_mutex; +}; + +typedef Locker<Mutex> MutexLocker; + +class ReadWriteLock : public Noncopyable { +public: + ReadWriteLock(); + ~ReadWriteLock(); + + void readLock(); + bool tryReadLock(); + + void writeLock(); + bool tryWriteLock(); + + void unlock(); + +private: + PlatformReadWriteLock m_readWriteLock; +}; + +class ThreadCondition : public Noncopyable { +public: + ThreadCondition(); + ~ThreadCondition(); + + void wait(Mutex& mutex); + // Returns true if the condition was signaled before absoluteTime, false if the absoluteTime was reached or is in the past. + // The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the same time zone as WTF::currentTime(). + bool timedWait(Mutex&, double absoluteTime); + void signal(); + void broadcast(); + +private: + PlatformCondition m_condition; +}; + +} // namespace WTF + +using WTF::Mutex; +using WTF::MutexLocker; +using WTF::ThreadCondition; + +#endif // ThreadingPrimitives_h diff --git a/JavaScriptCore/wtf/ThreadingPthreads.cpp b/JavaScriptCore/wtf/ThreadingPthreads.cpp index 5a7ff55..7ff9266 100644 --- a/JavaScriptCore/wtf/ThreadingPthreads.cpp +++ b/JavaScriptCore/wtf/ThreadingPthreads.cpp @@ -57,10 +57,6 @@ typedef HashMap<ThreadIdentifier, pthread_t> ThreadMap; static Mutex* atomicallyInitializedStaticMutex; -#if !OS(DARWIN) || PLATFORM(CHROMIUM) || USE(WEB_THREAD) -static pthread_t mainThread; // The thread that was the first to call initializeThreading(), which must be the main thread. -#endif - void clearPthreadHandleForIdentifier(ThreadIdentifier); static Mutex& threadMapMutex() @@ -71,15 +67,12 @@ static Mutex& threadMapMutex() void initializeThreading() { - if (!atomicallyInitializedStaticMutex) { - atomicallyInitializedStaticMutex = new Mutex; - threadMapMutex(); - initializeRandomNumberGenerator(); -#if !OS(DARWIN) || PLATFORM(CHROMIUM) || USE(WEB_THREAD) - mainThread = pthread_self(); -#endif - initializeMainThread(); - } + if (atomicallyInitializedStaticMutex) + return; + + atomicallyInitializedStaticMutex = new Mutex; + threadMapMutex(); + initializeRandomNumberGenerator(); } void lockAtomicallyInitializedStaticMutex() @@ -240,15 +233,6 @@ ThreadIdentifier currentThread() return id; } -bool isMainThread() -{ -#if OS(DARWIN) && !PLATFORM(CHROMIUM) && !USE(WEB_THREAD) - return pthread_main_np(); -#else - return pthread_equal(pthread_self(), mainThread); -#endif -} - Mutex::Mutex() { pthread_mutex_init(&m_mutex, NULL); diff --git a/JavaScriptCore/wtf/ThreadingWin.cpp b/JavaScriptCore/wtf/ThreadingWin.cpp index 73c3f0c..c16be5a 100644 --- a/JavaScriptCore/wtf/ThreadingWin.cpp +++ b/JavaScriptCore/wtf/ThreadingWin.cpp @@ -145,8 +145,6 @@ void unlockAtomicallyInitializedStaticMutex() atomicallyInitializedStaticMutex->unlock(); } -static ThreadIdentifier mainThreadIdentifier; - static Mutex& threadMapMutex() { static Mutex mutex; @@ -155,14 +153,12 @@ static Mutex& threadMapMutex() void initializeThreading() { - if (!atomicallyInitializedStaticMutex) { - atomicallyInitializedStaticMutex = new Mutex; - threadMapMutex(); - initializeRandomNumberGenerator(); - initializeMainThread(); - mainThreadIdentifier = currentThread(); - initializeCurrentThreadInternal("Main Thread"); - } + if (atomicallyInitializedStaticMutex) + return; + + atomicallyInitializedStaticMutex = new Mutex; + threadMapMutex(); + initializeRandomNumberGenerator(); } static HashMap<DWORD, HANDLE>& threadMap() @@ -275,11 +271,6 @@ ThreadIdentifier currentThread() return static_cast<ThreadIdentifier>(GetCurrentThreadId()); } -bool isMainThread() -{ - return currentThread() == mainThreadIdentifier; -} - Mutex::Mutex() { m_mutex.m_recursionCount = 0; diff --git a/JavaScriptCore/wtf/Vector.h b/JavaScriptCore/wtf/Vector.h index 6f55e53..e495067 100644 --- a/JavaScriptCore/wtf/Vector.h +++ b/JavaScriptCore/wtf/Vector.h @@ -939,7 +939,7 @@ namespace WTF { return; } -#if COMPILER(MSVC7) +#if COMPILER(MSVC7_OR_LOWER) // FIXME: MSVC7 generates compilation errors when trying to assign // a pointer to a Vector of its base class (i.e. can't downcast). So far // I've been unable to determine any logical reason for this, so I can diff --git a/JavaScriptCore/wtf/WTFThreadData.cpp b/JavaScriptCore/wtf/WTFThreadData.cpp index bbc9986..0716dc9 100644 --- a/JavaScriptCore/wtf/WTFThreadData.cpp +++ b/JavaScriptCore/wtf/WTFThreadData.cpp @@ -39,8 +39,8 @@ WTFThreadData::WTFThreadData() : m_atomicStringTable(0) , m_atomicStringTableDestructor(0) #if USE(JSC) - , m_defaultIdentifierTable(0) - , m_currentIdentifierTable(0) + , m_defaultIdentifierTable(new JSC::IdentifierTable()) + , m_currentIdentifierTable(m_defaultIdentifierTable) #endif { } @@ -49,6 +49,9 @@ WTFThreadData::~WTFThreadData() { if (m_atomicStringTableDestructor) m_atomicStringTableDestructor(m_atomicStringTable); +#if USE(JSC) + delete m_defaultIdentifierTable; +#endif } } // namespace WebCore diff --git a/JavaScriptCore/wtf/OwnPtrBrew.cpp b/JavaScriptCore/wtf/brew/OwnPtrBrew.cpp index c8384e1..c8384e1 100644 --- a/JavaScriptCore/wtf/OwnPtrBrew.cpp +++ b/JavaScriptCore/wtf/brew/OwnPtrBrew.cpp diff --git a/JavaScriptCore/wtf/chromium/ChromiumThreading.h b/JavaScriptCore/wtf/chromium/ChromiumThreading.h index b2c5075..3938621 100644 --- a/JavaScriptCore/wtf/chromium/ChromiumThreading.h +++ b/JavaScriptCore/wtf/chromium/ChromiumThreading.h @@ -36,8 +36,7 @@ namespace WTF { // An interface to the embedding layer, which provides threading support. class ChromiumThreading { public: - static void initializeMainThread(); - static void scheduleDispatchFunctionsOnMainThread(); + static void callOnMainThread(void (*func)(void*), void* context); }; } // namespace WTF diff --git a/JavaScriptCore/wtf/chromium/MainThreadChromium.cpp b/JavaScriptCore/wtf/chromium/MainThreadChromium.cpp index 394370f..9e6592b 100644 --- a/JavaScriptCore/wtf/chromium/MainThreadChromium.cpp +++ b/JavaScriptCore/wtf/chromium/MainThreadChromium.cpp @@ -31,18 +31,42 @@ #include "config.h" #include "MainThread.h" +#include "Assertions.h" #include "ChromiumThreading.h" +#include "Threading.h" namespace WTF { -void initializeMainThreadPlatform() +static ThreadIdentifier mainThreadIdentifier; + +void initializeMainThread() +{ + static bool initializedMainThread; + if (initializedMainThread) + return; + initializedMainThread = true; + + mainThreadIdentifier = currentThread(); +} + +void callOnMainThread(MainThreadFunction* function, void* context) +{ + ChromiumThreading::callOnMainThread(function, context); +} + +void callOnMainThreadAndWait(MainThreadFunction*, void*) +{ + ASSERT_NOT_REACHED(); +} + +void setMainThreadCallbacksPaused(bool) { - ChromiumThreading::initializeMainThread(); + ASSERT_NOT_REACHED(); } -void scheduleDispatchFunctionsOnMainThread() +bool isMainThread() { - ChromiumThreading::scheduleDispatchFunctionsOnMainThread(); + return currentThread() == mainThreadIdentifier; } } // namespace WTF diff --git a/JavaScriptCore/wtf/gobject/GRefPtr.h b/JavaScriptCore/wtf/gobject/GRefPtr.h index 66739ef..3a33605 100644 --- a/JavaScriptCore/wtf/gobject/GRefPtr.h +++ b/JavaScriptCore/wtf/gobject/GRefPtr.h @@ -27,6 +27,9 @@ #include <algorithm> typedef struct _GHashTable GHashTable; +typedef void* gpointer; +extern "C" void g_object_unref(gpointer object); +extern "C" gpointer g_object_ref_sink(gpointer object); namespace WTF { diff --git a/JavaScriptCore/wtf/gtk/ThreadingGtk.cpp b/JavaScriptCore/wtf/gtk/ThreadingGtk.cpp index a6ec8f7..0c5cf0c 100644 --- a/JavaScriptCore/wtf/gtk/ThreadingGtk.cpp +++ b/JavaScriptCore/wtf/gtk/ThreadingGtk.cpp @@ -44,8 +44,6 @@ namespace WTF { static Mutex* atomicallyInitializedStaticMutex; -static ThreadIdentifier mainThreadIdentifier; - static Mutex& threadMapMutex() { static Mutex mutex; @@ -62,8 +60,6 @@ void initializeThreading() atomicallyInitializedStaticMutex = new Mutex; threadMapMutex(); initializeRandomNumberGenerator(); - mainThreadIdentifier = currentThread(); - initializeMainThread(); } } @@ -168,11 +164,6 @@ ThreadIdentifier currentThread() return establishIdentifierForThread(currentThread); } -bool isMainThread() -{ - return currentThread() == mainThreadIdentifier; -} - Mutex::Mutex() : m_mutex(g_mutex_new()) { diff --git a/JavaScriptCore/wtf/mac/MainThreadMac.mm b/JavaScriptCore/wtf/mac/MainThreadMac.mm index 586ef4d..17363bc 100644 --- a/JavaScriptCore/wtf/mac/MainThreadMac.mm +++ b/JavaScriptCore/wtf/mac/MainThreadMac.mm @@ -31,6 +31,7 @@ #import <CoreFoundation/CoreFoundation.h> #import <Foundation/NSThread.h> +#import <stdio.h> #import <wtf/Assertions.h> #import <wtf/Threading.h> @@ -50,22 +51,38 @@ namespace WTF { -static WTFMainThreadCaller* staticMainThreadCaller = nil; -#if USE(WEB_THREAD) -static NSThread* webThread = nil; -#endif +static WTFMainThreadCaller* staticMainThreadCaller; +static bool isTimerPosted; // This is only accessed on the 'main' thread. +static bool mainThreadEstablishedAsPthreadMain; +static pthread_t mainThreadPthread; +static NSThread* mainThreadNSThread; void initializeMainThreadPlatform() { +#if !defined(BUILDING_ON_TIGER) ASSERT(!staticMainThreadCaller); staticMainThreadCaller = [[WTFMainThreadCaller alloc] init]; -#if USE(WEB_THREAD) - webThread = [[NSThread currentThread] retain]; + mainThreadEstablishedAsPthreadMain = false; + mainThreadPthread = pthread_self(); + mainThreadNSThread = [[NSThread currentThread] retain]; +#else + ASSERT_NOT_REACHED(); #endif } -static bool isTimerPosted; // This is only accessed on the 'main' thread. +void initializeMainThreadToProcessMainThreadPlatform() +{ + if (!pthread_main_np()) + NSLog(@"WebKit Threading Violation - initial use of WebKit from a secondary thread."); + + ASSERT(!staticMainThreadCaller); + staticMainThreadCaller = [[WTFMainThreadCaller alloc] init]; + + mainThreadEstablishedAsPthreadMain = true; + mainThreadPthread = 0; + mainThreadNSThread = nil; +} static void timerFired(CFRunLoopTimerRef timer, void*) { @@ -85,7 +102,6 @@ static void postTimer() CFRunLoopAddTimer(CFRunLoopGetCurrent(), CFRunLoopTimerCreate(0, 0, 0, 0, 0, timerFired, 0), kCFRunLoopCommonModes); } - void scheduleDispatchFunctionsOnMainThread() { ASSERT(staticMainThreadCaller); @@ -95,10 +111,33 @@ void scheduleDispatchFunctionsOnMainThread() return; } -#if USE(WEB_THREAD) - [staticMainThreadCaller performSelector:@selector(call) onThread:webThread withObject:nil waitUntilDone:NO]; + if (mainThreadEstablishedAsPthreadMain) { + ASSERT(!mainThreadNSThread); + [staticMainThreadCaller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO]; + return; + } + +#if !defined(BUILDING_ON_TIGER) + ASSERT(mainThreadNSThread); + [staticMainThreadCaller performSelector:@selector(call) onThread:mainThreadNSThread withObject:nil waitUntilDone:NO]; +#else + ASSERT_NOT_REACHED(); +#endif +} + +bool isMainThread() +{ + if (mainThreadEstablishedAsPthreadMain) { + ASSERT(!mainThreadPthread); + return pthread_main_np(); + } + +#if !defined(BUILDING_ON_TIGER) + ASSERT(mainThreadPthread); + return pthread_equal(pthread_self(), mainThreadPthread); #else - [staticMainThreadCaller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO]; + ASSERT_NOT_REACHED(); + return false; #endif } diff --git a/JavaScriptCore/wtf/qt/MainThreadQt.cpp b/JavaScriptCore/wtf/qt/MainThreadQt.cpp index 7b2d0f2..98b6a0c 100644 --- a/JavaScriptCore/wtf/qt/MainThreadQt.cpp +++ b/JavaScriptCore/wtf/qt/MainThreadQt.cpp @@ -33,7 +33,7 @@ #include <QtCore/QObject> #include <QtCore/QCoreApplication> - +#include <QThread> namespace WTF { @@ -67,6 +67,11 @@ void scheduleDispatchFunctionsOnMainThread() QMetaObject::invokeMethod(webkit_main_thread_invoker(), "dispatch", Qt::QueuedConnection); } +bool isMainThread() +{ + return QThread::currentThread() == QCoreApplication::instance()->thread(); +} + } // namespace WTF #include "MainThreadQt.moc" diff --git a/JavaScriptCore/wtf/qt/ThreadingQt.cpp b/JavaScriptCore/wtf/qt/ThreadingQt.cpp index dc04a68..7f81646 100644 --- a/JavaScriptCore/wtf/qt/ThreadingQt.cpp +++ b/JavaScriptCore/wtf/qt/ThreadingQt.cpp @@ -84,8 +84,6 @@ public Q_SLOTS: static Mutex* atomicallyInitializedStaticMutex; -static ThreadIdentifier mainThreadIdentifier; - static Mutex& threadMapMutex() { static Mutex mutex; @@ -146,11 +144,6 @@ void initializeThreading() atomicallyInitializedStaticMutex = new Mutex; threadMapMutex(); initializeRandomNumberGenerator(); - QThread* mainThread = QCoreApplication::instance()->thread(); - mainThreadIdentifier = identifierByQthreadHandle(mainThread); - if (!mainThreadIdentifier) - mainThreadIdentifier = establishIdentifierForThread(mainThread); - initializeMainThread(); } } @@ -215,11 +208,6 @@ ThreadIdentifier currentThread() return establishIdentifierForThread(currentThread); } -bool isMainThread() -{ - return QThread::currentThread() == QCoreApplication::instance()->thread(); -} - Mutex::Mutex() : m_mutex(new QMutex()) { diff --git a/JavaScriptCore/wtf/text/AtomicString.cpp b/JavaScriptCore/wtf/text/AtomicString.cpp index 79b9ab5..ab52488 100644 --- a/JavaScriptCore/wtf/text/AtomicString.cpp +++ b/JavaScriptCore/wtf/text/AtomicString.cpp @@ -28,8 +28,8 @@ #include "StaticConstructors.h" #include "StringHash.h" -#include <wtf/Threading.h> #include <wtf/HashSet.h> +#include <wtf/Threading.h> #include <wtf/WTFThreadData.h> namespace WebCore { @@ -55,6 +55,9 @@ public: private: static void destroy(AtomicStringTable* table) { + HashSet<StringImpl*>::iterator end = table->m_table.end(); + for (HashSet<StringImpl*>::iterator iter = table->m_table.begin(); iter != end; ++iter) + (*iter)->setIsAtomic(false); delete table; } @@ -92,7 +95,7 @@ struct CStringTranslator { { location = StringImpl::create(c).releaseRef(); location->setHash(hash); - location->setInTable(); + location->setIsAtomic(true); } }; @@ -171,7 +174,7 @@ struct UCharBufferTranslator { { location = StringImpl::create(buf.s, buf.length).releaseRef(); location->setHash(hash); - location->setInTable(); + location->setIsAtomic(true); } }; @@ -197,7 +200,7 @@ struct HashAndCharactersTranslator { { location = StringImpl::create(buffer.characters, buffer.length).releaseRef(); location->setHash(hash); - location->setInTable(); + location->setIsAtomic(true); } }; @@ -254,7 +257,7 @@ PassRefPtr<StringImpl> AtomicString::add(const UChar* s) PassRefPtr<StringImpl> AtomicString::add(StringImpl* r) { - if (!r || r->inTable()) + if (!r || r->isAtomic()) return r; if (r->length() == 0) @@ -262,7 +265,7 @@ PassRefPtr<StringImpl> AtomicString::add(StringImpl* r) StringImpl* result = *stringTable().add(r).first; if (result == r) - r->setInTable(); + r->setIsAtomic(true); return result; } diff --git a/JavaScriptCore/wtf/text/AtomicStringImpl.h b/JavaScriptCore/wtf/text/AtomicStringImpl.h index d21a00a..4b813f8 100644 --- a/JavaScriptCore/wtf/text/AtomicStringImpl.h +++ b/JavaScriptCore/wtf/text/AtomicStringImpl.h @@ -29,6 +29,8 @@ namespace WebCore { class AtomicStringImpl : public StringImpl { +public: + AtomicStringImpl() : StringImpl(0) {} }; } diff --git a/JavaScriptCore/wtf/text/StringImpl.cpp b/JavaScriptCore/wtf/text/StringImpl.cpp index 287e529..ff69737 100644 --- a/JavaScriptCore/wtf/text/StringImpl.cpp +++ b/JavaScriptCore/wtf/text/StringImpl.cpp @@ -42,7 +42,7 @@ StringImpl::~StringImpl() { ASSERT(!isStatic()); - if (inTable()) + if (isAtomic()) AtomicString::remove(this); #if USE(JSC) if (isIdentifier()) @@ -879,7 +879,7 @@ Vector<char> StringImpl::ascii() for (unsigned i = 0; i != m_length; ++i) { UChar c = m_data[i]; if ((c >= 0x20 && c < 0x7F) || c == 0x00) - buffer[i] = c; + buffer[i] = static_cast<char>(c); else buffer[i] = '?'; } diff --git a/JavaScriptCore/wtf/text/StringImpl.h b/JavaScriptCore/wtf/text/StringImpl.h index 6ac9e40..dbf51e3 100644 --- a/JavaScriptCore/wtf/text/StringImpl.h +++ b/JavaScriptCore/wtf/text/StringImpl.h @@ -27,6 +27,7 @@ #include <wtf/ASCIICType.h> #include <wtf/CrossThreadRefCounted.h> #include <wtf/OwnFastMallocPtr.h> +#include <wtf/StdLibExtras.h> #include <wtf/StringHashFunctions.h> #include <wtf/Vector.h> #include <wtf/text/StringImplBase.h> @@ -72,6 +73,7 @@ class StringImpl : public StringImplBase { friend struct CStringTranslator; friend struct HashAndCharactersTranslator; friend struct UCharBufferTranslator; + friend class AtomicStringImpl; private: // Used to construct static strings, which have an special refCount that can never hit zero. // This means that the static string will never be destroyed, which is important because @@ -178,6 +180,7 @@ public: return adoptRef(new(resultImpl) StringImpl(length)); } + static unsigned dataOffset() { return OBJECT_OFFSETOF(StringImpl, m_data); } static PassRefPtr<StringImpl> createWithTerminatingNullCharacter(const StringImpl&); static PassRefPtr<StringImpl> createStrippingNullCharacters(const UChar*, unsigned length); @@ -220,8 +223,15 @@ public: bool hasTerminatingNullCharacter() const { return m_refCountAndFlags & s_refCountFlagHasTerminatingNullCharacter; } - bool inTable() const { return m_refCountAndFlags & s_refCountFlagInTable; } - void setInTable() { m_refCountAndFlags |= s_refCountFlagInTable; } + bool isAtomic() const { return m_refCountAndFlags & s_refCountFlagIsAtomic; } + void setIsAtomic(bool isIdentifier) + { + ASSERT(!isStatic()); + if (isIdentifier) + m_refCountAndFlags |= s_refCountFlagIsAtomic; + else + m_refCountAndFlags &= ~s_refCountFlagIsAtomic; + } unsigned hash() const { if (!m_hash) m_hash = computeHash(m_data, m_length); return m_hash; } unsigned existingHash() const { ASSERT(m_hash); return m_hash; } @@ -317,7 +327,6 @@ private: BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_refCountAndFlags & s_refCountMaskBufferOwnership); } bool isStatic() const { return m_refCountAndFlags & s_refCountFlagStatic; } - const UChar* m_data; union { void* m_buffer; diff --git a/JavaScriptCore/wtf/text/StringImplBase.h b/JavaScriptCore/wtf/text/StringImplBase.h index a8e3385..6567672 100644 --- a/JavaScriptCore/wtf/text/StringImplBase.h +++ b/JavaScriptCore/wtf/text/StringImplBase.h @@ -83,7 +83,7 @@ protected: static const unsigned s_refCountIncrement = 0x80; static const unsigned s_refCountFlagStatic = 0x40; static const unsigned s_refCountFlagHasTerminatingNullCharacter = 0x20; - static const unsigned s_refCountFlagInTable = 0x10; + static const unsigned s_refCountFlagIsAtomic = 0x10; static const unsigned s_refCountFlagShouldReportedCost = 0x8; static const unsigned s_refCountFlagIsIdentifier = 0x4; static const unsigned s_refCountMaskBufferOwnership = 0x3; diff --git a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h index 9b1754a..97c42b7 100644 --- a/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h +++ b/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h @@ -56,7 +56,7 @@ namespace QUnicodeTables { QT_END_NAMESPACE // ugly hack to make UChar compatible with JSChar in API/JSStringRef.h -#if defined(Q_OS_WIN) || COMPILER(WINSCW) || COMPILER(RVCT) +#if defined(Q_OS_WIN) || COMPILER(WINSCW) || (COMPILER(RVCT) && OS(SYMBIAN)) typedef wchar_t UChar; #else typedef uint16_t UChar; diff --git a/JavaScriptCore/wtf/url/src/URLComponent.h b/JavaScriptCore/wtf/url/src/URLComponent.h new file mode 100644 index 0000000..ca7e6f3 --- /dev/null +++ b/JavaScriptCore/wtf/url/src/URLComponent.h @@ -0,0 +1,71 @@ +// Copyright 2010, Google 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER 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 URLComponent_h +#define URLComponent_h + +namespace WTF { + +// Represents a substring for URL parsing. +class URLComponent { +public: + URLComponent() : m_begin(0), m_length(-1) { } + URLComponent(int begin, int length) : m_begin(begin), m_length(length) { } + + // Returns true if this component is valid, meaning the length is given. Even + // valid components may be empty to record the fact that they exist. + bool isValid() const { return m_length != -1; } + + // Returns true if the given component is specified on false, the component + // is either empty or invalid. + bool isNonempty() const { return m_length > 0; } + + void reset() + { + m_begin = 0; + m_length = -1; + } + + bool operator==(const URLComponent& other) const { return m_begin == other.m_begin && m_length == other.m_length; } + + int begin() const { return m_begin; } + void setBegin(int begin) { m_begin = begin; } + + int length() const { return m_length; } + void setLength(int length) { m_length = length; } + + int end() const { return m_begin + m_length; } + +private: + int m_begin; // Byte offset in the string of this component. + int m_length; // Will be -1 if the component is unspecified. +}; + +} // namespace WTF + +#endif // URLComponent_h diff --git a/JavaScriptCore/wtf/url/src/URLSegments.cpp b/JavaScriptCore/wtf/url/src/URLSegments.cpp new file mode 100644 index 0000000..bb9542f --- /dev/null +++ b/JavaScriptCore/wtf/url/src/URLSegments.cpp @@ -0,0 +1,110 @@ +/* Based on nsURLParsers.cc from Mozilla + * ------------------------------------- + * Copyright (C) 1998 Netscape Communications Corporation. + * + * Other contributors: + * Darin Fisher (original author) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Alternatively, the contents of this file may be used under the terms + * of either the Mozilla Public License Version 1.1, found at + * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public + * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html + * (the "GPL"), in which case the provisions of the MPL or the GPL are + * applicable instead of those above. If you wish to allow use of your + * version of this file only under the terms of one of those two + * licenses (the MPL or the GPL) and not to allow others to use your + * version of this file under the LGPL, indicate your decision by + * deletingthe provisions above and replace them with the notice and + * other provisions required by the MPL or the GPL, as the case may be. + * If you do not delete the provisions above, a recipient may use your + * version of this file under any of the LGPL, the MPL or the GPL. + */ + +#include "config.h" +#include "URLSegments.h" + +namespace WTF { + +int URLSegments::length() const +{ + if (fragment.isValid()) + return fragment.end(); + return charactersBefore(Fragment, false); +} + +int URLSegments::charactersBefore(ComponentType type, bool includeDelimiter) const +{ + if (type == Scheme) + return scheme.begin(); + + int current = 0; + if (scheme.isValid()) + current = scheme.end() + 1; // Advance over the ':' at the end of the scheme. + + if (username.isValid()) { + if (type <= Username) + return username.begin(); + current = username.end() + 1; // Advance over the '@' or ':' at the end. + } + + if (password.isValid()) { + if (type <= Password) + return password.begin(); + current = password.end() + 1; // Advance over the '@' at the end. + } + + if (host.isValid()) { + if (type <= Host) + return host.begin(); + current = host.end(); + } + + if (port.isValid()) { + if (type < Port || (type == Port && includeDelimiter)) + return port.begin() - 1; // Back over delimiter. + if (type == Port) + return port.begin(); // Don't want delimiter counted. + current = port.end(); + } + + if (path.isValid()) { + if (type <= Path) + return path.begin(); + current = path.end(); + } + + if (query.isValid()) { + if (type < Query || (type == Query && includeDelimiter)) + return query.begin() - 1; // Back over delimiter. + if (type == Query) + return query.begin(); // Don't want delimiter counted. + current = query.end(); + } + + if (fragment.isValid()) { + if (type == Fragment && !includeDelimiter) + return fragment.begin(); // Back over delimiter. + + // When there is a fragment and we get here, the component we wanted was before + // this and not found, so we always know the beginning of the fragment is right. + return fragment.begin() - 1; // Don't want delimiter counted. + } + + return current; +} + +} // namespace WTF diff --git a/JavaScriptCore/wtf/url/src/URLSegments.h b/JavaScriptCore/wtf/url/src/URLSegments.h new file mode 100644 index 0000000..436c7fe --- /dev/null +++ b/JavaScriptCore/wtf/url/src/URLSegments.h @@ -0,0 +1,105 @@ +// Copyright 2007, Google 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER 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 URLSegments_h +#define URLSegments_h + +#include "URLComponent.h" + +namespace WTF { + +// A structure that holds the identified parts of an input URL. This structure +// does NOT store the URL itself. The caller will have to store the URL text +// and its corresponding Parsed structure separately. +class URLSegments { +public: + // Identifies different components. + enum ComponentType { + Scheme, + Username, + Password, + Host, + Port, + Path, + Query, + Fragment, + }; + + URLSegments() { } + + // Returns the length of the URL (the end of the last component). + // + // Note that for some invalid, non-canonical URLs, this may not be the length + // of the string. For example "http://": the parsed structure will only + // contain an entry for the four-character scheme, and it doesn't know about + // the "://". For all other last-components, it will return the real length. + int length() const; + + // Returns the number of characters before the given component if it exists, + // or where the component would be if it did exist. This will return the + // string length if the component would be appended to the end. + // + // Note that this can get a little funny for the port, query, and fragment + // components which have a delimiter that is not counted as part of the + // component. The |includeDelimiter| flag controls if you want this counted + // as part of the component or not when the component exists. + // + // This example shows the difference between the two flags for two of these + // delimited components that is present (the port and query) and one that + // isn't (the reference). The components that this flag affects are marked + // with a *. + // 0 1 2 + // 012345678901234567890 + // Example input: http://foo:80/?query + // include_delim=true, ...=false ("<-" indicates different) + // Scheme: 0 0 + // Username: 5 5 + // Password: 5 5 + // Host: 7 7 + // *Port: 10 11 <- + // Path: 13 13 + // *Query: 14 15 <- + // *Fragment: 20 20 + // + int charactersBefore(ComponentType, bool includeDelimiter) const; + + // Each component excludes the related delimiters and has a length of -1 + // if that component is absent but 0 if the component exists but is empty. + URLComponent scheme; + URLComponent username; + URLComponent password; + URLComponent host; + URLComponent port; + URLComponent path; + URLComponent query; + URLComponent fragment; +}; + +} // namespace WTF + +#endif // URLSegments_h diff --git a/JavaScriptCore/wtf/url/wtfurl.gyp b/JavaScriptCore/wtf/url/wtfurl.gyp new file mode 100644 index 0000000..f254ae4 --- /dev/null +++ b/JavaScriptCore/wtf/url/wtfurl.gyp @@ -0,0 +1,58 @@ +# Copyright (C) 2009 Google 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: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +# OWNER 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. + +{ + 'variables': { + 'chromium_code': 1, + }, + 'targets': [ + { + 'target_name': 'wtfurl', + 'type': '<(library)', + 'msvs_guid': 'EF5E94AB-B646-4E5B-A058-52EF07B8351C', + 'dependencies': [ + ], + 'sources': [ + 'src/URLComponent.h', + 'src/URLSegments.cpp', + 'src/URLSegments.h', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + 'src', + ], + }, + }, + ], +} + +# Local Variables: +# tab-width:2 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=2 shiftwidth=2: diff --git a/JavaScriptCore/wtf/win/MainThreadWin.cpp b/JavaScriptCore/wtf/win/MainThreadWin.cpp index ee70b59..ee3a273 100644 --- a/JavaScriptCore/wtf/win/MainThreadWin.cpp +++ b/JavaScriptCore/wtf/win/MainThreadWin.cpp @@ -77,6 +77,8 @@ void initializeMainThreadPlatform() threadingWindowHandle = CreateWindow(kThreadingWindowClassName, 0, 0, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, hWndParent, 0, 0, 0); threadingFiredMessage = RegisterWindowMessage(L"com.apple.WebKit.MainThreadFired"); + + initializeCurrentThreadInternal("Main Thread"); } void scheduleDispatchFunctionsOnMainThread() diff --git a/JavaScriptCore/wtf/OwnPtrWin.cpp b/JavaScriptCore/wtf/win/OwnPtrWin.cpp index 67a32ff..67a32ff 100644 --- a/JavaScriptCore/wtf/OwnPtrWin.cpp +++ b/JavaScriptCore/wtf/win/OwnPtrWin.cpp diff --git a/JavaScriptCore/wtf/wx/MainThreadWx.cpp b/JavaScriptCore/wtf/wx/MainThreadWx.cpp index bcd5f05..e1d15c9 100644 --- a/JavaScriptCore/wtf/wx/MainThreadWx.cpp +++ b/JavaScriptCore/wtf/wx/MainThreadWx.cpp @@ -29,6 +29,29 @@ #include "config.h" #include "MainThread.h" +#include <wx/defs.h> +#include <wx/app.h> +#include <wx/event.h> + +const wxEventType wxEVT_CALL_AFTER = wxNewEventType(); + +class wxCallAfter : public wxEvtHandler +{ +public: + wxCallAfter() + : wxEvtHandler() + { + wxTheApp->Connect(-1, -1, wxEVT_CALL_AFTER, wxCommandEventHandler(wxCallAfter::OnCallback)); + wxCommandEvent event(wxEVT_CALL_AFTER); + wxPostEvent(wxTheApp, event); + } + + void OnCallback(wxCommandEvent& event) + { + WTF::dispatchFunctionsFromMainThread(); + } +}; + namespace WTF { void initializeMainThreadPlatform() @@ -37,6 +60,7 @@ void initializeMainThreadPlatform() void scheduleDispatchFunctionsOnMainThread() { + wxCallAfter(); } } // namespace WTF diff --git a/JavaScriptGlue/ChangeLog b/JavaScriptGlue/ChangeLog index 69a8208..d442a77 100644 --- a/JavaScriptGlue/ChangeLog +++ b/JavaScriptGlue/ChangeLog @@ -1,3 +1,43 @@ +2010-04-23 Sam Weinig <sam@webkit.org> + + Reviewed by David Levin. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38060 + Split up Threading.h + + Add necessary forwarding headers. + + * ForwardingHeaders/wtf/Atomics.h: Added. + * ForwardingHeaders/wtf/ThreadSafeShared.h: Added. + * ForwardingHeaders/wtf/ThreadingPrimitives.h: Added. + +2010-04-22 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38022 + Move isMainThread predicate function to MainThread.h + + Added forwarding header for MainThread.h + + * ForwardingHeaders/wtf/MainThread.h: Added. + +2010-04-22 Gavin Barraclough <barraclough@apple.com> + + Rubber stamped by Sam Weinig + + Do not get the globaldata for the APIShim via the + global object; global object construction creates identifiers + which results in the ASSERTs checking the thread data's + identifierTable has been set failing. + + * JSUtils.cpp: + (unprotectGlobalObject): + (getThreadGlobalData): + (getThreadGlobalObject): + (JSGlueAPIEntry::JSGlueAPIEntry): + (JSGlueAPICallback::~JSGlueAPICallback): + 2010-04-21 Geoffrey Garen <ggaren@apple.com> Reviewed by Sam Weinig. diff --git a/JavaScriptGlue/Configurations/Version.xcconfig b/JavaScriptGlue/Configurations/Version.xcconfig index 6aeb263..cc5943e 100644 --- a/JavaScriptGlue/Configurations/Version.xcconfig +++ b/JavaScriptGlue/Configurations/Version.xcconfig @@ -22,7 +22,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAJOR_VERSION = 533; -MINOR_VERSION = 6; +MINOR_VERSION = 9; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/JavaScriptGlue/ForwardingHeaders/wtf/Atomics.h b/JavaScriptGlue/ForwardingHeaders/wtf/Atomics.h new file mode 100644 index 0000000..37b1892 --- /dev/null +++ b/JavaScriptGlue/ForwardingHeaders/wtf/Atomics.h @@ -0,0 +1 @@ +#include <JavaScriptCore/Atomics.h> diff --git a/JavaScriptGlue/ForwardingHeaders/wtf/MainThread.h b/JavaScriptGlue/ForwardingHeaders/wtf/MainThread.h new file mode 100644 index 0000000..ff75971 --- /dev/null +++ b/JavaScriptGlue/ForwardingHeaders/wtf/MainThread.h @@ -0,0 +1 @@ +#include <JavaScriptCore/MainThread.h> diff --git a/JavaScriptGlue/ForwardingHeaders/wtf/ThreadSafeShared.h b/JavaScriptGlue/ForwardingHeaders/wtf/ThreadSafeShared.h new file mode 100644 index 0000000..4a7a77f --- /dev/null +++ b/JavaScriptGlue/ForwardingHeaders/wtf/ThreadSafeShared.h @@ -0,0 +1 @@ +#include <JavaScriptCore/ThreadSafeShared.h> diff --git a/JavaScriptGlue/ForwardingHeaders/wtf/ThreadingPrimitives.h b/JavaScriptGlue/ForwardingHeaders/wtf/ThreadingPrimitives.h new file mode 100644 index 0000000..a7ee117 --- /dev/null +++ b/JavaScriptGlue/ForwardingHeaders/wtf/ThreadingPrimitives.h @@ -0,0 +1 @@ +#include <JavaScriptCore/ThreadingPrimitives.h> diff --git a/JavaScriptGlue/JSUtils.cpp b/JavaScriptGlue/JSUtils.cpp index f2b7e64..b83ac52 100644 --- a/JavaScriptGlue/JSUtils.cpp +++ b/JavaScriptGlue/JSUtils.cpp @@ -395,9 +395,8 @@ static pthread_once_t globalObjectKeyOnce = PTHREAD_ONCE_INIT; static void unprotectGlobalObject(void* data) { - JSGlobalObject* jsGlobalObject = static_cast<JSGlueGlobalObject*>(data); - JSGlueAPIEntry entry(jsGlobalObject); - gcUnprotect(jsGlobalObject); + JSGlueAPIEntry entry; + gcUnprotect(static_cast<JSGlueGlobalObject*>(data)); } static void initializeGlobalObjectKey() @@ -405,19 +404,18 @@ static void initializeGlobalObjectKey() pthread_key_create(&globalObjectKey, unprotectGlobalObject); } +JSGlobalData* getThreadGlobalData() +{ + return &JSGlobalData::sharedInstance(); +} + static JSGlueGlobalObject* getThreadGlobalObject() { pthread_once(&globalObjectKeyOnce, initializeGlobalObjectKey); JSGlueGlobalObject* globalObject = static_cast<JSGlueGlobalObject*>(pthread_getspecific(globalObjectKey)); if (!globalObject) { - JSGlobalData& globalData = JSGlobalData::sharedInstance(); - - IdentifierTable* storedIdentifierTable = wtfThreadData().currentIdentifierTable(); - wtfThreadData().setCurrentIdentifierTable(globalData.identifierTable); - globalObject = new (&globalData) JSGlueGlobalObject(JSGlueGlobalObject::createStructure(jsNull())); + globalObject = new (getThreadGlobalData()) JSGlueGlobalObject(JSGlueGlobalObject::createStructure(jsNull())); gcProtect(globalObject); - wtfThreadData().setCurrentIdentifierTable(storedIdentifierTable); - pthread_setspecific(globalObjectKey, globalObject); } return globalObject; @@ -437,14 +435,7 @@ JSGlueAPIEntry::JSGlueAPIEntry() : m_lock(LockForReal) , m_storedIdentifierTable(wtfThreadData().currentIdentifierTable()) { - wtfThreadData().setCurrentIdentifierTable(getThreadGlobalObject()->globalExec()->globalData().identifierTable); -} - -JSGlueAPIEntry::JSGlueAPIEntry(JSGlobalObject* jsGlobalObject) - : m_lock(LockForReal) - , m_storedIdentifierTable(wtfThreadData().currentIdentifierTable()) -{ - wtfThreadData().setCurrentIdentifierTable(jsGlobalObject->globalExec()->globalData().identifierTable); + wtfThreadData().setCurrentIdentifierTable(getThreadGlobalData()->identifierTable); } JSGlueAPIEntry::~JSGlueAPIEntry() @@ -460,5 +451,5 @@ JSGlueAPICallback::JSGlueAPICallback(ExecState* exec) JSGlueAPICallback::~JSGlueAPICallback() { - wtfThreadData().setCurrentIdentifierTable(getThreadGlobalObject()->globalExec()->globalData().identifierTable); + wtfThreadData().setCurrentIdentifierTable(getThreadGlobalData()->identifierTable); } diff --git a/LayoutTests/fast/events/touch/basic-multi-touch-events.html b/LayoutTests/fast/events/touch/basic-multi-touch-events.html index 951e169..cdf0a71 100644 --- a/LayoutTests/fast/events/touch/basic-multi-touch-events.html +++ b/LayoutTests/fast/events/touch/basic-multi-touch-events.html @@ -4,11 +4,16 @@ <link rel="stylesheet" href="../../js/resources/js-test-style.css"> <script src="../../js/resources/js-test-pre.js"></script> <script src="../../js/resources/js-test-post-function.js"></script> +<!-- + Touch tests that involve the ontouchstart, ontouchmove, ontouchend or ontouchcancel callbacks + should be written in an asynchronous fashion so they can be run on mobile platforms like Android. + This template will generate an asynchronous style test by using the js-test-post-function script. + You will need to invoke isSuccessfullyParsed() in your test script when the test completes. +--> </head> <body> <p id="description"></p> <div id="console"></div> <script src="script-tests/basic-multi-touch-events.js"></script> - </body> </html> diff --git a/LayoutTests/fast/events/touch/basic-single-touch-events-expected.txt b/LayoutTests/fast/events/touch/basic-single-touch-events-expected.txt index ec168cb..47fa08a 100644 --- a/LayoutTests/fast/events/touch/basic-single-touch-events-expected.txt +++ b/LayoutTests/fast/events/touch/basic-single-touch-events-expected.txt @@ -32,10 +32,10 @@ PASS lastEvent.changedTouches.length is 1 PASS lastEvent.targetTouches.length is 1 PASS lastEvent.pageX is 0 PASS lastEvent.pageY is 0 -PASS lastEvent.touches[0].pageX is 20 -PASS lastEvent.touches[0].pageY is 15 -PASS lastEvent.touches[0].clientX is 20 -PASS lastEvent.touches[0].clientY is 15 +PASS lastEvent.touches[0].pageX is 50 +PASS lastEvent.touches[0].pageY is 50 +PASS lastEvent.touches[0].clientX is 50 +PASS lastEvent.touches[0].clientY is 50 PASS lastEvent.touches[0].identifier is 0 PASS lastEvent.shiftKey is true PASS lastEvent.altKey is true @@ -47,10 +47,10 @@ PASS lastEvent.changedTouches.length is 1 PASS lastEvent.targetTouches.length is 0 PASS lastEvent.pageX is 0 PASS lastEvent.pageY is 0 -PASS lastEvent.changedTouches[0].pageX is 20 -PASS lastEvent.changedTouches[0].pageY is 15 -PASS lastEvent.changedTouches[0].clientX is 20 -PASS lastEvent.changedTouches[0].clientY is 15 +PASS lastEvent.changedTouches[0].pageX is 50 +PASS lastEvent.changedTouches[0].pageY is 50 +PASS lastEvent.changedTouches[0].clientX is 50 +PASS lastEvent.changedTouches[0].clientY is 50 PASS lastEvent.changedTouches[0].identifier is 0 PASS lastEvent.shiftKey is false PASS lastEvent.altKey is false diff --git a/LayoutTests/fast/events/touch/basic-single-touch-events.html b/LayoutTests/fast/events/touch/basic-single-touch-events.html index 4f870f4..cd841a1 100644 --- a/LayoutTests/fast/events/touch/basic-single-touch-events.html +++ b/LayoutTests/fast/events/touch/basic-single-touch-events.html @@ -4,6 +4,12 @@ <link rel="stylesheet" href="../../js/resources/js-test-style.css"> <script src="../../js/resources/js-test-pre.js"></script> <script src="../../js/resources/js-test-post-function.js"></script> +<!-- + Touch tests that involve the ontouchstart, ontouchmove, ontouchend or ontouchcancel callbacks + should be written in an asynchronous fashion so they can be run on mobile platforms like Android. + This template will generate an asynchronous style test by using the js-test-post-function script. + You will need to invoke isSuccessfullyParsed() in your test script when the test completes. +--> </head> <body> <p id="description"></p> diff --git a/LayoutTests/fast/events/touch/create-touch-event.html b/LayoutTests/fast/events/touch/create-touch-event.html index ace4459..17aa183 100644 --- a/LayoutTests/fast/events/touch/create-touch-event.html +++ b/LayoutTests/fast/events/touch/create-touch-event.html @@ -7,7 +7,7 @@ <body> <p id="description"></p> <div id="console"></div> -<script src="script-tests/create-touch-event.js"></script> +<script src="resources/create-touch-event.js"></script> <script src="../../js/resources/js-test-post.js"></script> </body> </html> diff --git a/LayoutTests/fast/events/touch/script-tests/create-touch-event.js b/LayoutTests/fast/events/touch/resources/create-touch-event.js index 78295d6..78295d6 100644 --- a/LayoutTests/fast/events/touch/script-tests/create-touch-event.js +++ b/LayoutTests/fast/events/touch/resources/create-touch-event.js diff --git a/LayoutTests/fast/events/touch/resources/send-touch-up.html b/LayoutTests/fast/events/touch/resources/send-touch-up.html new file mode 100644 index 0000000..8b7380f --- /dev/null +++ b/LayoutTests/fast/events/touch/resources/send-touch-up.html @@ -0,0 +1,39 @@ +<html> +<head> +<title></title> +<script type='text/javascript'> +function doGC() +{ + if (window.GCController) + return GCController.collect(); + + if (window.gc) + return window.gc(); + + for (var i = 0; i < 10000; i++) + var s = new String(""); +} + +function sendTouchUp() +{ + doGC(); + // This touchend will cause a crash if the bug is present. + eventSender.releaseTouchPoint(0); + eventSender.touchEnd(); + // This touchstart will finish the test when we don't crash. + eventSender.addTouchPoint(10,10); + eventSender.touchStart(); +} + +function finishTest(e) +{ + layoutTestController.notifyDone(); +} + +document.ontouchstart = finishTest; +</script> +</head> +<body onload="sendTouchUp();"> +<p>If the test doesn't crash, then PASS</p> +</body> +</html> diff --git a/LayoutTests/fast/events/touch/resources/touch-stale-node-crash.js b/LayoutTests/fast/events/touch/resources/touch-stale-node-crash.js new file mode 100644 index 0000000..c546a69 --- /dev/null +++ b/LayoutTests/fast/events/touch/resources/touch-stale-node-crash.js @@ -0,0 +1,20 @@ +document.ontouchstart = touchStartHandler; + +function touchStartHandler(e) +{ + var target = e.touches[0].target; + document.body.removeChild(target); + window.location = 'resources/send-touch-up.html'; +} + +description("If this test does not crash then you pass!"); + +if (window.layoutTestController) + layoutTestController.waitUntilDone(); + +if (window.eventSender) { + eventSender.clearTouchPoints(); + eventSender.addTouchPoint(50, 150); + eventSender.touchStart(); +} else + debug('This test requires DRT.'); diff --git a/LayoutTests/fast/events/touch/script-tests/TEMPLATE.html b/LayoutTests/fast/events/touch/script-tests/TEMPLATE.html index 1951c43..fd006b9 100644 --- a/LayoutTests/fast/events/touch/script-tests/TEMPLATE.html +++ b/LayoutTests/fast/events/touch/script-tests/TEMPLATE.html @@ -3,11 +3,17 @@ <head> <link rel="stylesheet" href="../../js/resources/js-test-style.css"> <script src="../../js/resources/js-test-pre.js"></script> +<script src="../../js/resources/js-test-post-function.js"></script> +<!-- + Touch tests that involve the ontouchstart, ontouchmove, ontouchend or ontouchcancel callbacks + should be written in an asynchronous fashion so they can be run on mobile platforms like Android. + This template will generate an asynchronous style test by using the js-test-post-function script. + You will need to invoke isSuccessfullyParsed() in your test script when the test completes. +--> </head> <body> <p id="description"></p> <div id="console"></div> <script src="YOUR_JS_FILE_HERE"></script> -<script src="../../js/resources/js-test-post.js"></script> </body> </html> diff --git a/LayoutTests/fast/events/touch/script-tests/basic-single-touch-events.js b/LayoutTests/fast/events/touch/script-tests/basic-single-touch-events.js index 9975c87..756f49e 100644 --- a/LayoutTests/fast/events/touch/script-tests/basic-single-touch-events.js +++ b/LayoutTests/fast/events/touch/script-tests/basic-single-touch-events.js @@ -62,7 +62,7 @@ function verifyTouch(which) { break; case 1: verifyTouchEvent("touchmove", 1, 1, 1); - verifyTouchPoint("touches", 0, 20, 15, 0); + verifyTouchPoint("touches", 0, 50, 50, 0); shouldBe("lastEvent.shiftKey", "true"); shouldBe("lastEvent.altKey", "true"); shouldBe("lastEvent.ctrlKey", "false"); @@ -70,7 +70,7 @@ function verifyTouch(which) { break; case 2: verifyTouchEvent("touchend", 0, 1, 0); - verifyTouchPoint("changedTouches", 0, 20, 15, 0); + verifyTouchPoint("changedTouches", 0, 50, 50, 0); shouldBe("lastEvent.shiftKey", "false"); shouldBe("lastEvent.altKey", "false"); break; @@ -92,7 +92,7 @@ function singleTouchSequence() eventSender.addTouchPoint(10, 10); eventSender.touchStart(); - eventSender.updateTouchPoint(0, 20, 15); + eventSender.updateTouchPoint(0, 50, 50); eventSender.setTouchModifier("shift", true); eventSender.setTouchModifier("alt", true); eventSender.touchMove(); @@ -106,7 +106,7 @@ function singleTouchSequence() function touchTargets() { - eventSender.addTouchPoint(10, 10); + eventSender.addTouchPoint(20, 20); eventSender.touchStart(); eventSender.updateTouchPoint(0, 1000, 1000); diff --git a/LayoutTests/fast/events/touch/script-tests/send-oncancel-event.js b/LayoutTests/fast/events/touch/script-tests/send-oncancel-event.js index 01eac2f..c83daa4 100644 --- a/LayoutTests/fast/events/touch/script-tests/send-oncancel-event.js +++ b/LayoutTests/fast/events/touch/script-tests/send-oncancel-event.js @@ -13,6 +13,7 @@ function touchcancelHandler() { shouldBe("cancelEvent.pageY", touchY.toString()); if (window.layoutTestController) { layoutTestController.notifyDone(); + isSuccessfullyParsed(); } } diff --git a/LayoutTests/fast/events/touch/script-tests/touch-target.js b/LayoutTests/fast/events/touch/script-tests/touch-target.js index 0623811..8e47f23 100644 --- a/LayoutTests/fast/events/touch/script-tests/touch-target.js +++ b/LayoutTests/fast/events/touch/script-tests/touch-target.js @@ -1,3 +1,6 @@ +var targetsDiv = document.createElement("div"); +targetsDiv.id = "targetsDiv"; + var div1 = document.createElement("div"); div1.id = "targetA"; div1.style.width = "100px"; @@ -13,9 +16,10 @@ div2.style.backgroundColor = "green"; var touchStartCount = 0; var touchMoveCount = 0; -document.getElementById('targetsDiv').appendChild(div1); -document.getElementById('targetsDiv').appendChild(document.createElement('br')); -document.getElementById('targetsDiv').appendChild(div2); +document.body.insertBefore(targetsDiv, document.getElementById('console')); +targetsDiv.appendChild(div1); +targetsDiv.appendChild(document.createElement('br')); +targetsDiv.appendChild(div2); function touchStartHandler() { diff --git a/LayoutTests/fast/events/touch/send-oncancel-event.html b/LayoutTests/fast/events/touch/send-oncancel-event.html index 5665c0c..0c913fb 100644 --- a/LayoutTests/fast/events/touch/send-oncancel-event.html +++ b/LayoutTests/fast/events/touch/send-oncancel-event.html @@ -3,11 +3,17 @@ <head> <link rel="stylesheet" href="../../js/resources/js-test-style.css"> <script src="../../js/resources/js-test-pre.js"></script> +<script src="../../js/resources/js-test-post-function.js"></script> +<!-- + Touch tests that involve the ontouchstart, ontouchmove, ontouchend or ontouchcancel callbacks + should be written in an asynchronous fashion so they can be run on mobile platforms like Android. + This template will generate an asynchronous style test by using the js-test-post-function script. + You will need to invoke isSuccessfullyParsed() in your test script when the test completes. +--> </head> <body> <p id="description"></p> <div id="console"></div> <script src="script-tests/send-oncancel-event.js"></script> -<script src="../../js/resources/js-test-post.js"></script> </body> </html> diff --git a/LayoutTests/fast/events/touch/touch-stale-node-crash-expected.txt b/LayoutTests/fast/events/touch/touch-stale-node-crash-expected.txt new file mode 100644 index 0000000..cec9f36 --- /dev/null +++ b/LayoutTests/fast/events/touch/touch-stale-node-crash-expected.txt @@ -0,0 +1 @@ +If the test doesn't crash, then PASS diff --git a/LayoutTests/fast/events/touch/touch-stale-node-crash.html b/LayoutTests/fast/events/touch/touch-stale-node-crash.html new file mode 100644 index 0000000..5e1c65a --- /dev/null +++ b/LayoutTests/fast/events/touch/touch-stale-node-crash.html @@ -0,0 +1,14 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<link rel="stylesheet" href="../../js/resources/js-test-style.css"> +<script src="../../js/resources/js-test-pre.js"></script> +<script src="../../js/resources/js-test-post-function.js"></script> +</head> +<body> +<p id="description"></p> +<div style="background-color:red;height:100px;width:100px;"></div> +<div id="console"></div> +<script src="resources/touch-stale-node-crash.js"></script> +</body> +</html> diff --git a/LayoutTests/fast/events/touch/touch-target.html b/LayoutTests/fast/events/touch/touch-target.html index dfd8dab..3447e73 100644 --- a/LayoutTests/fast/events/touch/touch-target.html +++ b/LayoutTests/fast/events/touch/touch-target.html @@ -4,10 +4,15 @@ <link rel="stylesheet" href="../../js/resources/js-test-style.css"> <script src="../../js/resources/js-test-pre.js"></script> <script src="../../js/resources/js-test-post-function.js"></script> +<!-- + Touch tests that involve the ontouchstart, ontouchmove, ontouchend or ontouchcancel callbacks + should be written in an asynchronous fashion so they can be run on mobile platforms like Android. + This template will generate an asynchronous style test by using the js-test-post-function script. + You will need to invoke isSuccessfullyParsed() in your test script when the test completes. +--> </head> <body> <p id="description"></p> -<div id="targetsDiv"></div> <div id="console"></div> <script src="script-tests/touch-target.js"></script> </body> diff --git a/LayoutTests/http/conf/apache2-debian-httpd.conf b/LayoutTests/http/conf/apache2-debian-httpd.conf index b8918db..7ef645f 100644 --- a/LayoutTests/http/conf/apache2-debian-httpd.conf +++ b/LayoutTests/http/conf/apache2-debian-httpd.conf @@ -681,7 +681,7 @@ ServerSignature On RewriteRule .* - [F] </IfModule> -<VirtualHost 127.0.0.1:8443> +<VirtualHost *:8443> ServerName 127.0.0.1 SSLEngine On </VirtualHost> diff --git a/LayoutTests/http/conf/apache2-httpd.conf b/LayoutTests/http/conf/apache2-httpd.conf index e915fa7..6b55a95 100644 --- a/LayoutTests/http/conf/apache2-httpd.conf +++ b/LayoutTests/http/conf/apache2-httpd.conf @@ -702,7 +702,7 @@ ServerSignature On RewriteRule .* - [F] </IfModule> -<VirtualHost 127.0.0.1:8443> +<VirtualHost *:8443> ServerName 127.0.0.1 SSLEngine On </VirtualHost> diff --git a/LayoutTests/http/conf/fedora-httpd.conf b/LayoutTests/http/conf/fedora-httpd.conf index 62100c8..b1560a9 100644 --- a/LayoutTests/http/conf/fedora-httpd.conf +++ b/LayoutTests/http/conf/fedora-httpd.conf @@ -882,7 +882,7 @@ AddHandler send-as-is asis RewriteRule .* - [F] </IfModule> -<VirtualHost 127.0.0.1:8443> +<VirtualHost *:8443> ServerName 127.0.0.1 SSLEngine On </VirtualHost> diff --git a/LayoutTests/http/conf/httpd.conf b/LayoutTests/http/conf/httpd.conf index 6e6157c..347deb4 100644 --- a/LayoutTests/http/conf/httpd.conf +++ b/LayoutTests/http/conf/httpd.conf @@ -737,7 +737,7 @@ ServerSignature On RewriteRule .* - [F] </IfModule> -<VirtualHost 127.0.0.1:8443> +<VirtualHost *:8443> ServerName 127.0.0.1 SSLEngine On </VirtualHost> diff --git a/LayoutTests/http/tests/appcache/credential-url-expected.txt b/LayoutTests/http/tests/appcache/credential-url-expected.txt new file mode 100644 index 0000000..3076236 --- /dev/null +++ b/LayoutTests/http/tests/appcache/credential-url-expected.txt @@ -0,0 +1,3 @@ +Test that application cache doesn't block loading resources from the same origin with credential. + +SUCCESS diff --git a/LayoutTests/http/tests/appcache/credential-url.html b/LayoutTests/http/tests/appcache/credential-url.html new file mode 100644 index 0000000..b6c7eec --- /dev/null +++ b/LayoutTests/http/tests/appcache/credential-url.html @@ -0,0 +1,28 @@ +<html manifest="http://user:password@127.0.0.1:8000/appcache/resources/empty.manifest"> +<body> +<p>Test that application cache doesn't block loading resources from the same origin with credential.</p> +<script> +if (window.layoutTestController) { + layoutTestController.dumpAsText(); + layoutTestController.waitUntilDone(); +} + +function test() +{ + var ifr = document.createElement("iframe"); + ifr.setAttribute("src", "javascript:parent.success(), 'PASS'"); + document.body.appendChild(ifr); +} + +function success() +{ + document.body.replaceChild(document.createTextNode("SUCCESS"), document.getElementsByTagName("iframe")[0]); + if (window.layoutTestController) + layoutTestController.notifyDone(); +} + +applicationCache.oncached = test; +applicationCache.onnoupdate = test; +</script> +<body> +</html> diff --git a/LayoutTests/http/tests/appcache/different-https-origin-resource-main-expected.txt b/LayoutTests/http/tests/appcache/different-https-origin-resource-main-expected.txt new file mode 100644 index 0000000..0dfbdc0 --- /dev/null +++ b/LayoutTests/http/tests/appcache/different-https-origin-resource-main-expected.txt @@ -0,0 +1,4 @@ +Test that a resource from a different https origin is not cached. + +PASS + diff --git a/LayoutTests/http/tests/appcache/different-https-origin-resource-main.html b/LayoutTests/http/tests/appcache/different-https-origin-resource-main.html new file mode 100644 index 0000000..55e744f --- /dev/null +++ b/LayoutTests/http/tests/appcache/different-https-origin-resource-main.html @@ -0,0 +1,19 @@ +<html> +<body> +<script> +if (window.layoutTestController) { + layoutTestController.waitUntilDone(); + layoutTestController.dumpAsText(); +} + +window.addEventListener("message", function(e) { + document.getElementById("result").innerHTML = e.data; + if (window.layoutTestController) + layoutTestController.notifyDone(); +}, false); +</script> +<p>Test that a resource from a different https origin is not cached.</p> +<div id=result></div> +<iframe src="https://127.0.0.1:8443/appcache/resources/different-https-origin-resource.html"></iframe> +</body> +</html> diff --git a/LayoutTests/http/tests/appcache/resources/different-https-origin-resource.html b/LayoutTests/http/tests/appcache/resources/different-https-origin-resource.html new file mode 100644 index 0000000..674706a --- /dev/null +++ b/LayoutTests/http/tests/appcache/resources/different-https-origin-resource.html @@ -0,0 +1,29 @@ +<html manifest="https://127.0.0.1:8443/appcache/resources/different-https-origin-resource.manifest"> +<script> +var hadError = false; +var result; + +function finish() +{ + if (!hadError) + result = "PASS"; + parent.postMessage(result, '*'); +} +function fail() +{ + result = "FAIL: Different https origin resource is getting downloaded to cache."; + hadError = true; +} +function error() +{ + result = "ERROR"; + hadError = true; + finish(); +} + +applicationCache.onprogress = function() { fail(); } +applicationCache.onnoupdate = function() { finish(); } +applicationCache.oncached = function() { finish(); } +applicationCache.onerror = function() { error(); } +</script> +</html> diff --git a/LayoutTests/http/tests/appcache/resources/different-https-origin-resource.manifest b/LayoutTests/http/tests/appcache/resources/different-https-origin-resource.manifest new file mode 100644 index 0000000..75a58a4 --- /dev/null +++ b/LayoutTests/http/tests/appcache/resources/different-https-origin-resource.manifest @@ -0,0 +1,3 @@ +CACHE MANIFEST +CACHE: +https://localhost:8443/appcache/resources/simple.txt diff --git a/LayoutTests/storage/domstorage/events/documentURI-expected.txt b/LayoutTests/storage/domstorage/events/documentURI-expected.txt index 5952523..d53d4dc 100644 --- a/LayoutTests/storage/domstorage/events/documentURI-expected.txt +++ b/LayoutTests/storage/domstorage/events/documentURI-expected.txt @@ -1,4 +1,4 @@ -Test that changing documentURI has no effects on the uri passed into storage events. +Test that changing documentURI has no effects on the url passed into storage events. On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". @@ -10,7 +10,7 @@ Reset storage event list storageEventList = new Array() storage.foo = '123' PASS storageEventList.length is 1 -Saving URI +Saving url document.documentURI = 'abc' PASS document.documentURI is "abc" storage.foo = 'xyz' @@ -25,7 +25,7 @@ Reset storage event list storageEventList = new Array() storage.foo = '123' PASS storageEventList.length is 1 -Saving URI +Saving url document.documentURI = 'abc' PASS document.documentURI is "abc" storage.foo = 'xyz' diff --git a/LayoutTests/storage/domstorage/events/script-tests/documentURI.js b/LayoutTests/storage/domstorage/events/script-tests/documentURI.js index 4b4f4cb..8df6fe9 100644 --- a/LayoutTests/storage/domstorage/events/script-tests/documentURI.js +++ b/LayoutTests/storage/domstorage/events/script-tests/documentURI.js @@ -1,4 +1,4 @@ -description("Test that changing documentURI has no effects on the uri passed into storage events."); +description("Test that changing documentURI has no effects on the url passed into storage events."); function test(storageString, callback) { @@ -29,8 +29,8 @@ function step1() function step2() { shouldBe("storageEventList.length", "1"); - debug("Saving URI"); - window.lastURI = storageEventList[0].uri; + debug("Saving url"); + window.lastURL = storageEventList[0].url; evalAndLog("document.documentURI = 'abc'"); shouldBeEqualToString("document.documentURI", "abc"); @@ -42,7 +42,7 @@ function step2() function step3() { shouldBe("storageEventList.length", "2"); - shouldBeTrue(String(window.lastURI == storageEventList[1].uri)); + shouldBeTrue(String(window.lastURL == storageEventList[1].url)); completionCallback(); } diff --git a/LayoutTests/storage/domstorage/localstorage/resources/iframe-events-second.html b/LayoutTests/storage/domstorage/localstorage/resources/iframe-events-second.html index 2ab8ba1..bed860f 100644 --- a/LayoutTests/storage/domstorage/localstorage/resources/iframe-events-second.html +++ b/LayoutTests/storage/domstorage/localstorage/resources/iframe-events-second.html @@ -7,7 +7,7 @@ function handleStorageEvent(e) parent.log("Key - " + e.key); parent.log("New Value - " + e.newValue); parent.log("Old Value - " + e.oldValue); - parent.log("URI - " + parent.normalizeURL(e.uri)); + parent.log("url - " + parent.normalizeURL(e.url)); parent.log("Storage Area - " + ((e.storageArea == window.localStorage) ? "This window's window.localStorage" : "Another window's window.localStorage")); parent.log(""); diff --git a/LayoutTests/storage/domstorage/sessionstorage/resources/iframe-events-second.html b/LayoutTests/storage/domstorage/sessionstorage/resources/iframe-events-second.html index 2d7b004..97781b1 100644 --- a/LayoutTests/storage/domstorage/sessionstorage/resources/iframe-events-second.html +++ b/LayoutTests/storage/domstorage/sessionstorage/resources/iframe-events-second.html @@ -7,7 +7,7 @@ function handleStorageEvent(e) parent.log("Key - " + e.key); parent.log("New Value - " + e.newValue); parent.log("Old Value - " + e.oldValue); - parent.log("URI - " + parent.normalizeURL(e.uri)); + parent.log("url - " + parent.normalizeURL(e.url)); parent.log("Storage Area - " + ((e.storageArea == window.sessionStorage) ? "This window's window.sessionStorage" : "Another window's window.sessionStorage")); parent.log(""); diff --git a/LayoutTests/storage/quota-tracking-expected.txt b/LayoutTests/storage/quota-tracking-expected.txt index 62a2c6b..6d860f0 100644 --- a/LayoutTests/storage/quota-tracking-expected.txt +++ b/LayoutTests/storage/quota-tracking-expected.txt @@ -1,6 +1,6 @@ UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{file, , 0} database:QuotaManagementDatabase2 This test checks to make sure that quotas are enforced per-origin instead of per-database, as they were prior to http://trac.webkit.org/projects/webkit/changeset/29983. -The test clears all databases, sets the quota for the origin to 32k, then tries to insert 17k of data into two databases. If things go as planned, the UI Delegate will be informed of the exceeded quota and should increase the quota for this origin. Inserting 17k of data the third time should succeed again. +The test clears all databases, sets the quota for the origin to 40k, then tries to insert 17k of data into two databases. If things go as planned, the second insert should fail, the UI Delegate should be informed of the exceeded quota and should increase the quota for this origin. Inserting 17k of data the third time should succeed again. Adding a table Inserting some data Done adding data diff --git a/LayoutTests/storage/quota-tracking.html b/LayoutTests/storage/quota-tracking.html index 2b5b49d..6e52523 100644 --- a/LayoutTests/storage/quota-tracking.html +++ b/LayoutTests/storage/quota-tracking.html @@ -91,7 +91,7 @@ function runTest() if (window.layoutTestController) { layoutTestController.clearAllDatabases(); layoutTestController.dumpDatabaseCallbacks(); - layoutTestController.setDatabaseQuota(32768); + layoutTestController.setDatabaseQuota(40960); layoutTestController.dumpAsText(); layoutTestController.waitUntilDone(); } @@ -105,7 +105,7 @@ function runTest() <body onload="runTest()"> This test checks to make sure that quotas are enforced per-origin instead of per-database, as they were prior to http://trac.webkit.org/projects/webkit/changeset/29983.<br> -The test clears all databases, sets the quota for the origin to 32k, then tries to insert 17k of data into two databases. If things go as planned, the UI Delegate will be informed of the exceeded quota and should increase the quota for this origin. Inserting 17k of data the third time should succeed again. +The test clears all databases, sets the quota for the origin to 40k, then tries to insert 17k of data into two databases. If things go as planned, the second insert should fail, the UI Delegate should be informed of the exceeded quota and should increase the quota for this origin. Inserting 17k of data the third time should succeed again. <pre id="console"> </pre> </body> diff --git a/WebCore/Android.derived.jscbindings.mk b/WebCore/Android.derived.jscbindings.mk index d51a4d5..47d70e2 100644 --- a/WebCore/Android.derived.jscbindings.mk +++ b/WebCore/Android.derived.jscbindings.mk @@ -69,10 +69,10 @@ GEN := \ $(intermediates)/css/JSCSSVariablesDeclaration.h \ $(intermediates)/css/JSCSSVariablesRule.h \ $(intermediates)/css/JSCounter.h \ - $(intermediates)/css/JSMedia.h \ $(intermediates)/css/JSMediaList.h \ $(intermediates)/css/JSRGBColor.h \ $(intermediates)/css/JSRect.h \ + $(intermediates)/css/JSStyleMedia.h \ $(intermediates)/css/JSStyleSheet.h \ $(intermediates)/css/JSStyleSheetList.h \ $(intermediates)/css/JSWebKitCSSKeyframeRule.h \ @@ -159,6 +159,7 @@ GEN := \ $(intermediates)/html/JSDataGridColumn.h \ $(intermediates)/html/JSDataGridColumnList.h \ $(intermediates)/html/JSFile.h \ + $(intermediates)/html/JSFileError.h \ $(intermediates)/html/JSFileList.h \ $(intermediates)/html/JSHTMLAllCollection.h \ $(intermediates)/html/JSHTMLAnchorElement.h \ diff --git a/WebCore/Android.derived.v8bindings.mk b/WebCore/Android.derived.v8bindings.mk index efc4ebf..0cc1f96 100644 --- a/WebCore/Android.derived.v8bindings.mk +++ b/WebCore/Android.derived.v8bindings.mk @@ -52,10 +52,10 @@ GEN := \ $(intermediates)/bindings/V8CSSVariablesDeclaration.h \ $(intermediates)/bindings/V8CSSVariablesRule.h \ $(intermediates)/bindings/V8Counter.h \ - $(intermediates)/bindings/V8Media.h \ $(intermediates)/bindings/V8MediaList.h \ $(intermediates)/bindings/V8Rect.h \ $(intermediates)/bindings/V8RGBColor.h \ + $(intermediates)/bindings/V8StyleMedia.h \ $(intermediates)/bindings/V8StyleSheet.h \ $(intermediates)/bindings/V8StyleSheetList.h \ $(intermediates)/bindings/V8WebKitCSSKeyframeRule.h \ @@ -143,6 +143,7 @@ GEN := \ $(intermediates)/bindings/V8DataGridColumn.h \ $(intermediates)/bindings/V8DataGridColumnList.h \ $(intermediates)/bindings/V8File.h \ + $(intermediates)/bindings/V8FileError.h \ $(intermediates)/bindings/V8FileList.h \ $(intermediates)/bindings/V8HTMLAllCollection.h \ $(intermediates)/bindings/V8HTMLAnchorElement.h \ diff --git a/WebCore/Android.jscbindings.mk b/WebCore/Android.jscbindings.mk index bd775b3..c768fae 100644 --- a/WebCore/Android.jscbindings.mk +++ b/WebCore/Android.jscbindings.mk @@ -61,7 +61,6 @@ LOCAL_SRC_FILES += \ bindings/js/DOMObjectHashTableMap.cpp \ bindings/js/DOMWrapperWorld.cpp \ bindings/js/GCController.cpp \ - bindings/js/JSAbstractWorkerCustom.cpp \ bindings/js/JSAttrCustom.cpp \ bindings/js/JSAudioConstructor.cpp \ bindings/js/JSCDATASectionCustom.cpp \ @@ -99,7 +98,6 @@ LOCAL_SRC_FILES += \ bindings/js/JSDatabaseCustom.cpp \ bindings/js/JSDedicatedWorkerContextCustom.cpp \ bindings/js/JSDocumentCustom.cpp \ - bindings/js/JSDocumentFragmentCustom.cpp \ bindings/js/JSElementCustom.cpp \ bindings/js/JSEventCustom.cpp \ bindings/js/JSEventListener.cpp \ diff --git a/WebCore/Android.mk b/WebCore/Android.mk index 217dd9f..7ad7005 100644 --- a/WebCore/Android.mk +++ b/WebCore/Android.mk @@ -448,7 +448,6 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ platform/graphics/FontFastPath.cpp \ platform/graphics/GeneratedImage.cpp \ platform/graphics/GlyphPageTreeNode.cpp \ - platform/graphics/GlyphMetricsMap.cpp \ platform/graphics/Gradient.cpp \ platform/graphics/GraphicsContext.cpp \ platform/graphics/GraphicsLayer.cpp \ @@ -652,10 +651,16 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ rendering/RenderSVGInline.cpp \ rendering/RenderSVGInlineText.cpp \ rendering/RenderSVGModelObject.cpp \ + rendering/RenderSVGResource.cpp \ rendering/RenderSVGResourceClipper.cpp \ rendering/RenderSVGResourceFilter.cpp \ + rendering/RenderSVGResourceGradient.cpp \ + rendering/RenderSVGResourceLinearGradient.cpp \ rendering/RenderSVGResourceMarker.cpp \ rendering/RenderSVGResourceMasker.cpp \ + rendering/RenderSVGResourcePattern.cpp \ + rendering/RenderSVGResourceRadialGradient.cpp \ + rendering/RenderSVGResourceSolidColor.cpp \ rendering/RenderSVGRoot.cpp \ rendering/RenderSVGShadowTreeRootContainer.cpp \ rendering/RenderSVGTSpan.cpp \ @@ -690,6 +695,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ ifeq ($(ENABLE_SVG), true) LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ + rendering/SVGCharacterData.cpp \ rendering/SVGCharacterLayoutInfo.cpp \ rendering/SVGInlineFlowBox.cpp \ rendering/SVGInlineTextBox.cpp \ @@ -901,13 +907,6 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ svg/animation/SVGSMILElement.cpp \ \ svg/graphics/SVGImage.cpp \ - svg/graphics/SVGPaintServer.cpp \ - svg/graphics/SVGPaintServerGradient.cpp \ - svg/graphics/SVGPaintServerLinearGradient.cpp \ - svg/graphics/SVGPaintServerPattern.cpp \ - svg/graphics/SVGPaintServerRadialGradient.cpp \ - svg/graphics/SVGPaintServerSolid.cpp \ - svg/graphics/SVGResource.cpp \ \ svg/graphics/filters/SVGFEConvolveMatrix.cpp \ svg/graphics/filters/SVGFEDiffuseLighting.cpp \ diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog index 9700ffe..c6bf40b 100644 --- a/WebCore/ChangeLog +++ b/WebCore/ChangeLog @@ -1,3 +1,7741 @@ +2010-05-07 Pavel Feldman <pfeldman@chromium.org> + + Not reviewed: chromium dev tools tests fix. + Add a more strict check prior to accessing constructor property in + Web Inspector frontend. + + * inspector/front-end/InjectedScript.js: + (injectedScriptConstructor): + +2010-05-07 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Joseph Pecoraro. + + Web Inspector: On Linux/Windows panel history is + traversed while iterating over words in text prompt. + + https://bugs.webkit.org/show_bug.cgi?id=38740 + + * inspector/front-end/TextPrompt.js: + (WebInspector.TextPrompt): + * inspector/front-end/inspector.js: + (WebInspector.documentKeyDown): + +2010-05-07 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: come up with InjectedScript._className that works for both JSC and V8. + + https://bugs.webkit.org/show_bug.cgi?id=38755 + + * inspector/front-end/InjectedScript.js: + (injectedScriptConstructor): + +2010-05-07 Joseph Pecoraro <joepeck@webkit.org> + + Reviewed by Adam Barth. + + document.write is not synchronous after page load + https://bugs.webkit.org/show_bug.cgi?id=38146 + + If there are no pending scripts, a document.write call should be + synchronous. This matches other browsers and the HTML5 spec. Forcing + the tokenizer to be synchronous in Document::write does not affect + external scripts written by the write call. This should only change + behavior of document.write after the page is done loading. + + Difficult to test reliably due to HTMLTokenizing relying on processing time. + I made a manual test because the test requires processing very large strings + synchronously and therefore can take some time. + + Test: WebCore/manual-tests/dom/document-write-synchronous-after-page-load.html + + * dom/Document.cpp: + (WebCore::SynchronousHTMLTokenizerGuard::SynchronousHTMLTokenizerGuard): if the provided tokenizer is an HTMLTokenizer make it synchronous + (WebCore::SynchronousHTMLTokenizerGuard::~SynchronousHTMLTokenizerGuard): if the provided tokenizer was an HTMLTokenizer return its synchronous state + (WebCore::Document::write): temporarily set the tokenizer to synchronous during document.write + * dom/Tokenizer.h: + (WebCore::Tokenizer::asHTMLTokenizer): default implementation returns 0, to be overridden by HTMLTokenizer + * html/HTMLTokenizer.h: allow access to to the force synchronous state + (WebCore::HTMLTokenizer::forceSynchronous): accessor + (WebCore::HTMLTokenizer::asHTMLTokenizer): override the default to return itself + * manual-tests/dom/document-write-synchronous-after-page-load.html: Added. + +2010-05-07 Tor Arne Vestbø <tor.arne.vestbo@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Fix rendering of -webkit-user-select: none + + -webkit-user-select: none is implemented by filling + the area with an invalid default-constructed Color. + In most ports passing an invalid color down to the + graphics backend seems to produce transparent fills. + + In Qt the behavior of painting with an invalid QColor + is undefined, and in practice it results in painting + black opaque areas. + + One way to fix this would be to use Qt::transparent + when converting an undefined Color to a QColor, but + Qt does not have short circuits for fully transparent + painting, and we actually end up in slow code paths + due to the transparency. So, we're better of doing the + short circuit in WebKit. + + https://bugs.webkit.org/show_bug.cgi?id=38523 + + * platform/graphics/qt/GraphicsContextQt.cpp: + +2010-05-07 Ben Murdoch <benm@google.com> + + Reviewed by Darin Adler. + + Potential crash in EventHandler::handleTouchEvent + https://bugs.webkit.org/show_bug.cgi?id=38646 + + Fix a ref counting bug that can cause a crash if the m_originatingouchPointTargets + hashmap holds the last ref to an EventTarget when the user lifts their finger. + + This is very hard to reproduce in a consistent way and clearly a + simple logic error in the code, therefore no new tests. + + * page/EventHandler.cpp: + (WebCore::EventHandler::handleTouchEvent): Don't let the RefPtr we get back from + the hasmap go out of scope so soon as it could delete the wrapped ptr if the + hashmap held the last ref (and we use the raw ptr that the RefPtr + wraps later in the WebCore::Touch constructor). + +2010-05-07 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Rubber-stamped by Kenneth Rohde Christiansen. + + [GTK] Fails to build on GTK+ < 2.14 + https://bugs.webkit.org/show_bug.cgi?id=38746 + + Build fix only. Do basically the same as gtk_adjustment_configure + would do if we are bellow GTK+ 2.14. + + * platform/gtk/ScrollViewGtk.cpp: + (WebCore::AdjustmentConfigure): + +2010-05-07 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Rubber-stamped by Xan Lopez. + + Crash with MgOpenModerna font, with non-UTF-8 character + https://bugs.webkit.org/show_bug.cgi?id=37795 + + NULL-check the font platform data, for now, to avoid the crash. + + Could not yet figure out a way to get a test written that does not + involve adding the font to the tree, but there are doubts about + licensing. + + * platform/graphics/cairo/FontCacheCairo.cpp: + (WebCore::FontCache::getFontDataForCharacters): + +2010-05-07 MORITA Hajime <morrita@google.com> + + Reviewed by Eric Seidel. + + [Chromium] RenderThemeChromiumMac.mm should share the code with RenderThemeMac.mm + https://bugs.webkit.org/show_bug.cgi?id=37204 + + Made RenderThemeChromiumMac subclass of RenderThemeMac, instead of RenderTheme. + Added some method to RenderThemeMac for overriding on RenderThemeChromiumMac. + + No new tests; Should have no behavioural change. + + * WebCore.gyp/WebCore.gyp: + * rendering/RenderThemeChromiumMac.h: + * rendering/RenderThemeChromiumMac.mm: + (WebCore::RenderThemeChromiumMac::usesTestModeFocusRingColor): + (WebCore::RenderThemeChromiumMac::documentViewFor): + (WebCore::RenderThemeChromiumMac::adjustMediaSliderThumbSize): + (WebCore::RenderThemeChromiumMac::paintMediaVolumeSliderTrack): + (WebCore::RenderThemeChromiumMac::paintMediaVolumeSliderThumb): + * rendering/RenderThemeMac.h: + (WebCore::RenderThemeMac::updateActiveState): Added for overriding + * rendering/RenderThemeMac.mm: + (WebCore::RenderThemeMac::usesTestModeFocusRingColor): Added for overriding + (WebCore::RenderThemeMac::documentViewFor): Added for overriding + (WebCore::RenderThemeMac::paintMenuList): + (WebCore::RenderThemeMac::setPopupButtonCellState): + (WebCore::RenderThemeMac::paintSliderThumb): + (WebCore::RenderThemeMac::paintSearchField): + (WebCore::RenderThemeMac::setSearchCellState): + (WebCore::RenderThemeMac::paintSearchFieldCancelButton): + (WebCore::RenderThemeMac::paintSearchFieldResultsDecoration): + (WebCore::RenderThemeMac::paintSearchFieldResultsButton): + (WebCore::RenderThemeMac::adjustSliderThumbSize): + (WebCore::RenderThemeMac::adjustMediaSliderThumbSize): Added for overriding + (WebCore::RenderThemeMac::extraMediaControlsStyleSheet): + +2010-05-06 Fumitoshi Ukai <ukai@chromium.org> + + Reviewed by Alexey Proskuryakov. + + JavaScriptCore/wtf/RandomNumber.h should provide using WTF::* + https://bugs.webkit.org/show_bug.cgi?id=38719 + + * platform/graphics/wince/FontCustomPlatformData.cpp: + (WebCore::createUniqueFontName): + Remove WTF:: prefix from randomNumber() + * platform/network/FormDataBuilder.cpp: + (WebCore::FormDataBuilder::generateUniqueBoundaryString): + Ditto. + +2010-04-27 Tony Chang <tony@chromium.org> + + Reviewed by Eric Seidel. + + [chromium] clicking a scrollbar in an iframe shouldn't lose the selection + https://bugs.webkit.org/show_bug.cgi?id=38189 + + Test: fast/events/mousedown-in-subframe-scrollbar.html + + * page/chromium/EventHandlerChromium.cpp: + (WebCore::EventHandler::passMousePressEventToSubframe): If clicking on + a scrollbar, pass the event directly to the scrollbar. This matches + mac which passes the event to the NSScroller. + +2010-05-06 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Dan Bernstein. + + Compositing layers that are clipped out by an overflow:scroll parent fail to get created on reveal + https://bugs.webkit.org/show_bug.cgi?id=38712 + + When compositing layer creation is testing layer overlap, we need to re-run the + algorithm when an overflow:scroll element scrolls, to create new layers for revealed + elements. + + Test: compositing/layer-creation/overflow-scroll-overlap.html + + * rendering/RenderLayer.cpp: + (WebCore::RenderLayer::scrollToOffset): First, move the compositing updates + until after the call to updateWidgetPositions(), so that this order is similar + to what we done when a FrameView scrolls. This change has no known side effects. + Second, if compositingConsultsOverlap() is true, we need to actually do a + compositing layer update to compute whether revealed/hidden layers should + be created/destroyed. + +2010-05-06 Maciej Stachowiak <mjs@apple.com> + + Not reviewed, build fix. + + Try again - with quotes this time. *facepalm* + + * dom/Notation.cpp: + +2010-05-06 Maciej Stachowiak <mjs@apple.com> + + Not reviewed, build fix. + + Speculative fix for Qt and Gtk. + + * dom/Notation.cpp: + +2010-05-06 Maciej Stachowiak <mjs@apple.com> + + Not reviewed, build fix. + + Fix an assert that I failed to update in my earlier change. + + * dom/CharacterData.h: + (WebCore::CharacterData::CharacterData): + +2010-05-06 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Geoff Garen. + + https://bugs.webkit.org/show_bug.cgi?id=38697 + REGRESSION (r58299): Replying on reddit.com no longer works + + * css/CSSSelector.cpp: (WebCore::CSSSelector::extractPseudoType): Don't recognize :first, + :left and :right. The aren't allowed in all contexts, and properly implementing them is out + of scope for this regression fix. + +2010-05-06 Jian Li <jianli@chromium.org> + + Reviewed by Adam Barth. + + Improve code generator scripts to support converting ScriptString. + https://bugs.webkit.org/show_bug.cgi?id=38699 + + Change both JSC and V8 generators to introduce "ConvertScriptString" + attribute to allow converting from ScriptString. Also updated the + bindings test result. + + These changes are necessary in order to avoid adding custom binding codes + when we add the FileReader interface. + + * bindings/scripts/CodeGeneratorJS.pm: + * bindings/scripts/CodeGeneratorV8.pm: + * bindings/scripts/test/GObject/WebKitDOMTestObj.cpp: + (webkit_dom_test_obj_get_script_string_attr): + (webkit_dom_test_obj_get_property): + (webkit_dom_test_obj_class_init): + * bindings/scripts/test/GObject/WebKitDOMTestObj.h: + * bindings/scripts/test/JS/JSTestObj.cpp: + (WebCore::): + (WebCore::jsTestObjScriptStringAttr): + * bindings/scripts/test/JS/JSTestObj.h: + * bindings/scripts/test/ObjC/DOMTestObj.h: + * bindings/scripts/test/ObjC/DOMTestObj.mm: + (-[DOMTestObj scriptStringAttr]): + * bindings/scripts/test/TestObj.idl: + * bindings/scripts/test/V8/V8TestObj.cpp: + (WebCore::TestObjInternal::scriptStringAttrAttrGetter): + (WebCore::): + +2010-05-06 Jian Li <jianli@chromium.org> + + Reviewed by Adam Barth. + + Improve code generator scripts to pass additional ScriptExecutionContext + argument to the constructor. + https://bugs.webkit.org/show_bug.cgi?id=38687 + + Change both JSC and V8 generators to introduce "CallWith=ScriptExecutionContext" + attribute to allow passing the additional ScriptExecutionContext argument to + the constructor. Also add another test IDL file to test interface-level + features. + + These changes are necessary in order to avoid adding custom binding codes + when we add the FileReader interface. + + * bindings/scripts/CodeGeneratorJS.pm: + * bindings/scripts/CodeGeneratorV8.pm: + * bindings/scripts/test/GObject/WebKitDOMTestInterface.cpp: Added. + * bindings/scripts/test/GObject/WebKitDOMTestInterface.h: Added. + * bindings/scripts/test/GObject/WebKitDOMTestInterfacePrivate.h: Added. + * bindings/scripts/test/JS/JSTestInterface.cpp: Added. + * bindings/scripts/test/JS/JSTestInterface.h: Added. + * bindings/scripts/test/ObjC/DOMTestInterface.h: Added. + * bindings/scripts/test/ObjC/DOMTestInterface.mm: Added. + * bindings/scripts/test/ObjC/DOMTestInterfaceInternal.h: Added. + * bindings/scripts/test/TestInterface.idl: Added. + * bindings/scripts/test/V8/V8TestInterface.cpp: Added. + * bindings/scripts/test/V8/V8TestInterface.h: Added. + * bindings/v8/V8Proxy.h: + (WebCore::V8Proxy::constructDOMObjectWithScriptExecutionContext): + +2010-05-06 Maciej Stachowiak <mjs@apple.com> + + Build fix, not reviewed. + + Speculative Windows and Debug build fixes for the last change. + + * dom/Node.h: + (WebCore::Node::inDocument): + (WebCore::Node::setFlag): + +2010-05-06 James Robinson <jamesr@chromium.org> + + Reviewed by Eric Seidel. + + Fix warnings emitted by gcc 4.4.1 on linux in chromium-specific platform graphics files. + https://bugs.webkit.org/show_bug.cgi?id=38158 + + Fixes: + - replace NULL with 0 + - remove unusued locals + - add parens around ambiguous looking compound predicates like (a || b && c) + + This also adds a check for x >= 0 to FontLinux.cpp's in this statement: + if (x < walker.width()) + This is more documentation than anything else since walker.width() returns + an unsigned the current behavior is that x is promoted to unsigned and as + long as x + walker.width() is less than 2^31 all negative values of x + end up wrapping around and not being < walker.width(). This behavior is + tested by fast/text/international/khmer-selection.html + + * platform/graphics/chromium/FontLinux.cpp: + (WebCore::adjustTextRenderMode): + (WebCore::TextRunWalker::TextRunWalker): + (WebCore::TextRunWalker::length): + (WebCore::TextRunWalker::width): + (WebCore::TextRunWalker::getTextRun): + (WebCore::TextRunWalker::getNormalizedTextRun): + (WebCore::Font::offsetForPositionForComplexText): + * platform/graphics/chromium/FontPlatformDataLinux.cpp: + (WebCore::FontPlatformData::setupPaint): + * platform/graphics/chromium/HarfbuzzSkia.cpp: + (WebCore::getOutlinePoint): + * platform/graphics/skia/GraphicsContext3DSkia.cpp: + (WebCore::GraphicsContext3D::getImageData): + * platform/graphics/skia/GraphicsContextSkia.cpp: + (WebCore::isCoordinateSkiaSafe): + (WebCore::GraphicsContext::fillRect): + (WebCore::GraphicsContext::strokePath): + (WebCore::GraphicsContext::strokeRect): + +2010-05-06 Ada Chan <adachan@apple.com> + + Reviewed by David Kilzer. + + https://bugs.webkit.org/show_bug.cgi?id=38695 + + Check the result from widget() for NULL before accessing it. + + * rendering/RenderIFrame.cpp: + (WebCore::RenderIFrame::calcHeight): + (WebCore::RenderIFrame::calcWidth): + +2010-05-06 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Darin Adler. + + further fixes towards REGRESSION (r57292): 1% PLT regression from visited link information leak fix + https://bugs.webkit.org/show_bug.cgi?id=38682 + <rdar://problem/7859794> + + Looks like a 1-2% speedup on PLT. + + - Reorder CSS properties. + - Remove short circuit tag check in matchRulesForList which costs more than it saves. + - Inline initForStyleResolve. + - Optimize applyDeclarations to avoid switch and take fewer branches in the inner loop. + + - Change the way Node handles flags - replace bitfield with a uint32_t and explicit masking, + to make it cheaper to initialize the bits and give faster access. + - Added new Node flags to check for isStyledElement, isHTMLElement, isSVGElement, isComment, + and devirtualize those methods. + - Inline constructors for Node, Element, Text, CharacterData, StyledElement, etc since + they are very simple and lots of nodes get constructed. + + * css/CSSPropertyNames.in: Move a few of the properties up front so we can check for them + with < instead of switch statements + * css/CSSStyleSelector.cpp: + (WebCore::CSSStyleSelector::matchRulesForList): Remove unnecessary preflight check + for tag match before checking selector. This check very rarely short circuits anything, + since most rules with a tag end up in the appropriate tag bucket. So doing the check + cost more time than the time saved. + (WebCore::CSSStyleSelector::initForStyleResolve): Inline. Create RenderStyle in a better way. + (WebCore::CSSStyleSelector::applyDeclarations): Get rid of switch statement and use <= to + check for the high priority properties. Convert to template to avoid checking "applyFirst" + each time through the loop. + (WebCore::CSSStyleSelector::styleForElement): Adjust for new applyDeclarations() signature. + (WebCore::CSSStyleSelector::keyframeStylesForAnimation): ditto + (WebCore::CSSStyleSelector::pseudoStyleForElement): ditto + * css/CSSStyleSelector.h: Adjust for new applyDeclarations() signature. + * rendering/style/RenderStyle.cpp: + (WebCore::RenderStyle::RenderStyle): Inline constructor. + * rendering/style/RenderStyle.h: Make constructor private so it can be inline. + * dom/Node.h: + (WebCore::): See high-level description of changes above. Redid the + way boolean flags work. + (WebCore::Node::isElementNode): + (WebCore::Node::isContainerNode): + (WebCore::Node::isTextNode): + (WebCore::Node::isHTMLElement): + (WebCore::Node::isSVGElement): + (WebCore::Node::isStyledElement): + (WebCore::Node::isCommentNode): + (WebCore::Node::hasID): + (WebCore::Node::hasClass): + (WebCore::Node::active): + (WebCore::Node::inActiveChain): + (WebCore::Node::inDetach): + (WebCore::Node::hovered): + (WebCore::Node::attached): + (WebCore::Node::setAttached): + (WebCore::Node::needsStyleRecalc): + (WebCore::Node::styleChangeType): + (WebCore::Node::childNeedsStyleRecalc): + (WebCore::Node::isLink): + (WebCore::Node::setHasID): + (WebCore::Node::setHasClass): + (WebCore::Node::setChildNeedsStyleRecalc): + (WebCore::Node::clearChildNeedsStyleRecalc): + (WebCore::Node::setInDocument): + (WebCore::Node::clearInDocument): + (WebCore::Node::setInActiveChain): + (WebCore::Node::clearInActiveChain): + (WebCore::Node::setIsLink): + (WebCore::Node::clearIsLink): + (WebCore::Node::setActive): + (WebCore::Node::setHovered): + (WebCore::Node::inDocument): + (WebCore::Node::): + (WebCore::Node::getFlag): + (WebCore::Node::setFlag): + (WebCore::Node::clearFlag): + (WebCore::Node::hasRareData): + (WebCore::Node::isParsingChildrenFinished): + (WebCore::Node::setIsParsingChildrenFinished): + (WebCore::Node::clearIsParsingChildrenFinished): + (WebCore::Node::isStyleAttributeValid): + (WebCore::Node::setIsStyleAttributeValid): + (WebCore::Node::clearIsStyleAttributeValid): + (WebCore::Node::isSynchronizingStyleAttribute): + (WebCore::Node::setIsSynchronizingStyleAttribute): + (WebCore::Node::clearIsSynchronizingStyleAttribute): + (WebCore::Node::areSVGAttributesValid): + (WebCore::Node::setAreSVGAttributesValid): + (WebCore::Node::clearAreSVGAttributesValid): + (WebCore::Node::isSynchronizingSVGAttributes): + (WebCore::Node::setIsSynchronizingSVGAttributes): + (WebCore::Node::clearIsSynchronizingSVGAttributes): + (WebCore::Node::hasRareSVGData): + (WebCore::Node::setHasRareSVGData): + (WebCore::Node::clearHasRareSVGData): + (WebCore::Node::initialRefCount): + * dom/Node.cpp: + (WebCore::Node::trackForDebugging): Adjusted for changes in + flag handling. + (WebCore::Node::ensureRareData): ditto + (WebCore::Node::setStyleChange): ditto + (WebCore::Node::setNeedsStyleRecalc): ditto + (WebCore::Node::lazyAttach): ditto + (WebCore::Node::attach): ditto + (WebCore::Node::detach): ditto + (WebCore::Node::insertedIntoDocument): ditto + (WebCore::Node::removedFromDocument): ditto + * dom/CharacterData.cpp: + * dom/CharacterData.h: + (WebCore::CharacterData::CharacterData): Inline the constructor (moved from .cpp) + * dom/Comment.cpp: + (WebCore::Comment::Comment): Tell the base class that we're a comment. + * dom/Comment.h: Remove isCommentNode override. + * dom/ContainerNode.cpp: + (WebCore::ContainerNode::detach): Adjusted for changes in flag + handling. + (WebCore::ContainerNode::removedFromDocument): ditto + * dom/Document.cpp: + (WebCore::Document::Document): Adjusted for changes in flag handling. + (WebCore::Document::recalcStyle): ditto + (WebCore::Document::setFocusedNode): ditto + * dom/Document.h: + (WebCore::Node::Node): Inline the Node constructor - goes here + because it uses Document. + * dom/DocumentFragment.cpp: include Document.h due to above change + * dom/EditingText.cpp: ditto + * dom/EntityReference.cpp: ditto + * dom/Element.cpp: + (WebCore::Element::getAttribute): Adjusted for changes in flag + handling. + (WebCore::Element::setAttribute): ditto + (WebCore::Element::hasAttributes): ditto + (WebCore::Element::recalcStyle): ditto + (WebCore::Element::finishParsingChildren): ditto + * dom/Element.h: + (WebCore::Element::Element): Inline (moved from .cpp) + (WebCore::Element::isFinishedParsingChildren): + (WebCore::Element::beginParsingChildren): + (WebCore::Element::attributes): Adjusted for changes in flag + handling. + * dom/StyledElement.cpp: + (WebCore::StyledElement::updateStyleAttribute): Adjust for + changes to flag handling. + (WebCore::StyledElement::mapToEntry): ditto + (WebCore::StyledElement::parseMappedAttribute): ditto + (WebCore::StyledElement::copyNonAttributeProperties): ditto + * dom/StyledElement.h: + (WebCore::StyledElement::StyledElement): Inline (moved from.cpp) + (WebCore::StyledElement::invalidateStyleAttribute): Adjust for + changes in flag handling. + * dom/Text.h: + (WebCore::Text::Text): Inline (moved from .cpp) + * dom/Text.cpp: + * html/HTMLAnchorElement.cpp: + (WebCore::HTMLAnchorElement::HTMLAnchorElement): Adjust for changes in + flag handling. + (WebCore::HTMLAnchorElement::parseMappedAttribute): ditto + * html/HTMLElement.cpp: + (WebCore::HTMLElement::create): Tell base class we're an HTML element. + * html/HTMLElement.h: ditto above; remove isHTMLElement override. + * html/HTMLFormControlElement.h: Tell base class we're an HTML element. + * html/HTMLFrameOwnerElement.cpp: + (WebCore::HTMLFrameOwnerElement::HTMLFrameOwnerElement): ditto + * html/HTMLProgressElement.cpp: + (WebCore::HTMLProgressElement::HTMLProgressElement): ditto + * mathml/MathMLElement.cpp: + (WebCore::MathMLElement::MathMLElement): Tell base class we're a styled + element. + * rendering/MediaControlElements.cpp: + (WebCore::MediaControlShadowRootElement::MediaControlShadowRootElement): + Adjust for changes in flag handling. + (WebCore::MediaControlElement::MediaControlElement): ditto + (WebCore::MediaControlInputElement::MediaControlInputElement): ditto + * rendering/RenderFileUploadControl.cpp: + (WebCore::RenderFileUploadControl::updateFromElement): ditto + * rendering/RenderLayer.cpp: + (WebCore::RenderLayer::updateHoverActiveState): ditto + * rendering/RenderProgress.cpp: + (WebCore::RenderProgress::updateValuePartState): ditto + * rendering/RenderSlider.cpp: + (WebCore::RenderSlider::updateFromElement): ditto + * rendering/SVGShadowTreeElements.cpp: + (WebCore::SVGShadowTreeRootElement::SVGShadowTreeRootElement): ditto + * rendering/TextControlInnerElements.cpp: + (WebCore::TextControlInnerElement::attachInnerElement): ditto + * svg/SVGAnimatedProperty.h: + (WebCore::SVGAnimatedPropertyTearOff::setBaseVal): ditto + (WebCore::SVGAnimatedPropertyTearOff::setAnimVal): ditto + * svg/SVGElement.cpp: + (WebCore::SVGElement::SVGElement): Tell base class we're + an svg element. + (WebCore::SVGElement::ensureRareSVGData): Adjust for flag handling + changes. + (WebCore::SVGElement::updateAnimatedSVGAttribute): ditto + * svg/SVGElement.h: + (WebCore::SVGElement::invalidateSVGAttributes): ditto + * svg/SVGPolyElement.cpp: + (WebCore::SVGPolyElement::svgAttributeChanged): ditto + * wml/WMLAnchorElement.cpp: + (WebCore::WMLAnchorElement::WMLAnchorElement): ditto + * wml/WMLElement.cpp: + (WebCore::WMLElement::WMLElement): Tell base class we're a styled + element. + +2010-05-06 Adam Barth <abarth@webkit.org> + + Unreviewed. Fix indent. Sorry, my OCD was acting up. + + * page/EventHandler.cpp: + (WebCore::EventHandler::handleMouseReleaseEvent): + +2010-05-06 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Joseph Pecoraro. + + Web Inspector: store selected Headers / Content tab on explicit switch and/or explicit navigate only. + + https://bugs.webkit.org/show_bug.cgi?id=38660 + + * inspector/front-end/ResourceView.js: + (WebInspector.ResourceView): + (WebInspector.ResourceView.prototype._selectHeadersTab): + (WebInspector.ResourceView.prototype.selectContentTab): + * inspector/front-end/ResourcesPanel.js: + (WebInspector.ResourcesPanel.prototype.showResource): + +2010-05-06 Luiz Agostini <luiz.agostini@openbossa.org> + + Rubber-stamped by Simon Hausmann. + + [Qt] use QT_MOBILE_THEME in Symbian + https://bugs.webkit.org/show_bug.cgi?id=38440 + + Putting QT_MOBILE_THEME into use for Symbian. + + * WebCore.pro: + +2010-05-06 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Unreviewed, build fix WinCE for QtWebKit. + + [Qt] Compilation with Plugins disabled is broken + https://bugs.webkit.org/show_bug.cgi?id=31407 + + Rename platform/qt/TemporaryLinkStubs.cpp to avoid name collition on + Windows. + + Thanks for Ismail "cartman" Donmez for help. + + No new tests, as there is no new functionality. + + * WebCore.gypi: + * WebCore.pro: + * platform/qt/TemporaryLinkStubs.cpp: Removed. + * platform/qt/TemporaryLinkStubsQt.cpp: Copied from WebCore/platform/qt/TemporaryLinkStubs.cpp. + +2010-05-06 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] REGRESSION: Loading of external CSS and JS files over network fails in some cases + https://bugs.webkit.org/show_bug.cgi?id=36755 + + Enable the direct connection between QtNetwork and QtWebKit only for Qt versions + greater than 4.6.2, due to a bug in Qt that's been fixed after 4.6.2. + + * platform/network/qt/QNetworkReplyHandler.cpp: + +2010-05-06 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Reviewed by Xan Lopez. + + Rework where we get page step and line step from, so we do not + depend on scrollbars existing. Caught by API test I forgot to run. + + * platform/gtk/ScrollViewGtk.cpp: + (WebCore::ScrollView::setGtkAdjustments): + +2010-05-06 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Reviewed by Xan Lopez. + + [GTK] Adjustment resetting uses wrong values, and misses page_size and steps + https://bugs.webkit.org/show_bug.cgi?id=38657 + + Fix resetting adjustment values. In the page cache case, we were + confusing page_size and upper, leading to stray scrollbars + sometimes. + + * platform/gtk/ScrollViewGtk.cpp: + (WebCore::ScrollView::setGtkAdjustments): + +2010-05-06 Darin Adler <darin@apple.com> + + Reviewed by Beth Dakin. + + Page::setCanStartMedia does not properly handle the case where a media listener is removed + https://bugs.webkit.org/show_bug.cgi?id=38602 + + We can't find any real case where this causes a crash at this time, but + we want to harden the code anyway. Thus there are no new regression tests. + + * page/Page.cpp: + (WebCore::Page::removeMediaCanStartListener): Removed incorrect assertion. + (WebCore::Page::setCanStartMedia): Change algorithm so we notify listeners + one at a time and don't notify any listener that has already been removed + from the set. + +2010-05-05 Ojan Vafai <ojan@chromium.org> + + Reviewed by Darin Adler. + + shift+click on an existing selection doesn't work right + https://bugs.webkit.org/show_bug.cgi?id=36542 + + NSTextView behavior is to move the end of the selection + closest to the shift-click. Win/Linux behavior is to always + move the focus end of the selection. + + Test: editing/selection/shift-click.html + + * page/EventHandler.cpp: + (WebCore::textDistance): + (WebCore::EventHandler::handleMousePressEventSingleClick): + +2010-05-06 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: implement panels history traversal on Cmd+Left/Right. + + https://bugs.webkit.org/show_bug.cgi?id=38649 + + * inspector/front-end/inspector.js: + (WebInspector.set currentPanel): + (WebInspector.loaded): + (WebInspector.documentKeyDown): + (WebInspector.PanelHistory): + (WebInspector.PanelHistory.prototype.canGoBack): + (WebInspector.PanelHistory.prototype.goBack): + (WebInspector.PanelHistory.prototype.canGoForward): + (WebInspector.PanelHistory.prototype.goForward): + (WebInspector.PanelHistory.prototype.setPanel): + +2010-05-03 Evan Martin <evan@chromium.org> + + Reviewed by Eric Seidel. + + [chromium] use glyphDataForCharacter so we hit the glyphdata cache + https://bugs.webkit.org/show_bug.cgi?id=38500 + + Calling fontDataForCharacters() while rendering text is expensive. + Examining the relevant Mac code in WebKit revealed that calling the + similarly-named glyphDataForCharacters() results in caching the font + data on a per-glyph basis. + + Since we now choose a font based on the first character in a run, we + need to be careful that all the glyphs within the run use the same font. + This is also similar to the WebKit Mac code. We need to remove all of + the script run bits eventually and this is a step in that direction. + + Tests: fast/text/international/danda-space.html spacing changes slightly + (now matches Firefox better) and fast/text/international/thai-baht-space.html + now picks the correct (serif) font for the digits. + + * platform/graphics/chromium/FontLinux.cpp: + (WebCore::TextRunWalker::nextScriptRun): + (WebCore::TextRunWalker::setupFontForScriptRun): + +2010-05-06 Martin Robinson <mrobinson@webkit.org> + + Reviewed by Gustavo Noronha Silva. + + [GTK] Enable DOM clipboard and drag-and-drop access + https://bugs.webkit.org/show_bug.cgi?id=30623 + + Convert dragging portion of drag-and-drop to use DataObjectGtk. + + No new tests, because functionality has not changed. + + * page/gtk/EventHandlerGtk.cpp: + (WebCore::EventHandler::createDraggingClipboard): Pass the DataObjectGtk as a parameter here. + * platform/gtk/ClipboardGtk.h: + (WebCore::ClipboardGtk::create): Take the DataObject as a parameter instead of creating it here. + (WebCore::ClipboardGtk::helper): Added. + (WebCore::ClipboardGtk::dataObject): Added. + * platform/gtk/PasteboardHelper.h: Make targetListForDataObject a public method. + +2010-05-06 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: Do not show content tab for resources + not supporting content preview. + + https://bugs.webkit.org/show_bug.cgi?id=38635 + + * English.lproj/localizedStrings.js: + * inspector/front-end/FontView.js: + (WebInspector.FontView.prototype.hasContentTab): + * inspector/front-end/ImageView.js: + (WebInspector.ImageView.prototype.hasContentTab): + * inspector/front-end/ResourceView.js: + (WebInspector.ResourceView): + (WebInspector.ResourceView.prototype._selectTab): + (WebInspector.ResourceView.prototype.hasContentTab): + * inspector/front-end/SourceView.js: + (WebInspector.SourceView.prototype.hasContentTab): + +2010-05-06 Antonio Gomes <tonikitoo@webkit.org> + + Reviewed by Kenneth Christiansen. + + Spatial Navigation: adapt the logic of {deep}findFocusableNodeInDirection to do traversal starting from Node* not Document* + https://bugs.webkit.org/show_bug.cgi?id=37803 + + Instead of receiving a Document pointer as incoming parameter, patch modifies + findFocusableNodeInDirection and deepFindFocusableNodeInDirection methods to + receive a Node pointer as start for content traversal. + This way we can make good use of deepFindFocusableNodeInDirection to traverse + other scrollable container like scrollable div's, and not only frames or iframes. + + Patch also makes use of 'while' instead of 'for' to loop control, that gives move + flexibility to the incremental step: e.g. if a scrollable div was processed, the incremental + step in the loop does not have to do node->traverseNextNode() but node->traverseNextSibling(). + + No behavior change. It is a preparation for supporting scrollable containers in Spatial + Navigation. + + * page/FocusController.cpp: + (WebCore::FocusController::advanceFocusDirectionally): + (WebCore::FocusController::findFocusableNodeInDirection): + (WebCore::FocusController::deepFindFocusableNodeInDirection): + * page/FocusController.h: + +2010-05-06 Csaba Osztrogonác <ossy@webkit.org> + + Unreviewed WinCE buildfix after r58842. + Preprocessor doesn't understand "true", changed to "1" + + * platform/graphics/MediaPlayer.cpp: + +2010-05-06 Mikhail Naganov <mnaganov@chromium.org> + + Reviewed by Pavel Feldman. + + Temporarily disable 'console.profiles' until we can distinguish + functions from different frames + + https://bugs.webkit.org/show_bug.cgi?id=38638 + + * bindings/v8/custom/V8ConsoleCustom.cpp: + (WebCore::V8Console::profilesAccessorGetter): + +2010-05-06 Steve Block <steveblock@google.com> + + Reviewed by Eric Seidel. + + MAC_JAVA_BRIDGE should be renamed JAVA_BRIDGE + https://bugs.webkit.org/show_bug.cgi?id=38544 + + No new tests, build fix only. + + * DerivedSources.make: + * bindings/js/ScriptController.cpp: + (WebCore::ScriptController::ScriptController): + * bindings/js/ScriptController.h: + * bindings/js/ScriptControllerMac.mm: + (WebCore::ScriptController::createScriptInstanceForWidget): + * bridge/jni/JNIBridge.cpp: + * bridge/jni/JNIBridge.h: + * bridge/jni/JNIUtility.cpp: + * bridge/jni/JNIUtility.h: + * bridge/jni/jni_jsobject.h: + * bridge/jni/jni_jsobject.mm: + * bridge/jni/jni_objc.mm: + * bridge/jni/jsc/JNIBridgeJSC.cpp: + * bridge/jni/jsc/JNIBridgeJSC.h: + * bridge/jni/jsc/JNIUtilityPrivate.cpp: + * bridge/jni/jsc/JNIUtilityPrivate.h: + * bridge/jni/jsc/JavaClassJSC.cpp: + * bridge/jni/jsc/JavaClassJSC.h: + * bridge/jni/jsc/JavaInstanceJSC.cpp: + * bridge/jni/jsc/JavaInstanceJSC.h: + * loader/FrameLoaderClient.h: + +2010-05-05 Alejandro G. Castro <alex@igalia.com> + + Reviewed by Xan Lopez. + + Fixed the gobject introspection compilation with the new DOM + bindings, we needed to add DOM objects. + + * GNUmakefile.am: + +2010-05-06 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + drop support for sessionStorage in sandbox iframes + https://bugs.webkit.org/show_bug.cgi?id=38151 + + This patch causes us to throw a security exception when a sandboxed + iframe attempts to access sessionStorage, matching our behavior for + localStorage. The letter of the spec asks us to create a separate + storage area for each unique origin. We might want to do that in a + future patch, but throwing a security error seems like a safe move now. + + * page/DOMWindow.cpp: + (WebCore::DOMWindow::sessionStorage): + (WebCore::DOMWindow::localStorage): + * page/DOMWindow.h: + * page/DOMWindow.idl: + * page/SecurityOrigin.h: + (WebCore::SecurityOrigin::canAccessSessionStorage): + * storage/StorageEventDispatcher.cpp: + (WebCore::StorageEventDispatcher::dispatch): + +2010-05-06 Andy Estes <aestes@apple.com> + + Reviewed by Maciej Stachowiak. + + Allow forms submitting to target="_blank" to open popups if the submission + originated from a user gesture. + + https://bugs.webkit.org/show_bug.cgi?id=37335 + <rdar://problem/7884980> + + Test: fast/events/popup-allowed-from-gesture-initiated-form-submit.html + + * bindings/js/ScriptController.cpp: + (WebCore::ScriptController::processingUserGesture): If no DOM event is + being processed, consult UserGestureIndicator to determine return value. + * bindings/js/ScriptController.h: Moved the logic of processingUserGestureEvent() + into processingUserGesture(). + +2010-05-06 Xan Lopez <xlopez@igalia.com> + + Rubber-stamped by Eric Seidel. + + [GTK] Refactor GenerateProperties in CodeGenerationGObject.pm + https://bugs.webkit.org/show_bug.cgi?id=38577 + + Thinko caught while refactoring, $custom variable was not + initialized. + + * bindings/scripts/CodeGeneratorGObject.pm: + * bindings/scripts/test/GObject/WebKitDOMTestObj.cpp: + (webkit_dom_test_obj_set_property): + (webkit_dom_test_obj_get_property): + (webkit_dom_test_obj_class_init): + +2010-05-06 Xan Lopez <xlopez@igalia.com> + + Rubber-stamped by Eric Seidel. + + [GTK] Refactor GenerateProperties in CodeGenerationGObject.pm + https://bugs.webkit.org/show_bug.cgi?id=38577 + + Refactor GenerateProperty out of GenerateProperties. This is in + preparation for EventListeren attributes, which won't generate + normal GObject properties. + + * bindings/scripts/CodeGeneratorGObject.pm: + +2010-05-06 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Joseph Pecoraro. + + Web Inspector: follow up to linkify event listeners. + + https://bugs.webkit.org/show_bug.cgi?id=38257 + + * bindings/js/ScriptEventListener.cpp: + (WebCore::eventListenerHandlerLocation): + * bindings/v8/ScriptEventListener.cpp: + (WebCore::eventListenerHandlerLocation): + * inspector/front-end/ElementsPanel.js: + (WebInspector.ElementsPanel.prototype.linkifyNodeReference): + * inspector/front-end/EventListenersSidebarPane.js: + +2010-05-05 Charles Wei <charles.wei@torchmobile.com.cn> + + Reviewed by George Staikos + + https://bugs.webkit.org/show_bug.cgi?id=37848 + This patch adds WCSS -wap-input-format and -wap-input-required support to WebKit + + Tests: fast/wcss/wap-input-format.xhtml + fast/wcss/wap-input-required.xhtml + + * css/CSSParser.cpp: + (WebCore::CSSParser::parseValue): + (WebCore::CSSParser::parseWCSSInputProperty): + * css/CSSParser.h: + * css/CSSStyleSelector.cpp: + (WebCore::CSSStyleSelector::applyProperty): + * css/WCSSPropertyNames.in: + * dom/InputElement.cpp: + (WebCore::InputElement::sanitizeValue): + (WebCore::InputElement::handleBeforeTextInsertedEvent): + (WebCore::InputElementData::InputElementData): + (WebCore::formatCodes): + (WebCore::cursorPositionToMaskIndex): + (WebCore::InputElement::isConformToInputMask): + (WebCore::InputElement::validateInputMask): + * dom/InputElement.h: + (WebCore::InputElementData::inputFormatMask): + (WebCore::InputElementData::setInputFormatMask): + (WebCore::InputElementData::maxInputCharsAllowed): + (WebCore::InputElementData::setMaxInputCharsAllowed): + * html/HTMLInputElement.cpp: + (WebCore::HTMLInputElement::setWapInputFormat): + * html/HTMLInputElement.h: + (WebCore::HTMLInputElement::data): + * wml/WMLInputElement.h: + (WebCore::WMLInputElement::data): + +2010-05-05 MORITA Hajime <morrita@google.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=38150 + Refactoring: webkitEditableContentChangedEvent should be handled by the owner of appropriate the renderer. + + Moved a part of code chunk in HTMLFormControlElementWithState::defaultEventHandler() + which accesses the renderer from foreign node, + to TextControlInnerTextElement::defaultEventHandler() which owns the renderer. + + No new tests. No behavioral change. + + * html/HTMLFormControlElement.cpp: + (WebCore::HTMLFormControlElementWithState::defaultEventHandler): + * html/HTMLFormControlElement.h: + * html/HTMLInputElement.h: + * html/HTMLTextAreaElement.h: + * rendering/TextControlInnerElements.cpp: + (WebCore::TextControlInnerTextElement::defaultEventHandler): + +2010-05-05 Joseph Pecoraro <joepeck@webkit.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: Line Numbers should be Aligned with the Source Code Line + https://bugs.webkit.org/show_bug.cgi?id=38593 + + If there is a message bubble, such as an error message, in a source view + the line number should be in line with the source code line, not centered + between the source and bubble. + + * inspector/front-end/textViewer.css: + (.webkit-line-number): added vertical-align: top + +2010-05-05 Dan Bernstein <mitz@apple.com> + + Fix the decelerated compositing build. + + * page/FrameView.cpp: + (WebCore::FrameView::isEnclosedInCompositingLayer): + * page/FrameView.h: + +2010-05-05 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Darin Adler. + + Bug 38604 - workers-gc2 crashing on Qt + + This appears to be due to a couple of issues. + (1) When the atomic string table is deleted it does not clear the 'inTable' bit + on AtomicStrings - it implicitly assumes that all AtomicStrings have already + been deleted at this point (otherwise they will crash in their destructor when + they try to remove themselves from the atomic string table). + (2) We don't fix the ordering in which WTF::WTFThreadData and + WebCore::ThreadGlobalData are destructed. + + We should make sure that ThreadGlobalData is cleaned up before worker threads + terminate and WTF::WTFThreadData is destroyed, and we should clear the inTable + bit of members on atomic string table destruction. + + WTF changes (fix issue 2, above) - clean up the thread data on worker termination. + + * platform/ThreadGlobalData.cpp: + (WebCore::ThreadGlobalData::~ThreadGlobalData): + (WebCore::ThreadGlobalData::destroy): + * platform/ThreadGlobalData.h: + * workers/WorkerThread.cpp: + (WebCore::WorkerThread::workerThread): + +2010-05-05 Dan Bernstein <mitz@apple.com> + + Reviewed by Simon Fraser. + + <rdar://problem/7932072> Iframes in composited layers don’t repaint correctly (affects Yahoo! Mail with Flash Player 10.1) + https://bugs.webkit.org/show_bug.cgi?id=38427 + + Test: compositing/iframes/iframe-in-composited-layer.html + + * WebCore.base.exp: Export FrameView::isEnclosedInCompositingLayer(). + * page/FrameView.cpp: + (WebCore::FrameView::isEnclosedInCompositingLayer): Added this predicate. + * page/FrameView.h: + +2010-05-05 Chris Marrin <cmarrin@apple.com> + + Reviewed by Simon Fraser. + + Got composited iframes showing up on Mac again + https://bugs.webkit.org/show_bug.cgi?id=38565 + + This was broken by http://trac.webkit.org/changeset/58798. That + change connected iframes through the parent document to the root + of the layer tree. That is correct for Windows, but not for Mac. + So the places where the linkage is made were wrapped in + shouldPropagateCompositingToIFrameParent() calls, which is + always false for Mac. + + Test: compositing/iframes/composited-iframe-alignment.html + + * rendering/RenderLayerCompositor.cpp:Avoid doing composited iframe linkage on Mac + (WebCore::RenderLayerCompositor::rebuildCompositingLayerTree): + (WebCore::RenderLayerCompositor::didMoveOnscreen): + (WebCore::RenderLayerCompositor::willMoveOffscreen): + (WebCore::RenderLayerCompositor::ensureRootPlatformLayer): + +2010-05-05 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=38260 + <rdar://problem/7917548> Fix whitespace removing in deprecatedParseURL(). + + Broken all the way since r4 (yes, that's a revision number). + + Test: http/tests/security/xss-DENIED-javascript-with-spaces.html + + * css/CSSHelper.cpp: (WebCore::deprecatedParseURL): Fixed loop conditions for remaining length. + +2010-05-05 Chris Fleizach <cfleizach@apple.com> + + Reviewed by Beth Dakin. + + Many AXUnknown showing up in the hierarchy + https://bugs.webkit.org/show_bug.cgi?id=38607 + + The RenderTableSection should not be an accessible element. + + Test: platform/mac/accessibility/parent-of-table-row-is-table.html + + * accessibility/AccessibilityRenderObject.cpp: + (WebCore::AccessibilityRenderObject::determineAccessibilityRole): + +2010-05-05 Csaba Osztrogonác <ossy@webkit.org> + + Reviewed by Simon Hausmann. + + [Qt]Disable Qt Multimedia backend for HTML 5 Audio and Video elements + Fall back to the Phonon backend until the release situation has been cleared up. + + https://bugs.webkit.org/show_bug.cgi?id=38612 + + Buildfix for QT_VERSION >= 0x040700 after r58810. + + * platform/graphics/MediaPlayer.cpp: + +2010-05-05 Jian Li <jianli@chromium.org> + + Reviewed by David Levin. + + XMLHttpRequestUpload events do not fire when sending a raw file or FormData object. + https://bugs.webkit.org/show_bug.cgi?id=37771 + + Test: http/tests/local/formdata/upload-events.html + + * xml/XMLHttpRequest.cpp: + (WebCore::XMLHttpRequest::createRequest): + +2010-05-05 Csaba Osztrogonác <ossy@webkit.org> + + Reviewed by Simon Hausmann. + + [Qt] Qt port should use its own QUuid class to create UUID string. + https://bugs.webkit.org/show_bug.cgi?id=38581 + + * platform/UUID.cpp: + (WebCore::createCanonicalUUIDString): Added PLATFORM(QT) case. + +2010-05-05 Alexey Proskuryakov <ap@apple.com> + + Roll out r58830 for breaking tests. + + Was: https://bugs.webkit.org/show_bug.cgi?id=38546 + Node.focus() fails to move focus from subframe properly + + * html/HTMLFrameElementBase.cpp: + (WebCore::HTMLFrameElementBase::setFocus): + +2010-05-05 Jian Li <jianli@chromium.org> + + Reviewed by Adam Barth. + + Implement FileReader class. + https://bugs.webkit.org/show_bug.cgi?id=38157 + + This patch only contains the implementation of FileReader class as defined + in the File API spec: http://www.w3.org/TR/file-upload/#dfn-filereader. + + New test will be added when a IDL is exposed and the FILE_READER is turned + on. + + * GNUmakefile.am: + * WebCore.gypi: + * WebCore.pro: + * WebCore.vcproj/WebCore.vcproj: + * WebCore.xcodeproj/project.pbxproj: + * dom/EventNames.h: + * dom/EventTarget.cpp: + (WebCore::EventTarget::toFileReader): + * dom/EventTarget.h: + * html/FileError.h: + (WebCore::FileError::FileError): + * html/FileReader.cpp: Added. + * html/FileReader.h: Added. + * html/FileStream.cpp: + (WebCore::FileStream::FileStream): + (WebCore::FileStream::openForRead): + (WebCore::FileStream::close): + (WebCore::FileStream::read): + * html/FileStream.h: + +2010-05-05 Steve Falkenburg <sfalken@apple.com> + + Reviewed by Maciej Stachowiak. + + REGRESSION(r57969) Image decoder is repeatedly destroyed/created in CoreGraphics-based Windows WebKit + https://bugs.webkit.org/show_bug.cgi?id=38595 + + * platform/graphics/cg/ImageSourceCG.cpp: + (WebCore::ImageSource::setData): + +2010-05-05 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Adele Peterson. + + https://bugs.webkit.org/show_bug.cgi?id=38546 + Node.focus() fails to move focus from subframe properly + + Test: fast/frames/take-focus-from-iframe.html + + * html/HTMLFrameElementBase.cpp: (WebCore::HTMLFrameElementBase::setFocus): Don't clear + focus if this frame doesn't have it. This can happen if page's and HTMLFrameElement's ideas + of focused frame get out of sync temporarily. + +2010-05-05 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Adele Peterson. + + https://bugs.webkit.org/show_bug.cgi?id=26824 + <rdar://problem/7018610> EventHandler can operate on a wrong frame if focus changes during + keyboard event dispatch. + + EventHandler object is tied to a frame, so it's wrong for it to continue processing a keyboard + event if focused frame changes between keydown and keypress. + + * manual-tests/focus-change-between-key-events.html: Added. + + * page/EventHandler.cpp: (WebCore::EventHandler::keyEvent): Bail out early if focused frame + changes while dispatching keydown. Also made similar changes for Windows to maintain matching + behavior, even though EventHandler was re-entered anyway due to WM_KEYDOWN and WM_CHAR being + separate events. + +2010-05-05 Steve Block <steveblock@google.com> + + Reviewed by Adam Barth. + + MediaError.h is missing PassRefPtr.h include + https://bugs.webkit.org/show_bug.cgi?id=38575 + + No new tests, build fix only. + + * html/MediaError.h: + +2010-05-05 Alexander Pavlov <apavlov@chromium.org> + + Reviewed by Pavel Feldman. + + Web Inspector: Audits panel: Resource counters get reset when switching panels while reloading page + https://bugs.webkit.org/show_bug.cgi?id=38579 + + * inspector/front-end/AuditLauncherView.js: + (WebInspector.AuditLauncherView.prototype.updateResourceTrackingState): + (WebInspector.AuditLauncherView.prototype._updateResourceProgress): + +2010-05-05 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Joseph Pecoraro. + + Web Inspector: Doubleclick on line number should not trigger source editing. + + https://bugs.webkit.org/show_bug.cgi?id=38588 + + * inspector/front-end/TextViewer.js: + (WebInspector.TextViewer.prototype._handleDoubleClick): + +2010-05-05 Martin Robinson <mrobinson@webkit.org> + + Reviewed by Gustavo Noronha. + + [GTK] Enable DOM clipboard and drag-and-drop access + https://bugs.webkit.org/show_bug.cgi?id=30623 + + Add support in the PasteboardHelper for images, in preparation for drag-and-drop data. + + No new tests as functionality has not changed. + + * platform/gtk/PasteboardHelper.cpp: + (WebCore::PasteboardHelper::fillSelectionData): Add support for images here. + (WebCore::PasteboardHelper::targetListForDataObject): Add support for images here. + +2010-05-05 Stuart Morgan <stuartmorgan@chromium.org> + + Reviewed by Darin Fisher. + + Add a "focused" parameter to Widget::setFocus, and updates Document + so that Widget is informed of focus loss as well as focus gain. + Changes all existing setFocus implementations so that they ignore + the 'false' case, so no behavior is changed until individual + platforms are updated to handle the new case (if they want to). + + https://bugs.webkit.org/show_bug.cgi?id=37961 + + * dom/Document.cpp: + (WebCore::Document::setFocusedNode): + * platform/Widget.h: + * platform/android/WidgetAndroid.cpp: + (WebCore::Widget::setFocus): + * platform/chromium/WidgetChromium.cpp: + (WebCore::Widget::setFocus): + * platform/efl/WidgetEfl.cpp: + (WebCore::Widget::setFocus): + * platform/gtk/WidgetGtk.cpp: + (WebCore::Widget::setFocus): + * platform/haiku/WidgetHaiku.cpp: + (WebCore::Widget::setFocus): + * platform/mac/WidgetMac.mm: + (WebCore::Widget::setFocus): + * platform/qt/WidgetQt.cpp: + (WebCore::Widget::setFocus): + * platform/win/WidgetWin.cpp: + (WebCore::Widget::setFocus): + * platform/wx/WidgetWx.cpp: + (WebCore::Widget::setFocus): + * plugins/PluginView.h: + * plugins/PluginViewNone.cpp: + (WebCore::PluginView::setFocus): + * plugins/gtk/PluginViewGtk.cpp: + (WebCore::PluginView::setFocus): + * plugins/mac/PluginViewMac.cpp: + (WebCore::PluginView::setFocus): + * plugins/qt/PluginViewQt.cpp: + (WebCore::PluginView::setFocus): + * plugins/symbian/PluginViewSymbian.cpp: + (WebCore::PluginView::setFocus): + * plugins/win/PluginViewWin.cpp: + (WebCore::PluginView::setFocus): + +2010-05-05 Steve Block <steveblock@google.com> + + Reviewed by Pavel Feldman. + + Move V8 ScriptDebugServer::topStackFrame() to ScriptCallStack + https://bugs.webkit.org/show_bug.cgi?id=38531 + + ScriptCallStack::create() uses ScriptDebugServer::topStackFrame(), but ScriptDebugServer + is guarded with ENABLE(JAVASCRIPT_DEBUGGER). This prevents ScriptCallStack from being + built on platforms that do not define ENABLE(JAVASCRIPT_DEBUGGER). + + No new tests, build fix only. + + * bindings/v8/ScriptCallStack.cpp: + (WebCore::ScriptCallStack::callLocation): + (WebCore::ScriptCallStack::createUtilityContext): Helper for topStackFrame, moved from ScriptDebugServer + (WebCore::ScriptCallStack::topStackFrame): Moved from ScriptDebugServer + * bindings/v8/ScriptCallStack.h: + (WebCore::ScriptCallStack::utilityContext): Helper for topStackFrame, moved from ScriptDebugServer + * bindings/v8/ScriptDebugServer.cpp: + * bindings/v8/ScriptDebugServer.h: + +2010-05-05 Csaba Osztrogonác <ossy@webkit.org> + + Rubber-stamped by Simon Hausmann. + + [Qt] REGRESSION(r56869): WinCE build is broken + https://bugs.webkit.org/show_bug.cgi?id=36929 + + * WebCore.pro: LIBS += -lOle32 added. + +2010-05-05 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Tor Arne Vestbø. + + [Qt] Disable Qt Multimedia backend for HTML 5 Audio and Video elements + + Fall back to the Phonon backend until the release situation has been cleared up. + + * WebCore.pro: + +2010-05-05 Ilya Tikhonovsky <loislo@chromium.org> + + Reviewed by Pavel Feldman. + + WebInspector: Clickable links to resources should be used as 'details' part for the all suitable kinds of records. + https://bugs.webkit.org/show_bug.cgi?id=38542 + + * inspector/front-end/TimelinePanel.js: + (WebInspector.TimelinePanel.prototype._innerAddRecordToTimeline): + (WebInspector.TimelineRecordListRow): + (WebInspector.TimelineRecordListRow.prototype.update): + (WebInspector.TimelinePanel.FormattedRecord): + (WebInspector.TimelinePanel.FormattedRecord.prototype._generatePopupContent): + (WebInspector.TimelinePanel.FormattedRecord.prototype._getRecordDetails): + (WebInspector.TimelinePanel.PopupContentHelper): + (WebInspector.TimelinePanel.PopupContentHelper.prototype._createCell): + (WebInspector.TimelinePanel.PopupContentHelper.prototype._appendTextRow): + (WebInspector.TimelinePanel.PopupContentHelper.prototype._appendElementRow): + (WebInspector.TimelinePanel.PopupContentHelper.prototype._appendLinkRow): + +2010-05-05 Nikolas Zimmermann <nzimmermann@rim.com> + + Not reviewed. Add missing files generated by "run-bindings-test", after the DOMTestCallback.idl addition. + + * bindings/scripts/test/GObject/WebKitDOMTestCallback.cpp: Added. + (WebKit::kit): + (webkit_dom_test_callback_callback_with_class1param): + (webkit_dom_test_callback_callback_with_class2param): + (webkit_dom_test_callback_callback_with_non_bool_return_type): + (WebKit::wrapTestCallback): + (WebKit::core): + (webkit_dom_test_callback_finalize): + (webkit_dom_test_callback_set_property): + (webkit_dom_test_callback_get_property): + (webkit_dom_test_callback_class_init): + (webkit_dom_test_callback_init): + * bindings/scripts/test/GObject/WebKitDOMTestCallback.h: Added. + * bindings/scripts/test/GObject/WebKitDOMTestCallbackPrivate.h: Added. + * bindings/scripts/test/ObjC/DOMTestCallback.h: Added. + * bindings/scripts/test/ObjC/DOMTestCallback.mm: Added. + (-[DOMTestCallback dealloc]): + (-[DOMTestCallback finalize]): + (-[DOMTestCallback callbackWithClass1Param:]): + (-[DOMTestCallback callbackWithClass2Param:strArg:]): + (-[DOMTestCallback callbackWithNonBoolReturnType:]): + (-[DOMTestCallback customCallback:class6Param:]): + (core): + (kit): + * bindings/scripts/test/ObjC/DOMTestCallbackInternal.h: Added. + +2010-05-05 Joseph Pecoraro <joepeck@webkit.org> + + Reviewed by Pavel Feldman. + + Web Inspector: FontView needs Cleanup + https://bugs.webkit.org/show_bug.cgi?id=38567 + + FontView was missing some of the newer practices for initialization + that other Resource Views had. Also its width calculations could + result in a single character wrapping. This is general cleanup. + + * inspector/front-end/FontView.js: + (WebInspector.FontView): move initialization into contentTabSelected + (WebInspector.FontView.prototype.contentTabSelected): handle initialization like other Resource Views + (WebInspector.FontView.prototype.updateFontPreviewSize): use a narrower width to prevent text from widowing + +2010-05-05 Dirk Schulze <krit@webkit.org> + + Reviewed by Nikolas Zimmermann. + + SVG hit testing is *way* too slow + https://bugs.webkit.org/show_bug.cgi?id=19312 + + Use the cached stroke and fill boundaries in RenderPath as a heuristik to + speed up SVG's hit testing. + + No new tests added. + + * rendering/RenderPath.cpp: + (WebCore::RenderPath::fillContains): + (WebCore::RenderPath::strokeContains): + +2010-05-04 Dumitru Daniliuc <dumi@chromium.org> + + Reviewed by Adam Barth. + + Auto-generate all Database callbacks. + https://bugs.webkit.org/show_bug.cgi?id=38503 + + * DerivedSources.cpp: + * DerivedSources.make: + * GNUmakefile.am: + * WebCore.gypi: + * WebCore.pri: + * WebCore.pro: + * WebCore.vcproj/WebCore.vcproj: + * WebCore.xcodeproj/project.pbxproj: + * bindings/js/JSBindingsAllInOne.cpp: + * bindings/js/JSCustomSQLStatementCallback.cpp: Removed. + * bindings/js/JSCustomSQLStatementCallback.h: Removed. + * bindings/js/JSCustomSQLStatementErrorCallback.cpp: + (WebCore::JSSQLStatementErrorCallback::handleEvent): + * bindings/js/JSCustomSQLStatementErrorCallback.h: Removed. + * bindings/js/JSCustomSQLTransactionCallback.cpp: Removed. + * bindings/js/JSCustomSQLTransactionCallback.h: Removed. + * bindings/js/JSCustomSQLTransactionErrorCallback.cpp: Removed. + * bindings/js/JSCustomSQLTransactionErrorCallback.h: Removed. + * bindings/js/JSDatabaseCallback.cpp: Removed. + * bindings/js/JSDatabaseCallback.h: Removed. + * bindings/js/JSDatabaseCustom.cpp: + (WebCore::JSDatabase::changeVersion): + (WebCore::createTransaction): + * bindings/js/JSSQLTransactionCustom.cpp: + (WebCore::JSSQLTransaction::executeSql): + * bindings/scripts/CodeGeneratorJS.pm: + * bindings/scripts/test/JS/JSTestCallback.cpp: + * bindings/v8/custom/V8CustomSQLStatementCallback.cpp: Removed. + * bindings/v8/custom/V8CustomSQLStatementCallback.h: Removed. + * bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp: + (WebCore::V8SQLStatementErrorCallback::handleEvent): + * bindings/v8/custom/V8CustomSQLStatementErrorCallback.h: Removed. + * bindings/v8/custom/V8CustomSQLTransactionCallback.cpp: Removed. + * bindings/v8/custom/V8CustomSQLTransactionCallback.h: Removed. + * bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp: Removed. + * bindings/v8/custom/V8CustomSQLTransactionErrorCallback.h: Removed. + * bindings/v8/custom/V8DatabaseCallback.cpp: Removed. + * bindings/v8/custom/V8DatabaseCallback.h: Removed. + * bindings/v8/custom/V8DatabaseCustom.cpp: + (WebCore::V8Database::changeVersionCallback): + (WebCore::createTransaction): + * bindings/v8/custom/V8SQLTransactionCustom.cpp: + (WebCore::V8SQLTransaction::executeSqlCallback): + * storage/DatabaseCallback.h: + * storage/DatabaseCallback.idl: Added. + * storage/SQLStatement.cpp: + (WebCore::SQLStatement::performCallback): + * storage/SQLStatementCallback.h: + * storage/SQLStatementCallback.idl: Added. + * storage/SQLStatementErrorCallback.idl: Added. + * storage/SQLTransaction.cpp: + (WebCore::SQLTransaction::deliverTransactionCallback): + * storage/SQLTransactionCallback.h: + * storage/SQLTransactionCallback.idl: Added. + * storage/SQLTransactionErrorCallback.h: + * storage/SQLTransactionErrorCallback.idl: Added. + +2010-05-04 Chris Marrin <cmarrin@apple.com> + + Reviewed by Simon Fraser. + + Made composited iframes work on Windows + https://bugs.webkit.org/show_bug.cgi?id=32446 + + This completes the work in http://trac.webkit.org/changeset/57919 + to create compositing layers in the parent document when an iframe has + a compositing layer. The parent document has a layer for the iframe + element and builds a layer tree to the page root. The layer tree for the + iframe document is then parented to the iframe element's GraphicsLayer. + + The RenderLayerCompositor for the iframe document (which owns the + root of the layer tree) now has a clippingLayer which is the + parent of the layer tree root so it can be clipped to the parent + iframe's bounds, taking into account borders, padding, etc. in + the parent iframe element. + + I also got rid of a no longer used function: RenderLayerCompositor::parentInRootLayer + + Test: compositing/iframes/composited-parent-iframe.html + + * rendering/RenderLayerBacking.cpp:Make calls to RenderLayerCompositor to set the clipping bounds for iframe content + * rendering/RenderLayerCompositor.cpp:Hook the iframe content to the parent iframe element + * rendering/RenderLayerCompositor.h: + +2010-05-03 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Adam Barth. + + https://bugs.webkit.org/show_bug.cgi?id=38497 + <rdar://problem/7759438> Make sure that http URLs always have a host in SecurityOrigin + + This is a hardening fix, and behavior really depends on what an underlying networking layer + does. So, no test. + + * page/SecurityOrigin.cpp: + (WebCore::schemeRequiresAuthority): List schemes that need an authority for successful loading. + (WebCore::SecurityOrigin::SecurityOrigin): Never let e.g. http origins with empty authorities + have the same security origin. + +2010-05-04 Zhenyao Mo <zmo@google.com> + + Reviewed by Dimitri Glazkov. + + getFramebufferAttachmentParameter should return the original WebGLTexture/WebGLRenderbuffer instead of creating new ones sharing names. + https://bugs.webkit.org/show_bug.cgi?id=38236 + + * html/canvas/CanvasObject.h: Add type check functions. + (WebCore::CanvasObject::isBuffer): + (WebCore::CanvasObject::isFramebuffer): + (WebCore::CanvasObject::isProgram): + (WebCore::CanvasObject::isRenderbuffer): + (WebCore::CanvasObject::isShader): + (WebCore::CanvasObject::isTexture): + * html/canvas/WebGLBuffer.h: Add type check functions. + (WebCore::WebGLBuffer::isBuffer): + * html/canvas/WebGLFramebuffer.h: Add type check functions. + (WebCore::WebGLFramebuffer::isFramebuffer): + * html/canvas/WebGLProgram.h: Add type check functions. + (WebCore::WebGLProgram::isProgram): + * html/canvas/WebGLRenderbuffer.cpp: remove constructor using existing name. + * html/canvas/WebGLRenderbuffer.h: Add type check functions; remove constructor using existing name. + (WebCore::WebGLRenderbuffer::isRenderbuffer): + * html/canvas/WebGLRenderingContext.cpp: + (WebCore::WebGLRenderingContext::getFramebufferAttachmentParameter): Return original Texture/Renderbuffer instead of creating new ones. + (WebCore::WebGLRenderingContext::findTexture): Find a WebGLTexture using a name. + (WebCore::WebGLRenderingContext::findRenderbuffer): Find a WebGLRenderbuffer using a name. + * html/canvas/WebGLRenderingContext.h: Add find* functions. + * html/canvas/WebGLShader.h: Add type check functions. + (WebCore::WebGLShader::isShader): + * html/canvas/WebGLTexture.cpp: remove constructor using existing name. + * html/canvas/WebGLTexture.h: Add type check functions; remove constructor using existing name. + (WebCore::WebGLTexture::isTexture): + +2010-05-04 Luiz Agostini <luiz.agostini@openbossa.org> + + Reviewed by Simon Hausmann. + + [Qt] QT_MOBILE_THEME compile time flag + https://bugs.webkit.org/show_bug.cgi?id=38439 + + Replacing preprocessor conditional used in RenderThemeQt from Q_WS_MAEMO_5 to + USE(QT_MOBILE_THEME). + + * WebCore.pro: + * platform/qt/RenderThemeQt.cpp: + (WebCore::RenderThemeQt::RenderThemeQt): + (WebCore::RenderThemeQt::qStyle): + (WebCore::RenderThemeQt::extraDefaultStyleSheet): + (WebCore::RenderThemeQt::adjustMenuListButtonStyle): + (WebCore::RenderThemeQt::setPaletteFromPageClientIfExists): + * platform/qt/RenderThemeQt.h: + +2010-05-04 Joseph Pecoraro <joepeck@webkit.org> + + Reviewed by Dan Bernstein. + + SVG fonts trigger GlyphPage::fill with null font + https://bugs.webkit.org/show_bug.cgi?id=38530 + + SVG fonts do not use the glyph page cache. This change detects when + attempting to fill a GlyphPage with an SVG font and indicates that + the glyphs were not available. + + * platform/graphics/GlyphPageTreeNode.cpp: + (WebCore::fill): helper method which handles attempts to fill a GlyphPage with SVG or non-SVG fonts + (WebCore::GlyphPageTreeNode::initializePage): use the helper where appropriate + +2010-05-04 Kent Tamura <tkent@chromium.org> + + Reviewed by David Levin (and unofficially by Enrica Casucci). + + REGRESSION(r54368): Text drag-and-drop from input/textarea doesn't work + if the text is like a URL + https://bugs.webkit.org/show_bug.cgi?id=38374 + + Since r54368, documentFragmentFromDragData() creates an <a> element + with no anchor text for URL-like text dragged from input/textarea + element. If such text is dropped to input/textarea element, the text + is not inserted. + To fix this problem, use the original text or the URL as an anchor + text. + + Test: editing/pasteboard/drag-drop-url-text.html + + * page/DragController.cpp: + (WebCore::documentFragmentFromDragData): + +2010-05-04 Steve Block <steveblock@google.com> + + Reviewed by Darin Adler. + + JavaInstanceJSC.cpp and JNIUtilityPrivate.cpp need to include jni_jsobject.h for jlong_to_pt() and ptr_to_jlong() + https://bugs.webkit.org/show_bug.cgi?id=38525 + + No new tests, build fix only. + + * bridge/jni/jni_jsobject.h: Guard Mac-specific code with PLATFORM(MAC) + * bridge/jni/jsc/JNIUtilityPrivate.cpp: Include jni_jsobject.h + * bridge/jni/jsc/JavaInstanceJSC.cpp: Include jni_jsobject.h + +2010-05-04 Steve Block <steveblock@google.com> + + Reviewed by Darin Adler. + + New FileSystemPOSIX functions cause linker errors on Android + https://bugs.webkit.org/show_bug.cgi?id=38521 + + No new tests, build fix only. + + * platform/android/FileSystemAndroid.cpp: Remove closeFile, which is provided in FileSystemPOSIX.cpp + * platform/posix/FileSystemPOSIX.cpp: Guard writeToFile with !PLATFORM(ANDROID) + +2010-05-04 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: restore main and sidebar scroller positions + when switching between panels. + + https://bugs.webkit.org/show_bug.cgi?id=38522 + + * inspector/front-end/ElementsPanel.js: + (WebInspector.ElementsPanel.prototype.elementsToRestoreScrollPositionsFor): + * inspector/front-end/Panel.js: + (WebInspector.Panel.prototype.show): + (WebInspector.Panel.prototype.hide): + (WebInspector.Panel.prototype.elementsToRestoreScrollPositionsFor): + (WebInspector.Panel.prototype._storeScrollPositions): + (WebInspector.Panel.prototype._restoreScrollPositions): + * inspector/front-end/ResourcesPanel.js: + (WebInspector.ResourcesPanel.prototype.elementsToRestoreScrollPositionsFor): + * inspector/front-end/ScriptsPanel.js: + (WebInspector.ScriptsPanel.prototype.elementsToRestoreScrollPositionsFor): + +2010-05-04 Steven Lai <steven_lai@asia.apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=37900 + <rdar://problem/7806164> cloneNode() does not preserve z-index with more than six digits + + Tests: fast/dom/HTMLInputElement/clone-input-checked.html + fast/dom/clone-node-z-index.html + + * dom/Element.cpp: undid the order change of calling copyNonAttributeProperties() before setAttributes() + (WebCore::Element::cloneElementWithoutChildren): uncheck the previous radio button in the same radio button group only when the checked radio box is appended to the dom tree + * html/HTMLInputElement.cpp: + (WebCore::HTMLInputElement::updateCheckedRadioButtons): + (WebCore::HTMLInputElement::attach): + (WebCore::HTMLInputElement::setChecked): + * html/HTMLInputElement.h: + +2010-04-29 John Gregg <johnnyg@google.com> + + Reviewed by Dmitry Titov. + + notifications should have dir and replaceId attributes. + Note that tests are only enabled in Chromium, skipped elsewhere + since notifications aren't implemented. + https://bugs.webkit.org/show_bug.cgi?id=38336 + + Tests: fast/notifications/notifications-replace.html + fast/notifications/notifications-rtl.html + + * notifications/Notification.h: + (WebCore::Notification::dir): + (WebCore::Notification::setDir): + (WebCore::Notification::replaceId): + (WebCore::Notification::setReplaceId): + * notifications/Notification.idl: + +2010-05-04 Alejandro G. Castro <alex@igalia.com> + + Reviewed by Xan Lopez. + + Fixed error defining the float/double minimum in the object + properties, the smallest value of a float/double is + -G_MAXDOUBLE/-G_MAXFLOAT. + + * bindings/scripts/CodeGeneratorGObject.pm: + +2010-05-03 Joseph Pecoraro <joepeck@webkit.org> + + Reviewed by Dan Bernstein. + + REGRESSION: Text clipped in absolutely positioned search inputs + https://bugs.webkit.org/show_bug.cgi?id=38468 + + Previously I incorrectly added x() and y() to the tx and ty positioning. + This clips a search input like a text input, respecting the vertically + centered text. + + * rendering/RenderTextControlSingleLine.cpp: + (WebCore::RenderTextControlSingleLine::layout): only the Y changes, so change setLocation to setY + (WebCore::RenderTextControlSingleLine::controlClipRect): + +2010-05-04 Alexander Pavlov <apavlov@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: REGRESSION: Up/Down, PgUp/PgDown keys do not change numeric style properties + https://bugs.webkit.org/show_bug.cgi?id=38516 + + * inspector/front-end/StylesSidebarPane.js: + (WebInspector.StylePropertyTreeElement.prototype): + +2010-05-04 Ben Murdoch <benm@google.com> + + Reviewed by Simon Hausmann. + + Crash in handleTouchEvent: using dangling node ptrs in hashmap + https://bugs.webkit.org/show_bug.cgi?id=38514 + + When navigating away from a page, if you have your finger still + pressed and then lift it on the new page we see a crash if the + node got deleted as we still have a dangling pointer in the + m_originatingTouchPointTargets hashmap and try to use it as the + receiver to dispatch a touchend event. + + Test: fast/events/touch/touch-stale-node-crash.html + + * page/EventHandler.cpp: + (WebCore::EventHandler::clear): Clear the hashmap of touch targets. + +2010-05-04 Joseph Pecoraro <joepeck@webkit.org> + + Reviewed by Pavel Feldman. + + Web Inspector: Drawer Misbehaving when Docking / Undocking in Console Panel + https://bugs.webkit.org/show_bug.cgi?id=38510 + + * inspector/front-end/inspector.js: + (WebInspector.set attached): resize the drawer after docking/undocking + +2010-05-04 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Unreviewed, build fix for Symbian. + + [Symbian] Build fix after r58598. + + Use C99 integer types for the Symbian plugin + implementation. + + No new tests, as there is no new functionality. + + * plugins/symbian/PluginPackageSymbian.cpp: + (WebCore::PluginPackage::NPVersion): + * plugins/symbian/PluginViewSymbian.cpp: + (WebCore::PluginView::handlePostReadFile): + +2010-05-04 Nikolas Zimmermann <nzimmermann@rim.com> + + Reviewed by Dirk Schulze. + + Split SVGCharacterLayoutInfo in smaller pieces + https://bugs.webkit.org/show_bug.cgi?id=38513 + + Split SVGCharacterLayoutInfo into SVGCharacterLayoutInfo/SVGCharacterData and SVGTextChunkLayoutInfo. + This is a preparation for more work in the text area. + + * Android.mk: Add SVGCharacterData.(cpp|h) and SVGTextChunkLayoutInfo.h to build. + * GNUmakefile.am: Ditto. + * WebCore.gypi: Ditto. + * WebCore.pro: Ditto + * WebCore.vcproj/WebCore.vcproj: Ditto. + * WebCore.xcodeproj/project.pbxproj: Ditto. + * rendering/SVGCharacterData.cpp: Copied from rendering/SVGCharacterLayoutInfo.cpp. + * rendering/SVGCharacterData.h: Copied from rendering/SVGCharacterLayoutInfo.h. + (WebCore::SVGChar::SVGChar): + * rendering/SVGCharacterLayoutInfo.cpp: + (WebCore::SVGCharacterLayoutInfo::isInitialLayout): Introduced new helper function to share code between addLayoutInformation/addStackContent. + (WebCore::SVGCharacterLayoutInfo::addLayoutInformation): Use new helper function. + (WebCore::SVGCharacterLayoutInfo::addStackContent): Ditto + * rendering/SVGCharacterLayoutInfo.h: + * rendering/SVGRootInlineBox.h: Include new files. + * rendering/SVGTextChunkLayoutInfo.h: Copied from rendering/SVGCharacterLayoutInfo.h. + +2010-05-04 Xan Lopez <xlopez@igalia.com> + + Reviewed by Holger Freyther. + + [GTK] GObject DOM bindings + https://bugs.webkit.org/show_bug.cgi?id=33590 + + Use helper functions from CodeGenerator.pm to figure out whether a + type is "fundamental" or not (basically whether it's anything + other than a string or a non-pointer type). + + * bindings/scripts/CodeGeneratorGObject.pm: + +2010-04-30 Alexander Pavlov <apavlov@chromium.org> + + Reviewed by Yury Semikhatsky. + + Web Inspector: REGRESSION: Disabled style properties are absent in Styles sidebar after WebInspector is re-opened + https://bugs.webkit.org/show_bug.cgi?id=38255 + + Moved stylesheet-related mappings into a separate object stored + in InspectorController rather than InspectorDOMAgent (which gets reset + on every frontend [dis]connect). + + * GNUmakefile.am: + * WebCore.gypi: + * WebCore.pro: + * WebCore.vcproj/WebCore.vcproj: + * WebCore.xcodeproj/project.pbxproj: + * inspector/InspectorCSSStore.cpp: Added. + (WebCore::InspectorCSSStore::InspectorCSSStore): + (WebCore::InspectorCSSStore::~InspectorCSSStore): + (WebCore::InspectorCSSStore::reset): + * inspector/InspectorCSSStore.h: Added. + * inspector/InspectorController.cpp: + (WebCore::InspectorController::InspectorController): + (WebCore::InspectorController::setFrontend): + (WebCore::InspectorController::didCommitLoad): + * inspector/InspectorController.h: + * inspector/InspectorDOMAgent.cpp: + (WebCore::InspectorDOMAgent::InspectorDOMAgent): + (WebCore::InspectorDOMAgent::discardBindings): + (WebCore::InspectorDOMAgent::applyStyleText): + (WebCore::InspectorDOMAgent::setStyleText): + (WebCore::InspectorDOMAgent::setStyleProperty): + (WebCore::InspectorDOMAgent::toggleStyleEnabled): + (WebCore::InspectorDOMAgent::setRuleSelector): + (WebCore::InspectorDOMAgent::addRule): + (WebCore::InspectorDOMAgent::bindStyle): + (WebCore::InspectorDOMAgent::bindRule): + (WebCore::InspectorDOMAgent::buildObjectForStyle): + (WebCore::InspectorDOMAgent::buildObjectForRule): + * inspector/InspectorDOMAgent.h: + (WebCore::InspectorDOMAgent::create): + (WebCore::InspectorDOMAgent::cssStore): + +2010-05-04 Mikhail Naganov <mnaganov@chromium.org> + + Reviewed by Pavel Feldman. + + Display "Recording..." item when recording an user-initiated CPU profile. + + https://bugs.webkit.org/show_bug.cgi?id=38043 + + * English.lproj/localizedStrings.js: + * inspector/front-end/ProfilesPanel.js: + (WebInspector.ProfilesPanel.prototype.addProfileHeader): + (WebInspector.ProfilesPanel.prototype.removeProfileHeader): + (WebInspector.ProfilesPanel.prototype.showProfile): + * inspector/front-end/inspector.js: + (WebInspector.setRecordingProfile): + +2010-05-04 Tucker Jay <jay.tucker@nokia.com> + + Reviewed by Holger Freyther. + + Animated GIF images does not animate 10x as expected by default. + https://bugs.webkit.org/show_bug.cgi?id=36818 + + Added test case to existing manual test to test the + fixed functionality. + + * manual-tests/qt/qt-10loop-anim.gif: Added. + * manual-tests/qt/qt-gif-test.html: + * platform/graphics/qt/ImageDecoderQt.cpp: + (WebCore::ImageDecoderQt::repetitionCount): + +2010-05-04 Dirk Schulze <krit@webkit.org> + + Unreviewed sort of XCodes project file. + + * WebCore.xcodeproj/project.pbxproj: + +2010-05-03 Steven Lai <steven_lai@asia.apple.com> + + Reviewed by Brady Eidson. + + Reverted hashchange() event back to async. + (This change does not update HashChangeEvent to its new proposed interface) + https://bugs.webkit.org/show_bug.cgi?id=36201 + rdar://problem/7780794 + rdar://problem/7761278 (partial fix) + + Tests: fast/loader/hashchange-event-async.html + + * dom/Document.cpp: reverted hashchange() event back to async + (WebCore::Document::enqueueHashchangeEvent): + +2010-05-03 Holger Hans Peter Freyther <zecke@selfish.org> + + Rubber-stamped by Xan Lopez. + + [Cairo,WX] Stop leaking a FontPlatformData. + https://bugs.webkit.org/show_bug.cgi?id=37500 + + Stephan Aßmus pointed out that the pango font backend + is leaking memory and fixed it. The WX font backend + and the Cairo/Fontconfig backend have the same snippet + of code and are leaking memory as well. This commit is + fixing that. + + * platform/graphics/cairo/SimpleFontDataCairo.cpp: + (WebCore::SimpleFontData::smallCapsFontData): + * platform/graphics/wx/SimpleFontDataWx.cpp: + (WebCore::SimpleFontData::smallCapsFontData): + +2010-05-03 James Robinson <jamesr@chromium.org> + + Reviewed by Eric Seidel. + + Clean up a few compiler warnings + https://bugs.webkit.org/show_bug.cgi?id=38073 + + * html/TextMetrics.h: + (WebCore::TextMetrics::width): + * rendering/style/StyleRareInheritedData.h: + * rendering/style/StyleRareNonInheritedData.h: + +2010-05-02 Dumitru Daniliuc <dumi@chromium.org> + + Reviewed by Adam Barth. + + Add the ability to auto-generate callbacks to all code generators. + https://bugs.webkit.org/show_bug.cgi?id=38414 + + * bindings/scripts/CodeGeneratorJS.pm: + * bindings/scripts/CodeGeneratorV8.pm: + * bindings/scripts/test/JS/JSTestCallback.cpp: Added. + (WebCore::JSTestCallback::JSTestCallback): + (WebCore::JSTestCallback::~JSTestCallback): + (WebCore::JSTestCallback::callbackWithClass1Param): + (WebCore::JSTestCallback::callbackWithClass2Param): + * bindings/scripts/test/JS/JSTestCallback.h: Added. + (WebCore::JSTestCallback::create): + * bindings/scripts/test/V8/JSTestCallback.cpp: Added. + (WebCore::V8TestCallback::V8TestCallback): + (WebCore::V8TestCallback::~V8TestCallback): + (WebCore::V8TestCallback::callbackWithClass1Param): + (WebCore::V8TestCallback::callbackWithClass2Param): + * bindings/scripts/test/V8/V8TestCallback.h: Added. + (WebCore::V8TestCallback::create): + * bindings/scripts/test/TestCallback.idl: Added. + +2010-05-03 Kevin Watters <kevinwatters@gmail.com> + + Reviewed by Kevin Ollivier. + + [wx] Build and use Mac's ComplexTextController to support complex text in wx. + https://bugs.webkit.org/show_bug.cgi?id=38482 + + * platform/graphics/FloatSize.h: + * platform/graphics/GlyphBuffer.h: + (WebCore::GlyphBuffer::advanceAt): + (WebCore::GlyphBuffer::add): + * platform/graphics/SimpleFontData.h: + (WebCore::SimpleFontData::getNSFont): + * platform/graphics/mac/ComplexTextController.cpp: + * platform/graphics/mac/ComplexTextController.h: + * platform/graphics/wx/FontCacheWx.cpp: + (WebCore::FontCache::getFontDataForCharacters): + (WebCore::FontCache::getLastResortFallbackFont): + * platform/graphics/wx/FontPlatformData.h: + (toCTFontRef): + (WebCore::FontPlatformData::FontPlatformData): + (WebCore::FontPlatformData::allowsLigatures): + * platform/graphics/wx/FontPlatformDataWx.cpp: + (WebCore::FontPlatformData::FontPlatformData): + (WebCore::FontPlatformData::cgFont): + * platform/graphics/wx/FontPlatformDataWxMac.mm: Added. + (WebCore::FontPlatformData::nsFont): + (WebCore::FontPlatformData::cacheNSFont): + * platform/graphics/wx/FontWx.cpp: + (WebCore::Font::canReturnFallbackFontsForComplexText): + (WebCore::Font::selectionRectForComplexText): + (WebCore::Font::drawComplexText): + (WebCore::Font::floatWidthForComplexText): + (WebCore::Font::offsetForPositionForComplexText): + * platform/graphics/wx/SimpleFontDataWx.cpp: + (WebCore::SimpleFontData::platformInit): + (WebCore::SimpleFontData::containsCharacters): + (WebCore::SimpleFontData::platformWidthForGlyph): + * platform/wx/wxcode/fontprops.h: + * platform/wx/wxcode/mac/carbon/fontprops.mm: + (wxFontContainsCharacters): + (GetTextExtent): + * platform/wx/wxcode/mac/carbon/non-kerned-drawing.cpp: + (WebCore::drawTextWithSpacing): + * platform/wx/wxcode/win/fontprops.cpp: + (wxFontContainsCharacters): + * wscript: + +2010-05-03 Abhishek Arya <inferno@chromium.org> + + Reviewed by Adam Barth. + + Add support for controlling clipboard access from javascript. + Clipboard access from javascript is disabled by default. + https://bugs.webkit.org/show_bug.cgi?id=27751 + + Test: editing/execCommand/clipboard-access.html + + * WebCore.base.exp: + * editing/EditorCommand.cpp: + (WebCore::supportedCopyCut): + (WebCore::supportedPaste): + (WebCore::createCommandMap): + * page/Settings.cpp: + (WebCore::Settings::Settings): + (WebCore::Settings::setJavaScriptCanAccessClipboard): + * page/Settings.h: + (WebCore::Settings::javaScriptCanAccessClipboard): + +2010-05-03 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Adam Barth. + + https://bugs.webkit.org/show_bug.cgi?id=38285 + <rdar://problem/7903453> REGRESSION: Javascript command window.open does not work in empty tab + + Cannot be tested, because new windows created in DRT always have an opener, and thus inherit + its security origin. Only new windows and tabs created by browser chrome had this problem. + + * loader/FrameLoader.cpp: (WebCore::FrameLoader::init): Moved updateSandboxFlags() call to + the beginning, so that an initial document would get correct flags. + +2010-05-03 Noam Rosenthal <noam.rosenthal@nokia.com> + + Reviewed by Darin Adler. + + WebGL compile issue. + Added ExceptionCode.h to JSWebGLArrayBufferConstructor.cpp, for some reason it was missing. + https://bugs.webkit.org/show_bug.cgi?id=38453 + + No new tests: compile fix. + + * bindings/js/JSWebGLArrayBufferConstructor.cpp: + +2010-05-03 Eric Seidel <eric@webkit.org> + + Unreviewed, rolling out r58685. + http://trac.webkit.org/changeset/58685 + https://bugs.webkit.org/show_bug.cgi?id=38461 + + Broke a test on Gtk + + * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: + (WebCore::MediaPlayerPrivateGStreamer::updateStates): + +2010-05-03 Yael Aharon <yael.aharon@nokia.com> + + Reviewed by Darin Adler. + + Use HTML5 number parsing in HTMLProgressElement + https://bugs.webkit.org/show_bug.cgi?id=38434 + + Use parseToDoubleForNumberType instead of toDouble. + Throw an exception when the number is NaN or Infinity. + + * html/HTMLProgressElement.cpp: + (WebCore::HTMLProgressElement::value): + (WebCore::HTMLProgressElement::setValue): + (WebCore::HTMLProgressElement::max): + (WebCore::HTMLProgressElement::setMax): + * html/HTMLProgressElement.h: + * html/HTMLProgressElement.idl: + +2010-05-03 Jens Alfke <snej@chromium.org> + + Reviewed by Darin Fisher. + + [chromium] Add "willSendSubmitEvent" hook to WebFrameClient and FrameLoaderClient + https://bugs.webkit.org/show_bug.cgi?id=38397 + + No tests (functionality is exposed only through native WebKit API.) + + * html/HTMLFormElement.cpp: + (WebCore::HTMLFormElement::prepareSubmit): Call frame loader's dispatchWillSendSubmitEvent + * loader/EmptyClients.h: + * loader/FrameLoaderClient.h: + (WebCore::FrameLoaderClient::dispatchWillSendSubmitEvent): New empty method + +2010-05-03 Philippe Normand <pnormand@igalia.com> + + Reviewed by Eric Carlson. + + [GStreamer] forgotten call to durationChanged in updateStates() + https://bugs.webkit.org/show_bug.cgi?id=38461 + + Notify MediaPlayer if duration is known after playback started. + + * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: + (WebCore::MediaPlayerPrivateGStreamer::updateStates): + +2010-05-03 Ryuan Choi <ryuan.choi@gmail.com> + + Reviewed by Darin Adler. + + fixing build break due to clearWatch() when Geolocation feature is + disabled. + + https://bugs.webkit.org/show_bug.cgi?id=38091 + + no test because this is a build fix only + + * page/Geolocation.cpp: + (WebCore::Geolocation::clearWatch): + +2010-05-03 Stephan Aßmus <superstippi@gmx.de> + + Reviewed by Holger Freyther. + + [Gtk] Fix leaking the FontPlatformData instance used to create the the + small caps font data. + https://bugs.webkit.org/show_bug.cgi?id=37500 + + No new tests needed. + + * platform/graphics/gtk/SimpleFontDataPango.cpp: + (WebCore::SimpleFontData::smallCapsFontData): + - Use a stack allocated FontPlatformData instead of a heap allocated + one that is never freed. + +2010-05-03 Jarkko Sakkinen <jarkko.j.sakkinen@gmail.com> + + Reviewed by Simon Hausmann. + + [Qt] GraphicsLayer: support webGL + https://bugs.webkit.org/show_bug.cgi?id=35388 + + Added support GraphicsContext3D to GraphicsLayer. + Added paint method to GraphicsContext3D for Qt platform that + uses drawTexture() when QGLWidget is used as viewport of + QGraphicsWebView. + Fine-tuned texture and handling and image to texture conversion to + work also when drawTexture() blitting is used. + + * platform/graphics/GraphicsContext3D.h: + * platform/graphics/qt/GraphicsContext3DQt.cpp: + (WebCore::GraphicsContext3DInternal::GraphicsContext3DInternal): + (WebCore::GraphicsContext3D::beginPaint): + (WebCore::GraphicsContext3D::paint): + (WebCore::GraphicsContext3D::texImage2D): + (WebCore::GraphicsContext3D::texSubImage2D): + (WebCore::GraphicsContext3D::getImageData): + * platform/graphics/qt/GraphicsLayerQt.cpp: + (WebCore::GraphicsLayerQtImpl::): + (WebCore::GraphicsLayerQtImpl::GraphicsLayerQtImpl): + (WebCore::GraphicsLayerQtImpl::paint): + (WebCore::GraphicsLayerQtImpl::flushChanges): + (WebCore::GraphicsLayerQt::setContentsToGraphicsContext3D): + (WebCore::GraphicsLayerQt::setGraphicsContext3DNeedsDisplay): + * platform/graphics/qt/GraphicsLayerQt.h: + +2010-05-03 Janne Koskinen <janne.p.koskinen@digia.com> + + Reviewed by Simon Hausmann. + + [Qt] Fix qtlibraryinfix not to contain space + + List catenation with += adds whitespace cutting the infix + from the final target. + + * WebCore.pro: + +2010-05-03 Tor Arne Vestbø <tor.arne.vestbo@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Fix rendering of <button> elements on Mac OS X + + The <button> element has ButtonPart appearance, not PushButton part, + so we have to include ButtonPart when we decide if we should draw the + button as raised on Mac OS X. + + https://bugs.webkit.org/show_bug.cgi?id=38458 + + * platform/qt/RenderThemeQt.cpp: + (WebCore::RenderThemeQt::initializeCommonQStyleOptions): + +2010-04-30 Philippe Normand <pnormand@igalia.com> + + Reviewed by Eric Seidel. + + [GStreamer] endless loop after playback ended + https://bugs.webkit.org/show_bug.cgi?id=38384 + + At playback end ensure duration() will return a valid duration if + we managed to calculate it based on current position. + + Test: media/video-duration-known-after-eos.html + + * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: + (WebCore::MediaPlayerPrivateGStreamer::didEnd): + +2010-05-03 Tor Arne Vestbø <tor.arne.vestbo@nokia.com> + + [Qt] Fix build break on Mac OS X + + * plugins/mac/PluginPackageMac.cpp: Use correct type + * WebCore.pro: Remove duplicate symbol, we now have a Qt implementation + +2010-05-03 Thomas Zander <t.zander@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Fix library infix usage when compiling inside of Qt + + Don't apply the infix when building inside Qt, as that's done through the + inclusion of qbase.pri. + + * WebCore.pro: + +2010-05-02 Dan Bernstein <mitz@apple.com> + + Reviewed by Simon Fraser. + + Another case of <rdar://problem/7552959> REGRESSION: Infinite recursion in Position::getInlineBoxAndOffset() + https://bugs.webkit.org/show_bug.cgi?id=38445 + + Test: editing/selection/mixed-editability-11.html + + * dom/Position.cpp: + (WebCore::downstreamIgnoringEditingBoundaries): Added. Returns the furthest visually equivalent + position downstream, crossing any editability boundaries. + (WebCore::upstreamIgnoringEditingBoundaries): Similarly for upstream. + (WebCore::Position::getInlineBoxAndOffset): Changed the logic for finding an inline box for positions + whose node is a block flow. Instead of traversing the DOM, advance downstream or upstream as far as + possible, crossing any editability boudaries. Infinite recursion is avoided by advancing all the way + and checking that the new position is different from the starting position. Also replaced the specific + test for buttons with the generic and more comprehensive canHaveChildrenForEditing(). + +2010-05-02 Tasuku Suzuki <tasuku.suzuki@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Fix compilation with QT_NO_BEARERMANAGEMENT + https://bugs.webkit.org/show_bug.cgi?id=38324 + + * platform/network/NetworkStateNotifier.h: + * platform/network/qt/NetworkStateNotifierQt.cpp: + +2010-04-29 Janne Koskinen <janne.p.koskinen@digia.com> + + Reviewed by Simon Hausmann. + + [Qt] QtWebKit versioning added + https://bugs.webkit.org/show_bug.cgi?id=37207 + + QtWebkit releases separated from Qt release cycle. + + * WebCore.pro: + +2010-05-02 Joseph Pecoraro <joepeck@webkit.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: Old Style trimWhitespace() should be trim() + https://bugs.webkit.org/show_bug.cgi?id=38441 + + * inspector/front-end/SourceFrame.js: + (WebInspector.SourceFrame.prototype._evalSelectionInCallFrame): + +2010-05-02 Tasuku Suzuki <tasuku.suzuki@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Fix compilation with QT_NO_LINEEDIT + https://bugs.webkit.org/show_bug.cgi?id=38324 + + * platform/qt/RenderThemeQt.cpp: + (WebCore::RenderThemeQt::~RenderThemeQt): + (WebCore::RenderThemeQt::findFrameLineWidth): + +2010-05-02 Pavel Feldman <pfeldman@chromium.org> + + Not reviewed: Touch inspector controller to kick windows tests. + + * inspector/InspectorController.cpp: + +2010-05-02 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: IMG nodes are being added to the DOM tree late, sometimes hiding the revealed element. + + https://bugs.webkit.org/show_bug.cgi?id=38432 + + * inspector/front-end/ElementsTreeOutline.js: + (WebInspector.ElementsTreeOutline.prototype._onmousemove): + (WebInspector.ElementsTreeElement.prototype._createTooltipForNode.setTooltip): + (WebInspector.ElementsTreeElement.prototype._createTooltipForNode): + (WebInspector.ElementsTreeElement.prototype.updateTitle): + (WebInspector.ElementsTreeElement.prototype._attributeHTML): + (): + +2010-05-02 Dirk Schulze <krit@webkit.org> + + Reviewed by Nikolas Zimmermann. + + SVG hkern implementation incomplete + https://bugs.webkit.org/show_bug.cgi?id=38407 + + Test: svg/text/text-hkern.svg + + The current SVG hkern implementation is incomplete and partly wrong. We pass the ACID3 test + by accident. + The new implementation supports all glyph and unicode combinations that are allowed by the Spec + and fixes various of bugs. The parser moved from SVGFontElement to the general parsing code in + SVGParserUtilities. + Some clean-up makes the code more readable and reuseable for the upcoming vkern implementation. + hkern support for text on path is missing and will be added by a following patch. + Unicode strings of hkern elements are just parsed once and not on every glyph again anymore. + + * rendering/SVGRootInlineBox.cpp: + (WebCore::calculateCSSKerning): + (WebCore::applySVGKerning): + (WebCore::SVGRootInlineBox::buildLayoutInformationForTextBox): + * svg/SVGFontElement.cpp: + (WebCore::stringMatchesUnicodeRange): + (WebCore::stringMatchesGlyphName): + (WebCore::matches): + (WebCore::SVGFontElement::getHorizontalKerningPairForStringsAndGlyphs): + * svg/SVGFontElement.h: + * svg/SVGHKernElement.cpp: + (WebCore::SVGHKernElement::buildHorizontalKerningPair): + * svg/SVGHKernElement.h: + * svg/SVGParserUtilities.cpp: + (WebCore::parseGlyphName): + (WebCore::parseUnicodeRange): + (WebCore::parseKerningUnicodeString): + * svg/SVGParserUtilities.h: + +2010-05-02 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: debugger shortcuts are processed twice if source frame has focus. + + https://bugs.webkit.org/show_bug.cgi?id=38431 + + * inspector/front-end/SourceFrame.js: + (WebInspector.SourceFrame): + (WebInspector.SourceFrame.prototype._createViewerIfNeeded): + +2010-05-02 Jarkko Sakkinen <jarkko.j.sakkinen@gmail.com> + + Reviewed by Eric Seidel. + + [Qt] Build error in GraphicsContext3DQt.cpp + https://bugs.webkit.org/show_bug.cgi?id=38382 + + Removed duplicate implementation of isGLES2Compliant from + GraphicsContext3DQt.cpp. Removed deprecated API stuff for + texImage2D/texSubImage2D. + * platform/graphics/qt/GraphicsContext3DQt.cpp: + +2010-05-02 Garret Kelly <gdk@chromium.org> + + Reviewed by David Levin. + + Make the Touch RuntimeEnabledFeature disabled by default. + https://bugs.webkit.org/show_bug.cgi?id=38392 + + * bindings/generic/RuntimeEnabledFeatures.cpp: Disable the Touch feature by default. + +2010-05-02 Michael Nordman <michaeln@google.com> + + Reviewed by Dmitry Titov. + + Define two new ResourceRequestBase TargetTypes for worker and shared worker + main resources. Use the new target types where appropiate. Add logic to marshal + the target type specified by requests initiated on a background worker thread. + + https://bugs.webkit.org/show_bug.cgi?id=38295 + + No new tests. This doesn't have script visible artifacts. + + * platform/network/ResourceRequestBase.cpp: marshal the values + (WebCore::ResourceRequestBase::adopt): + (WebCore::ResourceRequestBase::copyData): + * platform/network/ResourceRequestBase.h: define the types + (WebCore::ResourceRequestBase::): + * workers/DefaultSharedWorkerRepository.cpp: use TargetIsSharedWorker + (WebCore::SharedWorkerScriptLoader::load): + * workers/Worker.cpp: use TargetIsWorker + (WebCore::Worker::Worker): + * workers/WorkerContext.cpp: use TargetIsScript for importScripts + (WebCore::WorkerContext::importScripts): + * workers/WorkerScriptLoader.cpp: add a data member for the target type + (WebCore::WorkerScriptLoader::WorkerScriptLoader): + (WebCore::WorkerScriptLoader::createResourceRequest): + * workers/WorkerScriptLoader.h: + +2010-05-02 Noam Rosenthal <noam.rosenthal@nokia.com> + + Reviewed by Adele Peterson. + + Webkit doesn't compile with 3D-canvas enabled and video disabled + https://bugs.webkit.org/show_bug.cgi?id=38297 + + Added a #ifdef ENABLE(VIDEO) to WebGL code + + No new tests: compile fix. + + * bindings/js/JSWebGLRenderingContextCustom.cpp: + (WebCore::JSWebGLRenderingContext::texImage2D): + (WebCore::JSWebGLRenderingContext::texSubImage2D): + +2010-05-01 Evan Stade <estade@chromium.org> + + Reviewed by David Levin. + + [chromium] Skia needs to fade DragImages + https://bugs.webkit.org/show_bug.cgi?id=38008 + + tested by DragImageTest + + * platform/chromium/DragImageChromiumSkia.cpp: + (WebCore::dissolveDragImageToFraction):implement + (WebCore::createDragImageFromImage):deep copy instead of shallow + +2010-05-01 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Sam Weinig. + + REGRESSION (r58273): Visited links do not change color immediately when Cmd-clicked + https://bugs.webkit.org/show_bug.cgi?id=38422 + <rdar://problem/7921778> + + Tests: + manual-tests/visited-link-new-window.html + + * css/CSSStyleSelector.cpp: + (WebCore::CSSStyleSelector::initElement): Only cache the visited link state + when invoked as part of a helper call to styleForElement or pseudoStyleForElement, + to avoid caching the visited link state beyond the scope of a single style lookup. + (WebCore::CSSStyleSelector::styleForElement): Adjust for above change. + (WebCore::CSSStyleSelector::pseudoStyleForElement): Adjust for above change. + * css/CSSStyleSelector.h: + (WebCore::CSSStyleSelector::styleForElement): Change so "visited link helper mode" + can't accidentally be called from outside CSSStyleSelector itself. + (WebCore::CSSStyleSelector::pseudoStyleForElement): ditto + * manual-tests/visited-link-new-window.html: Added. I could not figure out any way + to make an automated test that supports visited link coloring. + +2010-05-01 Yael Aharon <yael.aharon@nokia.com> + + Reviewed by Darin Adler. + + Move number parsing code out of HTMLInputElement. + https://bugs.webkit.org/show_bug.cgi?id=38203 + + The numebr parsing code follows HTML5 parsing rules and should be available outside of HTMLInputElement. + No new tests as no new functionality was introduced. + + * html/HTMLInputElement.cpp: + * html/HTMLInputElement.h: + * html/HTMLParser.cpp: + (WebCore::serializeForNumberType): + (WebCore::parseToDoubleForNumberType): + * html/HTMLParser.h: + * html/StepRange.cpp: + (WebCore::StepRange::clampValue): + (WebCore::StepRange::valueFromElement): + * html/ValidityState.cpp: + (WebCore::ValidityState::typeMismatch): + * rendering/RenderSlider.cpp: + (WebCore::RenderSlider::setValueForPosition): + +2010-05-01 Xan Lopez <xlopez@igalia.com> + + Reviewed by Oliver Hunt. + + [GTK] GObject DOM bindings + https://bugs.webkit.org/show_bug.cgi?id=33590 + + Unify more logic to skip functions into SkipFunction, and + whitelist the two [Custom] methods in HTMLCollection.idl. + + * bindings/scripts/CodeGeneratorGObject.pm: + +2010-05-01 Robert Hogan <robert@webkit.org> + + Reviewed by Simon Hausmann. + + [Qt] Add smart paste support + + https://bugs.webkit.org/show_bug.cgi?id=38136 + + * WebCore.pro: + * editing/qt/SmartReplaceQt.cpp: Added. + (WebCore::isCharacterSmartReplaceExempt): + * platform/qt/PasteboardQt.cpp: + (WebCore::Pasteboard::writeSelection): + (WebCore::Pasteboard::canSmartReplace): + +2010-04-30 Yoshiki Hayashi <yhayashi@google.com> + + Reviewed by Shinichiro Hamaji. + + https://bugs.webkit.org/show_bug.cgi?id=38249 + + Fixes an issue where border height and padding height are ignored when computing vertically shrinking flexbox's height. + + Test: fast/flexbox/child-flexing.html + + * rendering/RenderFlexibleBox.cpp: + (WebCore::RenderFlexibleBox::allowedChildFlex): + +2010-04-30 Shinichiro Hamaji <hamaji@chromium.org> + + Reviewed by Darin Adler. + + Add layoutTestController.setPrinting() + https://bugs.webkit.org/show_bug.cgi?id=37203 + + Use the renderer's width insteead of screen's width as the width of + a screen depends on machines. + + * rendering/RenderTreeAsText.cpp: + (WebCore::externalRepresentation): + +2010-04-30 Joseph Pecoraro <joepeck@webkit.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: Missing INSPECTOR Guard in Console::lastWMLErrorMessage + https://bugs.webkit.org/show_bug.cgi?id=38366 + + Console::lastWMLErrorMessage is only available if WML is enabled, however + its implementation only makes sense as long as INSPECTOR is enabled + as well. So this adds the ENABLE(INSPECTOR) guard in the function. A + browser without ENABLE(INSPECTOR) will always get an empty result. + + * page/Console.cpp: + +2010-04-28 Joseph Pecoraro <joepeck@webkit.org> + + Reviewed by Oliver Hunt. + + REGRESSION(r58313): Regression evident in pixel tests: the search icon is always clipped at the bottom. + https://bugs.webkit.org/show_bug.cgi?id=38253 + + Test: fast/css/input-search-padding.html + + An <input type="search"> contains an inner block, which is explicitly + centered in RenderTextControlSingleLine based on the height of the element. + However, the clipping rect was not using the set location, and instead + calculated off of the top border and padding alone. This also vertically + centers the Caps Lock indicator. + + * rendering/RenderTextControl.cpp: moved controlClipRect implementation to RenderTextControlSingleLine + * rendering/RenderTextControl.h: allow a subclass implementation of controlClipRect, removed redundant hasControlClip implementation, and moved controlClipRect + * rendering/RenderTextControlSingleLine.cpp: + (WebCore::RenderTextControlSingleLine::paint): vertically center the Caps Lock indicator + (WebCore::RenderTextControlSingleLine::controlClipRect): use the set location of the anonymous inner block instead + * rendering/RenderTextControlSingleLine.h: allow for an implementation of controlClipRect for <input type="search"> + +2010-04-30 Jon Honeycutt <jhoneycutt@apple.com> + + Caret may fail to blink if a focus handler brings up a modal dialog + https://bugs.webkit.org/show_bug.cgi?id=38372 + + Reviewed by Darin Adler. + + * manual-tests/onfocus-alert-blinking-caret.html: Added. + + * page/EventHandler.cpp: + (WebCore::EventHandler::handleMousePressEvent): + Moved the call to setCaretBlinkingSuspended() from here... + (WebCore::EventHandler::handleMousePressEvent): + ... to here. This makes us suspend caret blinking before dispatching the + mouse down event. If dispatching the mouse down event allows the message + loop to run, we want mouse up events received in that message loop to be + able to resume caret blinking. + (WebCore::EventHandler::lostMouseCapture): + We've lost mouse capture and won't be notified of mouse up events; + resume caret blinking. + + * page/EventHandler.h: + Declare lostMouseCapture(). + +2010-04-30 Dimitri Glazkov <dglazkov@chromium.org> + + Unreviewed, build fix. + + [Chromium] Added a simple IdentifierRep struct and removed dependency on + IdentifierRep.h. + + * bindings/v8/V8NPObject.cpp: Added simple IdentifierRep struct. + +2010-04-30 Dimitri Glazkov <dglazkov@chromium.org> + + Unreviewed, build fix. + + [Chromium] Remove bridge/ from include paths. + + * WebCore.gyp/WebCore.gyp: Removed bridge/ from include path. + +2010-04-30 Abhishek Arya <inferno@chromium.org> + + Reviewed by David Kilzer. + + Convert m_documentUnderMouse, m_dragInitiator to RefPtr. + Eliminated unused m_dragInitiator accessor to prevent dereferencing. + https://bugs.webkit.org/show_bug.cgi?id=37618 + + Test: editing/pasteboard/drag-drop-iframe-refresh-crash.html + + * page/DragController.cpp: + (WebCore::DragController::tryDocumentDrag): + (WebCore::DragController::concludeEditDrag): + * page/DragController.h: + (WebCore::DragController::draggingImageURL): + (WebCore::DragController::documentUnderMouse): + +2010-04-29 James Robinson <jamesr@chromium.org> + + Reviewed by Simon Fraser. + + Calls FrameView::scrollPositionChanged whenever a ScrollView is scrolled + https://bugs.webkit.org/show_bug.cgi?id=38286 + + When a ScrollView's scroll position is changed, we have to call + FrameView::scrollPositionChanged to generate repaint invalidation for + fixed position elements. This ends up getting called indirectly when + the ScrollView has a platformWidget through the port layer + (see WebHTMLView.mm's _frameOrBoundsChanged method for how the mac + port does it) but not when there is no platformWidget. + + This is tested by the fast/repaint/fixed-* tests when run in pixel + mode. + + Test: fast/repaint/fixed-move-after-keyboard-scroll.html + + * page/FrameView.h: + * platform/ScrollView.cpp: + (WebCore::ScrollView::valueChanged): + * platform/ScrollView.h: + (WebCore::ScrollView::scrollPositionChanged): + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Reviewed by Darin Adler. + + Use C99 integer types in more places. + + * manual-tests/NPN_Invoke/main.c: + (NPP_New): + (NPP_NewStream): + (NPP_WriteReady): + (NPP_Write): + (NPP_HandleEvent): + (functionPointerForTVector): + * plugins/mac/PluginViewMac.cpp: + (WebCore::PluginView::platformGetValueStatic): + (WebCore::PluginView::handlePostReadFile): + +2010-04-30 Darin Adler <darin@apple.com> + + Reviewed by Oliver Hunt. + + Remove unused scrollRectIntoViewRecursively function + https://bugs.webkit.org/show_bug.cgi?id=38403 + + * page/Chrome.cpp: + (WebCore::Chrome::scrollRectIntoView): Moved comment here that was previously + in the scrollRectIntoViewRecursively function. + + * platform/ScrollView.cpp: Get rid scrollRectIntoViewRecursively. + * platform/ScrollView.h: Ditto. Fix comment that refers to the two functions. + Also correct all uses of the term "method" to use the C++ term "function" and + got rid of double spaces after periods. + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Another Qt build fix. + + * plugins/qt/PluginViewQt.cpp: + (WebCore::PluginView::platformGetValueStatic): + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Add back TRUE, FALSE and NULL macros. They were not meant to be removed! + + * bridge/npapi.h: + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Try to fix the Qt build this time. + + * plugins/qt/PluginPackageQt.cpp: + (WebCore::staticPluginQuirkRequiresGtkToolKit_NPN_GetValue): + (WebCore::PluginPackage::NPVersion): + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Yet another build fix. + + * plugins/gtk/PluginPackageGtk.cpp: + (WebCore::PluginPackage::NPVersion): + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Fix build. + + * bridge/npapi.h: + +2010-04-30 Jian Li <jianli@chromium.org> + + Reviewed by Darin Fisher. + + [chromium] Add WebFileSystem interface and hook up with all FileSystem methods. + https://bugs.webkit.org/show_bug.cgi?id=38228 + + * platform/chromium/ChromiumBridge.h: + * platform/chromium/FileSystemChromium.cpp: + (WebCore::openFile): + (WebCore::closeFile): + (WebCore::seekFile): + (WebCore::truncateFile): + (WebCore::readFromFile): + (WebCore::writeToFile): + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Reviewed by Dan Bernstein. + + Final part of + + https://bugs.webkit.org/show_bug.cgi?id=20784 + move npapi.h to C99 integer types + + * bridge/npapi.h: + Remove the old types. + +2010-04-30 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r58569. + http://trac.webkit.org/changeset/58569 + https://bugs.webkit.org/show_bug.cgi?id=38399 + + This broke the GTK bots due to bad GC behavior (Requested by + ericu on #webkit). + + * bindings/js/JSWorkerContextCustom.cpp: + * bindings/v8/custom/V8WorkerContextCustom.cpp: + * storage/Database.idl: + * storage/SQLError.idl: + * storage/SQLResultSet.idl: + * storage/SQLResultSetRowList.idl: + * storage/SQLTransaction.idl: + * workers/WorkerContext.cpp: + (WebCore::WorkerContext::openDatabase): + * workers/WorkerContext.h: + (WebCore::WorkerContext::databaseExceededQuota): + * workers/WorkerContext.idl: + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Fix GTK+ build. + + * plugins/gtk/PluginViewGtk.cpp: + (WebCore::PluginView::handlePostReadFile): + (WebCore::PluginView::platformGetValueStatic): + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Fix Qt build. + + * plugins/qt/PluginViewQt.cpp: + (WebCore::PluginView::handlePostReadFile): + (WebCore::PluginView::platformGetValue): + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Reviewed by Timothy Hatcher. + + Next step towards fixing + + https://bugs.webkit.org/show_bug.cgi?id=20784 + move npapi.h to C99 integer types + + Use the C99 types everywhere. The "old" types are still around but will be removed + in a subsequent commit. + + * bridge/npapi.h: + (_NPCocoaEvent::): + * plugins/PluginPackage.h: + * plugins/PluginStream.cpp: + (WebCore::PluginStream::deliverData): + * plugins/PluginStream.h: + * plugins/PluginView.cpp: + (WebCore::PluginView::postURLNotify): + (WebCore::PluginView::postURL): + (WebCore::PluginView::write): + (WebCore::PluginView::handlePost): + * plugins/PluginView.h: + * plugins/PluginViewNone.cpp: + (WebCore::PluginView::handlePostReadFile): + * plugins/npapi.cpp: + (NPN_MemAlloc): + (NPN_MemFlush): + (NPN_PostURLNotify): + (NPN_PostURL): + (NPN_Write): + * plugins/npfunctions.h: + * plugins/win/PluginPackageWin.cpp: + (WebCore::PluginPackage::NPVersion): + * plugins/win/PluginViewWin.cpp: + (WebCore::PluginView::handlePostReadFile): + +2010-04-30 Peter Kasting <pkasting@google.com> + + Reviewed by David Levin. + + Make all image decoders set the "failed" bit if an image could not be + completely decoded, but no more data is coming. The ICO and BMP + decoders already did this. + https://bugs.webkit.org/show_bug.cgi?id=35411 + + "Failed" does not cause the image to not be displayed, it simply causes + us to not bother to try to decode again if future requests are made, and + for some decoders, lets the decoder clean up some of its temporary + objects. + + No layout tests because this does not change the visible output of decoding in any way. + + * platform/image-decoders/gif/GIFImageDecoder.cpp: + (WebCore::GIFImageDecoder::frameComplete): Return whether the frame could be marked as complete. + (WebCore::GIFImageDecoder::decode): Fail if read() needs more data (and thus returns false) and no more is coming. + * platform/image-decoders/gif/GIFImageDecoder.h: + * platform/image-decoders/gif/GIFImageReader.cpp: + (GIFImageReader::do_lzw): Instead of returning true for buffer underrun and false for failure, return false for both and set the failure flag on failure. + (GIFImageReader::read): Ditto. + * platform/image-decoders/gif/GIFImageReader.h: + * platform/image-decoders/jpeg/JPEGImageDecoder.cpp: + (WebCore::): + (WebCore::JPEGImageReader::decode): See do_lzw() comment above. + (WebCore::JPEGImageDecoder::decode): Fail if decode() needs more data (and thus returns false) and no more is coming. + * platform/image-decoders/jpeg/JPEGImageDecoder.h: + * platform/image-decoders/png/PNGImageDecoder.cpp: + (WebCore::PNGImageReader::decode): Return true for decode success, false for buffer underrun or decode failure, and set the failure flag on decode failure. + (WebCore::PNGImageDecoder::decode): See JPEGImageDecoder::decode() comment above. + * platform/image-decoders/png/PNGImageDecoder.h: + +2010-04-30 Brady Eidson <beidson@apple.com> + + Reviewed by Eric Carlson. + + <rdar://problem/7902467> - Audio plays upon loading of npr.org but shouldn't + + No new tests. (Currently no way to test such site specific hack behavior) + + * html/HTMLMediaElement.cpp: + (WebCore::HTMLMediaElement::HTMLMediaElement): + (WebCore::HTMLMediaElement::asyncEventTimerFired): If the event to be dispatched is the canplay + event, wrap the dispatch with m_dispatchingCanPlayEvent set. + (WebCore::HTMLMediaElement::play): If m_dispatchingCanPlayEvent is true and the site is npr.org, + don't perform the play(). + * html/HTMLMediaElement.h: Add m_dispatchingCanPlayEvent member. + +2010-04-30 Dan Bernstein <mitz@apple.com> + + Reviewed by Adele Peterson. + + Part of <rdar://problem/6649734> Text repainting does not account for glyphs which draw outside the typographic bounds of the font + https://bugs.webkit.org/show_bug.cgi?id=6274 + + Account for glyph overflow of characters in the range U+1E00..U+2000, but without sending them + through the complex text code path. Instead, introduce a variant of the fast path that tracks + glyph overflow. + + * platform/graphics/Font.cpp: + (WebCore::Font::drawText): Use codePath(). + (WebCore::Font::floatWidth): Use codePath(). Pass the GlyphOverflow pointer through to + floatWidthForSimpleText() if the code path is SimpleWithGlyphOverflow. + (WebCore::Font::selectionRectForText): Use codePath(). + (WebCore::Font::offsetForPosition): Ditto. + * platform/graphics/Font.h: Replaced canUseGlyphCache() with codePath(). Added a GlyphOverflow + parameter to floatWidthForSimpleText(). + * platform/graphics/FontFastPath.cpp: + Removed ROMAN_AND_GREEK_DIACRITICS_CAN_USE_GLYPH_CACHE. + (WebCore::Font::codePath): Renamed canUseGlyphCache() to this. Where it used to return false, + it now returns Complex. Where it used to return true, it now returns Simple, except for + the range U+1E00..U+2000, where it now returns SimpleWithGlyphOverflow. + (WebCore::Font::floatWidthForSimpleText): Added a GlyphOverflow parameter. If not 0, have the + width iterator account for glyph bounds, then update the GlyphOverflow accordingly. + * platform/graphics/WidthIterator.cpp: + (WebCore::WidthIterator::WidthIterator): Added boolean parameter telling the width iterator + whether to account for glyph bounds. Initialize m_accountForGlyphBounds accordingly. Initialize + m_maxGlyphBoundingBoxY, m_minGlyphBoundingBoxY, m_firstGlyphOverflow and m_lastGlyphOverflow. + (WebCore::WidthIterator::advance): If accounting for glyph bounds, update the above member variables. + * platform/graphics/WidthIterator.h: + (WebCore::WidthIterator::maxGlyphBoundingBoxY): Added this accessor. + (WebCore::WidthIterator::minGlyphBoundingBoxY): Ditto. + (WebCore::WidthIterator::firstGlyphOverflow): Ditto. + (WebCore::WidthIterator::lastGlyphOverflow): Ditto. + +2010-04-30 Chris Marrin <cmarrin@apple.com> + + Reviewed by Simon Fraser. + + Reversed the order of the CSSMatrix.multiply method + https://bugs.webkit.org/show_bug.cgi?id=38337 + + Test: transforms/svg-vs-css.xhtml + + * css/WebKitCSSMatrix.cpp: + (WebCore::WebKitCSSMatrix::multiply): + * platform/graphics/transforms/TransformationMatrix.cpp: + +2010-04-30 Kevin Ollivier <kevino@theolliviers.com> + + Unreviewed. Attempt to fix the Chromium Mac build after the last commit. + + * WebCore.gypi: + +2010-04-30 Kevin Ollivier <kevino@theolliviers.com> + + Reviewed by Dan Bernstein. + + Allow other ports to compile ATSUI and CoreText functions in SimpleFontData for Mac. + https://bugs.webkit.org/show_bug.cgi?id=38334 + + * WebCore.xcodeproj/project.pbxproj: + * platform/graphics/mac/SimpleFontDataATSUI.mm: Copied from WebCore/platform/graphics/mac/SimpleFontDataMac.mm. + * platform/graphics/mac/SimpleFontDataCoreText.cpp: Copied from WebCore/platform/graphics/mac/SimpleFontDataMac.mm. + * platform/graphics/mac/SimpleFontDataMac.mm: + +2010-04-30 Shinichiro Hamaji <hamaji@chromium.org> + + Reviewed by Simon Fraser. + + SHOULD NEVER BE REACHED assertion loading forbes.com + https://bugs.webkit.org/show_bug.cgi?id=38272 + + Ignore page media related pseudo classes. + + Test: printing/pseudo-class-outside-page.html + + * css/CSSStyleSelector.cpp: + (WebCore::CSSStyleSelector::SelectorChecker::checkOneSelector): + +2010-04-30 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Unreviewed, build fix. + + Fix compiler warning "suggest parentheses around" + + No new tests as there is no new functionality. + + * svg/SVGAnimateElement.cpp: + (WebCore::SVGAnimateElement::calculateFromAndToValues): + +2010-04-30 Kent Tamura <tkent@chromium.org> + + Unreviewed. Regression fix. + + Revert a part of r58564 to be compatible with prior behavior + https://bugs.webkit.org/show_bug.cgi?id=38383 + + * rendering/RenderTextControlSingleLine.cpp: + (WebCore::RenderTextControlSingleLine::forwardEvent): + r58564 made a region check for the cancel button stricter, but it + made some tests failing on Chromium. So, relax the check again. + +2010-04-29 Jeremy Orlow <jorlow@chromium.org> + + Reviewed by Darin Fisher. + + Change StorageEvent.uri to StorageEvent.url to match the spec + https://bugs.webkit.org/show_bug.cgi?id=38331 + + As I mentioned in http://www.mail-archive.com/public-webapps@w3.org/msg08495.html + WebKit is the only one who places the document's URL in a 'uri' property + rather than a 'url' property. Even though we've shipped several versions of + browsers with the old name, we probably should change this to comply with the + spec. + + This stuff is covered by existing tests. + + * storage/StorageEvent.cpp: + (WebCore::StorageEvent::create): + (WebCore::StorageEvent::StorageEvent): + (WebCore::StorageEvent::initStorageEvent): + * storage/StorageEvent.h: + (WebCore::StorageEvent::url): + * storage/StorageEvent.idl: + +2010-04-30 Nikolas Zimmermann <nzimmermann@rim.com> + + Reviewed by Dirk Schulze. + + REGRESSION: RenderPath does not handle repaints correctly anymore if bounds changed + https://bugs.webkit.org/show_bug.cgi?id=38385 + + The last SVG performance patch broke repainting if bounds of a RenderPath get smaller. + It would only repaint the smaller part, not the original larger bounds. + + Remove all lazy calculation of the repaint rects, instead calculate object/strokeBoundingBox and repaintRectInLocalCoordinates + once in layout - after LayoutRepainter grabbed the initial bounds, before calling repaintAfterLayout(). We can now inline + all these functions, and save a lot of m_path.isEmpty() checks, which are expensive. No need to store a seperated markerBoundingBox(), + combine with strokeBoundingBox() -> save one FloatRect per RenderPath. Move strokeBoundingBox() from SVGRenderBase to RenderObject, + right next to objectBoundingBox() - to save unnecessary toSVGRenderBase() calls. Completly remove this method. + + Overall this is a regression fix, a performance improvement and saves memory. Something for everyone. + + Tests: svg/custom/repaint-stroke-width-changes.svg + + * rendering/RenderObject.cpp: Added strokeBoundingBox() here, to avoid the toSVGRenderBase() dance. + (WebCore::RenderObject::strokeBoundingBox): + * rendering/RenderObject.h: Ditto. + * rendering/RenderPath.cpp: + (WebCore::RenderPath::RenderPath): + (WebCore::RenderPath::layout): Fix regression, do repainting correctly, by recalculating the boundaries, if needed, instead of nulling them. + (WebCore::RenderPath::paint): Cache SVGRenderStyle in local variable, remove no longer valid FIXME. + (WebCore::RenderPath::calculateMarkerBoundsIfNeeded): Return a FloatRect, to avoid having to store the marker bounding box seperated. + (WebCore::RenderPath::styleWillChange): Mark boundaries as dirty. + (WebCore::RenderPath::updateCachedBoundaries): New function to (re-)calculate all cached boundaries, only called from layout(). + * rendering/RenderPath.h: Rename cached rect variables to have more sensible names. + (WebCore::RenderPath::objectBoundingBox): Inlined, just returns the cached value - no more lazy creation. Huge speedup as this is hot code. + (WebCore::RenderPath::strokeBoundingBox): Ditto. + (WebCore::RenderPath::repaintRectInLocalCoordinates): Ditto. + * rendering/RenderSVGBlock.h: Remove toSVGRenderBase() method. + * rendering/RenderSVGImage.h: Ditto. + * rendering/RenderSVGInline.cpp: No need to call toSVGRenderBase() just to get the strokeBoundingBox(). Unifies code to retrieve bounding boxes. + (WebCore::RenderSVGInline::strokeBoundingBox): + * rendering/RenderSVGInline.h: Remove toSVGRenderBase() method. + * rendering/RenderSVGModelObject.h: Ditto. + * rendering/RenderSVGResourceFilter.cpp: No need to call toSVGRenderBase() anymore, just grab the strokeBoundingBox() from the RenderObject. + (WebCore::RenderSVGResourceFilter::applyResource): + * rendering/RenderSVGText.h: Remove toSVGRenderBase() method. + * rendering/SVGRenderSupport.h: Ditto. Remove markerBoundingBox() method, now combined with strokeBoundingBox(). + (WebCore::SVGRenderBase::strokeBoundingBox): + * rendering/SVGRootInlineBox.h: Remove toSVGRenderBase() method. + * rendering/style/SVGRenderStyle.h: Add hasMarkers() helper method, to avoid doing unnecessary work in RenderPath. + (WebCore::SVGRenderStyle::hasMarkers): + +2010-04-30 Eric Uhrhane <ericu@chromium.org> + + Reviewed by Dmitry Titov. + + Add bindings for async DB API in Workers. + https://bugs.webkit.org/show_bug.cgi?id=34992 + + Tests: storage/change-version-handle-reuse-worker.html + storage/execute-sql-args-worker.html + + * bindings/js/JSWorkerContextCustom.cpp: Add openDatabase binding. + (WebCore::JSWorkerContext::openDatabase): + + * bindings/v8/custom/V8WorkerContextCustom.cpp: Add openDatabase stub; Chromium will need work both in V8 and in the browser process before we can turn this on there. + (WebCore::V8WorkerContext::openDatabaseCallback): + + Add NoStaticTables flags to all objects now shared with workers. + * storage/Database.idl: + * storage/SQLError.idl: + * storage/SQLResultSet.idl: + * storage/SQLResultSetRowList.idl: + * storage/SQLTransaction.idl: + + * workers/WorkerContext.h: Add databaseExceededQuota. + * workers/WorkerContext.cpp: + (WebCore::WorkerContext::databaseExceededQuota): Add stub implementation for testing; you just get 5MB for now. + (WebCore::WorkerContext::openDatabase): Remove invalid assertion. + + Add the IDL for the call to openDatabase. + * workers/WorkerContext.idl: + +2010-04-30 Shinichiro Hamaji <hamaji@chromium.org> + + Reviewed by Darin Adler. + + Unnecessary PrintContext::end() calls + https://bugs.webkit.org/show_bug.cgi?id=38247 + + Refactoring only, so no new tests. + + * page/PrintContext.cpp: + (WebCore::PrintContext::pageNumberForElement): + (WebCore::PrintContext::numberOfPages): + +2010-04-30 Kent Tamura <tkent@chromium.org> + + Reviewed by Adele Peterson. + + Implement interactive behavior of spin buttons. + https://bugs.webkit.org/show_bug.cgi?id=35686 + + Introduce SpinButtonElement. It is a shadow element class for + spin buttons. If the upper side of the element is clicked, calls + HTMLInputElement::stepUpFromRenderer(1). If the lower button is + clicked, calls HTMLInputElement::stepUpFromRenderer(-1). + + SpinButtonElement tracks the mouse pointer position, and + RenderTheme sets ControlStates::SpinUpState if the pointer is on + the upper side. + + Test: platform/mac/fast/forms/input-number-click.html + + * dom/Element.h: + (WebCore::Element::isSpinButtonElement): + * editing/VisibleSelection.cpp: + (WebCore::VisibleSelection::adjustSelectionToAvoidCrossingEditingBoundaries): + Remove an assertion. lastEditablePositionBeforePositionInRoot() can + return null in a case that m_end is at a shadow element (a spin button) + and baseRoot is another shadow element (inner text block) in the same + node (an INPUT element). + * html/HTMLInputElement.cpp: + (WebCore::HTMLInputElement::stepUpFromRenderer): + * html/HTMLInputElement.h: + (WebCore::HTMLInputElement::hasSpinButton): + Add types supporting step attribute except RANGE. + * rendering/RenderTextControlSingleLine.cpp: + (WebCore::RenderTextControlSingleLine::nodeAtPoint): + (WebCore::RenderTextControlSingleLine::forwardEvent): + (WebCore::RenderTextControlSingleLine::preferredContentWidth): + (WebCore::RenderTextControlSingleLine::createSubtreeIfNeeded): + * rendering/RenderTextControlSingleLine.h: + * rendering/RenderTheme.cpp: + (WebCore::RenderTheme::controlStatesForRenderer): + (WebCore::RenderTheme::isSpinUpButtonPartPressed): + (WebCore::RenderTheme::isSpinUpButtonPartHovered): + * rendering/RenderTheme.h: + * rendering/TextControlInnerElements.cpp: + (WebCore::SpinButtonElement::SpinButtonElement): + (WebCore::SpinButtonElement::defaultEventHandler): + * rendering/TextControlInnerElements.h: + (WebCore::SpinButtonElement::isSpinButtonElement): + (WebCore::SpinButtonElement::isEnabledFormControl): + (WebCore::SpinButtonElement::onUpButton): + +2010-04-30 Yael Aharon <yael.aharon@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Enable DOMWindow constructor for HTMLProgressElement + https://bugs.webkit.org/show_bug.cgi?id=38333 + + Add ENABLE_PROGRESS_TAG to FEATURES_DEFINES_JAVASCRIPT. + + * WebCore.pri: + +2010-04-30 Kent Tamura <tkent@chromium.org> + + Reviewed by Adele Peterson. + + Mac implementation of outer-spin-button appearance, and anonymous + element generation for <input type=number>. + https://bugs.webkit.org/show_bug.cgi?id=32813 + + The implementation uses NSStepperCell. Like the other Mac + controls, it has only three candidates for sizes. + + The editable block of an input element is shrunk, and the + anonymous block for a spin button is put on the right of the + editable block. + + Tests: platform/mac/fast/forms/input-appearance-spinbutton-size.html + platform/mac/fast/forms/input-appearance-spinbutton.html + + * dom/Element.cpp: + (WebCore::Element::pseudoStyleCacheIsInvalid): + * dom/InputElement.h: + (WebCore::InputElement::hasSpinButton): + * html/HTMLInputElement.h: + (WebCore::HTMLInputElement::hasSpinButton): Return true for NUMBER type. + * platform/mac/ThemeMac.mm: + (WebCore::sizeFromNSControlSize): Split the main part of sizeFromFont() + to this in order to use stepperControlSizeForFont() instead of + controlSizeForFont(). + (WebCore::sizeFromFont): Just calls sizeFromNSControlSize() with + sizeFromFont(). No behavior changes. + (WebCore::stepperSizes): Returns sizes for mini, small, and regular. + (WebCore::stepperControlSizeForFont): + Dedicated version of controlSizeForFont(). + (WebCore::stepper): Returns NSStepperCell object with specified settings. + (WebCore::paintStepper): + (WebCore::ThemeMac::controlSize): Support for OuterSpinButton. + (WebCore::ThemeMac::minimumControlSize): ditto. + (WebCore::ThemeMac::inflateControlPaintRect): ditto. + (WebCore::ThemeMac::paint): ditto. + * rendering/RenderBox.cpp: + (WebCore::RenderBox::paintBoxDecorations): + Move the content to paintBoxDecorationsWithSize(). + (WebCore::RenderBox::paintBoxDecorationsWithSize): + * rendering/RenderBox.h: Declare paintBoxDecorationsWithSize(). + * rendering/RenderTextControlSingleLine.cpp: + (WebCore::RenderTextControlSingleLine::~RenderTextControlSingleLine): + (WebCore::RenderTextControlSingleLine::paintBoxDecorations): + Call paintBoxDecorationsWithSize() with smaller width by decorationWidthRight(). + (WebCore::RenderTextControlSingleLine::addFocusRingRects): + Add a rectangle of which width is smaller by decorationWidthRight(). + (WebCore::RenderTextControlSingleLine::layout): + Adjust m_outerSpinButton position. + (WebCore::RenderTextControlSingleLine::styleDidChange): + (WebCore::RenderTextControlSingleLine::textBlockWidth): + (WebCore::RenderTextControlSingleLine::decorationWidthRight): + (WebCore::RenderTextControlSingleLine::preferredDecorationWidthRight): + (WebCore::RenderTextControlSingleLine::createSubtreeIfNeeded): + Creates an element for m_outerSpinButton if it is needed. + (WebCore::RenderTextControlSingleLine::createInnerTextStyle): + (WebCore::RenderTextControlSingleLine::createOuterSpinButtonStyle): + * rendering/RenderTextControlSingleLine.h: Declare new methods and m_outerSpinButton. + * rendering/RenderThemeMac.mm: + (WebCore::RenderThemeMac::adjustRepaintRect): Support for OuterSpinButton. + +2010-04-29 Adam Barth <abarth@webkit.org> + + Unreviewed. Update JSC CodeGenerator baseline. Not sure how I missed + this one earlier. + + * bindings/scripts/test/JS/JSTestObj.cpp: + (WebCore::jsTestObjPrototypeFunctionSerializedValue): + +2010-04-29 Justin Garcia <justin.garcia@apple.com> + + Reviewed by Adele Peterson. + + Need to updateLayout after typing commands too + https://bugs.webkit.org/show_bug.cgi?id=38352 + + Replaced !m_parent checks in EditCommand.cpp by the more descriptive isTopLevelCommand(). + Move the post editing operation updateLayout() call to {un,re}appliedEditing so that text insertions, + which don't go through EditCommand::{un,re}apply() can benefit from it too. No test case possible + since most platforms have a layout performed as a side effect of post operation selection code. + + * editing/EditCommand.cpp: + (WebCore::EditCommand::apply): + (WebCore::EditCommand::unapply): + (WebCore::EditCommand::reapply): + * editing/EditCommand.h: + (WebCore::EditCommand::isTopLevelCommand): + * editing/Editor.cpp: + (WebCore::Editor::appliedEditing): + (WebCore::Editor::unappliedEditing): + (WebCore::Editor::reappliedEditing): + +2010-04-29 Dan Bernstein <mitz@apple.com> + + Reviewed by Simon Fraser. + + <rdar://problem/7918086> REGRESSION (r57820): Controller is not displayed in window when opening a MP3 file in browser window + https://bugs.webkit.org/show_bug.cgi?id=38350 + + Tests: media/audio-only-video-intrinsic-size.html + media/media-document-audio-size.html + + * rendering/RenderVideo.cpp: + (WebCore::RenderVideo::RenderVideo): Until metadata is available, ignore the natural size + reported by the player. + (WebCore::RenderVideo::videoSizeChanged): Respect a natural size of zero if reported by the + player, except in standalone media documents. + +2010-04-29 Anders Carlsson <andersca@apple.com> + + Reviewed by Dan Bernstein. + + First part of + https://bugs.webkit.org/show_bug.cgi?id=20784 + move npapi.h to C99 integer types. + + Add nptypes.h to the build. + + * WebCore.xcodeproj/project.pbxproj: + * bridge/npapi.h: + * bridge/npruntime.h: + * bridge/nptypes.h: Added. + +2010-04-29 Xan Lopez <xlopez@igalia.com> + + Rubber-stamped by Adam Barth. + + Update GObject bindings test results. We are actually moving + backwards here, but we'll update them again when we figure out + what broke. + + * bindings/scripts/test/GObject/WebKitDOMTestObj.cpp: + (webkit_dom_test_obj_set_property): + (webkit_dom_test_obj_get_property): + +2010-04-29 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38277 + MiniBrowser: -[WebCoreFlippedView currentEditor]: unrecognized selector + + * platform/mac/ThemeMac.mm: + (-[WebCoreFlippedView currentEditor]): Added currentEditor nil implementation. + +2010-04-29 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + CodeGeneratorJS.pm should be consistent about castedThis versus castedThisObj + https://bugs.webkit.org/show_bug.cgi?id=38338 + + Currently CodeGeneratorJS.pm uses castThis for methods and + castedThisObj for attributes. This inconsistency makes it difficult to + factor common code genereration code into methods shared by both kinds + of bindings. This match aligns the names so that a future patch (e.g., + in https://bugs.webkit.org/show_bug.cgi?id=38313) can reduce copy/paste + code. + + * bindings/scripts/CodeGeneratorJS.pm: + * bindings/scripts/test/JS/JSTestObj.cpp: + (WebCore::setJSTestObjIntAttr): + (WebCore::setJSTestObjLongLongAttr): + (WebCore::setJSTestObjUnsignedLongLongAttr): + (WebCore::setJSTestObjStringAttr): + (WebCore::setJSTestObjTestObjAttr): + (WebCore::setJSTestObjAttrWithException): + (WebCore::setJSTestObjAttrWithSetterException): + (WebCore::setJSTestObjAttrWithGetterException): + (WebCore::jsTestObjPrototypeFunctionVoidMethod): + (WebCore::jsTestObjPrototypeFunctionVoidMethodWithArgs): + (WebCore::jsTestObjPrototypeFunctionIntMethod): + (WebCore::jsTestObjPrototypeFunctionIntMethodWithArgs): + (WebCore::jsTestObjPrototypeFunctionObjMethod): + (WebCore::jsTestObjPrototypeFunctionObjMethodWithArgs): + (WebCore::jsTestObjPrototypeFunctionMethodWithException): + (WebCore::jsTestObjPrototypeFunctionCustomMethod): + (WebCore::jsTestObjPrototypeFunctionCustomMethodWithArgs): + (WebCore::jsTestObjPrototypeFunctionCustomArgsAndException): + (WebCore::jsTestObjPrototypeFunctionAddEventListener): + (WebCore::jsTestObjPrototypeFunctionRemoveEventListener): + (WebCore::jsTestObjPrototypeFunctionWithDynamicFrame): + (WebCore::jsTestObjPrototypeFunctionWithDynamicFrameAndArg): + (WebCore::jsTestObjPrototypeFunctionWithDynamicFrameAndOptionalArg): + (WebCore::jsTestObjPrototypeFunctionWithDynamicFrameAndUserGesture): + (WebCore::jsTestObjPrototypeFunctionWithDynamicFrameAndUserGestureASAD): + (WebCore::jsTestObjPrototypeFunctionWithScriptStateVoid): + (WebCore::jsTestObjPrototypeFunctionWithScriptStateObj): + (WebCore::jsTestObjPrototypeFunctionWithScriptStateVoidException): + (WebCore::jsTestObjPrototypeFunctionWithScriptStateObjException): + (WebCore::jsTestObjPrototypeFunctionMethodWithOptionalArg): + (WebCore::jsTestObjPrototypeFunctionMethodWithNonOptionalArgAndOptionalArg): + (WebCore::jsTestObjPrototypeFunctionMethodWithNonOptionalArgAndTwoOptionalArgs): + +2010-04-29 Gustavo Noronha Silva <gustavo.noronhaollabora.co.uk> + + Reviewed by Xan Lopez. + + [GTK] pointerCursor should use the default cursor set for the window, not GDK_LEFT_PTR + https://bugs.webkit.org/show_bug.cgi?id=36963 + + Use the default cursor instead of hard-coding left pointer. + + * platform/gtk/CursorGtk.cpp: + (WebCore::Cursor::Cursor): + (WebCore::pointerCursor): + +2010-04-29 Ilya Tikhonovsky <loislo@chromium.org> + + Reviewed by Yury Semikhatsky. + + WebInspector: If Timeline panel is in recording mode and is not visible and has received + new events then these events do not appear in the panel when the panel becomes visible. + Timeline popup may appear in the upper left window corner when you switch to another panel. + https://bugs.webkit.org/show_bug.cgi?id=38322 + + * inspector/front-end/Popover.js: + (WebInspector.PopoverHelper.prototype._mouseMove.doHide): + (WebInspector.PopoverHelper.prototype._mouseMove): + (WebInspector.PopoverHelper.prototype.hidePopup): + (WebInspector.PopoverHelper.prototype._hidePopup): + * inspector/front-end/TimelinePanel.js: + (WebInspector.TimelinePanel.prototype.show): + (WebInspector.TimelinePanel.prototype._scheduleRefresh): + (WebInspector.TimelinePanel.prototype._refresh): + +2010-04-29 Anton Muhin <antonm@chromium.org> + + Reviewed by Darin Adler. + + Let's cache nodelists instead of DynamicNodeList::Caches + https://bugs.webkit.org/show_bug.cgi?id=33696 + + Test: fast/dom/Element/node-list-identity.html + + * bindings/js/JSNodeCustom.cpp: + (WebCore::JSNode::markChildren): Mark all cached node lists as well + * dom/ClassNodeList.cpp: + (WebCore::ClassNodeList::ClassNodeList): Don't need DynamicNodeList::Caches argument any more + (WebCore::ClassNodeList::~ClassNodeList): Remove from the cache + * dom/ClassNodeList.h: Added a field with original class names to be used as a key for removal from the cache + (WebCore::ClassNodeList::create): Don't need DynamicNodeList::Caches argument any more + * dom/NameNodeList.cpp: + (WebCore::NameNodeList::NameNodeList): Don't need DynamicNodeList::Caches argument any more + (WebCore::NameNodeList::~NameNodeList): Remove from the cache + * dom/NameNodeList.h: + (WebCore::NameNodeList::create): Don't need DynamicNodeList::Caches argument any more + * dom/Node.cpp: + (WebCore::Node::removeCachedClassNodeList): Remove ClassNodeList from the cache + (WebCore::Node::removeCachedNameNodeList): Remove NameNodeList from the cache + (WebCore::Node::removeCachedTagNodeList): Remove TagNodeList from the cache + (WebCore::Node::getElementsByTagNameNS): Switch to caching node lists themselves, not the data + (WebCore::Node::getElementsByName): Switch to caching node lists themselves, not the data + (WebCore::Node::getElementsByClassName): Switch to caching node lists themselves, not the data + (WebCore::NodeListsNodeData::invalidateCaches): Switch to caching node lists themselves, not the data + (WebCore::NodeListsNodeData::invalidateCachesThatDependOnAttributes): Switch to caching node lists themselves, not the data + (WebCore::NodeListsNodeData::isEmpty): Switch to caching node lists themselves, not the data + (WebCore::markNodeLists): Helper to mark all the node lists in the cache + (WebCore::Node::markCachedNodeListsSlow): Mark all the cached node lists if any could be present + * dom/Node.h: + (WebCore::Node::markCachedNodeLists): Fast-path marking of cached node lists---bails out if there is no rare data + * dom/NodeRareData.h: Changed type of caches to hold raw pointers to node lists, not RefPtr's to data + * dom/TagNodeList.cpp: + (WebCore::TagNodeList::TagNodeList): Don't need DynamicNodeList::Caches argument any more + (WebCore::TagNodeList::~TagNodeList): Remove from the cache + * dom/TagNodeList.h: + (WebCore::TagNodeList::create): Don't need DynamicNodeList::Caches argument any more + +2010-04-29 Mikhail Naganov <mnaganov@chromium.org> + + Reviewed by Yury Semikhatsky. + + [Chromium] Update ScriptProfileNode to retrieve execution time in milliseconds. + + https://bugs.webkit.org/show_bug.cgi?id=38330 + + * bindings/v8/ScriptProfileNode.cpp: + (WebCore::ScriptProfileNode::totalTime): + (WebCore::ScriptProfileNode::selfTime): + +2010-04-28 Dimitri Glazkov <dglazkov@chromium.org> + + Reviewed by Darin Adler. + + A form without a submit button unexpectedly performs its action when Return is pressed + https://bugs.webkit.org/show_bug.cgi?id=9756 + + Implemented implicit form submission algorithm as defined in HTML5 spec: + http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#implicit-submission, + falling back to match IE's behavior in the edge cases. + + The underlying rules are: + + * If the form has no enabled submit buttons, submit if Enter/Return is pressed on the only single-line text field. + + * Otherwise, submit form using first enabled submit button if Enter/Return is pressed on a field + that's not a textarea or a select. + + Test: fast/forms/implicit-submission.html + + * dom/SelectElement.cpp: + (WebCore::SelectElement::menuListDefaultEventHandler): Ripped out implicit submission for select elements. + (WebCore::SelectElement::listBoxDefaultEventHandler): Ditto. + (WebCore::SelectElement::defaultEventHandler): Ditto. + * dom/SelectElement.h: Ditto. + (WebCore::HTMLFormElement::submitImplicitly): Renamed submitClick to submitImplicitly to better match HTML5 spec + language, changed the logic to match the rules above. + * html/HTMLInputElement.cpp: + (WebCore::HTMLInputElement::defaultEventHandler): Reamed clickDefaultButton to implicitSubmission to better match + HTML5 spec language, made radio element to trigger implicit submission. + * html/HTMLSelectElement.cpp: + (WebCore::HTMLSelectElement::defaultEventHandler): Removed passing of form() as parameter, because it's no longer + necessary. + +2010-04-29 Paweł Hajdan, Jr. <phajdan.jr@chromium.org> + + Reviewed by Jeremy Orlow. + + Fix building with libpng-1.4. + https://bugs.webkit.org/show_bug.cgi?id=33287 + + No new tests (no behavior change). + + Original patch by John Bowler <jbowler@acm.org> + + * platform/image-encoders/skia/PNGImageEncoder.cpp: + (WebCore::PNGImageEncoder::encode): + +2010-04-29 Adam Langley <agl@chromium.org> + + Reviewed by David Levin. + + This patch adds support for WOFF in Chromium. Since Chromium + already transcodes all OpenType files for security reasons we + are adding WOFF support into the transcoder. + + https://bugs.webkit.org/show_bug.cgi?id=38217 + + * css/CSSFontFaceSrcValue.cpp: + (WebCore::CSSFontFaceSrcValue::isSupportedFormat): + Recognise "woff" as a font-face format value (guarded by + ENABLE(OPENTYPE_SANITIZER) at this point) + * platform/graphics/opentype/OpenTypeSanitizer.cpp: + (WebCore::OpenTypeSanitizer::sanitize): + Change so that the transcoded font can be larger than the original. + (WOFF files are compressed, so the transcoded TTF is typically + larger.) + +2010-04-29 Alex Milowski <alex@milowski.com> + + Reviewed by Kenneth Rohde Christiansen. + + Updates to the Qt build to enable building MathML support. + + * WebCore.pri: + * WebCore.pro: + +2010-04-29 Xan Lopez <xlopez@igalia.com> + + Reviewed by Gustavo Noronha. + + [GTK] GObject DOM bindings + https://bugs.webkit.org/show_bug.cgi?id=33590 + + Do not generate unneeded boilerplate in {get,set}_property methods + when there are no properties to generate code for. This gets rid + of lots of compiler warnings. + + * bindings/scripts/CodeGeneratorGObject.pm: + +2010-04-29 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Speed up text layouting + https://bugs.webkit.org/show_bug.cgi?id=31719 + + Use QFontMetrics::width() for the text width calculation instead + of QTextLayout. This avoids expensive bearing calculations and the + line breaking code. + + * platform/graphics/qt/FontQt.cpp: + (WebCore::Font::floatWidthForComplexText): + +2010-04-29 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Simon Hausmann. + + [WINCE] Export g_stackBase with JS_EXPORTDATA + https://bugs.webkit.org/show_bug.cgi?id=37437 + + Declare g_stackBase with JS_EXPORTDATA as it is imported from JavaScriptCore. + + * platform/wince/SharedTimerWince.cpp: + +2010-04-29 Adam Barth <abarth@webkit.org> + + Reviewed by Maciej Stachowiak. + + Remove custom bindings for PopStateEvent.initPopStateEvent + https://bugs.webkit.org/show_bug.cgi?id=38311 + + Our code generation of SerializedScriptValue was slightly buggy, but + it's easy to fix. Notice that the conversion to an atomic string is + handled by the C++ type system and doesn't require logic in the code + generator. + + * bindings/js/JSPopStateEventCustom.cpp: + * bindings/scripts/CodeGeneratorJS.pm: + * bindings/scripts/CodeGeneratorV8.pm: + * bindings/scripts/test/GObject/WebKitDOMTestObj.cpp: + (webkit_dom_test_obj_serialized_value): + * bindings/scripts/test/GObject/WebKitDOMTestObj.h: + * bindings/scripts/test/JS/JSTestObj.cpp: + (WebCore::): + (WebCore::jsTestObjPrototypeFunctionSerializedValue): + * bindings/scripts/test/JS/JSTestObj.h: + * bindings/scripts/test/ObjC/DOMTestObj.h: + * bindings/scripts/test/ObjC/DOMTestObj.mm: + (-[DOMTestObj serializedValue:]): + * bindings/scripts/test/TestObj.idl: + * bindings/scripts/test/V8/V8TestObj.cpp: + (WebCore::TestObjInternal::serializedValueCallback): + (WebCore::ConfigureV8TestObjTemplate): + * bindings/v8/custom/V8PopStateEventCustom.cpp: + * dom/PopStateEvent.idl: + +2010-04-29 Kent Tamura <tkent@chromium.org> + + Reviewed by Darin Adler. + + Fix a bug that selection drag-and-drop doesn't work for input/textarea. + https://bugs.webkit.org/show_bug.cgi?id=38175 + + The code supposed the selected region was in the destination text + field. It is not true in a case of drag-and-drop. + + Test: editing/pasteboard/drag-drop-input-textarea.html + + * dom/InputElement.cpp: + (WebCore::InputElement::handleBeforeTextInsertedEvent): + * html/HTMLTextAreaElement.cpp: + (WebCore::HTMLTextAreaElement::handleBeforeTextInsertedEvent): + +2010-04-29 Adam Barth <abarth@webkit.org> + + Reviewed by Maciej Stachowiak. + + Remove custom bindings for NodeFilter.acceptNode + https://bugs.webkit.org/show_bug.cgi?id=38309 + + This "custom" code was just an instance of the CallWith=ScriptState + pattern. Also, it looks like V8 just had a garbage implemenation that + did nothing. + + * WebCore.gypi: + * bindings/js/JSNodeFilterCustom.cpp: + * bindings/v8/custom/V8NodeFilterCustom.cpp: Removed. + * dom/NodeFilter.idl: + +2010-04-29 Noam Rosenthal <noam.rosenthal@nokia.com> + + Reviewed by Laszlo Gombos. + + [Qt] QtWebkit doesn't link with 3D canvas + https://bugs.webkit.org/show_bug.cgi?id=38299 + + Added implementation for GraphicsContext3D::isGLES2Compliant, which returns the correct value based on a Qt #define. + + No new tests: build fix + + * platform/graphics/qt/GraphicsContext3DQt.cpp: + (WebCore::GraphicsContext3D::isGLES2Compliant): + +2010-04-29 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Tor Arne Vestbø. + + [Qt] REGRESSION(r57638): tst_qwebframe::objectDeleted() fails + https://bugs.webkit.org/show_bug.cgi?id=38316 + + Accessing properties of a deleted objects doesn't throw an exception + anymore. + + Continue to expose the QObject class wrapper for objects that + previously existed but don't exist anymore. QtClass is safe to + use with a deleted QObject. + + * bridge/qt/qt_instance.cpp: + (JSC::Bindings::QtInstance::getClass): Return null only if m_class + doesn't exist yet and there's no m_object. + +2010-04-29 Noam Rosenthal <noam.rosenthal@nokia.com> + + Reviewed by Simon Hausmann. + + Reverse animations don't work in some use cases + https://bugs.webkit.org/show_bug.cgi?id=38075 + + This was due to a code path special-casing reverse animations, that became obselete when we aligned our animation code + with the CA implementation. That special case code path is now a bug - and this patch removes it. + + http://staff.washington.edu/fmf/2009/03/25/iphone-3d-css-transformations/ now runs the reverse + animation correctly. + + * platform/graphics/qt/GraphicsLayerQt.cpp: + (WebCore::TransformAnimationQt::applyFrame): + +2010-04-29 Jan Hanssen <jhanssen@codeaurora.org> + + Reviewed by Adam Barth. + + HTMLOptionElement::ownerSelectElement() needs to consider keygen elements + https://bugs.webkit.org/show_bug.cgi?id=26016 + + Patch written by Grace Kloba <klobag@gmail.com>, test fixed by me. + + Test: fast/dom/HTMLKeygenElement/keygen-option-select.html + + * html/HTMLOptionElement.cpp: + (WebCore::HTMLOptionElement::ownerSelectElement): + Make HTMLOptionElement::ownerSelectElement() consider the keygen element in addition to the current select element. + +2010-04-29 Gustavo Sverzut Barbieri <barbieri@profusion.mobi> + + Reviewed by Eric Seidel. + + Add EFL-specific code to Widget.h and move the empty + frameRectsChanged() definition to Widget.cpp, since the EFL port + needs to override that. + http://webkit.org/b/36317 + + No new tests required. + + * WebCore.base.exp: + * platform/Widget.cpp: + (WebCore::Widget::frameRectsChanged): + * platform/Widget.h: + +2010-04-29 Jarkko Sakkinen <jarkko.j.sakkinen@gmail.com> + + Reviewed by Simon Hausmann. + + [Qt] GraphicsContext3DQt.cpp does not implement isGLES2Compliant() + https://bugs.webkit.org/show_bug.cgi?id=38216 + + * platform/graphics/qt/GraphicsContext3DQt.cpp: + (WebCore::GraphicsContext3D::isGLES2Compliant): + +2010-04-29 Zhenyao Mo <zmo@google.com> + + Reviewed by Dimitri Glazkov. + + Remove the unnecessary texImage2D function with Image as input in GraphicsContext3D + https://bugs.webkit.org/show_bug.cgi?id=38235 + + * html/canvas/WebGLRenderingContext.cpp: + (WebCore::WebGLRenderingContext::texImage2D): Add extractImageData; add a common entry point for texImage2D with image input. + (WebCore::WebGLRenderingContext::texImage2DBase): Add this function as the common entry point for texImage2D. + (WebCore::WebGLRenderingContext::texSubImage2D): Add extractImageData; add a common entry point for texSubImage2D with image input. + (WebCore::WebGLRenderingContext::texSubImage2DBase): Add this function as the common entry point for texSubImage2D. + * html/canvas/WebGLRenderingContext.h: Add tex*Image{Base/Image} function declaration. + * platform/graphics/GraphicsContext3D.h: Remove tex*Image declaration with Image input. + * platform/graphics/mac/GraphicsContext3DMac.cpp: Remove tex*Image implementation with Image input. + (WebCore::GraphicsContext3D::texImage2D): + (WebCore::GraphicsContext3D::texSubImage2D): + +2010-04-29 Noam Rosenthal <noam.rosenthal@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] GraphicsLayer: flicker when starting an animation before the previous one ended. + https://bugs.webkit.org/show_bug.cgi?id=38076 + + This was due to the cude in the removeAnimations functions, which called deleteLater() without stopping the + animation synchronously. The delay between the call to that function and the actual call to the animation's destructor + is when the flicker occured. We fix this by calling stop() synchronously, and making sure that the value is reverted + upon stop (updateState) and not upon the object's destruction. + + http://staff.washington.edu/fmf/2009/03/25/iphone-3d-css-transformations/ now doesn't flicker when + the animation is toggled frequently. + + * platform/graphics/qt/GraphicsLayerQt.cpp: + (WebCore::TransformAnimationQt::~TransformAnimationQt): + (WebCore::TransformAnimationQt::applyFrame): + (WebCore::TransformAnimationQt::updateState): + (WebCore::OpacityAnimationQt::~OpacityAnimationQt): + (WebCore::OpacityAnimationQt::updateState): + (WebCore::GraphicsLayerQt::removeAnimationsForProperty): + (WebCore::GraphicsLayerQt::removeAnimationsForKeyframes): + +2010-04-28 Luiz Agostini <luiz.agostini@openbossa.org> + + Reviewed by Simon Fraser. + + Media queries empty values + https://bugs.webkit.org/show_bug.cgi?id=38116 + + Adding isValid() method to MediaQueryExp to make it possible to differentiate + between queries with empty values and queries with invalid values. + + Test: fast/media/media-query-invalid-value.html + + * css/MediaQueryEvaluator.cpp: + (WebCore::MediaQueryEvaluator::eval): + * css/MediaQueryExp.cpp: + (WebCore::MediaQueryExp::MediaQueryExp): + * css/MediaQueryExp.h: + (WebCore::MediaQueryExp::isValid): + +2010-04-28 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Yury Semikhatsky. + + Web Inspector: Allow editing script resources when resource tracking is enabled. + + https://bugs.webkit.org/show_bug.cgi?id=38269 + + * inspector/front-end/ScriptView.js: + * inspector/front-end/ScriptsPanel.js: + (WebInspector.ScriptsPanel.prototype.canEditScripts): + (WebInspector.ScriptsPanel.prototype.editScriptSource): + * inspector/front-end/SourceFrame.js: + (WebInspector.SourceFrame.prototype.get textModel): + * inspector/front-end/SourceView.js: + (WebInspector.SourceView): + (WebInspector.SourceView.prototype._addBreakpoint): + (WebInspector.SourceView.prototype._editLine): + (WebInspector.SourceView.prototype._editLineComplete): + (WebInspector.SourceView.prototype._sourceIDForLine): + +2010-04-25 Antonio Gomes <tonikitoo@webkit.org> + + Reviewed by Darin Adler. + + Clicking a scrollbar blurs the currently focused element + https://bugs.webkit.org/show_bug.cgi?id=16809 + + WebKit ports that do not use native (platform) widgets for rendering the scrollbars + are currently mismatching a common behaviour of other browser vendors (including + Firefox and Opera): clicking on a frame scrollbar *should not* steal focus from content. + WebKit browsers based ports that do use WebCore for handling scrollbars, like QtWebKit for + instance, can observe the opposite behaviour. + + Patch fixes this behaviour by checking if current MouseDown event targets a frame scrollbar. + If that is the case, it bails out and do not change focus behavior at all. + + It is important to note that the given way this is implemented by this patch, non-frame + scrollbars (e.g. a vertical scrollbar of an overflowed textareas or divs) will keep working + in the same way as it works currently. + + Tests: scrollbars/scrollbar-click-does-not-blur-content.html + scrollbars/scrollbar-iframe-click-does-not-blur-content.html + + * page/EventHandler.cpp: + (WebCore::EventHandler::dispatchMouseEvent): + +2010-04-28 Dan Bernstein <mitz@apple.com> + + Rubber-stamped by Maciej Stachowiak. + + Try to fix test failures seen on the Leopard build bot after r58467 + + * platform/graphics/SimpleFontData.cpp: + (WebCore::SimpleFontData::platformGlyphInit): Initialize m_zeroWidthSpaceGlyph before + calling widthForGlyph(), as the latter uses the former. + +2010-04-28 Martin Robinson <mrobinson@webkit.org> + + Reviewed by Gustavo Noronha. + + [GTK] Enable DOM clipboard and drag-and-drop access + https://bugs.webkit.org/show_bug.cgi?id=30623 + + Make ClipboardGtk a "live" DataTransfer object, able to modify + the clipboard when setData(...) is called. + + * platform/gtk/ClipboardGtk.cpp: + (WebCore::Editor::newGeneralClipboard): Pass the GtkClipboard into the factory method. + (WebCore::ClipboardGtk::ClipboardGtk): Create two separate constructors, one for DnD data and one for clipboard data. + (WebCore::dataObjectTypeFromHTMLClipboardType): Added. + (WebCore::ClipboardGtk::clearData): Clear the member DataObject, optionally write the clipboard. + (WebCore::ClipboardGtk::clearAllData): Ditto. + (WebCore::joinURIList): Added. + (WebCore::ClipboardGtk::getData): Get the data from the clipboard, if possible. + (WebCore::ClipboardGtk::setData): Write data to the DataObject and maybe the clipboard. + (WebCore::ClipboardGtk::types): Read the clipboard/DataObject to find applicable types. + (WebCore::ClipboardGtk::files): Read the clipboard/DataObject to find the files. + (WebCore::ClipboardGtk::writeURL): Write to the DataObject and maybe the clipboard. + (WebCore::ClipboardGtk::writeRange): Ditto. + (WebCore::ClipboardGtk::writePlainText): Ditto. + (WebCore::ClipboardGtk::hasData): Query the clipboard/DataObject. + * platform/gtk/ClipboardGtk.h: + (WebCore::ClipboardGtk::create): Added one factory for pasteboard-backed DataObjects and one for DnD-backed objects. + * platform/gtk/DataObjectGtk.cpp: + (WebCore::replaceNonBreakingSpaceWithSpace): Added this helper function to clean from plain text. + (WebCore::DataObjectGtk::markup): Actually return the range if it's set. + (WebCore::DataObjectGtk::setText): Clean from plain text. + (WebCore::DataObjectGtk::clearText): Added. + (WebCore::DataObjectGtk::clearMarkup): Added. + * platform/gtk/DataObjectGtk.h: + (WebCore::DataObjectGtk::clearURIList): Added. + (WebCore::DataObjectGtk::clearImage): Added. + * platform/gtk/PasteboardHelper.cpp: + (WebCore::PasteboardHelper::initializeTargetList): Added target ID's for URI list and Netscape URL targets. + (WebCore::urisToKURLVector): Added. + (WebCore::PasteboardHelper::getClipboardContents): Added. + (WebCore::PasteboardHelper::fillSelectionData): Added logic for URI lists and Netscape URLs. + (WebCore::PasteboardHelper::targetListForDataObject): Ditto. + * platform/gtk/PasteboardHelper.h: Added default argument to writeClipboardContents and new method. + +2010-04-28 Martin Robinson <mrobinson@webkit.org> + + Reviewed by Gustavo Noronha. + + [GTK] Enable DOM clipboard and drag-and-drop access + https://bugs.webkit.org/show_bug.cgi?id=30623 + + Use the length of the UTF-8 markup data in bytes when filling GtkSelectionData. + + No new tests, because pasteboard DataTransfer tests will be enabled + with the completion of the GTK+ DataTransfer object. + + * platform/gtk/PasteboardGtk.cpp: + (WebCore::clipboard_get_contents_cb): Use strlen here instead of g_utf8_strlen. + +2010-04-28 Dan Bernstein <mitz@apple.com> + + Reviewed by Adele Peterson. + + More of <rdar://problem/7855777> REGRESSION: Memory usage increase caused by storing glyph bounds in GlyphMetricsMap + https://bugs.webkit.org/show_bug.cgi?id=37936 + + Assigning zero width and empty bounds to the ZERO WIDTH SPACE glyph often allocates a width map + page and a bounds map page for the glyph, each of which pages contains 255 unused entries. Save + this space by not storing the zero width and empty bounds in the metrics maps. + + * platform/graphics/SimpleFontData.cpp: + (WebCore::SimpleFontData::SimpleFontData): Initialize m_zeroWidthSpaceGlyph. + (WebCore::SimpleFontData::platformGlyphInit): Set m_zeroWidthSpaceGlyph. Don’t create entries + for the ZERO WIDTH SPACE glyph in the width map and in the bounds map. + * platform/graphics/SimpleFontData.h: + (WebCore::SimpleFontData::boundsForGlyph): Return empty bounds for the ZERO WIDTH SPACE glyph + without consulting the bounds map. + (WebCore::SimpleFontData::widthForGlyph): Return zero for the ZERO WIDTH SPACE glyph without + consulting the width map. + +2010-04-28 Mark Rowe <mrowe@apple.com> + + Reviewed by Adele Peterson. + + <rdar://problem/7847573> Safari welcome page logs JavaScript exception during page load + + The Safari welcome page runs afoul of the same-origin restriction on access to stylesheet rules + that was added to address <https://bugs.webkit.org/show_bug.cgi?id=20527>. To work around this we're + adding a temporary site-specific quirk that relaxes this restriction for the particular cross-origin + access that occurs on the Safari welcome page. + + * css/CSSStyleSheet.cpp: + (WebCore::CSSStyleSheet::cssRules): + +2010-04-28 Mike Thole <mthole@apple.com> + + Reviewed by Mark Rowe. + + Add separate exports file for symbols dependent on WTF_USE_PROTECTION_SPACE_AUTH_CALLBACK. + + * DerivedSources.make: Updated for WebCore.ProtectionSpaceAuthCallback.exp. + * WebCore.ProtectionSpaceAuthCallback.exp: Added. + * WebCore.xcodeproj/project.pbxproj: + +2010-04-28 Evan Martin <evan@chromium.org> + + Reviewed by David Levin. + + [chromium] revert getFontDataForCharacters change in r58341 + https://bugs.webkit.org/show_bug.cgi?id=38288 + + It caused a performance regression. + + * platform/chromium/ChromiumBridge.h: + * platform/graphics/chromium/FontCacheLinux.cpp: + (WebCore::FontCache::getFontDataForCharacters): + +2010-04-28 Eric Seidel <eric@webkit.org> + + Unreviewed, rolling out r58441. + http://trac.webkit.org/changeset/58441 + https://bugs.webkit.org/show_bug.cgi?id=37618 + + Broke 3 test on Qt. + + * page/DragController.cpp: + (WebCore::DragController::tryDocumentDrag): + (WebCore::DragController::concludeEditDrag): + * page/DragController.h: + (WebCore::DragController::setDragInitiator): + (WebCore::DragController::dragInitiator): + (WebCore::DragController::documentUnderMouse): + +2010-04-28 Darin Adler <darin@apple.com> + + Reviewed by Dan Bernstein. + + Remove some obsolete scrolling code + https://bugs.webkit.org/show_bug.cgi?id=38293 + + * page/Chrome.cpp: + (WebCore::Chrome::scrollRectIntoView): Removed ScrollView* argument. + * page/Chrome.h: Made scrollRectIntoView non-virtual, and removed ScrollView* argument. + + * page/FrameView.cpp: Removed scrollRectIntoViewRecursively. + * page/FrameView.h: Removed scrollRectIntoViewRecursively and made + setScrollPosition non-virtual, since there is no class derived from + this class, and ScrollView's setScrollPosition is non-virtual. + + * platform/HostWindow.h: Removed scrollRectIntoView. + + * platform/ScrollView.cpp: + (WebCore::ScrollView::scrollRectIntoViewRecursively): Updated comment + since I was able to do most of the tasks listed here. + + * rendering/RenderLayer.cpp: + (WebCore::RenderLayer::scrollRectToVisible): Removed 0 passed for + ScrollView* argument to Chrome::scrollRectIntoView. + +2010-04-28 Mike Thole <mthole@apple.com> + + Reviewed by David Kilzer. + + Add canAuthenticateAgainstProtectionSpace() to frame loader so that a protection space + can be inspected before attempting to authenticate against it + https://bugs.webkit.org/show_bug.cgi?id=38271 + + * loader/EmptyClients.h: + (WebCore::EmptyFrameLoaderClient::canAuthenticateAgainstProtectionSpace): Added. + * loader/FrameLoader.cpp: + (WebCore::FrameLoader::canAuthenticateAgainstProtectionSpace): Added. + * loader/FrameLoader.h: + * loader/FrameLoaderClient.h: + * loader/ResourceLoader.cpp: + (WebCore::ResourceLoader::canAuthenticateAgainstProtectionSpace): Added. + * loader/ResourceLoader.h: + (WebCore::ResourceLoader::canAuthenticateAgainstProtectionSpace): Added. + * platform/network/ProtectionSpace.h: + (WebCore::): + * platform/network/ResourceHandle.h: + * platform/network/ResourceHandleClient.h: + (WebCore::ResourceHandleClient::canAuthenticateAgainstProtectionSpace): Added. + * platform/network/mac/AuthenticationMac.mm: + (WebCore::mac): + Add cases for case ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested and + ProtectionSpaceAuthenticationSchemeClientCertificateRequested. Guarded with the + #if USE(PROTECTION_SPACE_AUTH_CALLBACK) as the new NSURLProtectionSpace constants don't + exist prior to Mac OS X 10.6. + (WebCore::core): Ditto. + * platform/network/mac/ResourceHandleMac.mm: + (WebCore::ResourceHandle::canAuthenticateAgainstProtectionSpace): Added. + (-[WebCoreResourceHandleAsDelegate connection:canAuthenticateAgainstProtectionSpace:]): Added. + +2010-04-28 Abhishek Arya <inferno@chromium.org> + + Reviewed by Eric Seidel. + + Convert m_documentUnderMouse, m_dragInitiator to RefPtr. + Eliminated unused m_dragInitiator accessor to prevent dereferencing. + https://bugs.webkit.org/show_bug.cgi?id=37618 + + Test: editing/pasteboard/drag-drop-iframe-refresh-crash.html + + * page/DragController.cpp: + (WebCore::DragController::tryDocumentDrag): + (WebCore::DragController::concludeEditDrag): + * page/DragController.h: + (WebCore::DragController::draggingImageURL): + (WebCore::DragController::documentUnderMouse): + +2010-04-28 Dumitru Daniliuc <dumi@chromium.org> + + Unreviewed, fixing a build problem introduced by the previous patch. + + * storage/DatabaseSync.cpp: + (WebCore::DatabaseSync::openDatabaseSync): + +2010-04-23 Dumitru Daniliuc <dumi@chromium.org> + + Reviewed by Jeremy Orlow. + + Adding some required classes for the sync WebSQLDatabases API. + https://bugs.webkit.org/show_bug.cgi?id=34994 + + * GNUmakefile.am: + * WebCore.gypi: + * WebCore.pro: + * WebCore.vcproj/WebCore.vcproj: + * WebCore.xcodeproj/project.pbxproj: + * storage/DatabaseSync.cpp: Added. + (WebCore::DatabaseSync::databaseInfoTableName): + (WebCore::DatabaseSync::setIsAvailable): + (WebCore::DatabaseSync::isAvailable): + (WebCore::DatabaseSync::openDatabaseSync): + (WebCore::DatabaseSync::DatabaseSync): + (WebCore::DatabaseSync::~DatabaseSync): + (WebCore::DatabaseSync::version): + (WebCore::DatabaseSync::changeVersion): + (WebCore::DatabaseSync::transaction): + * storage/DatabaseSync.h: Added. + (WebCore::DatabaseSync::databaseDebugName): + * storage/SQLTransactionSync.cpp: Added. + (WebCore::SQLTransactionSync::create): + (WebCore::SQLTransactionSync::SQLTransactionSync): + (WebCore::SQLTransactionSync::~SQLTransactionSync): + (WebCore::SQLTransactionSync::executeSQL): + * storage/SQLTransactionSync.h: Added. + (WebCore::SQLTransactionSync::database): + (WebCore::SQLTransactionSync::isReadOnly): + * storage/SQLTransactionSyncCallback.h: Added. + (WebCore::SQLTransactionSyncCallback::~SQLTransactionSyncCallback): + +2010-04-28 İsmail Dönmez <ismail@namtrac.org> + + Reviewed by Simon Hausmann. + + Fix compilation with QT_NO_CURSOR defined. + + * platform/qt/QWebPageClient.h: + (QWebPageClient::resetCursor): + (QWebPageClient::setCursor): + +2010-04-28 Abhishek Arya <inferno@chromium.org> + + Reviewed by Alexey Proskuryakov. + + Added a check to make sure that resources from a different https origin are not cached. + https://bugs.webkit.org/show_bug.cgi?id=33456 + + Test: http/tests/appcache/different-https-origin-resource-main.html + + * loader/appcache/ManifestParser.cpp: + (WebCore::parseManifest): + +2010-04-28 Sam Weinig <sam@webkit.org> + + Reviewed by Mark Rowe. + + Only set -allowable_client WebKit2 for engineering builds on SnowLeopard + and later. + + * Configurations/WebCore.xcconfig: + +2010-04-28 Darin Adler <darin@apple.com> + + Reviewed by Adele Peterson. + + REGRESSION: Autoscroll does not work in Mail messages + https://bugs.webkit.org/show_bug.cgi?id=38267 + rdar://problem/7559799 + + Still haven't figured out a good way to test this with DumpRenderTree + or with Safari. Testing has to be done with Mail for now. + + The machinery to make autoscrolling work on Mac OS X when a WebView is embedded in another + view had gotten broken in multiple ways. For some reason, a combination of bugs made it + partly work until around r48064. This brings it back. + + There were three problems: + + 1) Code in EventHandler decided there was nothing to scroll, so didn't start + the autoscroll timer. + 2) The wrong rectangle was passed to Chrome::scrollRectIntoView. + 3) The Mac WebKit implementation of ChromeClient::scrollRectIntoView did incorrect + coordinate conversion. + + I verified that none of these have any effect on regression tests, or behavior in + web browsers, or behavior on platforms other than Mac. + + * page/EventHandler.cpp: + (WebCore::canAutoscroll): Added. Returns true for boxes that can scroll directly + and for the top level box of the top frame. + (WebCore::EventHandler::handleMouseDraggedEvent): Use canAutoscroll. + (WebCore::EventHandler::updateAutoscrollRenderer): Ditto. + + * page/FrameView.cpp: + (WebCore::FrameView::scrollToAnchor): Fixed comment. + + * platform/ScrollView.cpp: + (WebCore::ScrollView::scrollRectIntoViewRecursively): Put ASSERT_NOT_REACHED into this + now-unused function along with some comments about removing some obsolete code. + + * rendering/RenderLayer.cpp: + (WebCore::RenderLayer::scrollRectToVisible): Removed call to scrollRectIntoViewRecursively + since from the WebKit point of view this is the topmost scroll view anyway. Instead call + setScrollPosition. Moved the code to call Chrome::scrollRectIntoView here since it needs + to use a different rectangle anyway. + +2010-04-21 Ojan Vafai <ojan@chromium.org> + + Reviewed by Adele Peterson. + + http://trac.webkit.org/changeset/57215 caused perf/memory regressions + https://bugs.webkit.org/show_bug.cgi?id=37292 + + #if out the canUseGlyphCache Changes from r57215 as they caused a + 8% perf regression on Chromium's international page load tests so that + the perf regression can be fixed properly without being left in the tree. + + * platform/graphics/FontFastPath.cpp: + (WebCore::Font::canUseGlyphCache): + +2010-04-28 Beth Dakin <bdakin@apple.com> + + Reviewed by Darin Adler. + + Fix for <rdar://problem/7474349> + + Add a synchronous display mechanism for WKCACFLayerRenderer. + + * platform/graphics/win/WKCACFLayerRenderer.cpp: + (WebCore::WKCACFLayerRenderer::setRootContentsAndDisplay): This is + just like setRootContents(), but it calls paint() instead of + renderSoon(). + * platform/graphics/win/WKCACFLayerRenderer.h: + +2010-04-28 Dmitry Titov <dimich@chromium.org> + + Reviewed by Geoffrey Garen. + + REGRESSION: fast/workers/wrapper-map-gc.html crashes on Snow Leopard Release Bot + https://bugs.webkit.org/show_bug.cgi?id=37554 + + The flaky fast/workers/wrapper-map-gc.html will stop being flaky. + + * bindings/js/JSEventListener.cpp: + (WebCore::JSEventListener::handleEvent): + check if JS execution was terminated, as in cases of Worker.terminate() or WorkerGlobalScope.close(). + * bindings/js/JSWorkerContextBase.cpp: + (WebCore::toJS): ASSERT the value of workerContextWrapper, it should never be 0. + * bindings/js/WorkerScriptController.h: + (WebCore::WorkerScriptController::workerContextWrapper): remove returning 0 if JS execution was forbidden. + (WebCore::WorkerScriptController::isExecutionForbidden): + * bindings/v8/WorkerScriptController.h: + (WebCore::WorkerScriptController::isExecutionForbidden): + + Add ScriptExecutionContext::isJSExecutionTerminated(), it is always 'false' for Document + and 'true' for WorkerContext when script is terminated. + * dom/ScriptExecutionContext.h: + * dom/Document.h: + (WebCore::Document::isJSExecutionTerminated): + * workers/WorkerContext.cpp: + (WebCore::WorkerContext::isJSExecutionTerminated): + * workers/WorkerContext.h: + +2010-04-28 Ilya Tikhonovsky <loislo@chromium.org> + + Reviewed by Yury Semikhatsky. + + WebInspector: Multiple Main Resource Content Loaded marks appear in Resource panel. + https://bugs.webkit.org/show_bug.cgi?id=38270 + + * inspector/front-end/ResourcesPanel.js: + (WebInspector.ResourcesPanel.prototype.updateGraphDividersIfNeeded): + +2010-04-28 Ilya Tikhonovsky <loislo@chromium.org> + + Reviewed by Yury Semikhatsky. + + WebInspector: Timeline: We can have precise urls in the EvaluateScript records. + https://bugs.webkit.org/show_bug.cgi?id=38264 + + * inspector/front-end/TimelinePanel.js: + (WebInspector.TimelinePanel.FormattedRecord.prototype._generatePopupContent): + (WebInspector.TimelinePanel.FormattedRecord.prototype._getRecordDetails): + +2010-04-28 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: Linkify node and function in the event listeners panel. + + https://bugs.webkit.org/show_bug.cgi?id=38251 + + * bindings/js/ScriptEventListener.cpp: + (WebCore::eventListenerHandlerBody): + (WebCore::eventListenerHandlerLocation): + * bindings/js/ScriptEventListener.h: + * bindings/v8/ScriptEventListener.cpp: + (WebCore::eventListenerHandlerBody): + (WebCore::eventListenerHandlerLocation): + * bindings/v8/ScriptEventListener.h: + * inspector/InspectorDOMAgent.cpp: + (WebCore::InspectorDOMAgent::buildObjectForEventListener): + * inspector/front-end/ElementsPanel.js: + (WebInspector.ElementsPanel.prototype.linkifyNodeReference): + (WebInspector.ElementsPanel.prototype.linkifyNodeReference.preventDefault): + * inspector/front-end/EventListenersSidebarPane.js: + (WebInspector.EventListenersSidebarPane.prototype.update.callback): + (WebInspector.EventListenersSidebarPane.prototype.update): + (): + * inspector/front-end/StylesSidebarPane.js: + (WebInspector.StylesSidebarPane.prototype._rebuildSectionsForStyleRules): + * inspector/front-end/inspector.css: + (.node-link): + +2010-04-28 Julien Chaffraix <jchaffraix@webkit.org> + + Reviewed by Alexey Proskuryakov. + + [XHR] Cross-Origin synchronous request with credential raises NETWORK_ERR + https://bugs.webkit.org/show_bug.cgi?id=37781 + <rdar://problem/7905150> + + Tests: http/tests/xmlhttprequest/access-control-preflight-credential-async.html + http/tests/xmlhttprequest/access-control-preflight-credential-sync.html + + Rolling the patch in as I could not reproduce Qt results locally. + + * loader/DocumentThreadableLoader.cpp: + (WebCore::DocumentThreadableLoader::DocumentThreadableLoader): Now we remove the + credential from the request here to avoid forgetting to do so in the different code path. + (WebCore::DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest): Just add the + "Origin" header. + (WebCore::DocumentThreadableLoader::loadRequest): Check here the the credential have + been removed so that we don't leak them. Also tweaked a comment to make it clear that + the URL check has issue when credential is involved. + +2010-04-28 Noam Rosenthal <noam.rosenthal@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] GraphicsLayer: preserves-3d and backface visibility + https://bugs.webkit.org/show_bug.cgi?id=35312 + + Implement preserves-3d by maintaining the 3D transformation heirarchy inside GraphicsLayerQt, and extrapolating + the relative QTransform. When the extrapolation fails (un-invertible matrix) we ignore the transformation change. + + WebKitSite/blog-files/3d-transforms test now work with Qt. + + * platform/graphics/qt/GraphicsLayerQt.cpp: + (WebCore::GraphicsLayerQtImpl::updateTransform): + (WebCore::GraphicsLayerQtImpl::opaqueArea): + (WebCore::GraphicsLayerQtImpl::boundingRect): + (WebCore::GraphicsLayerQtImpl::paint): + (WebCore::GraphicsLayerQtImpl::flushChanges): + +2010-04-28 Ilya Tikhonovsky <loislo@chromium.org> + + Reviewed by Yury Semikhatsky. + + Web Inspector: View frame selector for Timeline overview panel is redesigned a bit. + Now it is possible to adjust view frame by resizer bars and by click-n-drag in overview pane. + https://bugs.webkit.org/show_bug.cgi?id=38251 + + * inspector/front-end/TimelineOverviewPane.js: + (WebInspector.TimelineOverviewPane): + (WebInspector.TimelineOverviewPane.prototype.reset): + (WebInspector.TimelineOverviewPane.prototype._dragWindow): + (WebInspector.TimelineOverviewPane.prototype._windowSelectorDragging): + (WebInspector.TimelineOverviewPane.prototype._endWindowSelectorDragging): + (WebInspector.TimelineOverviewPane.prototype._resizeWindowLeft): + (WebInspector.TimelineOverviewPane.prototype._resizeWindowRight): + (WebInspector.TimelineOverviewPane.prototype._setWindowPosition): + (WebInspector.TimelinePanel.WindowSelector): + (WebInspector.TimelinePanel.WindowSelector.prototype._createSelectorElement): + (WebInspector.TimelinePanel.WindowSelector.prototype._close): + (WebInspector.TimelinePanel.WindowSelector.prototype._updatePosition): + * inspector/front-end/inspector.css: + (#timeline-overview-grid): + (.timeline-window-selector): + (#timeline-overview-window): + (.timeline-overview-dividers-background): + (.timeline-overview-window-rulers): + (.timeline-window-resizer): + +2010-04-28 Marcus Bulach <bulach@chromium.org> + + Reviewed by Jeremy Orlow. + + Reverts 58340 (https://bugs.webkit.org/show_bug.cgi?id=38158) due to regression on fast/text/international/khmer-selection.html + https://bugs.webkit.org/show_bug.cgi?id=38254 + + * platform/graphics/chromium/FontLinux.cpp: + (WebCore::adjustTextRenderMode): + (WebCore::TextRunWalker::getTextRun): + (WebCore::TextRunWalker::getNormalizedTextRun): + (WebCore::TextRunWalker::setGlyphXPositions): + (WebCore::glyphIndexForXPositionInScriptRun): + (WebCore::Font::offsetForPositionForComplexText): + (WebCore::Font::selectionRectForComplexText): + * platform/graphics/chromium/FontPlatformDataLinux.cpp: + (WebCore::FontPlatformData::setupPaint): + * platform/graphics/chromium/HarfbuzzSkia.cpp: + (WebCore::getOutlinePoint): + * platform/graphics/skia/GraphicsContext3DSkia.cpp: + (WebCore::GraphicsContext3D::getImageData): + * platform/graphics/skia/GraphicsContextSkia.cpp: + (WebCore::isCoordinateSkiaSafe): + (WebCore::GraphicsContext::fillRect): + (WebCore::GraphicsContext::strokePath): + (WebCore::GraphicsContext::strokeRect): + +2010-04-28 Andrey Kosyakov <caseq@chromium.org> + + Reviewed by Yury Semikhatsky. + + Log error message to inspector console if a resource fails to load. + Disable checking of mime-type consistency for failed resources. + https://bugs.webkit.org/show_bug.cgi?id=37215 + + Test: http/tests/inspector/console-resource-errors.html + + * inspector/InspectorController.cpp: + (WebCore::InspectorController::didReceiveResponse): + (WebCore::InspectorController::didFailLoading): + * inspector/front-end/Resource.js: + (WebInspector.Resource.prototype._mimeTypeIsConsistentWithType): + * inspector/front-end/ResourcesPanel.js: + (WebInspector.ResourcesPanel.prototype.recreateViewForResourceIfNeeded): + +2010-04-28 Yury Semikhatsky <yurys@chromium.org> + + Reviewed by Pavel Feldman. + + Support pause on exceptions in v8 implementation of ScriptDebugServer. + + https://bugs.webkit.org/show_bug.cgi?id=38205 + + * bindings/v8/ScriptDebugServer.cpp: + (WebCore::ScriptDebugServer::addListener): + (WebCore::ScriptDebugServer::pauseOnExceptionsState): + (WebCore::ScriptDebugServer::setPauseOnExceptionsState): + (WebCore::ScriptDebugServer::currentCallFrame): + (WebCore::ScriptDebugServer::handleV8DebugMessage): + (WebCore::ScriptDebugServer::dispatchDidParseSource): + * bindings/v8/ScriptDebugServer.h: + +2010-04-28 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r58313. + http://trac.webkit.org/changeset/58313 + https://bugs.webkit.org/show_bug.cgi?id=38253 + + Regression evident in pixel tests: the search icon is always + clipped at the bottom. (Requested by jorlow on #webkit). + + * rendering/RenderTextControl.cpp: + (WebCore::RenderTextControl::controlClipRect): + * rendering/RenderTextControl.h: + (WebCore::RenderTextControl::hasControlClip): + * rendering/RenderTextControlSingleLine.cpp: + (WebCore::RenderTextControlSingleLine::paint): + * rendering/RenderTextControlSingleLine.h: + +2010-04-28 Justin McPherson <justin.mcpherson@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Fix detection of Qt 4.7's multimedia libraries + + QtMultimedia has been split into an additional media services library, which + we're using. mediaservices depends on multimedia. + + * WebCore.pro: + +2010-04-28 Shinichiro Hamaji <hamaji@chromium.org> + + Unreviewed attempt to fix the chromium build. + + Add layoutTestController.setPrinting() + https://bugs.webkit.org/show_bug.cgi?id=37203 + + * rendering/RenderTreeAsText.cpp: + +2010-04-27 Shinichiro Hamaji <hamaji@chromium.org> + + Reviewed by Darin Adler and Eric Seidel. + + Add layoutTestController.setPrinting() + https://bugs.webkit.org/show_bug.cgi?id=37203 + + Added RenderAsTextPrintingMode as a behavior of externalRepresentation. + + Now ~PrintContext() calls end() automatically. + + * page/PrintContext.cpp: + (WebCore::PrintContext::~PrintContext): + * rendering/RenderTreeAsText.cpp: + (WebCore::externalRepresentation): + * rendering/RenderTreeAsText.h: + (WebCore::): + +2010-04-27 Yuzo Fujishima <yuzo@google.com> + + Reviewed by Eric Seidel. + + Enhance CSS parser for Paged Media (Iteration 4) + Implement page property parsing as specified at http://dev.w3.org/csswg/css3-page/#using-named-pages. + https://bugs.webkit.org/show_bug.cgi?id=35853 + + * css/CSSParser.cpp: + (WebCore::CSSParser::parseValue): + (WebCore::CSSParser::parsePage): + * css/CSSParser.h: + +2010-04-27 Yuzo Fujishima <yuzo@google.com> + + Reviewed by Dimitri Glazkov. + + Enhance CSS parser for Paged Media (Iteration 3) + Implement size parameter parsing for Paged Media. + https://bugs.webkit.org/show_bug.cgi?id=35851 + + I believe size property hasn't been used so far because (1) it hasn't been properly parsed and + (2) a comment in CSSComputedStyleDeclaration::getPropertyCSSValue says so. + Changing the way of parsing it should not cause any regressions -- no existing tests fail because of this change. + + * css/CSSParser.cpp: + (WebCore::CSSParser::parseValue): + (WebCore::CSSParser::parseSize): + (WebCore::CSSParser::parseSizeParameter): + * css/CSSParser.h: + (WebCore::CSSParser::): + * css/CSSValueKeywords.in: + +2010-04-27 Yuzo Fujishima <yuzo@google.com> + + Reviewed by Eric Seidel. + + Enhance CSS parser for Paged Media (Iteration 2) + Parse and hold paged media rules in CSSStyleSelector. + + https://bugs.webkit.org/show_bug.cgi?id=35782 + + Test: printing/page-rule-css-text.html + + * css/CSSGrammar.y: + * css/CSSPageRule.cpp: + (WebCore::CSSPageRule::CSSPageRule): + (WebCore::CSSPageRule::selectorText): + * css/CSSPageRule.h: + (WebCore::CSSPageRule::create): + (WebCore::CSSPageRule::isPageRule): + * css/CSSParser.cpp: + (WebCore::CSSParser::createPageRule): + * css/CSSStyleRule.h: + * css/CSSStyleSelector.cpp: + (WebCore::CSSRuleSet::getPageRules): + (WebCore::CSSRuleSet::CSSRuleSet): + (WebCore::CSSRuleSet::~CSSRuleSet): + (WebCore::CSSRuleSet::addPageRule): + (WebCore::CSSRuleSet::addRulesFromSheet): + * css/CSSStyleSelector.h: + * css/StyleBase.h: + (WebCore::StyleBase::isPageRule): + +2010-04-27 Daniel Bates <dbates@rim.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=37686 + + Fixes an issue where the canvas method strokeRect will stroke a + rectangle whose dimensions are 0 when lineWidth > 1. + + As per the definition of strokeRect in the HTML Canvas 2D Context + spec. <http://www.w3.org/TR/2dcontext/#dom-context-2d-strokerect>, + this method should have no effect when both the height and width + are zero. + + Tests: fast/canvas/canvas-clearRect.html + fast/canvas/canvas-fillRect.html + + * html/canvas/CanvasRenderingContext2D.cpp: + (WebCore::validateRectForCanvas): Return false if height, width == 0. + +2010-04-27 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Remove obsolete custom bindings file + https://bugs.webkit.org/show_bug.cgi?id=38223 + + We don't need these files anymore because they are empty. + + * Android.jscbindings.mk: + * GNUmakefile.am: + * WebCore.pro: + * WebCore.vcproj/WebCore.vcproj: + * WebCore.xcodeproj/project.pbxproj: + * bindings/js/JSAbstractWorkerCustom.cpp: Removed. + * bindings/js/JSBindingsAllInOne.cpp: + * bindings/js/JSDocumentFragmentCustom.cpp: Removed. + * bindings/js/JSEventSourceCustom.cpp: Removed. + +2010-04-27 Daniel Cheng <dcheng@chromium.org> + + Reviewed by Jian Li. + + [Chromium] Filter out URLs with a file scheme from text/uri-list when dragging. + https://bugs.webkit.org/show_bug.cgi?id=38227 + + Unfortunately, the simple fix of not populating the drag data with file URLs doesn't work + since the default drop handling uses the drag data URL to navigate to dropped files/URLs. + For now, we hack around the problem in the Chromium platform, but the proper long term + solution is to change DragController::performDrag to check dragData::asFilenames(). + + No new tests. + + * platform/chromium/ClipboardChromium.cpp: + (WebCore::ClipboardChromium::getData): + (WebCore::ClipboardChromium::types): + +2010-04-27 Simon Fraser <simon.fraser@apple.com> + + Reviewed by the inimitable Dan Bernstein. + + SVG as background image renders incorrectly after zooming + https://bugs.webkit.org/show_bug.cgi?id=38215 + + When doing a partial redraw of an SVGImage used as a CSS background + image, we're limited to drawing the entire Frame, clipped to the dirty rect. + Because of this, we need to fix up the CTM so that the origin is at the + top left of the unclipped image, rather than the top left of the + portion being redrawn. + + Test: fast/images/svg-background-partial-redraw.html + + * svg/graphics/SVGImage.cpp: + (WebCore::SVGImage::draw): + +2010-04-27 Yuzo Fujishima <yuzo@google.com> + + Reviewed by David Hyatt. + + Retry of: Enhance CSS parser for Paged Media (Iteration 1) + + In this change, the grammar is extended and skeletal methods for creating page rules and margin at-rules are defined. + The contents of the methods should be implemented by other changes. + + https://bugs.webkit.org/show_bug.cgi?id=35329 + + Test: fast/css/parsing-page-rule.html + + * css/CSSGrammar.y: + * css/CSSParser.cpp: + (WebCore::CSSParser::CSSParser): + (WebCore::CSSParser::clearProperties): + (WebCore::CSSParser::createPageRule): + (WebCore::CSSParser::createMarginAtRule): + (WebCore::CSSParser::startDeclarationsForMarginBox): + (WebCore::CSSParser::endDeclarationsForMarginBox): + * css/CSSParser.h: + * css/CSSSelector.cpp: + (WebCore::CSSSelector::pseudoId): + (WebCore::nameToPseudoTypeMap): + (WebCore::CSSSelector::extractPseudoType): + * css/CSSSelector.h: + (WebCore::CSSSelector::): + * css/tokenizer.flex: + +2010-04-27 Julien Chaffraix <jchaffraix@webkit.org> + + Unreviewed, rolling out my changes as it rendered the Qt bot unreliable. + + * loader/DocumentThreadableLoader.cpp: + (WebCore::DocumentThreadableLoader::DocumentThreadableLoader): + (WebCore::DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest): + (WebCore::DocumentThreadableLoader::loadRequest): + +2010-04-27 Julien Chaffraix <jchaffraix@webkit.org> + + Reviewed by Alexey Proskuryakov. + + [XHR] Cross-Origin synchronous request with credential raises NETWORK_ERR + https://bugs.webkit.org/show_bug.cgi?id=37781 + <rdar://problem/7905150> + + Tests: http/tests/xmlhttprequest/access-control-preflight-credential-async.html + http/tests/xmlhttprequest/access-control-preflight-credential-sync.html + + * loader/DocumentThreadableLoader.cpp: + (WebCore::DocumentThreadableLoader::DocumentThreadableLoader): Now we remove the + credential from the request here to avoid forgetting to do so in the different code path. + (WebCore::DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest): Just add the + "Origin" header. + (WebCore::DocumentThreadableLoader::loadRequest): Check here the the credential have + been removed so that we don't leak them. Also tweaked a comment to make it clear that + the URL check has issue when credential is involved. + +2010-04-27 Sam Weinig <sam@webkit.org> + + Reviewed by Maciej Stachowiak. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38238 + Allow both WebKit and WebKit2 to link to the same WebCore.framework + + * Configurations/WebCore.xcconfig: Use -allowable_client WebKit2 to add + WebKit2 to the list of frameworks that can link directly to WebCore. It + is not necessary for it to be an umbrella since we don't need to reexport + any symbols. + +2010-04-27 Dumitru Daniliuc <dumi@chromium.org> + + Reviewed by David Levin. + + Turn on AUTO_VACUUM = INCREMENTAL for all HTML5 databases. + https://bugs.webkit.org/show_bug.cgi?id=38191 + + Vacuum all databases when the number of free pages is at least 10% + of the number of total pages. Also, add a guard against a bug that + was fixed in SQLite only starting with version 3.6.16. + + * platform/sql/SQLiteDatabase.cpp: + (WebCore::SQLiteDatabase::maximumSize): + (WebCore::SQLiteDatabase::freeSpaceSize): + (WebCore::SQLiteDatabase::totalSize): + (WebCore::SQLiteDatabase::runIncrementalVacuumCommand): + (WebCore::SQLiteDatabase::turnOnIncrementalAutoVacuum): + * platform/sql/SQLiteDatabase.h: + (WebCore::SQLiteDatabase::): + * platform/sql/SQLiteStatement.cpp: + (WebCore::SQLiteStatement::prepare): + (WebCore::SQLiteStatement::step): + * storage/Database.cpp: + (WebCore::Database::performOpenAndVerify): + (WebCore::Database::incrementalVacuumIfNeeded): + * storage/Database.h: + * storage/SQLTransaction.cpp: + (WebCore::SQLTransaction::postflightAndCommit): + +2010-04-27 Garret Kelly <gdk@chromium.org> + + Reviewed by Darin Fisher. + + Turn all of the touch event handlers into RuntimeEnabledFeatures, and + modify the createEvent methond on Document so that it won't create a + TouchEvent if the feature is disabled. + https://bugs.webkit.org/show_bug.cgi?id=37485 + + * bindings/generic/RuntimeEnabledFeatures.cpp: + * bindings/generic/RuntimeEnabledFeatures.h: + (WebCore::RuntimeEnabledFeatures::touchEnabled): + (WebCore::RuntimeEnabledFeatures::setTouchEnabled): + (WebCore::RuntimeEnabledFeatures::ontouchstartEnabled): + (WebCore::RuntimeEnabledFeatures::ontouchmoveEnabled): + (WebCore::RuntimeEnabledFeatures::ontouchendEnabled): + (WebCore::RuntimeEnabledFeatures::ontouchcancelEnabled): + * dom/Document.cpp: + (WebCore::Document::createEvent): + * dom/Document.idl: + * dom/Element.idl: + * page/DOMWindow.idl: + +2010-04-27 Jens Alfke <snej@chromium.org> + + Reviewed by Darin Fisher. + + [Chromium] Add some notifications and an accessor to WebKit API + https://bugs.webkit.org/show_bug.cgi?id=37625 + + * dom/Node.cpp: + (WebCore::Node::hasNonEmptyBoundingBox): New method. + * dom/Node.h: + * html/HTMLAnchorElement.cpp: + (WebCore::HTMLAnchorElement::isKeyboardFocusable): Moved part of method into new Node method + +2010-04-27 Jochen Eisinger <jochen@chromium.org> + + Reviewed by Shinichiro Hamaji. + + Fix gyp build on Mac OS X with enable_svg=0. + https://bugs.webkit.org/show_bug.cgi?id=38192 + + * WebCore.gyp/WebCore.gyp: Only generate SVG symbols if enable_svg!=0. + * css/CSSComputedStyleDeclaration.cpp: + (WebCore::CSSComputedStyleDeclaration::getPropertyCSSValue): Add missing unimplemented CSS properties to switch statement. + +2010-04-27 Kinuko Yasuda <kinuko@chromium.org> + + Reviewed by Jian Li. + + [V8] Handle OR ('|') conditional in action_derivedsourcesallinone.py + https://bugs.webkit.org/show_bug.cgi?id=38207 + + No new tests. + + * WebCore.gyp/scripts/action_derivedsourcesallinone.py: + +2010-04-27 François Sausset <sausset@gmail.com> + + Reviewed by Kenneth Rohde Christiansen. + + Implementation of the MathML mroot & msqrt elements. + https://bugs.webkit.org/show_bug.cgi?id=37044 + + Test: mathml/presentation/roots.xhtml + + * WebCore.xcodeproj/project.pbxproj: + * css/mathml.css: + (mroot): + (mroot > * + *): + (mroot > * + mrow, mroot > * + mfenced): + * mathml/MathMLInlineContainerElement.cpp: + (WebCore::MathMLInlineContainerElement::createRenderer): + * mathml/RenderMathMLRoot.cpp: Added. + (WebCore::RenderMathMLRoot::RenderMathMLRoot): + (WebCore::RenderMathMLRoot::addChild): + (WebCore::RenderMathMLRoot::paint): + (WebCore::RenderMathMLRoot::layout): + * mathml/RenderMathMLRoot.h: Added. + * mathml/RenderMathMLSquareRoot.cpp: Added. + (WebCore::RenderMathMLSquareRoot::RenderMathMLSquareRoot): + (WebCore::RenderMathMLSquareRoot::paint): + (WebCore::RenderMathMLSquareRoot::layout): + * mathml/RenderMathMLSquareRoot.h: Added. + +2010-04-27 Darin Adler <darin@apple.com> + + Reviewed by Maciej Stachowiak. + + I noticed an unused forwarding header. + + * ForwardingHeaders/runtime/PropertyMap.h: Removed. + +2010-04-27 James Robinson <jamesr@chromium.org> + + Reviewed by Adam Barth. + + Fix gcc 4.4.1 warnings on Linux in the chromium V8 bindings code. + https://bugs.webkit.org/show_bug.cgi?id=38153 + + * bindings/scripts/CodeGeneratorV8.pm: + * bindings/v8/V8Proxy.cpp: + (WebCore::V8Proxy::callFunction): + +2010-04-27 Eric Seidel <eric@webkit.org> + + Unreviewed, rolling out r58318. + http://trac.webkit.org/changeset/58318 + https://bugs.webkit.org/show_bug.cgi?id=37215 + + Broke test on Tiger. Might just need updated results, + unclear. + + * inspector/InspectorController.cpp: + (WebCore::InspectorController::didReceiveResponse): + (WebCore::InspectorController::didFailLoading): + * inspector/front-end/Resource.js: + (WebInspector.Resource.prototype._mimeTypeIsConsistentWithType): + * inspector/front-end/ResourcesPanel.js: + (WebInspector.ResourcesPanel.prototype.recreateViewForResourceIfNeeded): + +2010-04-27 Evan Martin <evan@chromium.org> + + Reviewed by David Levin. + + [chromium] bold bengali text not rendered properly on Linux + https://bugs.webkit.org/show_bug.cgi?id=37904 + + We must let Skia do font fallback, rather than picking a font name + then handing that to Skia. For example, if we have Bengali text and + choose FreeSans + fake bold, and then later reuse the name, Skia will + helpfully use FreeSansBold (which doesn't cover Bengali). + + Test: fast/text/international/bold-bengali.html + + * platform/graphics/chromium/FontCacheLinux.cpp: + (WebCore::FontCache::getFontDataForCharacters): + +2010-04-27 James Robinson <jamesr@chromium.org> + + Reviewed by Darin Adler. + + Fix warnings emitted by gcc 4.4.1 on linux in chromium-specific platform graphics files. + https://bugs.webkit.org/show_bug.cgi?id=38158 + + Most of the issues are signed/unsigned mismatches, but there are a few unusued variables + and functions mixed in. + + * platform/graphics/chromium/FontLinux.cpp: + (WebCore::adjustTextRenderMode): + (WebCore::TextRunWalker::getTextRun): + (WebCore::TextRunWalker::getNormalizedTextRun): + (WebCore::TextRunWalker::setGlyphXPositions): + (WebCore::glyphIndexForXPositionInScriptRun): + (WebCore::Font::offsetForPositionForComplexText): + (WebCore::Font::selectionRectForComplexText): + * platform/graphics/chromium/FontPlatformDataLinux.cpp: + (WebCore::FontPlatformData::setupPaint): + * platform/graphics/chromium/HarfbuzzSkia.cpp: + (WebCore::getOutlinePoint): + * platform/graphics/skia/GraphicsContext3DSkia.cpp: + (WebCore::GraphicsContext3D::getImageData): + * platform/graphics/skia/GraphicsContextSkia.cpp: + (WebCore::isCoordinateSkiaSafe): + (WebCore::GraphicsContext::fillRect): + (WebCore::GraphicsContext::strokePath): + (WebCore::GraphicsContext::strokeRect): + +2010-04-27 Jian Li <jianli@chromium.org> + + Reviewed by Darin Adler. + + Sending a package file using FormData crashes WebKit on Mac. + https://bugs.webkit.org/show_bug.cgi?id=37882 + + Can't add a layout test because DRT does not support generating the file name. + + * loader/FrameLoader.cpp: + (WebCore::FrameLoader::submitForm): + (WebCore::FrameLoader::navigateToDifferentDocument): + * platform/network/FormData.cpp: + (WebCore::FormData::appendDOMFormData): + * platform/network/FormData.h: + * xml/XMLHttpRequest.cpp: + (WebCore::XMLHttpRequest::send): + +2010-04-27 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Remove custom NodeIterator bindings + https://bugs.webkit.org/show_bug.cgi?id=38188 + + Another example of CallWith=ScriptState. This case shows us the right + way to handle the interaction with exception codes. + + In my previous patch, I put the exception code handling after the + ScriptState exception handling. It turns out this was a mistake + (although a harmless one at the time because no IDL caused us to + generate that code). Now that we're generating both kinds of exception + handling, we need to generate them in the right order. + + * WebCore.gypi: + * bindings/js/JSNodeIteratorCustom.cpp: + * bindings/scripts/CodeGeneratorJS.pm: + * bindings/scripts/CodeGeneratorV8.pm: + * bindings/scripts/test/GObject/WebKitDOMTestObj.cpp: + (webkit_dom_test_obj_with_script_state_void_exception): + (webkit_dom_test_obj_with_script_state_obj_exception): + * bindings/scripts/test/GObject/WebKitDOMTestObj.h: + * bindings/scripts/test/JS/JSTestObj.cpp: + (WebCore::): + (WebCore::jsTestObjPrototypeFunctionWithScriptStateVoidException): + (WebCore::jsTestObjPrototypeFunctionWithScriptStateObjException): + * bindings/scripts/test/JS/JSTestObj.h: + * bindings/scripts/test/ObjC/DOMTestObj.h: + * bindings/scripts/test/ObjC/DOMTestObj.mm: + (-[DOMTestObj withScriptStateVoidException]): + (-[DOMTestObj withScriptStateObjException]): + * bindings/scripts/test/TestObj.idl: + * bindings/scripts/test/V8/V8TestObj.cpp: + (WebCore::TestObjInternal::withScriptStateVoidCallback): + (WebCore::TestObjInternal::withScriptStateObjCallback): + (WebCore::TestObjInternal::withScriptStateVoidExceptionCallback): + (WebCore::TestObjInternal::withScriptStateObjExceptionCallback): + (WebCore::): + * bindings/v8/custom/V8NodeIteratorCustom.cpp: Removed. + * dom/NodeIterator.idl: + +2010-04-27 Adam Barth <abarth@webkit.org> + + Reviewed by Darin Adler. + + Remove copy/paste addEventListener "custom" bindings via code generation + https://bugs.webkit.org/show_bug.cgi?id=38210 + + It's somewhat lame to special case addEventListener and + removeEventListener in the code generator, but it saves a large amount + of boilerplate "custom" bindings code. + + Idea shamelessly stolen from the V8 code generator. + + This patch points to some good refactoring opportunities in + CodeGeneratorJS.pm, but I'm going to hold off on those for a future + patch. By generating test coverage for the code generator, we make + these future refactorings easier. + + * bindings/js/JSAbstractWorkerCustom.cpp: + * bindings/js/JSDOMApplicationCacheCustom.cpp: + * bindings/js/JSDesktopNotificationsCustom.cpp: + * bindings/js/JSEventSourceCustom.cpp: + * bindings/js/JSMessagePortCustom.cpp: + * bindings/js/JSNodeCustom.cpp: + * bindings/js/JSSVGElementInstanceCustom.cpp: + * bindings/js/JSWebSocketCustom.cpp: + * bindings/js/JSWorkerContextCustom.cpp: + * bindings/js/JSXMLHttpRequestCustom.cpp: + * bindings/js/JSXMLHttpRequestUploadCustom.cpp: + * bindings/scripts/CodeGeneratorJS.pm: + * bindings/scripts/test/GObject/WebKitDOMTestObj.cpp: + * bindings/scripts/test/GObject/WebKitDOMTestObj.h: + * bindings/scripts/test/JS/JSTestObj.cpp: + (WebCore::): + (WebCore::jsTestObjPrototypeFunctionAddEventListener): + (WebCore::jsTestObjPrototypeFunctionRemoveEventListener): + * bindings/scripts/test/JS/JSTestObj.h: + * bindings/scripts/test/ObjC/DOMTestObj.h: + * bindings/scripts/test/ObjC/DOMTestObj.mm: + (-[DOMTestObj addEventListener:listener:useCapture:]): + (-[DOMTestObj removeEventListener:listener:useCapture:]): + * bindings/scripts/test/TestObj.idl: + * bindings/scripts/test/V8/V8TestObj.cpp: + (WebCore::TestObjInternal::addEventListenerCallback): + (WebCore::TestObjInternal::removeEventListenerCallback): + (WebCore::): + * dom/MessagePort.idl: + * dom/Node.idl: + * loader/appcache/DOMApplicationCache.idl: + * notifications/Notification.idl: + * page/EventSource.idl: + * svg/SVGElementInstance.idl: + * websockets/WebSocket.idl: + * workers/AbstractWorker.idl: + * workers/WorkerContext.idl: + * xml/XMLHttpRequest.idl: + * xml/XMLHttpRequestUpload.idl: + +2010-04-27 Sam Weinig <sam@webkit.org> + + Rubber-stamped by Beth Dakin. + + Remove now unnecessary EXPERIMENTAL_SINGLE_VIEW_MODE #define. + + * page/EventHandler.cpp: + (WebCore::EventHandler::EventHandler): + (WebCore::EventHandler::clearDragState): + * page/EventHandler.h: + * page/mac/DragControllerMac.mm: + * page/mac/EventHandlerMac.mm: + * platform/mac/PopupMenuMac.mm: + +2010-04-27 Ben Murdoch <benm@google.com> + + Reviewed by Simon Hausmann. + + The TouchStationary state of WebCore::PlatformTouchPoint is not handled inside the touch event handler. + https://bugs.webkit.org/show_bug.cgi?id=37609 + + No new tests required, only updating documentation. + + * page/EventHandler.cpp: + (WebCore::EventHandler::handleTouchEvent): Improve the documentation for handling + the TouchStationary state as a result of discussions in bug 37609. + +2010-04-27 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Darin Adler, Maciej Stachowiak. + + REGRESSION (r57919): Some pages opened in background tabs don't render the first time you activate their tab + https://bugs.webkit.org/show_bug.cgi?id=38183 + + Rather than sprinkle PLATFORM #ifdefs around, add a new method, + RenderLayerCompositor::shouldPropagateCompositingToIFrameParent(), that indicates whether + an iframe with composited content should trigger compositing mode in the enclosing document + (a behavior that differs between platforms). + + Use this new method to determine whether to trigger a style recalc in the parent document + when an iframe becomes composited. + + Move the code formerly in RenderView::compositingStateChanged() into RenderLayerCompositor(). + + * manual-tests/compositing/accel-comp-iframe-tab-repaint.html: Added. + * manual-tests/compositing/resources/flash-frame.html: Added. + * manual-tests/compositing/resources/tab-repaint-part-2.html: Added. + * rendering/RenderLayerCompositor.cpp: + (WebCore::RenderLayerCompositor::enableCompositingMode): + (WebCore::RenderLayerCompositor::shouldPropagateCompositingToIFrameParent): + (WebCore::RenderLayerCompositor::requiresCompositingForIFrame): + * rendering/RenderLayerCompositor.h: + * rendering/RenderView.cpp: + * rendering/RenderView.h: + +2010-04-27 Andrey Kosyakov <caseq@chromium.org> + + Reviewed by Yury Semikhatsky. + + Log error message to inspector console if a resource fails to load. + Disable checking of mime-type consistency for failed resources. + https://bugs.webkit.org/show_bug.cgi?id=37215 + + Test: http/tests/inspector/console-resource-errors.html + + * inspector/InspectorController.cpp: + (WebCore::InspectorController::didReceiveResponse): + (WebCore::InspectorController::didFailLoading): + * inspector/front-end/Resource.js: + (WebInspector.Resource.prototype._mimeTypeIsConsistentWithType): + * inspector/front-end/ResourcesPanel.js: + (WebInspector.ResourcesPanel.prototype.recreateViewForResourceIfNeeded): + +2010-04-27 Vitaly Repeshko <vitalyr@chromium.org> + + Reviewed by Nate Chapin. + + [V8] Fix XHR memory leak in GC controller. + https://bugs.webkit.org/show_bug.cgi?id=38202 + + http://trac.webkit.org/changeset/55798 simplified processing of + active DOM objects but introduced a subtle bug in garbage + collection of XHRs. ActiveDOMObject is not a direct base class of + XHR and so upcasting changes pointer identity and breaks DOM + maps. This leads to forever live persistent handles to XHR that + had pending activity while V8 GC happened. + + * bindings/v8/V8GCController.cpp: + (WebCore::GCEpilogueVisitor::visitDOMWrapper): + +2010-04-27 Adam Barth <abarth@webkit.org> + + Unreviewed. Regenerate reference bindings code generator output. + + * bindings/scripts/test/V8/V8TestObj.cpp: + (WebCore::TestObjInternal::withScriptStateVoidCallback): + (WebCore::TestObjInternal::withScriptStateObjCallback): + +2010-04-27 Joseph Pecoraro <joepeck@webkit.org> + + Reviewed by Dan Bernstein. + + <input type="search"> with uneven padding causes text clipping + https://bugs.webkit.org/show_bug.cgi?id=38160 + + Test: fast/css/input-search-padding.html + + An <input type="search"> contains an inner block, which is explicitly + centered in RenderTextControlSingleLine based on the height of the element. + However, the clipping rect was not using the set location, and instead + calculated off of the top border and padding alone. This also vertically + centers the Caps Lock indicator. + + * rendering/RenderTextControl.cpp: moved controlClipRect implementation to RenderTextControlSingleLine + * rendering/RenderTextControl.h: allow a subclass implementation of controlClipRect, removed redundant hasControlClip implementation, and moved controlClipRect + * rendering/RenderTextControlSingleLine.cpp: + (WebCore::RenderTextControlSingleLine::paint): vertically center the Caps Lock indicator + (WebCore::RenderTextControlSingleLine::controlClipRect): use the set location of the anonymous inner block instead + * rendering/RenderTextControlSingleLine.h: allow for an implementation of controlClipRect for <input type="search"> + +2010-04-27 Thomas Zander <t.zander@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Fix linking on Symbian on Linux using the Makefile based mkspec. + + Disable thumb mode due to library size limitations, just like it's done + for the sbs/sbsv2 based build system. + + * WebCore.pro: + +2010-04-21 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Make sure WebKit is not compiled using C++0x. + https://bugs.webkit.org/show_bug.cgi?id=37867 + + As the rest of Qt compiles in the C++0x mode, people might start + compiling it in this mode. WebKit don't support this yet. + + Patch by Thiago Macieira <thiago.macieira@nokia.com> + + * WebCore.pro: + +2010-04-27 Jeremy Orlow <jorlow@chromium.org> + + Unreviewed build fix. + + Revert 58274 and 58269 (WebSQLDatabase changes) + https://bugs.webkit.org/show_bug.cgi?id=38191 + + Chromium bots are hitting ASSERTS when running layout tests. + + * platform/sql/SQLiteDatabase.cpp: + (WebCore::SQLiteDatabase::maximumSize): + (WebCore::SQLiteDatabase::freeSpaceSize): + * platform/sql/SQLiteDatabase.h: + * platform/sql/SQLiteStatement.cpp: + (WebCore::SQLiteStatement::prepare): + * storage/Database.cpp: + (WebCore::Database::performOpenAndVerify): + * storage/Database.h: + * storage/SQLTransaction.cpp: + (WebCore::SQLTransaction::postflightAndCommit): + +2010-04-27 Yuzo Fujishima <yuzo@google.com> + + Unreviewed, fix build breakage by reverting r58299. + + * css/CSSGrammar.y: + * css/CSSParser.cpp: + (WebCore::CSSParser::CSSParser): + (WebCore::CSSParser::clearProperties): + * css/CSSParser.h: + * css/CSSSelector.cpp: + (WebCore::CSSSelector::pseudoId): + (WebCore::nameToPseudoTypeMap): + (WebCore::CSSSelector::extractPseudoType): + * css/CSSSelector.h: + (WebCore::CSSSelector::): + * css/tokenizer.flex: + +2010-04-27 Yuzo Fujishima <yuzo@google.com> + + Reviewed by Shinichiro Hamaji. + + WebCore::CSSSelector::RareData::parseNth doesn't check whether the search for '-' in the argument was successful. + This results in incorrect parsing. + For example, '3n' is parsed as if it were '3n-3'. The code has been working OK just accidentally. + + https://bugs.webkit.org/show_bug.cgi?id=37787 + + No new tests are added because the original behavior is accidentally OK. + + * css/CSSSelector.cpp: + (WebCore::CSSSelector::RareData::parseNth): + +2010-04-27 Yuzo Fujishima <yuzo@google.com> + + Reviewed by David Hyatt. + + Enhance CSS parser for Paged Media (Iteration 1) + + In this change, the grammar is extended and skeletal methods for creating page rules and margin at-rules are defined. + The contents of the methods should be implemented by other changes. + + https://bugs.webkit.org/show_bug.cgi?id=35329 + + Test: fast/css/parsing-page-rule.html + + * css/CSSGrammar.y: + * css/CSSParser.cpp: + (WebCore::CSSParser::CSSParser): + (WebCore::CSSParser::clearProperties): + (WebCore::CSSParser::lex): + (WebCore::CSSParser::text): + (WebCore::CSSParser::createPageRule): + (WebCore::CSSParser::createMarginAtRule): + (WebCore::CSSParser::startDeclarationsForMarginBox): + (WebCore::CSSParser::endDeclarationsForMarginBox): + * css/CSSParser.h: + * css/CSSSelector.cpp: + (WebCore::CSSSelector::extractPseudoType): + * css/CSSSelector.h: + (WebCore::CSSSelector::): + * css/tokenizer.flex: + +2010-04-27 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Remove custom bindings for TreeWalker + https://bugs.webkit.org/show_bug.cgi?id=38182 + + This custom code is just CallWith=ScriptState. + + * WebCore.gypi: + * bindings/js/JSTreeWalkerCustom.cpp: + (WebCore::JSTreeWalker::markChildren): + * bindings/scripts/CodeGeneratorJS.pm: + * bindings/scripts/CodeGeneratorV8.pm: + * bindings/scripts/test/TestObj.idl: + * bindings/v8/custom/V8TreeWalkerCustom.cpp: Removed. + * dom/TreeWalker.idl: + +2010-04-27 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Move code out of GenerateImplementation to make it more smaller + https://bugs.webkit.org/show_bug.cgi?id=38176 + + * bindings/scripts/CodeGeneratorJS.pm: + - Move some code into a new GenerateAttributesHashTable method. + +2010-04-26 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Add CallWith=DynamicFrame to CodeGenerator + https://bugs.webkit.org/show_bug.cgi?id=38174 + + I've only used this in one instance, but this is infrastructure that I + think will help remove a bunch of custom bindings code. Also, added a + few tests of tricky argument cases. + + * bindings/js/JSHTMLFormElementCustom.cpp: + * bindings/scripts/CodeGeneratorJS.pm: + * bindings/scripts/CodeGeneratorV8.pm: + * bindings/scripts/test/GObject/WebKitDOMTestObj.cpp: + (webkit_dom_test_obj_with_dynamic_frame): + (webkit_dom_test_obj_with_dynamic_frame_and_arg): + (webkit_dom_test_obj_with_dynamic_frame_and_optional_arg): + (webkit_dom_test_obj_with_dynamic_frame_and_user_gesture): + (webkit_dom_test_obj_with_dynamic_frame_and_user_gesture_asad): + * bindings/scripts/test/GObject/WebKitDOMTestObj.h: + * bindings/scripts/test/JS/JSTestObj.cpp: + (WebCore::): + (WebCore::jsTestObjPrototypeFunctionWithDynamicFrame): + (WebCore::jsTestObjPrototypeFunctionWithDynamicFrameAndArg): + (WebCore::jsTestObjPrototypeFunctionWithDynamicFrameAndOptionalArg): + (WebCore::jsTestObjPrototypeFunctionWithDynamicFrameAndUserGesture): + (WebCore::jsTestObjPrototypeFunctionWithDynamicFrameAndUserGestureASAD): + * bindings/scripts/test/JS/JSTestObj.h: + * bindings/scripts/test/ObjC/DOMTestObj.h: + * bindings/scripts/test/ObjC/DOMTestObj.mm: + (-[DOMTestObj withDynamicFrame]): + (-[DOMTestObj withDynamicFrameAndArg:]): + (-[DOMTestObj withDynamicFrameAndOptionalArg:optionalArg:]): + (-[DOMTestObj withDynamicFrameAndUserGesture:]): + (-[DOMTestObj withDynamicFrameAndUserGestureASAD:optionalArg:]): + * bindings/scripts/test/TestObj.idl: + * bindings/scripts/test/V8/V8TestObj.cpp: + (WebCore::TestObjInternal::withDynamicFrameCallback): + (WebCore::TestObjInternal::withDynamicFrameAndArgCallback): + (WebCore::TestObjInternal::withDynamicFrameAndOptionalArgCallback): + (WebCore::TestObjInternal::withDynamicFrameAndUserGestureCallback): + (WebCore::TestObjInternal::withDynamicFrameAndUserGestureASADCallback): + (WebCore::): + * bindings/v8/custom/V8HTMLFormElementCustom.cpp: + * html/HTMLFormElement.idl: + +2010-04-26 Adam Barth <abarth@webkit.org> + + Unreviewed. Update comment to better reflect reality. + + * bindings/scripts/test/TestObj.idl: + +2010-04-26 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Add ObjC and GObject to run-bindings-test + https://bugs.webkit.org/show_bug.cgi?id=38168 + + Added expected results. + + * bindings/scripts/test/GObject/WebKitDOMTestObj.cpp: Added. + (WebKit::kit): + (webkit_dom_test_obj_void_method): + (webkit_dom_test_obj_void_method_with_args): + (webkit_dom_test_obj_int_method): + (webkit_dom_test_obj_int_method_with_args): + (webkit_dom_test_obj_obj_method): + (webkit_dom_test_obj_obj_method_with_args): + (webkit_dom_test_obj_method_with_exception): + (webkit_dom_test_obj_method_with_optional_arg): + (webkit_dom_test_obj_method_with_non_optional_arg_and_optional_arg): + (webkit_dom_test_obj_method_with_non_optional_arg_and_two_optional_args): + (webkit_dom_test_obj_get_read_only_int_attr): + (webkit_dom_test_obj_get_read_only_string_attr): + (webkit_dom_test_obj_get_read_only_test_obj_attr): + (webkit_dom_test_obj_get_int_attr): + (webkit_dom_test_obj_set_int_attr): + (webkit_dom_test_obj_get_string_attr): + (webkit_dom_test_obj_set_string_attr): + (webkit_dom_test_obj_get_test_obj_attr): + (webkit_dom_test_obj_set_test_obj_attr): + (webkit_dom_test_obj_get_attr_with_exception): + (webkit_dom_test_obj_set_attr_with_exception): + (webkit_dom_test_obj_get_attr_with_setter_exception): + (webkit_dom_test_obj_set_attr_with_setter_exception): + (webkit_dom_test_obj_get_attr_with_getter_exception): + (webkit_dom_test_obj_set_attr_with_getter_exception): + (WebKit::wrapTestObj): + (WebKit::core): + (webkit_dom_test_obj_finalize): + (webkit_dom_test_obj_set_property): + (webkit_dom_test_obj_get_property): + (webkit_dom_test_obj_class_init): + (webkit_dom_test_obj_init): + * bindings/scripts/test/GObject/WebKitDOMTestObj.h: Added. + * bindings/scripts/test/GObject/WebKitDOMTestObjPrivate.h: Added. + * bindings/scripts/test/ObjC/DOMTestObj.h: Added. + * bindings/scripts/test/ObjC/DOMTestObj.mm: Added. + (-[DOMTestObj dealloc]): + (-[DOMTestObj finalize]): + (-[DOMTestObj readOnlyIntAttr]): + (-[DOMTestObj readOnlyStringAttr]): + (-[DOMTestObj readOnlyTestObjAttr]): + (-[DOMTestObj intAttr]): + (-[DOMTestObj setIntAttr:]): + (-[DOMTestObj stringAttr]): + (-[DOMTestObj setStringAttr:]): + (-[DOMTestObj testObjAttr]): + (-[DOMTestObj setTestObjAttr:]): + (-[DOMTestObj attrWithException]): + (-[DOMTestObj setAttrWithException:]): + (-[DOMTestObj attrWithSetterException]): + (-[DOMTestObj setAttrWithSetterException:]): + (-[DOMTestObj attrWithGetterException]): + (-[DOMTestObj setAttrWithGetterException:]): + (-[DOMTestObj customAttr]): + (-[DOMTestObj setCustomAttr:]): + (-[DOMTestObj voidMethod]): + (-[DOMTestObj voidMethodWithArgs:strArg:objArg:]): + (-[DOMTestObj intMethod]): + (-[DOMTestObj intMethodWithArgs:strArg:objArg:]): + (-[DOMTestObj objMethod]): + (-[DOMTestObj objMethodWithArgs:strArg:objArg:]): + (-[DOMTestObj methodWithException]): + (-[DOMTestObj customMethod]): + (-[DOMTestObj customMethodWithArgs:strArg:objArg:]): + (-[DOMTestObj methodWithOptionalArg:]): + (-[DOMTestObj methodWithNonOptionalArgAndOptionalArg:opt:]): + (-[DOMTestObj methodWithNonOptionalArgAndTwoOptionalArgs:opt1:opt2:]): + (core): + (kit): + * bindings/scripts/test/ObjC/DOMTestObjInternal.h: Added. + +2010-04-26 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Add testing infrastructure for JSC bindings generator + https://bugs.webkit.org/show_bug.cgi?id=38167 + + This required moving the test files around a bit more. + + * bindings/scripts/test/JS/JSTestObj.cpp: Added. + (WebCore::): + (WebCore::JSTestObjConstructor::JSTestObjConstructor): + (WebCore::JSTestObjConstructor::classInfo): + (WebCore::JSTestObjConstructor::createStructure): + (WebCore::JSTestObjConstructor::getOwnPropertySlot): + (WebCore::JSTestObjConstructor::getOwnPropertyDescriptor): + (WebCore::JSTestObjPrototype::self): + (WebCore::JSTestObjPrototype::getOwnPropertySlot): + (WebCore::JSTestObjPrototype::getOwnPropertyDescriptor): + (WebCore::JSTestObj::JSTestObj): + (WebCore::JSTestObj::~JSTestObj): + (WebCore::JSTestObj::createPrototype): + (WebCore::JSTestObj::getOwnPropertySlot): + (WebCore::JSTestObj::getOwnPropertyDescriptor): + (WebCore::jsTestObjReadOnlyIntAttr): + (WebCore::jsTestObjReadOnlyStringAttr): + (WebCore::jsTestObjReadOnlyTestObjAttr): + (WebCore::jsTestObjIntAttr): + (WebCore::jsTestObjStringAttr): + (WebCore::jsTestObjTestObjAttr): + (WebCore::jsTestObjAttrWithException): + (WebCore::jsTestObjAttrWithSetterException): + (WebCore::jsTestObjAttrWithGetterException): + (WebCore::jsTestObjCustomAttr): + (WebCore::jsTestObjConstructor): + (WebCore::JSTestObj::put): + (WebCore::setJSTestObjIntAttr): + (WebCore::setJSTestObjStringAttr): + (WebCore::setJSTestObjTestObjAttr): + (WebCore::setJSTestObjAttrWithException): + (WebCore::setJSTestObjAttrWithSetterException): + (WebCore::setJSTestObjAttrWithGetterException): + (WebCore::setJSTestObjCustomAttr): + (WebCore::JSTestObj::getConstructor): + (WebCore::jsTestObjPrototypeFunctionVoidMethod): + (WebCore::jsTestObjPrototypeFunctionVoidMethodWithArgs): + (WebCore::jsTestObjPrototypeFunctionIntMethod): + (WebCore::jsTestObjPrototypeFunctionIntMethodWithArgs): + (WebCore::jsTestObjPrototypeFunctionObjMethod): + (WebCore::jsTestObjPrototypeFunctionObjMethodWithArgs): + (WebCore::jsTestObjPrototypeFunctionMethodWithException): + (WebCore::jsTestObjPrototypeFunctionCustomMethod): + (WebCore::jsTestObjPrototypeFunctionCustomMethodWithArgs): + (WebCore::jsTestObjPrototypeFunctionMethodWithOptionalArg): + (WebCore::jsTestObjPrototypeFunctionMethodWithNonOptionalArgAndOptionalArg): + (WebCore::jsTestObjPrototypeFunctionMethodWithNonOptionalArgAndTwoOptionalArgs): + (WebCore::toJS): + (WebCore::toTestObj): + * bindings/scripts/test/JS/JSTestObj.h: Added. + (WebCore::JSTestObj::classInfo): + (WebCore::JSTestObj::createStructure): + (WebCore::JSTestObj::impl): + (WebCore::JSTestObjPrototype::classInfo): + (WebCore::JSTestObjPrototype::createStructure): + (WebCore::JSTestObjPrototype::JSTestObjPrototype): + * bindings/scripts/test/TestObj.idl: + * bindings/scripts/test/V8/V8TestObj.cpp: Renamed from WebCore/bindings/scripts/test/V8TestObj.cpp. + (WebCore::): + (WebCore::TestObjInternal::V8_USE): + (WebCore::TestObjInternal::readOnlyIntAttrAttrGetter): + (WebCore::TestObjInternal::readOnlyStringAttrAttrGetter): + (WebCore::TestObjInternal::readOnlyTestObjAttrAttrGetter): + (WebCore::TestObjInternal::intAttrAttrGetter): + (WebCore::TestObjInternal::intAttrAttrSetter): + (WebCore::TestObjInternal::stringAttrAttrGetter): + (WebCore::TestObjInternal::stringAttrAttrSetter): + (WebCore::TestObjInternal::testObjAttrAttrGetter): + (WebCore::TestObjInternal::testObjAttrAttrSetter): + (WebCore::TestObjInternal::attrWithExceptionAttrGetter): + (WebCore::TestObjInternal::attrWithExceptionAttrSetter): + (WebCore::TestObjInternal::attrWithSetterExceptionAttrGetter): + (WebCore::TestObjInternal::attrWithSetterExceptionAttrSetter): + (WebCore::TestObjInternal::attrWithGetterExceptionAttrGetter): + (WebCore::TestObjInternal::attrWithGetterExceptionAttrSetter): + (WebCore::TestObjInternal::voidMethodCallback): + (WebCore::TestObjInternal::voidMethodWithArgsCallback): + (WebCore::TestObjInternal::intMethodCallback): + (WebCore::TestObjInternal::intMethodWithArgsCallback): + (WebCore::TestObjInternal::objMethodCallback): + (WebCore::TestObjInternal::objMethodWithArgsCallback): + (WebCore::TestObjInternal::methodWithExceptionCallback): + (WebCore::TestObjInternal::methodWithOptionalArgCallback): + (WebCore::TestObjInternal::methodWithNonOptionalArgAndOptionalArgCallback): + (WebCore::TestObjInternal::methodWithNonOptionalArgAndTwoOptionalArgsCallback): + (WebCore::TestObjInternal::overloadedMethod1Callback): + (WebCore::TestObjInternal::overloadedMethod2Callback): + (WebCore::TestObjInternal::overloadedMethod3Callback): + (WebCore::TestObjInternal::overloadedMethod4Callback): + (WebCore::TestObjInternal::overloadedMethodCallback): + (WebCore::ConfigureV8TestObjTemplate): + (WebCore::V8TestObj::GetRawTemplate): + (WebCore::V8TestObj::GetTemplate): + (WebCore::V8TestObj::toNative): + (WebCore::V8TestObj::HasInstance): + (WebCore::V8TestObj::wrap): + (WebCore::toV8): + (WebCore::V8TestObj::derefObject): + * bindings/scripts/test/V8/V8TestObj.h: Renamed from WebCore/bindings/scripts/test/V8TestObj.h. + +2010-04-26 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Need to support more efficient dispatch of lightweight builtins + https://bugs.webkit.org/show_bug.cgi?id=38155 + + Update bindings generation to include new thunk generator field + in the property map hash tables. + + * bindings/scripts/CodeGeneratorJS.pm: + +2010-04-26 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Move bindings test directory into the scripts directory + https://bugs.webkit.org/show_bug.cgi?id=38161 + + This test is really of the bindings scripts not of the bindings + themselves. By moving the files into the scripts directory, we'll be + able to test JSC as well. + + * bindings/scripts/test/TestObj.idl: Renamed from WebCore/bindings/v8/test/TestObj.idl. + * bindings/scripts/test/V8TestObj.cpp: Renamed from WebCore/bindings/v8/test/V8TestObj.cpp. + (WebCore::): + (WebCore::TestObjInternal::V8_USE): + (WebCore::TestObjInternal::readOnlyIntAttrAttrGetter): + (WebCore::TestObjInternal::readOnlyStringAttrAttrGetter): + (WebCore::TestObjInternal::readOnlyTestObjAttrAttrGetter): + (WebCore::TestObjInternal::intAttrAttrGetter): + (WebCore::TestObjInternal::intAttrAttrSetter): + (WebCore::TestObjInternal::stringAttrAttrGetter): + (WebCore::TestObjInternal::stringAttrAttrSetter): + (WebCore::TestObjInternal::testObjAttrAttrGetter): + (WebCore::TestObjInternal::testObjAttrAttrSetter): + (WebCore::TestObjInternal::attrWithExceptionAttrGetter): + (WebCore::TestObjInternal::attrWithExceptionAttrSetter): + (WebCore::TestObjInternal::attrWithSetterExceptionAttrGetter): + (WebCore::TestObjInternal::attrWithSetterExceptionAttrSetter): + (WebCore::TestObjInternal::attrWithGetterExceptionAttrGetter): + (WebCore::TestObjInternal::attrWithGetterExceptionAttrSetter): + (WebCore::TestObjInternal::voidMethodCallback): + (WebCore::TestObjInternal::voidMethodWithArgsCallback): + (WebCore::TestObjInternal::intMethodCallback): + (WebCore::TestObjInternal::intMethodWithArgsCallback): + (WebCore::TestObjInternal::objMethodCallback): + (WebCore::TestObjInternal::objMethodWithArgsCallback): + (WebCore::TestObjInternal::methodWithExceptionCallback): + (WebCore::TestObjInternal::methodWithOptionalArgCallback): + (WebCore::TestObjInternal::methodWithNonOptionalArgAndOptionalArgCallback): + (WebCore::TestObjInternal::methodWithNonOptionalArgAndTwoOptionalArgsCallback): + (WebCore::TestObjInternal::overloadedMethod1Callback): + (WebCore::TestObjInternal::overloadedMethod2Callback): + (WebCore::TestObjInternal::overloadedMethod3Callback): + (WebCore::TestObjInternal::overloadedMethod4Callback): + (WebCore::TestObjInternal::overloadedMethodCallback): + (WebCore::ConfigureV8TestObjTemplate): + (WebCore::V8TestObj::GetRawTemplate): + (WebCore::V8TestObj::GetTemplate): + (WebCore::V8TestObj::toNative): + (WebCore::V8TestObj::HasInstance): + (WebCore::V8TestObj::wrap): + (WebCore::toV8): + (WebCore::V8TestObj::derefObject): + * bindings/scripts/test/V8TestObj.h: Renamed from WebCore/bindings/v8/test/V8TestObj.h. + +2010-04-26 Daniel Cheng <dcheng@chromium.org> + + Reviewed by Jian Li. + + [chromium] Fix ChromiumDataObject::setURL to not populate its internal URL list with empty URLs. + https://bugs.webkit.org/show_bug.cgi?id=38159 + + No new tests. + + * platform/chromium/ChromiumDataObject.h: + (WebCore::ChromiumDataObject::setURL): + +2010-04-26 Daniel Cheng <dcheng@chromium.org> + + Reviewed by Jian Li. + + [Chromium] Don't make file paths available in text/uri-list when dragging files. + https://bugs.webkit.org/show_bug.cgi?id=25882 + + Test will be checked in with WebCore/platform/mac fix. + + * platform/chromium/ClipboardChromium.cpp: + (WebCore::ClipboardChromium::getData): + (WebCore::ClipboardChromium::types): + +2010-04-26 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Darin Adler. + + REGRESSION (r57292): 1.5% page load speed regression from visited link information leak fix + https://bugs.webkit.org/show_bug.cgi?id=38131 + + I did a number of separate optimizations which speed up style + resolution enough to more than make up for the regression. This + measures as a total PLT speedup of somewhere between 1.5% and + 3.7%. + + Optimizations done: + - Cache determineLinkState results, to avoid the need to repeatedly compute + the visited link hash for the same element. This directly addresses much + of the slowdown, since all elements get their style computed twice now. + - Added a fast way to get the length of a CSSMutableStyleDeclaration, and use + in CSSStyleSelector::matchRulesForList, since it was hot there. + - Hoist some loop invariant code that's not detected by the compiler out of the + main loop in matchRulesForList + - inline CSSStyleSelector::initElement and locateSharedStyle, + since there is only one call site in each case + - Inline the common non-line fast case of determineLinkState, and split the rest into + out-of-line determineLinkStateSlowCase. + - Added inline versions of the functions called by + visitedLinkHash (the version called by determineLinkState). + + * css/CSSMutableStyleDeclaration.cpp: + (WebCore::CSSMutableStyleDeclaration::length): Implemented in terms of new + inline nonvirtual mutableLength(). + * css/CSSMutableStyleDeclaration.h: + (WebCore::CSSMutableStyleDeclaration::mutableLength): Added new nonvirtual + inline way to get the length if you know you have a mutable style decl. + * css/CSSStyleSelector.cpp: + (WebCore::CSSStyleSelector::init): Clear cached link state. + (WebCore::CSSStyleSelector::matchRulesForList): hoist some code out of the main + loop and get style decl length more efficiently. + (WebCore::CSSStyleSelector::initElement): inline (only one call site) + (WebCore::CSSStyleSelector::SelectorChecker::determineLinkState): Inline fast + case, call slow case. + (WebCore::CSSStyleSelector::SelectorChecker::determineLinkStateSlowCase): Split + most of the above function into this slow case helper. + (WebCore::CSSStyleSelector::canShareStyleWithElement): Use the cache-enabled + way to get the current link state. + (WebCore::CSSStyleSelector::locateSharedStyle): inline + (WebCore::CSSStyleSelector::styleForElement): Use the cache-enabled way + to get the current link state. + * css/CSSStyleSelector.h: + (WebCore::CSSStyleSelector::currentElementLinkState): inline way to + get link state for the current element; manages the cache + * platform/LinkHash.cpp: + (WebCore::visitedLinkHashInline): inline version of below function + (WebCore::visitedLinkHash): call the inline version + (WebCore::visitedURLInline): inline version of below function + (WebCore::visitedURL): call the inline version + (WebCore::visitedURL): call inline versions of above two functions + +2010-04-26 Sam Weinig <sam@webkit.org> + + Reviewed by Alexey Proskuryakov. + + Remove last use of WEB_THREAD. + + * platform/mac/WebCoreObjCExtras.mm: + (WebCoreObjCScheduleDeallocateOnMainThread): This can always use + isMainThread(). + +2010-04-26 Dumitru Daniliuc <dumi@chromium.org> + + Reviewed by Dimitri Glazkov. + + Turn on AUTO_VACUUM = INCREMENTAL for all HTML5 databases, and + vacuum all databases when the number of free pages is at least 10% + of the number of total pages. Also, adding a guard against a bug + that was fixed in SQLite only starting with version 3.6.16. + + https://bugs.webkit.org/show_bug.cgi?id=36251 + + * platform/sql/SQLiteDatabase.cpp: + (WebCore::SQLiteDatabase::totalSize): + (WebCore::SQLiteDatabase::runIncrementalVacuumCommand): + (WebCore::SQLiteDatabase::turnOnIncrementalAutoVacuum): + * platform/sql/SQLiteDatabase.h: + * platform/sql/SQLiteStatement.cpp: + (WebCore::SQLiteStatement::prepare): + * storage/Database.cpp: + (WebCore::Database::performOpenAndVerify): + (WebCore::Database::incrementalVacuumIfNeeded): + * storage/Database.h: + * storage/SQLTransaction.cpp: + (WebCore::SQLTransaction::postflightAndCommit): + +2010-04-26 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + <rdar://problem/7766413> + + Fixed a crash seen when using the JavaScriptCore API with WebKit. + + No layout test because DumpRenderTree doesn't use the JavaScriptCore API + in this way. + + * bindings/js/JSEventListener.cpp: + (WebCore::JSEventListener::JSEventListener): Don't assign 0 to a WeakGCPtr. + JavaScriptCore no longer allows this. + + * bindings/js/ScriptWrappable.h: + (WebCore::ScriptWrappable::setWrapper): No need to initialize a WeakGCPtr + to 0, or ASSERT a non-0 value before assigning to a WeakGCPtr -- both are + default behaviors. + +2010-04-25 Sam Weinig <sam@webkit.org> + + Reviewed by Maciej Stachowiak. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38097 + Disentangle initializing the main thread from initializing threading + + * WebCore.xcodeproj/project.pbxproj: Sort files. + + * accessibility/mac/AccessibilityObjectWrapper.mm: Remove unnessary + +initialize method. The AccessibilityObjectWrapper has no data members + that need to be derefed, so it does not need to be finalized on the main + thread. + + * bindings/js/ScriptController.cpp: + (WebCore::ScriptController::initializeThreading): Add call to initializeMainThread. + * bindings/objc/WebScriptObject.mm: + (+[WebScriptObject initialize]): Add call to initializeMainThreadToProcessMainThread. + * bindings/v8/ScriptController.cpp: + (WebCore::ScriptController::initializeThreading): Add call to initializeMainThread. + * platform/mac/SharedBufferMac.mm: + (+[WebCoreSharedBufferData initialize]): Add call to initializeMainThreadToProcessMainThread. + +2010-04-26 Yongjun Zhang <yongjun_zhang@apple.com> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=38128 + Don't add empty credential to CredentialStorage. + + An empty credential is currently regarded as a invalid login because it means a missing value in + protectionSpaceToCredentialMap. This change makes it consistent with current WebCore's behavior + by ignoring empty credentials. + + No new tests added since this only affects credential entered by user from credential dialog, + which is not testable in DRT. + + * platform/network/mac/ResourceHandleMac.mm: + (WebCore::ResourceHandle::receivedCredential): + +2010-04-26 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Clean-up WebCore.pro after now that JavaScriptCore is built separately + https://bugs.webkit.org/show_bug.cgi?id=38123 + + HAVE_STDINT_H, and HAVE_PTHREAD_NP_H no longer needs to be defined + for QtWebKit as JavaScriptCore is built separately. These defines are only + used by JavaScriptCore and for JavaScriptCore these are already + properly defined in JavaScriptCore/config.h. + + No new tests, no new functionality. + + * WebCore.pro: + +2010-04-26 Roman Gershman <romange@google.com> + + Reviewed by Adam Barth. + + [Chromium] Font size in suggestions popup menu should be correlated with the font size of its text field. + The following manual test checks for desired behavior. + + https://bugs.webkit.org/show_bug.cgi?id=37977 + + * manual-tests/chromium/suggestions-popup-font-change.html: Added. + +2010-04-26 Luiz Agostini <luiz.agostini@openbossa.org> + + Reviewed by Kenneth Rohde Christiansen. + + View modes names in CSSValueKeywords.in + https://bugs.webkit.org/show_bug.cgi?id=38125 + + View mode names has changed in previous patch but CSSValueKeywords.in file was + not updated. + + * css/CSSValueKeywords.in: + +2010-04-26 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Fix compilation with RVCT 4 + https://bugs.webkit.org/show_bug.cgi?id=37727 + + Swap extern and declspec to fix visibility of symbol imported from QtGui. + + * page/qt/EventHandlerQt.cpp: + +2010-04-26 Ruben Van Boxem <vanboxem.ruben@gmail.com> + + Reviewed by Adam Roben. + + Fixes for Win64 compilation under gcc (mingw-w64) + + * WebCore/bridge/npapi.h: for win64 compatibility, mirroring mozilla-central, see Mozilla bug 560298 + * WebCore/platform/Arena.h: uword is used to cast from pointers here. unsigned long is 32-bit on Windows (but 64-bit on mac), and too small to hold a pointer. uintptr_t is 32-bit on 32-bit systems (mac, linux and windows) and 64-bit on all 64-bit systems + * WebCore/platform/graphics/transforms/TransformationMatrix.h: let mingw-w64/w32 use MSVC codepath + * WebCore/platform/text/TextStream.cpp: let mingw-w64 use MSVC codepath + * WebCore/platform/text/TextStream.h: let mingw-w64 use MSVC codepath + * WebCore/plugins/PluginView.cpp: fix pointer casts on WIN64 and let mingw-w64 use MSVC codepath + * WebCore/plugins/win/PluginViewWin.cpp: fix pointer casts on WIN64 + +2010-04-26 Markus Goetz <Markus.Goetz@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] HTTP pipelining efficiency increase + https://bugs.webkit.org/show_bug.cgi?id=38062 + + Increase number of network requests that are fed into + QNetworkAccessManager. + + * platform/network/qt/ResourceRequestQt.cpp: + (WebCore::initializeMaximumHTTPConnectionCountPerHost): + +2010-04-26 Ilya Tikhonovsky <loislo@chromium.org> + + Reviewed by Yury Semikhatsky. + + Web Inspector: undefined shows up on inspector. + https://bugs.webkit.org/show_bug.cgi?id=38120 + + * inspector/front-end/ScriptsPanel.js: + (WebInspector.ScriptsPanel.prototype.hide): + * inspector/front-end/SourceFrame.js: + (WebInspector.SourceFrame.prototype.set visible): + +2010-04-26 Bruno Schmidt <bruno.schmidt@gmail.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Exposing an QVariantMap containing QObjectStar to Javascript + causes Segmentation Fault + https://bugs.webkit.org/show_bug.cgi?id=34729 + + If an QVariantMap containing QObjectStar is added to the to QtWebkit + Javascript, it's use causes Segmentation Fault. + It happens because, in the case QMetaType::QVariantMap, the "root" + object that is inside of a PassRefPtr is passed recursively inside a + loop to recover the content of the map, but the PassRefPtr semantics + prohibit its use inside a loop, so the "root" object mus be passed + using the method "PassRefPtr::get" in order to keep the current + reference. + + * bridge/qt/qt_runtime.cpp: + (JSC::Bindings::convertValueToQVariant): + (JSC::Bindings::convertQVariantToValue): change to root.get() + +2010-04-26 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Yury Semikhatsky. + + Web Inspector: Render clip in summary bar using "arc", not "quadraticCurveTo". + + https://bugs.webkit.org/show_bug.cgi?id=38107 + + * inspector/front-end/SummaryBar.js: + (WebInspector.SummaryBar.prototype._drawSummaryGraph.drawPill): + (WebInspector.SummaryBar.prototype._drawSummaryGraph): + +2010-04-26 Andreas Kling <andreas.kling@nokia.com> + + Reviewed by Tor Arne Vestbø. + + [Qt] Fix compilation against Qt 4.7 + + Some QtMultimedia things have been moved into QtMediaServices + https://bugs.webkit.org/show_bug.cgi?id=38111 + + * WebCore.pro: + * platform/graphics/qt/MediaPlayerPrivateQt.cpp: + (WebCore::MediaPlayerPrivate::supportsType): + (WebCore::MediaPlayerPrivate::totalBytes): + +2010-04-26 Zoltan Herczeg <zherczeg@webkit.org> + + Reviewed by Dirk Schulze. + + Call setStrokeStyle in applyStrokeStyleToContext + https://bugs.webkit.org/show_bug.cgi?id=37849 + + Not all platforms set the stroke style to solid if they + get an empty line dash array. Some just ignore the operation. + + * rendering/SVGRenderSupport.cpp: + (WebCore::applyStrokeStyleToContext): + +2010-04-23 Ilya Tikhonovsky <loislo@chromium.org> + + Reviewed by Pavel Feldman. + + WebInspector: Aggregated stats of time spent in children records should be visible + in the popup panel of parent record. Crash in pushGCEventRecord also was fixed. + https://bugs.webkit.org/show_bug.cgi?id=37820 + + * English.lproj/localizedStrings.js: + * inspector/InspectorTimelineAgent.cpp: + (WebCore::InspectorTimelineAgent::pushGCEventRecords): + * inspector/front-end/TimelinePanel.js: + (WebInspector.TimelinePanel.prototype._innerAddRecordToTimeline): + (WebInspector.TimelinePanel.prototype._createRootRecord): + (WebInspector.TimelinePanel.prototype._showPopover): + (WebInspector.TimelineCalculator.prototype.computeBarGraphPercentages): + (WebInspector.TimelineCalculator.prototype.computeBarGraphWindowPosition): + (WebInspector.TimelineRecordGraphRow): + (WebInspector.TimelineRecordGraphRow.prototype.update): + (WebInspector.TimelinePanel.FormattedRecord): + (WebInspector.TimelinePanel.FormattedRecord.prototype._generateAggregatedInfo): + (WebInspector.TimelinePanel.FormattedRecord.prototype._generatePopupContent): + (WebInspector.TimelinePanel.FormattedRecord.prototype._getRecordDetails): + (WebInspector.TimelinePanel.FormattedRecord.prototype._calculateAggregatedStats): + * inspector/front-end/inspector.css: + (.timeline-graph-bar.with-children): + (.timeline-graph-bar.cpu): + (.timeline-aggregated-category): + (.timeline-loading): + (.timeline-scripting): + (.timeline-rendering): + (.popover .timeline-aggregated-category.timeline-loading): + (.timeline-details-title): + +2010-04-25 Kent Tamura <tkent@chromium.org> + + Reviewed by Darin Adler. + + WebKit crashes with deeply nested divs + https://bugs.webkit.org/show_bug.cgi?id=18282 + + The HTML parser caps a tree depth by MAX_DOM_TREE_DEPTH defined in + TreeDepthLimit.h. This is performance-efficient, but does not work for + DOM operations such as Node.appendChild(). + + Test: fast/parser/element-nesting-cap.html + + * dom/Node.h: + * dom/XMLTokenizer.cpp: + (WebCore::XMLTokenizer::pushCurrentNode): + * html/HTMLParser.cpp: + + * GNUmakefile.am: + * WebCore.gypi: + * WebCore.pro: + * WebCore.vcproj/WebCore.vcproj: + * WebCore.xcodeproj/project.pbxproj: + * dom/TreeDepthLimit.h: + Added. Define MAX_DOM_TREE_DEPTH. The default value is 5000. + * dom/XMLTokenizer.cpp: Use maxDOMTreeDepth. + (WebCore::XMLTokenizer::pushCurrentNode): + * html/HTMLParser.cpp: + Introduce m_treeDepth, which counts the depth of the tree. + Unlike m_blocksInStack, it contains the number of non-block nodes. + (WebCore::HTMLParser::HTMLParser): + (WebCore::HTMLParser::reset): + (WebCore::HTMLParser::limitDepth): + Renamed from limitBlockDepth. Add check for m_nodeDepth. + (WebCore::HTMLParser::insertNodeAfterLimitDepth): + Renamed from insertNodeAfterLimitBlockDepth. + (WebCore::HTMLParser::parseToken): + (WebCore::HTMLParser::handleResidualStyleCloseTagAcrossBlocks): + (WebCore::HTMLParser::pushBlock): + (WebCore::HTMLParser::popOneBlockCommon): + (WebCore::HTMLParser::freeBlock): + * html/HTMLParser.h: + +2010-04-25 Andrey Kosyakov <caseq@chromium.org> + + Reviewed by Adam Barth. + + Get context properly when event handler was created on + the main world. + https://bugs.webkit.org/show_bug.cgi?id=37947 + + Test: http/tests/security/isolatedWorld/dispatchEvent.html + + * bindings/v8/WorldContextHandle.cpp: + (WebCore::WorldContextHandle::adjustedContext): + +2010-04-25 yael aharon <yael.aharon@nokia.com> + + Reviewed by Adele Peterson. + + Allow styling of HTMLProgressElement. + https://bugs.webkit.org/show_bug.cgi?id=37901 + + Added a new pseudo element to represent the value portion of the progress element. + Web developers can style this pseudo element separate from the rest of the progress element. + + Test: fast/dom/HTMLProgressElement/progress-bar-value-pseudo-element.html + + * css/CSSPrimitiveValueMappings.h: + (WebCore::CSSPrimitiveValue::CSSPrimitiveValue): + * css/CSSSelector.cpp: + (WebCore::CSSSelector::pseudoId): + (WebCore::nameToPseudoTypeMap): + (WebCore::CSSSelector::extractPseudoType): + * css/CSSSelector.h: + * css/CSSValueKeywords.in: + * platform/ThemeTypes.h: + * rendering/RenderProgress.cpp: + (WebCore::ProgressValueElement::isShadowNode): + (WebCore::ProgressValueElement::shadowParentNode): + (WebCore::ProgressValueElement::ProgressValueElement): + (WebCore::RenderProgress::RenderProgress): + (WebCore::RenderProgress::~RenderProgress): + (WebCore::RenderProgress::layout): + (WebCore::RenderProgress::styleDidChange): + (WebCore::RenderProgress::updateFromElement): + (WebCore::RenderProgress::updateValuePartState): + (WebCore::RenderProgress::createStyleForValuePart): + (WebCore::RenderProgress::updateAnimationState): + * rendering/RenderTheme.cpp: + (WebCore::RenderTheme::isControlStyled): + * rendering/RenderProgress.h: + * rendering/style/RenderStyleConstants.h: + +2010-04-24 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Dan Bernstein. + + Don't propagate compositing out of iframes on Mac + https://bugs.webkit.org/show_bug.cgi?id=38072 + + Propagating compositing out of iframes caused too many regressions on Mac, + so only do it for other platforms that may need to hook compositing layers + together across iframe boundaries. + + * rendering/RenderLayerCompositor.cpp: + (WebCore::RenderLayerCompositor::requiresCompositingForIFrame): + +2010-04-24 Anton Muhin <antonm@chromium.org> + + Reviewed by Darin Adler. + + Allow to construct HashTraits<WebCore::QualifiedName>::constructDeletedValue + + Former implementation attempted to use AtomicString(HashTableDeletedValue) + however those values cannot be used that way: one cannot construct + QualifiedNameImpl out of such AtomicString as we'll try to lookup this string + in the table, for example. + https://bugs.webkit.org/show_bug.cgi?id=37722 + + * dom/QualifiedName.cpp: + (WebCore::QualifiedName::deref): check that hash table deleted values never derefed + * dom/QualifiedName.h: + (WebCore::QualifiedName::QualifiedName): add a constructor to create hash table deleted values + (WebCore::QualifiedName::isHashTableDeletedValue): add a check if given instance is hash table deleted value + (WTF::): + +2010-04-24 Julien Chaffraix <jchaffraix@webkit.org> + + Reviewed by Alexey Proskuryakov. + + protocolHostAndPortEquals host check makes a wrong assumption + https://bugs.webkit.org/show_bug.cgi?id=37777 + + The host check assumed that both host started at the same position. This is true + if both URL are the same but sometimes one has credential and the other does not. + In this case, the method would compare invalid positions. + + Test: http/tests/appcache/credential-url.html + + * platform/KURL.cpp: + (WebCore::protocolHostAndPortAreEqual): + * platform/KURLGoogle.cpp: + (WebCore::protocolHostAndPortAreEqual): + Fix the host check to take both URL's credential into account. + +2010-04-24 Nikolas Zimmermann <nzimmermann@rim.com> + + Not reviewed. Fix linkage on several bots (no idea, why it worked in a from-scratch rebuild on Leopard on my machine!) -> include NodeRenderStyle.h + Having to include NodeRenderStyle.h just to pull in the renderStyle() is a crazy concept, but I see what it tries to avoid (including RenderObject.h in Node.h) + + * rendering/SVGRenderSupport.cpp: + +2010-04-24 Nikolas Zimmermann <nzimmermann@rim.com> + + Not reviewed. Fix release builds, wrap resourceMode assertion in NDEBUG blocks, use UNUSED_PARAM() otherwhise. + + * rendering/RenderSVGResourceClipper.cpp: + (WebCore::RenderSVGResourceClipper::applyResource): + * rendering/RenderSVGResourceFilter.cpp: + (WebCore::RenderSVGResourceFilter::applyResource): + (WebCore::RenderSVGResourceFilter::postApplyResource): + * rendering/RenderSVGResourceMasker.cpp: + (WebCore::RenderSVGResourceMasker::applyResource): + +2010-04-24 Nikolas Zimmermann <nzimmermann@rim.com> + + Reviewed by Dirk Schulze. + + SVGPaintServer needs to be converted to the new RenderSVGResource* system + https://bugs.webkit.org/show_bug.cgi?id=37986 + + Huge speedup for SVG painting using paint servers (gradient/patterns). Cache underlying + WebCore::Gradient/Pattern datastructures, do not rebuild them on every painting. This marks + the finish of the SVGResource -> RenderSVGResource transition. + + Outline of same key changes: + - RenderSVGResource is an abstract base class now, and the previous class is now named RenderSVGResourceContainer + All resources except RenderSVGResourceSolidColor now inherit from RenderSVGResourceContainer, as they are all + associated with a SVG*Element class. RenderSVGResourceSolidColor inherits from RenderSVGResource, and is not + associated with any SVG*Element class. RenderSVGResourceSolidColor is not a render tree object, despite its name. + The reason for that is consistency with all other painting resources. + - RenderSVGResourceSolidColor does not live in the render tree, and exists only as static object, which is shared + and always used when filling/stroking with solid colors - just like the old SVGPaintServerSolid. + - RenderSVGResourceGradient/RenderSVGResourcePattern now store the underlying WebCore::Gradient/Pattern object + instead of rebuilding it everytime we're asked to paint -> this is the main difference with the old concept, leading + to much faster speed. + - SVGResource has vanished. All resources (clipper/filter/marker/masker/gradient/pattern) now share the same codepaths + to handle updates and client invalidation - which is a huge benefit, and makes the code easier to understand. + + * Android.mk: Remove svg/graphics/SVGResource*, svg/graphics/SVGPaintServer.h from build. + * GNUmakefile.am: Ditto. + * WebCore.gypi: Ditto. + * WebCore.pro: Ditto. + * WebCore.vcproj/WebCore.vcproj: Ditto. + * WebCore.xcodeproj/project.pbxproj: Ditto. + * platform/graphics/Gradient.cpp: Add addColorStop() method taking a ColorStop const-reference. + (WebCore::Gradient::addColorStop): + * platform/graphics/Gradient.h: Ditto. + * platform/graphics/TextRun.h: Rename SVGPaintServer to RenderSVGResource + (WebCore::TextRun::TextRun): + (WebCore::TextRun::activePaintingResource): Renamed from activePaintServer. + (WebCore::TextRun::setActivePaintingResource): Renamed from setActivePaintServer. + * platform/graphics/win/GraphicsContextWin.cpp: Remove references to SVGResourceImage, which was removed a long time ago. + * rendering/RenderObject.cpp: + (WebCore::RenderObject::toRenderSVGResourceContainer): Renamed from toRenderSVGResource(). + * rendering/RenderObject.h: + (WebCore::RenderObject::isSVGGradientStop): Added. + (WebCore::RenderObject::isSVGResourceContainer): Renamed from isSVGResource(). + * rendering/RenderPath.cpp: Utilize RenderSVGResource::fill/strokePaintingResource to request paint servers, instead of SVGPaintServer. + (WebCore::RenderPath::fillContains): Adapt to new concept. + (WebCore::RenderPath::strokeContains): Ditto. + (WebCore::fillAndStrokePath): Ditto. + (WebCore::RenderPath::paint): Ditto. + * rendering/RenderSVGGradientStop.cpp: + (WebCore::RenderSVGGradientStop::styleDidChange): Ditto. + * rendering/RenderSVGGradientStop.h: Fixed indention. + * rendering/RenderSVGResource.cpp: Refactored old SVGPaintServer code to request fill/stroke painting resources, splitted up in several methods to aid readability. + (WebCore::registerPendingResource): + (WebCore::adjustColorForPseudoRules): + (WebCore::RenderSVGResource::fillPaintingResource): + (WebCore::RenderSVGResource::strokePaintingResource): + (WebCore::RenderSVGResource::sharedSolidPaintingResource): + (WebCore::RenderSVGResource::markForLayoutAndResourceInvalidation): + * rendering/RenderSVGResource.h: Make RenderSVGResource an abstract base class, see above for the reasoning. + (WebCore::RenderSVGResource::RenderSVGResource): + (WebCore::RenderSVGResource::~RenderSVGResource): + (WebCore::RenderSVGResource::postApplyResource): + * rendering/RenderSVGResourceClipper.cpp: Inherit from RenderSVGResourceContainer instead of RenderSVGResource. + (WebCore::RenderSVGResourceClipper::RenderSVGResourceClipper): + (WebCore::RenderSVGResourceClipper::invalidateClient): + (WebCore::RenderSVGResourceClipper::applyResource): Adapt to signature changes (add RenderStyle* and resource mode parameters) + (WebCore::RenderSVGResourceClipper::applyClippingToContext): + * rendering/RenderSVGResourceClipper.h: + * rendering/RenderSVGResourceContainer.h: Added. Renamed from RenderSVGResource. Now inherits from RenderSVGHiddenContainer and RenderSVGResource. + (WebCore::RenderSVGResourceContainer::RenderSVGResourceContainer): + (WebCore::RenderSVGResourceContainer::~RenderSVGResourceContainer): + (WebCore::RenderSVGResourceContainer::idChanged): + (WebCore::RenderSVGResourceContainer::isSVGResourceContainer): + (WebCore::RenderSVGResourceContainer::drawsContents): + (WebCore::RenderSVGResourceContainer::toRenderSVGResourceContainer): + (WebCore::getRenderSVGResourceContainerById): + (WebCore::getRenderSVGResourceById): + * rendering/RenderSVGResourceFilter.cpp: Inherit from RenderSVGResourceContainer instead of RenderSVGResource. + (WebCore::RenderSVGResourceFilter::RenderSVGResourceFilter): + (WebCore::RenderSVGResourceFilter::invalidateClient): + (WebCore::RenderSVGResourceFilter::applyResource): Adapt to signature changes (add RenderStyle* and resource mode parameters) + (WebCore::RenderSVGResourceFilter::postApplyResource): + * rendering/RenderSVGResourceFilter.h: + * rendering/RenderSVGResourceGradient.cpp: Moved from SVGPaintServerGradient, cleaned up and refactored. + (WebCore::RenderSVGResourceGradient::RenderSVGResourceGradient): + (WebCore::RenderSVGResourceGradient::~RenderSVGResourceGradient): + (WebCore::RenderSVGResourceGradient::invalidateClients): + (WebCore::RenderSVGResourceGradient::invalidateClient): + (WebCore::createMaskAndSwapContextForTextGradient): + (WebCore::clipToTextMask): + (WebCore::RenderSVGResourceGradient::applyResource): + * rendering/RenderSVGResourceGradient.h: + (WebCore::RenderSVGResourceGradient::resourceBoundingBox): + * rendering/RenderSVGResourceLinearGradient.cpp: Moved from SVGPaintServerLinearGradient, cleaned up and refactored. + (WebCore::RenderSVGResourceLinearGradient::RenderSVGResourceLinearGradient): + (WebCore::RenderSVGResourceLinearGradient::~RenderSVGResourceLinearGradient): + (WebCore::RenderSVGResourceLinearGradient::buildGradient): + * rendering/RenderSVGResourceLinearGradient.h: + (WebCore::RenderSVGResourceLinearGradient::renderName): + (WebCore::RenderSVGResourceLinearGradient::resourceType): + * rendering/RenderSVGResourceMarker.cpp: Inherit from RenderSVGResourceContainer instead of RenderSVGResource. + (WebCore::RenderSVGResourceMarker::RenderSVGResourceMarker): + (WebCore::RenderSVGResourceMarker::invalidateClient): + * rendering/RenderSVGResourceMarker.h: + (WebCore::RenderSVGResourceMarker::applyResource): + * rendering/RenderSVGResourceMasker.cpp: Inherit from RenderSVGResourceContainer instead of RenderSVGResource. + (WebCore::RenderSVGResourceMasker::RenderSVGResourceMasker): + (WebCore::RenderSVGResourceMasker::invalidateClient): + (WebCore::RenderSVGResourceMasker::applyResource): + * rendering/RenderSVGResourceMasker.h: + (WebCore::MaskerData::MaskerData): + * rendering/RenderSVGResourcePattern.cpp: Moved from SVGPaintServerPattern, cleaned up and refactored. + (WebCore::RenderSVGResourcePattern::RenderSVGResourcePattern): + (WebCore::RenderSVGResourcePattern::~RenderSVGResourcePattern): + (WebCore::RenderSVGResourcePattern::invalidateClients): + (WebCore::RenderSVGResourcePattern::invalidateClient): + (WebCore::RenderSVGResourcePattern::applyResource): + (WebCore::RenderSVGResourcePattern::postApplyResource): + (WebCore::calculatePatternBoundaries): + (WebCore::RenderSVGResourcePattern::calculatePatternBoundariesIncludingOverflow): + (WebCore::RenderSVGResourcePattern::createTileImage): + (WebCore::RenderSVGResourcePattern::buildPattern): + * rendering/RenderSVGResourcePattern.h: + (WebCore::RenderSVGResourcePattern::renderName): + (WebCore::RenderSVGResourcePattern::resourceBoundingBox): + (WebCore::RenderSVGResourcePattern::resourceType): + * rendering/RenderSVGResourceRadialGradient.cpp: Moved from SVGPaintServerRadialGradient, cleaned up and refactored. + (WebCore::RenderSVGResourceRadialGradient::RenderSVGResourceRadialGradient): + (WebCore::RenderSVGResourceRadialGradient::~RenderSVGResourceRadialGradient): + (WebCore::RenderSVGResourceRadialGradient::buildGradient): + * rendering/RenderSVGResourceRadialGradient.h: + (WebCore::RenderSVGResourceRadialGradient::renderName): + (WebCore::RenderSVGResourceRadialGradient::resourceType): + * rendering/RenderSVGResourceSolidColor.cpp: Moved from SVGPaintServerSolid, cleaned up and refactored. + (WebCore::RenderSVGResourceSolidColor::RenderSVGResourceSolidColor): + (WebCore::RenderSVGResourceSolidColor::~RenderSVGResourceSolidColor): + (WebCore::RenderSVGResourceSolidColor::applyResource): + (WebCore::RenderSVGResourceSolidColor::postApplyResource): + * rendering/RenderSVGResourceSolidColor.h: + (WebCore::RenderSVGResourceSolidColor::invalidateClients): + (WebCore::RenderSVGResourceSolidColor::invalidateClient): + (WebCore::RenderSVGResourceSolidColor::resourceBoundingBox): + (WebCore::RenderSVGResourceSolidColor::resourceType): + (WebCore::RenderSVGResourceSolidColor::color): + (WebCore::RenderSVGResourceSolidColor::setColor): + * rendering/RenderSVGText.cpp: + (WebCore::RenderSVGText::paint): Early exit if painting is disabled. + * rendering/RenderTreeAsText.cpp: + (WebCore::write): Add RenderSVGGradientStop dumping. + (WebCore::externalRepresentation): Remove SVGResource dumping. + * rendering/SVGInlineTextBox.cpp: Adapt to SVGPaintServer changes (paint server request). + (WebCore::SVGInlineTextBox::paintCharacters): + (WebCore::SVGInlineTextBox::paintDecoration): + * rendering/SVGInlineTextBox.h: Ditto. + (WebCore::SVGTextPaintInfo::SVGTextPaintInfo): + * rendering/SVGRenderSupport.cpp: Ditto. + (WebCore::SVGRenderBase::prepareToRenderSVGContent): + (WebCore::SVGRenderBase::finishRenderSVGContent): + (WebCore::invalidatePaintingResource): + (WebCore::deregisterFromResources): + (WebCore::dashArrayFromRenderingStyle): Moved here from SVGPaintServer. + (WebCore::applyStrokeStyleToContext): Ditto. + * rendering/SVGRenderSupport.h: + * rendering/SVGRenderTreeAsText.cpp: Add new gradient/pattern dumping code. Stops are now properly dumped as well! + (WebCore::operator<<): + (WebCore::writeSVGPaintingResource): + (WebCore::writeStyle): + (WebCore::boundingBoxModeString): + (WebCore::writeCommonGradientProperties): + (WebCore::writeSVGResourceContainer): + (WebCore::writeSVGGradientStop): + * rendering/SVGRenderTreeAsText.h: + * rendering/SVGRootInlineBox.cpp: Adapt to SVGPaintServer changes (paint server request). + (WebCore::SVGRootInlineBoxPaintWalker::SVGRootInlineBoxPaintWalker): + (WebCore::SVGRootInlineBoxPaintWalker::~SVGRootInlineBoxPaintWalker): + (WebCore::SVGRootInlineBoxPaintWalker::teardownFillPaintServer): + (WebCore::SVGRootInlineBoxPaintWalker::teardownStrokePaintServer): + (WebCore::SVGRootInlineBoxPaintWalker::setupBackground): + (WebCore::SVGRootInlineBoxPaintWalker::setupFill): + (WebCore::SVGRootInlineBoxPaintWalker::setupFillSelection): + (WebCore::SVGRootInlineBoxPaintWalker::setupStroke): + (WebCore::SVGRootInlineBoxPaintWalker::setupStrokeSelection): + (WebCore::SVGRootInlineBoxPaintWalker::setupForeground): + (WebCore::SVGRootInlineBoxPaintWalker::activePaintingResource): + (WebCore::SVGRootInlineBoxPaintWalker::paintChunk): + * svg/GradientAttributes.h: Remove SVGGradientStop, use Gradient::ColorStop vector. Cleanup. + (WebCore::GradientAttributes::stops): + (WebCore::GradientAttributes::setStops): + * svg/LinearGradientAttributes.h: Move ENABLE(SVG) guard to correct location. + * svg/PatternAttributes.h: Add missing includes and class forwards. + * svg/RadialGradientAttributes.h: Move ENABLE(SVG) guard to correct location. + * svg/SVGClipPathElement.cpp: Rename invalidateCanvasResources() to invalidateResourceClients(). + (WebCore::SVGClipPathElement::svgAttributeChanged): + (WebCore::SVGClipPathElement::childrenChanged): Only call invalidateResourceClients() when !changedByParser is set. + * svg/SVGClipPathElement.h: + * svg/SVGDocumentExtensions.cpp: Change HashMaps to hash AtomicStrings instead of Strings. Rename RenderSVGResource to RenderSVGResourceContainer. + (WebCore::SVGDocumentExtensions::addResource): + (WebCore::SVGDocumentExtensions::removeResource): + (WebCore::SVGDocumentExtensions::resourceById): + (WebCore::SVGDocumentExtensions::addPendingResource): + * svg/SVGDocumentExtensions.h: + * svg/SVGElement.cpp: + (WebCore::SVGElement::insertedIntoDocument): Remove reference to SVGResource::invalidateClients(), handled differently now. + (WebCore::SVGElement::updateAnimatedSVGAttribute): Change assertion, that is incorrect now. + * svg/SVGElement.h: Make updateAnimatedSVGAttribute() public. + * svg/SVGFont.cpp: Adapt to SVGPaintServer changes (paint server request). + (WebCore::Font::drawTextUsingSVGFont): + * svg/SVGGElement.cpp: If style()->display() is NONE, create a RenderSVGHiddenContainer, removing hacks in SVGStopElement for pservers-grad-19-b.svg (yes, SVG is crazy.) + (WebCore::SVGGElement::createRenderer): + * svg/SVGGElement.h: Remove childrenChanged() method which _always_ called renderer->setNeedsLayout(true), which is completly wrong and unnecessary. + (WebCore::SVGGElement::rendererIsNeeded): Always return true. + * svg/SVGGradientElement.cpp: Adapt to new RenderSVGResourceGradient code. + (WebCore::SVGGradientElement::svgAttributeChanged): + (WebCore::SVGGradientElement::childrenChanged): Only call invalidateResourceClients() when !changedByParser is set. + (WebCore::SVGGradientElement::buildStops): + * svg/SVGGradientElement.h: + * svg/SVGLinearGradientElement.cpp: Adapt to new RenderSVGResourceLinearGradient code. + (WebCore::SVGLinearGradientElement::svgAttributeChanged): + (WebCore::SVGLinearGradientElement::createRenderer): + (WebCore::SVGLinearGradientElement::collectGradientProperties): + (WebCore::SVGLinearGradientElement::calculateStartEndPoints): + * svg/SVGLinearGradientElement.h: + * svg/SVGMarkerElement.cpp: Rename invalidateCanvasResources() to invalidateResourceClients(). + (WebCore::SVGMarkerElement::svgAttributeChanged): + (WebCore::SVGMarkerElement::childrenChanged): Only call invalidateResourceClients() when !changedByParser is set. + (WebCore::SVGMarkerElement::setOrientToAuto): + (WebCore::SVGMarkerElement::setOrientToAngle): + * svg/SVGMaskElement.cpp: Rename invalidateCanvasResources() to invalidateResourceClients(). + (WebCore::SVGMaskElement::svgAttributeChanged): + (WebCore::SVGMaskElement::childrenChanged): Only call invalidateResourceClients() when !changedByParser is set. + * svg/SVGPatternElement.cpp: Rename invalidateCanvasResources() to invalidateResourceClients(). + (WebCore::SVGPatternElement::svgAttributeChanged): + (WebCore::SVGPatternElement::childrenChanged): Only call invalidateResourceClients() when !changedByParser is set. + (WebCore::SVGPatternElement::createRenderer): + * svg/SVGPatternElement.h: + * svg/SVGPolyElement.h: Remove unneded rendererIsNeeded() override. + * svg/SVGRadialGradientElement.cpp: Adapt to new RenderSVGResourceRadialGradient code. + (WebCore::SVGRadialGradientElement::svgAttributeChanged): + (WebCore::SVGRadialGradientElement::createRenderer): + (WebCore::SVGRadialGradientElement::collectGradientProperties): + (WebCore::SVGRadialGradientElement::calculateFocalCenterPointsAndRadius): + * svg/SVGRadialGradientElement.h: + * svg/SVGStopElement.cpp: Clean up code, moved stop color calculation from SVGGradientElement to here, where it belongs. + (WebCore::SVGStopElement::parseMappedAttribute): + (WebCore::SVGStopElement::stopColorIncludingOpacity): + * svg/SVGStopElement.h: + * svg/SVGStyledElement.cpp: + (WebCore::SVGStyledElement::~SVGStyledElement): + (WebCore::SVGStyledElement::svgAttributeChanged): Only invalidateResourcesInAncestorChain()/deregisterFromResources() when we're not parsing. + (WebCore::SVGStyledElement::invalidateResourcesInAncestorChain): Early exit if we find a parent resources, there is no resource nesting. + (WebCore::SVGStyledElement::invalidateResourceClients): Renamed from invalidateCanvasResources() + (WebCore::SVGStyledElement::childrenChanged): Only invalidate SVGElementInstances when !changedByParser is set. + * svg/SVGStyledElement.h: Remove canvasResource() logic, remove detach() method. + * svg/SVGTextPathElement.h: + * svg/graphics/SVGPaintServer.h: Removed. + * svg/graphics/SVGResource.cpp: Removed. + * svg/graphics/SVGResource.h: Removed. + +2010-04-23 Zhenyao Mo <zmo@google.com> + + Reviewed by Darin Fisher. + + Add isGLES2Compliant to GraphicsContext3D: make the method const. + https://bugs.webkit.org/show_bug.cgi?id=37872 + + * platform/graphics/GraphicsContext3D.h: Make isGLES2Compliant() const. + * platform/graphics/mac/GraphicsContext3DMac.cpp: Ditto. + (WebCore::GraphicsContext3D::isGLES2Compliant): + +2010-04-23 Qi Zhang <qi.2.zhang@nokia.com> + + Reviewed by Laszlo Gombos. + + [Qt] LayoutTests/fast/canvas/pointInPath.html passed, actually it failed + https://bugs.webkit.org/show_bug.cgi?id=37276 + + QPainterPath::contains doesn't count the point on the bound. + + * platform/graphics/qt/PathQt.cpp: + (WebCore::isPointOnPathBorder): + (WebCore::Path::contains): + +2010-04-23 Sam Weinig <sam@webkit.org> + + Reviewed by David Levin. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38060 + Split up Threading.h + + Add necessary forwarding headers. + + * ForwardingHeaders/wtf/Atomics.h: Added. + * ForwardingHeaders/wtf/ThreadSafeShared.h: Added. + * ForwardingHeaders/wtf/ThreadingPrimitives.h: Added. + +2010-04-23 Rafael Weinstein <rafaelw@grafaelw.sfo.corp.google.com> + + Reviewed by Darin Fisher. + + This patch adds a vector of additionalFeatures to WindowFeatures + and populates it with any feature strings that evaluate to "yes" + and aren't directly observed in WindowFeatures. This allows + clients to capture experimental window features. + + https://bugs.webkit.org/show_bug.cgi?id=38013 + + * page/WindowFeatures.cpp: + (WebCore::WindowFeatures::setWindowFeature): + * page/WindowFeatures.h: + +2010-04-23 Dan Bernstein <mitz@apple.com> + + Reviewed by Simon Fraser. + + <rdar://problem/7898436> :after content is duplicated + + Test: fast/css-generated-content/after-duplicated-after-split.html + + * rendering/RenderInline.cpp: + (WebCore::RenderInline::splitInlines): Pass the correct owner of the child list. + +2010-04-23 Adele Peterson <adele@apple.com> + + Fixing the Tiger build for real. + + * platform/graphics/mac/SimpleFontDataMac.mm: + +2010-04-23 Adele Peterson <adele@apple.com> + + Fixing the Tiger build. + + * platform/graphics/mac/SimpleFontDataMac.mm: + (WebCore::SimpleFontData::platformBoundsForGlyph): + +2010-04-23 Jian Li <jianli@chromium.org> + + Reviewed by Dmitry Titov. + + Add FileError for File API. + https://bugs.webkit.org/show_bug.cgi?id=37840 + + The test will be added when implementing FileReader and FilerWriter. + + * Android.derived.jscbindings.mk: + * Android.derived.v8bindings.mk: + * DerivedSources.cpp: + * DerivedSources.make: + * GNUmakefile.am: + * WebCore.gypi: + * WebCore.pri: + * WebCore.pro: + * WebCore.vcproj/WebCore.vcproj: + * WebCore.xcodeproj/project.pbxproj: + * dom/ExceptionCode.h: + (WebCore::): + * html/FileError.h: Added. + * html/FileError.idl: Added. + * page/DOMWindow.idl: + +2010-04-23 Jian Li <jianli@chromium.org> + + Reviewed by Adam Barth. + + Improve code generator scripts to handle OR ('|') condition in the + extended attributes. + https://bugs.webkit.org/show_bug.cgi?id=37998 + + * bindings/scripts/CodeGeneratorJS.pm: + * bindings/scripts/CodeGeneratorObjC.pm: + * bindings/scripts/CodeGeneratorV8.pm: + * bindings/scripts/IDLStructure.pm: + +2010-04-23 Adele Peterson <adele@apple.com> + + Reviewed by Dan Bernstein. + + Fix for <rdar://problem/7855777> REGRESSION: Memory usage increase caused by storing glyph bounds in GlyphMetricsMap + https://bugs.webkit.org/show_bug.cgi?id=37936 + + This change breaks the GlyphMetricsMap into two maps - one for width and one for bounds, so that we don't store + a FloatRect for the glyph bounds unless we need to. + + Covered by existing tests. This should not cause any change in functionality. + + Updated for removal of GlyphMetricsMap.cpp + * Android.mk: + * GNUmakefile.am: + * WebCore.gypi: + * WebCore.vcproj/WebCore.vcproj: + * WebCore.xcodeproj/project.pbxproj: + + Made GlyphMetricsMap a template, so it can be used for separate width and bounds maps. + * platform/graphics/GlyphMetricsMap.cpp: Removed. + * platform/graphics/GlyphMetricsMap.h: + (WebCore::GlyphMetricsMap::metricsForGlyph): + (WebCore::GlyphMetricsMap::setMetricsForGlyph): + (WebCore::GlyphMetricsMap::GlyphMetricsPage::metricsForGlyph): + (WebCore::GlyphMetricsMap::GlyphMetricsPage::setMetricsForGlyph): + (WebCore::GlyphMetricsMap::GlyphMetricsPage::setMetricsForIndex): + (WebCore::::unknownMetrics): + (WebCore::::locatePageSlowCase): + + * platform/graphics/mac/ComplexTextController.cpp: (WebCore::ComplexTextController::adjustGlyphsAndAdvances): + Call boundsForGlyph instead of metricsForGlyph. + * platform/graphics/win/UniscribeController.cpp: (WebCore::UniscribeController::shapeAndPlaceItem): + ditto. + * platform/graphics/SimpleFontData.cpp: (WebCore::SimpleFontData::platformGlyphInit): + Call setMetricsForGlyph for both glyph maps. + + Break getters and setters for metricsForGlyph into widthForGlyph and boundsForGlyph, maintaining present behavior. + * platform/graphics/SimpleFontData.h: + (WebCore::): + (WebCore::SimpleFontData::boundsForGlyph): + (WebCore::SimpleFontData::widthForGlyph): + * platform/graphics/cairo/SimpleFontDataCairo.cpp: + (WebCore::SimpleFontData::platformBoundsForGlyph): + (WebCore::SimpleFontData::platformWidthForGlyph): + * platform/graphics/chromium/SimpleFontDataChromiumWin.cpp: + (WebCore::SimpleFontData::platformBoundsForGlyph): + (WebCore::SimpleFontData::platformWidthForGlyph): + * platform/graphics/chromium/SimpleFontDataLinux.cpp: + (WebCore::SimpleFontData::platformBoundsForGlyph): + (WebCore::SimpleFontData::platformWidthForGlyph): + * platform/graphics/gtk/SimpleFontDataPango.cpp: + (WebCore::SimpleFontData::platformBoundsForGlyph): + (WebCore::SimpleFontData::platformWidthForGlyph): + * platform/graphics/mac/SimpleFontDataMac.mm: + (WebCore::SimpleFontData::platformBoundsForGlyph): + (WebCore::SimpleFontData::platformWidthForGlyph): + * platform/graphics/win/SimpleFontDataCGWin.cpp: + (WebCore::SimpleFontData::platformBoundsForGlyph): + (WebCore::SimpleFontData::platformWidthForGlyph): + * platform/graphics/win/SimpleFontDataCairoWin.cpp: + (WebCore::SimpleFontData::platformBoundsForGlyph): + * platform/graphics/win/SimpleFontDataWin.cpp: + (WebCore::SimpleFontData::boundsForGDIGlyph): + (WebCore::SimpleFontData::widthForGDIGlyph): + * platform/graphics/wince/SimpleFontDataWince.cpp: + (WebCore::SimpleFontData::platformBoundsForGlyph): + * platform/graphics/wx/SimpleFontDataWx.cpp: + (WebCore::SimpleFontData::platformBoundsForGlyph): + (WebCore::SimpleFontData::platformWidthForGlyph): + +2010-04-23 Xiaomei Ji <xji@chromium.org> + + Reviewed by Dan Bernstein and Darin Adler + + Fix issue "caret does not paint after type in characters in right + aligned div or after delete all characters in RTL div or + 0px right padding RTL textarea" + https://bugs.webkit.org/show_bug.cgi?id=25319 + + Test: editing/inserting/caret-position.html + + * rendering/RenderText.cpp: + (WebCore::RenderText::localCaretRect): + +2010-04-23 No'am Rosenthal <noam.rosenthal@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] [Performance] GraphicsLayer: constructing the layers takes too long + https://bugs.webkit.org/show_bug.cgi?id=36365 + + The issue came from using QGraphicsView's cache as is. The problem is that + several code-paths require re-rendering of the item, but not re-rendering + of the web content into the cache. + + The way to solve it is by having GraphicsLayerQt manage the cache directly + via QPixmapCache, instead of using QGraphicsItem cache modes. + + FPS measurement shows significant improvement (20FPS before, 40FPS after) + on several use-cases, including blog-files/leaves on a desktop environment. + + * platform/graphics/qt/GraphicsLayerQt.cpp: + (WebCore::GraphicsLayerQtImpl::GraphicsLayerQtImpl): + (WebCore::GraphicsLayerQtImpl::recache): + (WebCore::GraphicsLayerQtImpl::paint): + (WebCore::GraphicsLayerQtImpl::flushChanges): + +2010-04-23 James Robinson <jamesr@chromium.org> + + Reviewed by Dimitri Glazkov. + + Avoid marking symbols as dllexport in chromium win builds + https://bugs.webkit.org/show_bug.cgi?id=38058 + + No new tests. + + * config.h: + +2010-04-23 MORITA Hajime <morrita@google.com> + + Reviewed by Nikolas Zimmermann. + + https://bugs.webkit.org/show_bug.cgi?id=37187 + SVG <use href="foo"> is interpreted as <use href="#foo"> + + getTarget() did return url parameter as is if doesn't have + fragment identifier. So fixed to return empty string in such case + because we need to distinguish "yyy.html" from "xxx.svg#yyy.html". + + Test: svg/custom/broken-internal-references.svg + + * svg/SVGElement.cpp: + (WebCore::SVGElement::insertedIntoDocument): + * svg/SVGURIReference.cpp: + (WebCore::SVGURIReference::getTarget): + +2010-04-23 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Dan Bernstein. + + ASSERT(willBeComposited == needsToBeComposited(layer)); on gmail.com + https://bugs.webkit.org/show_bug.cgi?id=38066 + + When a layer goes into compositing mode because it has a negative z-index child that is going + into compositing mode, then set willBeComposited to true. Also add another assertion to catch + any other cases where the state of willBeComposited is mismanaged. + + Test: compositing/composited-negative-zindex-child.html + + * rendering/RenderLayerCompositor.cpp: + (WebCore::RenderLayerCompositor::computeCompositingRequirements): + +2010-04-23 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Dan Bernstein. + + When webkitAnimationEnd event fires, on-screen rendering should show the last frame of animation + https://bugs.webkit.org/show_bug.cgi?id=37955 + + After r37484, animation and transition end events were fired on a timer, after the animation/transition + ended. This opened up one event loop cycle in which the non-animating state of the element was visible + before the event fired, resulting in flashes in content that reset style from the event handler. + + Fix by firing these events in the same event cycle as the animation end, once all animations + have been updated. This also required moving the place that start animations are fixed until + a later state in the state machine, so that animations have their start time set at the point + the event is fired (to avoid an assertion when using the freeze API in DRT). + + Not testable, since the flash is very transitory and cannot be captured in a pixel test. + + * page/animation/AnimationBase.cpp: + (WebCore::AnimationBase::updateStateMachine): Move the firing of 'start' events into the state + where the start time is known. + * page/animation/AnimationControllerPrivate.h: + * page/animation/AnimationController.cpp: + (WebCore::AnimationControllerPrivate::updateStyleIfNeededDispatcherFired): Call the new fireEventsAndUpdateStyle() + method. + (WebCore::AnimationControllerPrivate::fireEventsAndUpdateStyle): New method to share code that used to be in + updateStyleIfNeededDispatcherFired(). + (WebCore::AnimationControllerPrivate::animationTimerFired): Call fireEventsAndUpdateStyle() once we've + processed all animations. + +2010-04-23 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Dan Bernstein. + + CompositeAnimation::updateKeyframeAnimations() can make a KeyframeAnimation for animation "none" + https://bugs.webkit.org/show_bug.cgi?id=38017 + + Check to see if the animation name is "none", and don't fire off a keyframe animation in + that case. + + * page/animation/CompositeAnimation.cpp: + (WebCore::CompositeAnimation::updateKeyframeAnimations): + +2010-04-23 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Disable Netscape plugin support for minimal configuration + https://bugs.webkit.org/show_bug.cgi?id=38026 + + No new tests, as there is no new functionality. + + * WebCore.pri: + +2010-04-23 Shinichiro Hamaji <hamaji@chromium.org> + + Reviewed by Darin Adler. + + Need borderAndPadding(Width|Height) + https://bugs.webkit.org/show_bug.cgi?id=38046 + + Refactoring only, so no new tests. + + * rendering/InlineBox.cpp: + (WebCore::InlineBox::height): + * rendering/RenderApplet.cpp: + (WebCore::RenderApplet::createWidgetIfNecessary): + * rendering/RenderBlock.cpp: + (WebCore::RenderBlock::isSelfCollapsingBlock): + (WebCore::RenderBlock::calcPrefWidths): + * rendering/RenderBox.cpp: + (WebCore::RenderBox::calcBorderBoxWidth): + (WebCore::RenderBox::calcBorderBoxHeight): + (WebCore::RenderBox::calcContentBoxWidth): + (WebCore::RenderBox::calcContentBoxHeight): + (WebCore::RenderBox::calcWidth): + (WebCore::RenderBox::calcHeight): + (WebCore::RenderBox::calcPercentageHeight): + (WebCore::RenderBox::calcReplacedHeightUsing): + (WebCore::RenderBox::availableHeightUsing): + (WebCore::RenderBox::calcAbsoluteHorizontal): + (WebCore::RenderBox::calcAbsoluteVertical): + (WebCore::RenderBox::calcAbsoluteHorizontalReplaced): + (WebCore::RenderBox::calcAbsoluteVerticalReplaced): + (WebCore::RenderBox::positionForPoint): + * rendering/RenderBoxModelObject.h: + (WebCore::RenderBoxModelObject::borderAndPaddingHeight): + (WebCore::RenderBoxModelObject::borderAndPaddingWidth): + * rendering/RenderDataGrid.cpp: + (WebCore::RenderDataGrid::calcPrefWidths): + * rendering/RenderFieldset.cpp: + (WebCore::RenderFieldset::calcPrefWidths): + * rendering/RenderFileUploadControl.cpp: + (WebCore::RenderFileUploadControl::calcPrefWidths): + * rendering/RenderFlexibleBox.cpp: + (WebCore::RenderFlexibleBox::calcPrefWidths): + (WebCore::RenderFlexibleBox::allowedChildFlex): + * rendering/RenderImage.cpp: + (WebCore::RenderImage::calcPrefWidths): + * rendering/RenderLayer.cpp: + (WebCore::RenderLayer::resize): + * rendering/RenderListBox.cpp: + (WebCore::RenderListBox::calcPrefWidths): + (WebCore::RenderListBox::calcHeight): + * rendering/RenderMenuList.cpp: + (WebCore::RenderMenuList::calcPrefWidths): + * rendering/RenderReplaced.cpp: + (WebCore::RenderReplaced::calcPrefWidths): + * rendering/RenderSVGRoot.cpp: + (WebCore::RenderSVGRoot::calcPrefWidths): + * rendering/RenderSlider.cpp: + (WebCore::RenderSlider::calcPrefWidths): + (WebCore::RenderSlider::layout): + * rendering/RenderTableCell.cpp: + (WebCore::RenderTableCell::styleOrColWidth): + * rendering/RenderTextControl.cpp: + (WebCore::RenderTextControl::textBlockHeight): + (WebCore::RenderTextControl::textBlockWidth): + (WebCore::RenderTextControl::calcHeight): + (WebCore::RenderTextControl::calcPrefWidths): + * rendering/RenderTextControlSingleLine.cpp: + (WebCore::RenderTextControlSingleLine::layout): + * rendering/RenderWidget.cpp: + (WebCore::RenderWidget::updateWidgetPosition): + +2010-04-23 David Kilzer <ddkilzer@apple.com> + + Size mismatch between format string and argument in dumpTextEncodingNameMap() + + Reviewed by Darin Adler. + + See Bug 38030 and r58157. + + * platform/text/TextEncodingRegistry.cpp: + (WebCore::dumpTextEncodingNameMap): Assigned + textEncodingNameMap->size() to an unsigned variable before using + it in the fprintf() statement. + +2010-04-23 David Kilzer <ddkilzer@apple.com> + + BUILD FIX: Attempt to fix Windows build after Bug 36187 landed in r58168 + + * DerivedSources.cpp: Changed include of JSMedia.cpp to + JSStyleMedia.cpp. + +2010-04-23 David Kilzer <ddkilzer@apple.com> + + BUILD FIX: Fix Mac build after Bug 36187 landed in r58168 + + * WebCore.xcodeproj/project.pbxproj: Renamed DOMMedia.h, + DOMMedia.mm, DOMMediaInternal.h to DOMStyleMedia.h, + DOMStyleMedia.mm, DOMStyleMediaInternal.h. + +2010-04-23 Kenneth Rohde Christiansen <kenneth@webkit.org> + + Unreviewed build fix. + + Change Media to StyleMedia + + * DerivedSources.make: + +2010-04-23 Xan Lopez <xlopez@igalia.com> + + Try to fix the GTK+ bots. + + * GNUmakefile.am: + +2010-04-22 Kenneth Rohde Christiansen <kenneth@webkit.org> + + Reviewed by Laszlo Gombos. + + Rename window.media to window.styleMedia + https://bugs.webkit.org/show_bug.cgi?id=36187 + + Rename the interface Media to StyleMedia as required by the + new CSSOM View spec. + + * Android.derived.jscbindings.mk: + * Android.derived.v8bindings.mk: + * GNUmakefile.am: + * WebCore.gypi: + * WebCore.pri: + * WebCore.pro: + * WebCore.vcproj/WebCore.vcproj: + * WebCore.xcodeproj/project.pbxproj: + * css/Media.cpp: Removed. + * css/Media.h: Removed. + * css/Media.idl: Removed. + * css/StyleMedia.cpp: Added. + (WebCore::StyleMedia::StyleMedia): + (WebCore::StyleMedia::type): + (WebCore::StyleMedia::matchMedium): + * css/StyleMedia.h: Added. + (WebCore::StyleMedia::create): + (WebCore::StyleMedia::disconnectFrame): + * css/StyleMedia.idl: Added. + * page/DOMWindow.cpp: + (WebCore::DOMWindow::styleMedia): + * page/DOMWindow.h: + (WebCore::DOMWindow::optionalMedia): + * page/DOMWindow.idl: + +2010-04-23 Yury Semikhatsky <yurys@chromium.org> + + Reviewed by Pavel Feldman. + + Web Inspector: provide JSC implementation for scopeType method on + call frame and use same jsvascript code for JSC and v8 when collecting + scope chain data. + + https://bugs.webkit.org/show_bug.cgi?id=37663 + + * bindings/js/JSInjectedScriptHostCustom.cpp: + (WebCore::JSInjectedScriptHost::currentCallFrame): + * bindings/js/JSJavaScriptCallFrameCustom.cpp: + (WebCore::JSJavaScriptCallFrame::scopeType): + * bindings/v8/custom/V8InjectedScriptHostCustom.cpp: + (WebCore::V8InjectedScriptHost::currentCallFrameCallback): + * inspector/InjectedScriptHost.idl: + * inspector/front-end/InjectedScript.js: + (injectedScriptConstructor.): + +2010-04-23 Alexander Pavlov <apavlov@chromium.org> + + Reviewed by Pavel Feldman. + + Web Inspector: Audits (Image Dimensions): full image URLs are prefixed with the hosting page name + https://bugs.webkit.org/show_bug.cgi?id=37988 + + * inspector/front-end/AuditRules.js: + (WebInspector.AuditRules.ImageDimensionsRule.prototype.doRun): + +2010-04-23 Ilya Tikhonovsky <loislo@chromium.org> + + Reviewed by Yury Semikhatsky. + + WebInspector: Flaky Inspector tests. + https://bugs.webkit.org/show_bug.cgi?id=36217 + + * inspector/InspectorController.cpp: + (WebCore::InspectorController::didCommitLoad): + +2010-04-23 Yaar Schnitman <yaar@chromium.org> + + Reviewed by Adam Barth. + + Auto-generate WebGLRenderingContext overloads in V8 + https://bugs.webkit.org/show_bug.cgi?id=37818 + + * bindings/v8/custom/V8WebGLRenderingContextCustom.cpp: + * html/canvas/WebGLRenderingContext.cpp: Added missing overloads for the following:. + (WebCore::WebGLRenderingContext::texImage2D) + (WebCore::WebGLRenderingContext::texSubImage2D) + * html/canvas/WebGLRenderingContext.h: Added missing overloads. + * html/canvas/WebGLRenderingContext.idl: IDL definition of overloads. + +2010-04-23 Jeff Schiller <codedread@gmail.com> + + Reviewed by Nikolas Zimmermann. + + Display tooltips when hovering over SVG elements, Bug 16854 + https://bugs.webkit.org/show_bug.cgi?id=16854 + + Manual test added for verifying tooltips. + + * manual-tests/svg-tooltip.svg: Added. + * svg/SVGAElement.cpp: + (WebCore::SVGAElement::title): xlink:title takes precedence, otherwise SVGStyledElement::title() is used + * svg/SVGStyledElement.cpp: + (WebCore::SVGStyledElement::title): checks for a shadow parent and uses that title, otherwise uses the content's title + * svg/SVGStyledElement.h: add title() method declaration + +2010-04-23 David Kilzer <ddkilzer@apple.com> + + <http://webkit.org/b/38032> No need to content sniff 304 responses + <rdar://problem/7891726> + + Reviewed by Brady Eidson. + + * platform/network/mac/ResourceHandleMac.mm: + (-[WebCoreResourceHandleAsDelegate connection:didReceiveResponse:]): + No need to adjust the MIME type on 304 responses since they're + only used to determine if the resource needs to be refetched. + +2010-04-23 David Kilzer <ddkilzer@apple.com> + + <http://webkit.org/b/38030> Add WebCore::dumpTextEncodingNameMap() to dump text encoding map on debug builds + + Reviewed by Alexey Proskuryakov. + + * platform/text/TextEncodingRegistry.cpp: + (WebCore::dumpTextEncodingNameMap): Added. + * platform/text/TextEncodingRegistry.h: + (WebCore::dumpTextEncodingNameMap): Added declaration. + +2010-04-22 Tony Chang <tony@chromium.org> + + Reviewed by Dan Bernstein. + + Crash in WebCore::TextIterator::handleTextNode() encountered in Google rich-text products + https://bugs.webkit.org/show_bug.cgi?id=37950 + + Test: editing/text-iterator/rtl-selection-crash.html + + * editing/TextIterator.cpp: + (WebCore::TextIterator::handleTextNode): + +2010-04-22 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Dan Bernstein and Beth Dakin. + + Links around blocks (e.g. divs) results in too many VoiceOver call outs + https://bugs.webkit.org/show_bug.cgi?id=37079 + <rdar://problem/7234118> + + The basic change is to modify the AccessibilityRenderObject tree + traversal methods to account for inline continuations in the + render tree and make the accessibility tree look as if + continuations didn't exist - the same as if CSS blocks could just + sit in CSS inlines. This is slightly tricky code but creates a + much saner accessibility tree. + + Tests: accessibility/image-link-inline-cont.html + accessibility/image-link.html + accessibility/inline-continuations.html + + * accessibility/AccessibilityRenderObject.cpp: + (WebCore::isInlineWithContinuation): Helper function for traversal functions to use in accounting for continuations. + (WebCore::firstChildInContinuation): ditto + (WebCore::firstChildConsideringContinuation): ditto + (WebCore::lastChildConsideringContinuation): ditto + (WebCore::startOfContinuations): ditto + (WebCore::endOfContinuations): ditto + (WebCore::childBeforeConsideringContinuations): ditto + (WebCore::firstChildIsInlineContinuation): ditto + (WebCore::lastChildHasContinuation): ditto + (WebCore::AccessibilityRenderObject::firstChild): Account for inline continuations. + (WebCore::AccessibilityRenderObject::lastChild): ditto + (WebCore::AccessibilityRenderObject::previousSibling): Account for inline continuations + and their anonymous block parents. + (WebCore::AccessibilityRenderObject::nextSibling): ditto + (WebCore::AccessibilityRenderObject::parentObjectIfExists): Account for inline continuations. + (WebCore::AccessibilityRenderObject::parentObject): Account for inline continuations. + * rendering/RenderInline.h: Make RenderInline::inlineContinuation public. + +2010-04-22 Shinichiro Hamaji <hamaji@chromium.org> + + Reviewed by Darin Adler. + + REGRESSION: TextIterator may use freed memory + https://bugs.webkit.org/show_bug.cgi?id=37973 + + Added TextIterator::m_text to hold the returned String. + + No new tests because there are no behavior change, but + copy-backslash-with-euc.html on chromium-win should test this. + + * editing/TextIterator.cpp: + (WebCore::TextIterator::emitText): + * editing/TextIterator.h: + +2010-04-22 Michael Forney <mforney@mforney.org> + + Reviewed by Adam Barth. + + https://bugs.webkit.org/show_bug.cgi?id=37761 + + Only include JSDatabase.h and JSDatabaseCallback.h when database is + enabled. This partially fixes building with --disable-database. + + * bindings/js/JSDOMWindowCustom.cpp: Add a check for database around + database-related headers. + +2010-04-22 Ray Rischpater <Raymond.Rischpater@Nokia.com> + + Reviewed by Darin Adler. + + In HTMLInputElement.cpp, shouldUseInputMethod does not return true for + some text input types (TELEPHONE, NUMBER, URL, and EMAIL). Addressed + this by changing shouldUseInputMethod to use internal methods to + check that the field is a text field that isn't a password field. + + No new tests. + + Fixes <https://bugs.webkit.org/show_bug.cgi?id=37719> + + * html/HTMLInputElement.cpp: + (WebCore::HTMLInputElement::shouldUseInputMethod): + +2010-04-22 Yaar Schnitman <yaar@chromium.org> + + Reviewed by Adam Barth. + + Integrate v8 testing utility with webkit tests + https://bugs.webkit.org/show_bug.cgi?id=37731 + + * bindings/v8/test/run_tests.py: Removed. + +2010-04-22 Zhenyao Mo <zmo@google.com> + + Reviewed by Darin Fisher. + + Add isGLES2Compliant to GraphicsContext3D + https://bugs.webkit.org/show_bug.cgi?id=37872 + + * html/canvas/WebGLRenderingContext.cpp: Add isGLES2Compliant(). + (WebCore::WebGLRenderingContext::isGLES2Compliant): + * html/canvas/WebGLRenderingContext.h: Ditto. + * platform/graphics/GraphicsContext3D.h: Ditto. + * platform/graphics/mac/GraphicsContext3DMac.cpp: Ditto. + (WebCore::GraphicsContext3D::isGLES2Compliant): + +2010-04-22 Fumitoshi Ukai <ukai@chromium.org> + + Reviewed by Adam Barth. + + MD5 is required for WebSocket new protocol implementation + https://bugs.webkit.org/show_bug.cgi?id=37913 + + * ForwardingHeaders/wtf/MD5.h: Added. + +2010-04-22 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=38012 + REGRESSION: Ctrl- and Option- shortcuts get wrong keyCode on non-QWERTY keyboard + + * platform/mac/KeyEventMac.mm: (WebCore::windowsKeyCodeForKeyEvent): Also look at unmodified + characters, to avoid falling through to virtual key code lookup for Roman characters. + +2010-04-22 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Darin Adler. + + Fix the MSVC 64bit build. + https://bugs.webkit.org/show_bug.cgi?id=37980 + + * platform/text/TextStream.cpp: + * platform/text/TextStream.h: + * plugins/win/PluginViewWin.cpp: + (WebCore::PluginView::platformStart): + +2010-04-22 Dave Moore <davemoore@chromium.org> + + Reviewed by Dimitri Glazkov. + + Added notification when the favicons for a page are changed + from a script. + The Document object will notify the frame loader, which will + notify the client. Implementations of FrameLoaderClient will + have to add one method; dispatchDidChangeIcons(). + + https://bugs.webkit.org/show_bug.cgi?id=33812 + + Test: fast/dom/icon-url-property.html + + * dom/Document.cpp: + (WebCore::Document::setIconURL): + * loader/DocumentLoader.cpp: + (WebCore::DocumentLoader::setIconURL): + * loader/DocumentLoader.h: + (WebCore::DocumentLoader::iconURL): + * loader/EmptyClients.h: + (WebCore::EmptyFrameLoaderClient::dispatchDidChangeIcons): + * loader/FrameLoader.cpp: + (WebCore::FrameLoader::setIconURL): + (WebCore::FrameLoader::didChangeIcons): + * loader/FrameLoader.h: + * loader/FrameLoaderClient.h: + +2010-04-22 Xan Lopez <xlopez@igalia.com> + + Reviewed by Gustavo Noronha. + + [GTK] GObject DOM bindings + https://bugs.webkit.org/show_bug.cgi?id=33590 + + Extend the bindings to cover most of Document.idl + + * GNUmakefile.am: + * bindings/gobject/WebKitDOMBinding.cpp: + (WebKit::createWrapper): + (WebKit::kit): + * bindings/gobject/WebKitDOMBinding.h: + * bindings/gobject/WebKitHTMLElementWrapperFactory.cpp: Added. + (WebKit::createAnchorWrapper): + (WebKit::createAppletWrapper): + (WebKit::createAreaWrapper): + (WebKit::createBaseWrapper): + (WebKit::createBaseFontWrapper): + (WebKit::createBlockquoteWrapper): + (WebKit::createBodyWrapper): + (WebKit::createBRWrapper): + (WebKit::createButtonWrapper): + (WebKit::createCanvasWrapper): + (WebKit::createTableCaptionWrapper): + (WebKit::createTableColWrapper): + (WebKit::createModWrapper): + (WebKit::createDirectoryWrapper): + (WebKit::createDivWrapper): + (WebKit::createDListWrapper): + (WebKit::createEmbedWrapper): + (WebKit::createFieldSetWrapper): + (WebKit::createFontWrapper): + (WebKit::createFormWrapper): + (WebKit::createFrameWrapper): + (WebKit::createFrameSetWrapper): + (WebKit::createHeadingWrapper): + (WebKit::createHeadWrapper): + (WebKit::createHRWrapper): + (WebKit::createHtmlWrapper): + (WebKit::createIFrameWrapper): + (WebKit::createImageWrapper): + (WebKit::createInputWrapper): + (WebKit::createIsIndexWrapper): + (WebKit::createLabelWrapper): + (WebKit::createLegendWrapper): + (WebKit::createLIWrapper): + (WebKit::createLinkWrapper): + (WebKit::createMapWrapper): + (WebKit::createMarqueeWrapper): + (WebKit::createMenuWrapper): + (WebKit::createMetaWrapper): + (WebKit::createObjectWrapper): + (WebKit::createOListWrapper): + (WebKit::createOptGroupWrapper): + (WebKit::createOptionWrapper): + (WebKit::createParagraphWrapper): + (WebKit::createParamWrapper): + (WebKit::createPreWrapper): + (WebKit::createQuoteWrapper): + (WebKit::createScriptWrapper): + (WebKit::createSelectWrapper): + (WebKit::createStyleWrapper): + (WebKit::createTableWrapper): + (WebKit::createTableSectionWrapper): + (WebKit::createTableCellWrapper): + (WebKit::createTextAreaWrapper): + (WebKit::createTitleWrapper): + (WebKit::createTableRowWrapper): + (WebKit::createUListWrapper): + (WebKit::createHTMLElementWrapper): + * bindings/gobject/WebKitHTMLElementWrapperFactory.h: Added. + * bindings/scripts/CodeGeneratorGObject.pm: + * dom/Node.idl: + +2010-04-22 Eric Carlson <eric.carlson@apple.com> + + Reviewed by Simon Fraser. + + Do not pause movie when readyState drops below HAVE_FUTURE_DATA + https://bugs.webkit.org/show_bug.cgi?id=37991 + <rdar://problem/7893937> + + No new tests, we don't have infrastructure in DRT to test with streamed + movies. + + * html/HTMLMediaElement.cpp: + (WebCore::HTMLMediaElement::HTMLMediaElement): Initialize m_readyStateMaximum. + (WebCore::HTMLMediaElement::prepareForLoad): Reset m_readyStateMaximum. + (WebCore::HTMLMediaElement::setReadyState): Maintain m_readyStateMaximum. + (WebCore::HTMLMediaElement::potentiallyPlaying): Also return true if the readyState was + previously >= HAVE_FUTURE_DATA. + * html/HTMLMediaElement.h: + +2010-04-22 Zhenyao Mo <zmo@google.com> + + Reviewed by Dimitri Glazkov. + + Regression: framebufferRenderbuffer crashes with null renderBuffer + https://bugs.webkit.org/show_bug.cgi?id=37963 + + * html/canvas/WebGLRenderingContext.cpp: + (WebCore::WebGLRenderingContext::framebufferRenderbuffer): Dealing with null renderbuffer input. + +2010-04-22 Zhenyao Mo <zmo@google.com> + + Reviewed by Dimitri Glazkov. + + Emulate GL_IMPLEMENTATION_COLOR_READ_FORMAT/TYPE for glGet + https://bugs.webkit.org/show_bug.cgi?id=37281 + + * html/canvas/WebGLRenderingContext.cpp: + (WebCore::WebGLRenderingContext::WebGLRenderingContext): Remove error check because two enums are supported now. + (WebCore::WebGLRenderingContext::getParameter): Add two enums. + (WebCore::WebGLRenderingContext::readPixels): Fix a tiny bug. + * platform/graphics/mac/GraphicsContext3DMac.cpp: + (WebCore::GraphicsContext3D::getIntegerv): Emulate two enums. + +2010-04-22 Diego Escalante Urrelo <descalante@igalia.com> + + Reviewed by Xan Lopez. + + [GTK] Mute/unmute button on <video> elements are backwards + https://bugs.webkit.org/show_bug.cgi?id=33967 + + Fix mute/unmute buttons icons-action relation and explain why their + variable names and corresponding icons seem to be misleading but are + actually right. Original patch by Mike Hommey. + + * platform/gtk/RenderThemeGtk.cpp: + (WebCore::RenderThemeGtk::initMediaStyling): + +2010-04-22 Gustavo Sverzut Barbieri <barbieri@profusion.mobi> + + Reviewed by Eric Seidel. + + Fix build if NPAPI support is disabled + https://bugs.webkit.org/show_bug.cgi?id=36621 + + No new tests, this is a build fix. + Re-submit r58043 with fix for EFL. + + * plugins/PluginViewNone.cpp: + +2010-04-22 Diego Escalante Urrelo <descalante@igalia.com> + + Reviewed by Xan Lopez. + + [Gtk] Evaluate and create tests for all the AtkRole's implemented by + WebKitGtk + https://bugs.webkit.org/show_bug.cgi?id=34449 + + Implement ATK_ROLE_COMBO_BOX. + + * accessibility/gtk/AccessibilityObjectAtk.cpp: + (WebCore::AccessibilityObject::accessibilityPlatformIncludesObject): + * accessibility/gtk/AccessibilityObjectWrapperAtk.cpp: + (atkRole): + +2010-04-22 Nikolas Zimmermann <nzimmermann@rim.com> + + Reviewed by Dirk Schulze. + + SVGPaintServer needs to be converted to the new RenderSVGResource* system + https://bugs.webkit.org/show_bug.cgi?id=37986 + + No functional changes, just move the SVGPaintServer* classes from svg/graphics/ to rendering/, the new location for the RenderSVGResource* classes. + This is a preparation for the real patch which follows soon. + + * Android.mk: Rename files and move to the right location. + * GNUmakefile.am: Ditto. + * WebCore.gypi: Ditto. + * WebCore.pro: Ditto. + * WebCore.vcproj/WebCore.vcproj: Ditto. + * WebCore.xcodeproj/project.pbxproj: Ditto. + * rendering/RenderSVGResource.cpp: Copied from svg/graphics/SVGPaintServer.cpp. + * rendering/RenderSVGResourceGradient.cpp: Copied from svg/graphics/SVGPaintServerGradient.cpp. + * rendering/RenderSVGResourceGradient.h: Copied from svg/graphics/SVGPaintServerGradient.h. + * rendering/RenderSVGResourceLinearGradient.cpp: Copied from svg/graphics/SVGPaintServerLinearGradient.cpp. + * rendering/RenderSVGResourceLinearGradient.h: Copied from svg/graphics/SVGPaintServerLinearGradient.h. + * rendering/RenderSVGResourcePattern.cpp: Copied from svg/graphics/SVGPaintServerPattern.cpp. + * rendering/RenderSVGResourcePattern.h: Copied from svg/graphics/SVGPaintServerPattern.h. + * rendering/RenderSVGResourceRadialGradient.cpp: Copied from svg/graphics/SVGPaintServerRadialGradient.cpp. + * rendering/RenderSVGResourceRadialGradient.h: Copied from svg/graphics/SVGPaintServerRadialGradient.h. + * rendering/RenderSVGResourceSolidColor.cpp: Copied from svg/graphics/SVGPaintServerSolid.cpp. + * rendering/RenderSVGResourceSolidColor.h: Copied from svg/graphics/SVGPaintServerSolid.h. + * rendering/SVGRenderTreeAsText.cpp: Change include file names. + * svg/SVGFont.cpp: Ditto. + * svg/SVGGradientElement.cpp: Ditto. + * svg/SVGGradientElement.h: Ditto. + * svg/SVGLinearGradientElement.cpp: Ditto. + * svg/SVGPatternElement.cpp: Ditto. + * svg/SVGPatternElement.h: Ditto. + * svg/SVGRadialGradientElement.cpp: Ditto. + * svg/graphics/SVGPaintServer.cpp: Removed. + * svg/graphics/SVGPaintServerGradient.cpp: Removed. + * svg/graphics/SVGPaintServerGradient.h: Removed. + * svg/graphics/SVGPaintServerLinearGradient.cpp: Removed. + * svg/graphics/SVGPaintServerLinearGradient.h: Removed. + * svg/graphics/SVGPaintServerPattern.cpp: Removed. + * svg/graphics/SVGPaintServerPattern.h: Removed. + * svg/graphics/SVGPaintServerRadialGradient.cpp: Removed. + * svg/graphics/SVGPaintServerRadialGradient.h: Removed. + * svg/graphics/SVGPaintServerSolid.cpp: Removed. + * svg/graphics/SVGPaintServerSolid.h: Removed. + * svg/graphics/SVGResourceListener.h: Removed. + +2010-04-22 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Hide the OpenGL and QtMultimedia dependencies from syncqt. + + This prevents the dependent headers from being included by + qt/include/QtWebKit/QtWebKit + + * WebCore.pro: + +2010-04-22 Gustavo Sverzut Barbieri <barbieri@profusion.mobi> + + Reviewed by Adam Roben. + + EFL does not support PluginDatabase yet. + http://webkit.org/b/37854 + + No behavior changes, so no new tests were added. + + * loader/FrameLoader.cpp: + (WebCore::FrameLoader::defaultObjectContentType): + +2010-04-22 Ilya Tikhonovsky <loislo@chromium.org> + + Reviewed by Yury Semikhatsky. + + Web Inspector: Timeline scrolling speed is slow if it has more than 1k timeline marks. + https://bugs.webkit.org/show_bug.cgi?id=37924 + + * inspector/front-end/TimelineGrid.js: + (WebInspector.TimelineGrid.prototype.updateDividers): + (WebInspector.TimelineGrid.prototype.addEventDividers): + * inspector/front-end/TimelineOverviewPane.js: + (WebInspector.TimelineOverviewPane.prototype.updateEventDividers): + * inspector/front-end/TimelinePanel.js: + (WebInspector.TimelinePanel.prototype._updateEventDividers): + (WebInspector.TimelinePanel.prototype._refresh): + +2010-04-22 Kenneth Rohde Christiansen <kenneth@webkit.org> + + Reviewed by Simon Fraser. + + Rename window.media to window.styleMedia + https://bugs.webkit.org/show_bug.cgi?id=36187 + + It has been defined that the AbstractView media extension + defined in the CSSOM View spec should be renamed to styleMedia. + This patch does that and updates the current layout tests + making use of it. + + * page/AbstractView.idl: + * page/DOMWindow.cpp: + (WebCore::DOMWindow::styleMedia): + * page/DOMWindow.h: + * page/DOMWindow.idl: + +2010-04-22 Anton Muhin <antonm@chromium.org> + + Reviewed by Adam Barth. + + [v8] Do not pass empty handle into SetHiddenValue which would crash. + https://bugs.webkit.org/show_bug.cgi?id=37801 + + * bindings/v8/V8AbstractEventListener.cpp: + (WebCore::V8AbstractEventListener::handleEvent): add couple of asserts to check for unexpected paths + (WebCore::V8AbstractEventListener::invokeEventHandler): bail out of jsEvent is empty handle + +2010-04-22 Stephan Aßmus <superstippi@gmx.de> + + Reviewed by David Levin. + + [Haiku] Implement ImageBuffer support + https://bugs.webkit.org/show_bug.cgi?id=35288 + + Covered by existing tests. + + Complete implementation of ImageBuffer for Haiku. Uses StillImage + class to export a WebCore::Image and associated GraphicsContext + to perform arbitrary drawing in the offscreen BBitmap buffer. + + * platform/graphics/haiku/ImageBufferData.h: + * platform/graphics/haiku/ImageBufferHaiku.cpp, + (WebCore::ImageBufferData::ImageBufferData), + (WebCore::ImageBufferData::~ImageBufferData), + (WebCore::ImageBuffer::ImageBuffer), + (WebCore::ImageBuffer::~ImageBuffer), + (WebCore::ImageBuffer::context), + (WebCore::ImageBuffer::image): + Implementation uses offscreen BBitmap and BView, wraps StillImage + around those to provide WebCore::Image interface. + (WebCore::ImageBuffer::platformTransformColorSpace): + (WebCore::convertFromData): + Method just performs BGRA <-> RGBA conversion. + (WebCore::convertFromInternalData): + Method just performs BGRA <-> RGBA conversion and handles + pre-multiplying the color values if requested. + (WebCore::convertToInternalData): + Method just performs BGRA <-> RGBA conversion and handles + de.multiplying the color values if requested. + (WebCore::getImageData): + Common code for the next two methods. + (WebCore::ImageBuffer::getUnmultipliedImageData), + (WebCore::ImageBuffer::getPremultipliedImageData): + Implemented. + (WebCore::putImageData): + Common code for the next two methods. + (WebCore::ImageBuffer::putUnmultipliedImageData), + (WebCore::ImageBuffer::putPremultipliedImageData): + Implemented. + (WebCore::ImageBuffer::toDataURL): + Uses Haiku "Translation Kit" to convert image data to data + of the requested mime type. + +2010-04-22 Adam Barth <abarth@webkit.org> + + Unreviewed, rolling out r58069. + http://trac.webkit.org/changeset/58069 + https://bugs.webkit.org/show_bug.cgi?id=27751 + + Broke compile on Windows. + + * WebCore.base.exp: + * editing/EditorCommand.cpp: + (WebCore::supportedPaste): + (WebCore::createCommandMap): + * page/Settings.cpp: + (WebCore::Settings::Settings): + * page/Settings.h: + +2010-04-22 Abhishek Arya <inferno@chromium.org> + + Reviewed by Adam Barth. + + Add support for controlling clipboard access from javascript. + Clipboard access from javascript is disabled by default. + https://bugs.webkit.org/show_bug.cgi?id=27751 + + Test: editing/execCommand/clipboard-access.html + + * WebCore.base.exp: + * editing/EditorCommand.cpp: + (WebCore::supportedCopyCut): + (WebCore::supportedPaste): + (WebCore::createCommandMap): + * page/Settings.cpp: + (WebCore::Settings::Settings): + (WebCore::Settings::setJavaScriptCanAccessClipboard): + * page/Settings.h: + (WebCore::Settings::javaScriptCanAccessClipboard): + +2010-04-22 Stephan Aßmus <superstippi@gmx.de> + + Reviewed by David Levin. + + [Haiku] Improve SimpleFontDataHaiku + https://bugs.webkit.org/show_bug.cgi?id=37411 + + Covered by existing tests. + + * platform/graphics/haiku/SimpleFontDataHaiku.cpp: + - Cleaned up includes + - Removed prototype "charUnicodeToUTF8HACK" + (WebCore::SimpleFontData::platformInit): + - Use const BFont pointer + (WebCore::SimpleFontData::smallCapsFontData): + - "fontPlatformData" was leaked. It is only + used as the key for the font cache lookup. + (WebCore::SimpleFontData::platformMetricsForGlyph): + - Use existing WebCore encoding infrastructure + instead of adding a hack for Haiku. + +2010-04-21 Steve Block <steveblock@google.com> + + Reviewed by Kenneth Rohde Christiansen. + + Replace Geolocation::suspend()/resume() which are required by Android. + https://bugs.webkit.org/show_bug.cgi?id=37942 + + These methods were removed in Bug 36255. + + Build fix only, no new tests. + + * page/Geolocation.cpp: + (WebCore::Geolocation::suspend): + (WebCore::Geolocation::resume): + * page/Geolocation.h: + +2010-04-21 Ray Rischpater <Raymond.Rischpater@Nokia.com> + + In HTMLInputElement.cpp there are numerous style + violations. + + This patch includes style changes to fix existing style + deviations in this file. + + Rubber stamped by Darin Adler. + + Fixes <https://bugs.webkit.org/show_bug.cgi?id=37881> + + * html/HTMLInputElement.cpp: + +2010-04-21 Gustavo Sverzut Barbieri <barbieri@profusion.mobi> + + Reviewed by Adam Roben. + + Add missing EFL WebCore file. + http://webkit.org/b/37854 + + No behavior changes, so no new tests were added. + + * bindings/js/ScriptControllerEfl.cpp: Added. + (WebCore::ScriptController::createScriptInstanceForWidget): + +2010-04-21 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Dan Bernstein. + + Printing Core Animation-based plug-ins is broken + https://bugs.webkit.org/show_bug.cgi?id=37967 + + When we do a "flattening" paint because of printing, we need to stash + the flattening flag in the FrameView's m_paintBehavior, because + WebBaseNetscapePluginView needs to find it there to decide whether + to grab a bitmap for printing, for CA plug-ins. + + * page/FrameView.cpp: + (WebCore::FrameView::paintContents): + +2010-04-21 François Sausset <sausset@gmail.com> + + Reviewed by Kenneth Rohde Christiansen. + + Fix to take into account a change made in "StringImpl". + https://bugs.webkit.org/show_bug.cgi?id=37763 + + * mathml/RenderMathMLOperator.cpp: + (WebCore::RenderMathMLOperator::updateFromElement): + +2010-04-21 Andy Estes <aestes@apple.com> + + Reviewed by Darin Adler. + + Create a template for creating reference-counted Windows GDI handles. + Refactor RefCountedHFONT to use this template. + + https://bugs.webkit.org/show_bug.cgi?id=37952 + + No change in behavior. + + * WebCore.vcproj/WebCore.vcproj: Add RefCountedHFONT.h + * platform/graphics/cairo/FontPlatformData.h: + (WebCore::FontPlatformData::hfont): Refactor to return m_hfont->handle() instead of m_hfont->hfont(). + * platform/graphics/cg/FontPlatformData.h: + (WebCore::FontPlatformData::hfont): Same. + * platform/graphics/win/FontPlatformDataCGWin.cpp: + (WebCore::FontPlatformData::FontPlatformData): Instantiate m_hfont with a RefCountedGDIHandle<HFONT>. + * platform/graphics/win/FontPlatformDataWin.cpp: + (WebCore::FontPlatformData::FontPlatformData): Same. + * platform/graphics/win/RefCountedGDIHandle.h: Added. Interface is identical to RefCountedHFONT with exception of renaming hfont() to handle(). + (WebCore::RefCountedGDIHandle::create): + (WebCore::RefCountedGDIHandle::createDeleted): + (WebCore::RefCountedGDIHandle::~RefCountedGDIHandle): + (WebCore::RefCountedGDIHandle::handle): Return the GDI handle. + (WebCore::RefCountedGDIHandle::hash): + (WebCore::RefCountedGDIHandle::RefCountedGDIHandle): + * platform/graphics/win/RefCountedHFONT.h: Removed. + +2010-04-21 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Darin Adler. + + Fix build if NPAPI support is disabled + https://bugs.webkit.org/show_bug.cgi?id=36621 + + No new tests, this is a build fix. + Re-submit r56585 with fix for Chromium. + + * plugins/PluginView.cpp: Guard getValueStatic() with + NETSCAPE_PLUGIN_API + (WebCore::PluginView::getValue): + * plugins/PluginView.h: Guard getValue() with NETSCAPE_PLUGIN_API + * plugins/PluginViewNone.cpp: Guard platformGetValue() and + platformGetValueStatic with NETSCAPE_PLUGIN_API; + Guard privateBrowsingStateChanged() and setJavaScriptPaused() with + PLATFORM(MAC) or PLATFORM(CHROMIUM) + +2010-04-21 David Yonge-Mallo <davinci@chromium.org> + + Reviewed by Dan Bernstein. + + ZWNJ - Display non-printing, invisible character + https://bugs.webkit.org/show_bug.cgi?id=16131 + + Fix the (non)display of glyphs for ZWJ and ZWNJ in simple font code path. + + Tests: fast/text/format-control.html + fast/text/zero-width-characters.html + + * platform/graphics/Font.h: + (WebCore::Font::operator!=): + (WebCore::Font::treatAsZeroWidthSpace): treat ZWNJ and ZWJ as ZWSP. + * platform/graphics/GlyphPageTreeNode.cpp: + (WebCore::GlyphPageTreeNode::initializePage): added ZWNJ and ZWJ. + * platform/text/CharacterNames.h: added ZWNJ and ZWJ. + +2010-04-21 Charles Wei <charles.wei@torchmobile.com.cn> + + Reviewed by George Staikos. + + Fix webkit build problem when xhtmlmp enabled, which is introduced by revision 57927, for + bug fix of 37175 , which seperates DocumentWriter from FrameLoader + https://bugs.webkit.org/show_bug.cgi?id=37915 + + No new tests since this only fixes the build problem. + + * dom/Document.cpp: + (WebCore::Document::isXHTMLMPDocument): + +2010-04-21 Shinichiro Hamaji <hamaji@chromium.org> + + Reviewed by Darin Adler. + + Call sites of TextIterator constructor are difficult to read + https://bugs.webkit.org/show_bug.cgi?id=37909 + + Now we use enum parameters instead of boolean parameters and + boolean version of constructors are eliminated. + + This change also changes the names of boolean members so they are + now third person singular. + + No new tests because this is just a refactoring. + + * WebCore.base.exp: + * editing/TextIterator.cpp: + (WebCore::TextIterator::TextIterator): + (WebCore::TextIterator::advance): + (WebCore::TextIterator::handleReplacedElement): + (WebCore::TextIterator::shouldRepresentNodeOffsetZero): + (WebCore::TextIterator::shouldEmitSpaceBeforeAndAfterNode): + (WebCore::TextIterator::handleNonTextNode): + (WebCore::TextIterator::exitNode): + (WebCore::TextIterator::emitCharacter): + (WebCore::TextIterator::emitText): + (WebCore::CharacterIterator::CharacterIterator): + (WebCore::TextIterator::rangeLength): + (WebCore::TextIterator::rangeFromLocationAndLength): + (WebCore::findPlainText): + * editing/TextIterator.h: + (WebCore::): + * editing/VisibleSelection.cpp: + (WebCore::VisibleSelection::appendTrailingWhitespace): + * editing/visible_units.cpp: + (WebCore::nextBoundary): + +2010-04-21 Jesus Sanchez-Palencia <jesus@webkit.org> + + Reviewed by Kenneth Rohde Christiansen. + + Add PageClientQt files. + + [Qt] PageClientQt specific implementation for QWidget + https://bugs.webkit.org/show_bug.cgi?id=37858 + + * WebCore.pro: + +2010-04-21 Diego Escalante Urrelo <descalante@igalia.com> + + Reviewed by Xan Lopez. + + [Gtk] Evaluate and create tests for all the AtkRole's implemented by + WebKitGtk + https://bugs.webkit.org/show_bug.cgi?id=34449 + + Implement ATK_ROLE_SEPARATOR. + + * accessibility/AccessibilityRenderObject.cpp: + (WebCore::AccessibilityRenderObject::determineAccessibilityRole): + * accessibility/gtk/AccessibilityObjectAtk.cpp: + (WebCore::AccessibilityObject::accessibilityPlatformIncludesObject): + +2010-04-21 David Leong <david.leong@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Symbian apps crash on exit due to a bad qObject_cast. + + https://bugs.webkit.org/show_bug.cgi?id=37303 + + Added check for NULL to avoid the crash. Reworked to fix memory leak + + * plugins/symbian/PluginViewSymbian.cpp: + (WebCore::PluginView::platformDestroy): + 2009-04-21 Chris Fleizach <cfleizach@apple.com> Reviewed by Alexey Proskuryakov. @@ -833,8 +8571,8 @@ declaration ( e.g. every "namespace WebCore { class String; }" much change to "namespace WTF { class String; }"). - Moving the files, but leaving the classes logically in the WebCore namespace – - which is technically a layering violation – I'll come back and fix this up in a + Moving the files, but leaving the classes logically in the WebCore namespace - + which is technically a layering violation - I'll come back and fix this up in a subsequent patch. * Android.mk: @@ -29869,7 +37607,7 @@ https://bugs.webkit.org/show_bug.cgi?id=34728 addressed the symptoms of this problem, and it is probably cleaner to make the client data's normal world no longer be a member (since it is a ref-counted object), however they should be - no requirement to 'detatch' – it makes no sense for anyone to be referencing + no requirement to 'detatch' - it makes no sense for anyone to be referencing the world after the JSGlobalData has gone away (the world's purpose is to hold wrapper objects in the JSGlobalData's heap). Keep the restructuring that makes the normal world no longer be a member, but remove the detach mechanism this @@ -35769,7 +43507,7 @@ https://bugs.webkit.org/show_bug.cgi?id=34335 * bindings/js/ScriptCallStack.cpp: - (WebCore::ScriptCallStack::ScriptCallStack): If the caller is unknown, the line number and source information is still availble so pass it to the ScriptCallFrame being constructed. + (WebCore::ScriptCallStack::ScriptCallStack): If the caller is unknown, the line number and source information is still available so pass it to the ScriptCallFrame being constructed. 2010-02-01 Dirk Schulze <krit@webkit.org> diff --git a/WebCore/Configurations/Version.xcconfig b/WebCore/Configurations/Version.xcconfig index 6aeb263..cc5943e 100644 --- a/WebCore/Configurations/Version.xcconfig +++ b/WebCore/Configurations/Version.xcconfig @@ -22,7 +22,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAJOR_VERSION = 533; -MINOR_VERSION = 6; +MINOR_VERSION = 9; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/WebCore/Configurations/WebCore.xcconfig b/WebCore/Configurations/WebCore.xcconfig index c678bce..b9b37fd 100644 --- a/WebCore/Configurations/WebCore.xcconfig +++ b/WebCore/Configurations/WebCore.xcconfig @@ -39,9 +39,14 @@ INSTALL_PATH = $(SYSTEM_LIBRARY_DIR)/Frameworks/WebKit.framework/Versions/A/Fram INSTALLHDRS_COPY_PHASE = YES; INSTALLHDRS_SCRIPT_PHASE = YES; PRODUCT_NAME = WebCore; -UMBRELLA_LDFLAGS = -umbrella WebKit; -VISIBILITY_LDFLAGS = ; -OTHER_LDFLAGS = -l$(SQLITE3_LIBRARY) -lobjc -sub_library libobjc $(UMBRELLA_LDFLAGS) $(VISIBILITY_LDFLAGS); + +OTHER_LDFLAGS = -l$(SQLITE3_LIBRARY) -lobjc -sub_library libobjc -umbrella WebKit $(WEBKIT2_LDFLAGS); + +WEBKIT2_LDFLAGS = $(WEBKIT2_LDFLAGS_$(TARGET_MAC_OS_X_VERSION_MAJOR)); +WEBKIT2_LDFLAGS_1060 = $(WEBKIT2_LDFLAGS_$(CONFIGURATION)); +WEBKIT2_LDFLAGS_1070 = $(WEBKIT2_LDFLAGS_$(CONFIGURATION)); +WEBKIT2_LDFLAGS_Release = -allowable_client WebKit2; +WEBKIT2_LDFLAGS_Debug = -allowable_client WebKit2; JAVASCRIPTCORE_PRIVATE_HEADERS_DIR = $(JAVASCRIPTCORE_PRIVATE_HEADERS_DIR_$(REAL_PLATFORM_NAME)_$(CONFIGURATION)); JAVASCRIPTCORE_PRIVATE_HEADERS_DIR_macosx_Release = $(JAVASCRIPTCORE_PRIVATE_HEADERS_engineering); diff --git a/WebCore/DerivedSources.cpp b/WebCore/DerivedSources.cpp index 72c5d47..c8be33f 100644 --- a/WebCore/DerivedSources.cpp +++ b/WebCore/DerivedSources.cpp @@ -64,6 +64,7 @@ #include "JSCSSVariablesRule.cpp" #include "JSCustomEvent.cpp" #include "JSDatabase.cpp" +#include "JSDatabaseCallback.cpp" #include "JSDataGridColumn.cpp" #include "JSDataGridColumnList.cpp" #include "JSDedicatedWorkerContext.cpp" @@ -85,6 +86,7 @@ #include "JSEventException.cpp" #include "JSEventSource.cpp" #include "JSFile.cpp" +#include "JSFileError.cpp" #include "JSFileList.cpp" #include "JSGeolocation.cpp" #include "JSGeoposition.cpp" @@ -165,7 +167,6 @@ #include "JSJavaScriptCallFrame.cpp" #include "JSKeyboardEvent.cpp" #include "JSLocation.cpp" -#include "JSMedia.cpp" #include "JSMediaError.cpp" #include "JSMediaList.cpp" #include "JSMessageChannel.cpp" @@ -204,9 +205,14 @@ #include "JSSQLError.cpp" #include "JSSQLResultSet.cpp" #include "JSSQLResultSetRowList.cpp" +#include "JSSQLStatementCallback.cpp" +#include "JSSQLStatementErrorCallback.cpp" #include "JSSQLTransaction.cpp" +#include "JSSQLTransactionCallback.cpp" +#include "JSSQLTransactionErrorCallback.cpp" #include "JSStorage.cpp" #include "JSStorageEvent.cpp" +#include "JSStyleMedia.cpp" #include "JSStyleSheet.cpp" #include "JSStyleSheetList.cpp" #include "JSSVGAElement.cpp" diff --git a/WebCore/DerivedSources.make b/WebCore/DerivedSources.make index 1aaa066..b4120f9 100644 --- a/WebCore/DerivedSources.make +++ b/WebCore/DerivedSources.make @@ -115,6 +115,7 @@ DOM_CLASSES = \ DOMSelection \ DOMWindow \ Database \ + DatabaseCallback \ Document \ DocumentFragment \ DocumentType \ @@ -129,6 +130,7 @@ DOM_CLASSES = \ EventSource \ EventTarget \ File \ + FileError \ FileList \ Geolocation \ Geoposition \ @@ -210,7 +212,6 @@ DOM_CLASSES = \ InspectorFrontendHost \ KeyboardEvent \ Location \ - Media \ MediaError \ MediaList \ MessageChannel \ @@ -248,7 +249,11 @@ DOM_CLASSES = \ SQLError \ SQLResultSet \ SQLResultSetRowList \ + SQLStatementCallback \ + SQLStatementErrorCallback \ SQLTransaction \ + SQLTransactionCallback \ + SQLTransactionErrorCallback \ Storage \ StorageEvent \ SVGAElement \ @@ -397,6 +402,7 @@ DOM_CLASSES = \ SVGZoomAndPan \ SVGZoomEvent \ Screen \ + StyleMedia \ StyleSheet \ StyleSheetList \ Text \ @@ -821,7 +827,7 @@ CharsetData.cpp : platform/text/mac/make-charset-table.pl platform/text/mac/char # export file -ifeq ($(shell gcc -E -P -dM $(FRAMEWORK_FLAGS) WebCore/ForwardingHeaders/wtf/Platform.h | grep ENABLE_MAC_JAVA_BRIDGE | cut -d' ' -f3), 1) +ifeq ($(shell gcc -E -P -dM $(FRAMEWORK_FLAGS) WebCore/ForwardingHeaders/wtf/Platform.h | grep ENABLE_JAVA_BRIDGE | cut -d' ' -f3), 1) WEBCORE_EXPORT_DEPENDENCIES := $(WEBCORE_EXPORT_DEPENDENCIES) WebCore.JNI.exp endif @@ -881,6 +887,10 @@ ifeq ($(findstring ENABLE_GEOLOCATION,$(FEATURE_DEFINES)), ENABLE_GEOLOCATION) WEBCORE_EXPORT_DEPENDENCIES := $(WEBCORE_EXPORT_DEPENDENCIES) WebCore.Geolocation.exp endif +ifeq ($(shell gcc -E -P -dM $(FRAMEWORK_FLAGS) WebCore/ForwardingHeaders/wtf/Platform.h | grep WTF_USE_PROTECTION_SPACE_AUTH_CALLBACK | cut -d' ' -f3), 1) + WEBCORE_EXPORT_DEPENDENCIES := $(WEBCORE_EXPORT_DEPENDENCIES) WebCore.ProtectionSpaceAuthCallback.exp +endif + WebCore.exp : WebCore.base.exp $(WEBCORE_EXPORT_DEPENDENCIES) cat $^ > $@ diff --git a/WebCore/English.lproj/localizedStrings.js b/WebCore/English.lproj/localizedStrings.js Binary files differindex a59ba83..720e09c 100644 --- a/WebCore/English.lproj/localizedStrings.js +++ b/WebCore/English.lproj/localizedStrings.js diff --git a/WebCore/ForwardingHeaders/runtime/PropertyMap.h b/WebCore/ForwardingHeaders/runtime/PropertyMap.h deleted file mode 100644 index fc40963..0000000 --- a/WebCore/ForwardingHeaders/runtime/PropertyMap.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef WebCore_FWD_PropertyMap_h -#define WebCore_FWD_PropertyMap_h -#include <JavaScriptCore/PropertyMap.h> -#endif - diff --git a/WebCore/ForwardingHeaders/wtf/Atomics.h b/WebCore/ForwardingHeaders/wtf/Atomics.h new file mode 100644 index 0000000..2fee175 --- /dev/null +++ b/WebCore/ForwardingHeaders/wtf/Atomics.h @@ -0,0 +1,4 @@ +#ifndef WebCore_FWD_Atomics_h +#define WebCore_FWD_Atomics_h +#include <JavaScriptCore/Atomics.h> +#endif diff --git a/WebCore/ForwardingHeaders/wtf/MD5.h b/WebCore/ForwardingHeaders/wtf/MD5.h new file mode 100644 index 0000000..0c65786 --- /dev/null +++ b/WebCore/ForwardingHeaders/wtf/MD5.h @@ -0,0 +1,5 @@ +#ifndef WebCore_FWD_MD5_h +#define WebCore_FWD_MD5_h +#include <JavaScriptCore/MD5.h> +#endif + diff --git a/WebCore/ForwardingHeaders/wtf/ThreadSafeShared.h b/WebCore/ForwardingHeaders/wtf/ThreadSafeShared.h new file mode 100644 index 0000000..50c2bf4 --- /dev/null +++ b/WebCore/ForwardingHeaders/wtf/ThreadSafeShared.h @@ -0,0 +1,4 @@ +#ifndef WebCore_FWD_ThreadSafeShared_h +#define WebCore_FWD_ThreadSafeShared_h +#include <JavaScriptCore/ThreadSafeShared.h> +#endif diff --git a/WebCore/ForwardingHeaders/wtf/ThreadingPrimitives.h b/WebCore/ForwardingHeaders/wtf/ThreadingPrimitives.h new file mode 100644 index 0000000..5dd2e03 --- /dev/null +++ b/WebCore/ForwardingHeaders/wtf/ThreadingPrimitives.h @@ -0,0 +1,4 @@ +#ifndef WebCore_FWD_ThreadingPrimitives_h +#define WebCore_FWD_ThreadingPrimitives_h +#include <JavaScriptCore/ThreadingPrimitives.h> +#endif diff --git a/WebCore/GNUmakefile.am b/WebCore/GNUmakefile.am index 93b685e..d8cfc3a 100644 --- a/WebCore/GNUmakefile.am +++ b/WebCore/GNUmakefile.am @@ -115,10 +115,10 @@ IDL_BINDINGS += \ WebCore/css/CSSVariablesDeclaration.idl \ WebCore/css/CSSVariablesRule.idl \ WebCore/css/Counter.idl \ - WebCore/css/Media.idl \ WebCore/css/MediaList.idl \ - WebCore/css/RGBColor.idl \ WebCore/css/Rect.idl \ + WebCore/css/RGBColor.idl \ + WebCore/css/StyleMedia.idl \ WebCore/css/StyleSheet.idl \ WebCore/css/StyleSheetList.idl \ WebCore/css/WebKitCSSKeyframeRule.idl \ @@ -194,6 +194,7 @@ IDL_BINDINGS += \ WebCore/html/DataGridColumnList.idl \ WebCore/html/DOMFormData.idl \ WebCore/html/File.idl \ + WebCore/html/FileError.idl \ WebCore/html/FileList.idl \ WebCore/html/HTMLAllCollection.idl \ WebCore/html/HTMLAnchorElement.idl \ @@ -318,6 +319,8 @@ webcoregtk_dom_sources = \ WebCore/bindings/gobject/ConvertToUTF8String.h \ WebCore/bindings/gobject/WebKitDOMBinding.cpp \ WebCore/bindings/gobject/WebKitDOMBinding.h \ + WebCore/bindings/gobject/WebKitHTMLElementWrapperFactory.cpp \ + WebCore/bindings/gobject/WebKitHTMLElementWrapperFactory.h \ WebCore/bindings/gobject/WebKitDOMObject.cpp \ WebCore/bindings/gobject/WebKitDOMObject.h @@ -417,14 +420,12 @@ webcore_sources += \ WebCore/bindings/js/JSDOMWrapper.cpp \ WebCore/bindings/js/JSDOMWrapper.h \ WebCore/bindings/js/JSDocumentCustom.cpp \ - WebCore/bindings/js/JSDocumentFragmentCustom.cpp \ WebCore/bindings/js/JSElementCustom.cpp \ WebCore/bindings/js/JSEventCustom.cpp \ WebCore/bindings/js/JSEventListener.cpp \ WebCore/bindings/js/JSEventListener.h \ WebCore/bindings/js/JSEventSourceConstructor.cpp \ WebCore/bindings/js/JSEventSourceConstructor.h \ - WebCore/bindings/js/JSEventSourceCustom.cpp \ WebCore/bindings/js/JSEventTarget.cpp \ WebCore/bindings/js/JSEventTarget.h \ WebCore/bindings/js/JSExceptionBase.cpp \ @@ -682,26 +683,26 @@ webcore_sources += \ WebCore/css/FontValue.h \ WebCore/css/MediaFeatureNames.cpp \ WebCore/css/MediaFeatureNames.h \ - WebCore/css/Media.cpp \ - WebCore/css/Media.h \ WebCore/css/MediaList.cpp \ WebCore/css/MediaList.h \ WebCore/css/MediaQuery.cpp \ - WebCore/css/MediaQuery.h \ WebCore/css/MediaQueryEvaluator.cpp \ WebCore/css/MediaQueryEvaluator.h \ WebCore/css/MediaQueryExp.cpp \ WebCore/css/MediaQueryExp.h \ + WebCore/css/MediaQuery.h \ WebCore/css/Pair.h \ + WebCore/css/Rect.h \ WebCore/css/RGBColor.cpp \ WebCore/css/RGBColor.h \ - WebCore/css/Rect.h \ WebCore/css/ShadowValue.cpp \ WebCore/css/ShadowValue.h \ WebCore/css/StyleBase.cpp \ WebCore/css/StyleBase.h \ WebCore/css/StyleList.cpp \ WebCore/css/StyleList.h \ + WebCore/css/StyleMedia.cpp \ + WebCore/css/StyleMedia.h \ WebCore/css/StyleSheet.cpp \ WebCore/css/StyleSheet.h \ WebCore/css/StyleSheetList.cpp \ @@ -885,6 +886,7 @@ webcore_sources += \ WebCore/dom/Tokenizer.h \ WebCore/dom/Traversal.cpp \ WebCore/dom/Traversal.h \ + WebCore/dom/TreeDepthLimit.h \ WebCore/dom/TreeWalker.cpp \ WebCore/dom/TreeWalker.h \ WebCore/dom/UIEvent.cpp \ @@ -1048,8 +1050,11 @@ webcore_sources += \ WebCore/html/DOMFormData.h \ WebCore/html/File.cpp \ WebCore/html/File.h \ + WebCore/html/FileError.h \ WebCore/html/FileList.cpp \ WebCore/html/FileList.h \ + WebCore/html/FileReader.cpp \ + WebCore/html/FileReader.h \ WebCore/html/FileStream.cpp \ WebCore/html/FileStream.h \ WebCore/html/FileStreamClient.h \ @@ -1271,6 +1276,8 @@ webcore_sources += \ WebCore/inspector/InjectedScriptHost.h \ WebCore/inspector/InspectorBackend.cpp \ WebCore/inspector/InspectorBackend.h \ + WebCore/inspector/InspectorCSSStore.cpp \ + WebCore/inspector/InspectorCSSStore.h \ WebCore/inspector/InspectorDatabaseResource.cpp \ WebCore/inspector/InspectorDatabaseResource.h \ WebCore/inspector/InspectorDOMAgent.cpp \ @@ -1639,10 +1646,9 @@ webcore_sources += \ WebCore/platform/graphics/GeneratedImage.h \ WebCore/platform/graphics/Generator.h \ WebCore/platform/graphics/GlyphBuffer.h \ + WebCore/platform/graphics/GlyphMetricsMap.h \ WebCore/platform/graphics/GlyphPageTreeNode.cpp \ WebCore/platform/graphics/GlyphPageTreeNode.h \ - WebCore/platform/graphics/GlyphMetricsMap.cpp \ - WebCore/platform/graphics/GlyphMetricsMap.h \ WebCore/platform/graphics/Gradient.cpp \ WebCore/platform/graphics/Gradient.h \ WebCore/platform/graphics/GraphicsContext.cpp \ @@ -2300,25 +2306,21 @@ FEATURE_DEFINES += ENABLE_DATABASE=1 IDL_BINDINGS += \ WebCore/storage/Database.idl \ + WebCore/storage/DatabaseCallback.idl \ WebCore/storage/SQLError.idl \ WebCore/storage/SQLResultSet.idl \ WebCore/storage/SQLResultSetRowList.idl \ - WebCore/storage/SQLTransaction.idl + WebCore/storage/SQLStatementCallback.idl \ + WebCore/storage/SQLStatementErrorCallback.idl \ + WebCore/storage/SQLTransaction.idl \ + WebCore/storage/SQLTransactionCallback.idl \ + WebCore/storage/SQLTransactionErrorCallback.idl webcore_cppflags += \ -DENABLE_DATABASE=1 webcore_sources += \ - WebCore/bindings/js/JSCustomSQLStatementCallback.cpp \ - WebCore/bindings/js/JSCustomSQLStatementCallback.h \ WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp \ - WebCore/bindings/js/JSCustomSQLStatementErrorCallback.h \ - WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp \ - WebCore/bindings/js/JSCustomSQLTransactionCallback.h \ - WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp \ - WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.h \ - WebCore/bindings/js/JSDatabaseCallback.cpp \ - WebCore/bindings/js/JSDatabaseCallback.h \ WebCore/bindings/js/JSDatabaseCustom.cpp \ WebCore/bindings/js/JSSQLResultSetRowListCustom.cpp \ WebCore/bindings/js/JSSQLTransactionCustom.cpp \ @@ -2341,6 +2343,8 @@ webcore_sources += \ WebCore/storage/DatabaseAuthorizer.h \ WebCore/storage/DatabaseCallback.h \ WebCore/storage/DatabaseDetails.h \ + WebCore/storage/DatabaseSync.cpp \ + WebCore/storage/DatabaseSync.h \ WebCore/storage/DatabaseTask.cpp \ WebCore/storage/DatabaseTask.h \ WebCore/storage/DatabaseThread.cpp \ @@ -2368,7 +2372,10 @@ webcore_sources += \ WebCore/storage/SQLTransactionClient.h \ WebCore/storage/SQLTransactionCoordinator.h \ WebCore/storage/SQLTransactionCoordinator.cpp \ - WebCore/storage/SQLTransactionErrorCallback.h + WebCore/storage/SQLTransactionErrorCallback.h \ + WebCore/storage/SQLTransactionSync.cpp \ + WebCore/storage/SQLTransactionSync.h \ + WebCore/storage/SQLTransactionSyncCallback.h else webcore_cppflags += -DENABLE_DATABASE=0 @@ -2670,7 +2677,6 @@ webcore_cppflags += \ -DENABLE_WORKERS=1 webcore_sources += \ - WebCore/bindings/js/JSAbstractWorkerCustom.cpp \ WebCore/bindings/js/JSDedicatedWorkerContextCustom.cpp \ WebCore/bindings/js/JSWorkerConstructor.cpp \ WebCore/bindings/js/JSWorkerConstructor.h \ @@ -3119,15 +3125,26 @@ webcore_sources += \ WebCore/rendering/RenderSVGInlineText.h \ WebCore/rendering/RenderSVGModelObject.cpp \ WebCore/rendering/RenderSVGModelObject.h \ + WebCore/rendering/RenderSVGResource.cpp \ WebCore/rendering/RenderSVGResource.h \ WebCore/rendering/RenderSVGResourceClipper.cpp \ WebCore/rendering/RenderSVGResourceClipper.h \ WebCore/rendering/RenderSVGResourceFilter.cpp \ WebCore/rendering/RenderSVGResourceFilter.h \ + WebCore/rendering/RenderSVGResourceGradient.cpp \ + WebCore/rendering/RenderSVGResourceGradient.h \ + WebCore/rendering/RenderSVGResourceLinearGradient.cpp \ + WebCore/rendering/RenderSVGResourceLinearGradient.h \ WebCore/rendering/RenderSVGResourceMarker.cpp \ WebCore/rendering/RenderSVGResourceMarker.h \ WebCore/rendering/RenderSVGResourceMasker.cpp \ WebCore/rendering/RenderSVGResourceMasker.h \ + WebCore/rendering/RenderSVGResourcePattern.cpp \ + WebCore/rendering/RenderSVGResourcePattern.h \ + WebCore/rendering/RenderSVGResourceRadialGradient.cpp \ + WebCore/rendering/RenderSVGResourceRadialGradient.h \ + WebCore/rendering/RenderSVGResourceSolidColor.cpp \ + WebCore/rendering/RenderSVGResourceSolidColor.h \ WebCore/rendering/RenderSVGRoot.cpp \ WebCore/rendering/RenderSVGRoot.h \ WebCore/rendering/RenderSVGShadowTreeRootContainer.cpp \ @@ -3142,6 +3159,8 @@ webcore_sources += \ WebCore/rendering/RenderSVGTransformableContainer.h \ WebCore/rendering/RenderSVGViewportContainer.cpp \ WebCore/rendering/RenderSVGViewportContainer.h \ + WebCore/rendering/SVGCharacterData.cpp \ + WebCore/rendering/SVGCharacterData.h \ WebCore/rendering/SVGCharacterLayoutInfo.cpp \ WebCore/rendering/SVGCharacterLayoutInfo.h \ WebCore/rendering/SVGInlineFlowBox.cpp \ @@ -3159,6 +3178,7 @@ webcore_sources += \ WebCore/rendering/SVGRootInlineBox.h \ WebCore/rendering/SVGShadowTreeElements.cpp \ WebCore/rendering/SVGShadowTreeElements.h \ + WebCore/rendering/SVGTextChunkLayoutInfo.h \ WebCore/rendering/style/SVGRenderStyle.cpp \ WebCore/rendering/style/SVGRenderStyle.h \ WebCore/rendering/style/SVGRenderStyleDefs.cpp \ @@ -3449,21 +3469,6 @@ webcore_sources += \ WebCore/svg/animation/SVGSMILElement.h \ WebCore/svg/graphics/SVGImage.cpp \ WebCore/svg/graphics/SVGImage.h \ - WebCore/svg/graphics/SVGPaintServer.cpp \ - WebCore/svg/graphics/SVGPaintServer.h \ - WebCore/svg/graphics/SVGPaintServerGradient.cpp \ - WebCore/svg/graphics/SVGPaintServerGradient.h \ - WebCore/svg/graphics/SVGPaintServerLinearGradient.cpp \ - WebCore/svg/graphics/SVGPaintServerLinearGradient.h \ - WebCore/svg/graphics/SVGPaintServerPattern.cpp \ - WebCore/svg/graphics/SVGPaintServerPattern.h \ - WebCore/svg/graphics/SVGPaintServerRadialGradient.cpp \ - WebCore/svg/graphics/SVGPaintServerRadialGradient.h \ - WebCore/svg/graphics/SVGPaintServerSolid.cpp \ - WebCore/svg/graphics/SVGPaintServerSolid.h \ - WebCore/svg/graphics/SVGResource.cpp \ - WebCore/svg/graphics/SVGResource.h \ - WebCore/svg/graphics/SVGResourceListener.h \ WebCore/svg/graphics/filters/SVGDistantLightSource.h \ WebCore/svg/graphics/filters/SVGFEConvolveMatrix.cpp \ WebCore/svg/graphics/filters/SVGFEConvolveMatrix.h \ @@ -3790,33 +3795,134 @@ $(top_builddir)/DerivedSources/webkit/WebKitDOMObject.h: cp -f $(WebCore)/bindings/gobject/WebKitDOMObject.h $@ # Start with a subset of all the DOM bindings -IDL_BINDINGS_GDOM := \ +IDL_BINDINGS_GDOM += \ WebCore/css/CSSRule.idl \ WebCore/css/CSSRuleList.idl \ WebCore/css/CSSStyleDeclaration.idl \ WebCore/css/CSSStyleSheet.idl \ WebCore/css/CSSValue.idl \ WebCore/css/MediaList.idl \ + WebCore/css/StyleMedia.idl \ WebCore/css/StyleSheet.idl \ + WebCore/css/StyleSheetList.idl \ WebCore/dom/Attr.idl \ + WebCore/dom/CDATASection.idl \ + WebCore/dom/CharacterData.idl \ + WebCore/dom/Comment.idl \ + WebCore/dom/Document.idl \ + WebCore/dom/DocumentFragment.idl \ + WebCore/dom/DocumentType.idl \ + WebCore/dom/DOMImplementation.idl \ WebCore/dom/Element.idl \ + WebCore/dom/EntityReference.idl \ + WebCore/dom/MessagePort.idl \ WebCore/dom/NamedNodeMap.idl \ WebCore/dom/Node.idl \ - WebCore/dom/NodeList.idl + WebCore/dom/NodeFilter.idl \ + WebCore/dom/NodeIterator.idl \ + WebCore/dom/NodeList.idl \ + WebCore/dom/ProcessingInstruction.idl \ + WebCore/dom/Range.idl \ + WebCore/dom/Text.idl \ + WebCore/dom/TreeWalker.idl \ + WebCore/html/Blob.idl \ + WebCore/html/File.idl \ + WebCore/html/FileList.idl \ + WebCore/html/HTMLAnchorElement.idl \ + WebCore/html/HTMLAppletElement.idl \ + WebCore/html/HTMLAreaElement.idl \ + WebCore/html/HTMLBaseElement.idl \ + WebCore/html/HTMLBaseFontElement.idl \ + WebCore/html/HTMLBlockquoteElement.idl \ + WebCore/html/HTMLBodyElement.idl \ + WebCore/html/HTMLBRElement.idl \ + WebCore/html/HTMLButtonElement.idl \ + WebCore/html/HTMLCanvasElement.idl \ + WebCore/html/HTMLCollection.idl \ + WebCore/html/HTMLDirectoryElement.idl \ + WebCore/html/HTMLDivElement.idl \ + WebCore/html/HTMLDListElement.idl \ + WebCore/html/HTMLDocument.idl \ + WebCore/html/HTMLElement.idl \ + WebCore/html/HTMLEmbedElement.idl \ + WebCore/html/HTMLFieldSetElement.idl \ + WebCore/html/HTMLFontElement.idl \ + WebCore/html/HTMLFormElement.idl \ + WebCore/html/HTMLFrameElement.idl \ + WebCore/html/HTMLFrameSetElement.idl \ + WebCore/html/HTMLHeadElement.idl \ + WebCore/html/HTMLHeadingElement.idl \ + WebCore/html/HTMLHRElement.idl \ + WebCore/html/HTMLHtmlElement.idl \ + WebCore/html/HTMLIFrameElement.idl \ + WebCore/html/HTMLImageElement.idl \ + WebCore/html/HTMLInputElement.idl \ + WebCore/html/HTMLIsIndexElement.idl \ + WebCore/html/HTMLLabelElement.idl \ + WebCore/html/HTMLLegendElement.idl \ + WebCore/html/HTMLLIElement.idl \ + WebCore/html/HTMLLinkElement.idl \ + WebCore/html/HTMLMapElement.idl \ + WebCore/html/HTMLMarqueeElement.idl \ + WebCore/html/HTMLMenuElement.idl \ + WebCore/html/HTMLMetaElement.idl \ + WebCore/html/HTMLModElement.idl \ + WebCore/html/HTMLObjectElement.idl \ + WebCore/html/HTMLOListElement.idl \ + WebCore/html/HTMLOptGroupElement.idl \ + WebCore/html/HTMLOptionElement.idl \ + WebCore/html/HTMLOptionsCollection.idl \ + WebCore/html/HTMLParagraphElement.idl \ + WebCore/html/HTMLParamElement.idl \ + WebCore/html/HTMLPreElement.idl \ + WebCore/html/HTMLQuoteElement.idl \ + WebCore/html/HTMLScriptElement.idl \ + WebCore/html/HTMLSelectElement.idl \ + WebCore/html/HTMLStyleElement.idl \ + WebCore/html/HTMLTableElement.idl \ + WebCore/html/HTMLTableCaptionElement.idl \ + WebCore/html/HTMLTableColElement.idl \ + WebCore/html/HTMLTableSectionElement.idl \ + WebCore/html/HTMLTableCellElement.idl \ + WebCore/html/HTMLTextAreaElement.idl \ + WebCore/html/HTMLTitleElement.idl \ + WebCore/html/HTMLTableRowElement.idl \ + WebCore/html/HTMLUListElement.idl \ + WebCore/html/ValidityState.idl \ + WebCore/loader/appcache/DOMApplicationCache.idl \ + WebCore/page/BarInfo.idl \ + WebCore/page/Console.idl \ + WebCore/page/DOMWindow.idl \ + WebCore/page/DOMSelection.idl \ + WebCore/page/Geolocation.idl \ + WebCore/page/History.idl \ + WebCore/page/Location.idl \ + WebCore/page/Navigator.idl \ + WebCore/page/Screen.idl \ + WebCore/page/WebKitPoint.idl \ + WebCore/plugins/MimeType.idl \ + WebCore/plugins/MimeTypeArray.idl \ + WebCore/plugins/Plugin.idl \ + WebCore/plugins/PluginArray.idl \ + WebCore/storage/Database.idl \ + WebCore/storage/Storage.idl \ + WebCore/xml/XPathExpression.idl \ + WebCore/xml/XPathNSResolver.idl \ + WebCore/xml/XPathResult.idl # All classes autogenerated in the GObject DOM bindings -GDOM_AUTO_CLASSES := $(basename $(notdir $(IDL_BINDINGS_GDOM))) +GDOM_AUTO_CLASSES += $(basename $(notdir $(IDL_BINDINGS_GDOM))) # The classes implemented manually -GDOM_FIXED_CLASSES := Object +GDOM_FIXED_CLASSES += Object -GDOM_CLASSES := $(GDOM_AUTO_CLASSES) $(GDOM_FIXED_CLASSES) +GDOM_CLASSES += $(GDOM_AUTO_CLASSES) $(GDOM_FIXED_CLASSES) # Filter out SVG for now FEATURE_DEFINES_GDOM := $(filter-out ENABLE-SVG%, $(FEATURE_DEFINES)) # Autogenerated header files -GDOM_HEADERS_BUILT := $(patsubst %,DerivedSources/webkit/WebKitDOM%.h,$(GDOM_AUTO_CLASSES)) \ +GDOM_HEADERS_BUILT += $(patsubst %,$(top_builddir)/DerivedSources/webkit/WebKitDOM%.h,$(GDOM_AUTO_CLASSES)) \ $(top_builddir)/DerivedSources/webkit/webkitdom.h \ $(top_builddir)/DerivedSources/webkit/webkitdomdefines.h \ $(top_builddir)/DerivedSources/webkit/WebKitDOMObject.h @@ -3825,10 +3931,10 @@ GDOM_HEADERS_BUILT := $(patsubst %,DerivedSources/webkit/WebKitDOM%.h,$(GDOM_AUT GDOM_SOURCES_BUILT := $(patsubst %,DerivedSources/webkit/WebKitDOM%.cpp,$(GDOM_AUTO_CLASSES)) # Hand-coded header files -GDOM_HEADERS_FIXED := $(patsubst %,$(srcdir)/WebCore/bindings/gobject/WebKitDOM%.h,$(GDOM_FIXED_CLASSES)) +GDOM_HEADERS_FIXED += $(patsubst %,$(srcdir)/WebCore/bindings/gobject/WebKitDOM%.h,$(GDOM_FIXED_CLASSES)) # All header files that get installed -libgdom_h_api := $(GDOM_HEADERS_FIXED) $(GDOM_HEADERS_BUILT) +libgdom_h_api += $(GDOM_HEADERS_FIXED) $(GDOM_HEADERS_BUILT) DerivedSources/webkit/webkitdom.h: $(WebCore)/bindings/scripts/gobject-generate-headers.pl echo $(GDOM_CLASSES) | $(PERL) $< gdom > $@ diff --git a/WebCore/WebCore.ProtectionSpaceAuthCallback.exp b/WebCore/WebCore.ProtectionSpaceAuthCallback.exp new file mode 100644 index 0000000..4c27ed9 --- /dev/null +++ b/WebCore/WebCore.ProtectionSpaceAuthCallback.exp @@ -0,0 +1,2 @@ +__ZN7WebCore3macERKNS_15ProtectionSpaceE +__ZNK7WebCore15ProtectionSpace20authenticationSchemeEv diff --git a/WebCore/WebCore.base.exp b/WebCore/WebCore.base.exp index fed064d..bcf4fd3 100644 --- a/WebCore/WebCore.base.exp +++ b/WebCore/WebCore.base.exp @@ -261,7 +261,7 @@ __ZN7WebCore12TextEncodingC1ERKNS_6StringE __ZN7WebCore12TextIterator11rangeLengthEPKNS_5RangeEb __ZN7WebCore12TextIterator26rangeFromLocationAndLengthEPNS_7ElementEiib __ZN7WebCore12TextIterator7advanceEv -__ZN7WebCore12TextIteratorC1EPKNS_5RangeEbb +__ZN7WebCore12TextIteratorC1EPKNS_5RangeENS_20TextIteratorBehaviorE __ZN7WebCore12WorkerThread17workerThreadCountEv __ZN7WebCore12applyCommandEN3WTF10PassRefPtrINS_11EditCommandEEE __ZN7WebCore12cacheStorageEv @@ -599,12 +599,13 @@ __ZN7WebCore6StringC1EP8NSString __ZN7WebCore6StringC1EPK10__CFString __ZN7WebCore6Widget12setFrameRectERKNS_7IntRectE __ZN7WebCore6Widget16removeFromParentEv +__ZN7WebCore6Widget17frameRectsChangedEv __ZN7WebCore6Widget20retainPlatformWidgetEv __ZN7WebCore6Widget21releasePlatformWidgetEv __ZN7WebCore6Widget4hideEv __ZN7WebCore6Widget4showEv __ZN7WebCore6Widget5paintEPNS_15GraphicsContextERKNS_7IntRectE -__ZN7WebCore6Widget8setFocusEv +__ZN7WebCore6Widget8setFocusEb __ZN7WebCore6Widget9setParentEPNS_10ScrollViewE __ZN7WebCore6WidgetC1EP6NSView __ZN7WebCore6WidgetC2EP6NSView @@ -677,6 +678,7 @@ __ZN7WebCore8Settings28setForceFTPDirectoryListingsEb __ZN7WebCore8Settings29setAuthorAndUserStylesEnabledEb __ZN7WebCore8Settings29setWebArchiveDebugModeEnabledEb __ZN7WebCore8Settings30setAllowFileAccessFromFileURLsEb +__ZN7WebCore8Settings31setJavaScriptCanAccessClipboardEb __ZN7WebCore8Settings31setShrinksStandaloneImagesToFitEb __ZN7WebCore8Settings32setAcceleratedCompositingEnabledEb __ZN7WebCore8Settings32setNeedsAdobeFrameReloadingQuirkEb @@ -996,6 +998,7 @@ __ZNK7WebCore9FrameTree6parentEb __ZNK7WebCore9FrameView11needsLayoutEv __ZNK7WebCore9FrameView13paintBehaviorEv __ZNK7WebCore9FrameView20isSoftwareRenderableEv +__ZNK7WebCore9FrameView28isEnclosedInCompositingLayerEv __ZNK7WebCore9PageCache10frameCountEv __ZNK7WebCore9PageCache21autoreleasedPageCountEv __ZTVN7WebCore12ChromeClientE diff --git a/WebCore/WebCore.gyp/WebCore.gyp b/WebCore/WebCore.gyp/WebCore.gyp index c564aff..e9ab1d7 100644 --- a/WebCore/WebCore.gyp/WebCore.gyp +++ b/WebCore/WebCore.gyp/WebCore.gyp @@ -115,7 +115,6 @@ '../bindings/v8', '../bindings/v8/custom', '../bindings/v8/specialization', - '../bridge', '../css', '../dom', '../dom/default', @@ -288,7 +287,6 @@ 'inputs': [ '../css/makeprop.pl', '../css/CSSPropertyNames.in', - '../css/SVGCSSPropertyNames.in', ], 'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/webkit/CSSPropertyNames.cpp', @@ -301,13 +299,19 @@ '--', '<@(_inputs)' ], + 'conditions': [ + ['enable_svg!=0', { + 'inputs': [ + '../css/SVGCSSPropertyNames.in', + ], + }], + ], }, { 'action_name': 'CSSValueKeywords', 'inputs': [ '../css/makevalues.pl', '../css/CSSValueKeywords.in', - '../css/SVGCSSValueKeywords.in', ], 'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/webkit/CSSValueKeywords.c', @@ -320,6 +324,13 @@ '--', '<@(_inputs)' ], + 'conditions': [ + ['enable_svg!=0', { + 'inputs': [ + '../css/SVGCSSValueKeywords.in', + ], + }], + ], }, { 'action_name': 'HTMLNames', @@ -988,6 +999,7 @@ # Cherry-pick some files that can't be included by broader regexps. # Some of these are used instead of Chromium platform files, see # the specific exclusions in the "sources!" list below. + ['include', 'rendering/RenderThemeMac\\.mm$'], ['include', 'loader/archive/cf/LegacyWebArchive\\.cpp$'], ['include', 'platform/graphics/mac/ColorMac\\.mm$'], ['include', 'platform/graphics/mac/FloatPointMac\\.mm$'], diff --git a/WebCore/WebCore.gyp/scripts/action_derivedsourcesallinone.py b/WebCore/WebCore.gyp/scripts/action_derivedsourcesallinone.py index 6a11414..c9c5bf5 100644 --- a/WebCore/WebCore.gyp/scripts/action_derivedsourcesallinone.py +++ b/WebCore/WebCore.gyp/scripts/action_derivedsourcesallinone.py @@ -49,7 +49,7 @@ import subprocess import sys # A regexp for finding Conditional attributes in interface definitions. -conditionalPattern = re.compile('interface[\s]*\[[^\]]*Conditional=([\_0-9a-zA-Z&]*)') +conditionalPattern = re.compile('interface[\s]*\[[^\]]*Conditional=([\_0-9a-zA-Z&|]*)') copyrightTemplate = """/* * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT. @@ -82,11 +82,13 @@ copyrightTemplate = """/* """ -# Wraps conditional with ENABLE() and && if more than one conditional is specified. +# Wraps conditional with ENABLE() and replace '&','|' with '&&','||' if more than one conditional is specified. def formatConditional(conditional): def wrapWithEnable(s): + if re.match('[|&]$', s): + return s * 2 return 'ENABLE(' + s + ')' - return ' && '.join(map(wrapWithEnable, conditional)) + return ' '.join(map(wrapWithEnable, conditional)) # Find the conditional interface attribute. @@ -101,7 +103,7 @@ def extractConditional(idlFilePath): match = conditionalPattern.search(idlContents) if match: conditional = match.group(1) - conditional = conditional.split('&') + conditional = re.split('([|&])', conditional) return conditional diff --git a/WebCore/WebCore.gypi b/WebCore/WebCore.gypi index d4d6767..263bde2 100644 --- a/WebCore/WebCore.gypi +++ b/WebCore/WebCore.gypi @@ -18,10 +18,10 @@ 'css/CSSVariablesDeclaration.idl', 'css/CSSVariablesRule.idl', 'css/Counter.idl', - 'css/Media.idl', 'css/MediaList.idl', - 'css/RGBColor.idl', 'css/Rect.idl', + 'css/RGBColor.idl', + 'css/StyleMedia.idl', 'css/StyleSheet.idl', 'css/StyleSheetList.idl', 'css/WebKitCSSKeyframeRule.idl', @@ -109,6 +109,7 @@ 'html/DataGridColumnList.idl', 'html/DOMFormData.idl', 'html/File.idl', + 'html/FileError.idl', 'html/FileList.idl', 'html/HTMLAllCollection.idl', 'html/HTMLAnchorElement.idl', @@ -217,6 +218,7 @@ 'plugins/Plugin.idl', 'plugins/PluginArray.idl', 'storage/Database.idl', + 'storage/DatabaseCallback.idl', 'storage/IDBDatabaseError.idl', 'storage/IDBDatabaseException.idl', 'storage/IDBDatabaseRequest.idl', @@ -224,7 +226,11 @@ 'storage/SQLError.idl', 'storage/SQLResultSet.idl', 'storage/SQLResultSetRowList.idl', + 'storage/SQLStatementCallback.idl', + 'storage/SQLStatementErrorCallback.idl', 'storage/SQLTransaction.idl', + 'storage/SQLTransactionCallback.idl', + 'storage/SQLTransactionErrorCallback.idl', 'storage/Storage.idl', 'storage/StorageEvent.idl', 'websockets/WebSocket.idl', @@ -495,14 +501,7 @@ 'bindings/js/JSCustomPositionCallback.h', 'bindings/js/JSCustomPositionErrorCallback.cpp', 'bindings/js/JSCustomPositionErrorCallback.h', - 'bindings/js/JSCustomSQLStatementCallback.cpp', - 'bindings/js/JSCustomSQLStatementCallback.h', 'bindings/js/JSCustomSQLStatementErrorCallback.cpp', - 'bindings/js/JSCustomSQLStatementErrorCallback.h', - 'bindings/js/JSCustomSQLTransactionCallback.cpp', - 'bindings/js/JSCustomSQLTransactionCallback.h', - 'bindings/js/JSCustomSQLTransactionErrorCallback.cpp', - 'bindings/js/JSCustomSQLTransactionErrorCallback.h', 'bindings/js/JSCustomVoidCallback.cpp', 'bindings/js/JSCustomVoidCallback.h', 'bindings/js/JSCustomXPathNSResolver.cpp', @@ -515,7 +514,6 @@ 'bindings/js/JSDebugWrapperSet.cpp', 'bindings/js/JSDebugWrapperSet.h', 'bindings/js/JSDocumentCustom.cpp', - 'bindings/js/JSDocumentFragmentCustom.cpp', 'bindings/js/JSDOMApplicationCacheCustom.cpp', 'bindings/js/JSDOMBinding.cpp', 'bindings/js/JSDOMBinding.h', @@ -708,20 +706,11 @@ 'bindings/v8/custom/V8CustomPositionCallback.h', 'bindings/v8/custom/V8CustomPositionErrorCallback.cpp', 'bindings/v8/custom/V8CustomPositionErrorCallback.h', - 'bindings/v8/custom/V8CustomSQLStatementCallback.cpp', - 'bindings/v8/custom/V8CustomSQLStatementCallback.h', 'bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp', - 'bindings/v8/custom/V8CustomSQLStatementErrorCallback.h', - 'bindings/v8/custom/V8CustomSQLTransactionCallback.cpp', - 'bindings/v8/custom/V8CustomSQLTransactionCallback.h', - 'bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp', - 'bindings/v8/custom/V8CustomSQLTransactionErrorCallback.h', 'bindings/v8/custom/V8CustomVoidCallback.cpp', 'bindings/v8/custom/V8CustomVoidCallback.h', 'bindings/v8/custom/V8CustomXPathNSResolver.cpp', 'bindings/v8/custom/V8CustomXPathNSResolver.h', - 'bindings/v8/custom/V8DatabaseCallback.cpp', - 'bindings/v8/custom/V8DatabaseCallback.h', 'bindings/v8/custom/V8DatabaseCustom.cpp', 'bindings/v8/custom/V8DataGridColumnListCustom.cpp', 'bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp', @@ -768,8 +757,6 @@ 'bindings/v8/custom/V8NamedNodesCollection.cpp', 'bindings/v8/custom/V8NamedNodesCollection.h', 'bindings/v8/custom/V8NodeCustom.cpp', - 'bindings/v8/custom/V8NodeFilterCustom.cpp', - 'bindings/v8/custom/V8NodeIteratorCustom.cpp', 'bindings/v8/custom/V8NodeListCustom.cpp', 'bindings/v8/custom/V8NotificationCenterCustom.cpp', 'bindings/v8/custom/V8PopStateEventCustom.cpp', @@ -786,7 +773,6 @@ 'bindings/v8/custom/V8SharedWorkerCustom.cpp', 'bindings/v8/custom/V8StyleSheetCustom.cpp', 'bindings/v8/custom/V8StyleSheetListCustom.cpp', - 'bindings/v8/custom/V8TreeWalkerCustom.cpp', 'bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp', 'bindings/v8/custom/V8WebKitPointConstructor.cpp', 'bindings/v8/custom/V8WebSocketCustom.cpp', @@ -1015,33 +1001,33 @@ 'css/FontValue.h', 'css/MediaFeatureNames.cpp', 'css/MediaFeatureNames.h', - 'css/Media.cpp', - 'css/Media.h', 'css/MediaList.cpp', 'css/MediaList.h', 'css/MediaQuery.cpp', - 'css/MediaQuery.h', 'css/MediaQueryEvaluator.cpp', 'css/MediaQueryEvaluator.h', 'css/MediaQueryExp.cpp', 'css/MediaQueryExp.h', + 'css/MediaQuery.h', 'css/Pair.h', 'css/Rect.h', 'css/RGBColor.cpp', 'css/RGBColor.h', - 'css/SVGCSSComputedStyleDeclaration.cpp', - 'css/SVGCSSParser.cpp', - 'css/SVGCSSStyleSelector.cpp', 'css/ShadowValue.cpp', 'css/ShadowValue.h', 'css/StyleBase.cpp', 'css/StyleBase.h', 'css/StyleList.cpp', 'css/StyleList.h', + 'css/StyleMedia.cpp', + 'css/StyleMedia.h', 'css/StyleSheet.cpp', 'css/StyleSheet.h', 'css/StyleSheetList.cpp', 'css/StyleSheetList.h', + 'css/SVGCSSComputedStyleDeclaration.cpp', + 'css/SVGCSSParser.cpp', + 'css/SVGCSSStyleSelector.cpp', 'css/WebKitCSSKeyframeRule.cpp', 'css/WebKitCSSKeyframeRule.h', 'css/WebKitCSSKeyframesRule.cpp', @@ -1232,6 +1218,7 @@ 'dom/TransformSource.h', 'dom/Traversal.cpp', 'dom/Traversal.h', + 'dom/TreeDepthLimit.h', 'dom/TreeWalker.cpp', 'dom/TreeWalker.h', 'dom/UIEvent.cpp', @@ -1442,8 +1429,11 @@ 'html/DateComponents.h', 'html/File.cpp', 'html/File.h', + 'html/FileError.h', 'html/FileList.cpp', 'html/FileList.h', + 'html/FileReader.cpp', + 'html/FileReader.h', 'html/FileStream.cpp', 'html/FileStream.h', 'html/FileStreamClient.h', @@ -1650,6 +1640,8 @@ 'inspector/InspectorBackend.h', 'inspector/InspectorController.cpp', 'inspector/InspectorController.h', + 'inspector/InspectorCSSStore.cpp', + 'inspector/InspectorCSSStore.h', 'inspector/InspectorDatabaseResource.cpp', 'inspector/InspectorDatabaseResource.h', 'inspector/InspectorDOMAgent.cpp', @@ -2163,6 +2155,8 @@ 'platform/graphics/mac/MediaPlayerPrivateQTKit.h', 'platform/graphics/mac/MediaPlayerPrivateQTKit.mm', 'platform/graphics/mac/MediaPlayerProxy.h', + 'platform/graphics/mac/SimpleFontDataATSUI.mm', + 'platform/graphics/mac/SimpleFontDataCoreText.cpp', 'platform/graphics/mac/SimpleFontDataMac.mm', 'platform/graphics/mac/WebLayer.h', 'platform/graphics/mac/WebLayer.mm', @@ -2341,10 +2335,9 @@ 'platform/graphics/GeneratedImage.h', 'platform/graphics/Generator.h', 'platform/graphics/GlyphBuffer.h', + 'platform/graphics/GlyphMetricsMap.h', 'platform/graphics/GlyphPageTreeNode.cpp', 'platform/graphics/GlyphPageTreeNode.h', - 'platform/graphics/GlyphMetricsMap.cpp', - 'platform/graphics/GlyphMetricsMap.h', 'platform/graphics/Gradient.cpp', 'platform/graphics/Gradient.h', 'platform/graphics/GraphicsContext.cpp', @@ -2661,7 +2654,7 @@ 'platform/qt/SharedBufferQt.cpp', 'platform/qt/SharedTimerQt.cpp', 'platform/qt/SoundQt.cpp', - 'platform/qt/TemporaryLinkStubs.cpp', + 'platform/qt/TemporaryLinkStubsQt.cpp', 'platform/qt/WheelEventQt.cpp', 'platform/qt/WidgetQt.cpp', 'platform/sql/SQLValue.cpp', @@ -3169,15 +3162,26 @@ 'rendering/RenderSVGInlineText.h', 'rendering/RenderSVGModelObject.cpp', 'rendering/RenderSVGModelObject.h', + 'rendering/RenderSVGResource.cpp', 'rendering/RenderSVGResource.h', 'rendering/RenderSVGResourceClipper.cpp', 'rendering/RenderSVGResourceClipper.h', 'rendering/RenderSVGResourceFilter.cpp', 'rendering/RenderSVGResourceFilter.h', + 'rendering/RenderSVGResourceGradient.cpp', + 'rendering/RenderSVGResourceGradient.h', + 'rendering/RenderSVGResourceLinearGradient.cpp', + 'rendering/RenderSVGResourceLinearGradient.h', 'rendering/RenderSVGResourceMarker.cpp', 'rendering/RenderSVGResourceMarker.h', 'rendering/RenderSVGResourceMasker.cpp', 'rendering/RenderSVGResourceMasker.h', + 'rendering/RenderSVGResourcePattern.cpp', + 'rendering/RenderSVGResourcePattern.h', + 'rendering/RenderSVGResourceRadialGradient.cpp', + 'rendering/RenderSVGResourceRadialGradient.h', + 'rendering/RenderSVGResourceSolidColor.cpp', + 'rendering/RenderSVGResourceSolidColor.h', 'rendering/RenderSVGRoot.cpp', 'rendering/RenderSVGRoot.h', 'rendering/RenderSVGShadowTreeRootContainer.cpp', @@ -3251,6 +3255,8 @@ 'rendering/RootInlineBox.h', 'rendering/ScrollBehavior.cpp', 'rendering/ScrollBehavior.h', + 'rendering/SVGCharacterData.cpp', + 'rendering/SVGCharacterData.h', 'rendering/SVGCharacterLayoutInfo.cpp', 'rendering/SVGCharacterLayoutInfo.h', 'rendering/SVGInlineFlowBox.cpp', @@ -3268,6 +3274,7 @@ 'rendering/SVGRootInlineBox.h', 'rendering/SVGShadowTreeElements.cpp', 'rendering/SVGShadowTreeElements.h', + 'rendering/SVGTextChunkLayoutInfo.h', 'rendering/TableLayout.h', 'rendering/TextControlInnerElements.cpp', 'rendering/TextControlInnerElements.h', @@ -3289,6 +3296,8 @@ 'storage/DatabaseAuthorizer.h', 'storage/DatabaseCallback.h', 'storage/DatabaseDetails.h', + 'storage/DatabaseSync.cpp', + 'storage/DatabaseSync.h', 'storage/DatabaseTask.cpp', 'storage/DatabaseTask.h', 'storage/DatabaseThread.cpp', @@ -3334,6 +3343,9 @@ 'storage/SQLTransactionCoordinator.h', 'storage/SQLTransactionCoordinator.cpp', 'storage/SQLTransactionErrorCallback.h', + 'storage/SQLTransactionSync.cpp', + 'storage/SQLTransactionSync.h', + 'storage/SQLTransactionSyncCallback.h', 'storage/Storage.cpp', 'storage/Storage.h', 'storage/StorageArea.h', @@ -3392,21 +3404,6 @@ 'svg/graphics/filters/SVGSpotLightSource.h', 'svg/graphics/SVGImage.cpp', 'svg/graphics/SVGImage.h', - 'svg/graphics/SVGPaintServer.cpp', - 'svg/graphics/SVGPaintServer.h', - 'svg/graphics/SVGPaintServerGradient.cpp', - 'svg/graphics/SVGPaintServerGradient.h', - 'svg/graphics/SVGPaintServerLinearGradient.cpp', - 'svg/graphics/SVGPaintServerLinearGradient.h', - 'svg/graphics/SVGPaintServerPattern.cpp', - 'svg/graphics/SVGPaintServerPattern.h', - 'svg/graphics/SVGPaintServerRadialGradient.cpp', - 'svg/graphics/SVGPaintServerRadialGradient.h', - 'svg/graphics/SVGPaintServerSolid.cpp', - 'svg/graphics/SVGPaintServerSolid.h', - 'svg/graphics/SVGResource.cpp', - 'svg/graphics/SVGResource.h', - 'svg/graphics/SVGResourceListener.h', 'svg/ColorDistance.cpp', 'svg/ColorDistance.h', 'svg/ElementTimeControl.h', diff --git a/WebCore/WebCore.pri b/WebCore/WebCore.pri index e45bd99..0581dae 100644 --- a/WebCore/WebCore.pri +++ b/WebCore/WebCore.pri @@ -4,6 +4,10 @@ CONFIG(standalone_package) { isEmpty(WC_GENERATED_SOURCES_DIR):WC_GENERATED_SOURCES_DIR = generated } +CONFIG(minimal) { + DEFINES += ENABLE_NETSCAPE_PLUGIN_API=0 +} + ## Define default features macros for optional components ## (look for defs in config.h and included files!) # Try to locate sqlite3 source @@ -159,9 +163,12 @@ contains(DEFINES, ENABLE_WEB_SOCKETS=1): FEATURE_DEFINES_JAVASCRIPT += ENABLE_WE contains(DEFINES, ENABLE_TOUCH_EVENTS=1): FEATURE_DEFINES_JAVASCRIPT += ENABLE_TOUCH_EVENTS=1 contains(DEFINES, ENABLE_TILED_BACKING_STORE=1): FEATURE_DEFINES_JAVASCRIPT += ENABLE_TILED_BACKING_STORE=1 contains(DEFINES, ENABLE_NOTIFICATIONS=1): FEATURE_DEFINES_JAVASCRIPT += ENABLE_NOTIFICATIONS=1 +contains(DEFINES, ENABLE_PROGRESS_TAG=1): FEATURE_DEFINES_JAVASCRIPT += ENABLE_PROGRESS_TAG=1 ## Derived source generators +MATHML_NAMES = $$PWD/mathml/mathtags.in + WML_NAMES = $$PWD/wml/WMLTagNames.in SVG_NAMES = $$PWD/svg/svgtags.in @@ -205,6 +212,7 @@ contains(DEFINES, ENABLE_WCSS=1) { STYLESHEETS_EMBED = \ $$PWD/css/html.css \ $$PWD/css/quirks.css \ + $$PWD/css/mathml.css \ $$PWD/css/svg.css \ $$PWD/css/view-source.css \ $$PWD/css/wml.css \ @@ -230,10 +238,10 @@ IDL_BINDINGS += \ css/CSSValueList.idl \ css/CSSVariablesDeclaration.idl \ css/CSSVariablesRule.idl \ - css/Media.idl \ css/MediaList.idl \ - css/RGBColor.idl \ css/Rect.idl \ + css/RGBColor.idl \ + css/StyleMedia.idl \ css/StyleSheet.idl \ css/StyleSheetList.idl \ css/WebKitCSSKeyframeRule.idl \ @@ -320,6 +328,7 @@ IDL_BINDINGS += \ html/DataGridColumnList.idl \ html/DOMFormData.idl \ html/File.idl \ + html/FileError.idl \ html/FileList.idl \ html/HTMLAllCollection.idl \ html/HTMLAudioElement.idl \ @@ -427,12 +436,17 @@ IDL_BINDINGS += \ plugins/PluginArray.idl \ plugins/MimeTypeArray.idl \ storage/Database.idl \ + storage/DatabaseCallback.idl \ storage/Storage.idl \ storage/StorageEvent.idl \ storage/SQLError.idl \ storage/SQLResultSet.idl \ storage/SQLResultSetRowList.idl \ + storage/SQLStatementCallback.idl \ + storage/SQLStatementErrorCallback.idl \ storage/SQLTransaction.idl \ + storage/SQLTransactionCallback.idl \ + storage/SQLTransactionErrorCallback.idl \ svg/SVGZoomEvent.idl \ svg/SVGAElement.idl \ svg/SVGAltGlyphElement.idl \ @@ -587,6 +601,15 @@ IDL_BINDINGS += \ xml/XPathEvaluator.idl \ xml/XSLTProcessor.idl +contains(DEFINES, ENABLE_MATHML=1) { + mathmlnames.output = $${WC_GENERATED_SOURCES_DIR}/MathMLNames.cpp + mathmlnames.input = MATHML_NAMES + mathmlnames.wkScript = $$PWD/dom/make_names.pl + mathmlnames.commands = perl -I$$PWD/bindings/scripts $$mathmlnames.wkScript --tags $$PWD/mathml/mathtags.in --attrs $$PWD/mathml/mathattrs.in --extraDefines \"$${DEFINES}\" --preprocessor \"$${QMAKE_MOC} -E\" --factory --wrapperFactory --outputDir $$WC_GENERATED_SOURCES_DIR + mathmlnames.wkExtraSources = $${WC_GENERATED_SOURCES_DIR}/MathMLElementFactory.cpp + addExtraCompiler(mathmlnames) +} + contains(DEFINES, ENABLE_WML=1) { wmlnames.output = $${WC_GENERATED_SOURCES_DIR}/WMLNames.cpp wmlnames.input = WML_NAMES diff --git a/WebCore/WebCore.pro b/WebCore/WebCore.pro index 8d90003..b17f12c 100644 --- a/WebCore/WebCore.pro +++ b/WebCore/WebCore.pro @@ -35,6 +35,9 @@ symbian: { # Move RW-section base address to start from 0xE00000 instead of the toolchain default 0x400000. QMAKE_LFLAGS.ARMCC += --rw-base 0xE00000 MMP_RULES += ALWAYS_BUILD_AS_ARM + } else { + QMAKE_CFLAGS -= --thumb + QMAKE_CXXFLAGS -= --thumb } CONFIG(release, debug|release): QMAKE_CXXFLAGS.ARMCC += -OTime -O3 } @@ -52,8 +55,6 @@ CONFIG(standalone_package) { isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = $$PWD/../JavaScriptCore/generated PRECOMPILED_HEADER = $$PWD/../WebKit/qt/WebKit_pch.h - - symbian: TARGET += $${QT_LIBINFIX} } else { isEmpty(WC_GENERATED_SOURCES_DIR):WC_GENERATED_SOURCES_DIR = generated isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = ../JavaScriptCore/generated @@ -68,12 +69,13 @@ CONFIG(standalone_package) { CONFIG(QTDIR_build) { include($$QT_SOURCE_TREE/src/qbase.pri) - # Qt will set the version for us when building in Qt's tree } else { - VERSION = $${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} DESTDIR = $$OUTPUT_DIR/lib !static: DEFINES += QT_MAKEDLL + symbian: TARGET =$$TARGET$${QT_LIBINFIX} } +include($$PWD/../WebKit/qt/qtwebkit_version.pri) +VERSION = $${QT_WEBKIT_MAJOR_VERSION}.$${QT_WEBKIT_MINOR_VERSION}.$${QT_WEBKIT_PATCH_VERSION} unix { QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui QtNetwork @@ -88,9 +90,6 @@ CONFIG(release):!CONFIG(standalone_package) { unix:contains(QT_CONFIG, reduce_relocations):CONFIG += bsymbolic_functions } -linux-*: DEFINES += HAVE_STDINT_H -freebsd-*: DEFINES += HAVE_PTHREAD_NP_H - DEFINES += BUILD_WEBKIT # Remove whole program optimizations due to miscompilations @@ -123,7 +122,11 @@ maemo5|symbian|embedded { DEFINES += ENABLE_FAST_MOBILE_SCROLLING=1 } -maemo5 { +maemo5|symbian { + DEFINES += WTF_USE_QT_MOBILE_THEME=1 +} + +contains(DEFINES, WTF_USE_QT_MOBILE_THEME=1) { DEFINES += ENABLE_NO_LISTBOX_RENDERING=1 } @@ -132,17 +135,12 @@ addJavaScriptCoreLib(../JavaScriptCore) # HTML5 Media Support -# We require phonon for versions of Qt < 4.7 -# We require QtMultimedia for versions of Qt >= 4.7 +# We require phonon. QtMultimedia support is disabled currently. !contains(DEFINES, ENABLE_VIDEO=.) { DEFINES -= ENABLE_VIDEO=1 DEFINES += ENABLE_VIDEO=0 - lessThan(QT_MINOR_VERSION, 7):contains(QT_CONFIG, phonon) { - DEFINES -= ENABLE_VIDEO=0 - DEFINES += ENABLE_VIDEO=1 - } - !lessThan(QT_MINOR_VERSION, 7):contains(QT_CONFIG, multimedia) { + contains(QT_CONFIG, phonon) { DEFINES -= ENABLE_VIDEO=0 DEFINES += ENABLE_VIDEO=1 } @@ -188,6 +186,7 @@ INCLUDEPATH = \ $$PWD/loader/appcache \ $$PWD/loader/archive \ $$PWD/loader/icon \ + $$PWD/mathml \ $$PWD/notifications \ $$PWD/page \ $$PWD/page/animation \ @@ -289,7 +288,6 @@ SOURCES += \ bindings/js/JSDebugWrapperSet.cpp \ bindings/js/JSDesktopNotificationsCustom.cpp \ bindings/js/JSDocumentCustom.cpp \ - bindings/js/JSDocumentFragmentCustom.cpp \ bindings/js/JSDOMFormDataCustom.cpp \ bindings/js/JSDOMGlobalObject.cpp \ bindings/js/JSDOMWindowBase.cpp \ @@ -299,7 +297,6 @@ SOURCES += \ bindings/js/JSElementCustom.cpp \ bindings/js/JSEventCustom.cpp \ bindings/js/JSEventSourceConstructor.cpp \ - bindings/js/JSEventSourceCustom.cpp \ bindings/js/JSEventTarget.cpp \ bindings/js/JSExceptionBase.cpp \ bindings/js/JSGeolocationCustom.cpp \ @@ -429,7 +426,6 @@ SOURCES += \ css/FontFamilyValue.cpp \ css/FontValue.cpp \ css/MediaFeatureNames.cpp \ - css/Media.cpp \ css/MediaList.cpp \ css/MediaQuery.cpp \ css/MediaQueryEvaluator.cpp \ @@ -438,6 +434,7 @@ SOURCES += \ css/ShadowValue.cpp \ css/StyleBase.cpp \ css/StyleList.cpp \ + css/StyleMedia.cpp \ css/StyleSheet.cpp \ css/StyleSheetList.cpp \ css/WebKitCSSKeyframeRule.cpp \ @@ -570,7 +567,6 @@ SOURCES += \ editing/ReplaceSelectionCommand.cpp \ editing/SelectionController.cpp \ editing/SetNodeAttributeCommand.cpp \ - editing/SmartReplace.cpp \ editing/SmartReplaceICU.cpp \ editing/SplitElementCommand.cpp \ editing/SplitTextNodeCommand.cpp \ @@ -603,6 +599,7 @@ SOURCES += \ html/DOMFormData.cpp \ html/File.cpp \ html/FileList.cpp \ + html/FileReader.cpp \ html/FileStream.cpp \ html/FileStreamProxy.cpp \ html/FileThread.cpp \ @@ -697,6 +694,7 @@ SOURCES += \ inspector/InjectedScript.cpp \ inspector/InjectedScriptHost.cpp \ inspector/InspectorBackend.cpp \ + inspector/InspectorCSSStore.cpp \ inspector/InspectorController.cpp \ inspector/InspectorDatabaseResource.cpp \ inspector/InspectorDOMAgent.cpp \ @@ -1027,13 +1025,8 @@ HEADERS += \ bindings/js/JSCSSStyleDeclarationCustom.h \ bindings/js/JSCustomPositionCallback.h \ bindings/js/JSCustomPositionErrorCallback.h \ - bindings/js/JSCustomSQLStatementCallback.h \ - bindings/js/JSCustomSQLStatementErrorCallback.h \ - bindings/js/JSCustomSQLTransactionCallback.h \ - bindings/js/JSCustomSQLTransactionErrorCallback.h \ bindings/js/JSCustomVoidCallback.h \ bindings/js/JSCustomXPathNSResolver.h \ - bindings/js/JSDatabaseCallback.h \ bindings/js/JSDataGridDataSource.h \ bindings/js/JSDebugWrapperSet.h \ bindings/js/JSDOMBinding.h \ @@ -1155,7 +1148,6 @@ HEADERS += \ css/FontFamilyValue.h \ css/FontValue.h \ css/MediaFeatureNames.h \ - css/Media.h \ css/MediaList.h \ css/MediaQueryEvaluator.h \ css/MediaQueryExp.h \ @@ -1164,6 +1156,7 @@ HEADERS += \ css/ShadowValue.h \ css/StyleBase.h \ css/StyleList.h \ + css/StyleMedia.h \ css/StyleSheet.h \ css/StyleSheetList.h \ css/WebKitCSSKeyframeRule.h \ @@ -1248,6 +1241,7 @@ HEADERS += \ dom/TouchList.h \ dom/TransformSource.h \ dom/Traversal.h \ + dom/TreeDepthLimit.h \ dom/TreeWalker.h \ dom/UIEvent.h \ dom/UIEventWithKeyState.h \ @@ -1321,7 +1315,9 @@ HEADERS += \ html/DOMDataGridDataSource.h \ html/DOMFormData.h \ html/File.h \ + html/FileError.h \ html/FileList.h \ + html/FileReader.h \ html/FileStream.h \ html/FileStreamClient.h \ html/FileStreamProxy.h \ @@ -1483,6 +1479,19 @@ HEADERS += \ loader/TextResourceDecoder.h \ loader/ThreadableLoader.h \ loader/WorkerThreadableLoader.h \ + mathml/MathMLElement.h \ + mathml/MathMLInlineContainerElement.h \ + mathml/MathMLMathElement.h \ + mathml/MathMLTextElement.h \ + mathml/RenderMathMLBlock.h \ + mathml/RenderMathMLFraction.h \ + mathml/RenderMathMLMath.h \ + mathml/RenderMathMLOperator.h \ + mathml/RenderMathMLRoot.h \ + mathml/RenderMathMLRow.h \ + mathml/RenderMathMLSquareRoot.h \ + mathml/RenderMathMLSubSup.h \ + mathml/RenderMathMLUnderOver.h \ notifications/Notification.h \ notifications/NotificationCenter.h \ notifications/NotificationPresenter.h \ @@ -1730,9 +1739,14 @@ HEADERS += \ rendering/RenderSVGModelObject.h \ rendering/RenderSVGResource.h \ rendering/RenderSVGResourceClipper.h \ - rendering/RenderSVGResourceFilter.h \ + rendering/RenderSVGResourceFilter.h \ + rendering/RenderSVGResourceGradient.h \ + rendering/RenderSVGResourceLinearGradient.h \ rendering/RenderSVGResourceMarker.h \ rendering/RenderSVGResourceMasker.h \ + rendering/RenderSVGResourcePattern.h \ + rendering/RenderSVGResourceRadialGradient.h \ + rendering/RenderSVGResourceSolidColor.h \ rendering/RenderSVGRoot.h \ rendering/RenderSVGShadowTreeRootContainer.h \ rendering/RenderSVGText.h \ @@ -1784,6 +1798,7 @@ HEADERS += \ rendering/style/StyleVisualData.h \ rendering/style/SVGRenderStyleDefs.h \ rendering/style/SVGRenderStyle.h \ + rendering/SVGCharacterData.h \ rendering/SVGCharacterLayoutInfo.h \ rendering/SVGInlineFlowBox.h \ rendering/SVGInlineTextBox.h \ @@ -1793,6 +1808,7 @@ HEADERS += \ rendering/SVGRenderTreeAsText.h \ rendering/SVGRootInlineBox.h \ rendering/SVGShadowTreeElements.h \ + rendering/SVGTextChunkLayoutInfo.h \ rendering/TextControlInnerElements.h \ rendering/TransformState.h \ svg/animation/SMILTimeContainer.h \ @@ -1814,13 +1830,6 @@ HEADERS += \ svg/graphics/filters/SVGFilter.h \ svg/graphics/filters/SVGLightSource.h \ svg/graphics/SVGImage.h \ - svg/graphics/SVGPaintServerGradient.h \ - svg/graphics/SVGPaintServer.h \ - svg/graphics/SVGPaintServerLinearGradient.h \ - svg/graphics/SVGPaintServerPattern.h \ - svg/graphics/SVGPaintServerRadialGradient.h \ - svg/graphics/SVGPaintServerSolid.h \ - svg/graphics/SVGResource.h \ svg/SVGAElement.h \ svg/SVGAltGlyphElement.h \ svg/SVGAngle.h \ @@ -2031,6 +2040,7 @@ HEADERS += \ $$PWD/../WebKit/qt/WebCoreSupport/QtFallbackWebPopup.h \ $$PWD/../WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h \ $$PWD/../WebKit/qt/WebCoreSupport/NotificationPresenterClientQt.h \ + $$PWD/../WebKit/qt/WebCoreSupport/PageClientQt.h \ $$PWD/platform/network/qt/DnsPrefetchHelper.h SOURCES += \ @@ -2066,6 +2076,7 @@ SOURCES += \ platform/network/qt/DnsPrefetchHelper.cpp \ platform/network/qt/QNetworkReplyHandler.cpp \ editing/qt/EditorQt.cpp \ + editing/qt/SmartReplaceQt.cpp \ platform/qt/ClipboardQt.cpp \ platform/qt/ContextMenuItemQt.cpp \ platform/qt/ContextMenuQt.cpp \ @@ -2101,7 +2112,7 @@ SOURCES += \ platform/qt/SharedTimerQt.cpp \ platform/qt/SoundQt.cpp \ platform/qt/LoggingQt.cpp \ - platform/qt/TemporaryLinkStubs.cpp \ + platform/qt/TemporaryLinkStubsQt.cpp \ platform/text/qt/TextBoundariesQt.cpp \ platform/text/qt/TextBreakIteratorQt.cpp \ platform/text/qt/TextCodecQt.cpp \ @@ -2118,6 +2129,7 @@ SOURCES += \ ../WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp \ ../WebKit/qt/WebCoreSupport/InspectorClientQt.cpp \ ../WebKit/qt/WebCoreSupport/NotificationPresenterClientQt.cpp \ + ../WebKit/qt/WebCoreSupport/PageClientQt.cpp \ ../WebKit/qt/Api/qwebframe.cpp \ ../WebKit/qt/Api/qgraphicswebview.cpp \ ../WebKit/qt/Api/qwebpage.cpp \ @@ -2133,13 +2145,15 @@ SOURCES += \ ../WebKit/qt/Api/qwebinspector.cpp \ ../WebKit/qt/Api/qwebkitversion.cpp + +contains(DEFINES, WTF_USE_QT_MOBILE_THEME=1) { + HEADERS += platform/qt/Maemo5Webstyle.h + SOURCES += platform/qt/Maemo5Webstyle.cpp +} + maemo5 { - HEADERS += \ - ../WebKit/qt/WebCoreSupport/QtMaemoWebPopup.h \ - platform/qt/Maemo5Webstyle.h - SOURCES += \ - ../WebKit/qt/WebCoreSupport/QtMaemoWebPopup.cpp \ - platform/qt/Maemo5Webstyle.cpp + HEADERS += ../WebKit/qt/WebCoreSupport/QtMaemoWebPopup.h + SOURCES += ../WebKit/qt/WebCoreSupport/QtMaemoWebPopup.cpp } @@ -2150,8 +2164,7 @@ maemo5 { SOURCES += \ platform/text/cf/StringCF.cpp \ platform/text/cf/StringImplCF.cpp \ - platform/cf/SharedBufferCF.cpp \ - editing/SmartReplaceCF.cpp + platform/cf/SharedBufferCF.cpp LIBS_PRIVATE += -framework Carbon -framework AppKit } @@ -2160,7 +2173,10 @@ maemo5 { LIBS += -lOle32 LIBS += -luser32 } - wince*: LIBS += -lmmtimer + wince* { + LIBS += -lmmtimer + LIBS += -lOle32 + } contains(DEFINES, ENABLE_NETSCAPE_PLUGIN_API=1) { @@ -2262,7 +2278,8 @@ contains(DEFINES, ENABLE_SQLITE=1) { platform/sql/SQLiteTransaction.cpp \ platform/sql/SQLValue.cpp \ storage/Database.cpp \ - storage/DatabaseAuthorizer.cpp + storage/DatabaseAuthorizer.cpp \ + storage/DatabaseSync.cpp } @@ -2280,11 +2297,8 @@ contains(DEFINES, ENABLE_DATABASE=1) { storage/SQLTransaction.cpp \ storage/SQLTransactionClient.cpp \ storage/SQLTransactionCoordinator.cpp \ - bindings/js/JSCustomSQLStatementCallback.cpp \ + storage/SQLTransactionSync.cpp \ bindings/js/JSCustomSQLStatementErrorCallback.cpp \ - bindings/js/JSCustomSQLTransactionCallback.cpp \ - bindings/js/JSCustomSQLTransactionErrorCallback.cpp \ - bindings/js/JSDatabaseCallback.cpp \ bindings/js/JSDatabaseCustom.cpp \ bindings/js/JSSQLResultSetRowListCustom.cpp \ bindings/js/JSSQLTransactionCustom.cpp @@ -2296,6 +2310,7 @@ contains(DEFINES, ENABLE_DOM_STORAGE=1) { storage/DatabaseAuthorizer.h \ storage/Database.h \ storage/DatabaseCallback.h \ + storage/DatabaseSync.h \ storage/DatabaseTask.h \ storage/DatabaseThread.h \ storage/DatabaseTracker.h \ @@ -2309,6 +2324,7 @@ contains(DEFINES, ENABLE_DOM_STORAGE=1) { storage/SQLTransaction.h \ storage/SQLTransactionClient.h \ storage/SQLTransactionCoordinator.h \ + storage/SQLTransactionSync.h \ storage/StorageArea.h \ storage/StorageAreaImpl.h \ storage/StorageAreaSync.h \ @@ -2347,7 +2363,6 @@ contains(DEFINES, ENABLE_ICONDATABASE=1) { contains(DEFINES, ENABLE_WORKERS=1) { SOURCES += \ - bindings/js/JSAbstractWorkerCustom.cpp \ bindings/js/JSDedicatedWorkerContextCustom.cpp \ bindings/js/JSWorkerConstructor.cpp \ bindings/js/JSWorkerContextBase.cpp \ @@ -2391,12 +2406,12 @@ contains(DEFINES, ENABLE_VIDEO=1) { rendering/RenderMedia.cpp \ bindings/js/JSAudioConstructor.cpp - # QtMultimedia since 4.7 - greaterThan(QT_MINOR_VERSION, 6) { + # QtMultimedia disabled currently + false:greaterThan(QT_MINOR_VERSION, 6) { HEADERS += platform/graphics/qt/MediaPlayerPrivateQt.h SOURCES += platform/graphics/qt/MediaPlayerPrivateQt.cpp - QT += multimedia + tobe|!tobe: QT += mediaservices } else { HEADERS += \ platform/graphics/qt/MediaPlayerPrivatePhonon.h @@ -2464,6 +2479,23 @@ contains(DEFINES, ENABLE_FILTERS=1) { platform/graphics/filters/SourceGraphic.cpp } +contains(DEFINES, ENABLE_MATHML=1) { + SOURCES += \ + mathml/MathMLElement.cpp \ + mathml/MathMLInlineContainerElement.cpp \ + mathml/MathMLMathElement.cpp \ + mathml/MathMLTextElement.cpp \ + mathml/RenderMathMLBlock.cpp \ + mathml/RenderMathMLFraction.cpp \ + mathml/RenderMathMLMath.cpp \ + mathml/RenderMathMLOperator.cpp \ + mathml/RenderMathMLRoot.cpp \ + mathml/RenderMathMLRow.cpp \ + mathml/RenderMathMLSquareRoot.cpp \ + mathml/RenderMathMLSubSup.cpp \ + mathml/RenderMathMLUnderOver.cpp +} + contains(DEFINES, ENABLE_WML=1) { SOURCES += \ wml/WMLAElement.cpp \ @@ -2683,13 +2715,6 @@ contains(DEFINES, ENABLE_SVG=1) { svg/graphics/filters/SVGFilterBuilder.cpp \ svg/graphics/filters/SVGLightSource.cpp \ svg/graphics/SVGImage.cpp \ - svg/graphics/SVGPaintServer.cpp \ - svg/graphics/SVGPaintServerGradient.cpp \ - svg/graphics/SVGPaintServerLinearGradient.cpp \ - svg/graphics/SVGPaintServerPattern.cpp \ - svg/graphics/SVGPaintServerRadialGradient.cpp \ - svg/graphics/SVGPaintServerSolid.cpp \ - svg/graphics/SVGResource.cpp \ rendering/RenderForeignObject.cpp \ rendering/RenderPath.cpp \ rendering/RenderSVGBlock.cpp \ @@ -2700,10 +2725,16 @@ contains(DEFINES, ENABLE_SVG=1) { rendering/RenderSVGInline.cpp \ rendering/RenderSVGInlineText.cpp \ rendering/RenderSVGModelObject.cpp \ + rendering/RenderSVGResource.cpp \ rendering/RenderSVGResourceClipper.cpp \ rendering/RenderSVGResourceFilter.cpp \ + rendering/RenderSVGResourceGradient.cpp \ + rendering/RenderSVGResourceLinearGradient.cpp \ rendering/RenderSVGResourceMarker.cpp \ rendering/RenderSVGResourceMasker.cpp \ + rendering/RenderSVGResourcePattern.cpp \ + rendering/RenderSVGResourceRadialGradient.cpp \ + rendering/RenderSVGResourceSolidColor.cpp \ rendering/RenderSVGRoot.cpp \ rendering/RenderSVGShadowTreeRootContainer.cpp \ rendering/RenderSVGText.cpp \ @@ -2711,6 +2742,7 @@ contains(DEFINES, ENABLE_SVG=1) { rendering/RenderSVGTransformableContainer.cpp \ rendering/RenderSVGTSpan.cpp \ rendering/RenderSVGViewportContainer.cpp \ + rendering/SVGCharacterData.cpp \ rendering/SVGCharacterLayoutInfo.cpp \ rendering/SVGInlineFlowBox.cpp \ rendering/SVGInlineTextBox.cpp \ @@ -2772,7 +2804,7 @@ contains(DEFINES, ENABLE_WEB_SOCKETS=1) { } contains(DEFINES, ENABLE_3D_CANVAS=1) { -QT += opengl +tobe|!tobe: QT += opengl HEADERS += \ bindings/js/JSWebGLArrayBufferConstructor.h \ bindings/js/JSWebGLArrayHelper.h \ @@ -2973,3 +3005,6 @@ symbian { } } } + +# Disable C++0x mode in WebCore for those who enabled it in their Qt's mkspec +*-g++*:QMAKE_CXXFLAGS -= -std=c++0x -std=gnu++0x diff --git a/WebCore/WebCore.vcproj/WebCore.vcproj b/WebCore/WebCore.vcproj/WebCore.vcproj index 0c624c2..eeb9d7f 100644 --- a/WebCore/WebCore.vcproj/WebCore.vcproj +++ b/WebCore/WebCore.vcproj/WebCore.vcproj @@ -3693,6 +3693,14 @@ >
</File>
<File
+ RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSFileError.cpp"
+ >
+ </File>
+ <File
+ RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSFileError.h"
+ >
+ </File>
+ <File
RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSFileList.cpp"
>
<FileConfiguration
@@ -8141,7 +8149,7 @@ >
</File>
<File
- RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSMedia.cpp"
+ RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSStyleMedia.cpp"
>
<FileConfiguration
Name="Debug|Win32"
@@ -8193,7 +8201,7 @@ </FileConfiguration>
</File>
<File
- RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSMedia.h"
+ RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSStyleMedia.h"
>
</File>
<File
@@ -22862,10 +22870,6 @@ >
</File>
<File
- RelativePath="..\platform\graphics\GlyphMetricsMap.cpp"
- >
- </File>
- <File
RelativePath="..\platform\graphics\GlyphMetricsMap.h"
>
</File>
@@ -23505,7 +23509,7 @@ >
</File>
<File
- RelativePath="..\platform\graphics\win\RefCountedHFONT.h"
+ RelativePath="..\platform\graphics\win\RefCountedGDIHandle.h"
>
</File>
<File
@@ -27171,11 +27175,11 @@ >
</File>
<File
- RelativePath="..\css\Media.cpp"
+ RelativePath="..\css\StyleMedia.cpp"
>
</File>
<File
- RelativePath="..\css\Media.h"
+ RelativePath="..\css\StyleMedia.h"
>
</File>
<File
@@ -27939,6 +27943,10 @@ >
</File>
<File
+ RelativePath="..\rendering\RenderSVGResource.cpp"
+ >
+ </File>
+ <File
RelativePath="..\rendering\RenderSVGResource.h"
>
</File>
@@ -27959,6 +27967,22 @@ >
</File>
<File
+ RelativePath="..\rendering\RenderSVGResourceGradient.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\rendering\RenderSVGResourceGradient.h"
+ >
+ </File>
+ <File
+ RelativePath="..\rendering\RenderSVGResourceLinearGradient.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\rendering\RenderSVGResourceLinearGradient.h"
+ >
+ </File>
+ <File
RelativePath="..\rendering\RenderSVGResourceMarker.cpp"
>
</File>
@@ -27975,6 +27999,30 @@ >
</File>
<File
+ RelativePath="..\rendering\RenderSVGResourcePattern.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\rendering\RenderSVGResourcePattern.h"
+ >
+ </File>
+ <File
+ RelativePath="..\rendering\RenderSVGResourceRadialGradient.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\rendering\RenderSVGResourceRadialGradient.h"
+ >
+ </File>
+ <File
+ RelativePath="..\rendering\RenderSVGResourceSolidColor.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\rendering\RenderSVGResourceSolidColor.h"
+ >
+ </File>
+ <File
RelativePath="..\rendering\RenderSVGRoot.cpp"
>
</File>
@@ -28261,6 +28309,14 @@ >
</File>
<File
+ RelativePath="..\rendering\SVGCharacterData.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\rendering\SVGCharacterData.h"
+ >
+ </File>
+ <File
RelativePath="..\rendering\SVGCharacterLayoutInfo.cpp"
>
</File>
@@ -28329,6 +28385,10 @@ >
</File>
<File
+ RelativePath="..\rendering\SVGTextChunkLayoutInfo.h"
+ >
+ </File>
+ <File
RelativePath="..\rendering\TableLayout.h"
>
</File>
@@ -29555,6 +29615,10 @@ >
</File>
<File
+ RelativePath="..\dom\TreeDepthLimit.h"
+ >
+ </File>
+ <File
RelativePath="..\dom\TreeWalker.cpp"
>
</File>
@@ -30331,6 +30395,10 @@ >
</File>
<File
+ RelativePath="..\html\FileError.h"
+ >
+ </File>
+ <File
RelativePath="..\html\FileList.cpp"
>
</File>
@@ -30339,6 +30407,14 @@ >
</File>
<File
+ RelativePath="..\html\FileReader.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\html\FileReader.h"
+ >
+ </File>
+ <File
RelativePath="..\html\FileStream.cpp"
>
</File>
@@ -34731,58 +34807,6 @@ >
</File>
<File
- RelativePath="..\bindings\js\JSAbstractWorkerCustom.cpp"
- >
- <FileConfiguration
- Name="Debug|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_Internal|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_Cairo|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release_Cairo|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_All|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- </File>
- <File
RelativePath="..\bindings\js\JSAttrCustom.cpp"
>
<FileConfiguration
@@ -35479,62 +35503,6 @@ >
</File>
<File
- RelativePath="..\bindings\js\JSCustomSQLStatementCallback.cpp"
- >
- <FileConfiguration
- Name="Debug|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_Internal|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_Cairo|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release_Cairo|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_All|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\bindings\js\JSCustomSQLStatementCallback.h"
- >
- </File>
- <File
RelativePath="..\bindings\js\JSCustomSQLStatementErrorCallback.cpp"
>
<FileConfiguration
@@ -35587,122 +35555,6 @@ </FileConfiguration>
</File>
<File
- RelativePath="..\bindings\js\JSCustomSQLStatementErrorCallback.h"
- >
- </File>
- <File
- RelativePath="..\bindings\js\JSCustomSQLTransactionCallback.cpp"
- >
- <FileConfiguration
- Name="Debug|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_Internal|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_Cairo|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release_Cairo|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_All|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\bindings\js\JSCustomSQLTransactionCallback.h"
- >
- </File>
- <File
- RelativePath="..\bindings\js\JSCustomSQLTransactionErrorCallback.cpp"
- >
- <FileConfiguration
- Name="Debug|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_Internal|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_Cairo|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release_Cairo|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_All|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\bindings\js\JSCustomSQLTransactionErrorCallback.h"
- >
- </File>
- <File
RelativePath="..\bindings\js\JSCustomVoidCallback.cpp"
>
<FileConfiguration
@@ -35815,14 +35667,6 @@ >
</File>
<File
- RelativePath="..\bindings\js\JSDatabaseCallback.cpp"
- >
- </File>
- <File
- RelativePath="..\bindings\js\JSDatabaseCallback.h"
- >
- </File>
- <File
RelativePath="..\bindings\js\JSDatabaseCustom.cpp"
>
<FileConfiguration
@@ -36143,58 +35987,6 @@ </FileConfiguration>
</File>
<File
- RelativePath="..\bindings\js\JSDocumentFragmentCustom.cpp"
- >
- <FileConfiguration
- Name="Debug|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_Internal|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_Cairo|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release_Cairo|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_All|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- </File>
- <File
RelativePath="..\bindings\js\JSDOMApplicationCacheCustom.cpp"
>
<FileConfiguration
@@ -36755,58 +36547,6 @@ >
</File>
<File
- RelativePath="..\bindings\js\JSEventSourceCustom.cpp"
- >
- <FileConfiguration
- Name="Debug|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_Internal|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_Cairo|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release_Cairo|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Debug_All|Win32"
- ExcludedFromBuild="true"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
- </File>
- <File
RelativePath="..\bindings\js\JSEventTarget.cpp"
>
<FileConfiguration
@@ -42329,66 +42069,6 @@ RelativePath="..\svg\graphics\SVGImage.h"
>
</File>
- <File
- RelativePath="..\svg\graphics\SVGPaintServer.cpp"
- >
- </File>
- <File
- RelativePath="..\svg\graphics\SVGPaintServer.h"
- >
- </File>
- <File
- RelativePath="..\svg\graphics\SVGPaintServerGradient.cpp"
- >
- </File>
- <File
- RelativePath="..\svg\graphics\SVGPaintServerGradient.h"
- >
- </File>
- <File
- RelativePath="..\svg\graphics\SVGPaintServerLinearGradient.cpp"
- >
- </File>
- <File
- RelativePath="..\svg\graphics\SVGPaintServerLinearGradient.h"
- >
- </File>
- <File
- RelativePath="..\svg\graphics\SVGPaintServerPattern.cpp"
- >
- </File>
- <File
- RelativePath="..\svg\graphics\SVGPaintServerPattern.h"
- >
- </File>
- <File
- RelativePath="..\svg\graphics\SVGPaintServerRadialGradient.cpp"
- >
- </File>
- <File
- RelativePath="..\svg\graphics\SVGPaintServerRadialGradient.h"
- >
- </File>
- <File
- RelativePath="..\svg\graphics\SVGPaintServerSolid.cpp"
- >
- </File>
- <File
- RelativePath="..\svg\graphics\SVGPaintServerSolid.h"
- >
- </File>
- <File
- RelativePath="..\svg\graphics\SVGResource.cpp"
- >
- </File>
- <File
- RelativePath="..\svg\graphics\SVGResource.h"
- >
- </File>
- <File
- RelativePath="..\svg\graphics\SVGResourceListener.h"
- >
- </File>
<Filter
Name="filters"
>
@@ -42871,6 +42551,14 @@ >
</File>
<File
+ RelativePath="..\storage\DatabaseSync.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\storage\DatabaseSync.h"
+ >
+ </File>
+ <File
RelativePath="..\storage\DatabaseTask.h"
>
</File>
@@ -42995,6 +42683,18 @@ >
</File>
<File
+ RelativePath="..\storage\SQLTransactionSync.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\storage\SQLTransactionSync.h"
+ >
+ </File>
+ <File
+ RelativePath="..\storage\SQLTransactionSyncCallback.h"
+ >
+ </File>
+ <File
RelativePath="..\storage\Storage.cpp"
>
</File>
@@ -43239,6 +42939,14 @@ >
</File>
<File
+ RelativePath="..\inspector\InspectorCSSStore.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\inspector\InspectorCSSStore.h"
+ >
+ </File>
+ <File
RelativePath="..\inspector\InspectorClient.h"
>
</File>
diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj index fe6d457..450c3fd 100644 --- a/WebCore/WebCore.xcodeproj/project.pbxproj +++ b/WebCore/WebCore.xcodeproj/project.pbxproj @@ -46,6 +46,7 @@ 080081970ED3B2DD00C53BC0 /* WMLAnchorElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 080081950ED3B2DD00C53BC0 /* WMLAnchorElement.h */; }; 0804BF6E0EE09C3B0006C000 /* WMLDoElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0804BF6C0EE09C3B0006C000 /* WMLDoElement.cpp */; }; 0804BF6F0EE09C3B0006C000 /* WMLDoElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 0804BF6D0EE09C3B0006C000 /* WMLDoElement.h */; }; + 08082373117987C100241DE8 /* RenderSVGResourceContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 08082372117987C100241DE8 /* RenderSVGResourceContainer.h */; }; 080AEC810ED8708B00DF4CCE /* WMLIntrinsicEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 080AEC7D0ED8708A00DF4CCE /* WMLIntrinsicEvent.cpp */; }; 080AEC820ED8708B00DF4CCE /* WMLIntrinsicEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 080AEC7E0ED8708B00DF4CCE /* WMLIntrinsicEvent.h */; }; 080AEC830ED8708B00DF4CCE /* WMLIntrinsicEventHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 080AEC7F0ED8708B00DF4CCE /* WMLIntrinsicEventHandler.cpp */; }; @@ -74,6 +75,9 @@ 083DAEA70F01A7FB00342754 /* RenderTextControlMultiLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 083DAEA30F01A7FB00342754 /* RenderTextControlMultiLine.h */; }; 083DAEA80F01A7FB00342754 /* RenderTextControlSingleLine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 083DAEA40F01A7FB00342754 /* RenderTextControlSingleLine.cpp */; }; 083DAEA90F01A7FB00342754 /* RenderTextControlSingleLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 083DAEA50F01A7FB00342754 /* RenderTextControlSingleLine.h */; }; + 0842BC721190144000C7D08F /* SVGCharacterData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0842BC701190144000C7D08F /* SVGCharacterData.cpp */; }; + 0842BC731190144000C7D08F /* SVGCharacterData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0842BC711190144000C7D08F /* SVGCharacterData.h */; }; + 0842BC811190147200C7D08F /* SVGTextChunkLayoutInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0842BC801190147200C7D08F /* SVGTextChunkLayoutInfo.h */; }; 084AEBE40FB505FA0038483E /* SelectElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 084AEBE20FB505FA0038483E /* SelectElement.cpp */; }; 084AEBE50FB505FA0038483E /* SelectElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 084AEBE30FB505FA0038483E /* SelectElement.h */; }; 084CE5CB0F27DADC00E6240E /* WMLOptGroupElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 084CE5C70F27DADC00E6240E /* WMLOptGroupElement.cpp */; }; @@ -84,6 +88,9 @@ 084D2834110A7FCB0038239A /* SVGAnimatedPropertyTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 084D2832110A7FCB0038239A /* SVGAnimatedPropertyTraits.h */; settings = {ATTRIBUTES = (Private, ); }; }; 084DBAA10ED39D360038C226 /* WMLVariables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 084DBA9D0ED39D350038C226 /* WMLVariables.cpp */; }; 084DBAA20ED39D360038C226 /* WMLVariables.h in Headers */ = {isa = PBXBuildFile; fileRef = 084DBA9E0ED39D360038C226 /* WMLVariables.h */; }; + 08563BB4117861780012B578 /* RenderSVGResourcePattern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08563BB2117861770012B578 /* RenderSVGResourcePattern.cpp */; }; + 08563BB5117861780012B578 /* RenderSVGResourcePattern.h in Headers */ = {isa = PBXBuildFile; fileRef = 08563BB3117861770012B578 /* RenderSVGResourcePattern.h */; }; + 08563BD0117865F50012B578 /* RenderSVGResource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08563BCF117865F50012B578 /* RenderSVGResource.cpp */; }; 08591AA50F085C4E009BACB1 /* InputElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 08591AA40F085C4E009BACB1 /* InputElement.h */; settings = {ATTRIBUTES = (Private, ); }; }; 085AFDC80F2977350061F2B3 /* WMLFormControlElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 085AFDC60F2977350061F2B3 /* WMLFormControlElement.cpp */; }; 085AFDC90F2977350061F2B3 /* WMLFormControlElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 085AFDC70F2977350061F2B3 /* WMLFormControlElement.h */; settings = {ATTRIBUTES = (); }; }; @@ -139,10 +146,18 @@ 08A484770E5272C500C3FE76 /* ScriptElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08A484750E5272C500C3FE76 /* ScriptElement.cpp */; }; 08A484780E5272C500C3FE76 /* ScriptElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 08A484760E5272C500C3FE76 /* ScriptElement.h */; }; 08A48A6E0E86CF6D00E225DD /* JSSVGElementInstanceCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08A48A6D0E86CF6D00E225DD /* JSSVGElementInstanceCustom.cpp */; }; + 08C34AF51179C057002D7456 /* RenderSVGResourceGradient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08C34AF11179C056002D7456 /* RenderSVGResourceGradient.cpp */; }; + 08C34AF61179C057002D7456 /* RenderSVGResourceGradient.h in Headers */ = {isa = PBXBuildFile; fileRef = 08C34AF21179C057002D7456 /* RenderSVGResourceGradient.h */; }; + 08C34AF71179C057002D7456 /* RenderSVGResourceLinearGradient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08C34AF31179C057002D7456 /* RenderSVGResourceLinearGradient.cpp */; }; + 08C34AF81179C057002D7456 /* RenderSVGResourceLinearGradient.h in Headers */ = {isa = PBXBuildFile; fileRef = 08C34AF41179C057002D7456 /* RenderSVGResourceLinearGradient.h */; }; + 08C34AFD1179C072002D7456 /* RenderSVGResourceRadialGradient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08C34AFB1179C072002D7456 /* RenderSVGResourceRadialGradient.cpp */; }; + 08C34AFE1179C072002D7456 /* RenderSVGResourceRadialGradient.h in Headers */ = {isa = PBXBuildFile; fileRef = 08C34AFC1179C072002D7456 /* RenderSVGResourceRadialGradient.h */; }; 08C4C5180EF19A4000E4840F /* WMLImageElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08C4C5140EF19A4000E4840F /* WMLImageElement.cpp */; }; 08C4C5190EF19A4000E4840F /* WMLImageElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 08C4C5150EF19A4000E4840F /* WMLImageElement.h */; }; 08C4C51A0EF19A4000E4840F /* WMLImageLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08C4C5160EF19A4000E4840F /* WMLImageLoader.cpp */; }; 08C4C51B0EF19A4000E4840F /* WMLImageLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 08C4C5170EF19A4000E4840F /* WMLImageLoader.h */; }; + 08C6A7AB117DFBAB00FEA1A2 /* RenderSVGResourceSolidColor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08C6A7A9117DFBAB00FEA1A2 /* RenderSVGResourceSolidColor.cpp */; }; + 08C6A7AC117DFBAB00FEA1A2 /* RenderSVGResourceSolidColor.h in Headers */ = {isa = PBXBuildFile; fileRef = 08C6A7AA117DFBAB00FEA1A2 /* RenderSVGResourceSolidColor.h */; }; 08C7A2C710DC7462002D368B /* SVGNames.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 656581E909D1508D000E61D7 /* SVGNames.h */; }; 08C925190FCC7C4A00480DEC /* FilterEffect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08C925170FCC7C4A00480DEC /* FilterEffect.cpp */; }; 08C9251A0FCC7C4A00480DEC /* FilterEffect.h in Headers */ = {isa = PBXBuildFile; fileRef = 08C925180FCC7C4A00480DEC /* FilterEffect.h */; }; @@ -208,13 +223,17 @@ 0FD308D6117D168500A791F7 /* RenderIFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD308D4117D168400A791F7 /* RenderIFrame.h */; }; 0FD723820EC8BD9300CA5DD7 /* FloatQuad.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD723800EC8BD9300CA5DD7 /* FloatQuad.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FD723830EC8BD9300CA5DD7 /* FloatQuad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD723810EC8BD9300CA5DD7 /* FloatQuad.cpp */; }; - 0FF5025B102BA9010066F39A /* DOMMedia.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF50259102BA9010066F39A /* DOMMedia.h */; }; - 0FF5025C102BA9010066F39A /* DOMMedia.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0FF5025A102BA9010066F39A /* DOMMedia.mm */; }; - 0FF50263102BA92C0066F39A /* DOMMediaInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF50262102BA92B0066F39A /* DOMMediaInternal.h */; }; - 0FF50269102BA9430066F39A /* JSMedia.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF50267102BA9430066F39A /* JSMedia.cpp */; }; - 0FF5026A102BA9430066F39A /* JSMedia.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF50268102BA9430066F39A /* JSMedia.h */; }; - 0FF50271102BA96A0066F39A /* Media.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF5026E102BA9660066F39A /* Media.cpp */; }; - 0FF50272102BA96A0066F39A /* Media.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF5026F102BA96A0066F39A /* Media.h */; }; + 0FF2859011864052007B7CD6 /* RenderMathMLRoot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF2813211821CB6007B7CD6 /* RenderMathMLRoot.cpp */; }; + 0FF2859111864053007B7CD6 /* RenderMathMLRoot.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF2813311821CB6007B7CD6 /* RenderMathMLRoot.h */; }; + 0FF2859211864054007B7CD6 /* RenderMathMLSquareRoot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF2813411821CB6007B7CD6 /* RenderMathMLSquareRoot.cpp */; }; + 0FF2859311864055007B7CD6 /* RenderMathMLSquareRoot.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF2813511821CB6007B7CD6 /* RenderMathMLSquareRoot.h */; }; + 0FF5025B102BA9010066F39A /* DOMStyleMedia.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF50259102BA9010066F39A /* DOMStyleMedia.h */; }; + 0FF5025C102BA9010066F39A /* DOMStyleMedia.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0FF5025A102BA9010066F39A /* DOMStyleMedia.mm */; }; + 0FF50263102BA92C0066F39A /* DOMStyleMediaInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF50262102BA92B0066F39A /* DOMStyleMediaInternal.h */; }; + 0FF50269102BA9430066F39A /* JSStyleMedia.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF50267102BA9430066F39A /* JSStyleMedia.cpp */; }; + 0FF5026A102BA9430066F39A /* JSStyleMedia.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF50268102BA9430066F39A /* JSStyleMedia.h */; }; + 0FF50271102BA96A0066F39A /* StyleMedia.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF5026E102BA9660066F39A /* StyleMedia.cpp */; }; + 0FF50272102BA96A0066F39A /* StyleMedia.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF5026F102BA96A0066F39A /* StyleMedia.h */; }; 1402645E0AFDC19B005919E2 /* LoggingMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1402645D0AFDC19B005919E2 /* LoggingMac.mm */; }; 1403B99709EB13AF00797C7F /* DOMWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 1403B99509EB13AF00797C7F /* DOMWindow.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1403B99809EB13AF00797C7F /* DOMWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1403B99609EB13AF00797C7F /* DOMWindow.cpp */; }; @@ -265,6 +284,8 @@ 15C77094100D3CA8005BA267 /* JSValidityState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 15C77092100D3CA8005BA267 /* JSValidityState.cpp */; }; 15C770A5100D41CD005BA267 /* DOMValidityState.mm in Sources */ = {isa = PBXBuildFile; fileRef = 15C770A3100D41CD005BA267 /* DOMValidityState.mm */; }; 15C770A6100D41CD005BA267 /* DOMValidityState.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C770A4100D41CD005BA267 /* DOMValidityState.h */; }; + 163E88F7118A39D200ED9231 /* SimpleFontDataCoreText.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 163E88F5118A39D200ED9231 /* SimpleFontDataCoreText.cpp */; }; + 163E8B13118B3ADD00ED9231 /* SimpleFontDataATSUI.mm in Sources */ = {isa = PBXBuildFile; fileRef = 163E8B12118B3ADD00ED9231 /* SimpleFontDataATSUI.mm */; }; 185BCF280F3279CE000EA262 /* ThreadTimers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 185BCF260F3279CE000EA262 /* ThreadTimers.cpp */; }; 185BCF290F3279CE000EA262 /* ThreadTimers.h in Headers */ = {isa = PBXBuildFile; fileRef = 185BCF270F3279CE000EA262 /* ThreadTimers.h */; }; 188604B30F2E654A000B6443 /* DOMTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 188604B10F2E654A000B6443 /* DOMTimer.cpp */; }; @@ -283,6 +304,7 @@ 1A22464C0CC98DDB00C05240 /* SQLiteStatement.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A2246460CC98DDB00C05240 /* SQLiteStatement.h */; }; 1A22464D0CC98DDB00C05240 /* SQLiteTransaction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2246470CC98DDB00C05240 /* SQLiteTransaction.cpp */; }; 1A22464E0CC98DDB00C05240 /* SQLiteTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A2246480CC98DDB00C05240 /* SQLiteTransaction.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1A27CF97118A354C0041D632 /* nptypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A27CF96118A354C0041D632 /* nptypes.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1A2A68230B5BEDE70002A480 /* ProgressTracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A68210B5BEDE70002A480 /* ProgressTracker.cpp */; }; 1A2A68240B5BEDE70002A480 /* ProgressTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A2A68220B5BEDE70002A480 /* ProgressTracker.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1A2AAC580DC2A3B100A20D9A /* ApplicationCacheStorage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2AAC560DC2A3B100A20D9A /* ApplicationCacheStorage.cpp */; }; @@ -612,6 +634,12 @@ 2E2D99EC10E2BD3900496337 /* DOMBlobInternal.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 2E2D99E910E2BC3800496337 /* DOMBlobInternal.h */; }; 2E3BBF071162DA1100B9409A /* UUID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E3BBF051162DA1100B9409A /* UUID.cpp */; }; 2E3BBF081162DA1100B9409A /* UUID.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E3BBF061162DA1100B9409A /* UUID.h */; }; + 2E3BC0BD117D3A4F00B9409A /* FileError.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E3BC0BB117D3A4F00B9409A /* FileError.h */; }; + 2E3BC0CA117D3E0800B9409A /* JSFileError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E3BC0C8117D3E0800B9409A /* JSFileError.cpp */; }; + 2E3BC0CB117D3E0800B9409A /* JSFileError.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E3BC0C9117D3E0800B9409A /* JSFileError.h */; }; + 2E3BC108117D479800B9409A /* DOMFileError.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E3BC106117D479800B9409A /* DOMFileError.h */; }; + 2E3BC109117D479800B9409A /* DOMFileError.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E3BC107117D479800B9409A /* DOMFileError.mm */; }; + 2E3BC10B117D47C800B9409A /* DOMFileErrorInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E3BC10A117D47C800B9409A /* DOMFileErrorInternal.h */; }; 2E4346440F546A8200B0F1BA /* GenericWorkerTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E4346320F546A8200B0F1BA /* GenericWorkerTask.h */; }; 2E4346450F546A8200B0F1BA /* Worker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E4346330F546A8200B0F1BA /* Worker.cpp */; }; 2E4346460F546A8200B0F1BA /* Worker.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E4346340F546A8200B0F1BA /* Worker.h */; }; @@ -721,13 +749,13 @@ 37C28A6810F659CC008C7813 /* TypesettingFeatures.h in Headers */ = {isa = PBXBuildFile; fileRef = 37C28A6710F659CC008C7813 /* TypesettingFeatures.h */; settings = {ATTRIBUTES = (Private, ); }; }; 37F818FD0D657606005E1F05 /* WebCoreURLResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 37F818FB0D657606005E1F05 /* WebCoreURLResponse.h */; settings = {ATTRIBUTES = (Private, ); }; }; 37F818FE0D657606005E1F05 /* WebCoreURLResponse.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37F818FC0D657606005E1F05 /* WebCoreURLResponse.mm */; }; + 37FD4298118368460093C029 /* TreeDepthLimit.h in Headers */ = {isa = PBXBuildFile; fileRef = 37FD4297118368460093C029 /* TreeDepthLimit.h */; }; 41002CCD0F66EDEF009E660D /* ScriptFunctionCall.h in Headers */ = {isa = PBXBuildFile; fileRef = 41002CCB0F66EDEF009E660D /* ScriptFunctionCall.h */; }; 41002CCE0F66EDEF009E660D /* ScriptFunctionCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41002CCC0F66EDEF009E660D /* ScriptFunctionCall.cpp */; }; 410B7E721045FAB000D8224F /* JSMessageEventCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 410B7E711045FAB000D8224F /* JSMessageEventCustom.cpp */; }; 411046410FA222A600BA436A /* ScriptEventListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 4110463F0FA222A600BA436A /* ScriptEventListener.h */; }; 411046420FA222A600BA436A /* ScriptEventListener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 411046400FA222A600BA436A /* ScriptEventListener.cpp */; }; 4127D5370F8AAB1D00E424F5 /* ScriptState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4127D5360F8AAB1D00E424F5 /* ScriptState.cpp */; }; - 415B7C570FF598E6006770F7 /* JSAbstractWorkerCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 415B7C540FF598E6006770F7 /* JSAbstractWorkerCustom.cpp */; }; 415B7C580FF598E6006770F7 /* JSSharedWorkerConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 415B7C550FF598E6006770F7 /* JSSharedWorkerConstructor.cpp */; }; 415B7C630FF5A767006770F7 /* JSSharedWorkerConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 415B7C620FF5A767006770F7 /* JSSharedWorkerConstructor.h */; }; 4162A450101145AE00DFF3ED /* DedicatedWorkerContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4162A44D101145AE00DFF3ED /* DedicatedWorkerContext.cpp */; }; @@ -1119,14 +1147,7 @@ 51E4ADB60C42B4CF0042BC55 /* FTPDirectoryDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51E4ADB20C42B4CF0042BC55 /* FTPDirectoryDocument.cpp */; }; 51E4ADB70C42B4CF0042BC55 /* FTPDirectoryDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E4ADB30C42B4CF0042BC55 /* FTPDirectoryDocument.h */; }; 51EC92590CE90DB400F90308 /* SQLError.h in Headers */ = {isa = PBXBuildFile; fileRef = 51EC92570CE90DB400F90308 /* SQLError.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 51EC92630CE90DD400F90308 /* JSCustomSQLStatementCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51EC925B0CE90DD400F90308 /* JSCustomSQLStatementCallback.cpp */; }; - 51EC92640CE90DD400F90308 /* JSCustomSQLStatementCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 51EC925C0CE90DD400F90308 /* JSCustomSQLStatementCallback.h */; }; 51EC92650CE90DD400F90308 /* JSCustomSQLStatementErrorCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51EC925D0CE90DD400F90308 /* JSCustomSQLStatementErrorCallback.cpp */; }; - 51EC92660CE90DD400F90308 /* JSCustomSQLStatementErrorCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 51EC925E0CE90DD400F90308 /* JSCustomSQLStatementErrorCallback.h */; }; - 51EC92670CE90DD400F90308 /* JSCustomSQLTransactionCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51EC925F0CE90DD400F90308 /* JSCustomSQLTransactionCallback.cpp */; }; - 51EC92680CE90DD400F90308 /* JSCustomSQLTransactionCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 51EC92600CE90DD400F90308 /* JSCustomSQLTransactionCallback.h */; }; - 51EC92690CE90DD400F90308 /* JSCustomSQLTransactionErrorCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51EC92610CE90DD400F90308 /* JSCustomSQLTransactionErrorCallback.cpp */; }; - 51EC926A0CE90DD400F90308 /* JSCustomSQLTransactionErrorCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 51EC92620CE90DD400F90308 /* JSCustomSQLTransactionErrorCallback.h */; }; 51FAFE340CECBF2D00BB3F24 /* DatabaseTrackerClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 51FAFE330CECBF2D00BB3F24 /* DatabaseTrackerClient.h */; settings = {ATTRIBUTES = (Private, ); }; }; 54C50F7B0E801DF3009832A0 /* XMLTokenizerLibxml2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 54C50F7A0E801DF3009832A0 /* XMLTokenizerLibxml2.cpp */; }; 550A0BC9085F6039007353D6 /* QualifiedName.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 550A0BC7085F6039007353D6 /* QualifiedName.cpp */; }; @@ -1326,6 +1347,8 @@ 7AED3E060FBB1EAA00D2B03C /* InspectorFrontend.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AED3E040FBB1EAA00D2B03C /* InspectorFrontend.h */; }; 7AFD4A8B1131C2760035B883 /* ScriptBreakpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AFD4A8A1131C2760035B883 /* ScriptBreakpoint.h */; settings = {ATTRIBUTES = (Private, ); }; }; 7AFD4FF4113277B60035B883 /* ScriptDebugListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AFD4FF3113277B60035B883 /* ScriptDebugListener.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 82B658981189E39200E052A1 /* InspectorCSSStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 82B658971189E39200E052A1 /* InspectorCSSStore.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 82B6589A1189E47600E052A1 /* InspectorCSSStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 82B658991189E47600E052A1 /* InspectorCSSStore.cpp */; }; 841FDC261178C9BE00F8AC9B /* RenderSVGResourceFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 841FDC241178C9BE00F8AC9B /* RenderSVGResourceFilter.cpp */; }; 841FDC271178C9BE00F8AC9B /* RenderSVGResourceFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 841FDC251178C9BE00F8AC9B /* RenderSVGResourceFilter.h */; }; 84224183107E77F400766A87 /* JSSVGFEMorphologyElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84224181107E77F400766A87 /* JSSVGFEMorphologyElement.cpp */; }; @@ -3731,21 +3754,6 @@ B25599A30D00D8BA00BB825C /* SVGImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B255990B0D00D8B900BB825C /* SVGImage.cpp */; }; B25599A40D00D8BA00BB825C /* SVGImage.h in Headers */ = {isa = PBXBuildFile; fileRef = B255990C0D00D8B900BB825C /* SVGImage.h */; }; B25599A50D00D8BA00BB825C /* EmptyClients.h in Headers */ = {isa = PBXBuildFile; fileRef = B255990D0D00D8B900BB825C /* EmptyClients.h */; }; - B25599A60D00D8BA00BB825C /* SVGPaintServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B255990E0D00D8B900BB825C /* SVGPaintServer.cpp */; }; - B25599A70D00D8BA00BB825C /* SVGPaintServer.h in Headers */ = {isa = PBXBuildFile; fileRef = B255990F0D00D8B900BB825C /* SVGPaintServer.h */; }; - B25599A80D00D8BA00BB825C /* SVGPaintServerGradient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B25599100D00D8B900BB825C /* SVGPaintServerGradient.cpp */; }; - B25599A90D00D8BA00BB825C /* SVGPaintServerGradient.h in Headers */ = {isa = PBXBuildFile; fileRef = B25599110D00D8B900BB825C /* SVGPaintServerGradient.h */; }; - B25599AA0D00D8BA00BB825C /* SVGPaintServerLinearGradient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B25599120D00D8B900BB825C /* SVGPaintServerLinearGradient.cpp */; }; - B25599AB0D00D8BA00BB825C /* SVGPaintServerLinearGradient.h in Headers */ = {isa = PBXBuildFile; fileRef = B25599130D00D8B900BB825C /* SVGPaintServerLinearGradient.h */; }; - B25599AC0D00D8BA00BB825C /* SVGPaintServerPattern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B25599140D00D8B900BB825C /* SVGPaintServerPattern.cpp */; }; - B25599AD0D00D8BA00BB825C /* SVGPaintServerPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = B25599150D00D8B900BB825C /* SVGPaintServerPattern.h */; }; - B25599AE0D00D8BA00BB825C /* SVGPaintServerRadialGradient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B25599160D00D8B900BB825C /* SVGPaintServerRadialGradient.cpp */; }; - B25599AF0D00D8BA00BB825C /* SVGPaintServerRadialGradient.h in Headers */ = {isa = PBXBuildFile; fileRef = B25599170D00D8B900BB825C /* SVGPaintServerRadialGradient.h */; }; - B25599B00D00D8BA00BB825C /* SVGPaintServerSolid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B25599180D00D8B900BB825C /* SVGPaintServerSolid.cpp */; }; - B25599B10D00D8BA00BB825C /* SVGPaintServerSolid.h in Headers */ = {isa = PBXBuildFile; fileRef = B25599190D00D8B900BB825C /* SVGPaintServerSolid.h */; }; - B25599B20D00D8BA00BB825C /* SVGResource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B255991A0D00D8B900BB825C /* SVGResource.cpp */; }; - B25599B30D00D8BA00BB825C /* SVGResource.h in Headers */ = {isa = PBXBuildFile; fileRef = B255991B0D00D8B900BB825C /* SVGResource.h */; }; - B25599B80D00D8BA00BB825C /* SVGResourceListener.h in Headers */ = {isa = PBXBuildFile; fileRef = B25599200D00D8B900BB825C /* SVGResourceListener.h */; }; B25DFAAF0B2E2929000E6510 /* JSSVGMatrixCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B25DFAAE0B2E2929000E6510 /* JSSVGMatrixCustom.cpp */; }; B262B8040D1F32D000158F09 /* SVGFont.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B262B8030D1F32D000158F09 /* SVGFont.cpp */; }; B26554EA0B80D74900A50EC3 /* RenderSVGTextPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B26554E80B80D74900A50EC3 /* RenderSVGTextPath.cpp */; }; @@ -4155,13 +4163,26 @@ B50F5B810E96CD9900AD71A6 /* WebCoreObjCExtras.mm in Sources */ = {isa = PBXBuildFile; fileRef = B50F5B800E96CD9900AD71A6 /* WebCoreObjCExtras.mm */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; }; B51BF6F0102C9E590002C15A /* SQLTransactionClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B51BF6EE102C9E590002C15A /* SQLTransactionClient.cpp */; }; B51BF6F1102C9E590002C15A /* SQLTransactionClient.h in Headers */ = {isa = PBXBuildFile; fileRef = B51BF6EF102C9E590002C15A /* SQLTransactionClient.h */; }; + B523CF061182675400EBB29C /* SQLTransactionSyncCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = B523CEFF1182675400EBB29C /* SQLTransactionSyncCallback.h */; }; + B523CF081182675400EBB29C /* SQLTransactionSync.h in Headers */ = {isa = PBXBuildFile; fileRef = B523CF011182675400EBB29C /* SQLTransactionSync.h */; }; + B523CF091182675400EBB29C /* SQLTransactionSync.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B523CF021182675400EBB29C /* SQLTransactionSync.cpp */; }; + B523CF0A1182675400EBB29C /* DatabaseSync.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B523CF031182675400EBB29C /* DatabaseSync.cpp */; }; + B523CF0B1182675400EBB29C /* DatabaseSync.h in Headers */ = {isa = PBXBuildFile; fileRef = B523CF041182675400EBB29C /* DatabaseSync.h */; }; + B59DD699119029E5007E9684 /* JSDatabaseCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = B59DD697119029E5007E9684 /* JSDatabaseCallback.h */; }; + B59DD69A119029E5007E9684 /* JSDatabaseCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B59DD698119029E5007E9684 /* JSDatabaseCallback.cpp */; }; + B59DD69D11902A42007E9684 /* JSSQLTransactionCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = B59DD69B11902A42007E9684 /* JSSQLTransactionCallback.h */; }; + B59DD69E11902A42007E9684 /* JSSQLTransactionCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B59DD69C11902A42007E9684 /* JSSQLTransactionCallback.cpp */; }; + B59DD6A111902A52007E9684 /* JSSQLTransactionErrorCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = B59DD69F11902A52007E9684 /* JSSQLTransactionErrorCallback.h */; }; + B59DD6A211902A52007E9684 /* JSSQLTransactionErrorCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B59DD6A011902A52007E9684 /* JSSQLTransactionErrorCallback.cpp */; }; + B59DD6A511902A62007E9684 /* JSSQLStatementCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = B59DD6A311902A62007E9684 /* JSSQLStatementCallback.h */; }; + B59DD6A611902A62007E9684 /* JSSQLStatementCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B59DD6A411902A62007E9684 /* JSSQLStatementCallback.cpp */; }; + B59DD6A911902A71007E9684 /* JSSQLStatementErrorCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = B59DD6A711902A71007E9684 /* JSSQLStatementErrorCallback.h */; }; + B59DD6AA11902A71007E9684 /* JSSQLStatementErrorCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B59DD6A811902A71007E9684 /* JSSQLStatementErrorCallback.cpp */; }; B5A684220FFABE9800D24689 /* SQLiteFileSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = B5A684210FFABE9800D24689 /* SQLiteFileSystem.h */; }; B5A684240FFABEAA00D24689 /* SQLiteFileSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5A684230FFABEAA00D24689 /* SQLiteFileSystem.cpp */; }; B5C1123B102B6C4600096578 /* SQLTransactionCoordinator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5C11239102B6C4600096578 /* SQLTransactionCoordinator.cpp */; }; B5C1123C102B6C4600096578 /* SQLTransactionCoordinator.h in Headers */ = {isa = PBXBuildFile; fileRef = B5C1123A102B6C4600096578 /* SQLTransactionCoordinator.h */; }; B5D3601A112F8B560048DEA8 /* DatabaseCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = B5D36019112F8B560048DEA8 /* DatabaseCallback.h */; }; - B5D3601D112F8BA00048DEA8 /* JSDatabaseCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = B5D3601C112F8BA00048DEA8 /* JSDatabaseCallback.h */; }; - B5D3601F112F8BA80048DEA8 /* JSDatabaseCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5D3601E112F8BA80048DEA8 /* JSDatabaseCallback.cpp */; }; B71FE6DF11091CB300DAEF77 /* PrintContext.h in Headers */ = {isa = PBXBuildFile; fileRef = B776D43A1104525D00BEB0EC /* PrintContext.h */; settings = {ATTRIBUTES = (Private, ); }; }; B776D43D1104527500BEB0EC /* PrintContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B776D43C1104527500BEB0EC /* PrintContext.cpp */; }; BC00F0040E0A185500FD04E3 /* DOMFile.h in Headers */ = {isa = PBXBuildFile; fileRef = BC00EFFE0E0A185500FD04E3 /* DOMFile.h */; }; @@ -4570,7 +4591,6 @@ BCCD74DC0A4C8D35005FDA6D /* HTMLViewSourceDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = BCCD74DB0A4C8D35005FDA6D /* HTMLViewSourceDocument.h */; }; BCCD74E50A4C8DDF005FDA6D /* HTMLViewSourceDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCCD74E40A4C8DDF005FDA6D /* HTMLViewSourceDocument.cpp */; }; BCCE58AC1061E8CF008FB35A /* JSDatabaseCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCCE58AB1061E8CF008FB35A /* JSDatabaseCustom.cpp */; }; - BCCE58AF1061E90C008FB35A /* JSDocumentFragmentCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCCE58AE1061E90C008FB35A /* JSDocumentFragmentCustom.cpp */; }; BCCFBAE80B5152ED0001F1D7 /* Tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = BCCFBAE70B5152ED0001F1D7 /* Tokenizer.h */; settings = {ATTRIBUTES = (Private, ); }; }; BCD0E0FA0E972C3500265DEA /* SecurityOrigin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCD0E0F70E972C3500265DEA /* SecurityOrigin.cpp */; }; BCD0E0FB0E972C3500265DEA /* SecurityOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD0E0F80E972C3500265DEA /* SecurityOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -4709,7 +4729,6 @@ C5160EEB1004543A00A7CEE2 /* StorageAreaImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = C5160EE91004543A00A7CEE2 /* StorageAreaImpl.h */; }; C55E38BF10040D5D00A56BDB /* StorageNamespaceImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = C55E38BB10040D5D00A56BDB /* StorageNamespaceImpl.h */; }; C55E38C010040D5D00A56BDB /* StorageNamespaceImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C55E38BC10040D5D00A56BDB /* StorageNamespaceImpl.cpp */; }; - C5D4AA79116BAFB60069CA93 /* GlyphMetricsMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C5D4AA77116BAFB60069CA93 /* GlyphMetricsMap.cpp */; }; C5D4AA7A116BAFB60069CA93 /* GlyphMetricsMap.h in Headers */ = {isa = PBXBuildFile; fileRef = C5D4AA78116BAFB60069CA93 /* GlyphMetricsMap.h */; settings = {ATTRIBUTES = (Private, ); }; }; C5E9B67710697E1300C7BB1A /* StorageEventDispatcher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C5E9B67610697E1300C7BB1A /* StorageEventDispatcher.cpp */; }; C5EBDD84105EDDEC0056816F /* StorageEventDispatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = C5EBDD81105EDDEC0056816F /* StorageEventDispatcher.h */; }; @@ -4747,7 +4766,6 @@ E0FEF372B27C53EAC1C1FBEE /* EventSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E0FEF371B27C53EAC1C1FBEE /* EventSource.cpp */; }; E0FEF372B37C53EAC1C1FBEE /* JSEventSource.h in Headers */ = {isa = PBXBuildFile; fileRef = E0FEF371B37C53EAC1C1FBEE /* JSEventSource.h */; }; E0FEF372B47C53EAC1C1FBEE /* JSEventSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E0FEF371B47C53EAC1C1FBEE /* JSEventSource.cpp */; }; - E0FEF372B57C53EAC1C1FBEE /* JSEventSourceCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E0FEF371B57C53EAC1C1FBEE /* JSEventSourceCustom.cpp */; }; E0FEF372B67C53EAC1C1FBEE /* JSEventSourceConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = E0FEF371B67C53EAC1C1FBEE /* JSEventSourceConstructor.h */; }; E0FEF372B77C53EAC1C1FBEE /* JSEventSourceConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E0FEF371B77C53EAC1C1FBEE /* JSEventSourceConstructor.cpp */; }; E107400D0E77BDC00033AF24 /* JSMessageChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E107400B0E77BDC00033AF24 /* JSMessageChannel.cpp */; }; @@ -5431,6 +5449,7 @@ 080081950ED3B2DD00C53BC0 /* WMLAnchorElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMLAnchorElement.h; sourceTree = "<group>"; }; 0804BF6C0EE09C3B0006C000 /* WMLDoElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WMLDoElement.cpp; sourceTree = "<group>"; }; 0804BF6D0EE09C3B0006C000 /* WMLDoElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMLDoElement.h; sourceTree = "<group>"; }; + 08082372117987C100241DE8 /* RenderSVGResourceContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGResourceContainer.h; sourceTree = "<group>"; }; 080AEC7D0ED8708A00DF4CCE /* WMLIntrinsicEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WMLIntrinsicEvent.cpp; sourceTree = "<group>"; }; 080AEC7E0ED8708B00DF4CCE /* WMLIntrinsicEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMLIntrinsicEvent.h; sourceTree = "<group>"; }; 080AEC7F0ED8708B00DF4CCE /* WMLIntrinsicEventHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WMLIntrinsicEventHandler.cpp; sourceTree = "<group>"; }; @@ -5457,6 +5476,9 @@ 083DAEA30F01A7FB00342754 /* RenderTextControlMultiLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderTextControlMultiLine.h; sourceTree = "<group>"; }; 083DAEA40F01A7FB00342754 /* RenderTextControlSingleLine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTextControlSingleLine.cpp; sourceTree = "<group>"; }; 083DAEA50F01A7FB00342754 /* RenderTextControlSingleLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderTextControlSingleLine.h; sourceTree = "<group>"; }; + 0842BC701190144000C7D08F /* SVGCharacterData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGCharacterData.cpp; sourceTree = "<group>"; }; + 0842BC711190144000C7D08F /* SVGCharacterData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGCharacterData.h; sourceTree = "<group>"; }; + 0842BC801190147200C7D08F /* SVGTextChunkLayoutInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGTextChunkLayoutInfo.h; sourceTree = "<group>"; }; 084AEBE20FB505FA0038483E /* SelectElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectElement.cpp; sourceTree = "<group>"; }; 084AEBE30FB505FA0038483E /* SelectElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectElement.h; sourceTree = "<group>"; }; 084CE5C70F27DADC00E6240E /* WMLOptGroupElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WMLOptGroupElement.cpp; sourceTree = "<group>"; }; @@ -5467,6 +5489,9 @@ 084D2832110A7FCB0038239A /* SVGAnimatedPropertyTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedPropertyTraits.h; sourceTree = "<group>"; }; 084DBA9D0ED39D350038C226 /* WMLVariables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WMLVariables.cpp; sourceTree = "<group>"; }; 084DBA9E0ED39D360038C226 /* WMLVariables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMLVariables.h; sourceTree = "<group>"; }; + 08563BB2117861770012B578 /* RenderSVGResourcePattern.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGResourcePattern.cpp; sourceTree = "<group>"; }; + 08563BB3117861770012B578 /* RenderSVGResourcePattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGResourcePattern.h; sourceTree = "<group>"; }; + 08563BCF117865F50012B578 /* RenderSVGResource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGResource.cpp; sourceTree = "<group>"; }; 08591AA40F085C4E009BACB1 /* InputElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InputElement.h; sourceTree = "<group>"; }; 085AFDC60F2977350061F2B3 /* WMLFormControlElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WMLFormControlElement.cpp; sourceTree = "<group>"; }; 085AFDC70F2977350061F2B3 /* WMLFormControlElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMLFormControlElement.h; sourceTree = "<group>"; }; @@ -5510,10 +5535,18 @@ 08A484750E5272C500C3FE76 /* ScriptElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptElement.cpp; sourceTree = "<group>"; }; 08A484760E5272C500C3FE76 /* ScriptElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptElement.h; sourceTree = "<group>"; }; 08A48A6D0E86CF6D00E225DD /* JSSVGElementInstanceCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSVGElementInstanceCustom.cpp; sourceTree = "<group>"; }; + 08C34AF11179C056002D7456 /* RenderSVGResourceGradient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGResourceGradient.cpp; sourceTree = "<group>"; }; + 08C34AF21179C057002D7456 /* RenderSVGResourceGradient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGResourceGradient.h; sourceTree = "<group>"; }; + 08C34AF31179C057002D7456 /* RenderSVGResourceLinearGradient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGResourceLinearGradient.cpp; sourceTree = "<group>"; }; + 08C34AF41179C057002D7456 /* RenderSVGResourceLinearGradient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGResourceLinearGradient.h; sourceTree = "<group>"; }; + 08C34AFB1179C072002D7456 /* RenderSVGResourceRadialGradient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGResourceRadialGradient.cpp; sourceTree = "<group>"; }; + 08C34AFC1179C072002D7456 /* RenderSVGResourceRadialGradient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGResourceRadialGradient.h; sourceTree = "<group>"; }; 08C4C5140EF19A4000E4840F /* WMLImageElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WMLImageElement.cpp; sourceTree = "<group>"; }; 08C4C5150EF19A4000E4840F /* WMLImageElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMLImageElement.h; sourceTree = "<group>"; }; 08C4C5160EF19A4000E4840F /* WMLImageLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WMLImageLoader.cpp; sourceTree = "<group>"; }; 08C4C5170EF19A4000E4840F /* WMLImageLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMLImageLoader.h; sourceTree = "<group>"; }; + 08C6A7A9117DFBAB00FEA1A2 /* RenderSVGResourceSolidColor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGResourceSolidColor.cpp; sourceTree = "<group>"; }; + 08C6A7AA117DFBAB00FEA1A2 /* RenderSVGResourceSolidColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGResourceSolidColor.h; sourceTree = "<group>"; }; 08C925170FCC7C4A00480DEC /* FilterEffect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FilterEffect.cpp; path = filters/FilterEffect.cpp; sourceTree = "<group>"; }; 08C925180FCC7C4A00480DEC /* FilterEffect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FilterEffect.h; path = filters/FilterEffect.h; sourceTree = "<group>"; }; 08CD61B80ED3929C002DDF51 /* WMLTaskElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WMLTaskElement.cpp; sourceTree = "<group>"; }; @@ -5582,14 +5615,18 @@ 0FD308D4117D168400A791F7 /* RenderIFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderIFrame.h; sourceTree = "<group>"; }; 0FD723800EC8BD9300CA5DD7 /* FloatQuad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FloatQuad.h; sourceTree = "<group>"; }; 0FD723810EC8BD9300CA5DD7 /* FloatQuad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FloatQuad.cpp; sourceTree = "<group>"; }; - 0FF50259102BA9010066F39A /* DOMMedia.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMMedia.h; sourceTree = "<group>"; }; - 0FF5025A102BA9010066F39A /* DOMMedia.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMMedia.mm; sourceTree = "<group>"; }; - 0FF50262102BA92B0066F39A /* DOMMediaInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMMediaInternal.h; sourceTree = "<group>"; }; - 0FF50267102BA9430066F39A /* JSMedia.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMedia.cpp; sourceTree = "<group>"; }; - 0FF50268102BA9430066F39A /* JSMedia.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMedia.h; sourceTree = "<group>"; }; - 0FF5026E102BA9660066F39A /* Media.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Media.cpp; sourceTree = "<group>"; }; - 0FF5026F102BA96A0066F39A /* Media.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Media.h; sourceTree = "<group>"; }; - 0FF50270102BA96A0066F39A /* Media.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Media.idl; sourceTree = "<group>"; }; + 0FF2813211821CB6007B7CD6 /* RenderMathMLRoot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderMathMLRoot.cpp; sourceTree = "<group>"; }; + 0FF2813311821CB6007B7CD6 /* RenderMathMLRoot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderMathMLRoot.h; sourceTree = "<group>"; }; + 0FF2813411821CB6007B7CD6 /* RenderMathMLSquareRoot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderMathMLSquareRoot.cpp; sourceTree = "<group>"; }; + 0FF2813511821CB6007B7CD6 /* RenderMathMLSquareRoot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderMathMLSquareRoot.h; sourceTree = "<group>"; }; + 0FF50259102BA9010066F39A /* DOMStyleMedia.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMStyleMedia.h; sourceTree = "<group>"; }; + 0FF5025A102BA9010066F39A /* DOMStyleMedia.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMStyleMedia.mm; sourceTree = "<group>"; }; + 0FF50262102BA92B0066F39A /* DOMStyleMediaInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMStyleMediaInternal.h; sourceTree = "<group>"; }; + 0FF50267102BA9430066F39A /* JSStyleMedia.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStyleMedia.cpp; sourceTree = "<group>"; }; + 0FF50268102BA9430066F39A /* JSStyleMedia.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStyleMedia.h; sourceTree = "<group>"; }; + 0FF5026E102BA9660066F39A /* StyleMedia.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleMedia.cpp; sourceTree = "<group>"; }; + 0FF5026F102BA96A0066F39A /* StyleMedia.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleMedia.h; sourceTree = "<group>"; }; + 0FF50270102BA96A0066F39A /* StyleMedia.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = StyleMedia.idl; sourceTree = "<group>"; }; 1402645D0AFDC19B005919E2 /* LoggingMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = LoggingMac.mm; sourceTree = "<group>"; }; 1403B90C09EB124500797C7F /* DOMWindow.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DOMWindow.idl; sourceTree = "<group>"; }; 1403B99509EB13AF00797C7F /* DOMWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMWindow.h; sourceTree = "<group>"; }; @@ -5652,6 +5689,8 @@ 15C77092100D3CA8005BA267 /* JSValidityState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSValidityState.cpp; sourceTree = "<group>"; }; 15C770A3100D41CD005BA267 /* DOMValidityState.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMValidityState.mm; sourceTree = "<group>"; }; 15C770A4100D41CD005BA267 /* DOMValidityState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMValidityState.h; sourceTree = "<group>"; }; + 163E88F5118A39D200ED9231 /* SimpleFontDataCoreText.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SimpleFontDataCoreText.cpp; sourceTree = "<group>"; }; + 163E8B12118B3ADD00ED9231 /* SimpleFontDataATSUI.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SimpleFontDataATSUI.mm; sourceTree = "<group>"; }; 185BCF260F3279CE000EA262 /* ThreadTimers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadTimers.cpp; sourceTree = "<group>"; }; 185BCF270F3279CE000EA262 /* ThreadTimers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadTimers.h; sourceTree = "<group>"; }; 188604B10F2E654A000B6443 /* DOMTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMTimer.cpp; sourceTree = "<group>"; }; @@ -5671,6 +5710,7 @@ 1A2246460CC98DDB00C05240 /* SQLiteStatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SQLiteStatement.h; path = sql/SQLiteStatement.h; sourceTree = "<group>"; }; 1A2246470CC98DDB00C05240 /* SQLiteTransaction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SQLiteTransaction.cpp; path = sql/SQLiteTransaction.cpp; sourceTree = "<group>"; }; 1A2246480CC98DDB00C05240 /* SQLiteTransaction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SQLiteTransaction.h; path = sql/SQLiteTransaction.h; sourceTree = "<group>"; }; + 1A27CF96118A354C0041D632 /* nptypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nptypes.h; path = bridge/nptypes.h; sourceTree = "<group>"; }; 1A2A68210B5BEDE70002A480 /* ProgressTracker.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ProgressTracker.cpp; sourceTree = "<group>"; }; 1A2A68220B5BEDE70002A480 /* ProgressTracker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ProgressTracker.h; sourceTree = "<group>"; }; 1A2AAC560DC2A3B100A20D9A /* ApplicationCacheStorage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ApplicationCacheStorage.cpp; sourceTree = "<group>"; }; @@ -5979,6 +6019,7 @@ 24F54EAB101FE914000AE741 /* ApplicationCacheHost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ApplicationCacheHost.h; sourceTree = "<group>"; }; 2542F4D81166C25A00E89A86 /* UserGestureIndicator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserGestureIndicator.cpp; sourceTree = "<group>"; }; 2542F4D91166C25A00E89A86 /* UserGestureIndicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserGestureIndicator.h; sourceTree = "<group>"; }; + 271245D311890AB70083E852 /* WebCore.ProtectionSpaceAuthCallback.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = WebCore.ProtectionSpaceAuthCallback.exp; sourceTree = "<group>"; }; 29A812080FBB9C1D00510293 /* AccessibilityRenderObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilityRenderObject.cpp; sourceTree = "<group>"; }; 29A812090FBB9C1D00510293 /* AccessibilityTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilityTable.cpp; sourceTree = "<group>"; }; 29A8120A0FBB9C1D00510293 /* AccessibilityARIAGrid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilityARIAGrid.cpp; sourceTree = "<group>"; }; @@ -6028,6 +6069,13 @@ 2E2D99E910E2BC3800496337 /* DOMBlobInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMBlobInternal.h; sourceTree = "<group>"; }; 2E3BBF051162DA1100B9409A /* UUID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UUID.cpp; sourceTree = "<group>"; }; 2E3BBF061162DA1100B9409A /* UUID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UUID.h; sourceTree = "<group>"; }; + 2E3BC0BB117D3A4F00B9409A /* FileError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileError.h; sourceTree = "<group>"; }; + 2E3BC0BC117D3A4F00B9409A /* FileError.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = FileError.idl; sourceTree = "<group>"; }; + 2E3BC0C8117D3E0800B9409A /* JSFileError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFileError.cpp; sourceTree = "<group>"; }; + 2E3BC0C9117D3E0800B9409A /* JSFileError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSFileError.h; sourceTree = "<group>"; }; + 2E3BC106117D479800B9409A /* DOMFileError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMFileError.h; sourceTree = "<group>"; }; + 2E3BC107117D479800B9409A /* DOMFileError.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMFileError.mm; sourceTree = "<group>"; }; + 2E3BC10A117D47C800B9409A /* DOMFileErrorInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMFileErrorInternal.h; sourceTree = "<group>"; }; 2E4346320F546A8200B0F1BA /* GenericWorkerTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GenericWorkerTask.h; path = workers/GenericWorkerTask.h; sourceTree = "<group>"; }; 2E4346330F546A8200B0F1BA /* Worker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Worker.cpp; path = workers/Worker.cpp; sourceTree = "<group>"; }; 2E4346340F546A8200B0F1BA /* Worker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Worker.h; path = workers/Worker.h; sourceTree = "<group>"; }; @@ -6048,6 +6096,8 @@ 2E4346430F546A8200B0F1BA /* WorkerThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WorkerThread.h; path = workers/WorkerThread.h; sourceTree = "<group>"; }; 2E4346560F546A9900B0F1BA /* CrossThreadCopier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CrossThreadCopier.cpp; sourceTree = "<group>"; }; 2E4346570F546A9900B0F1BA /* CrossThreadCopier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrossThreadCopier.h; sourceTree = "<group>"; }; + 2E94F3CB118B908E00B7F75D /* FileReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileReader.cpp; sourceTree = "<group>"; }; + 2E94F3CC118B908E00B7F75D /* FileReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileReader.h; sourceTree = "<group>"; }; 2EA768030FE7126400AB9C8A /* WorkerScriptLoaderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WorkerScriptLoaderClient.h; path = workers/WorkerScriptLoaderClient.h; sourceTree = "<group>"; }; 2EAFAF0B10E2AF2D007ED3D6 /* Blob.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Blob.cpp; sourceTree = "<group>"; }; 2EAFAF0C10E2AF2D007ED3D6 /* Blob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Blob.h; sourceTree = "<group>"; }; @@ -6151,13 +6201,13 @@ 37F818FB0D657606005E1F05 /* WebCoreURLResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebCoreURLResponse.h; sourceTree = "<group>"; }; 37F818FC0D657606005E1F05 /* WebCoreURLResponse.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCoreURLResponse.mm; sourceTree = "<group>"; }; 37FC96DA1104ED71003E1FAD /* TrailingFloatsRootInlineBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrailingFloatsRootInlineBox.h; sourceTree = "<group>"; }; + 37FD4297118368460093C029 /* TreeDepthLimit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TreeDepthLimit.h; sourceTree = "<group>"; }; 41002CCB0F66EDEF009E660D /* ScriptFunctionCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptFunctionCall.h; sourceTree = "<group>"; }; 41002CCC0F66EDEF009E660D /* ScriptFunctionCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptFunctionCall.cpp; sourceTree = "<group>"; }; 410B7E711045FAB000D8224F /* JSMessageEventCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMessageEventCustom.cpp; sourceTree = "<group>"; }; 4110463F0FA222A600BA436A /* ScriptEventListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptEventListener.h; sourceTree = "<group>"; }; 411046400FA222A600BA436A /* ScriptEventListener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptEventListener.cpp; sourceTree = "<group>"; }; 4127D5360F8AAB1D00E424F5 /* ScriptState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptState.cpp; sourceTree = "<group>"; }; - 415B7C540FF598E6006770F7 /* JSAbstractWorkerCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAbstractWorkerCustom.cpp; sourceTree = "<group>"; }; 415B7C550FF598E6006770F7 /* JSSharedWorkerConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSharedWorkerConstructor.cpp; sourceTree = "<group>"; }; 415B7C620FF5A767006770F7 /* JSSharedWorkerConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSharedWorkerConstructor.h; sourceTree = "<group>"; }; 4162A44D101145AE00DFF3ED /* DedicatedWorkerContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DedicatedWorkerContext.cpp; path = workers/DedicatedWorkerContext.cpp; sourceTree = "<group>"; }; @@ -6616,14 +6666,7 @@ 51E4ADB30C42B4CF0042BC55 /* FTPDirectoryDocument.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FTPDirectoryDocument.h; sourceTree = "<group>"; }; 51EC92570CE90DB400F90308 /* SQLError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLError.h; sourceTree = "<group>"; }; 51EC92580CE90DB400F90308 /* SQLError.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SQLError.idl; sourceTree = "<group>"; }; - 51EC925B0CE90DD400F90308 /* JSCustomSQLStatementCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCustomSQLStatementCallback.cpp; sourceTree = "<group>"; }; - 51EC925C0CE90DD400F90308 /* JSCustomSQLStatementCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCustomSQLStatementCallback.h; sourceTree = "<group>"; }; 51EC925D0CE90DD400F90308 /* JSCustomSQLStatementErrorCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCustomSQLStatementErrorCallback.cpp; sourceTree = "<group>"; }; - 51EC925E0CE90DD400F90308 /* JSCustomSQLStatementErrorCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCustomSQLStatementErrorCallback.h; sourceTree = "<group>"; }; - 51EC925F0CE90DD400F90308 /* JSCustomSQLTransactionCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCustomSQLTransactionCallback.cpp; sourceTree = "<group>"; }; - 51EC92600CE90DD400F90308 /* JSCustomSQLTransactionCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCustomSQLTransactionCallback.h; sourceTree = "<group>"; }; - 51EC92610CE90DD400F90308 /* JSCustomSQLTransactionErrorCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCustomSQLTransactionErrorCallback.cpp; sourceTree = "<group>"; }; - 51EC92620CE90DD400F90308 /* JSCustomSQLTransactionErrorCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCustomSQLTransactionErrorCallback.h; sourceTree = "<group>"; }; 51F6A3D50663BF04004D2919 /* HTMLCanvasElement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLCanvasElement.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; 51F6A3D60663BF04004D2919 /* HTMLCanvasElement.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = HTMLCanvasElement.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; 51FAFE330CECBF2D00BB3F24 /* DatabaseTrackerClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseTrackerClient.h; sourceTree = "<group>"; }; @@ -6842,6 +6885,8 @@ 7AED3E040FBB1EAA00D2B03C /* InspectorFrontend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorFrontend.h; sourceTree = "<group>"; }; 7AFD4A8A1131C2760035B883 /* ScriptBreakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptBreakpoint.h; sourceTree = "<group>"; }; 7AFD4FF3113277B60035B883 /* ScriptDebugListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptDebugListener.h; sourceTree = "<group>"; }; + 82B658971189E39200E052A1 /* InspectorCSSStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorCSSStore.h; sourceTree = "<group>"; }; + 82B658991189E47600E052A1 /* InspectorCSSStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorCSSStore.cpp; sourceTree = "<group>"; }; 841FDC241178C9BE00F8AC9B /* RenderSVGResourceFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGResourceFilter.cpp; sourceTree = "<group>"; }; 841FDC251178C9BE00F8AC9B /* RenderSVGResourceFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGResourceFilter.h; sourceTree = "<group>"; }; 84224181107E77F400766A87 /* JSSVGFEMorphologyElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSVGFEMorphologyElement.cpp; sourceTree = "<group>"; }; @@ -9066,21 +9111,6 @@ B255990B0D00D8B900BB825C /* SVGImage.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SVGImage.cpp; sourceTree = "<group>"; }; B255990C0D00D8B900BB825C /* SVGImage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SVGImage.h; sourceTree = "<group>"; }; B255990D0D00D8B900BB825C /* EmptyClients.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = EmptyClients.h; sourceTree = "<group>"; }; - B255990E0D00D8B900BB825C /* SVGPaintServer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SVGPaintServer.cpp; sourceTree = "<group>"; }; - B255990F0D00D8B900BB825C /* SVGPaintServer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SVGPaintServer.h; sourceTree = "<group>"; }; - B25599100D00D8B900BB825C /* SVGPaintServerGradient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SVGPaintServerGradient.cpp; sourceTree = "<group>"; }; - B25599110D00D8B900BB825C /* SVGPaintServerGradient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SVGPaintServerGradient.h; sourceTree = "<group>"; }; - B25599120D00D8B900BB825C /* SVGPaintServerLinearGradient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SVGPaintServerLinearGradient.cpp; sourceTree = "<group>"; }; - B25599130D00D8B900BB825C /* SVGPaintServerLinearGradient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SVGPaintServerLinearGradient.h; sourceTree = "<group>"; }; - B25599140D00D8B900BB825C /* SVGPaintServerPattern.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SVGPaintServerPattern.cpp; sourceTree = "<group>"; }; - B25599150D00D8B900BB825C /* SVGPaintServerPattern.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SVGPaintServerPattern.h; sourceTree = "<group>"; }; - B25599160D00D8B900BB825C /* SVGPaintServerRadialGradient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SVGPaintServerRadialGradient.cpp; sourceTree = "<group>"; }; - B25599170D00D8B900BB825C /* SVGPaintServerRadialGradient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SVGPaintServerRadialGradient.h; sourceTree = "<group>"; }; - B25599180D00D8B900BB825C /* SVGPaintServerSolid.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SVGPaintServerSolid.cpp; sourceTree = "<group>"; }; - B25599190D00D8B900BB825C /* SVGPaintServerSolid.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SVGPaintServerSolid.h; sourceTree = "<group>"; }; - B255991A0D00D8B900BB825C /* SVGResource.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SVGResource.cpp; sourceTree = "<group>"; }; - B255991B0D00D8B900BB825C /* SVGResource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SVGResource.h; sourceTree = "<group>"; }; - B25599200D00D8B900BB825C /* SVGResourceListener.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SVGResourceListener.h; sourceTree = "<group>"; }; B25DFAAE0B2E2929000E6510 /* JSSVGMatrixCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSSVGMatrixCustom.cpp; sourceTree = "<group>"; }; B262B8030D1F32D000158F09 /* SVGFont.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SVGFont.cpp; sourceTree = "<group>"; }; B26554E80B80D74900A50EC3 /* RenderSVGTextPath.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGTextPath.cpp; sourceTree = "<group>"; }; @@ -9495,13 +9525,31 @@ B50F5B800E96CD9900AD71A6 /* WebCoreObjCExtras.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCoreObjCExtras.mm; sourceTree = "<group>"; }; B51BF6EE102C9E590002C15A /* SQLTransactionClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SQLTransactionClient.cpp; sourceTree = "<group>"; }; B51BF6EF102C9E590002C15A /* SQLTransactionClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLTransactionClient.h; sourceTree = "<group>"; }; + B523CEFF1182675400EBB29C /* SQLTransactionSyncCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLTransactionSyncCallback.h; sourceTree = "<group>"; }; + B523CF011182675400EBB29C /* SQLTransactionSync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLTransactionSync.h; sourceTree = "<group>"; }; + B523CF021182675400EBB29C /* SQLTransactionSync.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SQLTransactionSync.cpp; sourceTree = "<group>"; }; + B523CF031182675400EBB29C /* DatabaseSync.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseSync.cpp; sourceTree = "<group>"; }; + B523CF041182675400EBB29C /* DatabaseSync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseSync.h; sourceTree = "<group>"; }; + B59DD68D1190298E007E9684 /* DatabaseCallback.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DatabaseCallback.idl; sourceTree = "<group>"; }; + B59DD68E1190298E007E9684 /* SQLStatementCallback.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SQLStatementCallback.idl; sourceTree = "<group>"; }; + B59DD68F1190298E007E9684 /* SQLStatementErrorCallback.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SQLStatementErrorCallback.idl; sourceTree = "<group>"; }; + B59DD6901190298E007E9684 /* SQLTransactionCallback.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SQLTransactionCallback.idl; sourceTree = "<group>"; }; + B59DD6911190298E007E9684 /* SQLTransactionErrorCallback.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SQLTransactionErrorCallback.idl; sourceTree = "<group>"; }; + B59DD697119029E5007E9684 /* JSDatabaseCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDatabaseCallback.h; sourceTree = "<group>"; }; + B59DD698119029E5007E9684 /* JSDatabaseCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDatabaseCallback.cpp; sourceTree = "<group>"; }; + B59DD69B11902A42007E9684 /* JSSQLTransactionCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSQLTransactionCallback.h; sourceTree = "<group>"; }; + B59DD69C11902A42007E9684 /* JSSQLTransactionCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSQLTransactionCallback.cpp; sourceTree = "<group>"; }; + B59DD69F11902A52007E9684 /* JSSQLTransactionErrorCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSQLTransactionErrorCallback.h; sourceTree = "<group>"; }; + B59DD6A011902A52007E9684 /* JSSQLTransactionErrorCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSQLTransactionErrorCallback.cpp; sourceTree = "<group>"; }; + B59DD6A311902A62007E9684 /* JSSQLStatementCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSQLStatementCallback.h; sourceTree = "<group>"; }; + B59DD6A411902A62007E9684 /* JSSQLStatementCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSQLStatementCallback.cpp; sourceTree = "<group>"; }; + B59DD6A711902A71007E9684 /* JSSQLStatementErrorCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSQLStatementErrorCallback.h; sourceTree = "<group>"; }; + B59DD6A811902A71007E9684 /* JSSQLStatementErrorCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSQLStatementErrorCallback.cpp; sourceTree = "<group>"; }; B5A684210FFABE9800D24689 /* SQLiteFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SQLiteFileSystem.h; path = sql/SQLiteFileSystem.h; sourceTree = "<group>"; }; B5A684230FFABEAA00D24689 /* SQLiteFileSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SQLiteFileSystem.cpp; path = sql/SQLiteFileSystem.cpp; sourceTree = "<group>"; }; B5C11239102B6C4600096578 /* SQLTransactionCoordinator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SQLTransactionCoordinator.cpp; sourceTree = "<group>"; }; B5C1123A102B6C4600096578 /* SQLTransactionCoordinator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLTransactionCoordinator.h; sourceTree = "<group>"; }; B5D36019112F8B560048DEA8 /* DatabaseCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseCallback.h; sourceTree = "<group>"; }; - B5D3601C112F8BA00048DEA8 /* JSDatabaseCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDatabaseCallback.h; sourceTree = "<group>"; }; - B5D3601E112F8BA80048DEA8 /* JSDatabaseCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDatabaseCallback.cpp; sourceTree = "<group>"; }; B776D43A1104525D00BEB0EC /* PrintContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrintContext.h; sourceTree = "<group>"; }; B776D43C1104527500BEB0EC /* PrintContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrintContext.cpp; sourceTree = "<group>"; }; BC00EFFE0E0A185500FD04E3 /* DOMFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMFile.h; sourceTree = "<group>"; }; @@ -9937,7 +9985,6 @@ BCCD74DB0A4C8D35005FDA6D /* HTMLViewSourceDocument.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HTMLViewSourceDocument.h; sourceTree = "<group>"; }; BCCD74E40A4C8DDF005FDA6D /* HTMLViewSourceDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLViewSourceDocument.cpp; sourceTree = "<group>"; }; BCCE58AB1061E8CF008FB35A /* JSDatabaseCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDatabaseCustom.cpp; sourceTree = "<group>"; }; - BCCE58AE1061E90C008FB35A /* JSDocumentFragmentCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDocumentFragmentCustom.cpp; sourceTree = "<group>"; }; BCCFBAE70B5152ED0001F1D7 /* Tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Tokenizer.h; sourceTree = "<group>"; }; BCD0E0F70E972C3500265DEA /* SecurityOrigin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecurityOrigin.cpp; sourceTree = "<group>"; }; BCD0E0F80E972C3500265DEA /* SecurityOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecurityOrigin.h; sourceTree = "<group>"; }; @@ -10085,7 +10132,6 @@ C5160EE91004543A00A7CEE2 /* StorageAreaImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageAreaImpl.h; sourceTree = "<group>"; }; C55E38BB10040D5D00A56BDB /* StorageNamespaceImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageNamespaceImpl.h; sourceTree = "<group>"; }; C55E38BC10040D5D00A56BDB /* StorageNamespaceImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StorageNamespaceImpl.cpp; sourceTree = "<group>"; }; - C5D4AA77116BAFB60069CA93 /* GlyphMetricsMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GlyphMetricsMap.cpp; sourceTree = "<group>"; }; C5D4AA78116BAFB60069CA93 /* GlyphMetricsMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GlyphMetricsMap.h; sourceTree = "<group>"; }; C5E9B67610697E1300C7BB1A /* StorageEventDispatcher.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StorageEventDispatcher.cpp; sourceTree = "<group>"; }; C5EBDD81105EDDEC0056816F /* StorageEventDispatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageEventDispatcher.h; sourceTree = "<group>"; }; @@ -10123,7 +10169,6 @@ E0FEF371B27C53EAC1C1FBEE /* EventSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventSource.cpp; sourceTree = "<group>"; }; E0FEF371B37C53EAC1C1FBEE /* JSEventSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSEventSource.h; sourceTree = "<group>"; }; E0FEF371B47C53EAC1C1FBEE /* JSEventSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSEventSource.cpp; sourceTree = "<group>"; }; - E0FEF371B57C53EAC1C1FBEE /* JSEventSourceCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSEventSourceCustom.cpp; sourceTree = "<group>"; }; E0FEF371B67C53EAC1C1FBEE /* JSEventSourceConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSEventSourceConstructor.h; sourceTree = "<group>"; }; E0FEF371B77C53EAC1C1FBEE /* JSEventSourceConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSEventSourceConstructor.cpp; sourceTree = "<group>"; }; E107400B0E77BDC00033AF24 /* JSMessageChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMessageChannel.cpp; sourceTree = "<group>"; }; @@ -10603,6 +10648,7 @@ 1A569CDF0D7E2B82007C3983 /* npruntime_impl.h */, 1A569CE00D7E2B82007C3983 /* npruntime_internal.h */, 1A569CE10D7E2B82007C3983 /* npruntime_priv.h */, + 1A27CF96118A354C0041D632 /* nptypes.h */, 1A569CEF0D7E2B82007C3983 /* runtime_array.cpp */, 1A569CF00D7E2B82007C3983 /* runtime_array.h */, 1A569CF10D7E2B82007C3983 /* runtime_method.cpp */, @@ -10726,7 +10772,10 @@ 51A45B550CAD7FD7000D2BE9 /* DatabaseAuthorizer.cpp */, 51A45B540CAD7FD7000D2BE9 /* DatabaseAuthorizer.h */, B5D36019112F8B560048DEA8 /* DatabaseCallback.h */, + B59DD68D1190298E007E9684 /* DatabaseCallback.idl */, 5116D9750CF177BD00C2B84D /* DatabaseDetails.h */, + B523CF031182675400EBB29C /* DatabaseSync.cpp */, + B523CF041182675400EBB29C /* DatabaseSync.h */, 519611E90CAC749C0010A80C /* DatabaseTask.cpp */, 519611E80CAC749C0010A80C /* DatabaseTask.h */, 519611610CAC56570010A80C /* DatabaseThread.cpp */, @@ -10753,16 +10802,23 @@ 515B03980CD1642A00B7EA9C /* SQLStatement.cpp */, 515B03970CD1642A00B7EA9C /* SQLStatement.h */, 1A7CCB150CD9469A00B7B64E /* SQLStatementCallback.h */, + B59DD68E1190298E007E9684 /* SQLStatementCallback.idl */, 1A7CCB160CD9469A00B7B64E /* SQLStatementErrorCallback.h */, + B59DD68F1190298E007E9684 /* SQLStatementErrorCallback.idl */, 1ABFE7520CD968D000FE4834 /* SQLTransaction.cpp */, 1A7CCB220CD946FD00B7B64E /* SQLTransaction.h */, 1A7CCB230CD946FD00B7B64E /* SQLTransaction.idl */, 1A7CCB170CD9469A00B7B64E /* SQLTransactionCallback.h */, + B59DD6901190298E007E9684 /* SQLTransactionCallback.idl */, B51BF6EE102C9E590002C15A /* SQLTransactionClient.cpp */, B51BF6EF102C9E590002C15A /* SQLTransactionClient.h */, B5C11239102B6C4600096578 /* SQLTransactionCoordinator.cpp */, B5C1123A102B6C4600096578 /* SQLTransactionCoordinator.h */, 1A7CCB180CD9469A00B7B64E /* SQLTransactionErrorCallback.h */, + B59DD6911190298E007E9684 /* SQLTransactionErrorCallback.idl */, + B523CF021182675400EBB29C /* SQLTransactionSync.cpp */, + B523CF011182675400EBB29C /* SQLTransactionSync.h */, + B523CEFF1182675400EBB29C /* SQLTransactionSyncCallback.h */, 51E3F9C50DA059DC00250911 /* Storage.cpp */, 51E3F9C40DA059DC00250911 /* Storage.h */, 51E3F9D10DA05D7100250911 /* Storage.idl */, @@ -10854,6 +10910,8 @@ 9FA37EF01172FD4100C4CD55 /* ScriptProfileNode.idl */, 7553CFE7108F473F00EA281E /* TimelineRecordFactory.cpp */, 7553CFE6108F473F00EA281E /* TimelineRecordFactory.h */, + 82B658971189E39200E052A1 /* InspectorCSSStore.h */, + 82B658991189E47600E052A1 /* InspectorCSSStore.cpp */, ); path = inspector; sourceTree = "<group>"; @@ -11044,6 +11102,7 @@ 4491959A0FBE17D700D9F824 /* WebCore.NPAPI.exp */, FE136AE710643BE50078CF6D /* WebCore.OrientationEvents.exp */, 4491959B0FBE17D700D9F824 /* WebCore.PluginHostProcess.exp */, + 271245D311890AB70083E852 /* WebCore.ProtectionSpaceAuthCallback.exp */, 449195990FBE17D700D9F824 /* WebCore.SVG.Animation.exp */, 449195980FBE17D700D9F824 /* WebCore.SVG.exp */, 449195970FBE17D700D9F824 /* WebCore.SVG.Filters.exp */, @@ -11761,10 +11820,10 @@ 850657040AAB476C002D15C0 /* StyleSheets */ = { isa = PBXGroup; children = ( - 0FF50259102BA9010066F39A /* DOMMedia.h */, - 0FF5025A102BA9010066F39A /* DOMMedia.mm */, 850656F80AAB4763002D15C0 /* DOMMediaList.h */, 850656F90AAB4763002D15C0 /* DOMMediaList.mm */, + 0FF50259102BA9010066F39A /* DOMStyleMedia.h */, + 0FF5025A102BA9010066F39A /* DOMStyleMedia.mm */, 850656FA0AAB4763002D15C0 /* DOMStyleSheet.h */, 850656FB0AAB4763002D15C0 /* DOMStyleSheet.mm */, 850656FC0AAB4763002D15C0 /* DOMStyleSheetList.h */, @@ -12447,6 +12506,8 @@ 2E2D99E610E2BC1C00496337 /* DOMBlob.mm */, BC00EFFE0E0A185500FD04E3 /* DOMFile.h */, BC00EFFF0E0A185500FD04E3 /* DOMFile.mm */, + 2E3BC106117D479800B9409A /* DOMFileError.h */, + 2E3BC107117D479800B9409A /* DOMFileError.mm */, BC00F0010E0A185500FD04E3 /* DOMFileList.h */, BC00F0020E0A185500FD04E3 /* DOMFileList.mm */, 85DF81210AA7787200486AD7 /* DOMHTMLAnchorElement.h */, @@ -12617,6 +12678,7 @@ 85E7114A0AC5D5340053270F /* DOMEntityInternal.h */, 85E7114B0AC5D5340053270F /* DOMEntityReferenceInternal.h */, 85B498F40ADB337A00925CBB /* DOMEventInternal.h */, + 2E3BC10A117D47C800B9409A /* DOMFileErrorInternal.h */, BC00F0000E0A185500FD04E3 /* DOMFileInternal.h */, BC00F0030E0A185500FD04E3 /* DOMFileListInternal.h */, 85E7114C0AC5D5340053270F /* DOMHTMLAnchorElementInternal.h */, @@ -12680,7 +12742,6 @@ 85E711800AC5D5350053270F /* DOMHTMLTitleElementInternal.h */, 85E711810AC5D5350053270F /* DOMHTMLUListElementInternal.h */, 85989DC50ACC8BBD00A0BC51 /* DOMKeyboardEventInternal.h */, - 0FF50262102BA92B0066F39A /* DOMMediaInternal.h */, 85E711820AC5D5350053270F /* DOMMediaListInternal.h */, 75793ED20D0CE85B007FC0AC /* DOMMessageEventInternal.h */, E1ADEDD40E76BD60004A1A5E /* DOMMessagePortInternal.h */, @@ -12697,6 +12758,7 @@ 8538F05A0AD722F1006A81D1 /* DOMRangeInternal.h */, 85E711870AC5D5350053270F /* DOMRectInternal.h */, BCD0FC4E0DBD720B00B2F630 /* DOMRGBColorInternal.h */, + 0FF50262102BA92B0066F39A /* DOMStyleMediaInternal.h */, 85B498FE0ADB348100925CBB /* DOMStyleSheetInternal.h */, 85E711880AC5D5350053270F /* DOMStyleSheetListInternal.h */, 85ACEF850ACDD04A001214FF /* DOMSVGAElementInternal.h */, @@ -12988,14 +13050,6 @@ 93EEC1EC09C2877700C515D1 /* html */ = { isa = PBXGroup; children = ( - 895253DE116C4F0600CABF00 /* FileThreadTask.h */, - 895253DA116C4EF500CABF00 /* FileStreamProxy.cpp */, - 895253DB116C4EF500CABF00 /* FileStreamProxy.h */, - 895253D4116C4C6800CABF00 /* FileStream.cpp */, - 895253D5116C4C6800CABF00 /* FileStream.h */, - 895253D6116C4C6800CABF00 /* FileStreamClient.h */, - 8952535011641B3400CABF00 /* FileThread.cpp */, - 8952535111641B3400CABF00 /* FileThread.h */, 49484FAE102CF01E00187DD3 /* canvas */, 2EAFAF0B10E2AF2D007ED3D6 /* Blob.cpp */, 2EAFAF0C10E2AF2D007ED3D6 /* Blob.h */, @@ -13020,9 +13074,21 @@ BCDBB8CC0E08958400C60FF6 /* File.cpp */, BCDBB8CB0E08958400C60FF6 /* File.h */, BC1881D90E08C4ED00048C13 /* File.idl */, + 2E3BC0BB117D3A4F00B9409A /* FileError.h */, + 2E3BC0BC117D3A4F00B9409A /* FileError.idl */, BCDBB8AB0E088CA500C60FF6 /* FileList.cpp */, BCDBB8AA0E088CA500C60FF6 /* FileList.h */, BC1881DC0E08C54300048C13 /* FileList.idl */, + 2E94F3CB118B908E00B7F75D /* FileReader.cpp */, + 2E94F3CC118B908E00B7F75D /* FileReader.h */, + 895253D4116C4C6800CABF00 /* FileStream.cpp */, + 895253D5116C4C6800CABF00 /* FileStream.h */, + 895253D6116C4C6800CABF00 /* FileStreamClient.h */, + 895253DA116C4EF500CABF00 /* FileStreamProxy.cpp */, + 895253DB116C4EF500CABF00 /* FileStreamProxy.h */, + 8952535011641B3400CABF00 /* FileThread.cpp */, + 8952535111641B3400CABF00 /* FileThread.h */, + 895253DE116C4F0600CABF00 /* FileThreadTask.h */, A8136D370973A8E700D74463 /* FormDataList.cpp */, A8136D360973A8E700D74463 /* FormDataList.h */, BC97E239109144950010D361 /* HTMLAllCollection.cpp */, @@ -13361,6 +13427,8 @@ 2E0888D31148848A00AF4265 /* JSDOMFormData.h */, BC00F0100E0A189500FD04E3 /* JSFile.cpp */, BC00F0110E0A189500FD04E3 /* JSFile.h */, + 2E3BC0C8117D3E0800B9409A /* JSFileError.cpp */, + 2E3BC0C9117D3E0800B9409A /* JSFileError.h */, BC00F0120E0A189500FD04E3 /* JSFileList.cpp */, BC00F0130E0A189500FD04E3 /* JSFileList.h */, BC97E410109154FA0010D361 /* JSHTMLAllCollection.cpp */, @@ -13884,14 +13952,14 @@ BC686C790E0C330100DE8A08 /* JSCSSVariablesDeclaration.h */, BC686C7A0E0C330100DE8A08 /* JSCSSVariablesRule.cpp */, BC686C7B0E0C330100DE8A08 /* JSCSSVariablesRule.h */, - 0FF50267102BA9430066F39A /* JSMedia.cpp */, - 0FF50268102BA9430066F39A /* JSMedia.h */, BC3C39B40C0D3D8D005F4D7A /* JSMediaList.cpp */, BC3C39B50C0D3D8D005F4D7A /* JSMediaList.h */, BCFE2F0F0C1B58370020235F /* JSRect.cpp */, BCFE2F100C1B58370020235F /* JSRect.h */, BC74DA461013F468007987AD /* JSRGBColor.cpp */, BC74DA471013F468007987AD /* JSRGBColor.h */, + 0FF50267102BA9430066F39A /* JSStyleMedia.cpp */, + 0FF50268102BA9430066F39A /* JSStyleMedia.h */, BCE013980C0BEF180043860A /* JSStyleSheet.cpp */, BCE013990C0BEF180043860A /* JSStyleSheet.h */, A84EBD820CB8C97700079609 /* JSStyleSheetList.cpp */, @@ -14027,6 +14095,16 @@ 51E3F9D50DA05E1D00250911 /* JSStorage.h */, 51E0BAE80DA55D4A00A9E417 /* JSStorageEvent.cpp */, 51E0BAE90DA55D4A00A9E417 /* JSStorageEvent.h */, + B59DD697119029E5007E9684 /* JSDatabaseCallback.h */, + B59DD698119029E5007E9684 /* JSDatabaseCallback.cpp */, + B59DD69B11902A42007E9684 /* JSSQLTransactionCallback.h */, + B59DD69C11902A42007E9684 /* JSSQLTransactionCallback.cpp */, + B59DD69F11902A52007E9684 /* JSSQLTransactionErrorCallback.h */, + B59DD6A011902A52007E9684 /* JSSQLTransactionErrorCallback.cpp */, + B59DD6A311902A62007E9684 /* JSSQLStatementCallback.h */, + B59DD6A411902A62007E9684 /* JSSQLStatementCallback.cpp */, + B59DD6A711902A71007E9684 /* JSSQLStatementErrorCallback.h */, + B59DD6A811902A71007E9684 /* JSSQLStatementErrorCallback.cpp */, ); name = Storage; sourceTree = "<group>"; @@ -14510,21 +14588,6 @@ B255989C0D00D8B800BB825C /* filters */, B255990B0D00D8B900BB825C /* SVGImage.cpp */, B255990C0D00D8B900BB825C /* SVGImage.h */, - B255990E0D00D8B900BB825C /* SVGPaintServer.cpp */, - B255990F0D00D8B900BB825C /* SVGPaintServer.h */, - B25599100D00D8B900BB825C /* SVGPaintServerGradient.cpp */, - B25599110D00D8B900BB825C /* SVGPaintServerGradient.h */, - B25599120D00D8B900BB825C /* SVGPaintServerLinearGradient.cpp */, - B25599130D00D8B900BB825C /* SVGPaintServerLinearGradient.h */, - B25599140D00D8B900BB825C /* SVGPaintServerPattern.cpp */, - B25599150D00D8B900BB825C /* SVGPaintServerPattern.h */, - B25599160D00D8B900BB825C /* SVGPaintServerRadialGradient.cpp */, - B25599170D00D8B900BB825C /* SVGPaintServerRadialGradient.h */, - B25599180D00D8B900BB825C /* SVGPaintServerSolid.cpp */, - B25599190D00D8B900BB825C /* SVGPaintServerSolid.h */, - B255991A0D00D8B900BB825C /* SVGResource.cpp */, - B255991B0D00D8B900BB825C /* SVGResource.h */, - B25599200D00D8B900BB825C /* SVGResourceListener.h */, ); path = graphics; sourceTree = "<group>"; @@ -14629,6 +14692,8 @@ E4B41E100CBF90EF00AF2ECE /* MediaPlayerPrivateQTKit.h */, E4B41E110CBF90EF00AF2ECE /* MediaPlayerPrivateQTKit.mm */, 0735EE690F40C5E4004A2604 /* MediaPlayerProxy.h */, + 163E8B12118B3ADD00ED9231 /* SimpleFontDataATSUI.mm */, + 163E88F5118A39D200ED9231 /* SimpleFontDataCoreText.cpp */, B2AFFC770D00A5C10030074D /* SimpleFontDataMac.mm */, 0FCF332B0F2B9A25004B6795 /* WebLayer.h */, 0FCF332A0F2B9A25004B6795 /* WebLayer.mm */, @@ -14683,7 +14748,6 @@ BC23F0DA0DAFF4A4009FDC91 /* GeneratedImage.h */, BCE04C890DAFF7A0007A0F41 /* Generator.h */, B2C3DA5B0D006CD600EF6F26 /* GlyphBuffer.h */, - C5D4AA77116BAFB60069CA93 /* GlyphMetricsMap.cpp */, C5D4AA78116BAFB60069CA93 /* GlyphMetricsMap.h */, B2C3DA5C0D006CD600EF6F26 /* GlyphPageTreeNode.cpp */, B2C3DA5D0D006CD600EF6F26 /* GlyphPageTreeNode.h */, @@ -14864,8 +14928,8 @@ BC53DA2D1143121E000D817E /* DOMWrapperWorld.h */, 1432E8480C51493F00B1500F /* GCController.cpp */, 1432E8460C51493800B1500F /* GCController.h */, - B5D3601E112F8BA80048DEA8 /* JSDatabaseCallback.cpp */, - B5D3601C112F8BA00048DEA8 /* JSDatabaseCallback.h */, + 1C81BA030E97348300266E07 /* JavaScriptCallFrame.cpp */, + 1C81BA040E97348300266E07 /* JavaScriptCallFrame.h */, BC53DAC411432FD9000D817E /* JSDebugWrapperSet.cpp */, BC53DAC111432EEE000D817E /* JSDebugWrapperSet.h */, 93B70D4709EB0C7C009D8468 /* JSDOMBinding.cpp */, @@ -14892,8 +14956,6 @@ E1C36D330EB0A094007410BC /* JSWorkerContextBase.h */, F3D461461161D53200CA0D09 /* JSWorkerContextErrorHandler.cpp */, F3D461471161D53200CA0D09 /* JSWorkerContextErrorHandler.h */, - 1C81BA030E97348300266E07 /* JavaScriptCallFrame.cpp */, - 1C81BA040E97348300266E07 /* JavaScriptCallFrame.h */, BCA378BA0D15F64200B793D6 /* ScheduledAction.cpp */, BCA378BB0D15F64200B793D6 /* ScheduledAction.h */, 7A1E88F3101CC384000C4DF5 /* ScriptArray.cpp */, @@ -14987,7 +15049,6 @@ BC4EDEF70C08F414007EDD49 /* Custom */ = { isa = PBXGroup; children = ( - 415B7C540FF598E6006770F7 /* JSAbstractWorkerCustom.cpp */, BC2ED6BB0C6BD2F000920BFF /* JSAttrCustom.cpp */, 49EED14B1051971900099FAB /* JSCanvasRenderingContext2DCustom.cpp */, 49EED14D1051971A00099FAB /* JSCanvasRenderingContextCustom.cpp */, @@ -15004,14 +15065,12 @@ 4162A453101145E300DFF3ED /* JSDedicatedWorkerContextCustom.cpp */, 33503CBF10179C1A003B47E1 /* JSDesktopNotificationsCustom.cpp */, 49C7BA8C1042F5B10009D447 /* JSDocumentCustom.cpp */, - BCCE58AE1061E90C008FB35A /* JSDocumentFragmentCustom.cpp */, 1AC226160DB69F740089B669 /* JSDOMApplicationCacheCustom.cpp */, 2E0888E5114884E200AF4265 /* JSDOMFormDataCustom.cpp */, BCD9C25E0C17AA67005C90A2 /* JSDOMWindowCustom.cpp */, 652FBBBB0DE27CB60001D386 /* JSDOMWindowCustom.h */, BC2ED5540C6B9BD300920BFF /* JSElementCustom.cpp */, BCEFAF4D0C317E6900FA81F6 /* JSEventCustom.cpp */, - E0FEF371B57C53EAC1C1FBEE /* JSEventSourceCustom.cpp */, FE80D7A60E9C1ED2000D6F75 /* JSGeolocationCustom.cpp */, BCE7B1920D4E86960075A539 /* JSHistoryCustom.cpp */, BC97E42B10915B060010D361 /* JSHTMLAllCollectionCustom.cpp */, @@ -15051,6 +15110,7 @@ A9C6E64A0D7465E7006442E9 /* JSPluginArrayCustom.cpp */, A9C6E64B0D7465E7006442E9 /* JSPluginCustom.cpp */, 5189F01710B3781300F3C739 /* JSPopStateEventCustom.cpp */, + 9FA37EE61172FCF000C4CD55 /* JSScriptProfileNodeCustom.cpp */, 51DCE8010CAC9F1C00488358 /* JSSQLResultSetRowListCustom.cpp */, 1AD2316D0CD269E700C1F194 /* JSSQLTransactionCustom.cpp */, 51D0C5150DAA90B7003B3831 /* JSStorageCustom.cpp */, @@ -15063,7 +15123,6 @@ B2C96D8C0B3AF2B7005E80EC /* JSSVGPathSegCustom.cpp */, B297BC6F0B3C14CF0045A590 /* JSSVGPathSegListCustom.cpp */, 087D97BE10FB8D7700C00874 /* JSSVGPODListCustom.h */, - 9FA37EE61172FCF000C4CD55 /* JSScriptProfileNodeCustom.cpp */, 1A2C40AA0DEB55AA005AF19E /* JSTextCustom.cpp */, 516BB7920CE91E6800512F79 /* JSTreeWalkerCustom.cpp */, 492273A21083B3B100EE5C84 /* JSWebGLArrayCustom.cpp */, @@ -15318,14 +15377,7 @@ FE80D7A30E9C1ED2000D6F75 /* JSCustomPositionCallback.h */, FE80D7A40E9C1ED2000D6F75 /* JSCustomPositionErrorCallback.cpp */, FE80D7A50E9C1ED2000D6F75 /* JSCustomPositionErrorCallback.h */, - 51EC925B0CE90DD400F90308 /* JSCustomSQLStatementCallback.cpp */, - 51EC925C0CE90DD400F90308 /* JSCustomSQLStatementCallback.h */, 51EC925D0CE90DD400F90308 /* JSCustomSQLStatementErrorCallback.cpp */, - 51EC925E0CE90DD400F90308 /* JSCustomSQLStatementErrorCallback.h */, - 51EC925F0CE90DD400F90308 /* JSCustomSQLTransactionCallback.cpp */, - 51EC92600CE90DD400F90308 /* JSCustomSQLTransactionCallback.h */, - 51EC92610CE90DD400F90308 /* JSCustomSQLTransactionErrorCallback.cpp */, - 51EC92620CE90DD400F90308 /* JSCustomSQLTransactionErrorCallback.h */, 1A3417C80CECFF250049CBDE /* JSCustomVoidCallback.cpp */, 1A3417C70CECFF250049CBDE /* JSCustomVoidCallback.h */, E10B93C20B73C291003ED890 /* JSCustomXPathNSResolver.cpp */, @@ -15764,9 +15816,6 @@ 93CA4C9B09DF93FA00DF8677 /* makeprop.pl */, 93CA4C9D09DF93FA00DF8677 /* makevalues.pl */, FA654A631108ABB7002615E0 /* mathml.css */, - 0FF5026E102BA9660066F39A /* Media.cpp */, - 0FF5026F102BA96A0066F39A /* Media.h */, - 0FF50270102BA96A0066F39A /* Media.idl */, 070DD8F50F01868000727DEB /* mediaControls.css */, 07AFE5900F1446BD00841617 /* mediaControlsQuickTime.css */, 4E19591F0A39DABA00220FE5 /* MediaFeatureNames.cpp */, @@ -15793,6 +15842,9 @@ A80E73490A199C77007FB8C5 /* StyleBase.h */, A80E73460A199C77007FB8C5 /* StyleList.cpp */, A80E734A0A199C77007FB8C5 /* StyleList.h */, + 0FF5026E102BA9660066F39A /* StyleMedia.cpp */, + 0FF5026F102BA96A0066F39A /* StyleMedia.h */, + 0FF50270102BA96A0066F39A /* StyleMedia.idl */, A8EA80050A19516E00A8EF5F /* StyleSheet.cpp */, A8EA80040A19516E00A8EF5F /* StyleSheet.h */, 850656DC0AAB44D9002D15C0 /* StyleSheet.idl */, @@ -15829,8 +15881,6 @@ F523D2F302DE443B018635CA /* rendering */ = { isa = PBXGroup; children = ( - 841FDC241178C9BE00F8AC9B /* RenderSVGResourceFilter.cpp */, - 841FDC251178C9BE00F8AC9B /* RenderSVGResourceFilter.h */, BC8C8FAA0DDCD2F200B592F4 /* style */, A8CFF04B0A154F09000A4234 /* AutoTableLayout.cpp */, A8CFF0490A154F09000A4234 /* AutoTableLayout.h */, @@ -15975,13 +16025,27 @@ 853CA9D10AEEC5E9002372DC /* RenderSVGInlineText.h */, A8F5C0B70F9285AC0098E06B /* RenderSVGModelObject.cpp */, A8F5C0B60F9285AC0098E06B /* RenderSVGModelObject.h */, + 08563BCF117865F50012B578 /* RenderSVGResource.cpp */, 083192A7112B43050083C3B9 /* RenderSVGResource.h */, 84BDA16911358D2A00DBF64C /* RenderSVGResourceClipper.cpp */, 84BDA16A11358D2A00DBF64C /* RenderSVGResourceClipper.h */, + 08082372117987C100241DE8 /* RenderSVGResourceContainer.h */, + 841FDC241178C9BE00F8AC9B /* RenderSVGResourceFilter.cpp */, + 841FDC251178C9BE00F8AC9B /* RenderSVGResourceFilter.h */, + 08C34AF11179C056002D7456 /* RenderSVGResourceGradient.cpp */, + 08C34AF21179C057002D7456 /* RenderSVGResourceGradient.h */, + 08C34AF31179C057002D7456 /* RenderSVGResourceLinearGradient.cpp */, + 08C34AF41179C057002D7456 /* RenderSVGResourceLinearGradient.h */, 8499A512115FB33000F566E3 /* RenderSVGResourceMarker.cpp */, 8499A513115FB33000F566E3 /* RenderSVGResourceMarker.h */, 083192A8112B43050083C3B9 /* RenderSVGResourceMasker.cpp */, 083192A9112B43050083C3B9 /* RenderSVGResourceMasker.h */, + 08563BB2117861770012B578 /* RenderSVGResourcePattern.cpp */, + 08563BB3117861770012B578 /* RenderSVGResourcePattern.h */, + 08C34AFB1179C072002D7456 /* RenderSVGResourceRadialGradient.cpp */, + 08C34AFC1179C072002D7456 /* RenderSVGResourceRadialGradient.h */, + 08C6A7A9117DFBAB00FEA1A2 /* RenderSVGResourceSolidColor.cpp */, + 08C6A7AA117DFBAB00FEA1A2 /* RenderSVGResourceSolidColor.h */, AA31B5B20C1DFD1000AE7083 /* RenderSVGRoot.cpp */, AA31B5B30C1DFD1000AE7083 /* RenderSVGRoot.h */, 08DAB9B81103D9A5003E7ABA /* RenderSVGShadowTreeRootContainer.cpp */, @@ -16034,6 +16098,8 @@ A8CFF5DA0A155A05000A4234 /* RootInlineBox.h */, 5D925B650F64D4DD00B847F0 /* ScrollBehavior.cpp */, 5D925B660F64D4DD00B847F0 /* ScrollBehavior.h */, + 0842BC701190144000C7D08F /* SVGCharacterData.cpp */, + 0842BC711190144000C7D08F /* SVGCharacterData.h */, B2B33A5D0B887CEF00C15984 /* SVGCharacterLayoutInfo.cpp */, B2B33A5E0B887CEF00C15984 /* SVGCharacterLayoutInfo.h */, 853CA9E20AEEC608002372DC /* SVGInlineFlowBox.cpp */, @@ -16051,6 +16117,7 @@ 853CA9E50AEEC608002372DC /* SVGRootInlineBox.h */, 08DAB9C01103D9C1003E7ABA /* SVGShadowTreeElements.cpp */, 08DAB9C11103D9C1003E7ABA /* SVGShadowTreeElements.h */, + 0842BC801190147200C7D08F /* SVGTextChunkLayoutInfo.h */, A8CFF04C0A154F09000A4234 /* TableLayout.h */, AB014DE10E689A4300E10445 /* TextControlInnerElements.cpp */, AB014DE20E689A4300E10445 /* TextControlInnerElements.h */, @@ -16285,6 +16352,7 @@ 5DB1BC6910715A6400EFAA49 /* TransformSourceLibxslt.cpp */, 854FE72C0A2297BE0058D7AD /* Traversal.cpp */, 854FE72D0A2297BE0058D7AD /* Traversal.h */, + 37FD4297118368460093C029 /* TreeDepthLimit.h */, 854FE72E0A2297BE0058D7AD /* TreeWalker.cpp */, 854FE72F0A2297BE0058D7AD /* TreeWalker.h */, 1A750D3C0A90DE35000FF215 /* TreeWalker.idl */, @@ -16338,8 +16406,12 @@ FA0B1F8311125CEE007F9839 /* RenderMathMLMath.h */, FA5FAE4011126A5D00D3750F /* RenderMathMLOperator.cpp */, FA5FAE4111126A5D00D3750F /* RenderMathMLOperator.h */, + 0FF2813211821CB6007B7CD6 /* RenderMathMLRoot.cpp */, + 0FF2813311821CB6007B7CD6 /* RenderMathMLRoot.h */, FA0B1F8411125CEE007F9839 /* RenderMathMLRow.cpp */, FA0B1F8511125CEE007F9839 /* RenderMathMLRow.h */, + 0FF2813411821CB6007B7CD6 /* RenderMathMLSquareRoot.cpp */, + 0FF2813511821CB6007B7CD6 /* RenderMathMLSquareRoot.h */, FAC12CC21120DA6900DACC36 /* RenderMathMLSubSup.cpp */, FAC12CC31120DA6900DACC36 /* RenderMathMLSubSup.h */, FA7EFB031120D25400CF79C7 /* RenderMathMLUnderOver.cpp */, @@ -16368,6 +16440,7 @@ 76CDD2F51103DA6600680521 /* AccessibilityMenuListPopup.h in Headers */, 29A812360FBB9C1D00510293 /* AccessibilityObject.h in Headers */, 29A812490FBB9CA900510293 /* AccessibilityObjectWrapper.h in Headers */, + A409C985116D0DDD007197BD /* AccessibilityProgressIndicator.h in Headers */, 29A812390FBB9C1D00510293 /* AccessibilityRenderObject.h in Headers */, 93C4F6EB1108F9A50099D0DB /* AccessibilityScrollbar.h in Headers */, 0709FC4E1025DEE30059CDBA /* AccessibilitySlider.h in Headers */, @@ -16567,12 +16640,14 @@ 93F1992F08245E59001E9ABC /* Cursor.h in Headers */, BC2272A20E82E87C00E7F975 /* CursorData.h in Headers */, BC2272AD0E82E8F300E7F975 /* CursorList.h in Headers */, + 62CD325A1157E57C0063B0A7 /* CustomEvent.h in Headers */, A8CB413E0E8633FD0032C4F0 /* DashArray.h in Headers */, A80E6D0B0A1989CA007FB8C5 /* DashboardRegion.h in Headers */, 5196116B0CAC56570010A80C /* Database.h in Headers */, 51A45B560CAD7FD7000D2BE9 /* DatabaseAuthorizer.h in Headers */, B5D3601A112F8B560048DEA8 /* DatabaseCallback.h in Headers */, 5116D9770CF177BD00C2B84D /* DatabaseDetails.h in Headers */, + B523CF0B1182675400EBB29C /* DatabaseSync.h in Headers */, 519611EA0CAC749C0010A80C /* DatabaseTask.h in Headers */, 519611780CAC56A80010A80C /* DatabaseThread.h in Headers */, 1AD51A140CB59CD300953D11 /* DatabaseTracker.h in Headers */, @@ -16599,6 +16674,7 @@ ED2BA83C09A24B91006C0AC4 /* DocumentMarker.h in Headers */, 0B90561A0F2578BF0095FF6A /* DocumentThreadableLoader.h in Headers */, A8185F3909765766005826D9 /* DocumentType.h in Headers */, + 973889A1116EA9DC00ADF313 /* DocumentWriter.h in Headers */, BC1A37AD097C715F0019F3D8 /* DOM.h in Headers */, 8538F0190AD718D8006A81D1 /* DOMAbstractView.h in Headers */, BC99812E0DBE807A008CE9EF /* DOMAbstractViewFrame.h in Headers */, @@ -16677,6 +16753,8 @@ 85C78A680ABDE1B40044FC16 /* DOMException.h in Headers */, BC1A37B5097C715F0019F3D8 /* DOMExtensions.h in Headers */, BC00F0040E0A185500FD04E3 /* DOMFile.h in Headers */, + 2E3BC108117D479800B9409A /* DOMFileError.h in Headers */, + 2E3BC10B117D47C800B9409A /* DOMFileErrorInternal.h in Headers */, BC00F0060E0A185500FD04E3 /* DOMFileInternal.h in Headers */, BC00F0070E0A185500FD04E3 /* DOMFileList.h in Headers */, BC00F0090E0A185500FD04E3 /* DOMFileListInternal.h in Headers */, @@ -16777,6 +16855,8 @@ 85E711C20AC5D5350053270F /* DOMHTMLParamElementInternal.h in Headers */, 85183B480AA6926100F19FA3 /* DOMHTMLPreElement.h in Headers */, 85E711C30AC5D5350053270F /* DOMHTMLPreElementInternal.h in Headers */, + A4226E951163D73A008B8397 /* DOMHTMLProgressElement.h in Headers */, + A4226E991163D7CC008B8397 /* DOMHTMLProgressElementInternal.h in Headers */, 85183B4A0AA6926100F19FA3 /* DOMHTMLQuoteElement.h in Headers */, 85E711C40AC5D5350053270F /* DOMHTMLQuoteElementInternal.h in Headers */, 85DF819B0AA77E4B00486AD7 /* DOMHTMLScriptElement.h in Headers */, @@ -16808,8 +16888,6 @@ BC1A37B9097C715F0019F3D8 /* DOMInternal.h in Headers */, 85FF315A0AAFBFCB00374F38 /* DOMKeyboardEvent.h in Headers */, 85989DCC0ACC8BBD00A0BC51 /* DOMKeyboardEventInternal.h in Headers */, - 0FF5025B102BA9010066F39A /* DOMMedia.h in Headers */, - 0FF50263102BA92C0066F39A /* DOMMediaInternal.h in Headers */, 850656FE0AAB4763002D15C0 /* DOMMediaList.h in Headers */, 85E711D10AC5D5350053270F /* DOMMediaListInternal.h in Headers */, 75793ED30D0CE85B007FC0AC /* DOMMessageEvent.h in Headers */, @@ -16851,6 +16929,8 @@ 855D358A0AD707310019AAC7 /* DOMRGBColor.h in Headers */, BCD0FC4F0DBD720B00B2F630 /* DOMRGBColorInternal.h in Headers */, BC5A86850C33676000EEA649 /* DOMSelection.h in Headers */, + 0FF5025B102BA9010066F39A /* DOMStyleMedia.h in Headers */, + 0FF50263102BA92C0066F39A /* DOMStyleMediaInternal.h in Headers */, 850657000AAB4763002D15C0 /* DOMStyleSheet.h in Headers */, 85B498FF0ADB348100925CBB /* DOMStyleSheetInternal.h in Headers */, 850657020AAB4763002D15C0 /* DOMStyleSheetList.h in Headers */, @@ -17354,6 +17434,7 @@ E415F1840D9A1A830033CE97 /* ElementTimeControl.h in Headers */, A8CFF6BE0A156118000A4234 /* EllipsisBox.h in Headers */, B25599A50D00D8BA00BB825C /* EmptyClients.h in Headers */, + 5DC87EF011716DF2001C0E6D /* EmptyProtocolDefinitions.h in Headers */, A8EA7EC20A1945D000A8EF5F /* Entity.h in Headers */, A8EA7EC00A1945D000A8EF5F /* EntityReference.h in Headers */, 2ECF7AE210162B5800427DE7 /* ErrorEvent.h in Headers */, @@ -17375,8 +17456,14 @@ 84801955108BAFB300CB2B1F /* FEGaussianBlur.h in Headers */, BCDBB8CD0E08958400C60FF6 /* File.h in Headers */, 066C772B0AB603B700238CC4 /* FileChooser.h in Headers */, + 2E3BC0BD117D3A4F00B9409A /* FileError.h in Headers */, BCDBB8AC0E088CA500C60FF6 /* FileList.h in Headers */, + 895253D8116C4C6800CABF00 /* FileStream.h in Headers */, + 895253D9116C4C6800CABF00 /* FileStreamClient.h in Headers */, + 895253DD116C4EF500CABF00 /* FileStreamProxy.h in Headers */, 514B3F730C722047000530DF /* FileSystem.h in Headers */, + 8952535311641B3400CABF00 /* FileThread.h in Headers */, + 895253DF116C4F0600CABF00 /* FileThreadTask.h in Headers */, BC5EB69F0E81DAEB00B25965 /* FillLayer.h in Headers */, 845E72F80FD261EE00A87D79 /* Filter.h in Headers */, 08C9251A0FCC7C4A00480DEC /* FilterEffect.h in Headers */, @@ -17436,6 +17523,7 @@ 59C77F2B10545B3B00506104 /* GeolocationServiceMock.h in Headers */, FE80D7C90E9C1F25000D6F75 /* Geoposition.h in Headers */, B2C3DA6C0D006CD600EF6F26 /* GlyphBuffer.h in Headers */, + C5D4AA7A116BAFB60069CA93 /* GlyphMetricsMap.h in Headers */, B2C3DA6E0D006CD600EF6F26 /* GlyphPageTreeNode.h in Headers */, BC53C5F50DA56B920021EB5D /* Gradient.h in Headers */, B22279640D00BF220071B782 /* GradientAttributes.h in Headers */, @@ -17526,6 +17614,7 @@ A871D4560A127CBC00B12A68 /* HTMLPlugInElement.h in Headers */, 4415292E0E1AE8A000C4A2D0 /* HTMLPlugInImageElement.h in Headers */, A8EA7CB00A192B9C00A8EF5F /* HTMLPreElement.h in Headers */, + A43BF5991149290A00C643CA /* HTMLProgressElement.h in Headers */, A8CFF7A30A156978000A4234 /* HTMLQuoteElement.h in Headers */, A871DC250A15205700B12A68 /* HTMLScriptElement.h in Headers */, A81369D8097374F600D74463 /* HTMLSelectElement.h in Headers */, @@ -17592,6 +17681,7 @@ 7A0E770F10C00A8800A0276E /* InspectorFrontendHost.h in Headers */, 41F062010F5F0B6600A07EAC /* InspectorResource.h in Headers */, 754133A8102E00E800075D00 /* InspectorTimelineAgent.h in Headers */, + F375CC071150D300008DDB81 /* InspectorWorkerResource.h in Headers */, B27535720B053814002CE64F /* IntPoint.h in Headers */, E462A4A1113E71BE004A4220 /* IntPointHash.h in Headers */, B27535740B053814002CE64F /* IntRect.h in Headers */, @@ -17644,16 +17734,12 @@ A8D05FAC0A23B30F005E7203 /* JSCSSValueList.h in Headers */, BC686C7D0E0C330100DE8A08 /* JSCSSVariablesDeclaration.h in Headers */, BC686C7F0E0C330100DE8A08 /* JSCSSVariablesRule.h in Headers */, + E4778B80115A581A00B5D372 /* JSCustomEvent.h in Headers */, FE80D7A80E9C1ED2000D6F75 /* JSCustomPositionCallback.h in Headers */, FE80D7AA0E9C1ED2000D6F75 /* JSCustomPositionErrorCallback.h in Headers */, - 51EC92640CE90DD400F90308 /* JSCustomSQLStatementCallback.h in Headers */, - 51EC92660CE90DD400F90308 /* JSCustomSQLStatementErrorCallback.h in Headers */, - 51EC92680CE90DD400F90308 /* JSCustomSQLTransactionCallback.h in Headers */, - 51EC926A0CE90DD400F90308 /* JSCustomSQLTransactionErrorCallback.h in Headers */, 1A3417C90CECFF250049CBDE /* JSCustomVoidCallback.h in Headers */, E10B937C0B73C00A003ED890 /* JSCustomXPathNSResolver.h in Headers */, 1AE82F900CAAFA9D002237AE /* JSDatabase.h in Headers */, - B5D3601D112F8BA00048DEA8 /* JSDatabaseCallback.h in Headers */, BC77D16A0FF19F560070887B /* JSDataGridColumn.h in Headers */, BC77D16C0FF19F560070887B /* JSDataGridColumnList.h in Headers */, BCBCAE3D0FF19399000762AE /* JSDataGridDataSource.h in Headers */, @@ -17686,6 +17772,7 @@ BC60901F0E91B8EC000C68B5 /* JSEventTarget.h in Headers */, 3314ACEC10892086000F0E56 /* JSExceptionBase.h in Headers */, BC00F0150E0A189500FD04E3 /* JSFile.h in Headers */, + 2E3BC0CB117D3E0800B9409A /* JSFileError.h in Headers */, BC00F0170E0A189500FD04E3 /* JSFileList.h in Headers */, FE80DA640E9C4703000D6F75 /* JSGeolocation.h in Headers */, FE80DA660E9C4703000D6F75 /* JSGeoposition.h in Headers */, @@ -17746,6 +17833,7 @@ 1AE2ABA70A1CE90500B42B25 /* JSHTMLParagraphElement.h in Headers */, 1AE2ABA90A1CE90500B42B25 /* JSHTMLParamElement.h in Headers */, 1AE2ABAB0A1CE90500B42B25 /* JSHTMLPreElement.h in Headers */, + A4226E5C1163D695008B8397 /* JSHTMLProgressElement.h in Headers */, 1AE2AEC80A1D297B00B42B25 /* JSHTMLQuoteElement.h in Headers */, 1AE2ABAD0A1CE90500B42B25 /* JSHTMLScriptElement.h in Headers */, E1E6EEA80B628DB3005F2F70 /* JSHTMLSelectElement.h in Headers */, @@ -17771,7 +17859,6 @@ A86629D309DA2B48009633A5 /* JSKeyboardEvent.h in Headers */, 935F45430F7C3B5F00D7C1FB /* JSLazyEventListener.h in Headers */, BCE1C43C0D9830D3003B02F2 /* JSLocation.h in Headers */, - 0FF5026A102BA9430066F39A /* JSMedia.h in Headers */, E44614190CD6826900FADA75 /* JSMediaError.h in Headers */, BC3C39B70C0D3D8D005F4D7A /* JSMediaList.h in Headers */, E107400E0E77BDC00033AF24 /* JSMessageChannel.h in Headers */, @@ -17785,6 +17872,7 @@ 65DF31FC09D1CC60000BE325 /* JSMutationEvent.h in Headers */, BCD9C2C10C17B69E005C90A2 /* JSNamedNodeMap.h in Headers */, A9D247F80D757E3400FDF959 /* JSNavigator.h in Headers */, + BC9439C3116CF4940048C750 /* JSNodeCustom.h in Headers */, 14115B7309F84CD600CA4FC1 /* JSNodeFilter.h in Headers */, BCB773620C17853D00132BA4 /* JSNodeFilterCondition.h in Headers */, 1A750D8E0A90E521000FF215 /* JSNodeIterator.h in Headers */, @@ -17807,6 +17895,8 @@ BCFE2F120C1B58380020235F /* JSRect.h in Headers */, BC74DA491013F468007987AD /* JSRGBColor.h in Headers */, BCEC01C30C274DDD009F4EC9 /* JSScreen.h in Headers */, + 9FA37EFB1172FDA600C4CD55 /* JSScriptProfile.h in Headers */, + 9FA37EFD1172FDA600C4CD55 /* JSScriptProfileNode.h in Headers */, 41D07A7F0FF935CA0095EDCE /* JSSharedWorker.h in Headers */, 415B7C630FF5A767006770F7 /* JSSharedWorkerConstructor.h in Headers */, 41D1690610238B66009BC827 /* JSSharedWorkerContext.h in Headers */, @@ -17815,6 +17905,7 @@ 1AFE119A0CBFFCC4003017FA /* JSSQLResultSetRowList.h in Headers */, BC82432A0D0CE8A200460C8F /* JSSQLTransaction.h in Headers */, 51E0BAEB0DA55D4A00A9E417 /* JSStorageEvent.h in Headers */, + 0FF5026A102BA9430066F39A /* JSStyleMedia.h in Headers */, BCE0139B0C0BEF180043860A /* JSStyleSheet.h in Headers */, A84EBD830CB8C97700079609 /* JSStyleSheetList.h in Headers */, B20111080AB7740500DB0E68 /* JSSVGAElement.h in Headers */, @@ -18020,6 +18111,8 @@ BCEFE1EB0DCA5F6400739219 /* JSXSLTProcessor.h in Headers */, BCE99EC40DCA624100182683 /* JSXSLTProcessorConstructor.h in Headers */, 85031B440A44EFC700F992E0 /* KeyboardEvent.h in Headers */, + A513B3D7114B1666001C429B /* KeyEventCocoa.h in Headers */, + A59E3C1E11580F510072928E /* KeyEventCodesIPhone.h in Headers */, 316FE11A0E6E1DA700BF6088 /* KeyframeAnimation.h in Headers */, BC5EBA110E823E4700B25965 /* KeyframeList.h in Headers */, 6593923809AE4346002C531F /* KURL.h in Headers */, @@ -18052,7 +18145,6 @@ FA654A6C1108ABED002615E0 /* MathMLTextElement.h in Headers */, 49D5DC2C0F423A73008F20FD /* Matrix3DTransformOperation.h in Headers */, 49E911C70EF86D47009D0CAF /* MatrixTransformOperation.h in Headers */, - 0FF50272102BA96A0066F39A /* Media.h in Headers */, 931BCC611124DFCB00BE70DD /* MediaCanStartListener.h in Headers */, ABFE7E130D32FAF60066F4D2 /* MediaControlElements.h in Headers */, AB40484E0E083FA8007D6920 /* MediaDocument.h in Headers */, @@ -18109,6 +18201,7 @@ 1A569D0F0D7E2B82007C3983 /* npruntime_impl.h in Headers */, 1A569D100D7E2B82007C3983 /* npruntime_internal.h in Headers */, 1A569D110D7E2B82007C3983 /* npruntime_priv.h in Headers */, + 1A27CF97118A354C0041D632 /* nptypes.h in Headers */, 1A569D120D7E2B82007C3983 /* objc_class.h in Headers */, 1A569D140D7E2B82007C3983 /* objc_header.h in Headers */, 1A569D150D7E2B82007C3983 /* objc_instance.h in Headers */, @@ -18209,8 +18302,10 @@ BCEA486E097D93020094C9E4 /* RenderFlexibleBox.h in Headers */, 853CA9ED0AEEC63C002372DC /* RenderForeignObject.h in Headers */, A871DED30A1530C700B12A68 /* RenderFrame.h in Headers */, + 0FD3080F117CF7E700A791F7 /* RenderFrameBase.h in Headers */, A871DED10A1530C700B12A68 /* RenderFrameSet.h in Headers */, BCEA486A097D93020094C9E4 /* RenderHTMLCanvas.h in Headers */, + 0FD308D6117D168500A791F7 /* RenderIFrame.h in Headers */, BCEA4876097D93020094C9E4 /* RenderImage.h in Headers */, BCB4F8900DB28DD60039139B /* RenderImageGeneratedContent.h in Headers */, BCEA4878097D93020094C9E4 /* RenderInline.h in Headers */, @@ -18223,9 +18318,12 @@ A8EA7A500A191A5200A8EF5F /* RenderListMarker.h in Headers */, 0F56028F0E4B76580065B038 /* RenderMarquee.h in Headers */, FA654A701108ABFF002615E0 /* RenderMathMLBlock.h in Headers */, + FAA10571114C2DF700940A01 /* RenderMathMLFraction.h in Headers */, FA0B1F8711125CEE007F9839 /* RenderMathMLMath.h in Headers */, FA5FAE4311126A5D00D3750F /* RenderMathMLOperator.h in Headers */, + 0FF2859111864053007B7CD6 /* RenderMathMLRoot.h in Headers */, FA0B1F8911125CEE007F9839 /* RenderMathMLRow.h in Headers */, + 0FF2859311864055007B7CD6 /* RenderMathMLSquareRoot.h in Headers */, FAC12CC51120DA6900DACC36 /* RenderMathMLSubSup.h in Headers */, FA7EFB061120D25400CF79C7 /* RenderMathMLUnderOver.h in Headers */, E4C279590CF9741900E97B98 /* RenderMedia.h in Headers */, @@ -18235,6 +18333,7 @@ BCFA930810333193007B25D1 /* RenderOverflow.h in Headers */, A871DED70A1530C700B12A68 /* RenderPart.h in Headers */, 853CA9F10AEEC657002372DC /* RenderPath.h in Headers */, + A43BF59D1149292800C643CA /* RenderProgress.h in Headers */, A871DFE30A15376B00B12A68 /* RenderReplaced.h in Headers */, BCA846D70DC67A350026C309 /* RenderReplica.h in Headers */, 1479FAEE109AE37500DED655 /* RenderRuby.h in Headers */, @@ -18258,8 +18357,15 @@ A8F5C0B80F9285AC0098E06B /* RenderSVGModelObject.h in Headers */, 083192AA112B43050083C3B9 /* RenderSVGResource.h in Headers */, 84BDA16C11358D2A00DBF64C /* RenderSVGResourceClipper.h in Headers */, + 08082373117987C100241DE8 /* RenderSVGResourceContainer.h in Headers */, 841FDC271178C9BE00F8AC9B /* RenderSVGResourceFilter.h in Headers */, + 08C34AF61179C057002D7456 /* RenderSVGResourceGradient.h in Headers */, + 08C34AF81179C057002D7456 /* RenderSVGResourceLinearGradient.h in Headers */, + 8499A515115FB33000F566E3 /* RenderSVGResourceMarker.h in Headers */, 083192AC112B43050083C3B9 /* RenderSVGResourceMasker.h in Headers */, + 08563BB5117861780012B578 /* RenderSVGResourcePattern.h in Headers */, + 08C34AFE1179C072002D7456 /* RenderSVGResourceRadialGradient.h in Headers */, + 08C6A7AC117DFBAB00FEA1A2 /* RenderSVGResourceSolidColor.h in Headers */, AA31B5B50C1DFD1000AE7083 /* RenderSVGRoot.h in Headers */, 08DAB9BB1103D9A5003E7ABA /* RenderSVGShadowTreeRootContainer.h in Headers */, 853CA9DF0AEEC5E9002372DC /* RenderSVGText.h in Headers */, @@ -18326,6 +18432,7 @@ 934CC1170EDCAC7300A658F2 /* ScriptInstance.h in Headers */, 41F066E40F64BCF600A07EAC /* ScriptObject.h in Headers */, 9F72304F11184B4100AD0126 /* ScriptProfile.h in Headers */, + 9FA37EE41172FC8000C4CD55 /* ScriptProfileNode.h in Headers */, 9F72305111184B4100AD0126 /* ScriptProfiler.h in Headers */, 934CC10A0EDB223900A658F2 /* ScriptSourceCode.h in Headers */, CE54FD381016D9A6008B44C8 /* ScriptSourceProvider.h in Headers */, @@ -18396,9 +18503,12 @@ B51BF6F1102C9E590002C15A /* SQLTransactionClient.h in Headers */, B5C1123C102B6C4600096578 /* SQLTransactionCoordinator.h in Headers */, 1A7CCB1C0CD9469A00B7B64E /* SQLTransactionErrorCallback.h in Headers */, + B523CF081182675400EBB29C /* SQLTransactionSync.h in Headers */, + B523CF061182675400EBB29C /* SQLTransactionSyncCallback.h in Headers */, 1A2E6E5A0CC55213004A2062 /* SQLValue.h in Headers */, 93F1996308245E59001E9ABC /* SSLKeyGenerator.h in Headers */, BC7FA62D0D1F0EFF00DB22A9 /* StaticNodeList.h in Headers */, + A5AFB350115151A700B045CB /* StepRange.h in Headers */, 51BE37E00DAEE00E001085FC /* StorageArea.h in Headers */, C5160EEB1004543A00A7CEE2 /* StorageAreaImpl.h in Headers */, C5102ECF0FD9EF8C00FAFF04 /* StorageAreaSync.h in Headers */, @@ -18428,6 +18538,7 @@ BC2273040E82F1E600E7F975 /* StyleInheritedData.h in Headers */, A80E73510A199C77007FB8C5 /* StyleList.h in Headers */, BC5EB72A0E81DE8100B25965 /* StyleMarqueeData.h in Headers */, + 0FF50272102BA96A0066F39A /* StyleMedia.h in Headers */, BC5EB74E0E81E06700B25965 /* StyleMultiColData.h in Headers */, BC2272E40E82EE9B00E7F975 /* StyleRareInheritedData.h in Headers */, BC2272BD0E82EAAE00E7F975 /* StyleRareNonInheritedData.h in Headers */, @@ -18442,6 +18553,7 @@ 659A7D130B6DB4D9001155B3 /* SubstituteData.h in Headers */, 1A8F6B020DB53006001DB794 /* SubstituteResource.h in Headers */, 93B2D8160F9920D2006AE6B2 /* SuddenTermination.h in Headers */, + 97C078501165D5BE003A32EF /* SuffixTree.h in Headers */, B22279740D00BF220071B782 /* SVGAElement.h in Headers */, 65653F2E0D9727D200CA9723 /* SVGAltGlyphElement.h in Headers */, B22279770D00BF220071B782 /* SVGAngle.h in Headers */, @@ -18456,6 +18568,7 @@ B22279930D00BF220071B782 /* SVGAnimateMotionElement.h in Headers */, B22279950D00BF220071B782 /* SVGAnimateTransformElement.h in Headers */, B22279980D00BF220071B782 /* SVGAnimationElement.h in Headers */, + 0842BC731190144000C7D08F /* SVGCharacterData.h in Headers */, B2B33A600B887CEF00C15984 /* SVGCharacterLayoutInfo.h in Headers */, B222799C0D00BF220071B782 /* SVGCircleElement.h in Headers */, B222799F0D00BF220071B782 /* SVGClipPathElement.h in Headers */, @@ -18551,12 +18664,6 @@ B2227A4E0D00BF220071B782 /* SVGMPathElement.h in Headers */, B2227A510D00BF220071B782 /* SVGNumberList.h in Headers */, B2227A540D00BF220071B782 /* SVGPaint.h in Headers */, - B25599A70D00D8BA00BB825C /* SVGPaintServer.h in Headers */, - B25599A90D00D8BA00BB825C /* SVGPaintServerGradient.h in Headers */, - B25599AB0D00D8BA00BB825C /* SVGPaintServerLinearGradient.h in Headers */, - B25599AD0D00D8BA00BB825C /* SVGPaintServerPattern.h in Headers */, - B25599AF0D00D8BA00BB825C /* SVGPaintServerRadialGradient.h in Headers */, - B25599B10D00D8BA00BB825C /* SVGPaintServerSolid.h in Headers */, B2227A570D00BF220071B782 /* SVGParserUtilities.h in Headers */, B2227A590D00BF220071B782 /* SVGPathElement.h in Headers */, B2227A5B0D00BF220071B782 /* SVGPathSeg.h in Headers */, @@ -18585,8 +18692,6 @@ BC22747B0E8366E200E7F975 /* SVGRenderStyleDefs.h in Headers */, A8F4FB940C169E7B002AFED5 /* SVGRenderSupport.h in Headers */, B2EBDC9D0AF77E3400AE4A68 /* SVGRenderTreeAsText.h in Headers */, - B25599B30D00D8BA00BB825C /* SVGResource.h in Headers */, - B25599B80D00D8BA00BB825C /* SVGResourceListener.h in Headers */, 853CA9E90AEEC608002372DC /* SVGRootInlineBox.h in Headers */, B2227AA30D00BF220071B782 /* SVGScriptElement.h in Headers */, B2227AA60D00BF220071B782 /* SVGSetElement.h in Headers */, @@ -18604,6 +18709,7 @@ B2227ABE0D00BF220071B782 /* SVGSwitchElement.h in Headers */, B2227AC10D00BF220071B782 /* SVGSymbolElement.h in Headers */, B2227AC50D00BF220071B782 /* SVGTests.h in Headers */, + 0842BC811190147200C7D08F /* SVGTextChunkLayoutInfo.h in Headers */, B2227AC80D00BF220071B782 /* SVGTextContentElement.h in Headers */, B2227ACB0D00BF220071B782 /* SVGTextElement.h in Headers */, B2227ACE0D00BF220071B782 /* SVGTextPathElement.h in Headers */, @@ -18672,6 +18778,7 @@ 0F500AAF0F54DB1B00EEF928 /* TransformState.h in Headers */, 49E911D20EF86D47009D0CAF /* TranslateTransformOperation.h in Headers */, 854FE7370A2297BE0058D7AD /* Traversal.h in Headers */, + 37FD4298118368460093C029 /* TreeDepthLimit.h in Headers */, 1419D2C50CEA6F6100FF507A /* TreeShared.h in Headers */, 854FE7390A2297BE0058D7AD /* TreeWalker.h in Headers */, 37C28A6810F659CC008C7813 /* TypesettingFeatures.h in Headers */, @@ -18683,11 +18790,14 @@ D086FE9809D53AAB005BC74D /* UnlinkCommand.h in Headers */, 656581B209D14EE6000E61D7 /* UserAgentStyleSheets.h in Headers */, BCACF3BD1072921A00C0C8A3 /* UserContentURLPattern.h in Headers */, + 2542F4DB1166C25A00E89A86 /* UserGestureIndicator.h in Headers */, BCA2B061105047600043BD1C /* UserScript.h in Headers */, BCA2B08B10505BCD0043BD1C /* UserScriptTypes.h in Headers */, BC8BF151105813BF00A40A07 /* UserStyleSheet.h in Headers */, BC8BF15A1058141800A40A07 /* UserStyleSheetTypes.h in Headers */, + 2E3BBF081162DA1100B9409A /* UUID.h in Headers */, 15C7708D100D3C6B005BA267 /* ValidityState.h in Headers */, + CEF418CF1179678C009D112C /* ViewportArguments.h in Headers */, 93309E1E099E64920056E581 /* visible_units.h in Headers */, 93309E20099E64920056E581 /* VisiblePosition.h in Headers */, A883DF280F3D045D00F19BF6 /* VisibleSelection.h in Headers */, @@ -18746,6 +18856,7 @@ 9380F47409A11AB4001FDB34 /* Widget.h in Headers */, 939B02EF0EA2DBC400C54570 /* WidthIterator.h in Headers */, BC8243E90D0CFD7500460C8F /* WindowFeatures.h in Headers */, + E1E1BF00115FF6FB006F52CA /* WindowsKeyboardCodes.h in Headers */, 08203AA00ED8C35300B8B61A /* WMLAccessElement.h in Headers */, 088C97520ECB6E28000534BA /* WMLAElement.h in Headers */, 080081970ED3B2DD00C53BC0 /* WMLAnchorElement.h in Headers */, @@ -18833,42 +18944,15 @@ 93F199EC08245E59001E9ABC /* XSLStyleSheet.h in Headers */, E1F1E8300C3C2BB9006DB391 /* XSLTExtensions.h in Headers */, 93F199ED08245E59001E9ABC /* XSLTProcessor.h in Headers */, + 82B658981189E39200E052A1 /* InspectorCSSStore.h in Headers */, E1BE512E0CF6C512002EA959 /* XSLTUnicodeSort.h in Headers */, 97DD4D870FDF4D6E00ECF9A4 /* XSSAuditor.h in Headers */, CE172E011136E8CE0062A533 /* ZoomMode.h in Headers */, - FAA10571114C2DF700940A01 /* RenderMathMLFraction.h in Headers */, - A43BF5991149290A00C643CA /* HTMLProgressElement.h in Headers */, - A43BF59D1149292800C643CA /* RenderProgress.h in Headers */, - F375CC071150D300008DDB81 /* InspectorWorkerResource.h in Headers */, - A5AFB350115151A700B045CB /* StepRange.h in Headers */, - A59E3C1E11580F510072928E /* KeyEventCodesIPhone.h in Headers */, - A513B3D7114B1666001C429B /* KeyEventCocoa.h in Headers */, - 62CD325A1157E57C0063B0A7 /* CustomEvent.h in Headers */, - E4778B80115A581A00B5D372 /* JSCustomEvent.h in Headers */, - E1E1BF00115FF6FB006F52CA /* WindowsKeyboardCodes.h in Headers */, - 8499A515115FB33000F566E3 /* RenderSVGResourceMarker.h in Headers */, - A4226E5C1163D695008B8397 /* JSHTMLProgressElement.h in Headers */, - A4226E951163D73A008B8397 /* DOMHTMLProgressElement.h in Headers */, - A4226E991163D7CC008B8397 /* DOMHTMLProgressElementInternal.h in Headers */, - 2E3BBF081162DA1100B9409A /* UUID.h in Headers */, - 8952535311641B3400CABF00 /* FileThread.h in Headers */, - 97C078501165D5BE003A32EF /* SuffixTree.h in Headers */, - 2542F4DB1166C25A00E89A86 /* UserGestureIndicator.h in Headers */, - BC9439C3116CF4940048C750 /* JSNodeCustom.h in Headers */, - C5D4AA7A116BAFB60069CA93 /* GlyphMetricsMap.h in Headers */, - A409C985116D0DDD007197BD /* AccessibilityProgressIndicator.h in Headers */, - 895253D8116C4C6800CABF00 /* FileStream.h in Headers */, - 973889A1116EA9DC00ADF313 /* DocumentWriter.h in Headers */, - 895253D9116C4C6800CABF00 /* FileStreamClient.h in Headers */, - 5DC87EF011716DF2001C0E6D /* EmptyProtocolDefinitions.h in Headers */, - 9FA37EE41172FC8000C4CD55 /* ScriptProfileNode.h in Headers */, - 9FA37EFB1172FDA600C4CD55 /* JSScriptProfile.h in Headers */, - 9FA37EFD1172FDA600C4CD55 /* JSScriptProfileNode.h in Headers */, - 895253DD116C4EF500CABF00 /* FileStreamProxy.h in Headers */, - 895253DF116C4F0600CABF00 /* FileThreadTask.h in Headers */, - CEF418CF1179678C009D112C /* ViewportArguments.h in Headers */, - 0FD3080F117CF7E700A791F7 /* RenderFrameBase.h in Headers */, - 0FD308D6117D168500A791F7 /* RenderIFrame.h in Headers */, + B59DD699119029E5007E9684 /* JSDatabaseCallback.h in Headers */, + B59DD69D11902A42007E9684 /* JSSQLTransactionCallback.h in Headers */, + B59DD6A111902A52007E9684 /* JSSQLTransactionErrorCallback.h in Headers */, + B59DD6A511902A62007E9684 /* JSSQLStatementCallback.h in Headers */, + B59DD6A911902A71007E9684 /* JSSQLStatementErrorCallback.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -19135,6 +19219,7 @@ 29A8123C0FBB9C1D00510293 /* AccessibilityObject.cpp in Sources */, 29A812480FBB9CA900510293 /* AccessibilityObjectMac.mm in Sources */, 29A8124A0FBB9CA900510293 /* AccessibilityObjectWrapper.mm in Sources */, + A409C984116D0DDD007197BD /* AccessibilityProgressIndicator.cpp in Sources */, 29A812260FBB9C1D00510293 /* AccessibilityRenderObject.cpp in Sources */, 93C4F6EA1108F9A50099D0DB /* AccessibilityScrollbar.cpp in Sources */, 0709FC4C1025DED80059CDBA /* AccessibilitySlider.cpp in Sources */, @@ -19300,8 +19385,10 @@ BCCBE69B0E06F51000EAFA8E /* CSSVariablesDeclaration.cpp in Sources */, BCCBE68B0E06E60D00EAFA8E /* CSSVariablesRule.cpp in Sources */, 93F19A2608245E59001E9ABC /* CursorMac.mm in Sources */, + 62CD32591157E57C0063B0A7 /* CustomEvent.cpp in Sources */, 5196116A0CAC56570010A80C /* Database.cpp in Sources */, 51A45B570CAD7FD7000D2BE9 /* DatabaseAuthorizer.cpp in Sources */, + B523CF0A1182675400EBB29C /* DatabaseSync.cpp in Sources */, 519611EB0CAC749C0010A80C /* DatabaseTask.cpp in Sources */, 5196116D0CAC56570010A80C /* DatabaseThread.cpp in Sources */, 1AD51A150CB59CD300953D11 /* DatabaseTracker.cpp in Sources */, @@ -19324,6 +19411,7 @@ 1C26497A0D7E248A00BD10F2 /* DocumentLoaderMac.cpp in Sources */, 0B9056190F2578BE0095FF6A /* DocumentThreadableLoader.cpp in Sources */, A8185F3A09765766005826D9 /* DocumentType.cpp in Sources */, + 973889A0116EA9DC00ADF313 /* DocumentWriter.cpp in Sources */, BC1A37AE097C715F0019F3D8 /* DOM.mm in Sources */, BCD0FBD00DBD625E00B2F630 /* DOMAbstractView.mm in Sources */, 1A8F6BC20DB55CDC001DB794 /* DOMApplicationCache.cpp in Sources */, @@ -19363,6 +19451,7 @@ 85AFA8230AAF528A00E84305 /* DOMEvent.mm in Sources */, BC1A37B3097C715F0019F3D8 /* DOMEvents.mm in Sources */, BC00F0050E0A185500FD04E3 /* DOMFile.mm in Sources */, + 2E3BC109117D479800B9409A /* DOMFileError.mm in Sources */, BC00F0080E0A185500FD04E3 /* DOMFileList.mm in Sources */, 2ED609BC1145B07100C8684E /* DOMFormData.cpp in Sources */, BC1A37B7097C715F0019F3D8 /* DOMHTML.mm in Sources */, @@ -19413,6 +19502,7 @@ 85183B470AA6926100F19FA3 /* DOMHTMLParagraphElement.mm in Sources */, 85ECBEF80AA7626900544F0B /* DOMHTMLParamElement.mm in Sources */, 85183B490AA6926100F19FA3 /* DOMHTMLPreElement.mm in Sources */, + A4226E961163D73A008B8397 /* DOMHTMLProgressElement.mm in Sources */, 85183B4B0AA6926100F19FA3 /* DOMHTMLQuoteElement.mm in Sources */, 85DF819C0AA77E4B00486AD7 /* DOMHTMLScriptElement.mm in Sources */, 85F32AF10AA63B8700FF3184 /* DOMHTMLSelectElement.mm in Sources */, @@ -19430,7 +19520,6 @@ 93C841FF09CE858300DFF5E5 /* DOMImplementationFront.cpp in Sources */, BC1A37BA097C715F0019F3D8 /* DOMInternal.mm in Sources */, 85FF315B0AAFBFCB00374F38 /* DOMKeyboardEvent.mm in Sources */, - 0FF5025C102BA9010066F39A /* DOMMedia.mm in Sources */, 850656FF0AAB4763002D15C0 /* DOMMediaList.mm in Sources */, 75793ED40D0CE85B007FC0AC /* DOMMessageEvent.mm in Sources */, E1ACAF4C0E791AAF0087D12B /* DOMMessagePort.mm in Sources */, @@ -19452,6 +19541,7 @@ 858C38A80AA8F20400B187A4 /* DOMRect.mm in Sources */, BCAEFCAE1016CE4A0040D34E /* DOMRGBColor.mm in Sources */, BC5A86840C33676000EEA649 /* DOMSelection.cpp in Sources */, + 0FF5025C102BA9010066F39A /* DOMStyleMedia.mm in Sources */, 850657010AAB4763002D15C0 /* DOMStyleSheet.mm in Sources */, 850657030AAB4763002D15C0 /* DOMStyleSheetList.mm in Sources */, 85ACEF7D0ACDCFCE001214FF /* DOMSVGAElement.mm in Sources */, @@ -19641,9 +19731,12 @@ 934FE9E50B5CA539003E4A73 /* FileChooser.cpp in Sources */, 066C772D0AB603D200238CC4 /* FileChooserMac.mm in Sources */, BCDBB8AD0E088CA500C60FF6 /* FileList.cpp in Sources */, + 895253D7116C4C6800CABF00 /* FileStream.cpp in Sources */, + 895253DC116C4EF500CABF00 /* FileStreamProxy.cpp in Sources */, 5160306C0CC4362300C8AC25 /* FileSystemCF.cpp in Sources */, 514B3F760C722055000530DF /* FileSystemMac.mm in Sources */, 5160300B0CC4251200C8AC25 /* FileSystemPOSIX.cpp in Sources */, + 8952535211641B3400CABF00 /* FileThread.cpp in Sources */, BC5EB69E0E81DAEB00B25965 /* FillLayer.cpp in Sources */, 08C925190FCC7C4A00480DEC /* FilterEffect.cpp in Sources */, A8CFF04D0A154F09000A4234 /* FixedTableLayout.cpp in Sources */, @@ -19784,6 +19877,7 @@ A871D4570A127CBC00B12A68 /* HTMLPlugInElement.cpp in Sources */, 4415292F0E1AE8A000C4A2D0 /* HTMLPlugInImageElement.cpp in Sources */, A8EA7CAD0A192B9C00A8EF5F /* HTMLPreElement.cpp in Sources */, + A43BF5981149290A00C643CA /* HTMLProgressElement.cpp in Sources */, A8CFF7A50A156978000A4234 /* HTMLQuoteElement.cpp in Sources */, A871DC220A15205700B12A68 /* HTMLScriptElement.cpp in Sources */, A81369D9097374F600D74463 /* HTMLSelectElement.cpp in Sources */, @@ -19864,7 +19958,6 @@ 59EE122C1106080500885116 /* JNIUtilityPrivate.cpp in Sources */, 93309DF3099E64920056E581 /* JoinTextNodesCommand.cpp in Sources */, 418F88040FF957AE0080F045 /* JSAbstractWorker.cpp in Sources */, - 415B7C570FF598E6006770F7 /* JSAbstractWorkerCustom.cpp in Sources */, 65DF31DA09D1C123000BE325 /* JSAttr.cpp in Sources */, BC2ED6BC0C6BD2F000920BFF /* JSAttrCustom.cpp in Sources */, E4EEFFC80D34550C00469A58 /* JSAudioConstructor.cpp in Sources */, @@ -19911,16 +20004,13 @@ A8D05FAB0A23B30F005E7203 /* JSCSSValueList.cpp in Sources */, BC686C7C0E0C330100DE8A08 /* JSCSSVariablesDeclaration.cpp in Sources */, BC686C7E0E0C330100DE8A08 /* JSCSSVariablesRule.cpp in Sources */, + E4778B7F115A581A00B5D372 /* JSCustomEvent.cpp in Sources */, FE80D7A70E9C1ED2000D6F75 /* JSCustomPositionCallback.cpp in Sources */, FE80D7A90E9C1ED2000D6F75 /* JSCustomPositionErrorCallback.cpp in Sources */, - 51EC92630CE90DD400F90308 /* JSCustomSQLStatementCallback.cpp in Sources */, 51EC92650CE90DD400F90308 /* JSCustomSQLStatementErrorCallback.cpp in Sources */, - 51EC92670CE90DD400F90308 /* JSCustomSQLTransactionCallback.cpp in Sources */, - 51EC92690CE90DD400F90308 /* JSCustomSQLTransactionErrorCallback.cpp in Sources */, 1A3417CA0CECFF250049CBDE /* JSCustomVoidCallback.cpp in Sources */, E10B93C30B73C291003ED890 /* JSCustomXPathNSResolver.cpp in Sources */, 1AE82F8F0CAAFA9D002237AE /* JSDatabase.cpp in Sources */, - B5D3601F112F8BA80048DEA8 /* JSDatabaseCallback.cpp in Sources */, BCCE58AC1061E8CF008FB35A /* JSDatabaseCustom.cpp in Sources */, BC77D1690FF19F560070887B /* JSDataGridColumn.cpp in Sources */, BC77D16B0FF19F560070887B /* JSDataGridColumnList.cpp in Sources */, @@ -19933,7 +20023,6 @@ 659DDC8209E198BA001BF3C6 /* JSDocument.cpp in Sources */, 49C7BA8D1042F5B10009D447 /* JSDocumentCustom.cpp in Sources */, 1A494EDE0A123F4C00FDAFC1 /* JSDocumentFragment.cpp in Sources */, - BCCE58AF1061E90C008FB35A /* JSDocumentFragmentCustom.cpp in Sources */, 65DF31F509D1CC60000BE325 /* JSDocumentType.cpp in Sources */, 1AC2260C0DB69F190089B669 /* JSDOMApplicationCache.cpp in Sources */, 1AC226170DB69F740089B669 /* JSDOMApplicationCacheCustom.cpp in Sources */, @@ -19961,10 +20050,10 @@ 93B70D6909EB0C7C009D8468 /* JSEventListener.cpp in Sources */, E0FEF372B47C53EAC1C1FBEE /* JSEventSource.cpp in Sources */, E0FEF372B77C53EAC1C1FBEE /* JSEventSourceConstructor.cpp in Sources */, - E0FEF372B57C53EAC1C1FBEE /* JSEventSourceCustom.cpp in Sources */, BC6090200E91B8EC000C68B5 /* JSEventTarget.cpp in Sources */, 3314ACEB10892086000F0E56 /* JSExceptionBase.cpp in Sources */, BC00F0140E0A189500FD04E3 /* JSFile.cpp in Sources */, + 2E3BC0CA117D3E0800B9409A /* JSFileError.cpp in Sources */, BC00F0160E0A189500FD04E3 /* JSFileList.cpp in Sources */, FE80DA630E9C4703000D6F75 /* JSGeolocation.cpp in Sources */, FE80D7AB0E9C1ED2000D6F75 /* JSGeolocationCustom.cpp in Sources */, @@ -20042,6 +20131,7 @@ 1AE2ABA60A1CE90500B42B25 /* JSHTMLParagraphElement.cpp in Sources */, 1AE2ABA80A1CE90500B42B25 /* JSHTMLParamElement.cpp in Sources */, 1AE2ABAA0A1CE90500B42B25 /* JSHTMLPreElement.cpp in Sources */, + A4226E5A1163D667008B8397 /* JSHTMLProgressElement.cpp in Sources */, 1AE2AEC70A1D297B00B42B25 /* JSHTMLQuoteElement.cpp in Sources */, 1AE2ABAC0A1CE90500B42B25 /* JSHTMLScriptElement.cpp in Sources */, E1E6EEA40B628DA8005F2F70 /* JSHTMLSelectElement.cpp in Sources */, @@ -20072,7 +20162,6 @@ 935F45420F7C3B5F00D7C1FB /* JSLazyEventListener.cpp in Sources */, BCE1C43B0D9830D3003B02F2 /* JSLocation.cpp in Sources */, BCE1C4400D9830F4003B02F2 /* JSLocationCustom.cpp in Sources */, - 0FF50269102BA9430066F39A /* JSMedia.cpp in Sources */, E44614180CD6826900FADA75 /* JSMediaError.cpp in Sources */, BC3C39B60C0D3D8D005F4D7A /* JSMediaList.cpp in Sources */, E107400D0E77BDC00033AF24 /* JSMessageChannel.cpp in Sources */, @@ -20121,6 +20210,9 @@ BCFE2F110C1B58370020235F /* JSRect.cpp in Sources */, BC74DA481013F468007987AD /* JSRGBColor.cpp in Sources */, BCEC01C20C274DDD009F4EC9 /* JSScreen.cpp in Sources */, + 9FA37EFA1172FDA600C4CD55 /* JSScriptProfile.cpp in Sources */, + 9FA37EFC1172FDA600C4CD55 /* JSScriptProfileNode.cpp in Sources */, + 9FA37EE71172FCF000C4CD55 /* JSScriptProfileNodeCustom.cpp in Sources */, 41D07A7E0FF935CA0095EDCE /* JSSharedWorker.cpp in Sources */, 415B7C580FF598E6006770F7 /* JSSharedWorkerConstructor.cpp in Sources */, 41D1690510238B66009BC827 /* JSSharedWorkerContext.cpp in Sources */, @@ -20134,6 +20226,7 @@ 51E3F9D60DA05E1D00250911 /* JSStorage.cpp in Sources */, 51D0C5160DAA90B7003B3831 /* JSStorageCustom.cpp in Sources */, 51E0BAEA0DA55D4A00A9E417 /* JSStorageEvent.cpp in Sources */, + 0FF50269102BA9430066F39A /* JSStyleMedia.cpp in Sources */, BCE0139A0C0BEF180043860A /* JSStyleSheet.cpp in Sources */, BC98A27D0C0C9950004BEBF7 /* JSStyleSheetCustom.cpp in Sources */, A84EBD840CB8C97700079609 /* JSStyleSheetList.cpp in Sources */, @@ -20360,6 +20453,8 @@ BCE99EC30DCA624100182683 /* JSXSLTProcessorConstructor.cpp in Sources */, BCEFE1E50DCA5F3300739219 /* JSXSLTProcessorCustom.cpp in Sources */, 85031B430A44EFC700F992E0 /* KeyboardEvent.cpp in Sources */, + A513B3D8114B166A001C429B /* KeyEventCocoa.mm in Sources */, + A59E3C1F11580F510072928E /* KeyEventIPhone.mm in Sources */, 935C477009AC4D7300A6AAB4 /* KeyEventMac.mm in Sources */, 316FE1190E6E1DA700BF6088 /* KeyframeAnimation.cpp in Sources */, BC5EBA100E823E4700B25965 /* KeyframeList.cpp in Sources */, @@ -20393,7 +20488,6 @@ FA654A6B1108ABED002615E0 /* MathMLTextElement.cpp in Sources */, 49D5DC2B0F423A73008F20FD /* Matrix3DTransformOperation.cpp in Sources */, 49E911C60EF86D47009D0CAF /* MatrixTransformOperation.cpp in Sources */, - 0FF50271102BA96A0066F39A /* Media.cpp in Sources */, ABFE7E120D32FAF60066F4D2 /* MediaControlElements.cpp in Sources */, AB40484D0E083FA8007D6920 /* MediaDocument.cpp in Sources */, 4E1959210A39DABA00220FE5 /* MediaFeatureNames.cpp in Sources */, @@ -20520,8 +20614,10 @@ BCEA486D097D93020094C9E4 /* RenderFlexibleBox.cpp in Sources */, 853CA9EC0AEEC63C002372DC /* RenderForeignObject.cpp in Sources */, A871DED40A1530C700B12A68 /* RenderFrame.cpp in Sources */, + 0FD3080E117CF7E700A791F7 /* RenderFrameBase.cpp in Sources */, A871DED20A1530C700B12A68 /* RenderFrameSet.cpp in Sources */, BCEA4869097D93020094C9E4 /* RenderHTMLCanvas.cpp in Sources */, + 0FD308D5117D168500A791F7 /* RenderIFrame.cpp in Sources */, BCEA4875097D93020094C9E4 /* RenderImage.cpp in Sources */, BCB4F8930DB28E530039139B /* RenderImageGeneratedContent.cpp in Sources */, BCEA4877097D93020094C9E4 /* RenderInline.cpp in Sources */, @@ -20534,9 +20630,12 @@ A8EA7A510A191A5200A8EF5F /* RenderListMarker.cpp in Sources */, 0F5602900E4B76580065B038 /* RenderMarquee.cpp in Sources */, FA654A6F1108ABFF002615E0 /* RenderMathMLBlock.cpp in Sources */, + FAA10570114C2DF700940A01 /* RenderMathMLFraction.cpp in Sources */, FA0B1F8611125CEE007F9839 /* RenderMathMLMath.cpp in Sources */, FA5FAE4211126A5D00D3750F /* RenderMathMLOperator.cpp in Sources */, + 0FF2859011864052007B7CD6 /* RenderMathMLRoot.cpp in Sources */, FA0B1F8811125CEE007F9839 /* RenderMathMLRow.cpp in Sources */, + 0FF2859211864054007B7CD6 /* RenderMathMLSquareRoot.cpp in Sources */, FAC12CC41120DA6900DACC36 /* RenderMathMLSubSup.cpp in Sources */, FA7EFB051120D25400CF79C7 /* RenderMathMLUnderOver.cpp in Sources */, E4C279580CF9741900E97B98 /* RenderMedia.cpp in Sources */, @@ -20545,6 +20644,7 @@ BC60EFB70F33A0E700812A93 /* RenderObjectChildList.cpp in Sources */, A871DED00A1530C700B12A68 /* RenderPart.cpp in Sources */, 853CA9F00AEEC657002372DC /* RenderPath.cpp in Sources */, + A43BF59C1149292800C643CA /* RenderProgress.cpp in Sources */, A871DFE20A15376B00B12A68 /* RenderReplaced.cpp in Sources */, BCA846D60DC67A350026C309 /* RenderReplica.cpp in Sources */, 1479FAED109AE37500DED655 /* RenderRuby.cpp in Sources */, @@ -20564,9 +20664,16 @@ 853CA9DA0AEEC5E9002372DC /* RenderSVGInline.cpp in Sources */, 853CA9DC0AEEC5E9002372DC /* RenderSVGInlineText.cpp in Sources */, A8F5C0B90F9285AC0098E06B /* RenderSVGModelObject.cpp in Sources */, + 08563BD0117865F50012B578 /* RenderSVGResource.cpp in Sources */, 84BDA16B11358D2A00DBF64C /* RenderSVGResourceClipper.cpp in Sources */, 841FDC261178C9BE00F8AC9B /* RenderSVGResourceFilter.cpp in Sources */, + 08C34AF51179C057002D7456 /* RenderSVGResourceGradient.cpp in Sources */, + 08C34AF71179C057002D7456 /* RenderSVGResourceLinearGradient.cpp in Sources */, + 8499A514115FB33000F566E3 /* RenderSVGResourceMarker.cpp in Sources */, 083192AB112B43050083C3B9 /* RenderSVGResourceMasker.cpp in Sources */, + 08563BB4117861780012B578 /* RenderSVGResourcePattern.cpp in Sources */, + 08C34AFD1179C072002D7456 /* RenderSVGResourceRadialGradient.cpp in Sources */, + 08C6A7AB117DFBAB00FEA1A2 /* RenderSVGResourceSolidColor.cpp in Sources */, AA31B5B40C1DFD1000AE7083 /* RenderSVGRoot.cpp in Sources */, 08DAB9BA1103D9A5003E7ABA /* RenderSVGShadowTreeRootContainer.cpp in Sources */, 853CA9DE0AEEC5E9002372DC /* RenderSVGText.cpp in Sources */, @@ -20664,6 +20771,8 @@ 41D168E710226E89009BC827 /* SharedWorkerContext.cpp in Sources */, 41D168ED10226E89009BC827 /* SharedWorkerThread.cpp in Sources */, B2C3DA640D006CD600EF6F26 /* SimpleFontData.cpp in Sources */, + 163E8B13118B3ADD00ED9231 /* SimpleFontDataATSUI.mm in Sources */, + 163E88F7118A39D200ED9231 /* SimpleFontDataCoreText.cpp in Sources */, B2AFFC7F0D00A5C10030074D /* SimpleFontDataMac.mm in Sources */, 49E911CC0EF86D47009D0CAF /* SkewTransformOperation.cpp in Sources */, 4B6FA6F50C39E48C00087011 /* SmartReplace.cpp in Sources */, @@ -20692,9 +20801,11 @@ 1ABFE7530CD968D000FE4834 /* SQLTransaction.cpp in Sources */, B51BF6F0102C9E590002C15A /* SQLTransactionClient.cpp in Sources */, B5C1123B102B6C4600096578 /* SQLTransactionCoordinator.cpp in Sources */, + B523CF091182675400EBB29C /* SQLTransactionSync.cpp in Sources */, 1A2E6E590CC55213004A2062 /* SQLValue.cpp in Sources */, 93F19AE608245E59001E9ABC /* SSLKeyGeneratorMac.mm in Sources */, BC7FA62E0D1F0EFF00DB22A9 /* StaticNodeList.cpp in Sources */, + A5AFB34F115151A700B045CB /* StepRange.cpp in Sources */, 51E3F9C70DA059DC00250911 /* Storage.cpp in Sources */, C5160EEA1004543A00A7CEE2 /* StorageAreaImpl.cpp in Sources */, C5102ED00FD9EF8C00FAFF04 /* StorageAreaSync.cpp in Sources */, @@ -20722,6 +20833,7 @@ BC2273030E82F1E600E7F975 /* StyleInheritedData.cpp in Sources */, A80E734D0A199C77007FB8C5 /* StyleList.cpp in Sources */, BC5EB7290E81DE8100B25965 /* StyleMarqueeData.cpp in Sources */, + 0FF50271102BA96A0066F39A /* StyleMedia.cpp in Sources */, BC5EB74D0E81E06700B25965 /* StyleMultiColData.cpp in Sources */, BC2272E30E82EE9B00E7F975 /* StyleRareInheritedData.cpp in Sources */, BC2272BC0E82EAAE00E7F975 /* StyleRareNonInheritedData.cpp in Sources */, @@ -20742,6 +20854,7 @@ B22279920D00BF220071B782 /* SVGAnimateMotionElement.cpp in Sources */, B22279940D00BF220071B782 /* SVGAnimateTransformElement.cpp in Sources */, B22279970D00BF220071B782 /* SVGAnimationElement.cpp in Sources */, + 0842BC721190144000C7D08F /* SVGCharacterData.cpp in Sources */, B2B33A5F0B887CEF00C15984 /* SVGCharacterLayoutInfo.cpp in Sources */, B222799B0D00BF220071B782 /* SVGCircleElement.cpp in Sources */, B222799E0D00BF220071B782 /* SVGClipPathElement.cpp in Sources */, @@ -20835,12 +20948,6 @@ A833C7CA0A2CF06B00D57664 /* SVGNames.cpp in Sources */, B2227A500D00BF220071B782 /* SVGNumberList.cpp in Sources */, B2227A530D00BF220071B782 /* SVGPaint.cpp in Sources */, - B25599A60D00D8BA00BB825C /* SVGPaintServer.cpp in Sources */, - B25599A80D00D8BA00BB825C /* SVGPaintServerGradient.cpp in Sources */, - B25599AA0D00D8BA00BB825C /* SVGPaintServerLinearGradient.cpp in Sources */, - B25599AC0D00D8BA00BB825C /* SVGPaintServerPattern.cpp in Sources */, - B25599AE0D00D8BA00BB825C /* SVGPaintServerRadialGradient.cpp in Sources */, - B25599B00D00D8BA00BB825C /* SVGPaintServerSolid.cpp in Sources */, B2227A560D00BF220071B782 /* SVGParserUtilities.cpp in Sources */, B2227A580D00BF220071B782 /* SVGPathElement.cpp in Sources */, B2227A5D0D00BF220071B782 /* SVGPathSegArc.cpp in Sources */, @@ -20866,7 +20973,6 @@ BC22747A0E8366E200E7F975 /* SVGRenderStyleDefs.cpp in Sources */, A8F4FB960C169E85002AFED5 /* SVGRenderSupport.cpp in Sources */, B2EBDC9C0AF77E3400AE4A68 /* SVGRenderTreeAsText.cpp in Sources */, - B25599B20D00D8BA00BB825C /* SVGResource.cpp in Sources */, 853CA9E80AEEC608002372DC /* SVGRootInlineBox.cpp in Sources */, B2227AA20D00BF220071B782 /* SVGScriptElement.cpp in Sources */, B2227AA50D00BF220071B782 /* SVGSetElement.cpp in Sources */, @@ -20946,7 +21052,10 @@ D086FE9909D53AAB005BC74D /* UnlinkCommand.cpp in Sources */, 65DF326109D1E199000BE325 /* UserAgentStyleSheetsData.cpp in Sources */, BCACF3BC1072921A00C0C8A3 /* UserContentURLPattern.cpp in Sources */, + 2542F4DA1166C25A00E89A86 /* UserGestureIndicator.cpp in Sources */, + 2E3BBF071162DA1100B9409A /* UUID.cpp in Sources */, 15C7708E100D3C6B005BA267 /* ValidityState.cpp in Sources */, + CEF418CE1179678C009D112C /* ViewportArguments.cpp in Sources */, 93309E1D099E64920056E581 /* visible_units.cpp in Sources */, 93309E1F099E64920056E581 /* VisiblePosition.cpp in Sources */, A883DF270F3D045D00F19BF6 /* VisibleSelection.cpp in Sources */, @@ -21049,8 +21158,8 @@ 93309E23099E64920056E581 /* WrapContentsInDummySpanCommand.cpp in Sources */, A833C7CC0A2CF07400D57664 /* XLinkNames.cpp in Sources */, BC772C460C4EB2C60083285F /* XMLHttpRequest.cpp in Sources */, - BCDFD48F0E305290009D10AD /* XMLHttpRequestUpload.cpp in Sources */, A136A00C1134DBD200CC8D50 /* XMLHttpRequestProgressEventThrottle.cpp in Sources */, + BCDFD48F0E305290009D10AD /* XMLHttpRequestUpload.cpp in Sources */, A833C80C0A2CF25600D57664 /* XMLNames.cpp in Sources */, E15A36D91104572700B7B639 /* XMLNSNames.cpp in Sources */, 1ACE53EA0A8D18E70022947D /* XMLSerializer.cpp in Sources */, @@ -21076,35 +21185,16 @@ 85217E020A5ECD4700DB8D00 /* XSLImportRule.cpp in Sources */, 93F19B0308245E59001E9ABC /* XSLStyleSheetLibxslt.cpp in Sources */, E1F1E82F0C3C2BB9006DB391 /* XSLTExtensions.cpp in Sources */, + 82B6589A1189E47600E052A1 /* InspectorCSSStore.cpp in Sources */, 93F19B0408245E59001E9ABC /* XSLTProcessor.cpp in Sources */, 93F19B0508245E59001E9ABC /* XSLTProcessorLibxslt.cpp in Sources */, E1BE512D0CF6C512002EA959 /* XSLTUnicodeSort.cpp in Sources */, 97DD4D860FDF4D6E00ECF9A4 /* XSSAuditor.cpp in Sources */, - FAA10570114C2DF700940A01 /* RenderMathMLFraction.cpp in Sources */, - A43BF5981149290A00C643CA /* HTMLProgressElement.cpp in Sources */, - A43BF59C1149292800C643CA /* RenderProgress.cpp in Sources */, - A5AFB34F115151A700B045CB /* StepRange.cpp in Sources */, - A59E3C1F11580F510072928E /* KeyEventIPhone.mm in Sources */, - A513B3D8114B166A001C429B /* KeyEventCocoa.mm in Sources */, - 62CD32591157E57C0063B0A7 /* CustomEvent.cpp in Sources */, - E4778B7F115A581A00B5D372 /* JSCustomEvent.cpp in Sources */, - 8499A514115FB33000F566E3 /* RenderSVGResourceMarker.cpp in Sources */, - A4226E5A1163D667008B8397 /* JSHTMLProgressElement.cpp in Sources */, - A4226E961163D73A008B8397 /* DOMHTMLProgressElement.mm in Sources */, - 2E3BBF071162DA1100B9409A /* UUID.cpp in Sources */, - 8952535211641B3400CABF00 /* FileThread.cpp in Sources */, - 2542F4DA1166C25A00E89A86 /* UserGestureIndicator.cpp in Sources */, - C5D4AA79116BAFB60069CA93 /* GlyphMetricsMap.cpp in Sources */, - A409C984116D0DDD007197BD /* AccessibilityProgressIndicator.cpp in Sources */, - 895253D7116C4C6800CABF00 /* FileStream.cpp in Sources */, - 9FA37EE71172FCF000C4CD55 /* JSScriptProfileNodeCustom.cpp in Sources */, - 9FA37EFA1172FDA600C4CD55 /* JSScriptProfile.cpp in Sources */, - 9FA37EFC1172FDA600C4CD55 /* JSScriptProfileNode.cpp in Sources */, - 895253DC116C4EF500CABF00 /* FileStreamProxy.cpp in Sources */, - CEF418CE1179678C009D112C /* ViewportArguments.cpp in Sources */, - 0FD3080E117CF7E700A791F7 /* RenderFrameBase.cpp in Sources */, - 0FD308D5117D168500A791F7 /* RenderIFrame.cpp in Sources */, - 973889A0116EA9DC00ADF313 /* DocumentWriter.cpp in Sources */, + B59DD69A119029E5007E9684 /* JSDatabaseCallback.cpp in Sources */, + B59DD69E11902A42007E9684 /* JSSQLTransactionCallback.cpp in Sources */, + B59DD6A211902A52007E9684 /* JSSQLTransactionErrorCallback.cpp in Sources */, + B59DD6A611902A62007E9684 /* JSSQLStatementCallback.cpp in Sources */, + B59DD6AA11902A71007E9684 /* JSSQLStatementErrorCallback.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/WebCore/accessibility/AccessibilityRenderObject.cpp b/WebCore/accessibility/AccessibilityRenderObject.cpp index 3463546..071bf5d 100644 --- a/WebCore/accessibility/AccessibilityRenderObject.cpp +++ b/WebCore/accessibility/AccessibilityRenderObject.cpp @@ -118,12 +118,72 @@ void AccessibilityRenderObject::detach() m_renderer = 0; } +static inline bool isInlineWithContinuation(RenderObject* renderer) +{ + if (!renderer->isRenderInline()) + return false; + + return toRenderInline(renderer)->continuation(); +} + +static inline RenderObject* firstChildInContinuation(RenderObject* renderer) +{ + RenderObject* r = toRenderInline(renderer)->continuation(); + + while (r) { + if (r->isRenderBlock()) + return r; + if (RenderObject* child = r->firstChild()) + return child; + r = toRenderInline(r)->continuation(); + } + + return 0; +} + +static inline RenderObject* firstChildConsideringContinuation(RenderObject* renderer) +{ + RenderObject* firstChild = renderer->firstChild(); + + if (!firstChild && isInlineWithContinuation(renderer)) + firstChild = firstChildInContinuation(renderer); + + return firstChild; +} + + +static inline RenderObject* lastChildConsideringContinuation(RenderObject* renderer) +{ + RenderObject* lastChild = renderer->lastChild(); + RenderObject* prev = renderer; + RenderObject* cur = renderer; + + if (!cur->isRenderInline() && !cur->isRenderBlock()) + return renderer; + + while (cur) { + prev = cur; + + if (RenderObject* lc = cur->lastChild()) + lastChild = lc; + + if (cur->isRenderInline()) { + cur = toRenderInline(cur)->inlineContinuation(); + ASSERT(cur || !toRenderInline(prev)->continuation()); + } else + cur = toRenderBlock(cur)->inlineContinuation(); + } + + return lastChild; +} + AccessibilityObject* AccessibilityRenderObject::firstChild() const { if (!m_renderer) return 0; - RenderObject* firstChild = m_renderer->firstChild(); + RenderObject* firstChild = firstChildConsideringContinuation(m_renderer); + if (!firstChild) return 0; @@ -134,32 +194,161 @@ AccessibilityObject* AccessibilityRenderObject::lastChild() const { if (!m_renderer) return 0; - - RenderObject* lastChild = m_renderer->lastChild(); + + RenderObject* lastChild = lastChildConsideringContinuation(m_renderer); + if (!lastChild) return 0; return m_renderer->document()->axObjectCache()->getOrCreate(lastChild); } +static inline RenderInline* startOfContinuations(RenderObject* r) +{ + if (r->isInlineContinuation()) + return toRenderInline(r->node()->renderer()); + + // Blocks with a previous continuation always have a next continuation + if (r->isRenderBlock() && toRenderBlock(r)->inlineContinuation()) + return toRenderInline(toRenderBlock(r)->inlineContinuation()->node()->renderer()); + + return 0; +} + +static inline RenderObject* endOfContinuations(RenderObject* renderer) +{ + RenderObject* prev = renderer; + RenderObject* cur = renderer; + + if (!cur->isRenderInline() && !cur->isRenderBlock()) + return renderer; + + while (cur) { + prev = cur; + if (cur->isRenderInline()) { + cur = toRenderInline(cur)->inlineContinuation(); + ASSERT(cur || !toRenderInline(prev)->continuation()); + } else + cur = toRenderBlock(cur)->inlineContinuation(); + } + + return prev; +} + + +static inline RenderObject* childBeforeConsideringContinuations(RenderInline* r, RenderObject* child) +{ + RenderBoxModelObject* curContainer = r; + RenderObject* cur = 0; + RenderObject* prev = 0; + + while (curContainer) { + if (curContainer->isRenderInline()) { + cur = curContainer->firstChild(); + while (cur) { + if (cur == child) + return prev; + prev = cur; + cur = cur->nextSibling(); + } + + curContainer = toRenderInline(curContainer)->continuation(); + } else if (curContainer->isRenderBlock()) { + if (curContainer == child) + return prev; + + prev = curContainer; + curContainer = toRenderBlock(curContainer)->inlineContinuation(); + } + } + + ASSERT_NOT_REACHED(); + + return 0; +} + +static inline bool firstChildIsInlineContinuation(RenderObject* renderer) +{ + return renderer->firstChild() && renderer->firstChild()->isInlineContinuation(); +} + AccessibilityObject* AccessibilityRenderObject::previousSibling() const { if (!m_renderer) return 0; - - RenderObject* previousSibling = m_renderer->previousSibling(); + + RenderObject* previousSibling = 0; + + // Case 1: The node is a block and is an inline's continuation. In that case, the inline's + // last child is our previous sibling (or further back in the continuation chain) + RenderInline* startOfConts; + if (m_renderer->isRenderBlock() && (startOfConts = startOfContinuations(m_renderer))) + previousSibling = childBeforeConsideringContinuations(startOfConts, m_renderer); + + // Case 2: Anonymous block parent of the end of a continuation - skip all the way to before + // the parent of the start, since everything in between will be linked up via the continuation. + else if (m_renderer->isAnonymousBlock() && firstChildIsInlineContinuation(m_renderer)) + previousSibling = startOfContinuations(m_renderer->firstChild())->parent()->previousSibling(); + + // Case 3: The node has an actual previous sibling + else if (RenderObject* ps = m_renderer->previousSibling()) + previousSibling = ps; + + // Case 4: This node has no previous siblings, but its parent is an inline, + // and is another node's inline continutation. Follow the continuation chain. + else if (m_renderer->parent()->isRenderInline() && (startOfConts = startOfContinuations(m_renderer->parent()))) + previousSibling = childBeforeConsideringContinuations(startOfConts, m_renderer->parent()->firstChild()); + if (!previousSibling) return 0; return m_renderer->document()->axObjectCache()->getOrCreate(previousSibling); } +static inline bool lastChildHasContinuation(RenderObject* renderer) +{ + return renderer->lastChild() && isInlineWithContinuation(renderer->lastChild()); +} + AccessibilityObject* AccessibilityRenderObject::nextSibling() const { if (!m_renderer) return 0; - - RenderObject* nextSibling = m_renderer->nextSibling(); + + RenderObject* nextSibling = 0; + + // Case 1: node is a block and has an inline continuation. Next sibling is the inline continuation's + // first child. + RenderInline* inlineContinuation; + if (m_renderer->isRenderBlock() && (inlineContinuation = toRenderBlock(m_renderer)->inlineContinuation())) + nextSibling = firstChildConsideringContinuation(inlineContinuation); + + // Case 2: Anonymous block parent of the start of a continuation - skip all the way to + // after the parent of the end, since everything in between will be linked up via the continuation. + else if (m_renderer->isAnonymousBlock() && lastChildHasContinuation(m_renderer)) + nextSibling = endOfContinuations(m_renderer->lastChild())->parent()->nextSibling(); + + // Case 3: node has an actual next sibling + else if (RenderObject* ns = m_renderer->nextSibling()) + nextSibling = ns; + + // Case 4: node is an inline with a continuation. Next sibling is the next sibling of the end + // of the continuation chain. + else if (isInlineWithContinuation(m_renderer)) + nextSibling = endOfContinuations(m_renderer)->nextSibling(); + + // Case 5: node has no next sibling, and its parent is an inline with a continuation. + else if (isInlineWithContinuation(m_renderer->parent())) { + RenderObject* continuation = toRenderInline(m_renderer->parent())->continuation(); + + // Case 4a: continuation is a block - in this case the block itself is the next sibling. + if (continuation->isRenderBlock()) + nextSibling = continuation; + // Case 4b: continuation is an inline - in this case the inline's first child is the next sibling + else + nextSibling = firstChildConsideringContinuation(continuation); + } + if (!nextSibling) return 0; @@ -170,8 +359,20 @@ AccessibilityObject* AccessibilityRenderObject::parentObjectIfExists() const { if (!m_renderer) return 0; - + RenderObject* parent = m_renderer->parent(); + + // Case 1: node is a block and is an inline's continuation. Parent + // is the start of the continuation chain. + RenderInline* startOfConts = 0; + if (m_renderer->isRenderBlock() && (startOfConts = startOfContinuations(m_renderer))) + parent = startOfConts; + + // Case 2: node's parent is an inline which is some node's continuation; parent is + // the earliest node in the continuation chain. + else if (parent && parent->isRenderInline() && (startOfConts = startOfContinuations(parent))) + parent = startOfConts; + if (!parent) return 0; @@ -184,6 +385,18 @@ AccessibilityObject* AccessibilityRenderObject::parentObject() const return 0; RenderObject* parent = m_renderer->parent(); + + // Case 1: node is a block and is an inline's continuation. Parent + // is the start of the continuation chain. + RenderInline* startOfConts = 0; + if (m_renderer->isRenderBlock() && (startOfConts = startOfContinuations(m_renderer))) + parent = startOfConts; + + // Case 2: node's parent is an inline which is some node's continuation; parent is + // the earliest node in the continuation chain. + else if (parent && parent->isRenderInline() && (startOfConts = startOfContinuations(parent))) + parent = startOfConts; + if (!parent) return 0; @@ -2800,7 +3013,16 @@ AccessibilityRole AccessibilityRenderObject::determineAccessibilityRole() if (node && node->hasTagName(tableTag)) return TableRole; -#endif +#endif + + // Table sections should be ignored. + if (m_renderer->isTableSection()) + return IgnoredRole; + +#if PLATFORM(GTK) + if (m_renderer->isHR()) + return SplitterRole; +#endif if (m_renderer->isBlockFlow() || (node && node->hasTagName(labelTag))) return GroupRole; diff --git a/WebCore/accessibility/gtk/AccessibilityObjectAtk.cpp b/WebCore/accessibility/gtk/AccessibilityObjectAtk.cpp index ca3e8cc..e32340a 100644 --- a/WebCore/accessibility/gtk/AccessibilityObjectAtk.cpp +++ b/WebCore/accessibility/gtk/AccessibilityObjectAtk.cpp @@ -38,8 +38,8 @@ AccessibilityObjectInclusion AccessibilityObject::accessibilityPlatformIncludesO if (!parent) return DefaultBehavior; - if (isMenuListPopup() || isMenuListOption()) - return IgnoreObject; + if (roleValue() == SplitterRole) + return IncludeObject; if (isGroup()) { // When a list item is made up entirely of children (e.g. paragraphs) diff --git a/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp b/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp index ffef2a8..d09877f 100644 --- a/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp +++ b/WebCore/accessibility/gtk/AccessibilityObjectWrapperAtk.cpp @@ -360,8 +360,10 @@ static AtkRole atkRole(AccessibilityRole role) return ATK_ROLE_TREE; case MenuBarRole: return ATK_ROLE_MENU_BAR; + case MenuListPopupRole: case MenuRole: return ATK_ROLE_MENU; + case MenuListOptionRole: case MenuItemRole: return ATK_ROLE_MENU_ITEM; case ColumnRole: @@ -379,6 +381,7 @@ static AtkRole atkRole(AccessibilityRole role) return ATK_ROLE_PROGRESS_BAR; case WindowRole: return ATK_ROLE_WINDOW; + case PopUpButtonRole: case ComboBoxRole: return ATK_ROLE_COMBO_BOX; case SplitGroupRole: diff --git a/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm b/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm index f13968d..97aaaf2 100644 --- a/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm +++ b/WebCore/accessibility/mac/AccessibilityObjectWrapper.mm @@ -59,7 +59,6 @@ #import "WebCoreViewFactory.h" #import "htmlediting.h" #import "visible_units.h" -#import <runtime/InitializeThreading.h> using namespace WebCore; using namespace HTMLNames; @@ -172,14 +171,6 @@ typedef unsigned NSUInteger; @implementation AccessibilityObjectWrapper -+ (void)initialize -{ - JSC::initializeThreading(); -#ifndef BUILDING_ON_TIGER - WebCoreObjCFinalizeOnMainThread(self); -#endif -} - - (id)initWithAccessibilityObject:(AccessibilityObject*)axObject { [super init]; diff --git a/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp b/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp index 6ba85da..a4cb57d 100644 --- a/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp +++ b/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp @@ -46,6 +46,7 @@ bool RuntimeEnabledFeatures::isGeolocationEnabled = true; bool RuntimeEnabledFeatures::isIndexedDBEnabled = false; bool RuntimeEnabledFeatures::isWebGLEnabled = false; bool RuntimeEnabledFeatures::isPushStateEnabled = false; +bool RuntimeEnabledFeatures::isTouchEnabled = false; #if ENABLE(VIDEO) diff --git a/WebCore/bindings/generic/RuntimeEnabledFeatures.h b/WebCore/bindings/generic/RuntimeEnabledFeatures.h index 37dceff..1534353 100644 --- a/WebCore/bindings/generic/RuntimeEnabledFeatures.h +++ b/WebCore/bindings/generic/RuntimeEnabledFeatures.h @@ -94,6 +94,15 @@ public: static bool pushStateEnabled() { return isPushStateEnabled; } static bool replaceStateEnabled() { return isPushStateEnabled; } +#if ENABLE(TOUCH_EVENTS) + static bool touchEnabled() { return isTouchEnabled; } + static void setTouchEnabled(bool isEnabled) { isTouchEnabled = isEnabled; } + static bool ontouchstartEnabled() { return isTouchEnabled; } + static bool ontouchmoveEnabled() { return isTouchEnabled; } + static bool ontouchendEnabled() { return isTouchEnabled; } + static bool ontouchcancelEnabled() { return isTouchEnabled; } +#endif + private: // Never instantiate. RuntimeEnabledFeatures() { } @@ -106,6 +115,7 @@ private: static bool isIndexedDBEnabled; static bool isWebGLEnabled; static bool isPushStateEnabled; + static bool isTouchEnabled; }; } // namespace WebCore diff --git a/WebCore/bindings/gobject/WebKitDOMBinding.cpp b/WebCore/bindings/gobject/WebKitDOMBinding.cpp index 1f900c3..b8fbdda 100644 --- a/WebCore/bindings/gobject/WebKitDOMBinding.cpp +++ b/WebCore/bindings/gobject/WebKitDOMBinding.cpp @@ -27,8 +27,10 @@ #include "Event.h" #include "EventException.h" #include "HTMLNames.h" +#include "WebKitDOMElementPrivate.h" #include "WebKitDOMNode.h" #include "WebKitDOMNodePrivate.h" +#include "WebKitHTMLElementWrapperFactory.h" namespace WebKit { @@ -66,11 +68,21 @@ void DOMObjectCache::forget(void* objectHandle) static gpointer createWrapper(Node* node) { ASSERT(node); + ASSERT(node->nodeType()); gpointer wrappedNode = 0; - if (node->nodeType()) + switch (node->nodeType()) { + case Node::ELEMENT_NODE: + if (node->isHTMLElement()) + wrappedNode = createHTMLElementWrapper(static_cast<HTMLElement*>(node)); + else + wrappedNode = wrapNode(node); + break; + default: wrappedNode = wrapNode(node); + break; + } return DOMObjectCache::put(node, wrappedNode); } @@ -87,4 +99,23 @@ gpointer kit(Node* node) return createWrapper(node); } +gpointer kit(Element* element) +{ + if (!element) + return 0; + + gpointer kitElement = DOMObjectCache::get(element); + if (kitElement) + return kitElement; + + gpointer wrappedElement; + + if (element->isHTMLElement()) + wrappedElement = createHTMLElementWrapper(static_cast<HTMLElement*>(element)); + else + wrappedElement = wrapElement(element); + + return DOMObjectCache::put(element, wrappedElement); +} + } // namespace WebKit diff --git a/WebCore/bindings/gobject/WebKitDOMBinding.h b/WebCore/bindings/gobject/WebKitDOMBinding.h index f6efa46..d27bdda 100644 --- a/WebCore/bindings/gobject/WebKitDOMBinding.h +++ b/WebCore/bindings/gobject/WebKitDOMBinding.h @@ -28,10 +28,12 @@ namespace WebCore { class Node; +class Element; } // namespace WebCore namespace WebKit { gpointer kit(WebCore::Node* node); +gpointer kit(WebCore::Element* element); class DOMObjectCache { public: diff --git a/WebCore/bindings/gobject/WebKitHTMLElementWrapperFactory.cpp b/WebCore/bindings/gobject/WebKitHTMLElementWrapperFactory.cpp new file mode 100644 index 0000000..1513b66 --- /dev/null +++ b/WebCore/bindings/gobject/WebKitHTMLElementWrapperFactory.cpp @@ -0,0 +1,526 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net> + * Copyright (C) 2008 Martin Soto <soto@freedesktop.org> + * Copyright (C) 2010 Igalia S.L. + * + * This file is derived by hand from an automatically generated file. + * Keeping it up-to-date could potentially be done by adding + * a make_names.pl generator, or by writing a separate + * generater which takes JSHTMLElementWrapperFactory.h as input. + * + * 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 "WebKitHTMLElementWrapperFactory.h" + +#include "HTMLAnchorElement.h" +#include "HTMLAppletElement.h" +#include "HTMLAreaElement.h" +#include "HTMLBRElement.h" +#include "HTMLBaseElement.h" +#include "HTMLBaseFontElement.h" +#include "HTMLBlockquoteElement.h" +#include "HTMLBodyElement.h" +#include "HTMLButtonElement.h" +#include "HTMLCanvasElement.h" +#include "HTMLDListElement.h" +#include "HTMLDirectoryElement.h" +#include "HTMLDivElement.h" +#include "HTMLEmbedElement.h" +#include "HTMLFieldSetElement.h" +#include "HTMLFontElement.h" +#include "HTMLFormElement.h" +#include "HTMLFrameElement.h" +#include "HTMLFrameSetElement.h" +#include "HTMLHRElement.h" +#include "HTMLHeadElement.h" +#include "HTMLHeadingElement.h" +#include "HTMLHtmlElement.h" +#include "HTMLIFrameElement.h" +#include "HTMLImageElement.h" +#include "HTMLInputElement.h" +#include "HTMLIsIndexElement.h" +#include "HTMLLIElement.h" +#include "HTMLLabelElement.h" +#include "HTMLLegendElement.h" +#include "HTMLLinkElement.h" +#include "HTMLMapElement.h" +#include "HTMLMarqueeElement.h" +#include "HTMLMenuElement.h" +#include "HTMLMetaElement.h" +#include "HTMLModElement.h" +#include "HTMLNames.h" +#include "HTMLOListElement.h" +#include "HTMLObjectElement.h" +#include "HTMLOptGroupElement.h" +#include "HTMLOptionElement.h" +#include "HTMLParagraphElement.h" +#include "HTMLParamElement.h" +#include "HTMLPreElement.h" +#include "HTMLQuoteElement.h" +#include "HTMLScriptElement.h" +#include "HTMLSelectElement.h" +#include "HTMLStyleElement.h" +#include "HTMLTableCaptionElement.h" +#include "HTMLTableCellElement.h" +#include "HTMLTableColElement.h" +#include "HTMLTableElement.h" +#include "HTMLTableRowElement.h" +#include "HTMLTableSectionElement.h" +#include "HTMLTextAreaElement.h" +#include "HTMLTitleElement.h" +#include "HTMLUListElement.h" + +#include "webkit/WebKitDOMHTMLAnchorElementPrivate.h" +#include "webkit/WebKitDOMHTMLAppletElementPrivate.h" +#include "webkit/WebKitDOMHTMLAreaElementPrivate.h" +#include "webkit/WebKitDOMHTMLBRElementPrivate.h" +#include "webkit/WebKitDOMHTMLBaseElementPrivate.h" +#include "webkit/WebKitDOMHTMLBaseFontElementPrivate.h" +#include "webkit/WebKitDOMHTMLBlockquoteElementPrivate.h" +#include "webkit/WebKitDOMHTMLBodyElementPrivate.h" +#include "webkit/WebKitDOMHTMLButtonElementPrivate.h" +#include "webkit/WebKitDOMHTMLCanvasElementPrivate.h" +#include "webkit/WebKitDOMHTMLDListElementPrivate.h" +#include "webkit/WebKitDOMHTMLDirectoryElementPrivate.h" +#include "webkit/WebKitDOMHTMLDivElementPrivate.h" +#include "webkit/WebKitDOMHTMLElementPrivate.h" +#include "webkit/WebKitDOMHTMLEmbedElementPrivate.h" +#include "webkit/WebKitDOMHTMLFieldSetElementPrivate.h" +#include "webkit/WebKitDOMHTMLFontElementPrivate.h" +#include "webkit/WebKitDOMHTMLFormElementPrivate.h" +#include "webkit/WebKitDOMHTMLFrameElementPrivate.h" +#include "webkit/WebKitDOMHTMLFrameSetElementPrivate.h" +#include "webkit/WebKitDOMHTMLHRElementPrivate.h" +#include "webkit/WebKitDOMHTMLHeadElementPrivate.h" +#include "webkit/WebKitDOMHTMLHeadingElementPrivate.h" +#include "webkit/WebKitDOMHTMLHtmlElementPrivate.h" +#include "webkit/WebKitDOMHTMLIFrameElementPrivate.h" +#include "webkit/WebKitDOMHTMLImageElementPrivate.h" +#include "webkit/WebKitDOMHTMLInputElementPrivate.h" +#include "webkit/WebKitDOMHTMLIsIndexElementPrivate.h" +#include "webkit/WebKitDOMHTMLLIElementPrivate.h" +#include "webkit/WebKitDOMHTMLLabelElementPrivate.h" +#include "webkit/WebKitDOMHTMLLegendElementPrivate.h" +#include "webkit/WebKitDOMHTMLLinkElementPrivate.h" +#include "webkit/WebKitDOMHTMLMapElementPrivate.h" +#include "webkit/WebKitDOMHTMLMarqueeElementPrivate.h" +#include "webkit/WebKitDOMHTMLMenuElementPrivate.h" +#include "webkit/WebKitDOMHTMLMetaElementPrivate.h" +#include "webkit/WebKitDOMHTMLModElementPrivate.h" +#include "webkit/WebKitDOMHTMLOListElementPrivate.h" +#include "webkit/WebKitDOMHTMLObjectElementPrivate.h" +#include "webkit/WebKitDOMHTMLOptGroupElementPrivate.h" +#include "webkit/WebKitDOMHTMLOptionElementPrivate.h" +#include "webkit/WebKitDOMHTMLParagraphElementPrivate.h" +#include "webkit/WebKitDOMHTMLParamElementPrivate.h" +#include "webkit/WebKitDOMHTMLPreElementPrivate.h" +#include "webkit/WebKitDOMHTMLQuoteElementPrivate.h" +#include "webkit/WebKitDOMHTMLScriptElementPrivate.h" +#include "webkit/WebKitDOMHTMLSelectElementPrivate.h" +#include "webkit/WebKitDOMHTMLStyleElementPrivate.h" +#include "webkit/WebKitDOMHTMLTableCaptionElementPrivate.h" +#include "webkit/WebKitDOMHTMLTableCellElementPrivate.h" +#include "webkit/WebKitDOMHTMLTableColElementPrivate.h" +#include "webkit/WebKitDOMHTMLTableElementPrivate.h" +#include "webkit/WebKitDOMHTMLTableRowElementPrivate.h" +#include "webkit/WebKitDOMHTMLTableSectionElementPrivate.h" +#include "webkit/WebKitDOMHTMLTextAreaElementPrivate.h" +#include "webkit/WebKitDOMHTMLTitleElementPrivate.h" +#include "webkit/WebKitDOMHTMLUListElementPrivate.h" +#include "webkit/webkitdom.h" + +#include <wtf/text/CString.h> + +namespace WebKit { + +using namespace WebCore; +using namespace WebCore::HTMLNames; + +typedef gpointer (*CreateHTMLElementWrapperFunction)(PassRefPtr<HTMLElement>); + +static gpointer createAnchorWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLAnchorElement(static_cast<HTMLAnchorElement*>(element.get())); +} + +static gpointer createAppletWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLAppletElement(static_cast<HTMLAppletElement*>(element.get())); +} + +static gpointer createAreaWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLAreaElement(static_cast<HTMLAreaElement*>(element.get())); +} + +static gpointer createBaseWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLBaseElement(static_cast<HTMLBaseElement*>(element.get())); +} + +static gpointer createBaseFontWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLBaseFontElement(static_cast<HTMLBaseFontElement*>(element.get())); +} + +static gpointer createBlockquoteWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLBlockquoteElement(static_cast<HTMLBlockquoteElement*>(element.get())); +} + +static gpointer createBodyWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLBodyElement(static_cast<HTMLBodyElement*>(element.get())); +} + +static gpointer createBRWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLBRElement(static_cast<HTMLBRElement*>(element.get())); +} + +static gpointer createButtonWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLButtonElement(static_cast<HTMLButtonElement*>(element.get())); +} + +static gpointer createCanvasWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLCanvasElement(static_cast<HTMLCanvasElement*>(element.get())); +} + +static gpointer createTableCaptionWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLTableCaptionElement(static_cast<HTMLTableCaptionElement*>(element.get())); +} + +static gpointer createTableColWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLTableColElement(static_cast<HTMLTableColElement*>(element.get())); +} + +static gpointer createModWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLModElement(static_cast<HTMLModElement*>(element.get())); +} + +static gpointer createDirectoryWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLDirectoryElement(static_cast<HTMLDirectoryElement*>(element.get())); +} + +static gpointer createDivWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLDivElement(static_cast<HTMLDivElement*>(element.get())); +} + +static gpointer createDListWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLDListElement(static_cast<HTMLDListElement*>(element.get())); +} + +static gpointer createEmbedWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLEmbedElement(static_cast<HTMLEmbedElement*>(element.get())); +} + +static gpointer createFieldSetWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLFieldSetElement(static_cast<HTMLFieldSetElement*>(element.get())); +} + +static gpointer createFontWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLFontElement(static_cast<HTMLFontElement*>(element.get())); +} + +static gpointer createFormWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLFormElement(static_cast<HTMLFormElement*>(element.get())); +} + +static gpointer createFrameWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLFrameElement(static_cast<HTMLFrameElement*>(element.get())); +} + +static gpointer createFrameSetWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLFrameSetElement(static_cast<HTMLFrameSetElement*>(element.get())); +} + +static gpointer createHeadingWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLHeadingElement(static_cast<HTMLHeadingElement*>(element.get())); +} + +static gpointer createHeadWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLHeadElement(static_cast<HTMLHeadElement*>(element.get())); +} + +static gpointer createHRWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLHRElement(static_cast<HTMLHRElement*>(element.get())); +} + +static gpointer createHtmlWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLHtmlElement(static_cast<HTMLHtmlElement*>(element.get())); +} + +static gpointer createIFrameWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLIFrameElement(static_cast<HTMLIFrameElement*>(element.get())); +} + +static gpointer createImageWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLImageElement(static_cast<HTMLImageElement*>(element.get())); +} + +static gpointer createInputWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLInputElement(static_cast<HTMLInputElement*>(element.get())); +} + +static gpointer createIsIndexWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLIsIndexElement(static_cast<HTMLIsIndexElement*>(element.get())); +} + +static gpointer createLabelWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLLabelElement(static_cast<HTMLLabelElement*>(element.get())); +} + +static gpointer createLegendWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLLegendElement(static_cast<HTMLLegendElement*>(element.get())); +} + +static gpointer createLIWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLLIElement(static_cast<HTMLLIElement*>(element.get())); +} + +static gpointer createLinkWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLLinkElement(static_cast<HTMLLinkElement*>(element.get())); +} + +static gpointer createMapWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLMapElement(static_cast<HTMLMapElement*>(element.get())); +} + +static gpointer createMarqueeWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLMarqueeElement(static_cast<HTMLMarqueeElement*>(element.get())); +} + +static gpointer createMenuWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLMenuElement(static_cast<HTMLMenuElement*>(element.get())); +} + +static gpointer createMetaWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLMetaElement(static_cast<HTMLMetaElement*>(element.get())); +} + +static gpointer createObjectWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLObjectElement(static_cast<HTMLObjectElement*>(element.get())); +} + +static gpointer createOListWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLOListElement(static_cast<HTMLOListElement*>(element.get())); +} + +static gpointer createOptGroupWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLOptGroupElement(static_cast<HTMLOptGroupElement*>(element.get())); +} + +static gpointer createOptionWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLOptionElement(static_cast<HTMLOptionElement*>(element.get())); +} + +static gpointer createParagraphWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLParagraphElement(static_cast<HTMLParagraphElement*>(element.get())); +} + +static gpointer createParamWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLParamElement(static_cast<HTMLParamElement*>(element.get())); +} + +static gpointer createPreWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLPreElement(static_cast<HTMLPreElement*>(element.get())); +} + +static gpointer createQuoteWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLQuoteElement(static_cast<HTMLQuoteElement*>(element.get())); +} + +static gpointer createScriptWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLScriptElement(static_cast<HTMLScriptElement*>(element.get())); +} + +static gpointer createSelectWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLSelectElement(static_cast<HTMLSelectElement*>(element.get())); +} + +static gpointer createStyleWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLStyleElement(static_cast<HTMLStyleElement*>(element.get())); +} + +static gpointer createTableWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLTableElement(static_cast<HTMLTableElement*>(element.get())); +} + +static gpointer createTableSectionWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLTableSectionElement(static_cast<HTMLTableSectionElement*>(element.get())); +} + +static gpointer createTableCellWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLTableCellElement(static_cast<HTMLTableCellElement*>(element.get())); +} + +static gpointer createTextAreaWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLTextAreaElement(static_cast<HTMLTextAreaElement*>(element.get())); +} + +static gpointer createTitleWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLTitleElement(static_cast<HTMLTitleElement*>(element.get())); +} + +static gpointer createTableRowWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLTableRowElement(static_cast<HTMLTableRowElement*>(element.get())); +} + +static gpointer createUListWrapper(PassRefPtr<HTMLElement> element) +{ + return wrapHTMLUListElement(static_cast<HTMLUListElement*>(element.get())); +} + +gpointer createHTMLElementWrapper(PassRefPtr<WebCore::HTMLElement> element) +{ + static HashMap<WebCore::AtomicStringImpl*, CreateHTMLElementWrapperFunction> map; + if (map.isEmpty()) { + map.set(aTag.localName().impl(), createAnchorWrapper); + map.set(appletTag.localName().impl(), createAppletWrapper); + map.set(areaTag.localName().impl(), createAreaWrapper); + map.set(baseTag.localName().impl(), createBaseWrapper); + map.set(basefontTag.localName().impl(), createBaseFontWrapper); + map.set(blockquoteTag.localName().impl(), createBlockquoteWrapper); + map.set(bodyTag.localName().impl(), createBodyWrapper); + map.set(brTag.localName().impl(), createBRWrapper); + map.set(buttonTag.localName().impl(), createButtonWrapper); + map.set(canvasTag.localName().impl(), createCanvasWrapper); + map.set(captionTag.localName().impl(), createTableCaptionWrapper); + map.set(colTag.localName().impl(), createTableColWrapper); + map.set(delTag.localName().impl(), createModWrapper); + map.set(dirTag.localName().impl(), createDirectoryWrapper); + map.set(divTag.localName().impl(), createDivWrapper); + map.set(dlTag.localName().impl(), createDListWrapper); + map.set(embedTag.localName().impl(), createEmbedWrapper); + map.set(fieldsetTag.localName().impl(), createFieldSetWrapper); + map.set(fontTag.localName().impl(), createFontWrapper); + map.set(formTag.localName().impl(), createFormWrapper); + map.set(frameTag.localName().impl(), createFrameWrapper); + map.set(framesetTag.localName().impl(), createFrameSetWrapper); + map.set(h1Tag.localName().impl(), createHeadingWrapper); + map.set(headTag.localName().impl(), createHeadWrapper); + map.set(hrTag.localName().impl(), createHRWrapper); + map.set(htmlTag.localName().impl(), createHtmlWrapper); + map.set(iframeTag.localName().impl(), createIFrameWrapper); + map.set(imgTag.localName().impl(), createImageWrapper); + map.set(inputTag.localName().impl(), createInputWrapper); + map.set(isindexTag.localName().impl(), createIsIndexWrapper); + map.set(labelTag.localName().impl(), createLabelWrapper); + map.set(legendTag.localName().impl(), createLegendWrapper); + map.set(liTag.localName().impl(), createLIWrapper); + map.set(linkTag.localName().impl(), createLinkWrapper); + map.set(mapTag.localName().impl(), createMapWrapper); + map.set(marqueeTag.localName().impl(), createMarqueeWrapper); + map.set(menuTag.localName().impl(), createMenuWrapper); + map.set(metaTag.localName().impl(), createMetaWrapper); + map.set(objectTag.localName().impl(), createObjectWrapper); + map.set(olTag.localName().impl(), createOListWrapper); + map.set(optgroupTag.localName().impl(), createOptGroupWrapper); + map.set(optionTag.localName().impl(), createOptionWrapper); + map.set(pTag.localName().impl(), createParagraphWrapper); + map.set(paramTag.localName().impl(), createParamWrapper); + map.set(preTag.localName().impl(), createPreWrapper); + map.set(qTag.localName().impl(), createQuoteWrapper); + map.set(scriptTag.localName().impl(), createScriptWrapper); + map.set(selectTag.localName().impl(), createSelectWrapper); + map.set(styleTag.localName().impl(), createStyleWrapper); + map.set(tableTag.localName().impl(), createTableWrapper); + map.set(tbodyTag.localName().impl(), createTableSectionWrapper); + map.set(tdTag.localName().impl(), createTableCellWrapper); + map.set(textareaTag.localName().impl(), createTextAreaWrapper); + map.set(titleTag.localName().impl(), createTitleWrapper); + map.set(trTag.localName().impl(), createTableRowWrapper); + map.set(ulTag.localName().impl(), createUListWrapper); + map.set(colgroupTag.localName().impl(), createTableColWrapper); + map.set(h2Tag.localName().impl(), createHeadingWrapper); + map.set(h3Tag.localName().impl(), createHeadingWrapper); + map.set(h4Tag.localName().impl(), createHeadingWrapper); + map.set(h5Tag.localName().impl(), createHeadingWrapper); + map.set(h6Tag.localName().impl(), createHeadingWrapper); + map.set(imageTag.localName().impl(), createImageWrapper); + map.set(insTag.localName().impl(), createModWrapper); + map.set(keygenTag.localName().impl(), createSelectWrapper); + map.set(listingTag.localName().impl(), createPreWrapper); + map.set(tfootTag.localName().impl(), createTableSectionWrapper); + map.set(thTag.localName().impl(), createTableCellWrapper); + map.set(theadTag.localName().impl(), createTableSectionWrapper); + map.set(xmpTag.localName().impl(), createPreWrapper); + } + + CreateHTMLElementWrapperFunction createWrapperFunction = + map.get(element->localName().impl()); + if (createWrapperFunction) + return createWrapperFunction(element); + return wrapHTMLElement(element.get()); +} + +} diff --git a/WebCore/bindings/gobject/WebKitHTMLElementWrapperFactory.h b/WebCore/bindings/gobject/WebKitHTMLElementWrapperFactory.h new file mode 100644 index 0000000..2677891 --- /dev/null +++ b/WebCore/bindings/gobject/WebKitHTMLElementWrapperFactory.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2010 Igalia S.L. + * + * 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 WebKitHTMLElementWrapperFactory_h +#define WebKitHTMLElementWrapperFactory_h + +#include "HTMLElement.h" +#include "glib-object.h" + +#include <wtf/Forward.h> + +namespace WebCore { +class HTMLElement; +} + +namespace WebKit { +gpointer createHTMLElementWrapper(PassRefPtr<WebCore::HTMLElement>); +} + +#endif // WebKitHTMLElementWrapperFactory_h diff --git a/WebCore/bindings/js/JSAbstractWorkerCustom.cpp b/WebCore/bindings/js/JSAbstractWorkerCustom.cpp deleted file mode 100644 index 1f843f9..0000000 --- a/WebCore/bindings/js/JSAbstractWorkerCustom.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2009 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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" - -#if ENABLE(WORKERS) - -#include "JSAbstractWorker.h" - -#include "AbstractWorker.h" -#include "JSDOMGlobalObject.h" -#include "JSEventListener.h" -#include "JSEventTarget.h" - -using namespace JSC; - -namespace WebCore { - -JSValue JSAbstractWorker::addEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - -JSValue JSAbstractWorker::removeEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - -} // namespace WebCore - -#endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/js/JSBindingsAllInOne.cpp b/WebCore/bindings/js/JSBindingsAllInOne.cpp index 2e05350..e275397 100644 --- a/WebCore/bindings/js/JSBindingsAllInOne.cpp +++ b/WebCore/bindings/js/JSBindingsAllInOne.cpp @@ -26,7 +26,6 @@ // This all-in-one cpp file cuts down on template bloat to allow us to build our Windows release build. #include "GCController.cpp" -#include "JSAbstractWorkerCustom.cpp" #include "JSAttrCustom.cpp" #include "JSAudioConstructor.cpp" #include "JSCDATASectionCustom.cpp" @@ -40,10 +39,7 @@ #include "JSClipboardCustom.cpp" #include "JSConsoleCustom.cpp" #include "JSCoordinatesCustom.cpp" -#include "JSCustomSQLStatementCallback.cpp" #include "JSCustomSQLStatementErrorCallback.cpp" -#include "JSCustomSQLTransactionCallback.cpp" -#include "JSCustomSQLTransactionErrorCallback.cpp" #include "JSCustomVoidCallback.cpp" #include "JSCustomXPathNSResolver.cpp" #include "JSDOMApplicationCacheCustom.cpp" @@ -58,12 +54,10 @@ #include "JSDedicatedWorkerContextCustom.cpp" #include "JSDesktopNotificationsCustom.cpp" #include "JSDocumentCustom.cpp" -#include "JSDocumentFragmentCustom.cpp" #include "JSElementCustom.cpp" #include "JSEventCustom.cpp" #include "JSEventListener.cpp" #include "JSEventSourceConstructor.cpp" -#include "JSEventSourceCustom.cpp" #include "JSEventTarget.cpp" #include "JSExceptionBase.cpp" #include "JSHTMLAllCollectionCustom.cpp" diff --git a/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp b/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp deleted file mode 100644 index 46a7ae5..0000000 --- a/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp +++ /dev/null @@ -1,81 +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. - */ - -#include "config.h" -#include "JSCustomSQLStatementCallback.h" - -#if ENABLE(DATABASE) - -#include "Frame.h" -#include "JSSQLResultSet.h" -#include "JSSQLTransaction.h" -#include "ScriptExecutionContext.h" -#include <runtime/JSLock.h> -#include <wtf/MainThread.h> - -namespace WebCore { - -using namespace JSC; - -JSCustomSQLStatementCallback::JSCustomSQLStatementCallback(JSObject* callback, JSDOMGlobalObject* globalObject) - : m_data(new JSCallbackData(callback, globalObject)) - , m_isolatedWorld(globalObject->world()) -{ -} - -JSCustomSQLStatementCallback::~JSCustomSQLStatementCallback() -{ - callOnMainThread(JSCallbackData::deleteData, m_data); -#ifndef NDEBUG - m_data = 0; -#endif -} - -void JSCustomSQLStatementCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, SQLResultSet* resultSet, bool& raisedException) -{ - ASSERT(m_data); - ASSERT(context); - - RefPtr<JSCustomSQLStatementCallback> protect(this); - - JSC::JSLock lock(SilenceAssertionsOnly); - JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get()); - if (!globalObject) - return; - - ExecState* exec = globalObject->globalExec(); - MarkedArgumentBuffer args; - args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), transaction)); - args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), resultSet)); - - m_data->invokeCallback(args, &raisedException); -} - -} - -#endif // ENABLE(DATABASE) diff --git a/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp b/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp index a2ba52a..3026a33 100644 --- a/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp +++ b/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp @@ -27,42 +27,26 @@ */ #include "config.h" -#include "JSCustomSQLStatementErrorCallback.h" +#include "JSSQLStatementErrorCallback.h" #if ENABLE(DATABASE) #include "Frame.h" -#include "JSCallbackData.h" #include "JSSQLError.h" #include "JSSQLTransaction.h" #include "ScriptExecutionContext.h" #include <runtime/JSLock.h> -#include <wtf/MainThread.h> namespace WebCore { using namespace JSC; -JSCustomSQLStatementErrorCallback::JSCustomSQLStatementErrorCallback(JSObject* callback, JSDOMGlobalObject* globalObject) - : m_data(new JSCallbackData(callback, globalObject)) - , m_isolatedWorld(globalObject->world()) -{ -} - -JSCustomSQLStatementErrorCallback::~JSCustomSQLStatementErrorCallback() -{ - callOnMainThread(JSCallbackData::deleteData, m_data); -#ifndef NDEBUG - m_data = 0; -#endif -} - -bool JSCustomSQLStatementErrorCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, SQLError* error) +bool JSSQLStatementErrorCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, SQLError* error) { ASSERT(m_data); ASSERT(context); - RefPtr<JSCustomSQLStatementErrorCallback> protect(this); + RefPtr<JSSQLStatementErrorCallback> protect(this); JSC::JSLock lock(SilenceAssertionsOnly); JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get()); diff --git a/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp b/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp deleted file mode 100644 index d5e9754..0000000 --- a/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 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. - */ - -#include "config.h" -#include "JSCustomSQLTransactionCallback.h" - -#if ENABLE(DATABASE) - -#include "Frame.h" -#include "JSCallbackData.h" -#include "JSSQLTransaction.h" -#include "ScriptExecutionContext.h" -#include <runtime/JSLock.h> -#include <wtf/MainThread.h> -#include <wtf/RefCountedLeakCounter.h> - -namespace WebCore { - -using namespace JSC; - -#ifndef NDEBUG -static WTF::RefCountedLeakCounter counter("JSCustomSQLTransactionCallback"); -#endif - -JSCustomSQLTransactionCallback::JSCustomSQLTransactionCallback(JSObject* callback, JSDOMGlobalObject* globalObject) - : m_data(new JSCallbackData(callback, globalObject)) - , m_isolatedWorld(globalObject->world()) -{ -#ifndef NDEBUG - counter.increment(); -#endif -} - -JSCustomSQLTransactionCallback::~JSCustomSQLTransactionCallback() -{ - callOnMainThread(JSCallbackData::deleteData, m_data); -#ifndef NDEBUG - m_data = 0; - counter.decrement(); -#endif -} - -void JSCustomSQLTransactionCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, bool& raisedException) -{ - ASSERT(m_data); - ASSERT(context); - - RefPtr<JSCustomSQLTransactionCallback> protect(this); - - JSC::JSLock lock(SilenceAssertionsOnly); - JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get()); - if (!globalObject) - return; - - ExecState* exec = globalObject->globalExec(); - MarkedArgumentBuffer args; - args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), transaction)); - m_data->invokeCallback(args, &raisedException); -} - -} - -#endif // ENABLE(DATABASE) diff --git a/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp b/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp index 6198d6e..b1f82a8 100644 --- a/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp +++ b/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp @@ -85,26 +85,6 @@ JSValue JSDOMApplicationCache::remove(ExecState* exec, const ArgList& args) #endif // ENABLE(APPLICATION_CACHE_DYNAMIC_ENTRIES) -JSValue JSDOMApplicationCache::addEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - -JSValue JSDOMApplicationCache::removeEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - } // namespace WebCore #endif // ENABLE(OFFLINE_WEB_APPLICATIONS) diff --git a/WebCore/bindings/js/JSDOMWindowCustom.cpp b/WebCore/bindings/js/JSDOMWindowCustom.cpp index f5f2ae2..05ea9b1 100644 --- a/WebCore/bindings/js/JSDOMWindowCustom.cpp +++ b/WebCore/bindings/js/JSDOMWindowCustom.cpp @@ -36,8 +36,10 @@ #include "HTMLDocument.h" #include "History.h" #include "JSAudioConstructor.h" +#if ENABLE(DATABASE) #include "JSDatabase.h" #include "JSDatabaseCallback.h" +#endif #include "JSDOMWindowShell.h" #include "JSEvent.h" #include "JSEventListener.h" diff --git a/WebCore/bindings/js/JSDatabaseCallback.cpp b/WebCore/bindings/js/JSDatabaseCallback.cpp deleted file mode 100644 index 6887c86..0000000 --- a/WebCore/bindings/js/JSDatabaseCallback.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2010 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 "JSDatabaseCallback.h" - -#if ENABLE(DATABASE) - -#include "Frame.h" -#include "JSDatabase.h" -#include "ScriptExecutionContext.h" -#include <runtime/JSLock.h> -#include <wtf/MainThread.h> - -namespace WebCore { - -using namespace JSC; - -JSDatabaseCallback::JSDatabaseCallback(JSObject* callback, JSDOMGlobalObject* globalObject) - : m_data(new JSCallbackData(callback, globalObject)) - , m_isolatedWorld(globalObject->world()) -{ -} - -JSDatabaseCallback::~JSDatabaseCallback() -{ - callOnMainThread(JSCallbackData::deleteData, m_data); -#ifndef NDEBUG - m_data = 0; -#endif -} - -void JSDatabaseCallback::handleEvent(ScriptExecutionContext* context, Database* database) -{ - ASSERT(m_data); - ASSERT(context); - - RefPtr<JSDatabaseCallback> protect(this); - - JSC::JSLock lock(SilenceAssertionsOnly); - - JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get()); - if (!globalObject) - return; - - ExecState* exec = globalObject->globalExec(); - MarkedArgumentBuffer args; - args.append(toJS(exec, database)); - - bool ignored; - m_data->invokeCallback(args, &ignored); -} - -} - -#endif // ENABLE(DATABASE) diff --git a/WebCore/bindings/js/JSDatabaseCustom.cpp b/WebCore/bindings/js/JSDatabaseCustom.cpp index 50f1d17..ccc5c0d 100644 --- a/WebCore/bindings/js/JSDatabaseCustom.cpp +++ b/WebCore/bindings/js/JSDatabaseCustom.cpp @@ -35,8 +35,8 @@ #include "Database.h" #include "Document.h" #include "ExceptionCode.h" -#include "JSCustomSQLTransactionCallback.h" -#include "JSCustomSQLTransactionErrorCallback.h" +#include "JSSQLTransactionCallback.h" +#include "JSSQLTransactionErrorCallback.h" #include "JSCustomVoidCallback.h" #include "JSDOMWindowCustom.h" #include "PlatformString.h" @@ -58,7 +58,7 @@ JSValue JSDatabase::changeVersion(ExecState* exec, const ArgList& args) return jsUndefined(); } - RefPtr<SQLTransactionCallback> callback(JSCustomSQLTransactionCallback::create(object, static_cast<JSDOMGlobalObject*>(exec->dynamicGlobalObject()))); + RefPtr<SQLTransactionCallback> callback(JSSQLTransactionCallback::create(object, static_cast<JSDOMGlobalObject*>(exec->dynamicGlobalObject()))); RefPtr<SQLTransactionErrorCallback> errorCallback; if (!args.at(3).isNull()) { @@ -67,7 +67,7 @@ JSValue JSDatabase::changeVersion(ExecState* exec, const ArgList& args) return jsUndefined(); } - errorCallback = JSCustomSQLTransactionErrorCallback::create(object, static_cast<JSDOMGlobalObject*>(exec->dynamicGlobalObject())); + errorCallback = JSSQLTransactionErrorCallback::create(object, static_cast<JSDOMGlobalObject*>(exec->dynamicGlobalObject())); } RefPtr<VoidCallback> successCallback; @@ -94,16 +94,15 @@ static JSValue createTransaction(ExecState* exec, const ArgList& args, Database* return jsUndefined(); } - RefPtr<SQLTransactionCallback> callback(JSCustomSQLTransactionCallback::create(object, globalObject)); + RefPtr<SQLTransactionCallback> callback(JSSQLTransactionCallback::create(object, globalObject)); RefPtr<SQLTransactionErrorCallback> errorCallback; - if (args.size() > 1 && !args.at(1).isNull()) { if (!(object = args.at(1).getObject())) { setDOMException(exec, TYPE_MISMATCH_ERR); return jsUndefined(); } - errorCallback = JSCustomSQLTransactionErrorCallback::create(object, globalObject); + errorCallback = JSSQLTransactionErrorCallback::create(object, globalObject); } RefPtr<VoidCallback> successCallback; diff --git a/WebCore/bindings/js/JSDesktopNotificationsCustom.cpp b/WebCore/bindings/js/JSDesktopNotificationsCustom.cpp index f86bae5..387f5f5 100644 --- a/WebCore/bindings/js/JSDesktopNotificationsCustom.cpp +++ b/WebCore/bindings/js/JSDesktopNotificationsCustom.cpp @@ -61,27 +61,6 @@ JSValue JSNotificationCenter::requestPermission(ExecState* exec, const ArgList& return jsUndefined(); } -JSValue JSNotification::addEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - -JSValue JSNotification::removeEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - - } // namespace #endif // ENABLE(NOTIFICATIONS) diff --git a/WebCore/bindings/js/JSEventListener.cpp b/WebCore/bindings/js/JSEventListener.cpp index 3853cfc..c64aa29 100644 --- a/WebCore/bindings/js/JSEventListener.cpp +++ b/WebCore/bindings/js/JSEventListener.cpp @@ -34,10 +34,11 @@ namespace WebCore { JSEventListener::JSEventListener(JSObject* function, JSObject* wrapper, bool isAttribute, DOMWrapperWorld* isolatedWorld) : EventListener(JSEventListenerType) , m_jsFunction(function) - , m_wrapper(wrapper) , m_isAttribute(isAttribute) , m_isolatedWorld(isolatedWorld) { + if (wrapper) + m_wrapper = wrapper; } JSEventListener::~JSEventListener() @@ -59,7 +60,7 @@ void JSEventListener::markJSFunction(MarkStack& markStack) void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event) { ASSERT(scriptExecutionContext); - if (!scriptExecutionContext) + if (!scriptExecutionContext || scriptExecutionContext->isJSExecutionTerminated()) return; JSLock lock(SilenceAssertionsOnly); diff --git a/WebCore/bindings/js/JSEventSourceCustom.cpp b/WebCore/bindings/js/JSEventSourceCustom.cpp deleted file mode 100644 index 86db431..0000000 --- a/WebCore/bindings/js/JSEventSourceCustom.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2009 Ericsson AB - * 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 Ericsson 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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" - -#if ENABLE(EVENTSOURCE) - -#include "JSEventSource.h" - -#include "EventSource.h" -#include "JSDOMGlobalObject.h" -#include "JSEventListener.h" - -using namespace JSC; - -namespace WebCore { - -JSValue JSEventSource::addEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - -JSValue JSEventSource::removeEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - -} // namespace WebCore - -#endif // ENABLE(EVENTSOURCE) diff --git a/WebCore/bindings/js/JSHTMLFormElementCustom.cpp b/WebCore/bindings/js/JSHTMLFormElementCustom.cpp index 2e7522c..4dd0b81 100644 --- a/WebCore/bindings/js/JSHTMLFormElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLFormElementCustom.cpp @@ -61,13 +61,4 @@ JSValue JSHTMLFormElement::nameGetter(ExecState* exec, JSValue slotBase, const I return toJS(exec, jsForm->globalObject(), StaticNodeList::adopt(namedItems).get()); } -JSValue JSHTMLFormElement::submit(ExecState* exec, const ArgList&) -{ - Frame* activeFrame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame(); - if (!activeFrame) - return jsUndefined(); - static_cast<HTMLFormElement*>(impl())->submit(activeFrame); - return jsUndefined(); -} - } diff --git a/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp b/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp index 8bfb8a3..1fedd7e 100644 --- a/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp +++ b/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp @@ -129,12 +129,6 @@ JSValue JSInjectedScriptHost::currentCallFrame(ExecState* exec, const ArgList&) JSLock lock(SilenceAssertionsOnly); return toJS(exec, callFrame); } - -JSValue JSInjectedScriptHost::isActivation(ExecState*, const ArgList& args) -{ - JSObject* object = args.at(0).getObject(); - return jsBoolean(object && object->isActivationObject()); -} #endif JSValue JSInjectedScriptHost::nodeForId(ExecState* exec, const ArgList& args) diff --git a/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp b/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp index 080f730..f45abf6 100644 --- a/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp +++ b/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp @@ -85,10 +85,41 @@ JSValue JSJavaScriptCallFrame::scopeChain(ExecState* exec) const return constructArray(exec, list); } -JSValue JSJavaScriptCallFrame::scopeType(ExecState*, const ArgList&) +JSValue JSJavaScriptCallFrame::scopeType(ExecState* exec, const ArgList& args) { - // FIXME(37663): implement this method the way it's done in the InjectedScipt.js - return jsNull(); + if (!impl()->scopeChain()) + return jsUndefined(); + + if (!args.at(0).isInt32()) + return jsUndefined(); + int index = args.at(0).asInt32(); + + const ScopeChainNode* scopeChain = impl()->scopeChain(); + ScopeChainIterator end = scopeChain->end(); + + bool foundLocalScope = false; + for (ScopeChainIterator iter = scopeChain->begin(); iter != end; ++iter) { + JSObject* scope = *iter; + if (scope->isActivationObject()) { + if (!foundLocalScope) { + // First activation object is local scope, each successive activation object is closure. + if (!index) + return jsJavaScriptCallFrameLOCAL_SCOPE(exec, JSValue(), Identifier()); + foundLocalScope = true; + } else if (!index) + return jsJavaScriptCallFrameCLOSURE_SCOPE(exec, JSValue(), Identifier()); + } + + if (!index) { + // Last in the chain is global scope. + if (++iter == end) + return jsJavaScriptCallFrameGLOBAL_SCOPE(exec, JSValue(), Identifier()); + return jsJavaScriptCallFrameWITH_SCOPE(exec, JSValue(), Identifier()); + } + + --index; + } + return jsUndefined(); } } // namespace WebCore diff --git a/WebCore/bindings/js/JSMessagePortCustom.cpp b/WebCore/bindings/js/JSMessagePortCustom.cpp index f7c0160..4c1491d 100644 --- a/WebCore/bindings/js/JSMessagePortCustom.cpp +++ b/WebCore/bindings/js/JSMessagePortCustom.cpp @@ -52,26 +52,6 @@ void JSMessagePort::markChildren(MarkStack& markStack) m_impl->markJSEventListeners(markStack); } -JSValue JSMessagePort::addEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - -JSValue JSMessagePort::removeEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - JSC::JSValue JSMessagePort::postMessage(JSC::ExecState* exec, const JSC::ArgList& args) { return handlePostMessage(exec, args, impl()); diff --git a/WebCore/bindings/js/JSNodeCustom.cpp b/WebCore/bindings/js/JSNodeCustom.cpp index 3a07b29..6d61037 100644 --- a/WebCore/bindings/js/JSNodeCustom.cpp +++ b/WebCore/bindings/js/JSNodeCustom.cpp @@ -169,26 +169,6 @@ JSValue JSNode::appendChild(ExecState* exec, const ArgList& args) return jsNull(); } -JSValue JSNode::addEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - -JSValue JSNode::removeEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - void JSNode::pushEventHandlerScope(ExecState*, ScopeChain&) const { } @@ -199,6 +179,7 @@ void JSNode::markChildren(MarkStack& markStack) Node* node = m_impl.get(); node->markJSEventListeners(markStack); + node->markCachedNodeLists(markStack, *Heap::heap(this)->globalData()); // Nodes in the document are kept alive by JSDocument::mark, so, if we're in // the document, we need to mark the document, but we don't need to explicitly diff --git a/WebCore/bindings/js/JSNodeFilterCustom.cpp b/WebCore/bindings/js/JSNodeFilterCustom.cpp index 2a99a93..bb90c4f 100644 --- a/WebCore/bindings/js/JSNodeFilterCustom.cpp +++ b/WebCore/bindings/js/JSNodeFilterCustom.cpp @@ -41,11 +41,6 @@ void JSNodeFilter::markChildren(MarkStack& markStack) impl()->markAggregate(markStack); } -JSValue JSNodeFilter::acceptNode(ExecState* exec, const ArgList& args) -{ - return jsNumber(exec, impl()->acceptNode(exec, toNode(args.at(0)))); -} - PassRefPtr<NodeFilter> toNodeFilter(JSValue value) { if (value.inherits(&JSNodeFilter::s_info)) diff --git a/WebCore/bindings/js/JSNodeIteratorCustom.cpp b/WebCore/bindings/js/JSNodeIteratorCustom.cpp index 6a09abf..7c858e5 100644 --- a/WebCore/bindings/js/JSNodeIteratorCustom.cpp +++ b/WebCore/bindings/js/JSNodeIteratorCustom.cpp @@ -37,34 +37,4 @@ void JSNodeIterator::markChildren(MarkStack& markStack) filter->markAggregate(markStack); } -JSValue JSNodeIterator::nextNode(ExecState* exec, const ArgList&) -{ - ExceptionCode ec = 0; - RefPtr<Node> node = impl()->nextNode(exec, ec); - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - - if (exec->hadException()) - return jsUndefined(); - - return toJS(exec, node.get()); -} - -JSValue JSNodeIterator::previousNode(ExecState* exec, const ArgList&) -{ - ExceptionCode ec = 0; - RefPtr<Node> node = impl()->previousNode(exec, ec); - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - - if (exec->hadException()) - return jsUndefined(); - - return toJS(exec, node.get()); -} - } diff --git a/WebCore/bindings/js/JSPopStateEventCustom.cpp b/WebCore/bindings/js/JSPopStateEventCustom.cpp index ce430ab..14fc9d9 100644 --- a/WebCore/bindings/js/JSPopStateEventCustom.cpp +++ b/WebCore/bindings/js/JSPopStateEventCustom.cpp @@ -33,16 +33,6 @@ using namespace JSC; namespace WebCore { -JSValue JSPopStateEvent::initPopStateEvent(ExecState* exec, const ArgList& args) -{ - const UString& typeArg = args.at(0).toString(exec); - bool canBubbleArg = args.at(1).toBoolean(exec); - bool cancelableArg = args.at(2).toBoolean(exec); - RefPtr<SerializedScriptValue> stateObjectArg = SerializedScriptValue::create(exec, args.at(3)); - - PopStateEvent* event = static_cast<PopStateEvent*>(impl()); - event->initPopStateEvent(ustringToAtomicString(typeArg), canBubbleArg, cancelableArg, stateObjectArg.release()); - return jsUndefined(); -} +// FIXME: Remove this file. } // namespace WebCore diff --git a/WebCore/bindings/js/JSSQLTransactionCustom.cpp b/WebCore/bindings/js/JSSQLTransactionCustom.cpp index 81e6c63..802a384 100644 --- a/WebCore/bindings/js/JSSQLTransactionCustom.cpp +++ b/WebCore/bindings/js/JSSQLTransactionCustom.cpp @@ -33,8 +33,8 @@ #include "DOMWindow.h" #include "ExceptionCode.h" -#include "JSCustomSQLStatementCallback.h" -#include "JSCustomSQLStatementErrorCallback.h" +#include "JSSQLStatementCallback.h" +#include "JSSQLStatementErrorCallback.h" #include "JSDOMWindowCustom.h" #include "SQLTransaction.h" @@ -95,7 +95,7 @@ JSValue JSSQLTransaction::executeSql(ExecState* exec, const ArgList& args) return jsUndefined(); } - callback = JSCustomSQLStatementCallback::create(object, static_cast<JSDOMGlobalObject*>(exec->dynamicGlobalObject())); + callback = JSSQLStatementCallback::create(object, static_cast<JSDOMGlobalObject*>(exec->dynamicGlobalObject())); } RefPtr<SQLStatementErrorCallback> errorCallback; @@ -106,7 +106,7 @@ JSValue JSSQLTransaction::executeSql(ExecState* exec, const ArgList& args) return jsUndefined(); } - errorCallback = JSCustomSQLStatementErrorCallback::create(object, static_cast<JSDOMGlobalObject*>(exec->dynamicGlobalObject())); + errorCallback = JSSQLStatementErrorCallback::create(object, static_cast<JSDOMGlobalObject*>(exec->dynamicGlobalObject())); } ExceptionCode ec = 0; diff --git a/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp b/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp index fdcab06..ccf5ccd 100644 --- a/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp +++ b/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp @@ -46,26 +46,6 @@ void JSSVGElementInstance::markChildren(MarkStack& markStack) markDOMNodeWrapper(markStack, impl()->correspondingElement()->document(), impl()->correspondingElement()); } -JSValue JSSVGElementInstance::addEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - -JSValue JSSVGElementInstance::removeEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - void JSSVGElementInstance::pushEventHandlerScope(ExecState*, ScopeChain&) const { } diff --git a/WebCore/bindings/js/JSTreeWalkerCustom.cpp b/WebCore/bindings/js/JSTreeWalkerCustom.cpp index f879cf4..0c1947f 100644 --- a/WebCore/bindings/js/JSTreeWalkerCustom.cpp +++ b/WebCore/bindings/js/JSTreeWalkerCustom.cpp @@ -36,61 +36,5 @@ void JSTreeWalker::markChildren(MarkStack& markStack) if (NodeFilter* filter = m_impl->filter()) filter->markAggregate(markStack); } - -JSValue JSTreeWalker::parentNode(ExecState* exec, const ArgList&) -{ - Node* node = impl()->parentNode(exec); - if (exec->hadException()) - return jsUndefined(); - return toJS(exec, node); -} - -JSValue JSTreeWalker::firstChild(ExecState* exec, const ArgList&) -{ - Node* node = impl()->firstChild(exec); - if (exec->hadException()) - return jsUndefined(); - return toJS(exec, node); -} - -JSValue JSTreeWalker::lastChild(ExecState* exec, const ArgList&) -{ - Node* node = impl()->lastChild(exec); - if (exec->hadException()) - return jsUndefined(); - return toJS(exec, node); -} - -JSValue JSTreeWalker::nextSibling(ExecState* exec, const ArgList&) -{ - Node* node = impl()->nextSibling(exec); - if (exec->hadException()) - return jsUndefined(); - return toJS(exec, node); -} - -JSValue JSTreeWalker::previousSibling(ExecState* exec, const ArgList&) -{ - Node* node = impl()->previousSibling(exec); - if (exec->hadException()) - return jsUndefined(); - return toJS(exec, node); -} - -JSValue JSTreeWalker::previousNode(ExecState* exec, const ArgList&) -{ - Node* node = impl()->previousNode(exec); - if (exec->hadException()) - return jsUndefined(); - return toJS(exec, node); -} - -JSValue JSTreeWalker::nextNode(ExecState* exec, const ArgList&) -{ - Node* node = impl()->nextNode(exec); - if (exec->hadException()) - return jsUndefined(); - return toJS(exec, node); -} } diff --git a/WebCore/bindings/js/JSWebGLArrayBufferConstructor.cpp b/WebCore/bindings/js/JSWebGLArrayBufferConstructor.cpp index 8671908..5f1f643 100644 --- a/WebCore/bindings/js/JSWebGLArrayBufferConstructor.cpp +++ b/WebCore/bindings/js/JSWebGLArrayBufferConstructor.cpp @@ -30,6 +30,7 @@ #include "JSWebGLArrayBufferConstructor.h" #include "Document.h" +#include "ExceptionCode.h" #include "JSWebGLArrayBuffer.h" namespace WebCore { diff --git a/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp b/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp index e336027..41000fd 100644 --- a/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp +++ b/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp @@ -32,10 +32,8 @@ #include "ExceptionCode.h" #include "HTMLCanvasElement.h" #include "HTMLImageElement.h" -#include "HTMLVideoElement.h" #include "JSHTMLCanvasElement.h" #include "JSHTMLImageElement.h" -#include "JSHTMLVideoElement.h" #include "JSImageData.h" #include "JSWebGLBuffer.h" #include "JSWebGLFloatArray.h" @@ -60,6 +58,11 @@ #include <wtf/FastMalloc.h> #include <wtf/OwnFastMallocPtr.h> +#if ENABLE(VIDEO) +#include "HTMLVideoElement.h" +#include "JSHTMLVideoElement.h" +#endif + using namespace JSC; namespace WebCore { @@ -352,9 +355,11 @@ JSValue JSWebGLRenderingContext::texImage2D(ExecState* exec, const ArgList& args } else if (o->inherits(&JSHTMLCanvasElement::s_info)) { HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLCanvasElement*>(o)->impl()); context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec); +#if ENABLE(VIDEO) } else if (o->inherits(&JSHTMLVideoElement::s_info)) { HTMLVideoElement* element = static_cast<HTMLVideoElement*>(static_cast<JSHTMLVideoElement*>(o)->impl()); context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec); +#endif } else ec = TYPE_MISMATCH_ERR; } else { @@ -461,9 +466,11 @@ JSValue JSWebGLRenderingContext::texSubImage2D(ExecState* exec, const ArgList& a } else if (o->inherits(&JSHTMLCanvasElement::s_info)) { HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLCanvasElement*>(o)->impl()); context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec); +#if ENABLE(VIDEO) } else if (o->inherits(&JSHTMLVideoElement::s_info)) { HTMLVideoElement* element = static_cast<HTMLVideoElement*>(static_cast<JSHTMLVideoElement*>(o)->impl()); context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec); +#endif } else ec = TYPE_MISMATCH_ERR; } else { diff --git a/WebCore/bindings/js/JSWebSocketCustom.cpp b/WebCore/bindings/js/JSWebSocketCustom.cpp index 18f4183..149ac5d 100644 --- a/WebCore/bindings/js/JSWebSocketCustom.cpp +++ b/WebCore/bindings/js/JSWebSocketCustom.cpp @@ -59,26 +59,6 @@ JSValue JSWebSocket::send(ExecState* exec, const ArgList& args) return ret; } -JSValue JSWebSocket::addEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - -JSValue JSWebSocket::removeEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - } // namespace WebCore #endif diff --git a/WebCore/bindings/js/JSWorkerContextBase.cpp b/WebCore/bindings/js/JSWorkerContextBase.cpp index 2491f4d..effe488 100644 --- a/WebCore/bindings/js/JSWorkerContextBase.cpp +++ b/WebCore/bindings/js/JSWorkerContextBase.cpp @@ -71,7 +71,9 @@ JSValue toJS(ExecState*, WorkerContext* workerContext) WorkerScriptController* script = workerContext->script(); if (!script) return jsNull(); - return script->workerContextWrapper(); + JSWorkerContext* contextWrapper = script->workerContextWrapper(); + ASSERT(contextWrapper); + return contextWrapper; } JSDedicatedWorkerContext* toJSDedicatedWorkerContext(JSValue value) diff --git a/WebCore/bindings/js/JSWorkerContextCustom.cpp b/WebCore/bindings/js/JSWorkerContextCustom.cpp index 0a9489b..a70c1b3 100644 --- a/WebCore/bindings/js/JSWorkerContextCustom.cpp +++ b/WebCore/bindings/js/JSWorkerContextCustom.cpp @@ -116,26 +116,6 @@ JSValue JSWorkerContext::importScripts(ExecState* exec, const ArgList& args) return jsUndefined(); } -JSValue JSWorkerContext::addEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - -JSValue JSWorkerContext::removeEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - JSValue JSWorkerContext::setTimeout(ExecState* exec, const ArgList& args) { OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, args, currentWorld(exec)); diff --git a/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp b/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp index da83801..fc72154 100644 --- a/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp +++ b/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp @@ -153,26 +153,6 @@ JSValue JSXMLHttpRequest::overrideMimeType(ExecState* exec, const ArgList& args) return jsUndefined(); } -JSValue JSXMLHttpRequest::addEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - -JSValue JSXMLHttpRequest::removeEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - JSValue JSXMLHttpRequest::responseText(ExecState* exec) const { return jsOwnedStringOrNull(exec, impl()->responseText()); diff --git a/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp b/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp index 42d4eb9..091c380 100644 --- a/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp +++ b/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp @@ -51,24 +51,4 @@ void JSXMLHttpRequestUpload::markChildren(MarkStack& markStack) m_impl->markJSEventListeners(markStack); } -JSValue JSXMLHttpRequestUpload::addEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - -JSValue JSXMLHttpRequestUpload::removeEventListener(ExecState* exec, const ArgList& args) -{ - JSValue listener = args.at(1); - if (!listener.isObject()) - return jsUndefined(); - - impl()->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); - return jsUndefined(); -} - } // namespace WebCore diff --git a/WebCore/bindings/js/ScriptController.cpp b/WebCore/bindings/js/ScriptController.cpp index b3695b4..508b2f8 100644 --- a/WebCore/bindings/js/ScriptController.cpp +++ b/WebCore/bindings/js/ScriptController.cpp @@ -36,6 +36,7 @@ #include "ScriptValue.h" #include "Settings.h" #include "StorageNamespace.h" +#include "UserGestureIndicator.h" #include "WebCoreJSClientData.h" #include "XSSAuditor.h" #include "npruntime_impl.h" @@ -43,6 +44,7 @@ #include <debugger/Debugger.h> #include <runtime/InitializeThreading.h> #include <runtime/JSLock.h> +#include <wtf/Threading.h> using namespace JSC; using namespace std; @@ -52,6 +54,7 @@ namespace WebCore { void ScriptController::initializeThreading() { JSC::initializeThreading(); + WTF::initializeMainThread(); } ScriptController::ScriptController(Frame* frame) @@ -70,7 +73,7 @@ ScriptController::ScriptController(Frame* frame) #endif , m_XSSAuditor(new XSSAuditor(frame)) { -#if PLATFORM(MAC) && ENABLE(MAC_JAVA_BRIDGE) +#if PLATFORM(MAC) && ENABLE(JAVA_BRIDGE) static bool initializedJavaJSBindings; if (!initializedJavaJSBindings) { initializedJavaJSBindings = true; @@ -226,19 +229,16 @@ JSDOMWindowShell* ScriptController::initScript(DOMWrapperWorld* world) bool ScriptController::processingUserGesture(DOMWrapperWorld* world) const { - return m_allowPopupsFromPlugin || processingUserGestureEvent(world) || isJavaScriptAnchorNavigation(); -} + if (m_allowPopupsFromPlugin || isJavaScriptAnchorNavigation()) + return true; -bool ScriptController::processingUserGestureEvent(DOMWrapperWorld* world) const -{ - JSDOMWindowShell* shell = existingWindowShell(world); - if (!shell) - return false; + // If a DOM event is being processed, check that it was initiated by the user + // and that it is in the whitelist of event types allowed to generate pop-ups. + if (JSDOMWindowShell* shell = existingWindowShell(world)) + if (Event* event = shell->window()->currentEvent()) + return event->fromUserGesture(); - if (Event* event = shell->window()->currentEvent()) - return event->fromUserGesture(); - - return false; + return UserGestureIndicator::processingUserGesture(); } // FIXME: This seems like an insufficient check to verify a click on a javascript: anchor. diff --git a/WebCore/bindings/js/ScriptController.h b/WebCore/bindings/js/ScriptController.h index d096c2e..468ac5c 100644 --- a/WebCore/bindings/js/ScriptController.h +++ b/WebCore/bindings/js/ScriptController.h @@ -152,7 +152,7 @@ public: PassRefPtr<JSC::Bindings::RootObject> createRootObject(void* nativeHandle); #if PLATFORM(MAC) -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) static void initJavaJSBindings(); #endif WebScriptObject* windowScriptObject(); @@ -172,7 +172,6 @@ private: void disconnectPlatformScriptObjects(); - bool processingUserGestureEvent(DOMWrapperWorld*) const; bool isJavaScriptAnchorNavigation() const; ShellMap m_windowShells; diff --git a/WebCore/bindings/js/ScriptControllerEfl.cpp b/WebCore/bindings/js/ScriptControllerEfl.cpp new file mode 100644 index 0000000..950c11e --- /dev/null +++ b/WebCore/bindings/js/ScriptControllerEfl.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com + * Copyright (C) 2007 Holger Hans Peter Freyther + * Copyright (C) 2008 Collabora Ltd. All rights reserved. + * Copyright (C) 2008 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009,2010 ProFUSION embedded systems + * Copyright (C) 2009,2010 Samsung Electronics + * 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 "ScriptController.h" + +#include "PluginView.h" + +namespace WebCore { + +PassRefPtr<JSC::Bindings::Instance> ScriptController::createScriptInstanceForWidget(Widget* widget) +{ + return 0; + +#if 0 // FIXME: disabled until we have Plugin system done. + if (!widget->isPluginView()) + return 0; + + return static_cast<PluginView*>(widget)->bindingInstance(); +#endif +} + +} diff --git a/WebCore/bindings/js/ScriptControllerMac.mm b/WebCore/bindings/js/ScriptControllerMac.mm index a895489..7c29bfc 100644 --- a/WebCore/bindings/js/ScriptControllerMac.mm +++ b/WebCore/bindings/js/ScriptControllerMac.mm @@ -49,7 +49,7 @@ #import "npruntime_impl.h" #endif -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #import "JavaInstanceJSC.h" #endif @@ -95,7 +95,7 @@ PassScriptInstance ScriptController::createScriptInstanceForWidget(Widget* widge #endif } -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) jobject applet = m_frame->loader()->client()->javaApplet(widgetView); if (!applet) return 0; @@ -136,7 +136,7 @@ void ScriptController::disconnectPlatformScriptObjects() } } -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) static pthread_t mainThread; diff --git a/WebCore/bindings/js/ScriptEventListener.cpp b/WebCore/bindings/js/ScriptEventListener.cpp index 01b9060..467f16b 100644 --- a/WebCore/bindings/js/ScriptEventListener.cpp +++ b/WebCore/bindings/js/ScriptEventListener.cpp @@ -105,7 +105,7 @@ PassRefPtr<JSLazyEventListener> createAttributeEventListener(Frame* frame, Attri return JSLazyEventListener::create(attr->localName().string(), eventParameterName(frame->document()->isSVGDocument()), attr->value(), 0, sourceURL, lineNumber, wrapper, mainThreadNormalWorld()); } -String getEventListenerHandlerBody(ScriptExecutionContext* context, ScriptState* scriptState, EventListener* eventListener) +String eventListenerHandlerBody(ScriptExecutionContext* context, ScriptState* scriptState, EventListener* eventListener) { const JSEventListener* jsListener = JSEventListener::cast(eventListener); if (!jsListener) @@ -116,4 +116,10 @@ String getEventListenerHandlerBody(ScriptExecutionContext* context, ScriptState* return ustringToString(jsFunction->toString(scriptState)); } +bool eventListenerHandlerLocation(ScriptExecutionContext*, ScriptState*, EventListener*, String&, int&) +{ + // FIXME: Add support for getting function location. + return false; +} + } // namespace WebCore diff --git a/WebCore/bindings/js/ScriptEventListener.h b/WebCore/bindings/js/ScriptEventListener.h index 3396541..f1f203c 100644 --- a/WebCore/bindings/js/ScriptEventListener.h +++ b/WebCore/bindings/js/ScriptEventListener.h @@ -45,8 +45,8 @@ namespace WebCore { PassRefPtr<JSLazyEventListener> createAttributeEventListener(Node*, Attribute*); PassRefPtr<JSLazyEventListener> createAttributeEventListener(Frame*, Attribute*); - String getEventListenerHandlerBody(ScriptExecutionContext*, ScriptState*, EventListener*); - + String eventListenerHandlerBody(ScriptExecutionContext*, ScriptState*, EventListener*); + bool eventListenerHandlerLocation(ScriptExecutionContext*, ScriptState*, EventListener*, String& sourceName, int& lineNumber); } // namespace WebCore #endif // ScriptEventListener_h diff --git a/WebCore/bindings/js/ScriptWrappable.h b/WebCore/bindings/js/ScriptWrappable.h index 5e99c1c..c57796c 100644 --- a/WebCore/bindings/js/ScriptWrappable.h +++ b/WebCore/bindings/js/ScriptWrappable.h @@ -38,8 +38,6 @@ namespace WebCore { class ScriptWrappable { public: - ScriptWrappable() : m_wrapper(0) { } - DOMObject* wrapper() const { return m_wrapper.get(); @@ -47,7 +45,6 @@ public: void setWrapper(DOMObject* wrapper) { - ASSERT(wrapper); m_wrapper = wrapper; } diff --git a/WebCore/bindings/js/WorkerScriptController.h b/WebCore/bindings/js/WorkerScriptController.h index 38c3c30..60c3b04 100644 --- a/WebCore/bindings/js/WorkerScriptController.h +++ b/WebCore/bindings/js/WorkerScriptController.h @@ -52,9 +52,6 @@ namespace WebCore { JSWorkerContext* workerContextWrapper() { - if (m_executionForbidden) - return 0; - initScriptIfNeeded(); return m_workerContextWrapper; } @@ -66,6 +63,7 @@ namespace WebCore { enum ForbidExecutionOption { TerminateRunningScript, LetRunningScriptFinish }; void forbidExecution(ForbidExecutionOption); + bool isExecutionForbidden() const { return m_executionForbidden; } JSC::JSGlobalData* globalData() { return m_globalData.get(); } diff --git a/WebCore/bindings/objc/WebScriptObject.mm b/WebCore/bindings/objc/WebScriptObject.mm index 618459a..1cec41c 100644 --- a/WebCore/bindings/objc/WebScriptObject.mm +++ b/WebCore/bindings/objc/WebScriptObject.mm @@ -49,6 +49,7 @@ #import <runtime/JSLock.h> #import <runtime/Completion.h> #import <runtime/Completion.h> +#import <wtf/Threading.h> #ifdef BUILDING_ON_TIGER typedef unsigned NSUInteger; @@ -109,6 +110,7 @@ static void addExceptionToConsole(ExecState* exec) + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebCore/bindings/scripts/CodeGeneratorGObject.pm b/WebCore/bindings/scripts/CodeGeneratorGObject.pm index 2a38eff..1d03f08 100644 --- a/WebCore/bindings/scripts/CodeGeneratorGObject.pm +++ b/WebCore/bindings/scripts/CodeGeneratorGObject.pm @@ -26,6 +26,10 @@ package CodeGeneratorGObject; my %implIncludes = (); my %hdrIncludes = (); +my @txtInstallProps = (); +my @txtSetProps = (); +my @txtGetProps = (); + my $className = ""; # Default constructor @@ -95,6 +99,16 @@ sub decamelize $s; } +sub FixUpDecamelizedName { + my $classname = shift; + + # FIXME: try to merge this somehow with the fixes in ClassNameToGobjectType + $classname =~ s/x_path/xpath/; + $classname =~ s/web_kit/webkit/; + + return $classname; +} + sub ClassNameToGObjectType { my $className = shift; my $CLASS_NAME = uc(decamelize($className)); @@ -102,6 +116,11 @@ sub ClassNameToGObjectType { # WebKitDOMCSS right, so we have to fix it manually (and there # might be more like this in the future) $CLASS_NAME =~ s/DOMCSS/DOM_CSS/; + $CLASS_NAME =~ s/DOMHTML/DOM_HTML/; + $CLASS_NAME =~ s/DOMDOM/DOM_DOM/; + $CLASS_NAME =~ s/DOMCDATA/DOM_CDATA/; + $CLASS_NAME =~ s/DOMX_PATH/DOM_XPATH/; + $CLASS_NAME =~ s/DOM_WEB_KIT/DOM_WEBKIT/; return $CLASS_NAME; } @@ -128,7 +147,8 @@ sub SkipAttribute { my $attribute = shift; if ($attribute->signature->extendedAttributes->{"CustomGetter"} || - $attribute->signature->extendedAttributes->{"CustomSetter"}) { + $attribute->signature->extendedAttributes->{"CustomSetter"} || + $attribute->signature->extendedAttributes->{"Replaceable"}) { return 1; } @@ -141,6 +161,55 @@ sub SkipAttribute { return 1; } + # This is for DOMWindow.idl location attribute + if ($attribute->signature->name eq "location") { + return 1; + } + + # This is for HTMLInput.idl valueAsDate + if ($attribute->signature->name eq "valueAsDate") { + return 1; + } + + # This is for DOMWindow.idl Crypto attribute + if ($attribute->signature->type eq "Crypto") { + return 1; + } + + return 0; +} + +sub SkipFunction { + my $function = shift; + my $decamelize = shift; + my $prefix = shift; + + my $functionName = "webkit_dom_" . $decamelize . "_" . $prefix . decamelize($function->signature->name); + my $isCustomFunction = $function->signature->extendedAttributes->{"Custom"} || + $function->signature->extendedAttributes->{"CustomArgumentHandling"}; + + if ($isCustomFunction && + $functionName ne "webkit_dom_node_replace_child" && + $functionName ne "webkit_dom_node_insert_before" && + $functionName ne "webkit_dom_node_replace_child" && + $functionName ne "webkit_dom_node_append_child" && + $functionName ne "webkit_dom_html_collection_item" && + $functionName ne "webkit_dom_html_collection_named_item") { + return 1; + } + + if ($function->signature->type eq "Event") { + return 1; + } + + if ($function->signature->name eq "getSVGDocument") { + return 1; + } + + if ($function->signature->name eq "getCSSCanvasContext") { + return 1; + } + return 0; } @@ -154,6 +223,7 @@ sub GetGValueTypeName { "boolean", "boolean", "char", "char", "long", "long", + "long long", "int64", "short", "int", "uchar", "uchar", "unsigned", "uint", @@ -172,11 +242,13 @@ sub GetGlibTypeName { my $name = GetClassName($type); my %types = ("DOMString", "gchar* ", + "CompareHow", "gushort", "float", "gfloat", "double", "gdouble", "boolean", "gboolean", "char", "gchar", "long", "glong", + "long long", "gint64", "short", "gshort", "uchar", "guchar", "unsigned", "guint", @@ -193,30 +265,192 @@ sub GetGlibTypeName { sub IsGDOMClassType { my $type = shift; - return 0 if $type eq "DOMString"; - return 0 if $type eq "float"; - return 0 if $type eq "double"; - return 0 if $type eq "boolean"; - return 0 if $type eq "char"; - return 0 if $type eq "long"; - return 0 if $type eq "short"; - return 0 if $type eq "uchar"; - return 0 if $type eq "unsigned"; - return 0 if $type eq "int"; - return 0 if $type eq "unsigned int"; - return 0 if $type eq "unsigned long"; - return 0 if $type eq "unsigned long long"; - return 0 if $type eq "unsigned short"; - return 0 if $type eq "void"; - + return 0 if $codeGenerator->IsNonPointerType($type) || $codeGenerator->IsStringType($type); return 1; } +sub GetReadableProperties { + my $properties = shift; + + my @result = (); + + foreach my $property (@{$properties}) { + if (!SkipAttribute($property)) { + push(@result, $property); + } + } + + return @result; +} + +sub GetWriteableProperties { + my $properties = shift; + my @result = (); + + foreach my $property (@{$properties}) { + my $writeable = $property->type !~ /^readonly/; + my $gtype = GetGValueTypeName($property->signature->type); + my $hasGtypeSignature = ($gtype eq "boolean" || $gtype eq "float" || $gtype eq "double" || + $gtype eq "uint64" || $gtype eq "ulong" || $gtype eq "long" || + $gtype eq "uint" || $gtype eq "ushort" || $gtype eq "uchar" || + $gtype eq "char" || $gtype eq "string"); + if ($writeable && $hasGtypeSignature) { + push(@result, $property); + } + } + + return @result; +} + +sub GenerateProperty { + my $attribute = shift; + my $interfaceName = shift; + my @writeableProperties = @{shift @_}; + + my $camelPropName = $attribute->signature->name; + my $setPropNameFunction = $codeGenerator->WK_ucfirst($camelPropName); + my $getPropNameFunction = $codeGenerator->WK_lcfirst($camelPropName); + + my $propName = decamelize($camelPropName); + my $propNameCaps = uc($propName); + $propName =~ s/_/-/g; + my ${propEnum} = "PROP_${propNameCaps}"; + push(@cBodyPriv, " ${propEnum},\n"); + + my $propType = $attribute->signature->type; + my ${propGType} = decamelize($propType); + if ($propGType eq "event_target") { + $propGType = "event_target_node"; + } + my ${ucPropGType} = uc($propGType); + + my $gtype = GetGValueTypeName($propType); + my $gparamflag = "WEBKIT_PARAM_READABLE"; + my $writeable = $attribute->type !~ /^readonly/; + my $const = "read-only "; + my $custom = $attribute->signature->extendedAttributes->{"Custom"}; + if ($writeable && $custom) { + $const = "read-only (due to custom functions needed in webkitdom)"; + return; + } + if ($writeable && !$custom) { + $gparamflag = "WEBKIT_PARAM_READWRITE"; + $const = "read-write "; + } + + my $type = GetGlibTypeName($propType); + $nick = decamelize("${interfaceName}_${propName}"); + $long = "${const} ${type} ${interfaceName}.${propName}"; + + my $convertFunction = ""; + if ($gtype eq "string") { + $convertFunction = "WebCore::String::fromUTF8"; + } elsif ($attribute->signature->extendedAttributes->{"ConvertFromString"}) { + $convertFunction = "WebCore::String::number"; + } + + my $setterContentHead; + my $getterContentHead; + my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; + my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; + if ($reflect || $reflectURL) { + my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $camelPropName : ($reflect || $reflectURL); + my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); + $implIncludes{"${namespace}.h"} = 1; + my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute"; + $setterContentHead = "coreSelf->setAttribute(WebCore::${namespace}::${contentAttributeName}Attr, ${convertFunction}(g_value_get_$gtype(value))"; + $getterContentHead = "coreSelf->${getAttributeFunctionName}(WebCore::${namespace}::${contentAttributeName}Attr"; + } else { + $setterContentHead = "coreSelf->set${setPropNameFunction}(${convertFunction}(g_value_get_$gtype(value))"; + $getterContentHead = "coreSelf->${getPropNameFunction}("; + } + + if (grep {$_ eq $attribute} @writeableProperties) { + push(@txtSetProps, " case ${propEnum}:\n {\n"); + push(@txtSetProps, " WebCore::ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions}; + push(@txtSetProps, " ${setterContentHead}"); + push(@txtSetProps, ", ec") if @{$attribute->setterExceptions}; + push(@txtSetProps, ");\n"); + push(@txtSetProps, " break;\n }\n"); + } + + push(@txtGetProps, " case ${propEnum}:\n {\n"); + + my $exception = ""; + if (@{$attribute->getterExceptions}) { + $exception = "ec"; + push(@txtGetProps, " WebCore::ExceptionCode ec = 0;\n"); + } + + my $postConvertFunction = ""; + my $done = 0; + if ($gtype eq "string") { + push(@txtGetProps, " g_value_take_string(value, convertToUTF8String(${getterContentHead}${exception})));\n"); + $done = 1; + } elsif ($gtype eq "object") { + $txtGetProp = << "EOF"; + RefPtr<WebCore::${propType}> ptr = coreSelf->${getPropNameFunction}(${exception}); + g_value_set_object(value, WebKit::kit(ptr.get())); +EOF + push(@txtGetProps, $txtGetProp); + $done = 1; + } + + if($attribute->signature->extendedAttributes->{"ConvertFromString"}) { + # TODO: Add other conversion functions for different types. Current + # IDLs only list longs. + if($gtype eq "long") { + $convertFunction = ""; + $postConvertFunction = ".toInt()"; + } else { + die "Can't convert to type ${gtype}."; + } + } + + # FIXME: get rid of this glitch? + my $_gtype = $gtype; + if ($gtype eq "ushort") { + $_gtype = "uint"; + } + + if (!$done) { + push(@txtGetProps, " g_value_set_$_gtype(value, ${convertFunction}coreSelf->${getPropNameFunction}(${exception})${postConvertFunction});\n"); + } + + push(@txtGetProps, " break;\n }\n"); + + my %param_spec_options = ("int", "G_MININT, /* min */\nG_MAXINT, /* max */\n0, /* default */", + "boolean", "FALSE, /* default */", + "float", "-G_MAXFLOAT, /* min */\nG_MAXFLOAT, /* max */\n0.0, /* default */", + "double", "-G_MAXDOUBLE, /* min */\nG_MAXDOUBLE, /* max */\n0.0, /* default */", + "uint64", "0, /* min */\nG_MAXUINT64, /* min */\n0, /* default */", + "long", "G_MINLONG, /* min */\nG_MAXLONG, /* max */\n0, /* default */", + "int64", "G_MININT64, /* min */\nG_MAXINT64, /* max */\n0, /* default */", + "ulong", "0, /* min */\nG_MAXULONG, /* max */\n0, /* default */", + "uint", "0, /* min */\nG_MAXUINT, /* max */\n0, /* default */", + "ushort", "0, /* min */\nG_MAXUINT16, /* max */\n0, /* default */", + "uchar", "G_MININT8, /* min */\nG_MAXINT8, /* max */\n0, /* default */", + "char", "0, /* min */\nG_MAXUINT8, /* max */\n0, /* default */", + "string", "\"\", /* default */", + "object", "WEBKIT_TYPE_DOM_${ucPropGType}, /* gobject type */"); + + my $txtInstallProp = << "EOF"; + g_object_class_install_property(gobjectClass, + ${propEnum}, + g_param_spec_${_gtype}("${propName}", /* name */ + "$nick", /* short description */ + "$long", /* longer - could do with some extra doc stuff here */ + $param_spec_options{$gtype} + ${gparamflag})); +EOF + push(@txtInstallProps, $txtInstallProp); +} + sub GenerateProperties { my ($object, $interfaceName, $dataNode) = @_; my $clsCaps = substr(ClassNameToGObjectType($className), 12); - my $lowerCaseIfaceName = "webkit_dom_" . (decamelize($interfaceName)); + my $lowerCaseIfaceName = "webkit_dom_" . (FixUpDecamelizedName(decamelize($interfaceName))); # Properties my $implContent = ""; @@ -228,169 +462,51 @@ enum { EOF push(@cBodyPriv, $implContent); - my @txtInstallProps = (); - my @txtSetProps = (); - my @txtGetProps = (); + my @readableProperties = GetReadableProperties($dataNode->attributes); my $privFunction = GetCoreObject($interfaceName, "coreSelf", "self"); my $txtGetProp = << "EOF"; static void ${lowerCaseIfaceName}_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { +EOF + push(@txtGetProps, $txtGetProp); + if (scalar @readableProperties > 0) { + $txtGetProp = << "EOF"; ${className}* self = WEBKIT_DOM_${clsCaps}(object); $privFunction +EOF + push(@txtGetProps, $txtGetProp); + } + $txtGetProp = << "EOF"; switch (prop_id) { EOF push(@txtGetProps, $txtGetProp); + my @writeableProperties = GetWriteableProperties(\@readableProperties); + my $txtSetProps = << "EOF"; static void ${lowerCaseIfaceName}_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { +EOF + push(@txtSetProps, $txtSetProps); + + if (scalar @writeableProperties > 0) { + $txtSetProps = << "EOF"; ${className} *self = WEBKIT_DOM_${clsCaps}(object); $privFunction +EOF + push(@txtSetProps, $txtSetProps); + } + $txtSetProps = << "EOF"; switch (prop_id) { EOF push(@txtSetProps, $txtSetProps); - # Iterate over the interface attributes and generate a property for - # each one of them. - SKIPENUM: - foreach my $attribute (@{$dataNode->attributes}) { - if (SkipAttribute($attribute)) { - next SKIPENUM; - } - - my $camelPropName = $attribute->signature->name; - my $setPropNameFunction = $codeGenerator->WK_ucfirst($camelPropName); - my $getPropNameFunction = $codeGenerator->WK_lcfirst($camelPropName); - - my $propName = decamelize($camelPropName); - my $propNameCaps = uc($propName); - $propName =~ s/_/-/g; - my ${propEnum} = "PROP_${propNameCaps}"; - push(@cBodyPriv, " ${propEnum},\n"); - - my $propType = $attribute->signature->type; - my ${propGType} = decamelize($propType); - if ($propGType eq "event_target") { - $propGType = "event_target_node"; - } - my ${ucPropGType} = uc($propGType); - - my $gtype = GetGValueTypeName($propType); - my $gparamflag = "WEBKIT_PARAM_READABLE"; - my $writeable = $attribute->type !~ /^readonly/; - my $const = "read-only "; - if ($writeable && $custom) { - $const = "read-only (due to custom functions needed in webkitdom)"; - next SKIPENUM; - } - if ($writeable && !$custom) { - $gparamflag = "WEBKIT_PARAM_READWRITE"; - $const = "read-write "; - } - - my $type = GetGlibTypeName($propType); - $nick = decamelize("${interfaceName}_${propName}"); - $long = "${const} ${type} ${interfaceName}.${propName}"; - - my $convertFunction = ""; - - if ($writeable && ($gtype eq "boolean" || $gtype eq "float" || $gtype eq "double" || - $gtype eq "uint64" || $gtype eq "ulong" || $gtype eq "long" || - $gtype eq "uint" || $gtype eq "ushort" || $gtype eq "uchar" || - $gtype eq "char" || $gtype eq "string")) { - - push(@txtSetProps, " case ${propEnum}:\n {\n"); - push(@txtSetProps, " WebCore::ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions}; - - if ($gtype eq "string") { - $convertFunction = "WebCore::String::fromUTF8"; - } elsif ($attribute->signature->extendedAttributes->{"ConvertFromString"}) { - $convertFunction = "WebCore::String::number"; - } - - push(@txtSetProps, " coreSelf->set${setPropNameFunction}(${convertFunction}(g_value_get_$gtype(value))"); - push(@txtSetProps, ", ec") if @{$attribute->setterExceptions}; - push(@txtSetProps, ");\n"); - - push(@txtSetProps, " break;\n }\n"); - } - - push(@txtGetProps, " case ${propEnum}:\n {\n"); - - my $exception = ""; - if (@{$attribute->getterExceptions}) { - $exception = "ec"; - push(@txtGetProps, " WebCore::ExceptionCode ec = 0;\n"); - } - - my $postConvertFunction = ""; - my $done = 0; - if ($gtype eq "string") { - push(@txtGetProps, " g_value_take_string(value, convertToUTF8String(coreSelf->${getPropNameFunction}(${exception})));\n"); - $done = 1; - } elsif ($gtype eq "object") { - - $txtGetProp = << "EOF"; - RefPtr<WebCore::${propType}> ptr = coreSelf->${getPropNameFunction}(${exception}); - g_value_set_object(value, WebKit::kit(ptr.get())); -EOF - push(@txtGetProps, $txtGetProp); - - $done = 1; - } - - if($attribute->signature->extendedAttributes->{"ConvertFromString"}) { - # TODO: Add other conversion functions for different types. Current - # IDLs only list longs. - if($gtype eq "long") { - $convertFunction = ""; - $postConvertFunction = ".toInt()"; - } else { - die "Can't convert to type ${gtype}."; - } - } - - # FIXME: get rid of this glitch? - my $_gtype = $gtype; - if ($gtype eq "ushort") { - $_gtype = "uint"; - } - - if (!$done) { - push(@txtGetProps, " g_value_set_$_gtype(value, ${convertFunction}coreSelf->${getPropNameFunction}(${exception})${postConvertFunction});\n"); - } - - push(@txtGetProps, " break;\n }\n"); - -my %param_spec_options = ("int", "G_MININT, /* min */\nG_MAXINT, /* max */\n0, /* default */", - "boolean", "FALSE, /* default */", - "float", "G_MINFLOAT, /* min */\nG_MAXFLOAT, /* max */\n0.0, /* default */", - "double", "G_MINDOUBLE, /* min */\nG_MAXDOUBLE, /* max */\n0.0, /* default */", - "uint64", "0, /* min */\nG_MAXUINT64, /* min */\n0, /* default */", - "long", "G_MINLONG, /* min */\nG_MAXLONG, /* max */\n0, /* default */", - "ulong", "0, /* min */\nG_MAXULONG, /* max */\n0, /* default */", - "uint", "0, /* min */\nG_MAXUINT, /* max */\n0, /* default */", - "ushort", "0, /* min */\nG_MAXUINT16, /* max */\n0, /* default */", - "uchar", "G_MININT8, /* min */\nG_MAXINT8, /* max */\n0, /* default */", - "char", "0, /* min */\nG_MAXUINT8, /* max */\n0, /* default */", - "string", "\"\", /* default */", - "object", "WEBKIT_TYPE_DOM_${ucPropGType}, /* gobject type */"); - - my $txtInstallProp = << "EOF"; - g_object_class_install_property(gobjectClass, - ${propEnum}, - g_param_spec_${_gtype}("${propName}", /* name */ - "$nick", /* short description */ - "$long", /* longer - could do with some extra doc stuff here */ - $param_spec_options{$gtype} - ${gparamflag})); -EOF - push(@txtInstallProps, $txtInstallProp); - $txtInstallProp = "/* TODO! $gtype */\n"; + foreach my $attribute (@readableProperties) { + GenerateProperty($attribute, $interfaceName, \@writeableProperties); } push(@cBodyPriv, "};\n\n"); @@ -483,11 +599,11 @@ EOF push(@hBodyPre, $implContent); - my $clsCaps = uc(decamelize($interfaceName)); - my $lowerCaseIfaceName = "webkit_dom_" . (decamelize($interfaceName)); + my $decamelize = FixUpDecamelizedName(decamelize($interfaceName)); + my $clsCaps = uc($decamelize); + my $lowerCaseIfaceName = "webkit_dom_" . ($decamelize); $implContent = << "EOF"; - #define WEBKIT_TYPE_DOM_${clsCaps} (${lowerCaseIfaceName}_get_type()) #define WEBKIT_DOM_${clsCaps}(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_DOM_${clsCaps}, ${className})) #define WEBKIT_DOM_${clsCaps}_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_DOM_${clsCaps}, ${className}Class) @@ -517,6 +633,7 @@ sub getIncludeHeader { return "" if $type eq "int"; return "" if $type eq "long"; + return "" if $type eq "long long"; return "" if $type eq "short"; return "" if $type eq "char"; return "" if $type eq "float"; @@ -533,6 +650,7 @@ sub getIncludeHeader { return "" if $type eq "float"; return "" if $type eq "boolean"; return "" if $type eq "void"; + return "" if $type eq "CompareHow"; return "$name.h"; } @@ -540,6 +658,10 @@ sub getIncludeHeader { sub addIncludeInBody { my $type = shift; + if ($type eq "DOMObject") { + return; + } + my $header = getIncludeHeader($type); if ($header eq "") { return; @@ -555,9 +677,15 @@ sub addIncludeInBody { sub GenerateFunction { my ($object, $interfaceName, $function, $prefix) = @_; + my $decamelize = FixUpDecamelizedName(decamelize($interfaceName)); + + if (SkipFunction($function, $decamelize, $prefix)) { + return; + } + my $functionSigName = $function->signature->name; my $functionSigType = $function->signature->type; - my $functionName = "webkit_dom_" . decamelize($interfaceName) . "_" . $prefix . decamelize($functionSigName); + my $functionName = "webkit_dom_" . $decamelize . "_" . $prefix . decamelize($functionSigName); my $returnType = GetGlibTypeName($functionSigType); my $returnValueIsGDOMType = IsGDOMClassType($functionSigType); @@ -571,7 +699,7 @@ sub GenerateFunction { foreach my $param (@{$function->parameters}) { my $paramIDLType = $param->type; - if ($paramIDLType eq "Event") { + if ($paramIDLType eq "Event" || $paramIDLType eq "EventListener") { push(@hBody, "\n/* TODO: event function ${functionName} */\n\n"); push(@cBody, "\n/* TODO: event function ${functionName} */\n\n"); return; @@ -588,7 +716,7 @@ sub GenerateFunction { $implIncludes{"webkit/WebKitDOM${paramIDLType}Private.h"} = 1; } } - if ($paramIsGDOMType || ($paramIDLType eq "DOMString")) { + if ($paramIsGDOMType || ($paramIDLType eq "DOMString") || ($paramIDLType eq "CompareHow")) { $paramName = "_g_" . $paramName; } if ($callImplParams) { @@ -598,13 +726,7 @@ sub GenerateFunction { } } - if ($functionSigType eq "Event") { - push(@hBody, "\n/* TODO: event function ${functionName} */\n\n"); - push(@cBody, "\n/* TODO: event function ${functionName} */\n\n"); - return; - } - - if ($returnType ne "void" && $returnValueIsGDOMType) { + if ($returnType ne "void" && $returnValueIsGDOMType && $functionSigType ne "DOMObject") { if ($functionSigType ne "EventTarget") { $implIncludes{"webkit/WebKitDOM${functionSigType}Private.h"} = 1; $implIncludes{"webkit/WebKitDOM${functionSigType}.h"} = 1; @@ -613,19 +735,6 @@ sub GenerateFunction { $implIncludes{"${functionSigType}.h"} = 1; } - # skip custom functions for now - # but skip from here to allow some headers to be created - # for a successful compile. - if ($isCustomFunction && - $functionName ne "webkit_dom_node_remove_child" && - $functionName ne "webkit_dom_node_insert_before" && - $functionName ne "webkit_dom_node_replace_child" && - $functionName ne "webkit_dom_node_append_child") { - push(@hBody, "\n/* TODO: custom function ${functionName} */\n\n"); - push(@cBody, "\n/* TODO: custom function ${functionName} */\n\n"); - return; - } - if(@{$function->raisesExceptions}) { $functionSig .= ", GError **error"; } @@ -667,8 +776,9 @@ sub GenerateFunction { my $paramIsGDOMType = IsGDOMClassType($paramIDLType); if ($paramIDLType eq "DOMString") { push(@cBody, " WebCore::String _g_${paramName} = WebCore::String::fromUTF8($paramName);\n"); - } - if ($paramIsGDOMType) { + } elsif ($paramIDLType eq "CompareHow") { + push(@cBody, " WebCore::Range::CompareHow _g_${paramName} = static_cast<WebCore::Range::CompareHow>($paramName);\n"); + } elsif ($paramIsGDOMType) { push(@cBody, " WebCore::${paramIDLType} * _g_${paramName} = WebKit::core($paramName);\n"); if ($returnType ne "void") { # TODO: return proper default result @@ -684,7 +794,15 @@ sub GenerateFunction { my $assignPre = ""; my $assignPost = ""; - if ($returnType ne "void" && !$isCustomFunction) { + # We need to special-case these Node methods because their C++ + # signature is different from what we'd expect given their IDL + # description; see Node.h. + my $functionHasCustomReturn = $functionName eq "webkit_dom_node_append_child" || + $functionName eq "webkit_dom_node_insert_before" || + $functionName eq "webkit_dom_node_replace_child" || + $functionName eq "webkit_dom_node_remove_child"; + + if ($returnType ne "void" && !$functionHasCustomReturn) { if ($returnValueIsGDOMType) { $assign = "PassRefPtr<WebCore::${functionSigType}> g_res = "; $assignPre = "WTF::getPtr("; @@ -703,12 +821,7 @@ sub GenerateFunction { } } - # We need to special-case these Node methods because their C++ signature is different - # from what we'd expect given their IDL description; see Node.h. - if ($functionName eq "webkit_dom_node_append_child" || - $functionName eq "webkit_dom_node_insert_before" || - $functionName eq "webkit_dom_node_replace_child" || - $functionName eq "webkit_dom_node_remove_child") { + if ($functionHasCustomReturn) { my $customNodeAppendChild = << "EOF"; bool ok = item->${functionSigName}(${callImplParams}${exceptions}); if (ok) @@ -732,13 +845,40 @@ EOF push(@cBody, "}\n\n"); return; } elsif ($functionSigType eq "DOMString") { - push(@cBody, " ${assign}convertToUTF8String(item->${functionSigName}(${callImplParams}${exceptions}));\n" ); + my $getterContentHead; + my $reflect = $function->signature->extendedAttributes->{"Reflect"}; + my $reflectURL = $function->signature->extendedAttributes->{"ReflectURL"}; + if ($reflect || $reflectURL) { + my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $functionSigName : ($reflect || $reflectURL); + my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); + $implIncludes{"${namespace}.h"} = 1; + my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute"; + $getterContentHead = "${assign}convertToUTF8String(item->${getAttributeFunctionName}(WebCore::${namespace}::${contentAttributeName}Attr));\n"; + } else { + $getterContentHead = "${assign}convertToUTF8String(item->${functionSigName}(${callImplParams}${exceptions}));\n"; + } + + push(@cBody, " ${getterContentHead}"); } else { - push(@cBody, " ${assign}${assignPre}item->${functionSigName}(${callImplParams}${exceptions}${assignPost});\n" ); + my $setterContentHead; + my $reflect = $function->signature->extendedAttributes->{"Reflect"}; + my $reflectURL = $function->signature->extendedAttributes->{"ReflectURL"}; + if ($reflect || $reflectURL) { + my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $functionSigName : ($reflect || $reflectURL); + $contentAttributeName =~ s/set//; + $contentAttributeName = $codeGenerator->WK_lcfirst($contentAttributeName); + my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); + $implIncludes{"${namespace}.h"} = 1; + $setterContentHead = "${assign}${assignPre}item->setAttribute(WebCore::${namespace}::${contentAttributeName}Attr, ${callImplParams}${exceptions}${assignPost});\n"; + } else { + $setterContentHead = "${assign}${assignPre}item->${functionSigName}(${callImplParams}${exceptions}${assignPost});\n"; + } + + push(@cBody, " ${setterContentHead}"); if(@{$function->raisesExceptions}) { my $exceptionHandling = << "EOF"; - if(ec) { + if (ec) { WebCore::ExceptionCodeDescription ecdesc; WebCore::getExceptionCodeDescription(ec, ecdesc); g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), ecdesc.code, ecdesc.name); @@ -748,7 +888,7 @@ EOF } } - if ($returnType ne "void" && !$isCustomFunction) { + if ($returnType ne "void" && !$functionHasCustomReturn) { if ($functionSigType ne "DOMObject") { if ($returnValueIsGDOMType) { push(@cBody, " ${returnType} res = static_cast<${returnType}>(WebKit::kit(g_res.get()));\n"); @@ -813,9 +953,7 @@ sub GenerateFunctions { $function->raisesExceptions($attribute->getterExceptions); $object->GenerateFunction($interfaceName, $function, "get_"); - if ($attribute->type =~ /^readonly/ || - $attribute->signature->extendedAttributes->{"Replaceable"} # can't handle this yet - ) { + if ($attribute->type =~ /^readonly/) { next TOP; } @@ -846,8 +984,8 @@ sub GenerateCFile { my ($object, $interfaceName, $parentClassName, $parentGObjType, $dataNode) = @_; my $implContent = ""; - my $clsCaps = uc(decamelize($interfaceName)); - my $lowerCaseIfaceName = "webkit_dom_" . decamelize($interfaceName); + my $clsCaps = uc(FixUpDecamelizedName(decamelize($interfaceName))); + my $lowerCaseIfaceName = "webkit_dom_" . FixUpDecamelizedName(decamelize($interfaceName)); $implContent = << "EOF"; G_DEFINE_TYPE(${className}, ${lowerCaseIfaceName}, ${parentGObjType}) @@ -962,12 +1100,10 @@ EOF close(PRIVHEADER); } -sub UsesManualToJSImplementation { +sub UsesManualKitImplementation { my $type = shift; - return 1 if $type eq "Node" or $type eq "Document" or $type eq "HTMLCollection" or - $type eq "SVGPathSeg" or $type eq "StyleSheet" or $type eq "CSSRule" or $type eq "CSSValue" or - $type eq "Event" or $type eq "Element" or $type eq "Text"; + return 1 if $type eq "Node" or $type eq "Element"; return 0; } @@ -996,7 +1132,7 @@ sub Generate { $hdrIncludes{"webkit/${parentClassName}.h"} = 1; - if ($className ne "WebKitDOMNode") { + if (!UsesManualKitImplementation($interfaceName)) { my $converter = << "EOF"; namespace WebKit { diff --git a/WebCore/bindings/scripts/CodeGeneratorJS.pm b/WebCore/bindings/scripts/CodeGeneratorJS.pm index 919e321..dc21314 100644 --- a/WebCore/bindings/scripts/CodeGeneratorJS.pm +++ b/WebCore/bindings/scripts/CodeGeneratorJS.pm @@ -101,8 +101,13 @@ sub GenerateInterface my $defines = shift; # Start actual generation - $object->GenerateHeader($dataNode); - $object->GenerateImplementation($dataNode); + if ($dataNode->extendedAttributes->{"Callback"}) { + $object->GenerateCallbackHeader($dataNode); + $object->GenerateCallbackImplementation($dataNode); + } else { + $object->GenerateHeader($dataNode); + $object->GenerateImplementation($dataNode); + } my $name = $dataNode->name; @@ -121,6 +126,25 @@ sub GenerateInterface } } +sub GenerateEventListenerCall +{ + my $className = shift; + my $functionName = shift; + my $passRefPtrHandling = ($functionName eq "add") ? "" : ".get()"; + + $implIncludes{"JSEventListener.h"} = 1; + + my @GenerateEventListenerImpl = (); + push(@GenerateEventListenerImpl, <<END); + JSValue listener = args.at(1); + if (!listener.isObject()) + return jsUndefined(); + imp->${functionName}EventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), castedThis, false, currentWorld(exec))$passRefPtrHandling, args.at(2).toBoolean(exec)); + return jsUndefined(); +END + return @GenerateEventListenerImpl; +} + # Params: 'idlDocument' struct sub GenerateModule { @@ -168,6 +192,7 @@ sub IndexGetterReturnsStrings sub AddIncludesForType { my $type = $codeGenerator->StripModule(shift); + my $isCallback = @_ ? shift : 0; # When we're finished with the one-file-per-class # reorganization, we won't need these special cases. @@ -180,6 +205,8 @@ sub AddIncludesForType } elsif ($type eq "XPathNSResolver") { $implIncludes{"JSXPathNSResolver.h"} = 1; $implIncludes{"JSCustomXPathNSResolver.h"} = 1; + } elsif ($isCallback) { + $implIncludes{"JS${type}.h"} = 1; } else { # default, include the same named file $implIncludes{"${type}.h"} = 1; @@ -290,6 +317,29 @@ sub prototypeHashTableAccessor } } +sub GenerateConditionalStringFromAttributeValue +{ + my $conditional = shift; + if ($conditional =~ /&/) { + return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; + } elsif ($conditional =~ /\|/) { + return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")"; + } else { + return "ENABLE(" . $conditional . ")"; + } +} + +sub GenerateConditionalString +{ + my $node = shift; + my $conditional = $node->extendedAttributes->{"Conditional"}; + if ($conditional) { + return GenerateConditionalStringFromAttributeValue($conditional); + } else { + return ""; + } +} + sub GenerateGetOwnPropertySlotBody { my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_; @@ -475,6 +525,36 @@ sub GenerateGetOwnPropertyDescriptorBody return @getOwnPropertyDescriptorImpl; } +sub GenerateHeaderContentHeader +{ + my $dataNode = shift; + my $className = "JS" . $dataNode->name; + + my @headerContentHeader = split("\r", $headerTemplate); + + # - Add header protection + push(@headerContentHeader, "\n#ifndef $className" . "_h"); + push(@headerContentHeader, "\n#define $className" . "_h\n\n"); + + my $conditionalString = GenerateConditionalString($dataNode); + push(@headerContentHeader, "#if ${conditionalString}\n\n") if $conditionalString; + return @headerContentHeader; +} + +sub GenerateImplementationContentHeader +{ + my $dataNode = shift; + my $className = "JS" . $dataNode->name; + + my @implContentHeader = split("\r", $headerTemplate); + + push(@implContentHeader, "\n#include \"config.h\"\n"); + my $conditionalString = GenerateConditionalString($dataNode); + push(@implContentHeader, "\n#if ${conditionalString}\n\n") if $conditionalString; + push(@implContentHeader, "#include \"$className.h\"\n\n"); + return @implContentHeader; +} + sub GenerateHeader { my $object = shift; @@ -496,22 +576,11 @@ sub GenerateHeader my $hasRealParent = @{$dataNode->parents} > 0; my $hasParent = $hasLegacyParent || $hasRealParent; my $parentClassName = GetParentClassName($dataNode); - my $conditional = $dataNode->extendedAttributes->{"Conditional"}; my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"}; my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"}; - # - Add default header template - @headerContentHeader = split("\r", $headerTemplate); - - # - Add header protection - push(@headerContentHeader, "\n#ifndef $className" . "_h"); - push(@headerContentHeader, "\n#define $className" . "_h\n\n"); - - my $conditionalString; - if ($conditional) { - $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; - push(@headerContentHeader, "#if ${conditionalString}\n\n"); - } + # - Add default header template and header protection + push(@headerContentHeader, GenerateHeaderContentHeader($dataNode)); if ($hasParent) { $headerIncludes{"$parentClassName.h"} = 1; @@ -905,8 +974,9 @@ sub GenerateHeader } } + my $conditionalString = GenerateConditionalString($dataNode); push(@headerContent, "\n} // namespace WebCore\n\n"); - push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditional; + push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString; push(@headerContent, "#endif\n"); # - Generate dependencies. @@ -916,6 +986,73 @@ sub GenerateHeader } } +sub GenerateAttributesHashTable($$) +{ + my ($object, $dataNode) = @_; + + # FIXME: These should be functions on $dataNode. + my $interfaceName = $dataNode->name; + my $className = "JS$interfaceName"; + + # - Add all attributes in a hashtable definition + my $numAttributes = @{$dataNode->attributes}; + $numAttributes++ if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})); + + return 0 if !$numAttributes; + + my $hashSize = $numAttributes; + my $hashName = $className . "Table"; + + my @hashKeys = (); + my @hashSpecials = (); + my @hashValue1 = (); + my @hashValue2 = (); + my %conditionals = (); + + my @entries = (); + + foreach my $attribute (@{$dataNode->attributes}) { + my $name = $attribute->signature->name; + push(@hashKeys, $name); + + my @specials = (); + push(@specials, "DontDelete") unless $attribute->signature->extendedAttributes->{"Deletable"}; + push(@specials, "DontEnum") if $attribute->signature->extendedAttributes->{"DontEnum"}; + push(@specials, "ReadOnly") if $attribute->type =~ /readonly/; + my $special = (@specials > 0) ? join("|", @specials) : "0"; + push(@hashSpecials, $special); + + my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); + push(@hashValue1, $getter); + + if ($attribute->type =~ /readonly/) { + push(@hashValue2, "0"); + } else { + my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); + push(@hashValue2, $setter); + } + + my $conditional = $attribute->signature->extendedAttributes->{"Conditional"}; + if ($conditional) { + $conditionals{$name} = $conditional; + } + } + + if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { + push(@hashKeys, "constructor"); + my $getter = "js" . $interfaceName . "Constructor"; + push(@hashValue1, $getter); + push(@hashValue2, "0"); + push(@hashSpecials, "DontEnum|ReadOnly"); # FIXME: Setting the constructor should be possible. + } + + $object->GenerateHashTable($hashName, $hashSize, + \@hashKeys, \@hashSpecials, + \@hashValue1, \@hashValue2, + \%conditionals); + return $numAttributes; +} + sub GenerateImplementation { my ($object, $dataNode) = @_; @@ -928,21 +1065,12 @@ sub GenerateImplementation my $hasRealParent = @{$dataNode->parents} > 0; my $hasParent = $hasLegacyParent || $hasRealParent; my $parentClassName = GetParentClassName($dataNode); - my $conditional = $dataNode->extendedAttributes->{"Conditional"}; my $visibleClassName = GetVisibleClassName($interfaceName); my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"}; my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"}; # - Add default header template - @implContentHeader = split("\r", $headerTemplate); - - push(@implContentHeader, "\n#include \"config.h\"\n"); - my $conditionalString; - if ($conditional) { - $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; - push(@implContentHeader, "\n#if ${conditionalString}\n\n"); - } - push(@implContentHeader, "#include \"$className.h\"\n\n"); + push(@implContentHeader, GenerateImplementationContentHeader($dataNode)); AddIncludesForSVGAnimatedType($interfaceName) if $className =~ /^JSSVGAnimated/; @@ -958,62 +1086,7 @@ sub GenerateImplementation push(@implContent, "ASSERT_CLASS_FITS_IN_CELL($className);\n\n"); - # - Add all attributes in a hashtable definition - my $numAttributes = @{$dataNode->attributes}; - $numAttributes++ if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})); - - if ($numAttributes > 0) { - my $hashSize = $numAttributes; - my $hashName = $className . "Table"; - - my @hashKeys = (); - my @hashSpecials = (); - my @hashValue1 = (); - my @hashValue2 = (); - my %conditionals = (); - - my @entries = (); - - foreach my $attribute (@{$dataNode->attributes}) { - my $name = $attribute->signature->name; - push(@hashKeys, $name); - - my @specials = (); - push(@specials, "DontDelete") unless $attribute->signature->extendedAttributes->{"Deletable"}; - push(@specials, "DontEnum") if $attribute->signature->extendedAttributes->{"DontEnum"}; - push(@specials, "ReadOnly") if $attribute->type =~ /readonly/; - my $special = (@specials > 0) ? join("|", @specials) : "0"; - push(@hashSpecials, $special); - - my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); - push(@hashValue1, $getter); - - if ($attribute->type =~ /readonly/) { - push(@hashValue2, "0"); - } else { - my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); - push(@hashValue2, $setter); - } - - my $conditional = $attribute->signature->extendedAttributes->{"Conditional"}; - if ($conditional) { - $conditionals{$name} = $conditional; - } - } - - if (!($dataNode->extendedAttributes->{"OmitConstructor"} || $dataNode->extendedAttributes->{"CustomConstructor"})) { - push(@hashKeys, "constructor"); - my $getter = "js" . $interfaceName . "Constructor"; - push(@hashValue1, $getter); - push(@hashValue2, "0"); - push(@hashSpecials, "DontEnum|ReadOnly"); # FIXME: Setting the constructor should be possible. - } - - $object->GenerateHashTable($hashName, $hashSize, - \@hashKeys, \@hashSpecials, - \@hashValue1, \@hashValue2, - \%conditionals); - } + my $numAttributes = GenerateAttributesHashTable($object, $dataNode); my $numConstants = @{$dataNode->constants}; my $numFunctions = @{$dataNode->functions}; @@ -1044,7 +1117,7 @@ sub GenerateImplementation my $protoClassName; $protoClassName = "${className}Prototype"; - push(@implContent, constructorFor($className, $protoClassName, $interfaceName, $visibleClassName, $dataNode->extendedAttributes->{"CanBeConstructed"})); + push(@implContent, constructorFor($className, $protoClassName, $interfaceName, $visibleClassName, $dataNode)); } # - Add functions and constants to a hashtable definition @@ -1305,11 +1378,8 @@ sub GenerateImplementation my $getFunctionName = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); my $implGetterFunctionName = $codeGenerator->WK_lcfirst($name); - my $conditional = $attribute->signature->extendedAttributes->{"Conditional"}; - if ($conditional) { - $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; - push(@implContent, "#if ${conditionalString}\n"); - } + my $attributeConditionalString = GenerateConditionalString($attribute->signature); + push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString; push(@implContent, "JSValue ${getFunctionName}(ExecState* exec, JSValue slotBase, const Identifier&)\n"); push(@implContent, "{\n"); @@ -1417,9 +1487,7 @@ sub GenerateImplementation push(@implContent, "}\n"); - if ($conditional) { - push(@implContent, "#endif\n"); - } + push(@implContent, "#endif\n") if $attributeConditionalString; push(@implContent, "\n"); } @@ -1486,11 +1554,8 @@ sub GenerateImplementation my $putFunctionName = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : ""); my $implSetterFunctionName = $codeGenerator->WK_ucfirst($name); - my $conditional = $attribute->signature->extendedAttributes->{"Conditional"}; - if ($conditional) { - $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; - push(@implContent, "#if ${conditionalString}\n"); - } + my $attributeConditionalString = GenerateConditionalString($attribute->signature); + push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString; push(@implContent, "void ${putFunctionName}(ExecState* exec, JSObject* thisObject, JSValue value)\n"); push(@implContent, "{\n"); @@ -1537,8 +1602,8 @@ sub GenerateImplementation push(@implContent, " // Shadowing a built-in object\n"); push(@implContent, " static_cast<$className*>(thisObject)->putDirect(Identifier(exec, \"$name\"), value);\n"); } else { - push(@implContent, " $className* castedThisObj = static_cast<$className*>(thisObject);\n"); - push(@implContent, " $implType* imp = static_cast<$implType*>(castedThisObj->impl());\n"); + push(@implContent, " $className* castedThis = static_cast<$className*>(thisObject);\n"); + push(@implContent, " $implType* imp = static_cast<$implType*>(castedThis->impl());\n"); if ($podType) { push(@implContent, " $podType podImp(*imp);\n"); if ($podType eq "float") { # Special case for JSSVGNumber @@ -1546,7 +1611,7 @@ sub GenerateImplementation } else { push(@implContent, " podImp.set$implSetterFunctionName(" . JSValueToNative($attribute->signature, "value") . ");\n"); } - push(@implContent, " imp->commitChange(podImp, castedThisObj);\n"); + push(@implContent, " imp->commitChange(podImp, castedThis);\n"); } else { my $nativeValue = JSValueToNative($attribute->signature, "value"); push(@implContent, " ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions}; @@ -1564,16 +1629,14 @@ sub GenerateImplementation push(@implContent, ");\n"); push(@implContent, " setDOMException(exec, ec);\n") if @{$attribute->setterExceptions}; if (IsSVGTypeNeedingContextParameter($implClassName)) { - push(@implContent, " JSSVGContextCache::propagateSVGDOMChange(castedThisObj, imp->associatedAttributeName());\n"); + push(@implContent, " JSSVGContextCache::propagateSVGDOMChange(castedThis, imp->associatedAttributeName());\n"); } } } push(@implContent, "}\n"); - if ($conditional) { - push(@implContent, "#endif\n"); - } + push(@implContent, "#endif\n") if $attributeConditionalString; push(@implContent, "\n"); } @@ -1614,22 +1677,22 @@ sub GenerateImplementation $implIncludes{"<runtime/Error.h>"} = 1; if ($interfaceName eq "DOMWindow") { - push(@implContent, " $className* castedThisObj = toJSDOMWindow(thisValue.toThisObject(exec));\n"); - push(@implContent, " if (!castedThisObj)\n"); + push(@implContent, " $className* castedThis = toJSDOMWindow(thisValue.toThisObject(exec));\n"); + push(@implContent, " if (!castedThis)\n"); push(@implContent, " return throwError(exec, TypeError);\n"); } elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) { - push(@implContent, " $className* castedThisObj = to${className}(thisValue.toThisObject(exec));\n"); - push(@implContent, " if (!castedThisObj)\n"); + push(@implContent, " $className* castedThis = to${className}(thisValue.toThisObject(exec));\n"); + push(@implContent, " if (!castedThis)\n"); push(@implContent, " return throwError(exec, TypeError);\n"); } else { push(@implContent, " if (!thisValue.inherits(&${className}::s_info))\n"); push(@implContent, " return throwError(exec, TypeError);\n"); - push(@implContent, " $className* castedThisObj = static_cast<$className*>(asObject(thisValue));\n"); + push(@implContent, " $className* castedThis = static_cast<$className*>(asObject(thisValue));\n"); } if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) { - push(@implContent, " if (!castedThisObj->allowsAccessFrom(exec))\n"); + push(@implContent, " if (!castedThis->allowsAccessFrom(exec))\n"); push(@implContent, " return jsUndefined();\n"); } @@ -1649,14 +1712,14 @@ sub GenerateImplementation } if ($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"JSCCustom"}) { - push(@implContent, " return castedThisObj->" . $functionImplementationName . "(exec, args);\n"); + push(@implContent, " return castedThis->" . $functionImplementationName . "(exec, args);\n"); } elsif ($svgPODListType) { $implIncludes{"JS${svgPODListType}.h"} = 1; $implIncludes{"JSSVGPODListCustom.h"} = 1; push(@implContent, " return JSSVGPODListCustom::$functionImplementationName<$className, " . GetNativeType($svgPODListType) - . ">(castedThisObj, exec, args, to" . $svgPODListType . ");\n"); + . ">(castedThis, exec, args, to" . $svgPODListType . ");\n"); } else { - push(@implContent, " $implType* imp = static_cast<$implType*>(castedThisObj->impl());\n"); + push(@implContent, " $implType* imp = static_cast<$implType*>(castedThis->impl());\n"); push(@implContent, " $podType podImp(*imp);\n") if $podType; my $numParameters = @{$function->parameters}; @@ -1676,72 +1739,94 @@ sub GenerateImplementation $implIncludes{"JSDOMBinding.h"} = 1; } - my $paramIndex = 0; - my $functionString = ($podType ? "podImp." : "imp->") . $functionImplementationName . "("; + if ($function->signature->name eq "addEventListener") { + push(@implContent, GenerateEventListenerCall($className, "add")); + } elsif ($function->signature->name eq "removeEventListener") { + push(@implContent, GenerateEventListenerCall($className, "remove")); + } else { + my $paramIndex = 0; + my $functionString = ($podType ? "podImp." : "imp->") . $functionImplementationName . "("; - my $hasOptionalArguments = 0; + my $hasOptionalArguments = 0; - if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) { - push(@implContent, " ScriptCallStack callStack(exec, args, $numParameters);\n"); - $implIncludes{"ScriptCallStack.h"} = 1; - } - - foreach my $parameter (@{$function->parameters}) { - if (!$hasOptionalArguments && $parameter->extendedAttributes->{"Optional"}) { - push(@implContent, "\n int argsCount = args.size();\n"); - $hasOptionalArguments = 1; + if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) { + push(@implContent, " ScriptCallStack callStack(exec, args, $numParameters);\n"); + $implIncludes{"ScriptCallStack.h"} = 1; } - if ($hasOptionalArguments) { - push(@implContent, " if (argsCount < " . ($paramIndex + 1) . ") {\n"); - GenerateImplementationFunctionCall($function, $functionString, $paramIndex, " " x 2, $podType, $implClassName); - push(@implContent, " }\n\n"); + my $callWith = $function->signature->extendedAttributes->{"CallWith"}; + if ($callWith) { + my $callWithArg = "COMPILE_ASSERT(false)"; + if ($callWith eq "DynamicFrame") { + push(@implContent, " Frame* dynamicFrame = toDynamicFrame(exec);\n"); + push(@implContent, " if (!dynamicFrame)\n"); + push(@implContent, " return jsUndefined();\n"); + $callWithArg = "dynamicFrame"; + } elsif ($callWith eq "ScriptState") { + $callWithArg = "exec"; + } + $functionString .= ", " if $paramIndex; + $functionString .= $callWithArg; + $paramIndex++; } - my $name = $parameter->name; + foreach my $parameter (@{$function->parameters}) { + if (!$hasOptionalArguments && $parameter->extendedAttributes->{"Optional"}) { + push(@implContent, "\n int argsCount = args.size();\n"); + $hasOptionalArguments = 1; + } + + if ($hasOptionalArguments) { + push(@implContent, " if (argsCount < " . ($paramIndex + 1) . ") {\n"); + GenerateImplementationFunctionCall($function, $functionString, $paramIndex, " " x 2, $podType, $implClassName); + push(@implContent, " }\n\n"); + } + + my $name = $parameter->name; - if ($parameter->type eq "XPathNSResolver") { - push(@implContent, " RefPtr<XPathNSResolver> customResolver;\n"); - push(@implContent, " XPathNSResolver* resolver = toXPathNSResolver(args.at($paramIndex));\n"); - push(@implContent, " if (!resolver) {\n"); - push(@implContent, " customResolver = JSCustomXPathNSResolver::create(exec, args.at($paramIndex));\n"); - push(@implContent, " if (exec->hadException())\n"); - push(@implContent, " return jsUndefined();\n"); - push(@implContent, " resolver = customResolver.get();\n"); - push(@implContent, " }\n"); - } else { - push(@implContent, " " . GetNativeTypeFromSignature($parameter) . " $name = " . JSValueToNative($parameter, "args.at($paramIndex)") . ";\n"); - - # If a parameter is "an index" and it's negative it should throw an INDEX_SIZE_ERR exception. - # But this needs to be done in the bindings, because the type is unsigned and the fact that it - # was negative will be lost by the time we're inside the DOM. - if ($parameter->extendedAttributes->{"IsIndex"}) { - $implIncludes{"ExceptionCode.h"} = 1; - push(@implContent, " if ($name < 0) {\n"); - push(@implContent, " setDOMException(exec, INDEX_SIZE_ERR);\n"); - push(@implContent, " return jsUndefined();\n"); + if ($parameter->type eq "XPathNSResolver") { + push(@implContent, " RefPtr<XPathNSResolver> customResolver;\n"); + push(@implContent, " XPathNSResolver* resolver = toXPathNSResolver(args.at($paramIndex));\n"); + push(@implContent, " if (!resolver) {\n"); + push(@implContent, " customResolver = JSCustomXPathNSResolver::create(exec, args.at($paramIndex));\n"); + push(@implContent, " if (exec->hadException())\n"); + push(@implContent, " return jsUndefined();\n"); + push(@implContent, " resolver = customResolver.get();\n"); push(@implContent, " }\n"); + } else { + push(@implContent, " " . GetNativeTypeFromSignature($parameter) . " $name = " . JSValueToNative($parameter, "args.at($paramIndex)") . ";\n"); + + # If a parameter is "an index" and it's negative it should throw an INDEX_SIZE_ERR exception. + # But this needs to be done in the bindings, because the type is unsigned and the fact that it + # was negative will be lost by the time we're inside the DOM. + if ($parameter->extendedAttributes->{"IsIndex"}) { + $implIncludes{"ExceptionCode.h"} = 1; + push(@implContent, " if ($name < 0) {\n"); + push(@implContent, " setDOMException(exec, INDEX_SIZE_ERR);\n"); + push(@implContent, " return jsUndefined();\n"); + push(@implContent, " }\n"); + } } - } - $functionString .= ", " if $paramIndex; + $functionString .= ", " if $paramIndex; - if ($parameter->type eq "NodeFilter") { - $functionString .= "$name.get()"; - } else { - $functionString .= $name; + if ($parameter->type eq "NodeFilter") { + $functionString .= "$name.get()"; + } else { + $functionString .= $name; + } + $paramIndex++; } - $paramIndex++; - } - if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) { - $functionString .= ", " if $paramIndex; - $functionString .= "processingUserGesture(exec)"; - $paramIndex++; - } + if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) { + $functionString .= ", " if $paramIndex; + $functionString .= "processingUserGesture(exec)"; + $paramIndex++; + } - push(@implContent, "\n"); - GenerateImplementationFunctionCall($function, $functionString, $paramIndex, " ", $podType, $implClassName); + push(@implContent, "\n"); + GenerateImplementationFunctionCall($function, $functionString, $paramIndex, " ", $podType, $implClassName); + } } push(@implContent, "}\n\n"); } @@ -1827,7 +1912,156 @@ sub GenerateImplementation push(@implContent, "\n}\n"); - push(@implContent, "\n#endif // ${conditionalString}\n") if $conditional; + my $conditionalString = GenerateConditionalString($dataNode); + push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; +} + +sub GenerateCallbackHeader +{ + my $object = shift; + my $dataNode = shift; + + my $interfaceName = $dataNode->name; + my $className = "JS$interfaceName"; + + # - Add default header template and header protection + push(@headerContentHeader, GenerateHeaderContentHeader($dataNode)); + + $headerIncludes{"$interfaceName.h"} = 1; + $headerIncludes{"JSCallbackData.h"} = 1; + $headerIncludes{"<wtf/Forward.h>"} = 1; + + push(@headerContent, "\nnamespace WebCore {\n\n"); + push(@headerContent, "class $className : public $interfaceName {\n"); + push(@headerContent, "public:\n"); + + # The static create() method. + push(@headerContent, " static PassRefPtr<$className> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)\n"); + push(@headerContent, " {\n"); + push(@headerContent, " return adoptRef(new $className(callback, globalObject));\n"); + push(@headerContent, " }\n\n"); + + # Destructor + push(@headerContent, " virtual ~$className();\n"); + + # Functions + my $numFunctions = @{$dataNode->functions}; + if ($numFunctions > 0) { + push(@headerContent, "\n // Functions\n"); + foreach my $function (@{$dataNode->functions}) { + my @params = @{$function->parameters}; + if (!$function->signature->extendedAttributes->{"Custom"} && + !(GetNativeType($function->signature->type) eq "bool")) { + push(@headerContent, " COMPILE_ASSERT(false)"); + } + + push(@headerContent, " virtual " . GetNativeType($function->signature->type) . " " . $function->signature->name . "(ScriptExecutionContext*"); + foreach my $param (@params) { + push(@headerContent, ", " . GetNativeType($param->type) . " " . $param->name); + } + + push(@headerContent, ");\n"); + } + } + + push(@headerContent, "\nprivate:\n"); + + # Constructor + push(@headerContent, " $className(JSC::JSObject* callback, JSDOMGlobalObject*);\n\n"); + + # Private members + push(@headerContent, " JSCallbackData* m_data;\n"); + push(@headerContent, " RefPtr<DOMWrapperWorld> m_isolatedWorld;\n"); + push(@headerContent, "};\n\n"); + + push(@headerContent, "} // namespace WebCore\n\n"); + my $conditionalString = GenerateConditionalString($dataNode); + push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString; + push(@headerContent, "#endif\n"); +} + +sub GenerateCallbackImplementation +{ + my ($object, $dataNode) = @_; + + my $interfaceName = $dataNode->name; + my $className = "JS$interfaceName"; + + # - Add default header template + push(@implContentHeader, GenerateImplementationContentHeader($dataNode)); + + $implIncludes{"ScriptExecutionContext.h"} = 1; + $implIncludes{"<runtime/JSLock.h>"} = 1; + $implIncludes{"<wtf/MainThread.h>"} = 1; + + @implContent = (); + + push(@implContent, "\nusing namespace JSC;\n\n"); + push(@implContent, "namespace WebCore {\n\n"); + + # Constructor + push(@implContent, "${className}::${className}(JSObject* callback, JSDOMGlobalObject* globalObject)\n"); + push(@implContent, " : m_data(new JSCallbackData(callback, globalObject))\n"); + push(@implContent, " , m_isolatedWorld(globalObject->world())\n"); + push(@implContent, "{\n"); + push(@implContent, "}\n\n"); + + # Destructor + push(@implContent, "${className}::~${className}()\n"); + push(@implContent, "{\n"); + push(@implContent, " callOnMainThread(JSCallbackData::deleteData, m_data);\n"); + push(@implContent, "#ifndef NDEBUG\n"); + push(@implContent, " m_data = 0;\n"); + push(@implContent, "#endif\n"); + push(@implContent, "}\n"); + + # Functions + my $numFunctions = @{$dataNode->functions}; + if ($numFunctions > 0) { + push(@implContent, "\n// Functions\n"); + foreach my $function (@{$dataNode->functions}) { + my @params = @{$function->parameters}; + if ($function->signature->extendedAttributes->{"Custom"} || + !(GetNativeType($function->signature->type) eq "bool")) { + next; + } + + AddIncludesForType($function->signature->type); + push(@implContent, "\n" . GetNativeType($function->signature->type) . " ${className}::" . $function->signature->name . "(ScriptExecutionContext* context"); + + foreach my $param (@params) { + AddIncludesForType($param->type, 1); + push(@implContent, ", " . GetNativeType($param->type) . " " . $param->name); + } + + push(@implContent, ")\n"); + + push(@implContent, "{\n"); + push(@implContent, " ASSERT(m_data);\n"); + push(@implContent, " ASSERT(context);\n\n"); + push(@implContent, " RefPtr<$className> protect(this);\n\n"); + push(@implContent, " JSLock lock(SilenceAssertionsOnly);\n\n"); + push(@implContent, " JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get());\n"); + push(@implContent, " if (!globalObject)\n"); + push(@implContent, " return true;\n\n"); + push(@implContent, " ExecState* exec = globalObject->globalExec();\n"); + push(@implContent, " MarkedArgumentBuffer args;\n"); + + foreach my $param (@params) { + my $paramName = $param->name; + push(@implContent, " args.append(toJS(exec, ${paramName}));\n"); + } + + push(@implContent, "\n bool raisedException = false;\n"); + push(@implContent, " m_data->invokeCallback(args, &raisedException);\n"); + push(@implContent, " return !raisedException;\n"); + push(@implContent, "}\n"); + } + } + + push(@implContent, "\n}\n"); + my $conditionalString = GenerateConditionalString($dataNode); + push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; } sub GenerateImplementationFunctionCall() @@ -1854,16 +2088,22 @@ sub GenerateImplementationFunctionCall() if ($function->signature->type eq "void") { push(@implContent, $indent . "$functionString;\n"); push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions}; - push(@implContent, $indent . "imp->commitChange(podImp, castedThisObj);\n") if $podType; + push(@implContent, $indent . "imp->commitChange(podImp, castedThis);\n") if $podType; push(@implContent, $indent . "return jsUndefined();\n"); } else { - push(@implContent, "\n" . $indent . "JSC::JSValue result = " . NativeToJSValue($function->signature, 1, $implClassName, "", $functionString, "castedThisObj") . ";\n"); + push(@implContent, "\n" . $indent . "JSC::JSValue result = " . NativeToJSValue($function->signature, 1, $implClassName, "", $functionString, "castedThis") . ";\n"); push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions}; + $callWith = $function->signature->extendedAttributes->{"CallWith"}; + if ($callWith and $callWith eq "ScriptState") { + push(@implContent, $indent . "if (exec->hadException())\n"); + push(@implContent, $indent . " return jsUndefined();\n"); + } + if ($podType and not $function->signature->extendedAttributes->{"Immutable"}) { # Immutable methods do not commit changes back to the instance, thus producing # a new instance rather than mutating existing one. - push(@implContent, $indent . "imp->commitChange(podImp, castedThisObj);\n"); + push(@implContent, $indent . "imp->commitChange(podImp, castedThis);\n"); } push(@implContent, $indent . "return result;\n"); @@ -1888,6 +2128,7 @@ my %nativeType = ( "DOMString" => "const String&", "DOMObject" => "ScriptValue", "NodeFilter" => "RefPtr<NodeFilter>", + "SerializedScriptValue" => "RefPtr<SerializedScriptValue>", "SVGAngle" => "SVGAngle", "SVGLength" => "SVGLength", "SVGMatrix" => "AffineTransform", @@ -1992,6 +2233,8 @@ sub NativeToJSValue die "Unknown value for ConvertNullStringTo extended attribute"; } + $conv = $signature->extendedAttributes->{"ConvertScriptString"}; + return "jsOwnedStringOrNull(exec, $value)" if $conv; $implIncludes{"<runtime/JSString.h>"} = 1; return "jsString(exec, $value)"; } @@ -2181,6 +2424,11 @@ tableSizeLoop: # Dump the hash table my $count = scalar @{$keys} + 1; + push(@implContent, "#if ENABLE(JIT)\n"); + push(@implContent, "#define THUNK_GENERATOR(generator) , generator\n"); + push(@implContent, "#else\n"); + push(@implContent, "#define THUNK_GENERATOR(generator)\n"); + push(@implContent, "#endif\n"); push(@implContent, "\nstatic const HashTableValue $nameEntries\[$count\] =\n\{\n"); $i = 0; foreach my $key (@{$keys}) { @@ -2191,7 +2439,7 @@ tableSizeLoop: $conditional = $conditionals->{$key}; } if ($conditional) { - my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; + my $conditionalString = GenerateConditionalStringFromAttributeValue($conditional); push(@implContent, "#if ${conditionalString}\n"); } @@ -2200,14 +2448,15 @@ tableSizeLoop: } else { $targetType = "static_cast<PropertySlot::GetValueFunc>"; } - push(@implContent, " { \"$key\", @$specials[$i], (intptr_t)" . $targetType . "(@$value1[$i]), (intptr_t)@$value2[$i] },\n"); + push(@implContent, " { \"$key\", @$specials[$i], (intptr_t)" . $targetType . "(@$value1[$i]), (intptr_t)@$value2[$i] THUNK_GENERATOR(0) },\n"); if ($conditional) { push(@implContent, "#endif\n"); } ++$i; } - push(@implContent, " { 0, 0, 0, 0 }\n"); + push(@implContent, " { 0, 0, 0, 0 THUNK_GENERATOR(0) }\n"); push(@implContent, "};\n\n"); + push(@implContent, "#undef THUNK_GENERATOR\n"); my $perfectSizeMask = $perfectSize - 1; my $compactSizeMask = $numEntries - 1; push(@implContent, "static JSC_CONST_HASHTABLE HashTable $name =\n"); @@ -2350,8 +2599,10 @@ sub constructorFor my $protoClassName = shift; my $interfaceName = shift; my $visibleClassName = shift; - my $canConstruct = shift; + my $dataNode = shift; my $constructorClassName = "${className}Constructor"; + my $canConstruct = $dataNode->extendedAttributes->{"CanBeConstructed"}; + my $callWith = $dataNode->extendedAttributes->{"CallWith"}; my $implContent = << "EOF"; class ${constructorClassName} : public DOMConstructorObject { @@ -2379,7 +2630,20 @@ EOF $implContent .= << "EOF"; static JSObject* construct${interfaceName}(ExecState* exec, JSObject* constructor, const ArgList&) { - return asObject(toJS(exec, static_cast<${constructorClassName}*>(constructor)->globalObject(), ${interfaceName}::create())); +EOF + + my $constructorArg = ""; + if ($callWith and $callWith eq "ScriptExecutionContext") { + $constructorArg = "context"; +$implContent .= << "EOF"; + ScriptExecutionContext* context = static_cast<${constructorClassName}*>(constructor)->scriptExecutionContext(); + if (!context) + return throwError(exec, ReferenceError); +EOF + } + +$implContent .= << "EOF"; + return asObject(toJS(exec, static_cast<${constructorClassName}*>(constructor)->globalObject(), ${interfaceName}::create(${constructorArg}))); } virtual ConstructType getConstructData(ConstructData& constructData) { diff --git a/WebCore/bindings/scripts/CodeGeneratorObjC.pm b/WebCore/bindings/scripts/CodeGeneratorObjC.pm index 3c5fe45..7132e22 100644 --- a/WebCore/bindings/scripts/CodeGeneratorObjC.pm +++ b/WebCore/bindings/scripts/CodeGeneratorObjC.pm @@ -269,6 +269,23 @@ sub ReadPublicInterfaces $interfaceAvailabilityVersion = "WEBKIT_VERSION_LATEST" if $newPublicClass; } +sub GenerateConditionalString +{ + my $node = shift; + my $conditional = $node->extendedAttributes->{"Conditional"}; + if ($conditional) { + if ($conditional =~ /&/) { + return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; + } elsif ($conditional =~ /\|/) { + return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")"; + } else { + return "ENABLE(" . $conditional . ")"; + } + } else { + return ""; + } +} + # Params: 'domClass' struct sub GenerateInterface { @@ -1014,7 +1031,6 @@ sub GenerateImplementation my $implClassNameWithNamespace = "WebCore::" . $implClassName; my $baseClass = GetBaseClass($parentImplClassName); my $classHeaderName = GetClassHeaderName($className); - my $conditional = $dataNode->extendedAttributes->{"Conditional"}; my $numAttributes = @{$dataNode->attributes}; my $numFunctions = @{$dataNode->functions}; @@ -1032,11 +1048,8 @@ sub GenerateImplementation # - INCLUDES - push(@implContentHeader, "\n#import \"config.h\"\n"); - my $conditionalString; - if ($conditional) { - $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; - push(@implContentHeader, "\n#if ${conditionalString}\n\n"); - } + my $conditionalString = GenerateConditionalString($dataNode); + push(@implContentHeader, "\n#if ${conditionalString}\n\n") if $conditionalString; push(@implContentHeader, "#import \"DOMInternal.h\"\n\n"); push(@implContentHeader, "#import \"$classHeaderName.h\"\n\n"); @@ -1585,7 +1598,7 @@ sub GenerateImplementation } # - End the ifdef conditional if necessary - push(@implContent, "\n#endif // ${conditionalString}\n") if $conditional; + push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; # - Generate dependencies. if ($writeDependencies && @ancestorInterfaceNames) { diff --git a/WebCore/bindings/scripts/CodeGeneratorV8.pm b/WebCore/bindings/scripts/CodeGeneratorV8.pm index 1c5f398..9553b8b 100644 --- a/WebCore/bindings/scripts/CodeGeneratorV8.pm +++ b/WebCore/bindings/scripts/CodeGeneratorV8.pm @@ -99,8 +99,13 @@ sub GenerateInterface my $defines = shift; # Start actual generation - $object->GenerateHeader($dataNode); - $object->GenerateImplementation($dataNode); + if ($dataNode->extendedAttributes->{"Callback"}) { + $object->GenerateCallbackHeader($dataNode); + $object->GenerateCallbackImplementation($dataNode); + } else { + $object->GenerateHeader($dataNode); + $object->GenerateImplementation($dataNode); + } my $name = $dataNode->name; @@ -189,7 +194,13 @@ sub GenerateConditionalString my $node = shift; my $conditional = $node->extendedAttributes->{"Conditional"}; if ($conditional) { - return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; + if ($conditional =~ /&/) { + return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; + } elsif ($conditional =~ /\|/) { + return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")"; + } else { + return "ENABLE(" . $conditional . ")"; + } } else { return ""; } @@ -226,14 +237,9 @@ sub GenerateHeader $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1); my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; - my $conditionalString = GenerateConditionalString($dataNode); # - Add default header template - @headerContent = split("\r", $headerTemplate); - - push(@headerContent, "\n#if ${conditionalString}\n\n") if $conditionalString; - push(@headerContent, "\n#ifndef $className" . "_h"); - push(@headerContent, "\n#define $className" . "_h\n\n"); + push(@headerContent, GenerateHeaderContentHeader($dataNode)); # Get correct pass/store types respecting PODType flag my $podType = $dataNode->extendedAttributes->{"PODType"}; @@ -351,6 +357,7 @@ END push(@headerContent, "}\n\n"); push(@headerContent, "#endif // $className" . "_h\n"); + my $conditionalString = GenerateConditionalString($dataNode); push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString; } @@ -1218,7 +1225,8 @@ END if ($parameter->type eq "SerializedScriptValue") { push(@implContentDecls, "SerializedScriptValue::create(args[$paramIndex], ${parameterName}DidThrow);\n"); - push(@implContentDecls, " if (${parameterName}DidThrow)\n return v8::Undefined();\n"); + push(@implContentDecls, " if (${parameterName}DidThrow)\n"); + push(@implContentDecls, " return v8::Undefined();\n"); } else { push(@implContentDecls, JSValueToNative($parameter, "args[$paramIndex]", BasicTypeCanFailConversion($parameter) ? "${parameterName}Ok" : undef) . ";\n"); @@ -1570,16 +1578,9 @@ sub GenerateImplementation my $implClassName = $interfaceName; my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; - my $conditionalString = GenerateConditionalString($dataNode); # - Add default header template - @implContentHeader = split("\r", $headerTemplate); - - push(@implFixedHeader, - "\n#include \"config.h\"\n" . - "#include \"${className}.h\"\n\n"); - - push(@implFixedHeader, "\n#if ${conditionalString}\n\n") if $conditionalString; + push(@implFixedHeader, GenerateImplementationContentHeader($dataNode)); $implIncludes{"RuntimeEnabledFeatures.h"} = 1; $implIncludes{"V8Proxy.h"} = 1; @@ -1780,11 +1781,18 @@ END # In namespace WebCore, add generated implementation for 'CanBeConstructed'. if ($dataNode->extendedAttributes->{"CanBeConstructed"} && !$dataNode->extendedAttributes->{"CustomConstructor"}) { + my $v8ConstructFunction; + my $callWith = $dataNode->extendedAttributes->{"CallWith"}; + if ($callWith and $callWith eq "ScriptExecutionContext") { + $v8ConstructFunction = "constructDOMObjectWithScriptExecutionContext"; + } else { + $v8ConstructFunction = "constructDOMObject"; + } push(@implContent, <<END); v8::Handle<v8::Value> ${className}::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.${interfaceName}.Contructor"); - return V8Proxy::constructDOMObject<$interfaceName>(args, &info); + return V8Proxy::${v8ConstructFunction}<$interfaceName>(args, &info); } END } @@ -2087,6 +2095,7 @@ END } // namespace WebCore END + my $conditionalString = GenerateConditionalString($dataNode); push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; # We've already added the header for this file in implFixedHeader, so remove @@ -2094,6 +2103,190 @@ END delete $implIncludes{"${className}.h"}; } +sub GenerateHeaderContentHeader +{ + my $dataNode = shift; + my $className = "V8" . $dataNode->name; + my $conditionalString = GenerateConditionalString($dataNode); + + my @headerContentHeader = split("\r", $headerTemplate); + + push(@headerContentHeader, "\n#if ${conditionalString}\n") if $conditionalString; + push(@headerContentHeader, "\n#ifndef ${className}" . "_h"); + push(@headerContentHeader, "\n#define ${className}" . "_h\n\n"); + return @headerContentHeader; +} + +sub GenerateImplementationContentHeader +{ + my $dataNode = shift; + my $className = "V8" . $dataNode->name; + my $conditionalString = GenerateConditionalString($dataNode); + + my @implContentHeader = split("\r", $headerTemplate); + + push(@implContentHeader, "\n#include \"config.h\"\n"); + push(@implContentHeader, "#include \"${className}.h\"\n\n"); + push(@implContentHeader, "#if ${conditionalString}\n\n") if $conditionalString; + return @implContentHeader; +} + +sub GenerateCallbackHeader +{ + my $object = shift; + my $dataNode = shift; + + my $interfaceName = $dataNode->name; + my $className = "V8$interfaceName"; + + + # - Add default header template + push(@headerContent, GenerateHeaderContentHeader($dataNode)); + + if ("$interfaceName.h" lt "WorldContextHandle.h") { + push(@headerContent, "#include \"$interfaceName.h\"\n"); + push(@headerContent, "#include \"WorldContextHandle.h\"\n"); + } else { + push(@headerContent, "#include \"WorldContextHandle.h\"\n"); + push(@headerContent, "#include \"$interfaceName.h\"\n"); + } + push(@headerContent, "#include <v8.h>\n"); + push(@headerContent, "#include <wtf/Forward.h>\n"); + + push(@headerContent, "\nnamespace WebCore {\n\n"); + push(@headerContent, "class Frame;\n\n"); + push(@headerContent, "class $className : public $interfaceName {\n"); + + push(@headerContent, <<END); +public: + static PassRefPtr<${className}> create(v8::Local<v8::Value> value, Frame* frame) + { + ASSERT(value->IsObject()); + return adoptRef(new ${className}(value->ToObject(), frame)); + } + + virtual ~${className}(); + +END + + # Functions + my $numFunctions = @{$dataNode->functions}; + if ($numFunctions > 0) { + push(@headerContent, " // Functions\n"); + foreach my $function (@{$dataNode->functions}) { + my @params = @{$function->parameters}; + if (!$function->signature->extendedAttributes->{"Custom"} && + !(GetNativeType($function->signature->type) eq "bool")) { + push(@headerContent, " COMPILE_ASSERT(false)"); + } + + push(@headerContent, " virtual " . GetNativeTypeForCallbacks($function->signature->type) . " " . $function->signature->name . "(ScriptExecutionContext*"); + foreach my $param (@params) { + push(@headerContent, ", " . GetNativeTypeForCallbacks($param->type) . " " . $param->name); + } + + push(@headerContent, ");\n"); + } + } + + push(@headerContent, <<END); + +private: + ${className}(v8::Local<v8::Object>, Frame*); + + v8::Persistent<v8::Object> m_callback; + RefPtr<Frame> m_frame; + WorldContextHandle m_worldContext; +}; + +END + + push(@headerContent, "}\n\n"); + push(@headerContent, "#endif // $className" . "_h\n\n"); + + my $conditionalString = GenerateConditionalString($dataNode); + push(@headerContent, "#endif // ${conditionalString}\n") if $conditionalString; +} + +sub GenerateCallbackImplementation +{ + my $object = shift; + my $dataNode = shift; + my $interfaceName = $dataNode->name; + my $className = "V8$interfaceName"; + + # - Add default header template + push(@implFixedHeader, GenerateImplementationContentHeader($dataNode)); + + $implIncludes{"Frame.h"} = 1; + $implIncludes{"ScriptExecutionContext.h"} = 1; + $implIncludes{"V8CustomVoidCallback.h"} = 1; + + push(@implContent, "namespace WebCore {\n\n"); + push(@implContent, <<END); +${className}::${className}(v8::Local<v8::Object> callback, Frame* frame) + : m_callback(v8::Persistent<v8::Object>::New(callback)) + , m_frame(frame) + , m_worldContext(UseCurrentWorld) +{ +} + +${className}::~${className}() +{ + m_callback.Dispose(); +} + +END + + # Functions + my $numFunctions = @{$dataNode->functions}; + if ($numFunctions > 0) { + push(@implContent, "// Functions\n"); + foreach my $function (@{$dataNode->functions}) { + my @params = @{$function->parameters}; + if ($function->signature->extendedAttributes->{"Custom"} || + !(GetNativeTypeForCallbacks($function->signature->type) eq "bool")) { + next; + } + + AddIncludesForType($function->signature->type); + push(@implContent, "\n" . GetNativeTypeForCallbacks($function->signature->type) . " ${className}::" . $function->signature->name . "(ScriptExecutionContext* context"); + + foreach my $param (@params) { + AddIncludesForType($param->type); + push(@implContent, ", " . GetNativeTypeForCallbacks($param->type) . " " . $param->name); + } + + push(@implContent, ")\n"); + push(@implContent, "{\n"); + push(@implContent, " v8::HandleScope handleScope;\n\n"); + push(@implContent, " v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext);\n"); + push(@implContent, " if (v8Context.IsEmpty())\n"); + push(@implContent, " return true;\n\n"); + push(@implContent, " v8::Context::Scope scope(v8Context);\n\n"); + push(@implContent, " v8::Handle<v8::Value> argv[] = {\n"); + + my @argvs = (); + foreach my $param (@params) { + my $paramName = $param->name; + push(@argvs, " toV8(${paramName})"); + } + push(@implContent, join(",\n", @argvs)); + + push(@implContent, "\n };\n\n"); + push(@implContent, " RefPtr<Frame> protect(m_frame);\n\n"); + push(@implContent, " bool callbackReturnValue = false;\n"); + push(@implContent, " return !invokeCallback(m_callback, " . scalar(@params). ", argv, callbackReturnValue);\n"); + push(@implContent, "}\n"); + } + } + + push(@implContent, "\n} // namespace WebCore\n\n"); + + my $conditionalString = GenerateConditionalString($dataNode); + push(@implContent, "#endif // ${conditionalString}\n") if $conditionalString; +} + sub GenerateToV8Converters { my $dataNode = shift; @@ -2326,15 +2519,33 @@ sub GenerateFunctionCallString() $functionString = "listImp->${name}("; } - my $first = 1; my $index = 0; + my $hasScriptState = 0; + + my $callWith = $function->signature->extendedAttributes->{"CallWith"}; + if ($callWith) { + my $callWithArg = "COMPILE_ASSERT(false)"; + if ($callWith eq "DynamicFrame") { + $result .= $indent . "Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext();\n"; + $result .= $indent . "if (!enteredFrame)\n"; + $result .= $indent . " return v8::Undefined();\n"; + $callWithArg = "enteredFrame"; + } elsif ($callWith eq "ScriptState") { + $result .= $indent . "EmptyScriptState state;\n"; + $callWithArg = "&state"; + $hasScriptState = 1; + } + $functionString .= ", " if $index; + $functionString .= $callWithArg; + $index++; + $numberOfParameters++ + } foreach my $parameter (@{$function->parameters}) { if ($index eq $numberOfParameters) { last; } - if ($first) { $first = 0; } - else { $functionString .= ", "; } + $functionString .= ", " if $index; my $paramName = $parameter->name; my $paramType = $parameter->type; @@ -2353,22 +2564,23 @@ sub GenerateFunctionCallString() } if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) { - $functionString .= ", " if not $first; + $functionString .= ", " if $index; $functionString .= "callStack.get()"; - if ($first) { $first = 0; } + $index++; } if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) { - $functionString .= ", " if not $first; + $functionString .= ", " if $index; # FIXME: We need to pass DOMWrapperWorld as a parameter. # See http://trac.webkit.org/changeset/54182 $functionString .= "processingUserGesture()"; - if ($first) { $first = 0; } + $index++; } if (@{$function->raisesExceptions}) { - $functionString .= ", " if not $first; + $functionString .= ", " if $index; $functionString .= "ec"; + $index++; } $functionString .= ")"; @@ -2381,7 +2593,7 @@ sub GenerateFunctionCallString() $result .= $indent . GetNativeType($returnType, 0) . " result = *imp;\n" . $indent . "$functionString;\n"; } elsif ($returnsListItemPodType) { $result .= $indent . "RefPtr<SVGPODListItem<$nativeReturnType> > result = $functionString;\n"; - } elsif (@{$function->raisesExceptions} or $returnsPodType or $isPodType or IsSVGTypeNeedingContextParameter($returnType)) { + } elsif ($hasScriptState or @{$function->raisesExceptions} or $returnsPodType or $isPodType or IsSVGTypeNeedingContextParameter($returnType)) { $result .= $indent . $nativeReturnType . " result = $functionString;\n"; } else { # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary @@ -2390,7 +2602,13 @@ sub GenerateFunctionCallString() } if (@{$function->raisesExceptions}) { - $result .= $indent . "if (UNLIKELY(ec))\n" . $indent . " goto fail;\n"; + $result .= $indent . "if (UNLIKELY(ec))\n"; + $result .= $indent . " goto fail;\n"; + } + + if ($hasScriptState) { + $result .= $indent . "if (state.hadException())\n"; + $result .= $indent . " return throwError(state.exception());\n" } # If the return type is a POD type, separate out the wrapper generation @@ -2537,6 +2755,8 @@ sub GetNativeType # temporary hack return "RefPtr<NodeFilter>" if $type eq "NodeFilter"; + return "RefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue"; + # necessary as resolvers could be constructed on fly. return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver"; @@ -2546,6 +2766,15 @@ sub GetNativeType return "${type}*"; } +sub GetNativeTypeForCallbacks +{ + my $type = shift; + return "const String&" if $type eq "DOMString"; + + # Callbacks use raw pointers, so pass isParameter = 1 + return GetNativeType($type, 1); +} + sub TranslateParameter { my $signature = shift; @@ -2735,6 +2964,7 @@ sub RequiresCustomSignature } +# FIXME: Sort this array. my %non_wrapper_types = ( 'float' => 1, 'double' => 1, @@ -2749,6 +2979,7 @@ my %non_wrapper_types = ( 'unsigned long long' => 1, 'DOMString' => 1, 'CompareHow' => 1, + 'SerializedScriptValue' => 1, 'SVGAngle' => 1, 'SVGRect' => 1, 'SVGPoint' => 1, @@ -2821,6 +3052,8 @@ sub ReturnNativeToJSValue return "return v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned"; return "return v8DateOrNull($value)" if $type eq "Date"; + # long long and unsigned long long are not representable in ECMAScript. + return "return v8::Number::New(static_cast<double>($value))" if $type eq "long long" or $type eq "unsigned long long"; return "return v8::Number::New($value)" if $codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType"; return "return $value.v8Value()" if $nativeType eq "ScriptValue"; @@ -2833,6 +3066,8 @@ sub ReturnNativeToJSValue die "Unknown value for ConvertNullStringTo extended attribute"; } + $conv = $signature->extendedAttributes->{"ConvertScriptString"}; + return "v8StringOrNull(exec, $value)" if $conv; return "return v8String($value)"; } diff --git a/WebCore/bindings/scripts/IDLParser.pm b/WebCore/bindings/scripts/IDLParser.pm index 7db7747..c6742dc 100644 --- a/WebCore/bindings/scripts/IDLParser.pm +++ b/WebCore/bindings/scripts/IDLParser.pm @@ -80,10 +80,11 @@ sub Parse print " | *** Starting to parse $fileName...\n |\n" unless $beQuiet; - open2(\*PP_OUT, \*PP_IN, split(' ', $preprocessor), (map { "-D$_" } split(' ', $defines)), $fileName); + $pid = open2(\*PP_OUT, \*PP_IN, split(' ', $preprocessor), (map { "-D$_" } split(' ', $defines)), $fileName); close PP_IN; my @documentContent = <PP_OUT>; close PP_OUT; + waitpid($pid, 0); my $dataAvailable = 0; diff --git a/WebCore/bindings/scripts/IDLStructure.pm b/WebCore/bindings/scripts/IDLStructure.pm index 6224e54..e060252 100644 --- a/WebCore/bindings/scripts/IDLStructure.pm +++ b/WebCore/bindings/scripts/IDLStructure.pm @@ -96,7 +96,7 @@ $typeNamespaceSelector = '((?:' . $idlId . '*::)*)\s*(' . $idlDataType . '*)'; $exceptionSelector = 'exception\s*(' . $idlIdNs . '*)\s*([a-zA-Z\s{;]*};)'; $exceptionSubSelector = '{\s*' . $supportedTypes . '\s*(' . $idlType . '*)\s*;\s*}'; -$interfaceSelector = 'interface\s*((?:' . $extendedAttributeSyntax . ' )?)(' . $idlIdNs . '*)\s*(?::(\s*[^{]*))?{([a-zA-Z0-9_=\s(),;:\[\]]*)'; +$interfaceSelector = 'interface\s*((?:' . $extendedAttributeSyntax . ' )?)(' . $idlIdNs . '*)\s*(?::(\s*[^{]*))?{([a-zA-Z0-9_=\s(),;:\[\]&\|]*)'; $interfaceMethodSelector = '\s*((?:' . $extendedAttributeSyntax . ' )?)' . $supportedTypes . '\s*(' . $idlIdNs . '*)\s*\(\s*([a-zA-Z0-9:\s,=\[\]]*)'; $interfaceParameterSelector = 'in\s*((?:' . $extendedAttributeSyntax . ' )?)' . $supportedTypes . '\s*(' . $idlIdNs . '*)'; diff --git a/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallback.cpp b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallback.cpp new file mode 100644 index 0000000..6cfec74 --- /dev/null +++ b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallback.cpp @@ -0,0 +1,186 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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 <glib-object.h> +#include "config.h" + +#include <wtf/GetPtr.h> +#include <wtf/RefPtr.h> +#include "ExceptionCode.h" +#include "TestCallback.h" +#include "WebKitDOMBinding.h" +#include "gobject/ConvertToUTF8String.h" +#include "webkit/WebKitDOMClass1.h" +#include "webkit/WebKitDOMClass1Private.h" +#include "webkit/WebKitDOMClass2.h" +#include "webkit/WebKitDOMClass2Private.h" +#include "webkit/WebKitDOMClass3.h" +#include "webkit/WebKitDOMClass3Private.h" +#include "webkit/WebKitDOMTestCallback.h" +#include "webkit/WebKitDOMTestCallbackPrivate.h" +#include "webkitmarshal.h" +#include "webkitprivate.h" + +namespace WebKit { + +gpointer kit(WebCore::TestCallback* obj) +{ + g_return_val_if_fail(obj != 0, 0); + + if (gpointer ret = DOMObjectCache::get(obj)) + return ret; + + return DOMObjectCache::put(obj, WebKit::wrapTestCallback(obj)); +} + +} // namespace WebKit // + +gboolean +webkit_dom_test_callback_callback_with_class1param (WebKitDOMTestCallback *self, WebKitDOMClass1* class1param) +{ + g_return_val_if_fail (self, 0); + WebCore::TestCallback * item = WebKit::core(self); + g_return_val_if_fail (class1param, 0); + WebCore::Class1 * _g_class1param = WebKit::core(class1param); + g_return_val_if_fail (_g_class1param, 0); + gboolean res = item->callbackWithClass1Param(_g_class1param); + return res; + +} + +gboolean +webkit_dom_test_callback_callback_with_class2param (WebKitDOMTestCallback *self, WebKitDOMClass2* class2param, gchar* str_arg) +{ + g_return_val_if_fail (self, 0); + WebCore::TestCallback * item = WebKit::core(self); + g_return_val_if_fail (class2param, 0); + g_return_val_if_fail (str_arg, 0); + WebCore::Class2 * _g_class2param = WebKit::core(class2param); + g_return_val_if_fail (_g_class2param, 0); + WebCore::String _g_str_arg = WebCore::String::fromUTF8(str_arg); + gboolean res = item->callbackWithClass2Param(_g_class2param, _g_str_arg); + return res; + +} + +glong +webkit_dom_test_callback_callback_with_non_bool_return_type (WebKitDOMTestCallback *self, WebKitDOMClass3* class3param) +{ + g_return_val_if_fail (self, 0); + WebCore::TestCallback * item = WebKit::core(self); + g_return_val_if_fail (class3param, 0); + WebCore::Class3 * _g_class3param = WebKit::core(class3param); + g_return_val_if_fail (_g_class3param, 0); + glong res = item->callbackWithNonBoolReturnType(_g_class3param); + return res; + +} + + +G_DEFINE_TYPE(WebKitDOMTestCallback, webkit_dom_test_callback, WEBKIT_TYPE_DOM_OBJECT) + +namespace WebKit { + +WebKitDOMTestCallback* wrapTestCallback(WebCore::TestCallback* coreObject) +{ + g_return_val_if_fail(coreObject != 0, 0); + + WebKitDOMTestCallback* wrapper = WEBKIT_DOM_TEST_CALLBACK(g_object_new(WEBKIT_TYPE_DOM_TEST_CALLBACK, NULL)); + g_return_val_if_fail(wrapper != 0, 0); + + /* We call ref() rather than using a C++ smart pointer because we can't store a C++ object + * in a C-allocated GObject structure. See the finalize() code for the + * matching deref(). + */ + + coreObject->ref(); + WEBKIT_DOM_OBJECT(wrapper)->coreObject = coreObject; + + return wrapper; +} + +WebCore::TestCallback* core(WebKitDOMTestCallback* request) +{ + g_return_val_if_fail(request != 0, 0); + + WebCore::TestCallback* coreObject = static_cast<WebCore::TestCallback*>(WEBKIT_DOM_OBJECT(request)->coreObject); + g_return_val_if_fail(coreObject != 0, 0); + + return coreObject; +} + +} // namespace WebKit +enum { + PROP_0, +}; + + +static void webkit_dom_test_callback_finalize(GObject* object) +{ + WebKitDOMObject* dom_object = WEBKIT_DOM_OBJECT(object); + + if (dom_object->coreObject != NULL) { + WebCore::TestCallback* coreObject = static_cast<WebCore::TestCallback *>(dom_object->coreObject); + + WebKit::DOMObjectCache::forget(coreObject); + coreObject->deref(); + + dom_object->coreObject = NULL; + } + + G_OBJECT_CLASS(webkit_dom_test_callback_parent_class)->finalize(object); +} + +static void webkit_dom_test_callback_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + + +static void webkit_dom_test_callback_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + + +static void webkit_dom_test_callback_class_init(WebKitDOMTestCallbackClass* requestClass) +{ + GObjectClass *gobjectClass = G_OBJECT_CLASS(requestClass); + gobjectClass->finalize = webkit_dom_test_callback_finalize; + gobjectClass->set_property = webkit_dom_test_callback_set_property; + gobjectClass->get_property = webkit_dom_test_callback_get_property; + + + + +} + +static void webkit_dom_test_callback_init(WebKitDOMTestCallback* request) +{ +} + diff --git a/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallback.h b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallback.h new file mode 100644 index 0000000..088c457 --- /dev/null +++ b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallback.h @@ -0,0 +1,60 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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 WebKitDOMTestCallback_h +#define WebKitDOMTestCallback_h + +#include "webkit/webkitdomdefines.h" +#include <glib-object.h> +#include <webkit/webkitdefines.h> +#include "webkit/WebKitDOMObject.h" + + +G_BEGIN_DECLS +#define WEBKIT_TYPE_DOM_TEST_CALLBACK (webkit_dom_test_callback_get_type()) +#define WEBKIT_DOM_TEST_CALLBACK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_DOM_TEST_CALLBACK, WebKitDOMTestCallback)) +#define WEBKIT_DOM_TEST_CALLBACK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_DOM_TEST_CALLBACK, WebKitDOMTestCallbackClass) +#define WEBKIT_DOM_IS_TEST_CALLBACK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_DOM_TEST_CALLBACK)) +#define WEBKIT_DOM_IS_TEST_CALLBACK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_DOM_TEST_CALLBACK)) +#define WEBKIT_DOM_TEST_CALLBACK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_DOM_TEST_CALLBACK, WebKitDOMTestCallbackClass)) + +struct _WebKitDOMTestCallback { + WebKitDOMObject parent_instance; +}; + +struct _WebKitDOMTestCallbackClass { + WebKitDOMObjectClass parent_class; +}; + +WEBKIT_API GType +webkit_dom_test_callback_get_type (void); + +WEBKIT_API gboolean +webkit_dom_test_callback_callback_with_class1param (WebKitDOMTestCallback *self, WebKitDOMClass1* class1param); + +WEBKIT_API gboolean +webkit_dom_test_callback_callback_with_class2param (WebKitDOMTestCallback *self, WebKitDOMClass2* class2param, gchar* str_arg); + +WEBKIT_API glong +webkit_dom_test_callback_callback_with_non_bool_return_type (WebKitDOMTestCallback *self, WebKitDOMClass3* class3param); + +G_END_DECLS + +#endif /* WebKitDOMTestCallback_h */ diff --git a/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallbackPrivate.h b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallbackPrivate.h new file mode 100644 index 0000000..45884b2 --- /dev/null +++ b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestCallbackPrivate.h @@ -0,0 +1,39 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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 WEB_KIT_DOM_TEST_CALLBACK_PRIVATE_H +#define WEB_KIT_DOM_TEST_CALLBACK_PRIVATE_H + +#include <glib-object.h> +#include <webkit/WebKitDOMObject.h> +#include "TestCallback.h" +namespace WebKit { + WebKitDOMTestCallback * + wrapTestCallback(WebCore::TestCallback *coreObject); + + WebCore::TestCallback * + core(WebKitDOMTestCallback *request); + + gpointer + kit(WebCore::TestCallback* node); + +} // namespace WebKit + +#endif /* WEB_KIT_DOM_TEST_CALLBACK_PRIVATE_H */ diff --git a/WebCore/bindings/scripts/test/GObject/WebKitDOMTestInterface.cpp b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestInterface.cpp new file mode 100644 index 0000000..2be0277 --- /dev/null +++ b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestInterface.cpp @@ -0,0 +1,139 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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 <glib-object.h> +#include "config.h" + +#include <wtf/GetPtr.h> +#include <wtf/RefPtr.h> +#include "ExceptionCode.h" +#include "TestInterface.h" +#include "WebKitDOMBinding.h" +#include "gobject/ConvertToUTF8String.h" +#include "webkit/WebKitDOMTestInterface.h" +#include "webkit/WebKitDOMTestInterfacePrivate.h" +#include "webkitmarshal.h" +#include "webkitprivate.h" + +namespace WebKit { + +gpointer kit(WebCore::TestInterface* obj) +{ + g_return_val_if_fail(obj != 0, 0); + + if (gpointer ret = DOMObjectCache::get(obj)) + return ret; + + return DOMObjectCache::put(obj, WebKit::wrapTestInterface(obj)); +} + +} // namespace WebKit // + + +G_DEFINE_TYPE(WebKitDOMTestInterface, webkit_dom_test_interface, WEBKIT_TYPE_DOM_OBJECT) + +namespace WebKit { + +WebKitDOMTestInterface* wrapTestInterface(WebCore::TestInterface* coreObject) +{ + g_return_val_if_fail(coreObject != 0, 0); + + WebKitDOMTestInterface* wrapper = WEBKIT_DOM_TEST_INTERFACE(g_object_new(WEBKIT_TYPE_DOM_TEST_INTERFACE, NULL)); + g_return_val_if_fail(wrapper != 0, 0); + + /* We call ref() rather than using a C++ smart pointer because we can't store a C++ object + * in a C-allocated GObject structure. See the finalize() code for the + * matching deref(). + */ + + coreObject->ref(); + WEBKIT_DOM_OBJECT(wrapper)->coreObject = coreObject; + + return wrapper; +} + +WebCore::TestInterface* core(WebKitDOMTestInterface* request) +{ + g_return_val_if_fail(request != 0, 0); + + WebCore::TestInterface* coreObject = static_cast<WebCore::TestInterface*>(WEBKIT_DOM_OBJECT(request)->coreObject); + g_return_val_if_fail(coreObject != 0, 0); + + return coreObject; +} + +} // namespace WebKit +enum { + PROP_0, +}; + + +static void webkit_dom_test_interface_finalize(GObject* object) +{ + WebKitDOMObject* dom_object = WEBKIT_DOM_OBJECT(object); + + if (dom_object->coreObject != NULL) { + WebCore::TestInterface* coreObject = static_cast<WebCore::TestInterface *>(dom_object->coreObject); + + WebKit::DOMObjectCache::forget(coreObject); + coreObject->deref(); + + dom_object->coreObject = NULL; + } + + G_OBJECT_CLASS(webkit_dom_test_interface_parent_class)->finalize(object); +} + +static void webkit_dom_test_interface_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + + +static void webkit_dom_test_interface_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + + +static void webkit_dom_test_interface_class_init(WebKitDOMTestInterfaceClass* requestClass) +{ + GObjectClass *gobjectClass = G_OBJECT_CLASS(requestClass); + gobjectClass->finalize = webkit_dom_test_interface_finalize; + gobjectClass->set_property = webkit_dom_test_interface_set_property; + gobjectClass->get_property = webkit_dom_test_interface_get_property; + + + + +} + +static void webkit_dom_test_interface_init(WebKitDOMTestInterface* request) +{ +} + diff --git a/WebCore/bindings/scripts/test/GObject/WebKitDOMTestInterface.h b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestInterface.h new file mode 100644 index 0000000..f9af866 --- /dev/null +++ b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestInterface.h @@ -0,0 +1,51 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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 WebKitDOMTestInterface_h +#define WebKitDOMTestInterface_h + +#include "webkit/webkitdomdefines.h" +#include <glib-object.h> +#include <webkit/webkitdefines.h> +#include "webkit/WebKitDOMObject.h" + + +G_BEGIN_DECLS +#define WEBKIT_TYPE_DOM_TEST_INTERFACE (webkit_dom_test_interface_get_type()) +#define WEBKIT_DOM_TEST_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_DOM_TEST_INTERFACE, WebKitDOMTestInterface)) +#define WEBKIT_DOM_TEST_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_DOM_TEST_INTERFACE, WebKitDOMTestInterfaceClass) +#define WEBKIT_DOM_IS_TEST_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_DOM_TEST_INTERFACE)) +#define WEBKIT_DOM_IS_TEST_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_DOM_TEST_INTERFACE)) +#define WEBKIT_DOM_TEST_INTERFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_DOM_TEST_INTERFACE, WebKitDOMTestInterfaceClass)) + +struct _WebKitDOMTestInterface { + WebKitDOMObject parent_instance; +}; + +struct _WebKitDOMTestInterfaceClass { + WebKitDOMObjectClass parent_class; +}; + +WEBKIT_API GType +webkit_dom_test_interface_get_type (void); + +G_END_DECLS + +#endif /* WebKitDOMTestInterface_h */ diff --git a/WebCore/bindings/scripts/test/GObject/WebKitDOMTestInterfacePrivate.h b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestInterfacePrivate.h new file mode 100644 index 0000000..45fb949 --- /dev/null +++ b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestInterfacePrivate.h @@ -0,0 +1,39 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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 WEB_KIT_DOM_TEST_INTERFACE_PRIVATE_H +#define WEB_KIT_DOM_TEST_INTERFACE_PRIVATE_H + +#include <glib-object.h> +#include <webkit/WebKitDOMObject.h> +#include "TestInterface.h" +namespace WebKit { + WebKitDOMTestInterface * + wrapTestInterface(WebCore::TestInterface *coreObject); + + WebCore::TestInterface * + core(WebKitDOMTestInterface *request); + + gpointer + kit(WebCore::TestInterface* node); + +} // namespace WebKit + +#endif /* WEB_KIT_DOM_TEST_INTERFACE_PRIVATE_H */ diff --git a/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObj.cpp b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObj.cpp new file mode 100644 index 0000000..8c1bae2 --- /dev/null +++ b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObj.cpp @@ -0,0 +1,779 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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 <glib-object.h> +#include "config.h" + +#include <wtf/GetPtr.h> +#include <wtf/RefPtr.h> +#include "ExceptionCode.h" +#include "TestObj.h" +#include "WebKitDOMBinding.h" +#include "gobject/ConvertToUTF8String.h" +#include "webkit/WebKitDOMSerializedScriptValue.h" +#include "webkit/WebKitDOMSerializedScriptValuePrivate.h" +#include "webkit/WebKitDOMTestObj.h" +#include "webkit/WebKitDOMTestObjPrivate.h" +#include "webkitmarshal.h" +#include "webkitprivate.h" + +namespace WebKit { + +gpointer kit(WebCore::TestObj* obj) +{ + g_return_val_if_fail(obj != 0, 0); + + if (gpointer ret = DOMObjectCache::get(obj)) + return ret; + + return DOMObjectCache::put(obj, WebKit::wrapTestObj(obj)); +} + +} // namespace WebKit // + +void +webkit_dom_test_obj_void_method (WebKitDOMTestObj *self) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + item->voidMethod(); + +} + +void +webkit_dom_test_obj_void_method_with_args (WebKitDOMTestObj *self, glong int_arg, gchar* str_arg, WebKitDOMTestObj* obj_arg) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + g_return_if_fail (str_arg); + g_return_if_fail (obj_arg); + WebCore::String _g_str_arg = WebCore::String::fromUTF8(str_arg); + WebCore::TestObj * _g_obj_arg = WebKit::core(obj_arg); + g_return_if_fail (_g_obj_arg); + item->voidMethodWithArgs(int_arg, _g_str_arg, _g_obj_arg); + +} + +glong +webkit_dom_test_obj_int_method (WebKitDOMTestObj *self) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + glong res = item->intMethod(); + return res; + +} + +glong +webkit_dom_test_obj_int_method_with_args (WebKitDOMTestObj *self, glong int_arg, gchar* str_arg, WebKitDOMTestObj* obj_arg) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + g_return_val_if_fail (str_arg, 0); + g_return_val_if_fail (obj_arg, 0); + WebCore::String _g_str_arg = WebCore::String::fromUTF8(str_arg); + WebCore::TestObj * _g_obj_arg = WebKit::core(obj_arg); + g_return_val_if_fail (_g_obj_arg, 0); + glong res = item->intMethodWithArgs(int_arg, _g_str_arg, _g_obj_arg); + return res; + +} + +WebKitDOMTestObj* +webkit_dom_test_obj_obj_method (WebKitDOMTestObj *self) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + PassRefPtr<WebCore::TestObj> g_res = WTF::getPtr(item->objMethod()); + WebKitDOMTestObj* res = static_cast<WebKitDOMTestObj* >(WebKit::kit(g_res.get())); + return res; + +} + +WebKitDOMTestObj* +webkit_dom_test_obj_obj_method_with_args (WebKitDOMTestObj *self, glong int_arg, gchar* str_arg, WebKitDOMTestObj* obj_arg) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + g_return_val_if_fail (str_arg, 0); + g_return_val_if_fail (obj_arg, 0); + WebCore::String _g_str_arg = WebCore::String::fromUTF8(str_arg); + WebCore::TestObj * _g_obj_arg = WebKit::core(obj_arg); + g_return_val_if_fail (_g_obj_arg, 0); + PassRefPtr<WebCore::TestObj> g_res = WTF::getPtr(item->objMethodWithArgs(int_arg, _g_str_arg, _g_obj_arg)); + WebKitDOMTestObj* res = static_cast<WebKitDOMTestObj* >(WebKit::kit(g_res.get())); + return res; + +} + +void +webkit_dom_test_obj_serialized_value (WebKitDOMTestObj *self, WebKitDOMSerializedScriptValue* serialized_arg) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + g_return_if_fail (serialized_arg); + WebCore::SerializedScriptValue * _g_serialized_arg = WebKit::core(serialized_arg); + g_return_if_fail (_g_serialized_arg); + item->serializedValue(_g_serialized_arg); + +} + +void +webkit_dom_test_obj_method_with_exception (WebKitDOMTestObj *self, GError **error) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + WebCore::ExceptionCode ec = 0; + item->methodWithException(ec); + if (ec) { + WebCore::ExceptionCodeDescription ecdesc; + WebCore::getExceptionCodeDescription(ec, ecdesc); + g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), ecdesc.code, ecdesc.name); + } + +} + + +/* TODO: event function webkit_dom_test_obj_add_event_listener */ + + +/* TODO: event function webkit_dom_test_obj_remove_event_listener */ + +void +webkit_dom_test_obj_with_dynamic_frame (WebKitDOMTestObj *self) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + item->withDynamicFrame(); + +} + +void +webkit_dom_test_obj_with_dynamic_frame_and_arg (WebKitDOMTestObj *self, glong int_arg) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + item->withDynamicFrameAndArg(int_arg); + +} + +void +webkit_dom_test_obj_with_dynamic_frame_and_optional_arg (WebKitDOMTestObj *self, glong int_arg, glong optional_arg) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + item->withDynamicFrameAndOptionalArg(int_arg, optional_arg); + +} + +void +webkit_dom_test_obj_with_dynamic_frame_and_user_gesture (WebKitDOMTestObj *self, glong int_arg) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + item->withDynamicFrameAndUserGesture(int_arg); + +} + +void +webkit_dom_test_obj_with_dynamic_frame_and_user_gesture_asad (WebKitDOMTestObj *self, glong int_arg, glong optional_arg) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + item->withDynamicFrameAndUserGestureASAD(int_arg, optional_arg); + +} + +void +webkit_dom_test_obj_with_script_state_void (WebKitDOMTestObj *self) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + item->withScriptStateVoid(); + +} + +WebKitDOMTestObj* +webkit_dom_test_obj_with_script_state_obj (WebKitDOMTestObj *self) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + PassRefPtr<WebCore::TestObj> g_res = WTF::getPtr(item->withScriptStateObj()); + WebKitDOMTestObj* res = static_cast<WebKitDOMTestObj* >(WebKit::kit(g_res.get())); + return res; + +} + +void +webkit_dom_test_obj_with_script_state_void_exception (WebKitDOMTestObj *self, GError **error) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + WebCore::ExceptionCode ec = 0; + item->withScriptStateVoidException(ec); + if (ec) { + WebCore::ExceptionCodeDescription ecdesc; + WebCore::getExceptionCodeDescription(ec, ecdesc); + g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), ecdesc.code, ecdesc.name); + } + +} + +WebKitDOMTestObj* +webkit_dom_test_obj_with_script_state_obj_exception (WebKitDOMTestObj *self, GError **error) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + WebCore::ExceptionCode ec = 0; + PassRefPtr<WebCore::TestObj> g_res = WTF::getPtr(item->withScriptStateObjException(ec)); + if (ec) { + WebCore::ExceptionCodeDescription ecdesc; + WebCore::getExceptionCodeDescription(ec, ecdesc); + g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), ecdesc.code, ecdesc.name); + } + WebKitDOMTestObj* res = static_cast<WebKitDOMTestObj* >(WebKit::kit(g_res.get())); + return res; + +} + +void +webkit_dom_test_obj_method_with_optional_arg (WebKitDOMTestObj *self, glong opt) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + item->methodWithOptionalArg(opt); + +} + +void +webkit_dom_test_obj_method_with_non_optional_arg_and_optional_arg (WebKitDOMTestObj *self, glong non_opt, glong opt) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + item->methodWithNonOptionalArgAndOptionalArg(non_opt, opt); + +} + +void +webkit_dom_test_obj_method_with_non_optional_arg_and_two_optional_args (WebKitDOMTestObj *self, glong non_opt, glong opt1, glong opt2) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + item->methodWithNonOptionalArgAndTwoOptionalArgs(non_opt, opt1, opt2); + +} + +glong +webkit_dom_test_obj_get_read_only_int_attr (WebKitDOMTestObj *self) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + glong res = item->readOnlyIntAttr(); + return res; + +} + +gchar* +webkit_dom_test_obj_get_read_only_string_attr (WebKitDOMTestObj *self) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + gchar* res = convertToUTF8String(item->readOnlyStringAttr()); + return res; + +} + +WebKitDOMTestObj* +webkit_dom_test_obj_get_read_only_test_obj_attr (WebKitDOMTestObj *self) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + PassRefPtr<WebCore::TestObj> g_res = WTF::getPtr(item->readOnlyTestObjAttr()); + WebKitDOMTestObj* res = static_cast<WebKitDOMTestObj* >(WebKit::kit(g_res.get())); + return res; + +} + +glong +webkit_dom_test_obj_get_int_attr (WebKitDOMTestObj *self) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + glong res = item->intAttr(); + return res; + +} + +void +webkit_dom_test_obj_set_int_attr (WebKitDOMTestObj *self, glong value) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + item->setIntAttr(value); + +} + +gint64 +webkit_dom_test_obj_get_long_long_attr (WebKitDOMTestObj *self) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + gint64 res = item->longLongAttr(); + return res; + +} + +void +webkit_dom_test_obj_set_long_long_attr (WebKitDOMTestObj *self, gint64 value) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + item->setLongLongAttr(value); + +} + +guint64 +webkit_dom_test_obj_get_unsigned_long_long_attr (WebKitDOMTestObj *self) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + guint64 res = item->unsignedLongLongAttr(); + return res; + +} + +void +webkit_dom_test_obj_set_unsigned_long_long_attr (WebKitDOMTestObj *self, guint64 value) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + item->setUnsignedLongLongAttr(value); + +} + +gchar* +webkit_dom_test_obj_get_string_attr (WebKitDOMTestObj *self) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + gchar* res = convertToUTF8String(item->stringAttr()); + return res; + +} + +void +webkit_dom_test_obj_set_string_attr (WebKitDOMTestObj *self, gchar* value) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + g_return_if_fail (value); + WebCore::String _g_value = WebCore::String::fromUTF8(value); + item->setStringAttr(_g_value); + +} + +WebKitDOMTestObj* +webkit_dom_test_obj_get_test_obj_attr (WebKitDOMTestObj *self) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + PassRefPtr<WebCore::TestObj> g_res = WTF::getPtr(item->testObjAttr()); + WebKitDOMTestObj* res = static_cast<WebKitDOMTestObj* >(WebKit::kit(g_res.get())); + return res; + +} + +void +webkit_dom_test_obj_set_test_obj_attr (WebKitDOMTestObj *self, WebKitDOMTestObj* value) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + g_return_if_fail (value); + WebCore::TestObj * _g_value = WebKit::core(value); + g_return_if_fail (_g_value); + item->setTestObjAttr(_g_value); + +} + +glong +webkit_dom_test_obj_get_attr_with_exception (WebKitDOMTestObj *self) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + glong res = item->attrWithException(); + return res; + +} + +void +webkit_dom_test_obj_set_attr_with_exception (WebKitDOMTestObj *self, glong value) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + item->setAttrWithException(value); + +} + +glong +webkit_dom_test_obj_get_attr_with_setter_exception (WebKitDOMTestObj *self) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + glong res = item->attrWithSetterException(); + return res; + +} + +void +webkit_dom_test_obj_set_attr_with_setter_exception (WebKitDOMTestObj *self, glong value) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + item->setAttrWithSetterException(value); + +} + +glong +webkit_dom_test_obj_get_attr_with_getter_exception (WebKitDOMTestObj *self) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + glong res = item->attrWithGetterException(); + return res; + +} + +void +webkit_dom_test_obj_set_attr_with_getter_exception (WebKitDOMTestObj *self, glong value) +{ + g_return_if_fail (self); + WebCore::TestObj * item = WebKit::core(self); + item->setAttrWithGetterException(value); + +} + +gchar* +webkit_dom_test_obj_get_script_string_attr (WebKitDOMTestObj *self) +{ + g_return_val_if_fail (self, 0); + WebCore::TestObj * item = WebKit::core(self); + gchar* res = convertToUTF8String(item->scriptStringAttr()); + return res; + +} + + +G_DEFINE_TYPE(WebKitDOMTestObj, webkit_dom_test_obj, WEBKIT_TYPE_DOM_OBJECT) + +namespace WebKit { + +WebKitDOMTestObj* wrapTestObj(WebCore::TestObj* coreObject) +{ + g_return_val_if_fail(coreObject != 0, 0); + + WebKitDOMTestObj* wrapper = WEBKIT_DOM_TEST_OBJ(g_object_new(WEBKIT_TYPE_DOM_TEST_OBJ, NULL)); + g_return_val_if_fail(wrapper != 0, 0); + + /* We call ref() rather than using a C++ smart pointer because we can't store a C++ object + * in a C-allocated GObject structure. See the finalize() code for the + * matching deref(). + */ + + coreObject->ref(); + WEBKIT_DOM_OBJECT(wrapper)->coreObject = coreObject; + + return wrapper; +} + +WebCore::TestObj* core(WebKitDOMTestObj* request) +{ + g_return_val_if_fail(request != 0, 0); + + WebCore::TestObj* coreObject = static_cast<WebCore::TestObj*>(WEBKIT_DOM_OBJECT(request)->coreObject); + g_return_val_if_fail(coreObject != 0, 0); + + return coreObject; +} + +} // namespace WebKit +enum { + PROP_0, + PROP_READ_ONLY_INT_ATTR, + PROP_READ_ONLY_STRING_ATTR, + PROP_READ_ONLY_TEST_OBJ_ATTR, + PROP_INT_ATTR, + PROP_LONG_LONG_ATTR, + PROP_UNSIGNED_LONG_LONG_ATTR, + PROP_STRING_ATTR, + PROP_TEST_OBJ_ATTR, + PROP_ATTR_WITH_EXCEPTION, + PROP_ATTR_WITH_SETTER_EXCEPTION, + PROP_ATTR_WITH_GETTER_EXCEPTION, + PROP_CUSTOM_ATTR, + PROP_SCRIPT_STRING_ATTR, +}; + + +static void webkit_dom_test_obj_finalize(GObject* object) +{ + WebKitDOMObject* dom_object = WEBKIT_DOM_OBJECT(object); + + if (dom_object->coreObject != NULL) { + WebCore::TestObj* coreObject = static_cast<WebCore::TestObj *>(dom_object->coreObject); + + WebKit::DOMObjectCache::forget(coreObject); + coreObject->deref(); + + dom_object->coreObject = NULL; + } + + G_OBJECT_CLASS(webkit_dom_test_obj_parent_class)->finalize(object); +} + +static void webkit_dom_test_obj_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) +{ + WebKitDOMTestObj *self = WEBKIT_DOM_TEST_OBJ(object); + WebCore::TestObj* coreSelf = WebKit::core(self); + switch (prop_id) { + case PROP_INT_ATTR: + { + coreSelf->setIntAttr((g_value_get_long(value)) ); + break; + } + case PROP_UNSIGNED_LONG_LONG_ATTR: + { + coreSelf->setUnsignedLongLongAttr((g_value_get_uint64(value)) ); + break; + } + case PROP_STRING_ATTR: + { + coreSelf->setStringAttr(WebCore::String::fromUTF8(g_value_get_string(value)) ); + break; + } + case PROP_ATTR_WITH_EXCEPTION: + { + coreSelf->setAttrWithException((g_value_get_long(value)) ); + break; + } + case PROP_ATTR_WITH_SETTER_EXCEPTION: + { + coreSelf->setAttrWithSetterException((g_value_get_long(value)) ); + break; + } + case PROP_ATTR_WITH_GETTER_EXCEPTION: + { + coreSelf->setAttrWithGetterException((g_value_get_long(value)) ); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + + +static void webkit_dom_test_obj_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) +{ + WebKitDOMTestObj* self = WEBKIT_DOM_TEST_OBJ(object); + WebCore::TestObj* coreSelf = WebKit::core(self); + switch (prop_id) { + case PROP_READ_ONLY_INT_ATTR: + { + g_value_set_long(value, coreSelf->readOnlyIntAttr()); + break; + } + case PROP_READ_ONLY_STRING_ATTR: + { + g_value_take_string(value, convertToUTF8String(coreSelf->readOnlyStringAttr())); + break; + } + case PROP_READ_ONLY_TEST_OBJ_ATTR: + { + RefPtr<WebCore::TestObj> ptr = coreSelf->readOnlyTestObjAttr(); + g_value_set_object(value, WebKit::kit(ptr.get())); + break; + } + case PROP_INT_ATTR: + { + g_value_set_long(value, coreSelf->intAttr()); + break; + } + case PROP_LONG_LONG_ATTR: + { + g_value_set_int64(value, coreSelf->longLongAttr()); + break; + } + case PROP_UNSIGNED_LONG_LONG_ATTR: + { + g_value_set_uint64(value, coreSelf->unsignedLongLongAttr()); + break; + } + case PROP_STRING_ATTR: + { + g_value_take_string(value, convertToUTF8String(coreSelf->stringAttr())); + break; + } + case PROP_TEST_OBJ_ATTR: + { + RefPtr<WebCore::TestObj> ptr = coreSelf->testObjAttr(); + g_value_set_object(value, WebKit::kit(ptr.get())); + break; + } + case PROP_ATTR_WITH_EXCEPTION: + { + g_value_set_long(value, coreSelf->attrWithException()); + break; + } + case PROP_ATTR_WITH_SETTER_EXCEPTION: + { + g_value_set_long(value, coreSelf->attrWithSetterException()); + break; + } + case PROP_ATTR_WITH_GETTER_EXCEPTION: + { + g_value_set_long(value, coreSelf->attrWithGetterException()); + break; + } + case PROP_SCRIPT_STRING_ATTR: + { + g_value_take_string(value, convertToUTF8String(coreSelf->scriptStringAttr())); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + + +static void webkit_dom_test_obj_class_init(WebKitDOMTestObjClass* requestClass) +{ + GObjectClass *gobjectClass = G_OBJECT_CLASS(requestClass); + gobjectClass->finalize = webkit_dom_test_obj_finalize; + gobjectClass->set_property = webkit_dom_test_obj_set_property; + gobjectClass->get_property = webkit_dom_test_obj_get_property; + + g_object_class_install_property(gobjectClass, + PROP_READ_ONLY_INT_ATTR, + g_param_spec_long("read-only-int-attr", /* name */ + "test_obj_read-only-int-attr", /* short description */ + "read-only glong TestObj.read-only-int-attr", /* longer - could do with some extra doc stuff here */ + G_MINLONG, /* min */ +G_MAXLONG, /* max */ +0, /* default */ + WEBKIT_PARAM_READABLE)); + g_object_class_install_property(gobjectClass, + PROP_READ_ONLY_STRING_ATTR, + g_param_spec_string("read-only-string-attr", /* name */ + "test_obj_read-only-string-attr", /* short description */ + "read-only gchar* TestObj.read-only-string-attr", /* longer - could do with some extra doc stuff here */ + "", /* default */ + WEBKIT_PARAM_READABLE)); + g_object_class_install_property(gobjectClass, + PROP_READ_ONLY_TEST_OBJ_ATTR, + g_param_spec_object("read-only-test-obj-attr", /* name */ + "test_obj_read-only-test-obj-attr", /* short description */ + "read-only WebKitDOMTestObj* TestObj.read-only-test-obj-attr", /* longer - could do with some extra doc stuff here */ + WEBKIT_TYPE_DOM_TEST_OBJ, /* gobject type */ + WEBKIT_PARAM_READABLE)); + g_object_class_install_property(gobjectClass, + PROP_INT_ATTR, + g_param_spec_long("int-attr", /* name */ + "test_obj_int-attr", /* short description */ + "read-write glong TestObj.int-attr", /* longer - could do with some extra doc stuff here */ + G_MINLONG, /* min */ +G_MAXLONG, /* max */ +0, /* default */ + WEBKIT_PARAM_READWRITE)); + g_object_class_install_property(gobjectClass, + PROP_LONG_LONG_ATTR, + g_param_spec_int64("long-long-attr", /* name */ + "test_obj_long-long-attr", /* short description */ + "read-write gint64 TestObj.long-long-attr", /* longer - could do with some extra doc stuff here */ + G_MININT64, /* min */ +G_MAXINT64, /* max */ +0, /* default */ + WEBKIT_PARAM_READWRITE)); + g_object_class_install_property(gobjectClass, + PROP_UNSIGNED_LONG_LONG_ATTR, + g_param_spec_uint64("unsigned-long-long-attr", /* name */ + "test_obj_unsigned-long-long-attr", /* short description */ + "read-write guint64 TestObj.unsigned-long-long-attr", /* longer - could do with some extra doc stuff here */ + 0, /* min */ +G_MAXUINT64, /* min */ +0, /* default */ + WEBKIT_PARAM_READWRITE)); + g_object_class_install_property(gobjectClass, + PROP_STRING_ATTR, + g_param_spec_string("string-attr", /* name */ + "test_obj_string-attr", /* short description */ + "read-write gchar* TestObj.string-attr", /* longer - could do with some extra doc stuff here */ + "", /* default */ + WEBKIT_PARAM_READWRITE)); + g_object_class_install_property(gobjectClass, + PROP_TEST_OBJ_ATTR, + g_param_spec_object("test-obj-attr", /* name */ + "test_obj_test-obj-attr", /* short description */ + "read-write WebKitDOMTestObj* TestObj.test-obj-attr", /* longer - could do with some extra doc stuff here */ + WEBKIT_TYPE_DOM_TEST_OBJ, /* gobject type */ + WEBKIT_PARAM_READWRITE)); + g_object_class_install_property(gobjectClass, + PROP_ATTR_WITH_EXCEPTION, + g_param_spec_long("attr-with-exception", /* name */ + "test_obj_attr-with-exception", /* short description */ + "read-write glong TestObj.attr-with-exception", /* longer - could do with some extra doc stuff here */ + G_MINLONG, /* min */ +G_MAXLONG, /* max */ +0, /* default */ + WEBKIT_PARAM_READWRITE)); + g_object_class_install_property(gobjectClass, + PROP_ATTR_WITH_SETTER_EXCEPTION, + g_param_spec_long("attr-with-setter-exception", /* name */ + "test_obj_attr-with-setter-exception", /* short description */ + "read-write glong TestObj.attr-with-setter-exception", /* longer - could do with some extra doc stuff here */ + G_MINLONG, /* min */ +G_MAXLONG, /* max */ +0, /* default */ + WEBKIT_PARAM_READWRITE)); + g_object_class_install_property(gobjectClass, + PROP_ATTR_WITH_GETTER_EXCEPTION, + g_param_spec_long("attr-with-getter-exception", /* name */ + "test_obj_attr-with-getter-exception", /* short description */ + "read-write glong TestObj.attr-with-getter-exception", /* longer - could do with some extra doc stuff here */ + G_MINLONG, /* min */ +G_MAXLONG, /* max */ +0, /* default */ + WEBKIT_PARAM_READWRITE)); + g_object_class_install_property(gobjectClass, + PROP_SCRIPT_STRING_ATTR, + g_param_spec_string("script-string-attr", /* name */ + "test_obj_script-string-attr", /* short description */ + "read-only gchar* TestObj.script-string-attr", /* longer - could do with some extra doc stuff here */ + "", /* default */ + WEBKIT_PARAM_READABLE)); + + + +} + +static void webkit_dom_test_obj_init(WebKitDOMTestObj* request) +{ +} + diff --git a/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObj.h b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObj.h new file mode 100644 index 0000000..f8ad9c4 --- /dev/null +++ b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObj.h @@ -0,0 +1,177 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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 WebKitDOMTestObj_h +#define WebKitDOMTestObj_h + +#include "webkit/webkitdomdefines.h" +#include <glib-object.h> +#include <webkit/webkitdefines.h> +#include "webkit/WebKitDOMObject.h" + + +G_BEGIN_DECLS +#define WEBKIT_TYPE_DOM_TEST_OBJ (webkit_dom_test_obj_get_type()) +#define WEBKIT_DOM_TEST_OBJ(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_DOM_TEST_OBJ, WebKitDOMTestObj)) +#define WEBKIT_DOM_TEST_OBJ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_DOM_TEST_OBJ, WebKitDOMTestObjClass) +#define WEBKIT_DOM_IS_TEST_OBJ(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_DOM_TEST_OBJ)) +#define WEBKIT_DOM_IS_TEST_OBJ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_DOM_TEST_OBJ)) +#define WEBKIT_DOM_TEST_OBJ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_DOM_TEST_OBJ, WebKitDOMTestObjClass)) + +struct _WebKitDOMTestObj { + WebKitDOMObject parent_instance; +}; + +struct _WebKitDOMTestObjClass { + WebKitDOMObjectClass parent_class; +}; + +WEBKIT_API GType +webkit_dom_test_obj_get_type (void); + +WEBKIT_API void +webkit_dom_test_obj_void_method (WebKitDOMTestObj *self); + +WEBKIT_API void +webkit_dom_test_obj_void_method_with_args (WebKitDOMTestObj *self, glong int_arg, gchar* str_arg, WebKitDOMTestObj* obj_arg); + +WEBKIT_API glong +webkit_dom_test_obj_int_method (WebKitDOMTestObj *self); + +WEBKIT_API glong +webkit_dom_test_obj_int_method_with_args (WebKitDOMTestObj *self, glong int_arg, gchar* str_arg, WebKitDOMTestObj* obj_arg); + +WEBKIT_API WebKitDOMTestObj* +webkit_dom_test_obj_obj_method (WebKitDOMTestObj *self); + +WEBKIT_API WebKitDOMTestObj* +webkit_dom_test_obj_obj_method_with_args (WebKitDOMTestObj *self, glong int_arg, gchar* str_arg, WebKitDOMTestObj* obj_arg); + +WEBKIT_API void +webkit_dom_test_obj_serialized_value (WebKitDOMTestObj *self, WebKitDOMSerializedScriptValue* serialized_arg); + +WEBKIT_API void +webkit_dom_test_obj_method_with_exception (WebKitDOMTestObj *self, GError **error); + + +/* TODO: event function webkit_dom_test_obj_add_event_listener */ + + +/* TODO: event function webkit_dom_test_obj_remove_event_listener */ + +WEBKIT_API void +webkit_dom_test_obj_with_dynamic_frame (WebKitDOMTestObj *self); + +WEBKIT_API void +webkit_dom_test_obj_with_dynamic_frame_and_arg (WebKitDOMTestObj *self, glong int_arg); + +WEBKIT_API void +webkit_dom_test_obj_with_dynamic_frame_and_optional_arg (WebKitDOMTestObj *self, glong int_arg, glong optional_arg); + +WEBKIT_API void +webkit_dom_test_obj_with_dynamic_frame_and_user_gesture (WebKitDOMTestObj *self, glong int_arg); + +WEBKIT_API void +webkit_dom_test_obj_with_dynamic_frame_and_user_gesture_asad (WebKitDOMTestObj *self, glong int_arg, glong optional_arg); + +WEBKIT_API void +webkit_dom_test_obj_with_script_state_void (WebKitDOMTestObj *self); + +WEBKIT_API WebKitDOMTestObj* +webkit_dom_test_obj_with_script_state_obj (WebKitDOMTestObj *self); + +WEBKIT_API void +webkit_dom_test_obj_with_script_state_void_exception (WebKitDOMTestObj *self, GError **error); + +WEBKIT_API WebKitDOMTestObj* +webkit_dom_test_obj_with_script_state_obj_exception (WebKitDOMTestObj *self, GError **error); + +WEBKIT_API void +webkit_dom_test_obj_method_with_optional_arg (WebKitDOMTestObj *self, glong opt); + +WEBKIT_API void +webkit_dom_test_obj_method_with_non_optional_arg_and_optional_arg (WebKitDOMTestObj *self, glong non_opt, glong opt); + +WEBKIT_API void +webkit_dom_test_obj_method_with_non_optional_arg_and_two_optional_args (WebKitDOMTestObj *self, glong non_opt, glong opt1, glong opt2); + +WEBKIT_API glong +webkit_dom_test_obj_get_read_only_int_attr (WebKitDOMTestObj *self); + +WEBKIT_API gchar* +webkit_dom_test_obj_get_read_only_string_attr (WebKitDOMTestObj *self); + +WEBKIT_API WebKitDOMTestObj* +webkit_dom_test_obj_get_read_only_test_obj_attr (WebKitDOMTestObj *self); + +WEBKIT_API glong +webkit_dom_test_obj_get_int_attr (WebKitDOMTestObj *self); + +WEBKIT_API void +webkit_dom_test_obj_set_int_attr (WebKitDOMTestObj *self, glong value); + +WEBKIT_API gint64 +webkit_dom_test_obj_get_long_long_attr (WebKitDOMTestObj *self); + +WEBKIT_API void +webkit_dom_test_obj_set_long_long_attr (WebKitDOMTestObj *self, gint64 value); + +WEBKIT_API guint64 +webkit_dom_test_obj_get_unsigned_long_long_attr (WebKitDOMTestObj *self); + +WEBKIT_API void +webkit_dom_test_obj_set_unsigned_long_long_attr (WebKitDOMTestObj *self, guint64 value); + +WEBKIT_API gchar* +webkit_dom_test_obj_get_string_attr (WebKitDOMTestObj *self); + +WEBKIT_API void +webkit_dom_test_obj_set_string_attr (WebKitDOMTestObj *self, gchar* value); + +WEBKIT_API WebKitDOMTestObj* +webkit_dom_test_obj_get_test_obj_attr (WebKitDOMTestObj *self); + +WEBKIT_API void +webkit_dom_test_obj_set_test_obj_attr (WebKitDOMTestObj *self, WebKitDOMTestObj* value); + +WEBKIT_API glong +webkit_dom_test_obj_get_attr_with_exception (WebKitDOMTestObj *self); + +WEBKIT_API void +webkit_dom_test_obj_set_attr_with_exception (WebKitDOMTestObj *self, glong value); + +WEBKIT_API glong +webkit_dom_test_obj_get_attr_with_setter_exception (WebKitDOMTestObj *self); + +WEBKIT_API void +webkit_dom_test_obj_set_attr_with_setter_exception (WebKitDOMTestObj *self, glong value); + +WEBKIT_API glong +webkit_dom_test_obj_get_attr_with_getter_exception (WebKitDOMTestObj *self); + +WEBKIT_API void +webkit_dom_test_obj_set_attr_with_getter_exception (WebKitDOMTestObj *self, glong value); + +WEBKIT_API gchar* +webkit_dom_test_obj_get_script_string_attr (WebKitDOMTestObj *self); + +G_END_DECLS + +#endif /* WebKitDOMTestObj_h */ diff --git a/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObjPrivate.h b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObjPrivate.h new file mode 100644 index 0000000..78cd87f --- /dev/null +++ b/WebCore/bindings/scripts/test/GObject/WebKitDOMTestObjPrivate.h @@ -0,0 +1,39 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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 WEB_KIT_DOM_TEST_OBJ_PRIVATE_H +#define WEB_KIT_DOM_TEST_OBJ_PRIVATE_H + +#include <glib-object.h> +#include <webkit/WebKitDOMObject.h> +#include "TestObj.h" +namespace WebKit { + WebKitDOMTestObj * + wrapTestObj(WebCore::TestObj *coreObject); + + WebCore::TestObj * + core(WebKitDOMTestObj *request); + + gpointer + kit(WebCore::TestObj* node); + +} // namespace WebKit + +#endif /* WEB_KIT_DOM_TEST_OBJ_PRIVATE_H */ diff --git a/WebCore/bindings/scripts/test/JS/JSTestCallback.cpp b/WebCore/bindings/scripts/test/JS/JSTestCallback.cpp new file mode 100644 index 0000000..2d0cfae --- /dev/null +++ b/WebCore/bindings/scripts/test/JS/JSTestCallback.cpp @@ -0,0 +1,100 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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" + +#if ENABLE(DATABASE) + +#include "JSTestCallback.h" + +#include "JSClass1.h" +#include "JSClass2.h" +#include "ScriptExecutionContext.h" +#include <runtime/JSLock.h> +#include <wtf/MainThread.h> + +using namespace JSC; + +namespace WebCore { + +JSTestCallback::JSTestCallback(JSObject* callback, JSDOMGlobalObject* globalObject) + : m_data(new JSCallbackData(callback, globalObject)) + , m_isolatedWorld(globalObject->world()) +{ +} + +JSTestCallback::~JSTestCallback() +{ + callOnMainThread(JSCallbackData::deleteData, m_data); +#ifndef NDEBUG + m_data = 0; +#endif +} + +// Functions + +bool JSTestCallback::callbackWithClass1Param(ScriptExecutionContext* context, Class1* class1Param) +{ + ASSERT(m_data); + ASSERT(context); + + RefPtr<JSTestCallback> protect(this); + + JSLock lock(SilenceAssertionsOnly); + + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get()); + if (!globalObject) + return true; + + ExecState* exec = globalObject->globalExec(); + MarkedArgumentBuffer args; + args.append(toJS(exec, class1Param)); + + bool raisedException = false; + m_data->invokeCallback(args, &raisedException); + return !raisedException; +} + +bool JSTestCallback::callbackWithClass2Param(ScriptExecutionContext* context, Class2* class2Param, const String& strArg) +{ + ASSERT(m_data); + ASSERT(context); + + RefPtr<JSTestCallback> protect(this); + + JSLock lock(SilenceAssertionsOnly); + + JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get()); + if (!globalObject) + return true; + + ExecState* exec = globalObject->globalExec(); + MarkedArgumentBuffer args; + args.append(toJS(exec, class2Param)); + args.append(toJS(exec, strArg)); + + bool raisedException = false; + m_data->invokeCallback(args, &raisedException); + return !raisedException; +} + +} + +#endif // ENABLE(DATABASE) diff --git a/WebCore/bindings/scripts/test/JS/JSTestCallback.h b/WebCore/bindings/scripts/test/JS/JSTestCallback.h new file mode 100644 index 0000000..6e8f083 --- /dev/null +++ b/WebCore/bindings/scripts/test/JS/JSTestCallback.h @@ -0,0 +1,58 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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 JSTestCallback_h +#define JSTestCallback_h + +#if ENABLE(DATABASE) + +#include "JSCallbackData.h" +#include "TestCallback.h" +#include <wtf/Forward.h> + +namespace WebCore { + +class JSTestCallback : public TestCallback { +public: + static PassRefPtr<JSTestCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject) + { + return adoptRef(new JSTestCallback(callback, globalObject)); + } + + virtual ~JSTestCallback(); + + // Functions + virtual bool callbackWithClass1Param(ScriptExecutionContext*, Class1* class1Param); + virtual bool callbackWithClass2Param(ScriptExecutionContext*, Class2* class2Param, const String& strArg); + COMPILE_ASSERT(false) virtual int callbackWithNonBoolReturnType(ScriptExecutionContext*, Class3* class3Param); + virtual int customCallback(ScriptExecutionContext*, Class5* class5Param, Class6* class6Param); + +private: + JSTestCallback(JSC::JSObject* callback, JSDOMGlobalObject*); + + JSCallbackData* m_data; + RefPtr<DOMWrapperWorld> m_isolatedWorld; +}; + +} // namespace WebCore + +#endif // ENABLE(DATABASE) + +#endif diff --git a/WebCore/bindings/scripts/test/JS/JSTestInterface.cpp b/WebCore/bindings/scripts/test/JS/JSTestInterface.cpp new file mode 100644 index 0000000..8855481 --- /dev/null +++ b/WebCore/bindings/scripts/test/JS/JSTestInterface.cpp @@ -0,0 +1,193 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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 "JSTestInterface.h" + +#include "TestInterface.h" +#include <wtf/GetPtr.h> + +using namespace JSC; + +namespace WebCore { + +ASSERT_CLASS_FITS_IN_CELL(JSTestInterface); + +/* Hash table */ +#if ENABLE(JIT) +#define THUNK_GENERATOR(generator) , generator +#else +#define THUNK_GENERATOR(generator) +#endif + +static const HashTableValue JSTestInterfaceTableValues[2] = +{ + { "constructor", DontEnum|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestInterfaceConstructor), (intptr_t)0 THUNK_GENERATOR(0) }, + { 0, 0, 0, 0 THUNK_GENERATOR(0) } +}; + +#undef THUNK_GENERATOR +static JSC_CONST_HASHTABLE HashTable JSTestInterfaceTable = +#if ENABLE(PERFECT_HASH_SIZE) + { 0, JSTestInterfaceTableValues, 0 }; +#else + { 2, 1, JSTestInterfaceTableValues, 0 }; +#endif + +/* Hash table for constructor */ +#if ENABLE(JIT) +#define THUNK_GENERATOR(generator) , generator +#else +#define THUNK_GENERATOR(generator) +#endif + +static const HashTableValue JSTestInterfaceConstructorTableValues[1] = +{ + { 0, 0, 0, 0 THUNK_GENERATOR(0) } +}; + +#undef THUNK_GENERATOR +static JSC_CONST_HASHTABLE HashTable JSTestInterfaceConstructorTable = +#if ENABLE(PERFECT_HASH_SIZE) + { 0, JSTestInterfaceConstructorTableValues, 0 }; +#else + { 1, 0, JSTestInterfaceConstructorTableValues, 0 }; +#endif + +class JSTestInterfaceConstructor : public DOMConstructorObject { +public: + JSTestInterfaceConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) + : DOMConstructorObject(JSTestInterfaceConstructor::createStructure(globalObject->objectPrototype()), globalObject) + { + putDirect(exec->propertyNames().prototype, JSTestInterfacePrototype::self(exec, globalObject), None); + } + virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); + virtual const ClassInfo* classInfo() const { return &s_info; } + static const ClassInfo s_info; + + static PassRefPtr<Structure> createStructure(JSValue proto) + { + return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); + } + +protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | DOMConstructorObject::StructureFlags; + static JSObject* constructTestInterface(ExecState* exec, JSObject* constructor, const ArgList&) + { + ScriptExecutionContext* context = static_cast<JSTestInterfaceConstructor*>(constructor)->scriptExecutionContext(); + if (!context) + return throwError(exec, ReferenceError); + return asObject(toJS(exec, static_cast<JSTestInterfaceConstructor*>(constructor)->globalObject(), TestInterface::create(context))); + } + virtual ConstructType getConstructData(ConstructData& constructData) + { + constructData.native.function = constructTestInterface; + return ConstructTypeHost; + } +}; + +const ClassInfo JSTestInterfaceConstructor::s_info = { "TestInterfaceConstructor", 0, &JSTestInterfaceConstructorTable, 0 }; + +bool JSTestInterfaceConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +{ + return getStaticValueSlot<JSTestInterfaceConstructor, DOMObject>(exec, &JSTestInterfaceConstructorTable, this, propertyName, slot); +} + +bool JSTestInterfaceConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + return getStaticValueDescriptor<JSTestInterfaceConstructor, DOMObject>(exec, &JSTestInterfaceConstructorTable, this, propertyName, descriptor); +} + +/* Hash table for prototype */ +#if ENABLE(JIT) +#define THUNK_GENERATOR(generator) , generator +#else +#define THUNK_GENERATOR(generator) +#endif + +static const HashTableValue JSTestInterfacePrototypeTableValues[1] = +{ + { 0, 0, 0, 0 THUNK_GENERATOR(0) } +}; + +#undef THUNK_GENERATOR +static JSC_CONST_HASHTABLE HashTable JSTestInterfacePrototypeTable = +#if ENABLE(PERFECT_HASH_SIZE) + { 0, JSTestInterfacePrototypeTableValues, 0 }; +#else + { 1, 0, JSTestInterfacePrototypeTableValues, 0 }; +#endif + +const ClassInfo JSTestInterfacePrototype::s_info = { "TestInterfacePrototype", 0, &JSTestInterfacePrototypeTable, 0 }; + +JSObject* JSTestInterfacePrototype::self(ExecState* exec, JSGlobalObject* globalObject) +{ + return getDOMPrototype<JSTestInterface>(exec, globalObject); +} + +const ClassInfo JSTestInterface::s_info = { "TestInterface", 0, &JSTestInterfaceTable, 0 }; + +JSTestInterface::JSTestInterface(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<TestInterface> impl) + : DOMObjectWithGlobalPointer(structure, globalObject) + , m_impl(impl) +{ +} + +JSTestInterface::~JSTestInterface() +{ + forgetDOMObject(this, impl()); +} + +JSObject* JSTestInterface::createPrototype(ExecState* exec, JSGlobalObject* globalObject) +{ + return new (exec) JSTestInterfacePrototype(JSTestInterfacePrototype::createStructure(globalObject->objectPrototype())); +} + +bool JSTestInterface::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +{ + return getStaticValueSlot<JSTestInterface, Base>(exec, &JSTestInterfaceTable, this, propertyName, slot); +} + +bool JSTestInterface::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + return getStaticValueDescriptor<JSTestInterface, Base>(exec, &JSTestInterfaceTable, this, propertyName, descriptor); +} + +JSValue jsTestInterfaceConstructor(ExecState* exec, JSValue slotBase, const Identifier&) +{ + JSTestInterface* domObject = static_cast<JSTestInterface*>(asObject(slotBase)); + return JSTestInterface::getConstructor(exec, domObject->globalObject()); +} +JSValue JSTestInterface::getConstructor(ExecState* exec, JSGlobalObject* globalObject) +{ + return getDOMConstructor<JSTestInterfaceConstructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject)); +} + +JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, TestInterface* object) +{ + return getDOMObjectWrapper<JSTestInterface>(exec, globalObject, object); +} +TestInterface* toTestInterface(JSC::JSValue value) +{ + return value.inherits(&JSTestInterface::s_info) ? static_cast<JSTestInterface*>(asObject(value))->impl() : 0; +} + +} diff --git a/WebCore/bindings/scripts/test/JS/JSTestInterface.h b/WebCore/bindings/scripts/test/JS/JSTestInterface.h new file mode 100644 index 0000000..c076dbd --- /dev/null +++ b/WebCore/bindings/scripts/test/JS/JSTestInterface.h @@ -0,0 +1,81 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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 JSTestInterface_h +#define JSTestInterface_h + +#include "JSDOMBinding.h" +#include <runtime/JSGlobalObject.h> +#include <runtime/ObjectPrototype.h> + +namespace WebCore { + +class TestInterface; + +class JSTestInterface : public DOMObjectWithGlobalPointer { + typedef DOMObjectWithGlobalPointer Base; +public: + JSTestInterface(NonNullPassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<TestInterface>); + virtual ~JSTestInterface(); + static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*); + virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); + virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&); + virtual const JSC::ClassInfo* classInfo() const { return &s_info; } + static const JSC::ClassInfo s_info; + + static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + { + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount); + } + + static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); + TestInterface* impl() const { return m_impl.get(); } + +private: + RefPtr<TestInterface> m_impl; +protected: + static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | Base::StructureFlags; +}; + +JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, TestInterface*); +TestInterface* toTestInterface(JSC::JSValue); + +class JSTestInterfacePrototype : public JSC::JSObject { + typedef JSC::JSObject Base; +public: + static JSC::JSObject* self(JSC::ExecState*, JSC::JSGlobalObject*); + virtual const JSC::ClassInfo* classInfo() const { return &s_info; } + static const JSC::ClassInfo s_info; + static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + { + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount); + } + JSTestInterfacePrototype(NonNullPassRefPtr<JSC::Structure> structure) : JSC::JSObject(structure) { } +protected: + static const unsigned StructureFlags = Base::StructureFlags; +}; + +// Attributes + +JSC::JSValue jsTestInterfaceConstructor(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); + +} // namespace WebCore + +#endif diff --git a/WebCore/bindings/scripts/test/JS/JSTestObj.cpp b/WebCore/bindings/scripts/test/JS/JSTestObj.cpp new file mode 100644 index 0000000..da99de2 --- /dev/null +++ b/WebCore/bindings/scripts/test/JS/JSTestObj.cpp @@ -0,0 +1,813 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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 "JSTestObj.h" + +#include "JSEventListener.h" +#include "JSTestObj.h" +#include "JSlog.h" +#include "KURL.h" +#include "ScriptCallStack.h" +#include "SerializedScriptValue.h" +#include "TestObj.h" +#include <runtime/Error.h> +#include <runtime/JSNumberCell.h> +#include <runtime/JSString.h> +#include <wtf/GetPtr.h> + +using namespace JSC; + +namespace WebCore { + +ASSERT_CLASS_FITS_IN_CELL(JSTestObj); + +/* Hash table */ +#if ENABLE(JIT) +#define THUNK_GENERATOR(generator) , generator +#else +#define THUNK_GENERATOR(generator) +#endif + +static const HashTableValue JSTestObjTableValues[15] = +{ + { "readOnlyIntAttr", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjReadOnlyIntAttr), (intptr_t)0 THUNK_GENERATOR(0) }, + { "readOnlyStringAttr", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjReadOnlyStringAttr), (intptr_t)0 THUNK_GENERATOR(0) }, + { "readOnlyTestObjAttr", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjReadOnlyTestObjAttr), (intptr_t)0 THUNK_GENERATOR(0) }, + { "intAttr", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjIntAttr), (intptr_t)setJSTestObjIntAttr THUNK_GENERATOR(0) }, + { "longLongAttr", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjLongLongAttr), (intptr_t)setJSTestObjLongLongAttr THUNK_GENERATOR(0) }, + { "unsignedLongLongAttr", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjUnsignedLongLongAttr), (intptr_t)setJSTestObjUnsignedLongLongAttr THUNK_GENERATOR(0) }, + { "stringAttr", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjStringAttr), (intptr_t)setJSTestObjStringAttr THUNK_GENERATOR(0) }, + { "testObjAttr", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjTestObjAttr), (intptr_t)setJSTestObjTestObjAttr THUNK_GENERATOR(0) }, + { "attrWithException", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjAttrWithException), (intptr_t)setJSTestObjAttrWithException THUNK_GENERATOR(0) }, + { "attrWithSetterException", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjAttrWithSetterException), (intptr_t)setJSTestObjAttrWithSetterException THUNK_GENERATOR(0) }, + { "attrWithGetterException", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjAttrWithGetterException), (intptr_t)setJSTestObjAttrWithGetterException THUNK_GENERATOR(0) }, + { "customAttr", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjCustomAttr), (intptr_t)setJSTestObjCustomAttr THUNK_GENERATOR(0) }, + { "scriptStringAttr", DontDelete|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjScriptStringAttr), (intptr_t)0 THUNK_GENERATOR(0) }, + { "constructor", DontEnum|ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjConstructor), (intptr_t)0 THUNK_GENERATOR(0) }, + { 0, 0, 0, 0 THUNK_GENERATOR(0) } +}; + +#undef THUNK_GENERATOR +static JSC_CONST_HASHTABLE HashTable JSTestObjTable = +#if ENABLE(PERFECT_HASH_SIZE) + { 127, JSTestObjTableValues, 0 }; +#else + { 34, 31, JSTestObjTableValues, 0 }; +#endif + +/* Hash table for constructor */ +#if ENABLE(JIT) +#define THUNK_GENERATOR(generator) , generator +#else +#define THUNK_GENERATOR(generator) +#endif + +static const HashTableValue JSTestObjConstructorTableValues[1] = +{ + { 0, 0, 0, 0 THUNK_GENERATOR(0) } +}; + +#undef THUNK_GENERATOR +static JSC_CONST_HASHTABLE HashTable JSTestObjConstructorTable = +#if ENABLE(PERFECT_HASH_SIZE) + { 0, JSTestObjConstructorTableValues, 0 }; +#else + { 1, 0, JSTestObjConstructorTableValues, 0 }; +#endif + +class JSTestObjConstructor : public DOMConstructorObject { +public: + JSTestObjConstructor(ExecState* exec, JSDOMGlobalObject* globalObject) + : DOMConstructorObject(JSTestObjConstructor::createStructure(globalObject->objectPrototype()), globalObject) + { + putDirect(exec->propertyNames().prototype, JSTestObjPrototype::self(exec, globalObject), None); + } + virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); + virtual const ClassInfo* classInfo() const { return &s_info; } + static const ClassInfo s_info; + + static PassRefPtr<Structure> createStructure(JSValue proto) + { + return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); + } + +protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | DOMConstructorObject::StructureFlags; +}; + +const ClassInfo JSTestObjConstructor::s_info = { "TestObjConstructor", 0, &JSTestObjConstructorTable, 0 }; + +bool JSTestObjConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +{ + return getStaticValueSlot<JSTestObjConstructor, DOMObject>(exec, &JSTestObjConstructorTable, this, propertyName, slot); +} + +bool JSTestObjConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + return getStaticValueDescriptor<JSTestObjConstructor, DOMObject>(exec, &JSTestObjConstructorTable, this, propertyName, descriptor); +} + +/* Hash table for prototype */ +#if ENABLE(JIT) +#define THUNK_GENERATOR(generator) , generator +#else +#define THUNK_GENERATOR(generator) +#endif + +static const HashTableValue JSTestObjPrototypeTableValues[26] = +{ + { "voidMethod", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionVoidMethod), (intptr_t)0 THUNK_GENERATOR(0) }, + { "voidMethodWithArgs", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionVoidMethodWithArgs), (intptr_t)3 THUNK_GENERATOR(0) }, + { "intMethod", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionIntMethod), (intptr_t)0 THUNK_GENERATOR(0) }, + { "intMethodWithArgs", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionIntMethodWithArgs), (intptr_t)3 THUNK_GENERATOR(0) }, + { "objMethod", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionObjMethod), (intptr_t)0 THUNK_GENERATOR(0) }, + { "objMethodWithArgs", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionObjMethodWithArgs), (intptr_t)3 THUNK_GENERATOR(0) }, + { "serializedValue", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionSerializedValue), (intptr_t)1 THUNK_GENERATOR(0) }, + { "methodWithException", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithException), (intptr_t)0 THUNK_GENERATOR(0) }, + { "customMethod", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionCustomMethod), (intptr_t)0 THUNK_GENERATOR(0) }, + { "customMethodWithArgs", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionCustomMethodWithArgs), (intptr_t)3 THUNK_GENERATOR(0) }, + { "customArgsAndException", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionCustomArgsAndException), (intptr_t)1 THUNK_GENERATOR(0) }, + { "addEventListener", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionAddEventListener), (intptr_t)3 THUNK_GENERATOR(0) }, + { "removeEventListener", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionRemoveEventListener), (intptr_t)3 THUNK_GENERATOR(0) }, + { "withDynamicFrame", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionWithDynamicFrame), (intptr_t)0 THUNK_GENERATOR(0) }, + { "withDynamicFrameAndArg", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionWithDynamicFrameAndArg), (intptr_t)1 THUNK_GENERATOR(0) }, + { "withDynamicFrameAndOptionalArg", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionWithDynamicFrameAndOptionalArg), (intptr_t)2 THUNK_GENERATOR(0) }, + { "withDynamicFrameAndUserGesture", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionWithDynamicFrameAndUserGesture), (intptr_t)1 THUNK_GENERATOR(0) }, + { "withDynamicFrameAndUserGestureASAD", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionWithDynamicFrameAndUserGestureASAD), (intptr_t)2 THUNK_GENERATOR(0) }, + { "withScriptStateVoid", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionWithScriptStateVoid), (intptr_t)0 THUNK_GENERATOR(0) }, + { "withScriptStateObj", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionWithScriptStateObj), (intptr_t)0 THUNK_GENERATOR(0) }, + { "withScriptStateVoidException", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionWithScriptStateVoidException), (intptr_t)0 THUNK_GENERATOR(0) }, + { "withScriptStateObjException", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionWithScriptStateObjException), (intptr_t)0 THUNK_GENERATOR(0) }, + { "methodWithOptionalArg", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithOptionalArg), (intptr_t)1 THUNK_GENERATOR(0) }, + { "methodWithNonOptionalArgAndOptionalArg", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithNonOptionalArgAndOptionalArg), (intptr_t)2 THUNK_GENERATOR(0) }, + { "methodWithNonOptionalArgAndTwoOptionalArgs", DontDelete|Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithNonOptionalArgAndTwoOptionalArgs), (intptr_t)3 THUNK_GENERATOR(0) }, + { 0, 0, 0, 0 THUNK_GENERATOR(0) } +}; + +#undef THUNK_GENERATOR +static JSC_CONST_HASHTABLE HashTable JSTestObjPrototypeTable = +#if ENABLE(PERFECT_HASH_SIZE) + { 8191, JSTestObjPrototypeTableValues, 0 }; +#else + { 67, 63, JSTestObjPrototypeTableValues, 0 }; +#endif + +const ClassInfo JSTestObjPrototype::s_info = { "TestObjPrototype", 0, &JSTestObjPrototypeTable, 0 }; + +JSObject* JSTestObjPrototype::self(ExecState* exec, JSGlobalObject* globalObject) +{ + return getDOMPrototype<JSTestObj>(exec, globalObject); +} + +bool JSTestObjPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +{ + return getStaticFunctionSlot<JSObject>(exec, &JSTestObjPrototypeTable, this, propertyName, slot); +} + +bool JSTestObjPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + return getStaticFunctionDescriptor<JSObject>(exec, &JSTestObjPrototypeTable, this, propertyName, descriptor); +} + +const ClassInfo JSTestObj::s_info = { "TestObj", 0, &JSTestObjTable, 0 }; + +JSTestObj::JSTestObj(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<TestObj> impl) + : DOMObjectWithGlobalPointer(structure, globalObject) + , m_impl(impl) +{ +} + +JSTestObj::~JSTestObj() +{ + forgetDOMObject(this, impl()); +} + +JSObject* JSTestObj::createPrototype(ExecState* exec, JSGlobalObject* globalObject) +{ + return new (exec) JSTestObjPrototype(JSTestObjPrototype::createStructure(globalObject->objectPrototype())); +} + +bool JSTestObj::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +{ + return getStaticValueSlot<JSTestObj, Base>(exec, &JSTestObjTable, this, propertyName, slot); +} + +bool JSTestObj::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + return getStaticValueDescriptor<JSTestObj, Base>(exec, &JSTestObjTable, this, propertyName, descriptor); +} + +JSValue jsTestObjReadOnlyIntAttr(ExecState* exec, JSValue slotBase, const Identifier&) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); + UNUSED_PARAM(exec); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + JSValue result = jsNumber(exec, imp->readOnlyIntAttr()); + return result; +} + +JSValue jsTestObjReadOnlyStringAttr(ExecState* exec, JSValue slotBase, const Identifier&) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); + UNUSED_PARAM(exec); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + JSValue result = jsString(exec, imp->readOnlyStringAttr()); + return result; +} + +JSValue jsTestObjReadOnlyTestObjAttr(ExecState* exec, JSValue slotBase, const Identifier&) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); + UNUSED_PARAM(exec); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->readOnlyTestObjAttr())); + return result; +} + +JSValue jsTestObjIntAttr(ExecState* exec, JSValue slotBase, const Identifier&) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); + UNUSED_PARAM(exec); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + JSValue result = jsNumber(exec, imp->intAttr()); + return result; +} + +JSValue jsTestObjLongLongAttr(ExecState* exec, JSValue slotBase, const Identifier&) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); + UNUSED_PARAM(exec); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + JSValue result = jsNumber(exec, imp->longLongAttr()); + return result; +} + +JSValue jsTestObjUnsignedLongLongAttr(ExecState* exec, JSValue slotBase, const Identifier&) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); + UNUSED_PARAM(exec); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + JSValue result = jsNumber(exec, imp->unsignedLongLongAttr()); + return result; +} + +JSValue jsTestObjStringAttr(ExecState* exec, JSValue slotBase, const Identifier&) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); + UNUSED_PARAM(exec); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + JSValue result = jsString(exec, imp->stringAttr()); + return result; +} + +JSValue jsTestObjTestObjAttr(ExecState* exec, JSValue slotBase, const Identifier&) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); + UNUSED_PARAM(exec); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->testObjAttr())); + return result; +} + +JSValue jsTestObjAttrWithException(ExecState* exec, JSValue slotBase, const Identifier&) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); + UNUSED_PARAM(exec); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + JSValue result = jsNumber(exec, imp->attrWithException()); + return result; +} + +JSValue jsTestObjAttrWithSetterException(ExecState* exec, JSValue slotBase, const Identifier&) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); + UNUSED_PARAM(exec); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + JSValue result = jsNumber(exec, imp->attrWithSetterException()); + return result; +} + +JSValue jsTestObjAttrWithGetterException(ExecState* exec, JSValue slotBase, const Identifier&) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); + UNUSED_PARAM(exec); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + JSValue result = jsNumber(exec, imp->attrWithGetterException()); + return result; +} + +JSValue jsTestObjCustomAttr(ExecState* exec, JSValue slotBase, const Identifier&) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); + return castedThis->customAttr(exec); +} + +JSValue jsTestObjScriptStringAttr(ExecState* exec, JSValue slotBase, const Identifier&) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); + UNUSED_PARAM(exec); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + JSValue result = jsOwnedStringOrNull(exec, imp->scriptStringAttr()); + return result; +} + +JSValue jsTestObjConstructor(ExecState* exec, JSValue slotBase, const Identifier&) +{ + JSTestObj* domObject = static_cast<JSTestObj*>(asObject(slotBase)); + return JSTestObj::getConstructor(exec, domObject->globalObject()); +} +void JSTestObj::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +{ + lookupPut<JSTestObj, Base>(exec, propertyName, value, &JSTestObjTable, this, slot); +} + +void setJSTestObjIntAttr(ExecState* exec, JSObject* thisObject, JSValue value) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(thisObject); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + imp->setIntAttr(value.toInt32(exec)); +} + +void setJSTestObjLongLongAttr(ExecState* exec, JSObject* thisObject, JSValue value) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(thisObject); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + imp->setLongLongAttr(static_cast<long long>(value.toInteger(exec))); +} + +void setJSTestObjUnsignedLongLongAttr(ExecState* exec, JSObject* thisObject, JSValue value) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(thisObject); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + imp->setUnsignedLongLongAttr(static_cast<unsigned long long>(value.toInteger(exec))); +} + +void setJSTestObjStringAttr(ExecState* exec, JSObject* thisObject, JSValue value) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(thisObject); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + imp->setStringAttr(ustringToString(value.toString(exec))); +} + +void setJSTestObjTestObjAttr(ExecState* exec, JSObject* thisObject, JSValue value) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(thisObject); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + imp->setTestObjAttr(toTestObj(value)); +} + +void setJSTestObjAttrWithException(ExecState* exec, JSObject* thisObject, JSValue value) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(thisObject); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + imp->setAttrWithException(value.toInt32(exec)); +} + +void setJSTestObjAttrWithSetterException(ExecState* exec, JSObject* thisObject, JSValue value) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(thisObject); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + imp->setAttrWithSetterException(value.toInt32(exec)); +} + +void setJSTestObjAttrWithGetterException(ExecState* exec, JSObject* thisObject, JSValue value) +{ + JSTestObj* castedThis = static_cast<JSTestObj*>(thisObject); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + imp->setAttrWithGetterException(value.toInt32(exec)); +} + +void setJSTestObjCustomAttr(ExecState* exec, JSObject* thisObject, JSValue value) +{ + static_cast<JSTestObj*>(thisObject)->setCustomAttr(exec, value); +} + +JSValue JSTestObj::getConstructor(ExecState* exec, JSGlobalObject* globalObject) +{ + return getDOMConstructor<JSTestObjConstructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject)); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionVoidMethod(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + + imp->voidMethod(); + return jsUndefined(); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionVoidMethodWithArgs(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + int intArg = args.at(0).toInt32(exec); + const String& strArg = ustringToString(args.at(1).toString(exec)); + TestObj* objArg = toTestObj(args.at(2)); + + imp->voidMethodWithArgs(intArg, strArg, objArg); + return jsUndefined(); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionIntMethod(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + + + JSC::JSValue result = jsNumber(exec, imp->intMethod()); + return result; +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionIntMethodWithArgs(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + int intArg = args.at(0).toInt32(exec); + const String& strArg = ustringToString(args.at(1).toString(exec)); + TestObj* objArg = toTestObj(args.at(2)); + + + JSC::JSValue result = jsNumber(exec, imp->intMethodWithArgs(intArg, strArg, objArg)); + return result; +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionObjMethod(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + + + JSC::JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->objMethod())); + return result; +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionObjMethodWithArgs(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + int intArg = args.at(0).toInt32(exec); + const String& strArg = ustringToString(args.at(1).toString(exec)); + TestObj* objArg = toTestObj(args.at(2)); + + + JSC::JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->objMethodWithArgs(intArg, strArg, objArg))); + return result; +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionSerializedValue(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + RefPtr<SerializedScriptValue> serializedArg = SerializedScriptValue::create(exec, args.at(0)); + + imp->serializedValue(serializedArg); + return jsUndefined(); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithException(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + ExceptionCode ec = 0; + + imp->methodWithException(ec); + setDOMException(exec, ec); + return jsUndefined(); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionCustomMethod(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + return castedThis->customMethod(exec, args); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionCustomMethodWithArgs(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + return castedThis->customMethodWithArgs(exec, args); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionCustomArgsAndException(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + ExceptionCode ec = 0; + ScriptCallStack callStack(exec, args, 1); + log* intArg = tolog(args.at(0)); + + imp->customArgsAndException(intArg, &callStack, ec); + setDOMException(exec, ec); + return jsUndefined(); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionAddEventListener(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + JSValue listener = args.at(1); + if (!listener.isObject()) + return jsUndefined(); + imp->addEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), castedThis, false, currentWorld(exec)), args.at(2).toBoolean(exec)); + return jsUndefined(); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionRemoveEventListener(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + JSValue listener = args.at(1); + if (!listener.isObject()) + return jsUndefined(); + imp->removeEventListener(ustringToAtomicString(args.at(0).toString(exec)), JSEventListener::create(asObject(listener), castedThis, false, currentWorld(exec)).get(), args.at(2).toBoolean(exec)); + return jsUndefined(); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithDynamicFrame(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + Frame* dynamicFrame = toDynamicFrame(exec); + if (!dynamicFrame) + return jsUndefined(); + + imp->withDynamicFrame(dynamicFrame); + return jsUndefined(); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithDynamicFrameAndArg(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + Frame* dynamicFrame = toDynamicFrame(exec); + if (!dynamicFrame) + return jsUndefined(); + int intArg = args.at(1).toInt32(exec); + + imp->withDynamicFrameAndArg(dynamicFrame, intArg); + return jsUndefined(); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithDynamicFrameAndOptionalArg(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + Frame* dynamicFrame = toDynamicFrame(exec); + if (!dynamicFrame) + return jsUndefined(); + int intArg = args.at(1).toInt32(exec); + + int argsCount = args.size(); + if (argsCount < 3) { + imp->withDynamicFrameAndOptionalArg(dynamicFrame, intArg); + return jsUndefined(); + } + + int optionalArg = args.at(2).toInt32(exec); + + imp->withDynamicFrameAndOptionalArg(dynamicFrame, intArg, optionalArg); + return jsUndefined(); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithDynamicFrameAndUserGesture(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + Frame* dynamicFrame = toDynamicFrame(exec); + if (!dynamicFrame) + return jsUndefined(); + int intArg = args.at(1).toInt32(exec); + + imp->withDynamicFrameAndUserGesture(dynamicFrame, intArg, processingUserGesture(exec)); + return jsUndefined(); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithDynamicFrameAndUserGestureASAD(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + Frame* dynamicFrame = toDynamicFrame(exec); + if (!dynamicFrame) + return jsUndefined(); + int intArg = args.at(1).toInt32(exec); + + int argsCount = args.size(); + if (argsCount < 3) { + imp->withDynamicFrameAndUserGestureASAD(dynamicFrame, intArg); + return jsUndefined(); + } + + int optionalArg = args.at(2).toInt32(exec); + + imp->withDynamicFrameAndUserGestureASAD(dynamicFrame, intArg, optionalArg, processingUserGesture(exec)); + return jsUndefined(); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithScriptStateVoid(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + + imp->withScriptStateVoid(exec); + return jsUndefined(); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithScriptStateObj(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + + + JSC::JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->withScriptStateObj(exec))); + if (exec->hadException()) + return jsUndefined(); + return result; +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithScriptStateVoidException(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + ExceptionCode ec = 0; + + imp->withScriptStateVoidException(exec, ec); + setDOMException(exec, ec); + return jsUndefined(); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithScriptStateObjException(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + ExceptionCode ec = 0; + + + JSC::JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->withScriptStateObjException(exec, ec))); + setDOMException(exec, ec); + if (exec->hadException()) + return jsUndefined(); + return result; +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithOptionalArg(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + + int argsCount = args.size(); + if (argsCount < 1) { + imp->methodWithOptionalArg(); + return jsUndefined(); + } + + int opt = args.at(0).toInt32(exec); + + imp->methodWithOptionalArg(opt); + return jsUndefined(); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithNonOptionalArgAndOptionalArg(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + int nonOpt = args.at(0).toInt32(exec); + + int argsCount = args.size(); + if (argsCount < 2) { + imp->methodWithNonOptionalArgAndOptionalArg(nonOpt); + return jsUndefined(); + } + + int opt = args.at(1).toInt32(exec); + + imp->methodWithNonOptionalArgAndOptionalArg(nonOpt, opt); + return jsUndefined(); +} + +JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithNonOptionalArgAndTwoOptionalArgs(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) +{ + UNUSED_PARAM(args); + if (!thisValue.inherits(&JSTestObj::s_info)) + return throwError(exec, TypeError); + JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(thisValue)); + TestObj* imp = static_cast<TestObj*>(castedThis->impl()); + int nonOpt = args.at(0).toInt32(exec); + + int argsCount = args.size(); + if (argsCount < 2) { + imp->methodWithNonOptionalArgAndTwoOptionalArgs(nonOpt); + return jsUndefined(); + } + + int opt1 = args.at(1).toInt32(exec); + if (argsCount < 3) { + imp->methodWithNonOptionalArgAndTwoOptionalArgs(nonOpt, opt1); + return jsUndefined(); + } + + int opt2 = args.at(2).toInt32(exec); + + imp->methodWithNonOptionalArgAndTwoOptionalArgs(nonOpt, opt1, opt2); + return jsUndefined(); +} + +JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, TestObj* object) +{ + return getDOMObjectWrapper<JSTestObj>(exec, globalObject, object); +} +TestObj* toTestObj(JSC::JSValue value) +{ + return value.inherits(&JSTestObj::s_info) ? static_cast<JSTestObj*>(asObject(value))->impl() : 0; +} + +} diff --git a/WebCore/bindings/scripts/test/JS/JSTestObj.h b/WebCore/bindings/scripts/test/JS/JSTestObj.h new file mode 100644 index 0000000..f726efb --- /dev/null +++ b/WebCore/bindings/scripts/test/JS/JSTestObj.h @@ -0,0 +1,141 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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 JSTestObj_h +#define JSTestObj_h + +#include "JSDOMBinding.h" +#include <runtime/JSGlobalObject.h> +#include <runtime/ObjectPrototype.h> + +namespace WebCore { + +class TestObj; + +class JSTestObj : public DOMObjectWithGlobalPointer { + typedef DOMObjectWithGlobalPointer Base; +public: + JSTestObj(NonNullPassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<TestObj>); + virtual ~JSTestObj(); + static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*); + virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); + virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&); + virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); + virtual const JSC::ClassInfo* classInfo() const { return &s_info; } + static const JSC::ClassInfo s_info; + + static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + { + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount); + } + + static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); + + // Custom attributes + JSC::JSValue customAttr(JSC::ExecState*) const; + void setCustomAttr(JSC::ExecState*, JSC::JSValue); + + // Custom functions + JSC::JSValue customMethod(JSC::ExecState*, const JSC::ArgList&); + JSC::JSValue customMethodWithArgs(JSC::ExecState*, const JSC::ArgList&); + TestObj* impl() const { return m_impl.get(); } + +private: + RefPtr<TestObj> m_impl; +protected: + static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | Base::StructureFlags; +}; + +JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, TestObj*); +TestObj* toTestObj(JSC::JSValue); + +class JSTestObjPrototype : public JSC::JSObject { + typedef JSC::JSObject Base; +public: + static JSC::JSObject* self(JSC::ExecState*, JSC::JSGlobalObject*); + virtual const JSC::ClassInfo* classInfo() const { return &s_info; } + static const JSC::ClassInfo s_info; + virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&); + virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&); + static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + { + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount); + } + JSTestObjPrototype(NonNullPassRefPtr<JSC::Structure> structure) : JSC::JSObject(structure) { } +protected: + static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | Base::StructureFlags; +}; + +// Functions + +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionVoidMethod(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionVoidMethodWithArgs(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionIntMethod(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionIntMethodWithArgs(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionObjMethod(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionObjMethodWithArgs(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionSerializedValue(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithException(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionCustomMethod(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionCustomMethodWithArgs(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionCustomArgsAndException(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionAddEventListener(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionRemoveEventListener(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithDynamicFrame(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithDynamicFrameAndArg(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithDynamicFrameAndOptionalArg(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithDynamicFrameAndUserGesture(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithDynamicFrameAndUserGestureASAD(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithScriptStateVoid(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithScriptStateObj(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithScriptStateVoidException(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionWithScriptStateObjException(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithOptionalArg(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithNonOptionalArgAndOptionalArg(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +JSC::JSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithNonOptionalArgAndTwoOptionalArgs(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +// Attributes + +JSC::JSValue jsTestObjReadOnlyIntAttr(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +JSC::JSValue jsTestObjReadOnlyStringAttr(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +JSC::JSValue jsTestObjReadOnlyTestObjAttr(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +JSC::JSValue jsTestObjIntAttr(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +void setJSTestObjIntAttr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); +JSC::JSValue jsTestObjLongLongAttr(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +void setJSTestObjLongLongAttr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); +JSC::JSValue jsTestObjUnsignedLongLongAttr(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +void setJSTestObjUnsignedLongLongAttr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); +JSC::JSValue jsTestObjStringAttr(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +void setJSTestObjStringAttr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); +JSC::JSValue jsTestObjTestObjAttr(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +void setJSTestObjTestObjAttr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); +JSC::JSValue jsTestObjAttrWithException(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +void setJSTestObjAttrWithException(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); +JSC::JSValue jsTestObjAttrWithSetterException(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +void setJSTestObjAttrWithSetterException(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); +JSC::JSValue jsTestObjAttrWithGetterException(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +void setJSTestObjAttrWithGetterException(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); +JSC::JSValue jsTestObjCustomAttr(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +void setJSTestObjCustomAttr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); +JSC::JSValue jsTestObjScriptStringAttr(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +JSC::JSValue jsTestObjConstructor(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); + +} // namespace WebCore + +#endif diff --git a/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.h b/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.h new file mode 100644 index 0000000..1213c6f --- /dev/null +++ b/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.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. + * + * 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. + */ + +#import <WebCore/DOMObject.h> + +#if WEBKIT_VERSION_MAX_ALLOWED >= WEBKIT_VERSION_LATEST + +@class DOMClass1; +@class DOMClass2; +@class DOMClass3; +@class DOMClass5; +@class DOMClass6; +@class NSString; + +@interface DOMTestCallback : DOMObject +- (BOOL)callbackWithClass1Param:(DOMClass1 *)class1Param; +- (BOOL)callbackWithClass2Param:(DOMClass2 *)class2Param strArg:(NSString *)strArg; +- (int)callbackWithNonBoolReturnType:(DOMClass3 *)class3Param; +- (int)customCallback:(DOMClass5 *)class5Param class6Param:(DOMClass6 *)class6Param; +@end + +#endif diff --git a/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.mm b/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.mm new file mode 100644 index 0000000..5201a91 --- /dev/null +++ b/WebCore/bindings/scripts/test/ObjC/DOMTestCallback.mm @@ -0,0 +1,122 @@ +/* + * This file is part of the WebKit open source project. + * This file has been generated by generate-bindings.pl. DO NOT MODIFY! + * + * 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. + */ + +#import "config.h" + +#if ENABLE(DATABASE) + +#import "DOMInternal.h" + +#import "DOMTestCallback.h" + +#import "Class1.h" +#import "Class2.h" +#import "Class3.h" +#import "Class5.h" +#import "Class6.h" +#import "DOMBlobInternal.h" +#import "DOMCSSRuleInternal.h" +#import "DOMCSSValueInternal.h" +#import "DOMClass1Internal.h" +#import "DOMClass2Internal.h" +#import "DOMClass3Internal.h" +#import "DOMClass5Internal.h" +#import "DOMClass6Internal.h" +#import "DOMEventInternal.h" +#import "DOMNodeInternal.h" +#import "DOMStyleSheetInternal.h" +#import "DOMTestCallbackInternal.h" +#import "ExceptionHandlers.h" +#import "KURL.h" +#import "TestCallback.h" +#import "ThreadCheck.h" +#import "WebCoreObjCExtras.h" +#import "WebScriptObjectPrivate.h" +#import <wtf/GetPtr.h> + +#define IMPL reinterpret_cast<WebCore::TestCallback*>(_internal) + +@implementation DOMTestCallback + +- (void)dealloc +{ + if (WebCoreObjCScheduleDeallocateOnMainThread([DOMTestCallback class], self)) + return; + + if (_internal) + IMPL->deref(); + [super dealloc]; +} + +- (void)finalize +{ + if (_internal) + IMPL->deref(); + [super finalize]; +} + +- (BOOL)callbackWithClass1Param:(DOMClass1 *)class1Param +{ + return IMPL->callbackWithClass1Param(core(class1Param)); +} + +- (BOOL)callbackWithClass2Param:(DOMClass2 *)class2Param strArg:(NSString *)strArg +{ + return IMPL->callbackWithClass2Param(core(class2Param), strArg); +} + +- (int)callbackWithNonBoolReturnType:(DOMClass3 *)class3Param +{ + return IMPL->callbackWithNonBoolReturnType(core(class3Param)); +} + +- (int)customCallback:(DOMClass5 *)class5Param class6Param:(DOMClass6 *)class6Param +{ + return IMPL->customCallback(core(class5Param), core(class6Param)); +} + +@end + +WebCore::TestCallback* core(DOMTestCallback *wrapper) +{ + return wrapper ? reinterpret_cast<WebCore::TestCallback*>(wrapper->_internal) : 0; +} + +DOMTestCallback *kit(WebCore::TestCallback* value) +{ + { DOM_ASSERT_MAIN_THREAD(); WebCoreThreadViolationCheckRoundOne(); }; + if (!value) + return nil; + if (DOMTestCallback *wrapper = getDOMWrapper(value)) + return [[wrapper retain] autorelease]; + DOMTestCallback *wrapper = [[DOMTestCallback alloc] _init]; + wrapper->_internal = reinterpret_cast<DOMObjectInternal*>(value); + value->ref(); + addDOMWrapper(wrapper, value); + return [wrapper autorelease]; +} + +#endif // ENABLE(DATABASE) diff --git a/WebCore/bindings/scripts/test/ObjC/DOMTestCallbackInternal.h b/WebCore/bindings/scripts/test/ObjC/DOMTestCallbackInternal.h new file mode 100644 index 0000000..d8ea940 --- /dev/null +++ b/WebCore/bindings/scripts/test/ObjC/DOMTestCallbackInternal.h @@ -0,0 +1,38 @@ +/* + * This file is part of the WebKit open source project. + * This file has been generated by generate-bindings.pl. DO NOT MODIFY! + * + * 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. + */ + +#import <WebCore/DOMTestCallback.h> + +#if WEBKIT_VERSION_MAX_ALLOWED >= WEBKIT_VERSION_LATEST + +namespace WebCore { + class TestCallback; +} + +WebCore::TestCallback* core(DOMTestCallback *); +DOMTestCallback *kit(WebCore::TestCallback*); + +#endif diff --git a/WebCore/bindings/js/JSDocumentFragmentCustom.cpp b/WebCore/bindings/scripts/test/ObjC/DOMTestInterface.h index 7bc7d68..db7be28 100644 --- a/WebCore/bindings/js/JSDocumentFragmentCustom.cpp +++ b/WebCore/bindings/scripts/test/ObjC/DOMTestInterface.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +11,10 @@ * 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 INC. ``AS IS'' AND ANY + * 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 INC. OR + * 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 @@ -23,18 +24,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "JSDocumentFragment.h" +#import <WebCore/DOMObject.h> -#include "DocumentFragment.h" -#include "Element.h" -#include "ExceptionCode.h" -#include "JSElement.h" -#include "JSNodeList.h" -#include "NodeList.h" +#if WEBKIT_VERSION_MAX_ALLOWED >= WEBKIT_VERSION_LATEST -using namespace JSC; +@interface DOMTestInterface : DOMObject +@end -namespace WebCore { - -} // namespace WebCore +#endif diff --git a/WebCore/bindings/scripts/test/ObjC/DOMTestInterface.mm b/WebCore/bindings/scripts/test/ObjC/DOMTestInterface.mm new file mode 100644 index 0000000..a88b366 --- /dev/null +++ b/WebCore/bindings/scripts/test/ObjC/DOMTestInterface.mm @@ -0,0 +1,86 @@ +/* + * This file is part of the WebKit open source project. + * This file has been generated by generate-bindings.pl. DO NOT MODIFY! + * + * 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. + */ + +#import "config.h" +#import "DOMInternal.h" + +#import "DOMTestInterface.h" + +#import "DOMBlobInternal.h" +#import "DOMCSSRuleInternal.h" +#import "DOMCSSValueInternal.h" +#import "DOMEventInternal.h" +#import "DOMNodeInternal.h" +#import "DOMStyleSheetInternal.h" +#import "DOMTestInterfaceInternal.h" +#import "ExceptionHandlers.h" +#import "TestInterface.h" +#import "ThreadCheck.h" +#import "WebCoreObjCExtras.h" +#import "WebScriptObjectPrivate.h" +#import <wtf/GetPtr.h> + +#define IMPL reinterpret_cast<WebCore::TestInterface*>(_internal) + +@implementation DOMTestInterface + +- (void)dealloc +{ + if (WebCoreObjCScheduleDeallocateOnMainThread([DOMTestInterface class], self)) + return; + + if (_internal) + IMPL->deref(); + [super dealloc]; +} + +- (void)finalize +{ + if (_internal) + IMPL->deref(); + [super finalize]; +} + +@end + +WebCore::TestInterface* core(DOMTestInterface *wrapper) +{ + return wrapper ? reinterpret_cast<WebCore::TestInterface*>(wrapper->_internal) : 0; +} + +DOMTestInterface *kit(WebCore::TestInterface* value) +{ + { DOM_ASSERT_MAIN_THREAD(); WebCoreThreadViolationCheckRoundOne(); }; + if (!value) + return nil; + if (DOMTestInterface *wrapper = getDOMWrapper(value)) + return [[wrapper retain] autorelease]; + DOMTestInterface *wrapper = [[DOMTestInterface alloc] _init]; + wrapper->_internal = reinterpret_cast<DOMObjectInternal*>(value); + value->ref(); + addDOMWrapper(wrapper, value); + return [wrapper autorelease]; +} diff --git a/WebCore/bindings/scripts/test/ObjC/DOMTestInterfaceInternal.h b/WebCore/bindings/scripts/test/ObjC/DOMTestInterfaceInternal.h new file mode 100644 index 0000000..fef60a3 --- /dev/null +++ b/WebCore/bindings/scripts/test/ObjC/DOMTestInterfaceInternal.h @@ -0,0 +1,38 @@ +/* + * This file is part of the WebKit open source project. + * This file has been generated by generate-bindings.pl. DO NOT MODIFY! + * + * 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. + */ + +#import <WebCore/DOMTestInterface.h> + +#if WEBKIT_VERSION_MAX_ALLOWED >= WEBKIT_VERSION_LATEST + +namespace WebCore { + class TestInterface; +} + +WebCore::TestInterface* core(DOMTestInterface *); +DOMTestInterface *kit(WebCore::TestInterface*); + +#endif diff --git a/WebCore/bindings/scripts/test/ObjC/DOMTestObj.h b/WebCore/bindings/scripts/test/ObjC/DOMTestObj.h new file mode 100644 index 0000000..dd9d2ee --- /dev/null +++ b/WebCore/bindings/scripts/test/ObjC/DOMTestObj.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.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. + * + * 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. + */ + +#import <WebCore/DOMObject.h> + +#if WEBKIT_VERSION_MAX_ALLOWED >= WEBKIT_VERSION_LATEST + +@class DOMTestObj; +@class DOMlog; +@class NSString; +@protocol DOMEventListener; + +@interface DOMTestObj : DOMObject +- (int)readOnlyIntAttr; +- (NSString *)readOnlyStringAttr; +- (DOMTestObj *)readOnlyTestObjAttr; +- (int)intAttr; +- (void)setIntAttr:(int)newIntAttr; +- (long long)longLongAttr; +- (void)setLongLongAttr:(long long)newLongLongAttr; +- (unsigned long long)unsignedLongLongAttr; +- (void)setUnsignedLongLongAttr:(unsigned long long)newUnsignedLongLongAttr; +- (NSString *)stringAttr; +- (void)setStringAttr:(NSString *)newStringAttr; +- (DOMTestObj *)testObjAttr; +- (void)setTestObjAttr:(DOMTestObj *)newTestObjAttr; +- (int)attrWithException; +- (void)setAttrWithException:(int)newAttrWithException; +- (int)attrWithSetterException; +- (void)setAttrWithSetterException:(int)newAttrWithSetterException; +- (int)attrWithGetterException; +- (void)setAttrWithGetterException:(int)newAttrWithGetterException; +- (int)customAttr; +- (void)setCustomAttr:(int)newCustomAttr; +- (NSString *)scriptStringAttr; +- (void)voidMethod; +- (void)voidMethodWithArgs:(int)intArg strArg:(NSString *)strArg objArg:(DOMTestObj *)objArg; +- (int)intMethod; +- (int)intMethodWithArgs:(int)intArg strArg:(NSString *)strArg objArg:(DOMTestObj *)objArg; +- (DOMTestObj *)objMethod; +- (DOMTestObj *)objMethodWithArgs:(int)intArg strArg:(NSString *)strArg objArg:(DOMTestObj *)objArg; +- (void)serializedValue:(NSString *)serializedArg; +- (void)methodWithException; +- (void)customMethod; +- (void)customMethodWithArgs:(int)intArg strArg:(NSString *)strArg objArg:(DOMTestObj *)objArg; +- (void)customArgsAndException:(DOMlog *)intArg; +- (void)addEventListener:(NSString *)type listener:(id <DOMEventListener>)listener useCapture:(BOOL)useCapture; +- (void)removeEventListener:(NSString *)type listener:(id <DOMEventListener>)listener useCapture:(BOOL)useCapture; +- (void)withDynamicFrame; +- (void)withDynamicFrameAndArg:(int)intArg; +- (void)withDynamicFrameAndOptionalArg:(int)intArg optionalArg:(int)optionalArg; +- (void)withDynamicFrameAndUserGesture:(int)intArg; +- (void)withDynamicFrameAndUserGestureASAD:(int)intArg optionalArg:(int)optionalArg; +- (void)withScriptStateVoid; +- (DOMTestObj *)withScriptStateObj; +- (void)withScriptStateVoidException; +- (DOMTestObj *)withScriptStateObjException; +- (void)methodWithOptionalArg:(int)opt; +- (void)methodWithNonOptionalArgAndOptionalArg:(int)nonOpt opt:(int)opt; +- (void)methodWithNonOptionalArgAndTwoOptionalArgs:(int)nonOpt opt1:(int)opt1 opt2:(int)opt2; +@end + +#endif diff --git a/WebCore/bindings/scripts/test/ObjC/DOMTestObj.mm b/WebCore/bindings/scripts/test/ObjC/DOMTestObj.mm new file mode 100644 index 0000000..b964e36 --- /dev/null +++ b/WebCore/bindings/scripts/test/ObjC/DOMTestObj.mm @@ -0,0 +1,340 @@ +/* + * This file is part of the WebKit open source project. + * This file has been generated by generate-bindings.pl. DO NOT MODIFY! + * + * 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. + */ + +#import "config.h" +#import "DOMInternal.h" + +#import "DOMTestObj.h" + +#import "DOMBlobInternal.h" +#import "DOMCSSRuleInternal.h" +#import "DOMCSSValueInternal.h" +#import "DOMEventInternal.h" +#import "DOMNodeInternal.h" +#import "DOMStyleSheetInternal.h" +#import "DOMTestObjInternal.h" +#import "DOMlogInternal.h" +#import "EventListener.h" +#import "ExceptionHandlers.h" +#import "KURL.h" +#import "ObjCEventListener.h" +#import "SerializedScriptValue.h" +#import "TestObj.h" +#import "ThreadCheck.h" +#import "WebCoreObjCExtras.h" +#import "WebScriptObjectPrivate.h" +#import "log.h" +#import <wtf/GetPtr.h> + +#define IMPL reinterpret_cast<WebCore::TestObj*>(_internal) + +@implementation DOMTestObj + +- (void)dealloc +{ + if (WebCoreObjCScheduleDeallocateOnMainThread([DOMTestObj class], self)) + return; + + if (_internal) + IMPL->deref(); + [super dealloc]; +} + +- (void)finalize +{ + if (_internal) + IMPL->deref(); + [super finalize]; +} + +- (int)readOnlyIntAttr +{ + return IMPL->readOnlyIntAttr(); +} + +- (NSString *)readOnlyStringAttr +{ + return IMPL->readOnlyStringAttr(); +} + +- (DOMTestObj *)readOnlyTestObjAttr +{ + return kit(WTF::getPtr(IMPL->readOnlyTestObjAttr())); +} + +- (int)intAttr +{ + return IMPL->intAttr(); +} + +- (void)setIntAttr:(int)newIntAttr +{ + IMPL->setIntAttr(newIntAttr); +} + +- (long long)longLongAttr +{ + return IMPL->longLongAttr(); +} + +- (void)setLongLongAttr:(long long)newLongLongAttr +{ + IMPL->setLongLongAttr(newLongLongAttr); +} + +- (unsigned long long)unsignedLongLongAttr +{ + return IMPL->unsignedLongLongAttr(); +} + +- (void)setUnsignedLongLongAttr:(unsigned long long)newUnsignedLongLongAttr +{ + IMPL->setUnsignedLongLongAttr(newUnsignedLongLongAttr); +} + +- (NSString *)stringAttr +{ + return IMPL->stringAttr(); +} + +- (void)setStringAttr:(NSString *)newStringAttr +{ + IMPL->setStringAttr(newStringAttr); +} + +- (DOMTestObj *)testObjAttr +{ + return kit(WTF::getPtr(IMPL->testObjAttr())); +} + +- (void)setTestObjAttr:(DOMTestObj *)newTestObjAttr +{ + ASSERT(newTestObjAttr); + + IMPL->setTestObjAttr(core(newTestObjAttr)); +} + +- (int)attrWithException +{ + return IMPL->attrWithException(); +} + +- (void)setAttrWithException:(int)newAttrWithException +{ + IMPL->setAttrWithException(newAttrWithException); +} + +- (int)attrWithSetterException +{ + return IMPL->attrWithSetterException(); +} + +- (void)setAttrWithSetterException:(int)newAttrWithSetterException +{ + IMPL->setAttrWithSetterException(newAttrWithSetterException); +} + +- (int)attrWithGetterException +{ + return IMPL->attrWithGetterException(); +} + +- (void)setAttrWithGetterException:(int)newAttrWithGetterException +{ + IMPL->setAttrWithGetterException(newAttrWithGetterException); +} + +- (int)customAttr +{ + return IMPL->customAttr(); +} + +- (void)setCustomAttr:(int)newCustomAttr +{ + IMPL->setCustomAttr(newCustomAttr); +} + +- (NSString *)scriptStringAttr +{ + return IMPL->scriptStringAttr(); +} + +- (void)voidMethod +{ + IMPL->voidMethod(); +} + +- (void)voidMethodWithArgs:(int)intArg strArg:(NSString *)strArg objArg:(DOMTestObj *)objArg +{ + IMPL->voidMethodWithArgs(intArg, strArg, core(objArg)); +} + +- (int)intMethod +{ + return IMPL->intMethod(); +} + +- (int)intMethodWithArgs:(int)intArg strArg:(NSString *)strArg objArg:(DOMTestObj *)objArg +{ + return IMPL->intMethodWithArgs(intArg, strArg, core(objArg)); +} + +- (DOMTestObj *)objMethod +{ + return kit(WTF::getPtr(IMPL->objMethod())); +} + +- (DOMTestObj *)objMethodWithArgs:(int)intArg strArg:(NSString *)strArg objArg:(DOMTestObj *)objArg +{ + return kit(WTF::getPtr(IMPL->objMethodWithArgs(intArg, strArg, core(objArg)))); +} + +- (void)serializedValue:(NSString *)serializedArg +{ + IMPL->serializedValue(WebCore::SerializedScriptValue::create(WebCore::String(serializedArg))); +} + +- (void)methodWithException +{ + WebCore::ExceptionCode ec = 0; + IMPL->methodWithException(ec); + WebCore::raiseOnDOMError(ec); +} + +- (void)customMethod +{ + IMPL->customMethod(); +} + +- (void)customMethodWithArgs:(int)intArg strArg:(NSString *)strArg objArg:(DOMTestObj *)objArg +{ + IMPL->customMethodWithArgs(intArg, strArg, core(objArg)); +} + +- (void)customArgsAndException:(DOMlog *)intArg +{ + WebCore::ExceptionCode ec = 0; + IMPL->customArgsAndException(core(intArg), ec); + WebCore::raiseOnDOMError(ec); +} + +- (void)addEventListener:(NSString *)type listener:(id <DOMEventListener>)listener useCapture:(BOOL)useCapture +{ + RefPtr<WebCore::EventListener> nativeEventListener = WebCore::ObjCEventListener::wrap(listener); + IMPL->addEventListener(type, WTF::getPtr(nativeEventListener), useCapture); +} + +- (void)removeEventListener:(NSString *)type listener:(id <DOMEventListener>)listener useCapture:(BOOL)useCapture +{ + RefPtr<WebCore::EventListener> nativeEventListener = WebCore::ObjCEventListener::wrap(listener); + IMPL->removeEventListener(type, WTF::getPtr(nativeEventListener), useCapture); +} + +- (void)withDynamicFrame +{ + IMPL->withDynamicFrame(); +} + +- (void)withDynamicFrameAndArg:(int)intArg +{ + IMPL->withDynamicFrameAndArg(intArg); +} + +- (void)withDynamicFrameAndOptionalArg:(int)intArg optionalArg:(int)optionalArg +{ + IMPL->withDynamicFrameAndOptionalArg(intArg, optionalArg); +} + +- (void)withDynamicFrameAndUserGesture:(int)intArg +{ + IMPL->withDynamicFrameAndUserGesture(intArg); +} + +- (void)withDynamicFrameAndUserGestureASAD:(int)intArg optionalArg:(int)optionalArg +{ + IMPL->withDynamicFrameAndUserGestureASAD(intArg, optionalArg); +} + +- (void)withScriptStateVoid +{ + IMPL->withScriptStateVoid(); +} + +- (DOMTestObj *)withScriptStateObj +{ + return kit(WTF::getPtr(IMPL->withScriptStateObj())); +} + +- (void)withScriptStateVoidException +{ + WebCore::ExceptionCode ec = 0; + IMPL->withScriptStateVoidException(ec); + WebCore::raiseOnDOMError(ec); +} + +- (DOMTestObj *)withScriptStateObjException +{ + WebCore::ExceptionCode ec = 0; + DOMTestObj *result = kit(WTF::getPtr(IMPL->withScriptStateObjException(ec))); + WebCore::raiseOnDOMError(ec); + return result; +} + +- (void)methodWithOptionalArg:(int)opt +{ + IMPL->methodWithOptionalArg(opt); +} + +- (void)methodWithNonOptionalArgAndOptionalArg:(int)nonOpt opt:(int)opt +{ + IMPL->methodWithNonOptionalArgAndOptionalArg(nonOpt, opt); +} + +- (void)methodWithNonOptionalArgAndTwoOptionalArgs:(int)nonOpt opt1:(int)opt1 opt2:(int)opt2 +{ + IMPL->methodWithNonOptionalArgAndTwoOptionalArgs(nonOpt, opt1, opt2); +} + +@end + +WebCore::TestObj* core(DOMTestObj *wrapper) +{ + return wrapper ? reinterpret_cast<WebCore::TestObj*>(wrapper->_internal) : 0; +} + +DOMTestObj *kit(WebCore::TestObj* value) +{ + { DOM_ASSERT_MAIN_THREAD(); WebCoreThreadViolationCheckRoundOne(); }; + if (!value) + return nil; + if (DOMTestObj *wrapper = getDOMWrapper(value)) + return [[wrapper retain] autorelease]; + DOMTestObj *wrapper = [[DOMTestObj alloc] _init]; + wrapper->_internal = reinterpret_cast<DOMObjectInternal*>(value); + value->ref(); + addDOMWrapper(wrapper, value); + return [wrapper autorelease]; +} diff --git a/WebCore/bindings/scripts/test/ObjC/DOMTestObjInternal.h b/WebCore/bindings/scripts/test/ObjC/DOMTestObjInternal.h new file mode 100644 index 0000000..c24ea84 --- /dev/null +++ b/WebCore/bindings/scripts/test/ObjC/DOMTestObjInternal.h @@ -0,0 +1,38 @@ +/* + * This file is part of the WebKit open source project. + * This file has been generated by generate-bindings.pl. DO NOT MODIFY! + * + * 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. + */ + +#import <WebCore/DOMTestObj.h> + +#if WEBKIT_VERSION_MAX_ALLOWED >= WEBKIT_VERSION_LATEST + +namespace WebCore { + class TestObj; +} + +WebCore::TestObj* core(DOMTestObj *); +DOMTestObj *kit(WebCore::TestObj*); + +#endif diff --git a/WebCore/bindings/scripts/test/TestCallback.idl b/WebCore/bindings/scripts/test/TestCallback.idl new file mode 100644 index 0000000..25db4c6 --- /dev/null +++ b/WebCore/bindings/scripts/test/TestCallback.idl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary formstrArg, 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 WARRANTIEstrArg, 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. + */ + +// This IDL file is for testing the bindings code generator with an interface +// that has the "Callback" attribute and for tracking changes in its ouput. +module test { + interface [ + Conditional=DATABASE, + Callback + ] TestCallback { + boolean callbackWithClass1Param(in Class1 class1Param); + boolean callbackWithClass2Param(in Class2 class2Param, in DOMString strArg); + long callbackWithNonBoolReturnType(in Class3 class3Param); + [Custom] long customCallback(in Class5 class5Param, in Class6 class6Param); + }; +} diff --git a/WebCore/bindings/scripts/test/TestInterface.idl b/WebCore/bindings/scripts/test/TestInterface.idl new file mode 100644 index 0000000..5a8b008 --- /dev/null +++ b/WebCore/bindings/scripts/test/TestInterface.idl @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary formstrArg, 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 WARRANTIEstrArg, 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. + */ + +// This IDL file is for testing the bindings code generator and for tracking +// changes in its ouput. +module test { + interface [ + CanBeConstructed, + CallWith=ScriptExecutionContext + ] TestInterface { + }; +} diff --git a/WebCore/bindings/v8/test/TestObj.idl b/WebCore/bindings/scripts/test/TestObj.idl index 662ac64..b14328d 100644 --- a/WebCore/bindings/v8/test/TestObj.idl +++ b/WebCore/bindings/scripts/test/TestObj.idl @@ -26,8 +26,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// This IDL file is for testing the V8 generator and for tracking changes -// in its ouput. +// This IDL file is for testing the bindings code generator and for tracking +// changes in its ouput. module test { interface TestObj { // Attributes @@ -35,6 +35,8 @@ module test { readonly attribute DOMString readOnlyStringAttr; readonly attribute TestObj readOnlyTestObjAttr; attribute long intAttr; + attribute long long longLongAttr; + attribute unsigned long long unsignedLongLongAttr; attribute DOMString stringAttr; attribute TestObj testObjAttr; @@ -46,6 +48,8 @@ module test { TestObj objMethod(); TestObj objMethodWithArgs(in long intArg, in DOMString strArg, in TestObj objArg); + void serializedValue(in SerializedScriptValue serializedArg); + // Exceptions void methodWithException() raises(DOMException); attribute long attrWithException raises(DOMException); @@ -57,15 +61,43 @@ module test { [Custom] void customMethod(); [Custom] void customMethodWithArgs(in long intArg, in DOMString strArg, in TestObj objArg); + [CustomArgumentHandling] void customArgsAndException(in log intArg) + raises(DOMException); + + void addEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); + void removeEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); + + // 'CallWith' extended attribute + [CallWith=DynamicFrame] void withDynamicFrame(); + [CallWith=DynamicFrame] void withDynamicFrameAndArg(in long intArg); + [CallWith=DynamicFrame] void withDynamicFrameAndOptionalArg(in long intArg, in [Optional] long optionalArg); + [NeedsUserGestureCheck, CallWith=DynamicFrame] void withDynamicFrameAndUserGesture(in long intArg); + [NeedsUserGestureCheck, CallWith=DynamicFrame] void withDynamicFrameAndUserGestureASAD(in long intArg, in [Optional] long optionalArg); + [CallWith=ScriptState] void withScriptStateVoid(); + [CallWith=ScriptState] TestObj withScriptStateObj(); + [CallWith=ScriptState] void withScriptStateVoidException() + raises(DOMException); + [CallWith=ScriptState] TestObj withScriptStateObjException() + raises(DOMException); + // 'Optional' extended attribute void methodWithOptionalArg(in [Optional] long opt); void methodWithNonOptionalArgAndOptionalArg(in long nonOpt, in [Optional] long opt); void methodWithNonOptionalArgAndTwoOptionalArgs(in long nonOpt, in [Optional] long opt1, in long opt2); + // 'ConvertScriptString' extended attribute + readonly attribute [ConvertScriptString] DOMString scriptStringAttr; + +#ifdef TESTING_V8 // Overloads void overloadedMethod(in TestObj objArg, in DOMString strArg); void overloadedMethod(in TestObj objArg, in [Optional] long intArg); void overloadedMethod(in DOMString strArg); void overloadedMethod(in long intArg); +#endif }; } diff --git a/WebCore/bindings/scripts/test/V8/V8TestCallback.cpp b/WebCore/bindings/scripts/test/V8/V8TestCallback.cpp new file mode 100644 index 0000000..e72330d --- /dev/null +++ b/WebCore/bindings/scripts/test/V8/V8TestCallback.cpp @@ -0,0 +1,92 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "config.h" +#include "V8TestCallback.h" + +#if ENABLE(DATABASE) + +#include "Frame.h" +#include "ScriptExecutionContext.h" +#include "V8Class1.h" +#include "V8Class2.h" +#include "V8CustomVoidCallback.h" +#include "V8DOMString.h" + +namespace WebCore { + +V8TestCallback::V8TestCallback(v8::Local<v8::Object> callback, Frame* frame) + : m_callback(v8::Persistent<v8::Object>::New(callback)) + , m_frame(frame) + , m_worldContext(UseCurrentWorld) +{ +} + +V8TestCallback::~V8TestCallback() +{ + m_callback.Dispose(); +} + +// Functions + +bool V8TestCallback::callbackWithClass1Param(ScriptExecutionContext* context, Class1* class1Param) +{ + v8::HandleScope handleScope; + + v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext); + if (v8Context.IsEmpty()) + return true; + + v8::Context::Scope scope(v8Context); + + v8::Handle<v8::Value> argv[] = { + toV8(class1Param) + }; + + RefPtr<Frame> protect(m_frame); + + bool callbackReturnValue = false; + return !invokeCallback(m_callback, 1, argv, callbackReturnValue); +} + +bool V8TestCallback::callbackWithClass2Param(ScriptExecutionContext* context, Class2* class2Param, const String& strArg) +{ + v8::HandleScope handleScope; + + v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext); + if (v8Context.IsEmpty()) + return true; + + v8::Context::Scope scope(v8Context); + + v8::Handle<v8::Value> argv[] = { + toV8(class2Param), + toV8(strArg) + }; + + RefPtr<Frame> protect(m_frame); + + bool callbackReturnValue = false; + return !invokeCallback(m_callback, 2, argv, callbackReturnValue); +} + +} // namespace WebCore + +#endif // ENABLE(DATABASE) diff --git a/WebCore/bindings/scripts/test/V8/V8TestCallback.h b/WebCore/bindings/scripts/test/V8/V8TestCallback.h new file mode 100644 index 0000000..f58f3f0 --- /dev/null +++ b/WebCore/bindings/scripts/test/V8/V8TestCallback.h @@ -0,0 +1,63 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#if ENABLE(DATABASE) + +#ifndef V8TestCallback_h +#define V8TestCallback_h + +#include "TestCallback.h" +#include "WorldContextHandle.h" +#include <v8.h> +#include <wtf/Forward.h> + +namespace WebCore { + +class Frame; + +class V8TestCallback : public TestCallback { +public: + static PassRefPtr<V8TestCallback> create(v8::Local<v8::Value> value, Frame* frame) + { + ASSERT(value->IsObject()); + return adoptRef(new V8TestCallback(value->ToObject(), frame)); + } + + virtual ~V8TestCallback(); + + // Functions + virtual bool callbackWithClass1Param(ScriptExecutionContext*, Class1* class1Param); + virtual bool callbackWithClass2Param(ScriptExecutionContext*, Class2* class2Param, const String& strArg); + COMPILE_ASSERT(false) virtual int callbackWithNonBoolReturnType(ScriptExecutionContext*, Class3* class3Param); + virtual int customCallback(ScriptExecutionContext*, Class5* class5Param, Class6* class6Param); + +private: + V8TestCallback(v8::Local<v8::Object>, Frame*); + + v8::Persistent<v8::Object> m_callback; + RefPtr<Frame> m_frame; + WorldContextHandle m_worldContext; +}; + +} + +#endif // V8TestCallback_h + +#endif // ENABLE(DATABASE) diff --git a/WebCore/bindings/scripts/test/V8/V8TestInterface.cpp b/WebCore/bindings/scripts/test/V8/V8TestInterface.cpp new file mode 100644 index 0000000..f0bfb86 --- /dev/null +++ b/WebCore/bindings/scripts/test/V8/V8TestInterface.cpp @@ -0,0 +1,115 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "config.h" +#include "V8TestInterface.h" + +#include "RuntimeEnabledFeatures.h" +#include "V8Binding.h" +#include "V8BindingState.h" +#include "V8DOMWrapper.h" +#include "V8IsolatedContext.h" +#include "V8Proxy.h" + +namespace WebCore { + +WrapperTypeInfo V8TestInterface::info = { V8TestInterface::GetTemplate, V8TestInterface::derefObject, 0 }; + +namespace TestInterfaceInternal { + +template <typename T> void V8_USE(T) { } + +} // namespace TestInterfaceInternal + +v8::Handle<v8::Value> V8TestInterface::constructorCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestInterface.Contructor"); + return V8Proxy::constructDOMObjectWithScriptExecutionContext<TestInterface>(args, &info); +} +static v8::Persistent<v8::FunctionTemplate> ConfigureV8TestInterfaceTemplate(v8::Persistent<v8::FunctionTemplate> desc) +{ + v8::Local<v8::Signature> defaultSignature = configureTemplate(desc, "TestInterface", v8::Persistent<v8::FunctionTemplate>(), V8TestInterface::internalFieldCount, + 0, 0, + 0, 0); + desc->SetCallHandler(V8TestInterface::constructorCallback); + + + // Custom toString template + desc->Set(getToStringName(), getToStringTemplate()); + return desc; +} + +v8::Persistent<v8::FunctionTemplate> V8TestInterface::GetRawTemplate() +{ + static v8::Persistent<v8::FunctionTemplate> V8TestInterfaceRawCache = createRawTemplate(); + return V8TestInterfaceRawCache; +} + +v8::Persistent<v8::FunctionTemplate> V8TestInterface::GetTemplate() +{ + static v8::Persistent<v8::FunctionTemplate> V8TestInterfaceCache = ConfigureV8TestInterfaceTemplate(GetRawTemplate()); + return V8TestInterfaceCache; +} + +TestInterface* V8TestInterface::toNative(v8::Handle<v8::Object> object) +{ + return reinterpret_cast<TestInterface*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); +} + +bool V8TestInterface::HasInstance(v8::Handle<v8::Value> value) +{ + return GetRawTemplate()->HasInstance(value); +} + + +v8::Handle<v8::Object> V8TestInterface::wrap(TestInterface* impl) +{ + v8::Handle<v8::Object> wrapper; + V8Proxy* proxy = 0; + wrapper = getDOMObjectMap().get(impl); + if (!wrapper.IsEmpty()) + return wrapper; + wrapper = V8DOMWrapper::instantiateV8Object(proxy, &info, impl); + if (wrapper.IsEmpty()) + return wrapper; + + impl->ref(); + getDOMObjectMap().set(impl, v8::Persistent<v8::Object>::New(wrapper)); + return wrapper; +} + +v8::Handle<v8::Value> toV8(PassRefPtr<TestInterface > impl) +{ + return toV8(impl.get()); +} + +v8::Handle<v8::Value> toV8(TestInterface* impl) +{ + if (!impl) + return v8::Null(); + return V8TestInterface::wrap(impl); +} + +void V8TestInterface::derefObject(void* object) +{ + static_cast<TestInterface*>(object)->deref(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/scripts/test/V8/V8TestInterface.h b/WebCore/bindings/scripts/test/V8/V8TestInterface.h new file mode 100644 index 0000000..ce1310e --- /dev/null +++ b/WebCore/bindings/scripts/test/V8/V8TestInterface.h @@ -0,0 +1,50 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef V8TestInterface_h +#define V8TestInterface_h + +#include "StringHash.h" +#include "TestInterface.h" +#include "WrapperTypeInfo.h" +#include <v8.h> +#include <wtf/HashMap.h> + +namespace WebCore { + +class V8TestInterface { + +public: + static bool HasInstance(v8::Handle<v8::Value> value); + static v8::Persistent<v8::FunctionTemplate> GetRawTemplate(); + static v8::Persistent<v8::FunctionTemplate> GetTemplate(); + static TestInterface* toNative(v8::Handle<v8::Object>); + static v8::Handle<v8::Object> wrap(TestInterface*); + static void derefObject(void*); + static WrapperTypeInfo info; + static v8::Handle<v8::Value> constructorCallback(const v8::Arguments& args); + static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + 0; +}; + +v8::Handle<v8::Value> toV8(TestInterface*); +v8::Handle<v8::Value> toV8(PassRefPtr<TestInterface >); +} + +#endif // V8TestInterface_h diff --git a/WebCore/bindings/v8/test/V8TestObj.cpp b/WebCore/bindings/scripts/test/V8/V8TestObj.cpp index d51884e..94dcd5e 100644 --- a/WebCore/bindings/v8/test/V8TestObj.cpp +++ b/WebCore/bindings/scripts/test/V8/V8TestObj.cpp @@ -23,11 +23,14 @@ #include "ExceptionCode.h" #include "RuntimeEnabledFeatures.h" +#include "ScriptCallStack.h" +#include "SerializedScriptValue.h" #include "V8Binding.h" #include "V8BindingState.h" #include "V8DOMWrapper.h" #include "V8IsolatedContext.h" #include "V8Proxy.h" +#include "V8log.h" #include <wtf/GetPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> @@ -84,6 +87,38 @@ static void intAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> v return; } +static v8::Handle<v8::Value> longLongAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.longLongAttr._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return v8::Number::New(static_cast<double>(imp->longLongAttr())); +} + +static void longLongAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.longLongAttr._set"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + long long v = toInt64(value); + imp->setLongLongAttr(WTF::getPtr(v)); + return; +} + +static v8::Handle<v8::Value> unsignedLongLongAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.unsignedLongLongAttr._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return v8::Number::New(static_cast<double>(imp->unsignedLongLongAttr())); +} + +static void unsignedLongLongAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.unsignedLongLongAttr._set"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + unsigned long long v = toInt64(value); + imp->setUnsignedLongLongAttr(WTF::getPtr(v)); + return; +} + static v8::Handle<v8::Value> stringAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.TestObj.stringAttr._get"); @@ -164,6 +199,13 @@ static void attrWithGetterExceptionAttrSetter(v8::Local<v8::String> name, v8::Lo return; } +static v8::Handle<v8::Value> scriptStringAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.scriptStringAttr._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + v8StringOrNull(exec, imp->scriptStringAttr()); +} + static v8::Handle<v8::Value> voidMethodCallback(const v8::Arguments& args) { INC_STATS("DOM.TestObj.voidMethod"); @@ -217,6 +259,18 @@ static v8::Handle<v8::Value> objMethodWithArgsCallback(const v8::Arguments& args return toV8(imp->objMethodWithArgs(intArg, strArg, objArg)); } +static v8::Handle<v8::Value> serializedValueCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.serializedValue"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + bool serializedArgDidThrow = false; + RefPtr<SerializedScriptValue> serializedArg = SerializedScriptValue::create(args[0], serializedArgDidThrow); + if (serializedArgDidThrow) + return v8::Undefined(); + imp->serializedValue(serializedArg); + return v8::Handle<v8::Value>(); +} + static v8::Handle<v8::Value> methodWithExceptionCallback(const v8::Arguments& args) { INC_STATS("DOM.TestObj.methodWithException"); @@ -233,6 +287,183 @@ static v8::Handle<v8::Value> methodWithExceptionCallback(const v8::Arguments& ar return v8::Handle<v8::Value>(); } +static v8::Handle<v8::Value> customArgsAndExceptionCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.customArgsAndException"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + ExceptionCode ec = 0; + { + OwnPtr<ScriptCallStack> callStack(ScriptCallStack::create(args, 1)); + if (!callStack) + return v8::Undefined(); + log* intArg = V8log::HasInstance(args[0]) ? V8log::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; + imp->customArgsAndException(intArg, callStack.get(), ec); + if (UNLIKELY(ec)) + goto fail; + return v8::Handle<v8::Value>(); + } + fail: + V8Proxy::setDOMException(ec); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> addEventListenerCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.addEventListener()"); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFindOrCreate); + if (listener) { + V8TestObj::toNative(args.Holder())->addEventListener(v8ValueToAtomicWebCoreString(args[0]), listener, args[2]->BooleanValue()); + createHiddenDependency(args.Holder(), args[1], V8TestObj::eventListenerCacheIndex); + } + return v8::Undefined(); +} + +static v8::Handle<v8::Value> removeEventListenerCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.removeEventListener()"); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFindOnly); + if (listener) { + V8TestObj::toNative(args.Holder())->removeEventListener(v8ValueToAtomicWebCoreString(args[0]), listener.get(), args[2]->BooleanValue()); + removeHiddenDependency(args.Holder(), args[1], V8TestObj::eventListenerCacheIndex); + } + return v8::Undefined(); +} + +static v8::Handle<v8::Value> withDynamicFrameCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.withDynamicFrame"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext(); + if (!enteredFrame) + return v8::Undefined(); + imp->withDynamicFrame(enteredFrame); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> withDynamicFrameAndArgCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.withDynamicFrameAndArg"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + int intArg = toInt32(args[0]); + Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext(); + if (!enteredFrame) + return v8::Undefined(); + imp->withDynamicFrameAndArg(enteredFrame, intArg); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> withDynamicFrameAndOptionalArgCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.withDynamicFrameAndOptionalArg"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + int intArg = toInt32(args[0]); + if (args.Length() <= 1) { + Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext(); + if (!enteredFrame) + return v8::Undefined(); + imp->withDynamicFrameAndOptionalArg(enteredFrame, intArg); + return v8::Handle<v8::Value>(); + } + int optionalArg = toInt32(args[1]); + Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext(); + if (!enteredFrame) + return v8::Undefined(); + imp->withDynamicFrameAndOptionalArg(enteredFrame, intArg, optionalArg); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> withDynamicFrameAndUserGestureCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.withDynamicFrameAndUserGesture"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + int intArg = toInt32(args[0]); + Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext(); + if (!enteredFrame) + return v8::Undefined(); + imp->withDynamicFrameAndUserGesture(enteredFrame, intArg, processingUserGesture()); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> withDynamicFrameAndUserGestureASADCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.withDynamicFrameAndUserGestureASAD"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + int intArg = toInt32(args[0]); + if (args.Length() <= 1) { + Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext(); + if (!enteredFrame) + return v8::Undefined(); + imp->withDynamicFrameAndUserGestureASAD(enteredFrame, intArg, processingUserGesture()); + return v8::Handle<v8::Value>(); + } + int optionalArg = toInt32(args[1]); + Frame* enteredFrame = V8Proxy::retrieveFrameForEnteredContext(); + if (!enteredFrame) + return v8::Undefined(); + imp->withDynamicFrameAndUserGestureASAD(enteredFrame, intArg, optionalArg, processingUserGesture()); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> withScriptStateVoidCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.withScriptStateVoid"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + EmptyScriptState state; + imp->withScriptStateVoid(&state); + if (state.hadException()) + return throwError(state.exception()); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> withScriptStateObjCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.withScriptStateObj"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + EmptyScriptState state; + RefPtr<TestObj> result = imp->withScriptStateObj(&state); + if (state.hadException()) + return throwError(state.exception()); + return toV8(result.release()); +} + +static v8::Handle<v8::Value> withScriptStateVoidExceptionCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.withScriptStateVoidException"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + ExceptionCode ec = 0; + { + EmptyScriptState state; + imp->withScriptStateVoidException(&state, ec); + if (UNLIKELY(ec)) + goto fail; + if (state.hadException()) + return throwError(state.exception()); + return v8::Handle<v8::Value>(); + } + fail: + V8Proxy::setDOMException(ec); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> withScriptStateObjExceptionCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.withScriptStateObjException"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + ExceptionCode ec = 0; + { + EmptyScriptState state; + RefPtr<TestObj> result = imp->withScriptStateObjException(&state, ec); + if (UNLIKELY(ec)) + goto fail; + if (state.hadException()) + return throwError(state.exception()); + return toV8(result.release()); + } + fail: + V8Proxy::setDOMException(ec); + return v8::Handle<v8::Value>(); +} + static v8::Handle<v8::Value> methodWithOptionalArgCallback(const v8::Arguments& args) { INC_STATS("DOM.TestObj.methodWithOptionalArg"); @@ -343,6 +574,10 @@ static const BatchedAttribute TestObjAttrs[] = { {"readOnlyTestObjAttr", TestObjInternal::readOnlyTestObjAttrAttrGetter, 0, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, // Attribute 'intAttr' (Type: 'attribute' ExtAttr: '') {"intAttr", TestObjInternal::intAttrAttrGetter, TestObjInternal::intAttrAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'longLongAttr' (Type: 'attribute' ExtAttr: '') + {"longLongAttr", TestObjInternal::longLongAttrAttrGetter, TestObjInternal::longLongAttrAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'unsignedLongLongAttr' (Type: 'attribute' ExtAttr: '') + {"unsignedLongLongAttr", TestObjInternal::unsignedLongLongAttrAttrGetter, TestObjInternal::unsignedLongLongAttrAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, // Attribute 'stringAttr' (Type: 'attribute' ExtAttr: '') {"stringAttr", TestObjInternal::stringAttrAttrGetter, TestObjInternal::stringAttrAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, // Attribute 'testObjAttr' (Type: 'attribute' ExtAttr: '') @@ -355,14 +590,28 @@ static const BatchedAttribute TestObjAttrs[] = { {"attrWithGetterException", TestObjInternal::attrWithGetterExceptionAttrGetter, TestObjInternal::attrWithGetterExceptionAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, // Attribute 'customAttr' (Type: 'attribute' ExtAttr: 'Custom') {"customAttr", V8TestObj::customAttrAccessorGetter, V8TestObj::customAttrAccessorSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'scriptStringAttr' (Type: 'readonly attribute' ExtAttr: 'ConvertScriptString') + {"scriptStringAttr", TestObjInternal::scriptStringAttrAttrGetter, 0, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, }; static const BatchedCallback TestObjCallbacks[] = { {"voidMethod", TestObjInternal::voidMethodCallback}, {"intMethod", TestObjInternal::intMethodCallback}, {"objMethod", TestObjInternal::objMethodCallback}, + {"serializedValue", TestObjInternal::serializedValueCallback}, {"methodWithException", TestObjInternal::methodWithExceptionCallback}, {"customMethod", V8TestObj::customMethodCallback}, {"customMethodWithArgs", V8TestObj::customMethodWithArgsCallback}, + {"addEventListener", TestObjInternal::addEventListenerCallback}, + {"removeEventListener", TestObjInternal::removeEventListenerCallback}, + {"withDynamicFrame", TestObjInternal::withDynamicFrameCallback}, + {"withDynamicFrameAndArg", TestObjInternal::withDynamicFrameAndArgCallback}, + {"withDynamicFrameAndOptionalArg", TestObjInternal::withDynamicFrameAndOptionalArgCallback}, + {"withDynamicFrameAndUserGesture", TestObjInternal::withDynamicFrameAndUserGestureCallback}, + {"withDynamicFrameAndUserGestureASAD", TestObjInternal::withDynamicFrameAndUserGestureASADCallback}, + {"withScriptStateVoid", TestObjInternal::withScriptStateVoidCallback}, + {"withScriptStateObj", TestObjInternal::withScriptStateObjCallback}, + {"withScriptStateVoidException", TestObjInternal::withScriptStateVoidExceptionCallback}, + {"withScriptStateObjException", TestObjInternal::withScriptStateObjExceptionCallback}, {"methodWithOptionalArg", TestObjInternal::methodWithOptionalArgCallback}, {"methodWithNonOptionalArgAndOptionalArg", TestObjInternal::methodWithNonOptionalArgAndOptionalArgCallback}, {"methodWithNonOptionalArgAndTwoOptionalArgs", TestObjInternal::methodWithNonOptionalArgAndTwoOptionalArgsCallback}, @@ -395,6 +644,12 @@ static v8::Persistent<v8::FunctionTemplate> ConfigureV8TestObjTemplate(v8::Persi v8::Handle<v8::Signature> objMethodWithArgsSignature = v8::Signature::New(desc, objMethodWithArgsArgc, objMethodWithArgsArgv); proto->Set(v8::String::New("objMethodWithArgs"), v8::FunctionTemplate::New(TestObjInternal::objMethodWithArgsCallback, v8::Handle<v8::Value>(), objMethodWithArgsSignature)); + // Custom Signature 'customArgsAndException' + const int customArgsAndExceptionArgc = 1; + v8::Handle<v8::FunctionTemplate> customArgsAndExceptionArgv[customArgsAndExceptionArgc] = { V8log::GetRawTemplate() }; + v8::Handle<v8::Signature> customArgsAndExceptionSignature = v8::Signature::New(desc, customArgsAndExceptionArgc, customArgsAndExceptionArgv); + proto->Set(v8::String::New("customArgsAndException"), v8::FunctionTemplate::New(TestObjInternal::customArgsAndExceptionCallback, v8::Handle<v8::Value>(), customArgsAndExceptionSignature)); + // Custom toString template desc->Set(getToStringName(), getToStringTemplate()); return desc; diff --git a/WebCore/bindings/v8/test/V8TestObj.h b/WebCore/bindings/scripts/test/V8/V8TestObj.h index 5d6770a..5d6770a 100644 --- a/WebCore/bindings/v8/test/V8TestObj.h +++ b/WebCore/bindings/scripts/test/V8/V8TestObj.h diff --git a/WebCore/bindings/v8/ScriptCallStack.cpp b/WebCore/bindings/v8/ScriptCallStack.cpp index 95e874b..6ca952e 100644 --- a/WebCore/bindings/v8/ScriptCallStack.cpp +++ b/WebCore/bindings/v8/ScriptCallStack.cpp @@ -33,13 +33,16 @@ #include "ScriptController.h" #include "ScriptDebugServer.h" +#include "V8Binding.h" +#include <v8-debug.h> #include <v8.h> - -#include "V8Binding.h" +#include <wtf/StdLibExtras.h> // For DEFINE_STATIC_LOCAL namespace WebCore { +v8::Persistent<v8::Context> ScriptCallStack::s_utilityContext; + ScriptCallStack* ScriptCallStack::create(const v8::Arguments& arguments, unsigned skipArgumentCount) { String sourceName; int sourceLineNumber; @@ -51,10 +54,14 @@ ScriptCallStack* ScriptCallStack::create(const v8::Arguments& arguments, unsigne bool ScriptCallStack::callLocation(String* sourceName, int* sourceLineNumber, String* functionName) { +<<<<<<< HEAD:WebCore/bindings/v8/ScriptCallStack.cpp #if PLATFORM(ANDROID) return false; #else if (!ScriptDebugServer::topStackFrame(*sourceName, *sourceLineNumber, *functionName)) +======= + if (!topStackFrame(*sourceName, *sourceLineNumber, *functionName)) +>>>>>>> webkit.org at r58956:WebCore/bindings/v8/ScriptCallStack.cpp return false; *sourceLineNumber += 1; return true; @@ -79,4 +86,67 @@ const ScriptCallFrame& ScriptCallStack::at(unsigned index) const return m_lastCaller; } +// Create the utility context for holding JavaScript functions used internally +// which are not visible to JavaScript executing on the page. +void ScriptCallStack::createUtilityContext() +{ + ASSERT(s_utilityContext.IsEmpty()); + + v8::HandleScope scope; + v8::Handle<v8::ObjectTemplate> globalTemplate = v8::ObjectTemplate::New(); + s_utilityContext = v8::Context::New(0, globalTemplate); + v8::Context::Scope contextScope(s_utilityContext); + + // Compile JavaScript function for retrieving the source line, the source + // name and the symbol name for the top JavaScript stack frame. + DEFINE_STATIC_LOCAL(const char*, topStackFrame, + ("function topStackFrame(exec_state) {" + " if (!exec_state.frameCount())" + " return undefined;" + " var frame = exec_state.frame(0);" + " var func = frame.func();" + " var scriptName;" + " if (func.resolved() && func.script())" + " scriptName = func.script().name();" + " return [scriptName, frame.sourceLine(), (func.name() || func.inferredName())];" + "}")); + v8::Script::Compile(v8::String::New(topStackFrame))->Run(); +} + +bool ScriptCallStack::topStackFrame(String& sourceName, int& lineNumber, String& functionName) +{ + v8::HandleScope scope; + v8::Handle<v8::Context> v8UtilityContext = utilityContext(); + if (v8UtilityContext.IsEmpty()) + return false; + v8::Context::Scope contextScope(v8UtilityContext); + v8::Handle<v8::Function> topStackFrame; + topStackFrame = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("topStackFrame"))); + if (topStackFrame.IsEmpty()) + return false; + v8::Handle<v8::Value> value = v8::Debug::Call(topStackFrame); + if (value.IsEmpty()) + return false; + // If there is no top stack frame, we still return success, but fill the input params with defaults. + if (value->IsUndefined()) { + // Fallback to setting lineNumber to 0, and source and function name to "undefined". + sourceName = toWebCoreString(value); + lineNumber = 0; + functionName = toWebCoreString(value); + return true; + } + if (!value->IsArray()) + return false; + v8::Local<v8::Object> jsArray = value->ToObject(); + v8::Local<v8::Value> sourceNameValue = jsArray->Get(0); + v8::Local<v8::Value> lineNumberValue = jsArray->Get(1); + v8::Local<v8::Value> functionNameValue = jsArray->Get(2); + if (sourceNameValue.IsEmpty() || lineNumberValue.IsEmpty() || functionNameValue.IsEmpty()) + return false; + sourceName = toWebCoreString(sourceNameValue); + lineNumber = lineNumberValue->Int32Value(); + functionName = toWebCoreString(functionNameValue); + return true; +} + } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptCallStack.h b/WebCore/bindings/v8/ScriptCallStack.h index 2433bde..11ec3bb 100644 --- a/WebCore/bindings/v8/ScriptCallStack.h +++ b/WebCore/bindings/v8/ScriptCallStack.h @@ -42,26 +42,48 @@ namespace v8 { namespace WebCore { - class ScriptCallStack : public Noncopyable { - public: - static ScriptCallStack* create(const v8::Arguments&, unsigned skipArgumentCount = 0); - ~ScriptCallStack(); - - static bool callLocation(String* sourceName, int* sourceLineNumber, String* functionName); - - const ScriptCallFrame& at(unsigned) const; - // FIXME: implement retrieving and storing call stack trace - unsigned size() const { return 1; } - - ScriptState* state() const { return m_scriptState; } - ScriptState* globalState() const { return m_scriptState; } - - private: - ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber, String funcName); - - ScriptCallFrame m_lastCaller; - ScriptState* m_scriptState; - }; +class ScriptCallStack : public Noncopyable { +public: + static ScriptCallStack* create(const v8::Arguments&, unsigned skipArgumentCount = 0); + ~ScriptCallStack(); + + static bool callLocation(String* sourceName, int* sourceLineNumber, String* functionName); + + const ScriptCallFrame& at(unsigned) const; + // FIXME: implement retrieving and storing call stack trace + unsigned size() const { return 1; } + + ScriptState* state() const { return m_scriptState; } + ScriptState* globalState() const { return m_scriptState; } + +private: + ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber, String funcName); + + // Function for retrieving the source name, line number and function name for the top + // JavaScript stack frame. + // + // It will return true if the caller information was successfully retrieved and written + // into the function parameters, otherwise the function will return false. It may + // fail due to a stack overflow in the underlying JavaScript implementation, handling + // of such exception is up to the caller. + static bool topStackFrame(String& sourceName, int& lineNumber, String& functionName); + + static void createUtilityContext(); + + // Returns a local handle of the utility context. + static v8::Local<v8::Context> utilityContext() + { + if (s_utilityContext.IsEmpty()) + createUtilityContext(); + return v8::Local<v8::Context>::New(s_utilityContext); + } + + ScriptCallFrame m_lastCaller; + ScriptState* m_scriptState; + + // Utility context holding JavaScript functions used internally. + static v8::Persistent<v8::Context> s_utilityContext; +}; } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptController.cpp b/WebCore/bindings/v8/ScriptController.cpp index ee15eaa..0f94a2e 100644 --- a/WebCore/bindings/v8/ScriptController.cpp +++ b/WebCore/bindings/v8/ScriptController.cpp @@ -68,6 +68,7 @@ void ScriptController::initializeThreading() static bool initializedThreading = false; if (!initializedThreading) { WTF::initializeThreading(); + WTF::initializeMainThread(); initializedThreading = true; } } diff --git a/WebCore/bindings/v8/ScriptDebugServer.cpp b/WebCore/bindings/v8/ScriptDebugServer.cpp index 54d7694..ce258fb 100644 --- a/WebCore/bindings/v8/ScriptDebugServer.cpp +++ b/WebCore/bindings/v8/ScriptDebugServer.cpp @@ -44,8 +44,6 @@ namespace WebCore { -v8::Persistent<v8::Context> ScriptDebugServer::s_utilityContext; - ScriptDebugServer::MessageLoopDispatchHandler ScriptDebugServer::s_messageLoopDispatchHandler = 0; ScriptDebugServer& ScriptDebugServer::shared() @@ -81,11 +79,10 @@ void ScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) m_listenersMap.set(page, listener); V8Proxy* proxy = V8Proxy::retrieve(page->mainFrame()); v8::Local<v8::Context> context = proxy->mainWorldContext(); - String contextData = toWebCoreStringWithNullCheck(context->GetData()); - m_contextDataMap.set(listener, contextData); v8::Handle<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("getScripts"))); - v8::Handle<v8::Value> value = v8::Debug::Call(getScriptsFunction); + v8::Handle<v8::Value> argv[] = { context->GetData() }; + v8::Handle<v8::Value> value = getScriptsFunction->Call(m_debuggerScript.get(), 1, argv); if (value.IsEmpty()) return; ASSERT(!value->IsUndefined() && value->IsArray()); @@ -175,6 +172,35 @@ void ScriptDebugServer::setBreakpointsActivated(bool enabled) #endif } +ScriptDebugServer::PauseOnExceptionsState ScriptDebugServer::pauseOnExceptionsState() +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + ensureDebuggerScriptCompiled(); + v8::HandleScope scope; + v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); + + v8::Handle<v8::Function> currentCallFrameFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("pauseOnExceptionsState"))); + v8::Handle<v8::Value> argv[] = { v8::Handle<v8::Value>() }; + v8::Handle<v8::Value> result = currentCallFrameFunction->Call(m_debuggerScript.get(), 0, argv); + return static_cast<ScriptDebugServer::PauseOnExceptionsState>(result->Int32Value()); +#else + return DontPauseOnExceptions; +#endif +} + +void ScriptDebugServer::setPauseOnExceptionsState(PauseOnExceptionsState pauseOnExceptionsState) +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + ensureDebuggerScriptCompiled(); + v8::HandleScope scope; + v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); + + v8::Handle<v8::Function> currentCallFrameFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("setPauseOnExceptionsState"))); + v8::Handle<v8::Value> argv[] = { v8::Int32::New(pauseOnExceptionsState) }; + currentCallFrameFunction->Call(m_debuggerScript.get(), 1, argv); +#endif +} + void ScriptDebugServer::continueProgram() { #if ENABLE(V8_SCRIPT_DEBUG_SERVER) @@ -216,26 +242,15 @@ ScriptState* ScriptDebugServer::currentCallFrameState() return m_currentCallFrameState; } -v8::Handle<v8::Value> ScriptDebugServer::currentCallFrameV8() -{ -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) - if (!m_currentCallFrame.get().IsEmpty()) - return m_currentCallFrame.get(); - - // Check on a bp. - v8::Handle<v8::Function> currentCallFrameFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("currentCallFrame"))); - v8::Handle<v8::Value> argv[] = { m_executionState.get() }; - v8::Handle<v8::Value> result = currentCallFrameFunction->Call(m_debuggerScript.get(), 1, argv); - m_currentCallFrame.set(result); - return result; -#else - return v8::Handle<v8::Value>(); -#endif -} - PassRefPtr<JavaScriptCallFrame> ScriptDebugServer::currentCallFrame() { - return JavaScriptCallFrame::create(v8::Debug::GetDebugContext(), v8::Handle<v8::Object>::Cast(currentCallFrameV8())); + if (!m_currentCallFrame) { + v8::Handle<v8::Function> currentCallFrameFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("currentCallFrame"))); + v8::Handle<v8::Value> argv[] = { m_executionState.get() }; + v8::Handle<v8::Value> currentCallFrameV8 = currentCallFrameFunction->Call(m_debuggerScript.get(), 1, argv); + m_currentCallFrame = JavaScriptCallFrame::create(v8::Debug::GetDebugContext(), v8::Handle<v8::Object>::Cast(currentCallFrameV8)); + } + return m_currentCallFrame; } void ScriptDebugServer::onV8DebugMessage(const v8::Debug::Message& message) @@ -268,7 +283,7 @@ void ScriptDebugServer::handleV8DebugMessage(const v8::Debug::Message& message) return; // Ignore unsupported event types. - if (message.GetEvent() != v8::AfterCompile && message.GetEvent() != v8::Break) + if (message.GetEvent() != v8::AfterCompile && message.GetEvent() != v8::Break && message.GetEvent() != v8::Exception) return; v8::Handle<v8::Context> context = message.GetEventContext(); @@ -286,11 +301,13 @@ void ScriptDebugServer::handleV8DebugMessage(const v8::Debug::Message& message) if (global.IsEmpty()) return; + bool handled = false; Frame* frame = V8Proxy::retrieveFrame(context); if (frame) { ScriptDebugListener* listener = m_listenersMap.get(frame->page()); if (listener) { if (message.GetEvent() == v8::AfterCompile) { + handled = true; v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); v8::Local<v8::Object> args = v8::Object::New(); args->Set(v8::String::New("eventData"), message.GetEventData()); @@ -300,7 +317,8 @@ void ScriptDebugServer::handleV8DebugMessage(const v8::Debug::Message& message) ASSERT(value->IsObject()); v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); dispatchDidParseSource(listener, object); - } else if (message.GetEvent() == v8::Break) { + } else if (message.GetEvent() == v8::Break || message.GetEvent() == v8::Exception) { + handled = true; m_executionState.set(message.GetExecutionState()); m_currentCallFrameState = mainWorldScriptState(frame); listener->didPause(); @@ -308,14 +326,13 @@ void ScriptDebugServer::handleV8DebugMessage(const v8::Debug::Message& message) } } } + + if (!handled && !message.WillStartRunning()) + continueProgram(); } void ScriptDebugServer::dispatchDidParseSource(ScriptDebugListener* listener, v8::Handle<v8::Object> object) { - String contextData = toWebCoreStringWithNullCheck(object->Get(v8::String::New("contextData"))); - if (contextData != m_contextDataMap.get(listener)) - return; - listener->didParseSource( toWebCoreStringWithNullCheck(object->Get(v8::String::New("id"))), toWebCoreStringWithNullCheck(object->Get(v8::String::New("name"))), @@ -339,69 +356,6 @@ void ScriptDebugServer::didResume() m_executionState.clear(); } -// Create the utility context for holding JavaScript functions used internally -// which are not visible to JavaScript executing on the page. -void ScriptDebugServer::createUtilityContext() -{ - ASSERT(s_utilityContext.IsEmpty()); - - v8::HandleScope scope; - v8::Handle<v8::ObjectTemplate> globalTemplate = v8::ObjectTemplate::New(); - s_utilityContext = v8::Context::New(0, globalTemplate); - v8::Context::Scope contextScope(s_utilityContext); - - // Compile JavaScript function for retrieving the source line, the source - // name and the symbol name for the top JavaScript stack frame. - DEFINE_STATIC_LOCAL(const char*, topStackFrame, - ("function topStackFrame(exec_state) {" - " if (!exec_state.frameCount())" - " return undefined;" - " var frame = exec_state.frame(0);" - " var func = frame.func();" - " var scriptName;" - " if (func.resolved() && func.script())" - " scriptName = func.script().name();" - " return [scriptName, frame.sourceLine(), (func.name() || func.inferredName())];" - "}")); - v8::Script::Compile(v8::String::New(topStackFrame))->Run(); -} - -bool ScriptDebugServer::topStackFrame(String& sourceName, int& lineNumber, String& functionName) -{ - v8::HandleScope scope; - v8::Handle<v8::Context> v8UtilityContext = utilityContext(); - if (v8UtilityContext.IsEmpty()) - return false; - v8::Context::Scope contextScope(v8UtilityContext); - v8::Handle<v8::Function> topStackFrame; - topStackFrame = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("topStackFrame"))); - if (topStackFrame.IsEmpty()) - return false; - v8::Handle<v8::Value> value = v8::Debug::Call(topStackFrame); - if (value.IsEmpty()) - return false; - // If there is no top stack frame, we still return success, but fill the input params with defaults. - if (value->IsUndefined()) { - // Fallback to setting lineNumber to 0, and source and function name to "undefined". - sourceName = toWebCoreString(value); - lineNumber = 0; - functionName = toWebCoreString(value); - return true; - } - if (!value->IsArray()) - return false; - v8::Local<v8::Object> jsArray = value->ToObject(); - v8::Local<v8::Value> sourceNameValue = jsArray->Get(0); - v8::Local<v8::Value> lineNumberValue = jsArray->Get(1); - v8::Local<v8::Value> functionNameValue = jsArray->Get(2); - if (sourceNameValue.IsEmpty() || lineNumberValue.IsEmpty() || functionNameValue.IsEmpty()) - return false; - sourceName = toWebCoreString(sourceNameValue); - lineNumber = lineNumberValue->Int32Value(); - functionName = toWebCoreString(functionNameValue); - return true; -} - } // namespace WebCore #endif // ENABLE(JAVASCRIPT_DEBUGGER) diff --git a/WebCore/bindings/v8/ScriptDebugServer.h b/WebCore/bindings/v8/ScriptDebugServer.h index 04857e4..6ef0afd 100644 --- a/WebCore/bindings/v8/ScriptDebugServer.h +++ b/WebCore/bindings/v8/ScriptDebugServer.h @@ -33,7 +33,7 @@ #if ENABLE(JAVASCRIPT_DEBUGGER) -#include "OwnHandle.h" +#include "JavaScriptCallFrame.h" #include "PlatformString.h" #include "ScriptBreakpoint.h" #include "ScriptState.h" @@ -45,22 +45,12 @@ namespace WebCore { -class JavaScriptCallFrame; class Page; class ScriptDebugListener; class ScriptDebugServer : public Noncopyable { public: static ScriptDebugServer& shared(); - - // Function for retrieving the source name, line number and function name for the top - // JavaScript stack frame. - // - // It will return true if the caller information was successfully retrieved and written - // into the function parameters, otherwise the function will return false. It may - // fail due to a stack overflow in the underlying JavaScript implementation, handling - // of such exception is up to the caller. - static bool topStackFrame(String& sourceName, int& lineNumber, String& functionName); void addListener(ScriptDebugListener*, Page*); void removeListener(ScriptDebugListener*, Page*); @@ -75,8 +65,8 @@ public: PauseOnAllExceptions, PauseOnUncaughtExceptions }; - PauseOnExceptionsState pauseOnExceptionsState() const { return m_pauseOnExceptionsState; } - void setPauseOnExceptionsState(PauseOnExceptionsState pauseOnExceptionsState) { m_pauseOnExceptionsState = pauseOnExceptionsState; } + PauseOnExceptionsState pauseOnExceptionsState(); + void setPauseOnExceptionsState(PauseOnExceptionsState pauseOnExceptionsState); void pauseProgram() { } void continueProgram(); @@ -97,7 +87,6 @@ public: typedef void (*MessageLoopDispatchHandler)(const Vector<WebCore::Page*>&); static void setMessageLoopDispatchHandler(MessageLoopDispatchHandler messageLoopDispatchHandler) { s_messageLoopDispatchHandler = messageLoopDispatchHandler; } - v8::Handle<v8::Value> currentCallFrameV8(); PassRefPtr<JavaScriptCallFrame> currentCallFrame(); private: @@ -115,28 +104,13 @@ private: void ensureDebuggerScriptCompiled(); void didResume(); - static void createUtilityContext(); - - // Returns a local handle of the utility context. - static v8::Local<v8::Context> utilityContext() - { - if (s_utilityContext.IsEmpty()) - createUtilityContext(); - return v8::Local<v8::Context>::New(s_utilityContext); - } - - // Utility context holding JavaScript functions used internally. - static v8::Persistent<v8::Context> s_utilityContext; - typedef HashMap<Page*, ScriptDebugListener*> ListenersMap; ListenersMap m_listenersMap; - typedef HashMap<ScriptDebugListener*, String> ContextDataMap; - ContextDataMap m_contextDataMap; String m_debuggerScriptSource; PauseOnExceptionsState m_pauseOnExceptionsState; OwnHandle<v8::Object> m_debuggerScript; ScriptState* m_currentCallFrameState; - OwnHandle<v8::Value> m_currentCallFrame; + RefPtr<JavaScriptCallFrame> m_currentCallFrame; OwnHandle<v8::Object> m_executionState; static MessageLoopDispatchHandler s_messageLoopDispatchHandler; diff --git a/WebCore/bindings/v8/ScriptEventListener.cpp b/WebCore/bindings/v8/ScriptEventListener.cpp index fdb6076..cad7a1c 100644 --- a/WebCore/bindings/v8/ScriptEventListener.cpp +++ b/WebCore/bindings/v8/ScriptEventListener.cpp @@ -106,7 +106,7 @@ PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame* frame, Attri return V8LazyEventListener::create(attr->localName().string(), frame->document()->isSVGDocument(), attr->value(), sourceURL, lineNumber, columnNumber, WorldContextHandle(UseMainWorld)); } -String getEventListenerHandlerBody(ScriptExecutionContext* context, ScriptState* scriptState, EventListener* listener) +String eventListenerHandlerBody(ScriptExecutionContext* context, ScriptState* scriptState, EventListener* listener) { if (listener->type() != EventListener::JSEventListenerType) return ""; @@ -120,4 +120,25 @@ String getEventListenerHandlerBody(ScriptExecutionContext* context, ScriptState* return toWebCoreStringWithNullCheck(function); } +bool eventListenerHandlerLocation(ScriptExecutionContext* context, ScriptState* scriptState, EventListener* listener, String& sourceName, int& lineNumber) +{ + if (listener->type() != EventListener::JSEventListenerType) + return false; + + ScriptScope scope(scriptState); + V8AbstractEventListener* v8Listener = static_cast<V8AbstractEventListener*>(listener); + v8::Handle<v8::Object> object = v8Listener->getListenerObject(context); + if (object.IsEmpty() || !object->IsFunction()) + return false; + + v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(object); + v8::ScriptOrigin origin = function->GetScriptOrigin(); + if (!origin.ResourceName().IsEmpty()) { + sourceName = toWebCoreString(origin.ResourceName()); + lineNumber = function->GetScriptLineNumber() + 1; + return true; + } + return false; +} + } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptEventListener.h b/WebCore/bindings/v8/ScriptEventListener.h index ce12a53..7815e29 100644 --- a/WebCore/bindings/v8/ScriptEventListener.h +++ b/WebCore/bindings/v8/ScriptEventListener.h @@ -45,7 +45,8 @@ namespace WebCore { PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node*, Attribute*); PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame*, Attribute*); - String getEventListenerHandlerBody(ScriptExecutionContext*, ScriptState*, EventListener*); + String eventListenerHandlerBody(ScriptExecutionContext*, ScriptState*, EventListener*); + bool eventListenerHandlerLocation(ScriptExecutionContext*, ScriptState*, EventListener*, String& sourceName, int& lineNumber); } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptProfileNode.cpp b/WebCore/bindings/v8/ScriptProfileNode.cpp index 3121128..7266c29 100644 --- a/WebCore/bindings/v8/ScriptProfileNode.cpp +++ b/WebCore/bindings/v8/ScriptProfileNode.cpp @@ -55,14 +55,12 @@ unsigned long ScriptProfileNode::lineNumber() const double ScriptProfileNode::totalTime() const { - // FIXME: use GetTotalMilliseconds once it is implemented in V8. - return m_profileNode->GetTotalSamplesCount(); + return m_profileNode->GetTotalTime(); } double ScriptProfileNode::selfTime() const { - // FIXME: use GetSelfMilliseconds once it is implemented in V8. - return m_profileNode->GetSelfSamplesCount(); + return m_profileNode->GetSelfTime(); } unsigned long ScriptProfileNode::numberOfCalls() const diff --git a/WebCore/bindings/v8/V8AbstractEventListener.cpp b/WebCore/bindings/v8/V8AbstractEventListener.cpp index 6dc2b29..b6c53df 100644 --- a/WebCore/bindings/v8/V8AbstractEventListener.cpp +++ b/WebCore/bindings/v8/V8AbstractEventListener.cpp @@ -71,6 +71,8 @@ V8AbstractEventListener::~V8AbstractEventListener() void V8AbstractEventListener::handleEvent(ScriptExecutionContext* context, Event* event) { + ASSERT(event); + // The callback function on XMLHttpRequest can clear the event listener and destroys 'this' object. Keep a local reference to it. // See issue 889829. RefPtr<V8AbstractEventListener> protect(this); @@ -86,6 +88,7 @@ void V8AbstractEventListener::handleEvent(ScriptExecutionContext* context, Event // Get the V8 wrapper for the event object. v8::Handle<v8::Value> jsEvent = toV8(event); + ASSERT(!jsEvent.IsEmpty()); invokeEventHandler(context, event, jsEvent); } @@ -114,6 +117,9 @@ void V8AbstractEventListener::setListenerObject(v8::Handle<v8::Object> listener) void V8AbstractEventListener::invokeEventHandler(ScriptExecutionContext* context, Event* event, v8::Handle<v8::Value> jsEvent) { + // If jsEvent is empty, attempt to set it as a hidden value would crash v8. + if (jsEvent.IsEmpty()) + return; v8::Local<v8::Context> v8Context = toV8Context(context, worldContext()); if (v8Context.IsEmpty()) diff --git a/WebCore/bindings/v8/V8GCController.cpp b/WebCore/bindings/v8/V8GCController.cpp index 61b2a88..fa7c357 100644 --- a/WebCore/bindings/v8/V8GCController.cpp +++ b/WebCore/bindings/v8/V8GCController.cpp @@ -378,7 +378,12 @@ public: ActiveDOMObject* activeDOMObject = typeInfo->toActiveDOMObject(wrapper); if (activeDOMObject && activeDOMObject->hasPendingActivity()) { ASSERT(!wrapper.IsWeak()); - wrapper.MakeWeak(activeDOMObject, &DOMDataStore::weakActiveDOMObjectCallback); + // NOTE: To re-enable weak status of the active object we use + // |object| from the map and not |activeDOMObject|. The latter + // may be a different pointer (in case ActiveDOMObject is not + // the main base class of the object's class) and pointer + // identity is required by DOM map functions. + wrapper.MakeWeak(object, &DOMDataStore::weakActiveDOMObjectCallback); } } } diff --git a/WebCore/bindings/v8/V8NPObject.cpp b/WebCore/bindings/v8/V8NPObject.cpp index 1ea6487..84450e5 100644 --- a/WebCore/bindings/v8/V8NPObject.cpp +++ b/WebCore/bindings/v8/V8NPObject.cpp @@ -33,7 +33,6 @@ #include "V8NPObject.h" #include "HTMLPlugInElement.h" -#include "IdentifierRep.h" #include "NPV8Object.h" #include "V8DOMMap.h" #include "V8HTMLAppletElement.h" @@ -54,6 +53,17 @@ enum InvokeFunctionType { InvokeDefault = 3 }; +struct IdentifierRep { + int number() const { return m_isString ? 0 : m_value.m_number; } + const char* string() const { return m_isString ? m_value.m_string : 0; } + + union { + const char* m_string; + int m_number; + } m_value; + bool m_isString; +}; + // FIXME: need comments. // Params: holder could be HTMLEmbedElement or NPObject static v8::Handle<v8::Value> npObjectInvokeImpl(const v8::Arguments& args, InvokeFunctionType functionId) diff --git a/WebCore/bindings/v8/V8Proxy.cpp b/WebCore/bindings/v8/V8Proxy.cpp index 0543037..7f52374 100644 --- a/WebCore/bindings/v8/V8Proxy.cpp +++ b/WebCore/bindings/v8/V8Proxy.cpp @@ -505,7 +505,7 @@ v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8 #if ENABLE(INSPECTOR) Page* inspectedPage = InspectorTimelineAgent::instanceCount() ? m_frame->page(): 0; - if (inspectedPage) + if (inspectedPage) { if (InspectorTimelineAgent* timelineAgent = inspectedPage->inspectorTimelineAgent()) { v8::ScriptOrigin origin = function->GetScriptOrigin(); String resourceName("undefined"); @@ -517,6 +517,7 @@ v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8 timelineAgent->willCallFunction(resourceName, lineNumber); } else inspectedPage = 0; + } #endif // !ENABLE(INSPECTOR) m_recursion++; diff --git a/WebCore/bindings/v8/V8Proxy.h b/WebCore/bindings/v8/V8Proxy.h index 98bc902..cd2ddad 100644 --- a/WebCore/bindings/v8/V8Proxy.h +++ b/WebCore/bindings/v8/V8Proxy.h @@ -39,6 +39,7 @@ #include "V8DOMWindowShell.h" #include "V8DOMWrapper.h" #include "V8GCController.h" +#include "V8Utilities.h" #include "WrapperTypeInfo.h" #include <v8.h> #include <wtf/PassRefPtr.h> // so generated bindings don't have to @@ -304,6 +305,9 @@ namespace WebCore { template <typename T> static v8::Handle<v8::Value> constructDOMObject(const v8::Arguments&, WrapperTypeInfo*); + template <typename T> + static v8::Handle<v8::Value> constructDOMObjectWithScriptExecutionContext(const v8::Arguments&, WrapperTypeInfo*); + // Process any pending JavaScript console messages. static void processConsoleMessages(); @@ -409,6 +413,25 @@ namespace WebCore { return args.Holder(); } + template <typename T> + v8::Handle<v8::Value> V8Proxy::constructDOMObjectWithScriptExecutionContext(const v8::Arguments& args, WrapperTypeInfo* type) + { + if (!args.IsConstructCall()) + return throwError(V8Proxy::TypeError, ""); + + ScriptExecutionContext* context = getScriptExecutionContext(); + if (!context) + return throwError(V8Proxy::ReferenceError, ""); + + // Note: it's OK to let this RefPtr go out of scope because we also call + // SetDOMWrapper(), which effectively holds a reference to obj. + RefPtr<T> obj = T::create(context); + V8DOMWrapper::setDOMWrapper(args.Holder(), type, obj.get()); + obj->ref(); + V8DOMWrapper::setJSWrapperForDOMObject(obj.get(), v8::Persistent<v8::Object>::New(args.Holder())); + return args.Holder(); + } + v8::Local<v8::Context> toV8Context(ScriptExecutionContext*, const WorldContextHandle& worldContext); diff --git a/WebCore/bindings/v8/WorkerScriptController.h b/WebCore/bindings/v8/WorkerScriptController.h index 616697a..5e3159f 100644 --- a/WebCore/bindings/v8/WorkerScriptController.h +++ b/WebCore/bindings/v8/WorkerScriptController.h @@ -58,6 +58,7 @@ namespace WebCore { enum ForbidExecutionOption { TerminateRunningScript, LetRunningScriptFinish }; void forbidExecution(ForbidExecutionOption); + bool isExecutionForbidden() const { return m_executionForbidden; } // Returns WorkerScriptController for the currently executing context. 0 will be returned if the current executing context is not the worker context. static WorkerScriptController* controllerForContext(); diff --git a/WebCore/bindings/v8/WorldContextHandle.cpp b/WebCore/bindings/v8/WorldContextHandle.cpp index 7ba76d3..24f461f 100644 --- a/WebCore/bindings/v8/WorldContextHandle.cpp +++ b/WebCore/bindings/v8/WorldContextHandle.cpp @@ -47,10 +47,9 @@ WorldContextHandle::WorldContextHandle(WorldToUse worldToUse) v8::Local<v8::Context> WorldContextHandle::adjustedContext(V8Proxy* proxy) const { - if (m_worldToUse == UseMainWorld) + if (m_worldToUse == UseMainWorld || !m_context || m_context->get().IsEmpty()) return proxy->mainWorldContext(); - if (!m_context || m_context->get().IsEmpty()) - return proxy->context(); + return v8::Local<v8::Context>::New(m_context->get()); } diff --git a/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp b/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp index 9026420..4cc6ac2 100644 --- a/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp +++ b/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp @@ -42,17 +42,11 @@ namespace WebCore { typedef Vector<RefPtr<ScriptProfile> > ProfilesArray; -v8::Handle<v8::Value> V8Console::profilesAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +v8::Handle<v8::Value> V8Console::profilesAccessorGetter(v8::Local<v8::String>, const v8::AccessorInfo&) { INC_STATS("DOM.Console.profilesAccessorGetter"); - Console* imp = V8Console::toNative(info.Holder()); - const ProfilesArray& profiles = imp->profiles(); - v8::Handle<v8::Array> result = v8::Array::New(profiles.size()); - int index = 0; - ProfilesArray::const_iterator end = profiles.end(); - for (ProfilesArray::const_iterator iter = profiles.begin(); iter != end; ++iter) - result->Set(v8::Integer::New(index++), toV8(iter->get())); - return result; + // FIXME: Provide a real implementation. + return v8::Array::New(0); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp deleted file mode 100644 index df0cc53..0000000 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2009 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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" - -#if ENABLE(DATABASE) - -#include "V8CustomSQLStatementCallback.h" - -#include "Frame.h" -#include "ScriptExecutionContext.h" -#include "V8CustomVoidCallback.h" -#include "V8SQLResultSet.h" -#include "V8SQLTransaction.h" - -namespace WebCore { - -V8CustomSQLStatementCallback::V8CustomSQLStatementCallback(v8::Local<v8::Object> callback, Frame* frame) - : m_callback(v8::Persistent<v8::Object>::New(callback)) - , m_frame(frame) - , m_worldContext(UseCurrentWorld) -{ -} - -V8CustomSQLStatementCallback::~V8CustomSQLStatementCallback() -{ - m_callback.Dispose(); -} - -void V8CustomSQLStatementCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, SQLResultSet* resultSet, bool& raisedException) -{ - v8::HandleScope handleScope; - - v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext); - if (v8Context.IsEmpty()) - return; - - v8::Context::Scope scope(v8Context); - - v8::Handle<v8::Value> argv[] = { - toV8(transaction), - toV8(resultSet) - }; - - // Protect the frame until the callback returns. - RefPtr<Frame> protector(m_frame); - - bool callbackReturnValue = false; - raisedException = invokeCallback(m_callback, 2, argv, callbackReturnValue); -} - -} // namespace WebCore - -#endif diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp index 2545f24..e033684 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp @@ -32,7 +32,7 @@ #if ENABLE(DATABASE) -#include "V8CustomSQLStatementErrorCallback.h" +#include "V8SQLStatementErrorCallback.h" #include "Frame.h" #include "ScriptExecutionContext.h" @@ -42,19 +42,7 @@ namespace WebCore { -V8CustomSQLStatementErrorCallback::V8CustomSQLStatementErrorCallback(v8::Local<v8::Object> callback, Frame* frame) - : m_callback(v8::Persistent<v8::Object>::New(callback)) - , m_frame(frame) - , m_worldContext(UseCurrentWorld) -{ -} - -V8CustomSQLStatementErrorCallback::~V8CustomSQLStatementErrorCallback() -{ - m_callback.Dispose(); -} - -bool V8CustomSQLStatementErrorCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, SQLError* error) +bool V8SQLStatementErrorCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, SQLError* error) { v8::HandleScope handleScope; diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.h b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.h deleted file mode 100644 index c3d7f79..0000000 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2009 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 V8CustomSQLStatementErrorCallback_h -#define V8CustomSQLStatementErrorCallback_h - -#if ENABLE(DATABASE) - -#include "SQLStatementErrorCallback.h" -#include "WorldContextHandle.h" -#include <v8.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - -class Frame; - -class V8CustomSQLStatementErrorCallback : public SQLStatementErrorCallback { -public: - static PassRefPtr<V8CustomSQLStatementErrorCallback> create(v8::Local<v8::Value> value, Frame* frame) - { - ASSERT(value->IsObject()); - return adoptRef(new V8CustomSQLStatementErrorCallback(value->ToObject(), frame)); - } - virtual ~V8CustomSQLStatementErrorCallback(); - - virtual bool handleEvent(ScriptExecutionContext*, SQLTransaction*, SQLError*); -private: - V8CustomSQLStatementErrorCallback(v8::Local<v8::Object>, Frame*); - - v8::Persistent<v8::Object> m_callback; - RefPtr<Frame> m_frame; - WorldContextHandle m_worldContext; -}; - -} // namespace WebCore - -#endif - -#endif // V8CustomSQLStatementErrorCallback_h diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp deleted file mode 100644 index efe415c..0000000 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2009, Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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" - -#if ENABLE(DATABASE) - -#include "V8CustomSQLTransactionCallback.h" - -#include "Frame.h" -#include "ScriptExecutionContext.h" -#include "V8CustomVoidCallback.h" -#include "V8SQLTransaction.h" - -namespace WebCore { - -V8CustomSQLTransactionCallback::V8CustomSQLTransactionCallback(v8::Local<v8::Object> callback, Frame* frame) - : m_callback(v8::Persistent<v8::Object>::New(callback)) - , m_frame(frame) - , m_worldContext(UseCurrentWorld) -{ -} - -V8CustomSQLTransactionCallback::~V8CustomSQLTransactionCallback() -{ - m_callback.Dispose(); -} - - -void V8CustomSQLTransactionCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, bool& raisedException) -{ - v8::HandleScope handleScope; - - v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext); - if (v8Context.IsEmpty()) - return; - - v8::Context::Scope scope(v8Context); - - v8::Handle<v8::Value> argv[] = { - toV8(transaction) - }; - - // Protect the frame until the callback returns. - RefPtr<Frame> protector(m_frame); - - // Step 5: If the callback couldn't be called (e.g. it was null) or if - // the callback was invoked and raised an exception, jump to the last - // step (rollback transaction). - bool callbackReturnValue = false; - raisedException = invokeCallback(m_callback, 1, argv, callbackReturnValue); -} - -} // namespace WebCore - -#endif diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.h b/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.h deleted file mode 100644 index 60ad529..0000000 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2009 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 V8CustomSQLTransactionCallback_h -#define V8CustomSQLTransactionCallback_h - -#if ENABLE(DATABASE) - -#include "SQLTransactionCallback.h" -#include "WorldContextHandle.h" -#include <v8.h> -#include <wtf/Forward.h> - -namespace WebCore { - -class Frame; - -class V8CustomSQLTransactionCallback : public SQLTransactionCallback { -public: - static PassRefPtr<V8CustomSQLTransactionCallback> create(v8::Local<v8::Value> value, Frame* frame) - { - ASSERT(value->IsObject()); - return adoptRef(new V8CustomSQLTransactionCallback(value->ToObject(), frame)); - } - virtual ~V8CustomSQLTransactionCallback(); - - virtual void handleEvent(ScriptExecutionContext*, SQLTransaction*, bool& raisedException); -private: - V8CustomSQLTransactionCallback(v8::Local<v8::Object>, Frame*); - - v8::Persistent<v8::Object> m_callback; - RefPtr<Frame> m_frame; - WorldContextHandle m_worldContext; -}; - -} // namespace WebCore - -#endif - -#endif // V8CustomSQLTransactionCallback_h diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp deleted file mode 100644 index 1ef711a..0000000 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2009, Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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" - -#if ENABLE(DATABASE) - -#include "V8CustomSQLTransactionErrorCallback.h" - -#include "Frame.h" -#include "ScriptExecutionContext.h" -#include "V8CustomVoidCallback.h" -#include "V8SQLError.h" - -namespace WebCore { - -V8CustomSQLTransactionErrorCallback::V8CustomSQLTransactionErrorCallback(v8::Local<v8::Object> callback, Frame* frame) - : m_callback(v8::Persistent<v8::Object>::New(callback)) - , m_frame(frame) - , m_worldContext(UseCurrentWorld) -{ -} - -V8CustomSQLTransactionErrorCallback::~V8CustomSQLTransactionErrorCallback() -{ - m_callback.Dispose(); -} - -void V8CustomSQLTransactionErrorCallback::handleEvent(ScriptExecutionContext* context, SQLError* error) -{ - v8::HandleScope handleScope; - - v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext); - if (v8Context.IsEmpty()) - return; - - v8::Context::Scope scope(v8Context); - - v8::Handle<v8::Value> argv[] = { - toV8(error) - }; - - // Protect the frame until the callback returns. - RefPtr<Frame> protector(m_frame); - - bool callbackReturnValue = false; - invokeCallback(m_callback, 1, argv, callbackReturnValue); -} - -} // namespace WebCore - -#endif diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.h b/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.h deleted file mode 100644 index 72e9e7a..0000000 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2009 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 V8CustomSQLTransactionErrorCallback_h -#define V8CustomSQLTransactionErrorCallback_h - -#if ENABLE(DATABASE) - -#include "SQLTransactionErrorCallback.h" -#include "WorldContextHandle.h" -#include <v8.h> -#include <wtf/Forward.h> - -namespace WebCore { - -class Frame; - -class V8CustomSQLTransactionErrorCallback : public SQLTransactionErrorCallback { -public: - static PassRefPtr<V8CustomSQLTransactionErrorCallback> create(v8::Local<v8::Value> value, Frame* frame) - { - ASSERT(value->IsObject()); - return adoptRef(new V8CustomSQLTransactionErrorCallback(value->ToObject(), frame)); - } - virtual ~V8CustomSQLTransactionErrorCallback(); - - virtual void handleEvent(ScriptExecutionContext*, SQLError*); - -private: - V8CustomSQLTransactionErrorCallback(v8::Local<v8::Object>, Frame*); - - v8::Persistent<v8::Object> m_callback; - RefPtr<Frame> m_frame; - WorldContextHandle m_worldContext; -}; - -} // namespace WebCore - -#endif - -#endif // V8CustomSQLTransactionErrorCallback_h diff --git a/WebCore/bindings/v8/custom/V8DatabaseCallback.cpp b/WebCore/bindings/v8/custom/V8DatabaseCallback.cpp deleted file mode 100644 index 088d89f..0000000 --- a/WebCore/bindings/v8/custom/V8DatabaseCallback.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2010, Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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" - -#if ENABLE(DATABASE) - -#include "V8DatabaseCallback.h" - -#include "Frame.h" -#include "ScriptExecutionContext.h" -#include "V8CustomVoidCallback.h" -#include "V8Database.h" - -namespace WebCore { - -V8DatabaseCallback::V8DatabaseCallback(v8::Local<v8::Object> callback, Frame* frame) - : m_callback(v8::Persistent<v8::Object>::New(callback)) - , m_frame(frame) - , m_worldContext(UseCurrentWorld) -{ -} - -V8DatabaseCallback::~V8DatabaseCallback() -{ - m_callback.Dispose(); -} - -void V8DatabaseCallback::handleEvent(ScriptExecutionContext* context, Database* database) -{ - v8::HandleScope handleScope; - - v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext); - if (v8Context.IsEmpty()) - return; - - v8::Context::Scope scope(v8Context); - - v8::Handle<v8::Value> argv[] = { - toV8(database) - }; - - // Protect the frame until the callback returns. - RefPtr<Frame> protector(m_frame); - - bool callbackReturnValue = false; - invokeCallback(m_callback, 1, argv, callbackReturnValue); -} - -} // namespace WebCore - -#endif diff --git a/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp b/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp index 9915d77..39e6632 100644 --- a/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp @@ -35,8 +35,8 @@ #include "Database.h" #include "V8Binding.h" -#include "V8CustomSQLTransactionCallback.h" -#include "V8CustomSQLTransactionErrorCallback.h" +#include "V8SQLTransactionCallback.h" +#include "V8SQLTransactionErrorCallback.h" #include "V8CustomVoidCallback.h" #include "V8Proxy.h" @@ -58,20 +58,20 @@ v8::Handle<v8::Value> V8Database::changeVersionCallback(const v8::Arguments& arg if (!frame) return v8::Undefined(); - RefPtr<V8CustomSQLTransactionCallback> callback; + RefPtr<V8SQLTransactionCallback> callback; if (args.Length() > 2) { if (!args[2]->IsObject()) return throwError("changeVersion transaction callback must be of valid type."); - callback = V8CustomSQLTransactionCallback::create(args[2], frame); + callback = V8SQLTransactionCallback::create(args[2], frame); } - RefPtr<V8CustomSQLTransactionErrorCallback> errorCallback; + RefPtr<V8SQLTransactionErrorCallback> errorCallback; if (args.Length() > 3) { if (!args[3]->IsObject()) return throwError("changeVersion error callback must be of valid type."); - errorCallback = V8CustomSQLTransactionErrorCallback::create(args[3], frame); + errorCallback = V8SQLTransactionErrorCallback::create(args[3], frame); } RefPtr<V8CustomVoidCallback> successCallback; @@ -101,14 +101,14 @@ static v8::Handle<v8::Value> createTransaction(const v8::Arguments& args, bool r if (!frame) return v8::Undefined(); - RefPtr<V8CustomSQLTransactionCallback> callback = V8CustomSQLTransactionCallback::create(args[0], frame); + RefPtr<V8SQLTransactionCallback> callback = V8SQLTransactionCallback::create(args[0], frame); - RefPtr<V8CustomSQLTransactionErrorCallback> errorCallback; + RefPtr<V8SQLTransactionErrorCallback> errorCallback; if (args.Length() > 1 && !isUndefinedOrNull(args[1])) { if (!args[1]->IsObject()) return throwError("Transaction error callback must be of valid type."); - errorCallback = V8CustomSQLTransactionErrorCallback::create(args[1], frame); + errorCallback = V8SQLTransactionErrorCallback::create(args[1], frame); } RefPtr<V8CustomVoidCallback> successCallback; diff --git a/WebCore/bindings/v8/custom/V8HTMLFormElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLFormElementCustom.cpp index 0a9e8dd..786a96a 100644 --- a/WebCore/bindings/v8/custom/V8HTMLFormElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLFormElementCustom.cpp @@ -81,16 +81,4 @@ v8::Handle<v8::Value> V8HTMLFormElement::namedPropertyGetter(v8::Local<v8::Strin return toV8(collection); } -v8::Handle<v8::Value> V8HTMLFormElement::submitCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.HTMLFormElement.submit()"); - HTMLFormElement* form = V8HTMLFormElement::toNative(args.Holder()); - Frame* frame = V8Proxy::retrieveFrameForEnteredContext(); - if (!frame) - return v8::Undefined(); - - form->submit(frame); - return v8::Undefined(); -} - } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp b/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp index 4c091c8..c7cd54c 100644 --- a/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp +++ b/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp @@ -161,12 +161,6 @@ v8::Handle<v8::Value> V8InjectedScriptHost::currentCallFrameCallback(const v8::A INC_STATS("InjectedScriptHost.currentCallFrame()"); return toV8(ScriptDebugServer::shared().currentCallFrame()); } - -v8::Handle<v8::Value> V8InjectedScriptHost::isActivationCallback(const v8::Arguments& args) -{ - INC_STATS("InjectedScriptHost.isActivation()"); - return v8::Boolean::New(true); -} #endif #if ENABLE(DATABASE) diff --git a/WebCore/bindings/v8/custom/V8NodeIteratorCustom.cpp b/WebCore/bindings/v8/custom/V8NodeIteratorCustom.cpp deleted file mode 100644 index 728b3dc..0000000 --- a/WebCore/bindings/v8/custom/V8NodeIteratorCustom.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2007-2009 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 "V8NodeIterator.h" - -#include "NodeIterator.h" -#include "ScriptState.h" - -#include "V8Binding.h" -#include "V8Node.h" -#include "V8Proxy.h" - -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - -static inline v8::Handle<v8::Value> toV8(PassRefPtr<Node> object, ExceptionCode ec, ScriptState* state) -{ - if (ec) - return throwError(ec); - - if (state->hadException()) - return throwError(state->exception()); - - if (!object) - return v8::Null(); - - return toV8(object); -} - -v8::Handle<v8::Value> V8NodeIterator::nextNodeCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.NodeIterator.nextNode()"); - NodeIterator* nodeIterator = V8NodeIterator::toNative(args.Holder()); - - ExceptionCode ec = 0; - EmptyScriptState state; - RefPtr<Node> result = nodeIterator->nextNode(&state, ec); - return toV8(result.release(), ec, &state); -} - -v8::Handle<v8::Value> V8NodeIterator::previousNodeCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.NodeIterator.previousNode()"); - NodeIterator* nodeIterator = V8NodeIterator::toNative(args.Holder()); - - ExceptionCode ec = 0; - EmptyScriptState state; - RefPtr<Node> result = nodeIterator->previousNode(&state, ec); - return toV8(result.release(), ec, &state); -} - -} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp b/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp index cdb160d..51a57c0 100644 --- a/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp +++ b/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp @@ -39,25 +39,6 @@ namespace WebCore { -v8::Handle<v8::Value> V8PopStateEvent::initPopStateEventCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.PopStateEvent.initPopStateEvent"); - - String typeArg = v8ValueToWebCoreString(args[0]); - bool canBubbleArg = args[1]->BooleanValue(); - bool cancelableArg = args[2]->BooleanValue(); - - bool didThrow = false; - RefPtr<SerializedScriptValue> stateArg = SerializedScriptValue::create(args[3], didThrow); - if (didThrow) - return v8::Undefined(); - - PopStateEvent* event = V8PopStateEvent::toNative(args.Holder()); - event->initPopStateEvent(typeArg, canBubbleArg, cancelableArg, stateArg.release()); - - return v8::Undefined(); -} - v8::Handle<v8::Value> V8PopStateEvent::stateAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.PopStateEvent.state"); diff --git a/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp b/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp index b7e7ff2..4e68b30 100644 --- a/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp @@ -37,8 +37,8 @@ #include "Database.h" #include "SQLValue.h" #include "V8Binding.h" -#include "V8CustomSQLStatementCallback.h" -#include "V8CustomSQLStatementErrorCallback.h" +#include "V8SQLStatementCallback.h" +#include "V8SQLStatementErrorCallback.h" #include "V8Proxy.h" #include <wtf/Vector.h> @@ -105,7 +105,7 @@ v8::Handle<v8::Value> V8SQLTransaction::executeSqlCallback(const v8::Arguments& return throwError("Statement callback must be of valid type.", V8Proxy::TypeError); if (frame) - callback = V8CustomSQLStatementCallback::create(args[2], frame); + callback = V8SQLStatementCallback::create(args[2], frame); } RefPtr<SQLStatementErrorCallback> errorCallback; @@ -114,7 +114,7 @@ v8::Handle<v8::Value> V8SQLTransaction::executeSqlCallback(const v8::Arguments& return throwError("Statement error callback must be of valid type.", V8Proxy::TypeError); if (frame) - errorCallback = V8CustomSQLStatementErrorCallback::create(args[3], frame); + errorCallback = V8SQLStatementErrorCallback::create(args[3], frame); } ExceptionCode ec = 0; @@ -127,4 +127,3 @@ v8::Handle<v8::Value> V8SQLTransaction::executeSqlCallback(const v8::Arguments& } // namespace WebCore #endif - diff --git a/WebCore/bindings/v8/custom/V8TreeWalkerCustom.cpp b/WebCore/bindings/v8/custom/V8TreeWalkerCustom.cpp deleted file mode 100644 index 37087df..0000000 --- a/WebCore/bindings/v8/custom/V8TreeWalkerCustom.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2007-2009 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 "V8TreeWalker.h" - -#include "Node.h" -#include "ScriptState.h" -#include "TreeWalker.h" - -#include "V8Binding.h" -#include "V8Node.h" -#include "V8Proxy.h" - -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - -static inline v8::Handle<v8::Value> toV8Object(PassRefPtr<Node> object, ScriptState* state) -{ - if (state->hadException()) - return throwError(state->exception()); - - if (!object) - return v8::Null(); - - return toV8(object); -} - -v8::Handle<v8::Value> V8TreeWalker::parentNodeCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.TreeWalker.parentNode()"); - TreeWalker* treeWalker = V8TreeWalker::toNative(args.Holder()); - - EmptyScriptState state; - RefPtr<Node> result = treeWalker->parentNode(&state); - return toV8Object(result.release(), &state); -} - -v8::Handle<v8::Value> V8TreeWalker::firstChildCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.TreeWalker.firstChild()"); - TreeWalker* treeWalker = V8TreeWalker::toNative(args.Holder()); - - EmptyScriptState state; - RefPtr<Node> result = treeWalker->firstChild(&state); - return toV8Object(result.release(), &state); -} - -v8::Handle<v8::Value> V8TreeWalker::lastChildCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.TreeWalker.lastChild()"); - TreeWalker* treeWalker = V8TreeWalker::toNative(args.Holder()); - - EmptyScriptState state; - RefPtr<Node> result = treeWalker->lastChild(&state); - return toV8Object(result.release(), &state); -} - -v8::Handle<v8::Value> V8TreeWalker::nextNodeCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.TreeWalker.nextNode()"); - TreeWalker* treeWalker = V8TreeWalker::toNative(args.Holder()); - - EmptyScriptState state; - RefPtr<Node> result = treeWalker->nextNode(&state); - return toV8Object(result.release(), &state); -} - -v8::Handle<v8::Value> V8TreeWalker::previousNodeCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.TreeWalker.previousNode()"); - TreeWalker* treeWalker = V8TreeWalker::toNative(args.Holder()); - - EmptyScriptState state; - RefPtr<Node> result = treeWalker->previousNode(&state); - return toV8Object(result.release(), &state); -} - -v8::Handle<v8::Value> V8TreeWalker::nextSiblingCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.TreeWalker.nextSibling()"); - TreeWalker* treeWalker = V8TreeWalker::toNative(args.Holder()); - - EmptyScriptState state; - RefPtr<Node> result = treeWalker->nextSibling(&state); - return toV8Object(result.release(), &state); -} - -v8::Handle<v8::Value> V8TreeWalker::previousSiblingCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.TreeWalker.previousSibling()"); - TreeWalker* treeWalker = V8TreeWalker::toNative(args.Holder()); - - EmptyScriptState state; - RefPtr<Node> result = treeWalker->previousSibling(&state); - return toV8Object(result.release(), &state); -} - -} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp index 1b8936d..75eff67 100644 --- a/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp @@ -105,80 +105,6 @@ static int* jsArrayToIntArray(v8::Handle<v8::Array> array, uint32_t len) return data; } -v8::Handle<v8::Value> V8WebGLRenderingContext::bufferDataCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLRenderingContext.bufferData()"); - - // Forms: - // * bufferData(GLenum target, WebGLArray data, GLenum usage); - // - Sets the buffer's data from the given WebGLArray - // * bufferData(GLenum target, GLsizeiptr size, GLenum usage); - // - Sets the size of the buffer to the given size in bytes - if (args.Length() != 3) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - - WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); - bool ok; - int target = toInt32(args[0], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - int usage = toInt32(args[2], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - if (args[1]->IsInt32()) { - int size = toInt32(args[1]); - ExceptionCode exceptionCode; - context->bufferData(target, size, usage, exceptionCode); - } else if (V8WebGLArray::HasInstance(args[1])) { - WebGLArray* array = V8WebGLArray::toNative(args[1]->ToObject()); - ExceptionCode exceptionCode; - context->bufferData(target, array, usage, exceptionCode); - } else { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8WebGLRenderingContext::bufferSubDataCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLRenderingContext.bufferSubData()"); - - // Forms: - // * bufferSubData(GLenum target, GLintptr offset, WebGLArray data); - if (args.Length() != 3) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - - WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); - bool ok; - int target = toInt32(args[0], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - int offset = toInt32(args[1], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - if (!V8WebGLArray::HasInstance(args[2])) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - WebGLArray* array = V8WebGLArray::toNative(args[2]->ToObject()); - ExceptionCode exceptionCode; - context->bufferSubData(target, offset, array, exceptionCode); - return v8::Undefined(); -} - static v8::Handle<v8::Value> toV8Object(const WebGLGetInfo& info) { switch (info.getType()) { @@ -443,290 +369,6 @@ v8::Handle<v8::Value> V8WebGLRenderingContext::getVertexAttribCallback(const v8: return getObjectParameter(args, kVertexAttrib); } -v8::Handle<v8::Value> V8WebGLRenderingContext::texImage2DCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLRenderingContext.texImage2D()"); - - // Currently supported forms: - // * void texImage2D(in GLenum target, in GLint level, - // in GLint internalformat, - // in GLsizei width, in GLsizei height, in GLint border, - // in GLenum format, in GLenum type, in WebGLArray pixels); - // * void texImage2D(in GLenum target, in GLint level, in ImageData pixels, - // [Optional] in GLboolean flipY, [Optional] in GLboolean premulitplyAlpha); - // * void texImage2D(in GLenum target, in GLint level, in HTMLImageElement image, - // [Optional] in GLboolean flipY, [Optional] in GLboolean premultiplyAlpha); - // * void texImage2D(in GLenum target, in GLint level, in HTMLCanvasElement image, - // [Optional] in GLboolean flipY, [Optional] in GLboolean premultiplyAlpha); - // * void texImage2D(in GLenum target, in GLint level, in HTMLVideoElement image, - // [Optional] in GLboolean flipY, [Optional] in GLboolean premultiplyAlpha); - if (args.Length() != 3 && - args.Length() != 4 && - args.Length() != 5 && - args.Length() != 9) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - - WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); - bool ok; - int target = toInt32(args[0], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - int level = toInt32(args[1], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - - ExceptionCode ec = 0; - if (args.Length() == 3 || - args.Length() == 4 || - args.Length() == 5) { - bool flipY = false; - bool premultiplyAlpha = false; - if (args.Length() >= 4) - flipY = args[3]->BooleanValue(); - if (args.Length() >= 5) - premultiplyAlpha = args[4]->BooleanValue(); - - v8::Handle<v8::Value> arg = args[2]; - if (V8HTMLImageElement::HasInstance(arg)) { - HTMLImageElement* element = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec); - } else if (V8HTMLCanvasElement::HasInstance(arg)) { - HTMLCanvasElement* element = V8HTMLCanvasElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec); - } else if(V8ImageData::HasInstance(arg)) { - ImageData* imageElement = V8ImageData::toNative(v8::Handle<v8::Object>::Cast(arg)); - context->texImage2D(target, level, imageElement, flipY, premultiplyAlpha, ec); - } else if (V8HTMLVideoElement::HasInstance(arg)) { - HTMLVideoElement* element = V8HTMLVideoElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec); - } - else { - // FIXME: consider different / better exception type. - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - // Fall through - } else if (args.Length() == 9) { - int internalformat = toInt32(args[2], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - int width = toInt32(args[3], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - int height = toInt32(args[4], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - int border = toInt32(args[5], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - int format = toInt32(args[6], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - int type = toInt32(args[7], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - v8::Handle<v8::Value> arg = args[8]; - if (!arg->IsObject()) - // Assume that the user is passing null for texture - context->texImage2D(target, - level, - internalformat, - width, - height, - border, - format, - type, - 0, - ec); - else if (V8WebGLArray::HasInstance(arg)) { - WebGLArray* array = V8WebGLArray::toNative(arg->ToObject()); - context->texImage2D(target, - level, - internalformat, - width, - height, - border, - format, - type, - array, - ec); - // Fall through - } else { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - } else { - ASSERT_NOT_REACHED(); - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - if (ec) { - V8Proxy::setDOMException(ec); - return v8::Handle<v8::Value>(); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8WebGLRenderingContext::texSubImage2DCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLRenderingContext.texSubImage2D()"); - - // Currently supported forms: - // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, - // in GLsizei width, in GLsizei height, - // in GLenum format, in GLenum type, in WebGLArray pixels); - // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, - // in ImageData pixels, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); - // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, - // in HTMLImageElement image, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); - // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, - // in HTMLCanvasElement canvas, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); - // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, - // in HTMLVideoElement video, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); - - if (args.Length() != 5 && - args.Length() != 6 && - args.Length() != 7 && - args.Length() != 9) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - - WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); - bool ok; - int target = toInt32(args[0], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - int level = toInt32(args[1], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - int xoff = toInt32(args[2], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - int yoff = toInt32(args[3], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - - ExceptionCode ec = 0; - if (args.Length() == 5 || - args.Length() == 6 || - args.Length() == 7) { - bool flipY = false; - bool premultiplyAlpha = false; - if (args.Length() >= 6) - flipY = args[5]->BooleanValue(); - if (args.Length() >= 7) - premultiplyAlpha = args[6]->BooleanValue(); - - v8::Handle<v8::Value> arg = args[4]; - if (V8HTMLImageElement::HasInstance(arg)) { - HTMLImageElement* element = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec); - } else if (V8HTMLCanvasElement::HasInstance(arg)) { - HTMLCanvasElement* element = V8HTMLCanvasElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec); - } else if(V8ImageData::HasInstance(arg)) { - ImageData* imageElement = V8ImageData::toNative(v8::Handle<v8::Object>::Cast(arg)); - context->texSubImage2D(target, level, xoff, yoff, imageElement, flipY, premultiplyAlpha, ec); - } else if (V8HTMLVideoElement::HasInstance(arg)) { - HTMLVideoElement* element = V8HTMLVideoElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec); - } - else { - // FIXME: consider different / better exception type. - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - // Fall through - } else if (args.Length() == 9) { - int width = toInt32(args[4], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - int height = toInt32(args[5], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - int format = toInt32(args[6], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - int type = toInt32(args[7], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - v8::Handle<v8::Value> arg = args[8]; - if (!arg->IsObject()) - // Assume that the user is passing null for texture - context->texSubImage2D(target, - level, - xoff, - yoff, - width, - height, - format, - type, - 0, - ec); - else if (V8WebGLArray::HasInstance(arg)) { - WebGLArray* array = V8WebGLArray::toNative(arg->ToObject()); - context->texSubImage2D(target, - level, - xoff, - yoff, - width, - height, - format, - type, - array, - ec); - // Fall through - } else { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - } else { - ASSERT_NOT_REACHED(); - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - if (ec) { - V8Proxy::setDOMException(ec); - return v8::Handle<v8::Value>(); - } - return v8::Undefined(); -} - enum FunctionToCall { kUniform1v, kUniform2v, kUniform3v, kUniform4v, kVertexAttrib1v, kVertexAttrib2v, kVertexAttrib3v, kVertexAttrib4v diff --git a/WebCore/bindings/v8/test/run_tests.py b/WebCore/bindings/v8/test/run_tests.py deleted file mode 100644 index e27d559..0000000 --- a/WebCore/bindings/v8/test/run_tests.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/python -# -# Copyright (C) 2010 Google 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. -# - -# This script generates h and cpp file for TestObj.idl using the V8 code -# generator. Please execute the script whenever changes are made to -# CodeGeneratorV8.pm, and submit the changes in V8TestObj.h/cpp in the same -# patch. This makes it easier to track and review changes in generated code. -# To execute, invoke: 'python run_tests.py' - -import os -import sys - - -def test(idlFilePath): - cmd = ['perl', '-w', - '-I../../scripts', - '../../scripts/generate-bindings.pl', - # idl include directories (path relative to generate-bindings.pl) - '--include .', - # place holder for defines (generate-bindings.pl requires it) - '--defines xxx', - '--generator V8', - '--outputDir .', - idlFilePath] - os.system(' '.join(cmd)) - - -def main(argv): - scriptDir = os.path.dirname(__file__) - os.chdir(scriptDir) - test('TestObj.idl') - - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/WebCore/bridge/jni/JNIBridge.cpp b/WebCore/bridge/jni/JNIBridge.cpp index 28e8698..35a0d34 100644 --- a/WebCore/bridge/jni/JNIBridge.cpp +++ b/WebCore/bridge/jni/JNIBridge.cpp @@ -27,7 +27,7 @@ #include "config.h" #include "JNIBridge.h" -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #include "StringBuilder.h" #include <wtf/text/CString.h> @@ -178,4 +178,4 @@ jmethodID JavaMethod::methodID(jobject obj) const return m_methodID; } -#endif // ENABLE(MAC_JAVA_BRIDGE) +#endif // ENABLE(JAVA_BRIDGE) diff --git a/WebCore/bridge/jni/JNIBridge.h b/WebCore/bridge/jni/JNIBridge.h index 5d482a7..78202ae 100644 --- a/WebCore/bridge/jni/JNIBridge.h +++ b/WebCore/bridge/jni/JNIBridge.h @@ -27,7 +27,7 @@ #ifndef JNIBridge_h #define JNIBridge_h -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #include "Bridge.h" #include "JNIUtility.h" @@ -118,6 +118,6 @@ private: } // namespace JSC -#endif // ENABLE(MAC_JAVA_BRIDGE) +#endif // ENABLE(JAVA_BRIDGE) #endif // JNIBridge_h diff --git a/WebCore/bridge/jni/JNIUtility.cpp b/WebCore/bridge/jni/JNIUtility.cpp index ece39ed..4b4f393 100644 --- a/WebCore/bridge/jni/JNIUtility.cpp +++ b/WebCore/bridge/jni/JNIUtility.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "JNIUtility.h" -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #include <dlfcn.h> @@ -340,4 +340,4 @@ jvalue getJNIField(jobject obj, JNIType type, const char* name, const char* sign } // namespace JSC -#endif // ENABLE(MAC_JAVA_BRIDGE) +#endif // ENABLE(JAVA_BRIDGE) diff --git a/WebCore/bridge/jni/JNIUtility.h b/WebCore/bridge/jni/JNIUtility.h index 0eb889c..5fb2138 100644 --- a/WebCore/bridge/jni/JNIUtility.h +++ b/WebCore/bridge/jni/JNIUtility.h @@ -26,7 +26,7 @@ #ifndef JNIUtility_h #define JNIUtility_h -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #include <JavaVM/jni.h> @@ -270,6 +270,6 @@ T callJNIStaticMethod(jclass cls, const char* methodName, const char* methodSign } // namespace JSC -#endif // ENABLE(MAC_JAVA_BRIDGE) +#endif // ENABLE(JAVA_BRIDGE) #endif // JNIUtility_h diff --git a/WebCore/bridge/jni/jni_jsobject.h b/WebCore/bridge/jni/jni_jsobject.h index d78eb97..3c87043 100644 --- a/WebCore/bridge/jni/jni_jsobject.h +++ b/WebCore/bridge/jni/jni_jsobject.h @@ -26,7 +26,7 @@ #ifndef JAVASCRIPTCORE_BINDINGS_JNI_JSOBJECT_H #define JAVASCRIPTCORE_BINDINGS_JNI_JSOBJECT_H -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #include <JavaVM/jni.h> #include <runtime/JSValue.h> @@ -128,6 +128,10 @@ jstring KJS_JSObject_JSObjectToString(JNIEnv*, jclass, jlong nativeJSObject); #endif // PLATFORM(MAC) +<<<<<<< HEAD:WebCore/bridge/jni/jni_jsobject.h #endif // ENABLE(MAC_JAVA_BRIDGE) +======= +#endif // ENABLE(JAVA_BRIDGE) +>>>>>>> webkit.org at r58956:WebCore/bridge/jni/jni_jsobject.h #endif // JAVASCRIPTCORE_BINDINGS_JNI_JSOBJECT_H diff --git a/WebCore/bridge/jni/jni_jsobject.mm b/WebCore/bridge/jni/jni_jsobject.mm index 5e036ab..3fb794b 100644 --- a/WebCore/bridge/jni/jni_jsobject.mm +++ b/WebCore/bridge/jni/jni_jsobject.mm @@ -26,7 +26,7 @@ #include "config.h" #include "jni_jsobject.h" -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #include "Frame.h" #include "JavaRuntimeObject.h" @@ -702,4 +702,4 @@ jstring KJS_JSObject_JSObjectToString (JNIEnv*, jclass, jlong nativeHandle) } -#endif // ENABLE(MAC_JAVA_BRIDGE) +#endif // ENABLE(JAVA_BRIDGE) diff --git a/WebCore/bridge/jni/jni_objc.mm b/WebCore/bridge/jni/jni_objc.mm index e2e71c5..8fa2c3f 100644 --- a/WebCore/bridge/jni/jni_objc.mm +++ b/WebCore/bridge/jni/jni_objc.mm @@ -25,7 +25,7 @@ #include "config.h" -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #import <Foundation/Foundation.h> #import "JNIUtility.h" @@ -81,4 +81,4 @@ bool JSC::Bindings::dispatchJNICall(ExecState* exec, const void* targetAppletVie return false; } -#endif // ENABLE(MAC_JAVA_BRIDGE) +#endif // ENABLE(JAVA_BRIDGE) diff --git a/WebCore/bridge/jni/jsc/JNIBridgeJSC.cpp b/WebCore/bridge/jni/jsc/JNIBridgeJSC.cpp index 6de1011..24e2b91 100644 --- a/WebCore/bridge/jni/jsc/JNIBridgeJSC.cpp +++ b/WebCore/bridge/jni/jsc/JNIBridgeJSC.cpp @@ -27,7 +27,7 @@ #include "config.h" #include "JNIBridgeJSC.h" -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #include "JNIUtilityPrivate.h" #include "Logging.h" @@ -442,4 +442,4 @@ unsigned int JavaArray::getLength() const return m_length; } -#endif // ENABLE(MAC_JAVA_BRIDGE) +#endif // ENABLE(JAVA_BRIDGE) diff --git a/WebCore/bridge/jni/jsc/JNIBridgeJSC.h b/WebCore/bridge/jni/jsc/JNIBridgeJSC.h index 902bd4e..dd65417 100644 --- a/WebCore/bridge/jni/jsc/JNIBridgeJSC.h +++ b/WebCore/bridge/jni/jsc/JNIBridgeJSC.h @@ -27,7 +27,7 @@ #ifndef JNIBridgeJSC_h #define JNIBridgeJSC_h -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #include "Bridge.h" #include "JNIBridge.h" @@ -84,6 +84,6 @@ private: } // namespace JSC -#endif // ENABLE(MAC_JAVA_BRIDGE) +#endif // ENABLE(JAVA_BRIDGE) #endif // JNIBridge_h diff --git a/WebCore/bridge/jni/jsc/JNIUtilityPrivate.cpp b/WebCore/bridge/jni/jsc/JNIUtilityPrivate.cpp index b48a757..2048d8e 100644 --- a/WebCore/bridge/jni/jsc/JNIUtilityPrivate.cpp +++ b/WebCore/bridge/jni/jsc/JNIUtilityPrivate.cpp @@ -27,7 +27,7 @@ #include "config.h" #include "JNIUtilityPrivate.h" -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #include "JavaRuntimeObject.h" #include "JNIBridgeJSC.h" @@ -314,4 +314,4 @@ jvalue convertValueToJValue(ExecState* exec, RootObject* rootObject, JSValue val } // end of namespace JSC -#endif // ENABLE(MAC_JAVA_BRIDGE) +#endif // ENABLE(JAVA_BRIDGE) diff --git a/WebCore/bridge/jni/jsc/JNIUtilityPrivate.h b/WebCore/bridge/jni/jsc/JNIUtilityPrivate.h index 8d4652d..1266acd 100644 --- a/WebCore/bridge/jni/jsc/JNIUtilityPrivate.h +++ b/WebCore/bridge/jni/jsc/JNIUtilityPrivate.h @@ -27,7 +27,7 @@ #ifndef JNIUtilityPrivate_h #define JNIUtilityPrivate_h -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #include "JNIUtility.h" #include <runtime/JSValue.h> @@ -48,6 +48,6 @@ bool dispatchJNICall(ExecState*, const void* targetAppletView, jobject obj, bool } // namespace JSC -#endif // ENABLE(MAC_JAVA_BRIDGE) +#endif // ENABLE(JAVA_BRIDGE) #endif // JNIUtilityPrivate_h diff --git a/WebCore/bridge/jni/jsc/JavaClassJSC.cpp b/WebCore/bridge/jni/jsc/JavaClassJSC.cpp index e1b8b4c..780c4fc 100644 --- a/WebCore/bridge/jni/jsc/JavaClassJSC.cpp +++ b/WebCore/bridge/jni/jsc/JavaClassJSC.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "JavaClassJSC.h" -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #include "JNIUtility.h" #include "JSDOMWindow.h" @@ -147,4 +147,4 @@ bool JavaClass::isStringClass() const return !strcmp(m_name, "java.lang.String"); } -#endif // ENABLE(MAC_JAVA_BRIDGE) +#endif // ENABLE(JAVA_BRIDGE) diff --git a/WebCore/bridge/jni/jsc/JavaClassJSC.h b/WebCore/bridge/jni/jsc/JavaClassJSC.h index 09b93e9..0527162 100644 --- a/WebCore/bridge/jni/jsc/JavaClassJSC.h +++ b/WebCore/bridge/jni/jsc/JavaClassJSC.h @@ -26,7 +26,7 @@ #ifndef JavaClassJSC_h #define JavaClassJSC_h -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #include "JNIBridgeJSC.h" #include <wtf/HashMap.h> @@ -57,6 +57,6 @@ private: } // namespace JSC -#endif // ENABLE(MAC_JAVA_BRIDGE) +#endif // ENABLE(JAVA_BRIDGE) #endif // JavaClassJSC_h diff --git a/WebCore/bridge/jni/jsc/JavaInstanceJSC.cpp b/WebCore/bridge/jni/jsc/JavaInstanceJSC.cpp index d8de40a..008d1ab 100644 --- a/WebCore/bridge/jni/jsc/JavaInstanceJSC.cpp +++ b/WebCore/bridge/jni/jsc/JavaInstanceJSC.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "JavaInstanceJSC.h" -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #include "JavaRuntimeObject.h" #include "JNIBridgeJSC.h" @@ -392,4 +392,4 @@ JObjectWrapper::~JObjectWrapper() m_env->DeleteGlobalRef(m_instance); } -#endif // ENABLE(MAC_JAVA_BRIDGE) +#endif // ENABLE(JAVA_BRIDGE) diff --git a/WebCore/bridge/jni/jsc/JavaInstanceJSC.h b/WebCore/bridge/jni/jsc/JavaInstanceJSC.h index d395cc8..53b6132 100644 --- a/WebCore/bridge/jni/jsc/JavaInstanceJSC.h +++ b/WebCore/bridge/jni/jsc/JavaInstanceJSC.h @@ -26,7 +26,7 @@ #ifndef JavaInstanceJSC_h #define JavaInstanceJSC_h -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #include "Bridge.h" #include "runtime_root.h" @@ -107,6 +107,6 @@ protected: } // namespace JSC -#endif // ENABLE(MAC_JAVA_BRIDGE) +#endif // ENABLE(JAVA_BRIDGE) #endif // JavaInstanceJSC_h diff --git a/WebCore/bridge/npapi.h b/WebCore/bridge/npapi.h index f82d25e..38e0905 100644 --- a/WebCore/bridge/npapi.h +++ b/WebCore/bridge/npapi.h @@ -43,6 +43,8 @@ #ifndef _NPAPI_H_ #define _NPAPI_H_ +#include "nptypes.h" + #ifdef INCLUDE_JAVA #include "jri.h" /* Java Runtime Interface */ #else @@ -127,42 +129,6 @@ /* Definition of Basic Types */ /*----------------------------------------------------------------------*/ -/* QNX sets the _INT16 and friends defines, but does not typedef the types */ -#ifdef __QNXNTO__ -#undef _UINT16 -#undef _INT16 -#undef _UINT32 -#undef _INT32 -#endif - -#ifndef _UINT16 -#define _UINT16 -typedef unsigned short uint16; -#endif - -#ifndef _UINT32 -#define _UINT32 -#ifdef __LP64__ -typedef unsigned int uint32; -#else /* __LP64__ */ -typedef unsigned long uint32; -#endif /* __LP64__ */ -#endif - -#ifndef _INT16 -#define _INT16 -typedef short int16; -#endif - -#ifndef _INT32 -#define _INT32 -#ifdef __LP64__ -typedef int int32; -#else /* __LP64__ */ -typedef long int32; -#endif /* __LP64__ */ -#endif - #ifndef FALSE #define FALSE (0) #endif @@ -174,8 +140,8 @@ typedef long int32; #endif typedef unsigned char NPBool; -typedef int16 NPError; -typedef int16 NPReason; +typedef int16_t NPError; +typedef int16_t NPReason; typedef char* NPMIMEType; @@ -207,8 +173,8 @@ typedef struct _NPStream void* pdata; /* plug-in private data */ void* ndata; /* netscape private data */ const char* url; - uint32 end; - uint32 lastmodified; + uint32_t end; + uint32_t lastmodified; void* notifyData; const char* headers; /* Response headers from host. * Exists only for >= NPVERS_HAS_RESPONSE_HEADERS. @@ -225,25 +191,25 @@ typedef struct _NPStream typedef struct _NPByteRange { - int32 offset; /* negative offset means from the end */ - uint32 length; + int32_t offset; /* negative offset means from the end */ + uint32_t length; struct _NPByteRange* next; } NPByteRange; typedef struct _NPSavedData { - int32 len; + int32_t len; void* buf; } NPSavedData; typedef struct _NPRect { - uint16 top; - uint16 left; - uint16 bottom; - uint16 right; + uint16_t top; + uint16_t left; + uint16_t bottom; + uint16_t right; } NPRect; @@ -264,12 +230,12 @@ enum { typedef struct { - int32 type; + int32_t type; } NPAnyCallbackStruct; typedef struct { - int32 type; + int32_t type; Display* display; Visual* visual; Colormap colormap; @@ -278,7 +244,7 @@ typedef struct typedef struct { - int32 type; + int32_t type; FILE* fp; } NPPrintCallbackStruct; @@ -498,25 +464,25 @@ typedef struct _NPNSMenu NPNSMenu; typedef struct _NPCocoaEvent { NPCocoaEventType type; - uint32 version; + uint32_t version; union { struct { - uint32 modifierFlags; + uint32_t modifierFlags; double pluginX; double pluginY; - int32 buttonNumber; - int32 clickCount; + int32_t buttonNumber; + int32_t clickCount; double deltaX; double deltaY; double deltaZ; } mouse; struct { - uint32 modifierFlags; + uint32_t modifierFlags; NPNSString *characters; NPNSString *charactersIgnoringModifiers; NPBool isARepeat; - uint16 keyCode; + uint16_t keyCode; } key; struct { CGContextRef context; @@ -540,10 +506,10 @@ typedef struct _NPCocoaEvent { typedef struct _NPWindow { void* window; /* Platform specific window handle */ - int32 x; /* Position of top left corner relative */ - int32 y; /* to a netscape page. */ - uint32 width; /* Maximum window size */ - uint32 height; + int32_t x; /* Position of top left corner relative */ + int32_t y; /* to a netscape page. */ + uint32_t width; /* Maximum window size */ + uint32_t height; NPRect clipRect; /* Clipping rectangle in port coordinates */ /* Used by MAC only. */ #if defined(XP_UNIX) || defined(XP_SYMBIAN) @@ -570,7 +536,7 @@ typedef struct _NPEmbedPrint typedef struct _NPPrint { - uint16 mode; /* NP_FULL or NP_EMBED */ + uint16_t mode; /* NP_FULL or NP_EMBED */ union { NPFullPrint fullPrint; /* if mode is NP_FULL */ @@ -603,9 +569,9 @@ typedef QEvent NPEvent; #elif defined(XP_WIN) typedef struct _NPEvent { - uint16 event; - uint32 wParam; - uint32 lParam; + uint16_t event; + uintptr_t wParam; + uintptr_t lParam; } NPEvent; #elif defined (XP_UNIX) typedef XEvent NPEvent; @@ -691,8 +657,8 @@ typedef struct NP_GLContext typedef struct NP_Port { CGrafPtr port; /* Grafport */ - int32 portx; /* position inside the topmost window */ - int32 porty; + int32_t portx; /* position inside the topmost window */ + int32_t porty; } NP_Port; #endif /* NP_NO_QUICKDRAW */ @@ -815,22 +781,22 @@ char* NPP_GetMIMEDescription(void); NPError NPP_Initialize(void); void NPP_Shutdown(void); NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance, - uint16 mode, int16 argc, char* argn[], + uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved); NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save); NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window); NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, - uint16* stype); + uint16_t* stype); NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason); -int32 NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream); -int32 NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32 offset, - int32 len, void* buffer); +int32_t NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream); +int32_t NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32_t offset, + int32_t len, void* buffer); void NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname); void NP_LOADDS NPP_Print(NPP instance, NPPrint* platformPrint); -int16 NPP_HandleEvent(NPP instance, void* event); +int16_t NPP_HandleEvent(NPP instance, void* event); void NP_LOADDS NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData); jref NP_LOADDS NPP_GetJavaClass(void); @@ -850,24 +816,24 @@ NPError NPN_GetURLNotify(NPP instance, const char* url, NPError NPN_GetURL(NPP instance, const char* url, const char* target); NPError NPN_PostURLNotify(NPP instance, const char* url, - const char* target, uint32 len, + const char* target, uint32_t len, const char* buf, NPBool file, void* notifyData); NPError NPN_PostURL(NPP instance, const char* url, - const char* target, uint32 len, + const char* target, uint32_t len, const char* buf, NPBool file); NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList); NPError NPN_NewStream(NPP instance, NPMIMEType type, const char* target, NPStream** stream); -int32 NPN_Write(NPP instance, NPStream* stream, int32 len, +int32_t NPN_Write(NPP instance, NPStream* stream, int32_t len, void* buffer); NPError NPN_DestroyStream(NPP instance, NPStream* stream, NPReason reason); void NPN_Status(NPP instance, const char* message); const char* NPN_UserAgent(NPP instance); -void* NPN_MemAlloc(uint32 size); +void* NPN_MemAlloc(uint32_t size); void NPN_MemFree(void* ptr); -uint32 NPN_MemFlush(uint32 size); +uint32_t NPN_MemFlush(uint32_t size); void NPN_ReloadPlugins(NPBool reloadPages); JRIEnv* NPN_GetJavaEnv(void); jref NPN_GetJavaPeer(NPP instance); @@ -881,11 +847,11 @@ void NPN_ForceRedraw(NPP instance); void NPN_PushPopupsEnabledState(NPP instance, NPBool enabled); void NPN_PopPopupsEnabledState(NPP instance); void NPN_PluginThreadAsyncCall(NPP instance, void (*func) (void *), void *userData); -NPError NPN_GetValueForURL(NPP instance, NPNURLVariable variable, const char* url, char** value, uint32* len); -NPError NPN_SetValueForURL(NPP instance, NPNURLVariable variable, const char* url, const char* value, uint32 len); -NPError NPN_GetAuthenticationInfo(NPP instance, const char* protocol, const char* host, int32 port, const char* scheme, const char *realm, char** username, uint32* ulen, char** password, uint32* plen); -uint32 NPN_ScheduleTimer(NPP instance, uint32 interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32 timerID)); -void NPN_UnscheduleTimer(NPP instance, uint32 timerID); +NPError NPN_GetValueForURL(NPP instance, NPNURLVariable variable, const char* url, char** value, uint32_t* len); +NPError NPN_SetValueForURL(NPP instance, NPNURLVariable variable, const char* url, const char* value, uint32_t len); +NPError NPN_GetAuthenticationInfo(NPP instance, const char* protocol, const char* host, int32_t port, const char* scheme, const char *realm, char** username, uint32_t* ulen, char** password, uint32_t* plen); +uint32_t NPN_ScheduleTimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID)); +void NPN_UnscheduleTimer(NPP instance, uint32_t timerID); NPError NPN_PopUpContextMenu(NPP instance, NPMenu* menu); NPBool NPN_ConvertPoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace); diff --git a/WebCore/bridge/npruntime.h b/WebCore/bridge/npruntime.h index 8a285be..d5ebcb2 100644 --- a/WebCore/bridge/npruntime.h +++ b/WebCore/bridge/npruntime.h @@ -72,7 +72,6 @@ extern "C" { #endif -#include <stdint.h> #include "npapi.h" /* diff --git a/WebCore/bridge/nptypes.h b/WebCore/bridge/nptypes.h new file mode 100644 index 0000000..11e9683 --- /dev/null +++ b/WebCore/bridge/nptypes.h @@ -0,0 +1,214 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * mozilla.org. + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Johnny Stenback <jst@mozilla.org> (Original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Header file for ensuring that C99 types ([u]int32_t and bool) are + * available. + */ + +#if defined(WIN32) || defined(OS2) + /* + * Win32 and OS/2 don't know C99, so define [u]int_16/32 here. The bool + * is predefined tho, both in C and C++. + */ + typedef short int16_t; + typedef unsigned short uint16_t; + typedef int int32_t; + typedef unsigned int uint32_t; +#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(IRIX) || defined(HPUX) + /* + * AIX and SunOS ship a inttypes.h header that defines [u]int32_t, + * but not bool for C. + */ + #include <inttypes.h> + + #ifndef __cplusplus + typedef int bool; + #endif +#elif defined(bsdi) || defined(FREEBSD) || defined(OPENBSD) + /* + * BSD/OS, FreeBSD, and OpenBSD ship sys/types.h that define int32_t and + * u_int32_t. + */ + #include <sys/types.h> + + /* + * BSD/OS ships no header that defines uint32_t, nor bool (for C) + */ + #if defined(bsdi) + typedef u_int32_t uint32_t; + + #if !defined(__cplusplus) + typedef int bool; + #endif + #else + /* + * FreeBSD and OpenBSD define uint32_t and bool. + */ + #include <inttypes.h> + #include <stdbool.h> + #endif +#elif defined(BEOS) + #include <inttypes.h> +#else + /* + * For those that ship a standard C99 stdint.h header file, include + * it. Can't do the same for stdbool.h tho, since some systems ship + * with a stdbool.h file that doesn't compile! + */ + #include <stdint.h> + + #ifndef __cplusplus + #if !defined(__GNUC__) || (__GNUC__ > 2 || __GNUC_MINOR__ > 95) + #include <stdbool.h> + #else + /* + * GCC 2.91 can't deal with a typedef for bool, but a #define + * works. + */ + #define bool int + #endif + #endif +#endif +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * mozilla.org. + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Johnny Stenback <jst@mozilla.org> (Original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * Header file for ensuring that C99 types ([u]int32_t and bool) are + * available. + */ + +#if defined(WIN32) || defined(OS2) + /* + * Win32 and OS/2 don't know C99, so define [u]int_16/32 here. The bool + * is predefined tho, both in C and C++. + */ + typedef short int16_t; + typedef unsigned short uint16_t; + typedef int int32_t; + typedef unsigned int uint32_t; +#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(IRIX) || defined(HPUX) + /* + * AIX and SunOS ship a inttypes.h header that defines [u]int32_t, + * but not bool for C. + */ + #include <inttypes.h> + + #ifndef __cplusplus + typedef int bool; + #endif +#elif defined(bsdi) || defined(FREEBSD) || defined(OPENBSD) + /* + * BSD/OS, FreeBSD, and OpenBSD ship sys/types.h that define int32_t and + * u_int32_t. + */ + #include <sys/types.h> + + /* + * BSD/OS ships no header that defines uint32_t, nor bool (for C) + */ + #if defined(bsdi) + typedef u_int32_t uint32_t; + + #if !defined(__cplusplus) + typedef int bool; + #endif + #else + /* + * FreeBSD and OpenBSD define uint32_t and bool. + */ + #include <inttypes.h> + #include <stdbool.h> + #endif +#elif defined(BEOS) + #include <inttypes.h> +#else + /* + * For those that ship a standard C99 stdint.h header file, include + * it. Can't do the same for stdbool.h tho, since some systems ship + * with a stdbool.h file that doesn't compile! + */ + #include <stdint.h> + + #ifndef __cplusplus + #if !defined(__GNUC__) || (__GNUC__ > 2 || __GNUC_MINOR__ > 95) + #include <stdbool.h> + #else + /* + * GCC 2.91 can't deal with a typedef for bool, but a #define + * works. + */ + #define bool int + #endif + #endif +#endif diff --git a/WebCore/bridge/qt/qt_instance.cpp b/WebCore/bridge/qt/qt_instance.cpp index 4e39371..f6f368b 100644 --- a/WebCore/bridge/qt/qt_instance.cpp +++ b/WebCore/bridge/qt/qt_instance.cpp @@ -171,10 +171,11 @@ QtInstance* QtInstance::getInstance(JSObject* object) Class* QtInstance::getClass() const { - if (!m_object) - return 0; - if (!m_class) + if (!m_class) { + if (!m_object) + return 0; m_class = QtClass::classForObject(m_object); + } return m_class; } diff --git a/WebCore/bridge/qt/qt_runtime.cpp b/WebCore/bridge/qt/qt_runtime.cpp index 40ff6a1..1775815 100644 --- a/WebCore/bridge/qt/qt_runtime.cpp +++ b/WebCore/bridge/qt/qt_runtime.cpp @@ -897,7 +897,7 @@ JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, con QVariantMap::const_iterator i = map.constBegin(); while (i != map.constEnd()) { QString s = i.key(); - JSValue val = convertQVariantToValue(exec, root, i.value()); + JSValue val = convertQVariantToValue(exec, root.get(), i.value()); if (val) { PutPropertySlot slot; ret->put(exec, Identifier(exec, (const UChar *)s.constData(), s.length()), val, slot); diff --git a/WebCore/config.h b/WebCore/config.h index 24b0f14..c812ee8 100644 --- a/WebCore/config.h +++ b/WebCore/config.h @@ -25,7 +25,7 @@ #include <wtf/Platform.h> -#if OS(WINDOWS) && !defined(BUILDING_WX__) && !COMPILER(GCC) +#if !PLATFORM(CHROMIUM) && OS(WINDOWS) && !defined(BUILDING_WX__) && !COMPILER(GCC) #if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF) #define JS_EXPORTDATA __declspec(dllexport) #else diff --git a/WebCore/css/CSSComputedStyleDeclaration.cpp b/WebCore/css/CSSComputedStyleDeclaration.cpp index d7f585f..86756b7 100644 --- a/WebCore/css/CSSComputedStyleDeclaration.cpp +++ b/WebCore/css/CSSComputedStyleDeclaration.cpp @@ -1474,6 +1474,8 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper break; /* Other unimplemented properties */ + case CSSPropertyBackgroundRepeatX: + case CSSPropertyBackgroundRepeatY: case CSSPropertyContent: // FIXME: needs implementation, bug 23668 case CSSPropertyCounterIncrement: case CSSPropertyCounterReset: @@ -1494,6 +1496,8 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper case CSSPropertyWebkitMarquee: case CSSPropertyWebkitMarqueeSpeed: case CSSPropertyWebkitMask: + case CSSPropertyWebkitMaskRepeatX: + case CSSPropertyWebkitMaskRepeatY: case CSSPropertyWebkitPaddingStart: case CSSPropertyWebkitPerspectiveOriginX: case CSSPropertyWebkitPerspectiveOriginY: @@ -1546,7 +1550,7 @@ void CSSComputedStyleDeclaration::setProperty(int /*propertyID*/, const String& ec = NO_MODIFICATION_ALLOWED_ERR; } -unsigned CSSComputedStyleDeclaration::length() const +unsigned CSSComputedStyleDeclaration::virtualLength() const { Node* node = m_node.get(); if (!node) diff --git a/WebCore/css/CSSComputedStyleDeclaration.h b/WebCore/css/CSSComputedStyleDeclaration.h index eb93bad..ba55d77 100644 --- a/WebCore/css/CSSComputedStyleDeclaration.h +++ b/WebCore/css/CSSComputedStyleDeclaration.h @@ -39,7 +39,7 @@ public: virtual String cssText() const; - virtual unsigned length() const; + virtual unsigned virtualLength() const; virtual String item(unsigned index) const; virtual PassRefPtr<CSSValue> getPropertyCSSValue(int propertyID) const; diff --git a/WebCore/css/CSSFontFaceSrcValue.cpp b/WebCore/css/CSSFontFaceSrcValue.cpp index 308ff31..21eea04 100644 --- a/WebCore/css/CSSFontFaceSrcValue.cpp +++ b/WebCore/css/CSSFontFaceSrcValue.cpp @@ -49,6 +49,9 @@ bool CSSFontFaceSrcValue::isSupportedFormat() const } return equalIgnoringCase(m_format, "truetype") || equalIgnoringCase(m_format, "opentype") +#if ENABLE(OPENTYPE_SANITIZER) + || equalIgnoringCase(m_format, "woff") +#endif #if ENABLE(SVG_FONTS) || isSVGFontFaceSrc() #endif diff --git a/WebCore/css/CSSGrammar.y b/WebCore/css/CSSGrammar.y index ec0c141..7798264 100644 --- a/WebCore/css/CSSGrammar.y +++ b/WebCore/css/CSSGrammar.y @@ -70,6 +70,7 @@ using namespace HTMLNames; CSSRuleList* ruleList; CSSSelector* selector; Vector<CSSSelector*>* selectorList; + CSSSelector::MarginBoxType marginBox; CSSSelector::Relation relation; MediaList* mediaList; MediaQuery* mediaQuery; @@ -97,7 +98,7 @@ static int cssyylex(YYSTYPE* yylval, void* parser) %} -%expect 54 +%expect 55 %nonassoc LOWEST_PREC @@ -142,6 +143,23 @@ static int cssyylex(YYSTYPE* yylval, void* parser) %token WEBKIT_DEFINE_SYM %token VARIABLES_FOR %token WEBKIT_VARIABLES_DECLS_SYM +%token <marginBox> TOPLEFTCORNER_SYM +%token <marginBox> TOPLEFT_SYM +%token <marginBox> TOPCENTER_SYM +%token <marginBox> TOPRIGHT_SYM +%token <marginBox> TOPRIGHTCORNER_SYM +%token <marginBox> BOTTOMLEFTCORNER_SYM +%token <marginBox> BOTTOMLEFT_SYM +%token <marginBox> BOTTOMCENTER_SYM +%token <marginBox> BOTTOMRIGHT_SYM +%token <marginBox> BOTTOMRIGHTCORNER_SYM +%token <marginBox> LEFTTOP_SYM +%token <marginBox> LEFTMIDDLE_SYM +%token <marginBox> LEFTBOTTOM_SYM +%token <marginBox> RIGHTTOP_SYM +%token <marginBox> RIGHTMIDDLE_SYM +%token <marginBox> RIGHTBOTTOM_SYM + %token ATKEYWORD %token IMPORTANT_SYM @@ -188,6 +206,7 @@ static int cssyylex(YYSTYPE* yylval, void* parser) %type <rule> import %type <rule> namespace %type <rule> page +%type <rule> margin_box %type <rule> font_face %type <rule> keyframes %type <rule> invalid_rule @@ -209,6 +228,7 @@ static int cssyylex(YYSTYPE* yylval, void* parser) %type <string> ident_or_string %type <string> medium %type <string> hexcolor +%type <marginBox> margin_sym %type <string> media_feature %type <mediaList> media_list @@ -237,10 +257,12 @@ static int cssyylex(YYSTYPE* yylval, void* parser) %type <selector> class %type <selector> attrib %type <selector> pseudo +%type <selector> page_selector %type <boolean> declaration_list %type <boolean> decl_list %type <boolean> declaration +%type <boolean> declarations_and_margins %type <boolean> prio @@ -729,26 +751,105 @@ key: } ; -/* page: - PAGE_SYM maybe_space IDENT? pseudo_page? maybe_space - '{' maybe_space declaration [ ';' maybe_space declaration ]* '}' maybe_space - ; - -pseudo_page - : ':' IDENT - ; -*/ - -page: - PAGE_SYM error invalid_block { + PAGE_SYM maybe_space page_selector maybe_space + '{' maybe_space declarations_and_margins closing_brace { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createPageRule(p->sinkFloatingSelector($3)); + } + | PAGE_SYM error invalid_block { $$ = 0; } - | PAGE_SYM error ';' { + | PAGE_SYM error ';' { $$ = 0; } ; +page_selector: + IDENT { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelector(); + $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace); + } + | IDENT pseudo { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = $2; + if ($$) + $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace); + } + | pseudo { + $$ = $1; + } + | /* empty */ { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelector(); + } + ; + +declarations_and_margins: + declaration_list + | declarations_and_margins margin_box maybe_space declaration_list + ; + +margin_box: + margin_sym { + static_cast<CSSParser*>(parser)->startDeclarationsForMarginBox(); + } maybe_space '{' maybe_space declaration_list closing_brace { + $$ = static_cast<CSSParser*>(parser)->createMarginAtRule($1); + } + ; + +margin_sym : + TOPLEFTCORNER_SYM { + $$ = CSSSelector::TopLeftCornerMarginBox; + } + | TOPLEFT_SYM { + $$ = CSSSelector::TopLeftMarginBox; + } + | TOPCENTER_SYM { + $$ = CSSSelector::TopCenterMarginBox; + } + | TOPRIGHT_SYM { + $$ = CSSSelector::TopRightMarginBox; + } + | TOPRIGHTCORNER_SYM { + $$ = CSSSelector::TopRightCornerMarginBox; + } + | BOTTOMLEFTCORNER_SYM { + $$ = CSSSelector::BottomLeftCornerMarginBox; + } + | BOTTOMLEFT_SYM { + $$ = CSSSelector::BottomLeftMarginBox; + } + | BOTTOMCENTER_SYM { + $$ = CSSSelector::BottomCenterMarginBox; + } + | BOTTOMRIGHT_SYM { + $$ = CSSSelector::BottomRightMarginBox; + } + | BOTTOMRIGHTCORNER_SYM { + $$ = CSSSelector::BottomRightCornerMarginBox; + } + | LEFTTOP_SYM { + $$ = CSSSelector::LeftTopMarginBox; + } + | LEFTMIDDLE_SYM { + $$ = CSSSelector::LeftMiddleMarginBox; + } + | LEFTBOTTOM_SYM { + $$ = CSSSelector::LeftBottomMarginBox; + } + | RIGHTTOP_SYM { + $$ = CSSSelector::RightTopMarginBox; + } + | RIGHTMIDDLE_SYM { + $$ = CSSSelector::RightMiddleMarginBox; + } + | RIGHTBOTTOM_SYM { + $$ = CSSSelector::RightBottomMarginBox; + } + ; + font_face: FONT_FACE_SYM maybe_space '{' maybe_space declaration_list '}' maybe_space { diff --git a/WebCore/css/CSSHelper.cpp b/WebCore/css/CSSHelper.cpp index 8e6f3a0..c3418b4 100644 --- a/WebCore/css/CSSHelper.cpp +++ b/WebCore/css/CSSHelper.cpp @@ -36,7 +36,7 @@ String deprecatedParseURL(const String& url) int o = 0; int l = i->length(); - while (o < l && (*i)[o] <= ' ') { + while (0 < l && (*i)[o] <= ' ') { ++o; --l; } @@ -53,7 +53,7 @@ String deprecatedParseURL(const String& url) l -= 5; } - while (o < l && (*i)[o] <= ' ') { + while (0 < l && (*i)[o] <= ' ') { ++o; --l; } @@ -65,7 +65,7 @@ String deprecatedParseURL(const String& url) l -= 2; } - while (o < l && (*i)[o] <= ' ') { + while (0 < l && (*i)[o] <= ' ') { ++o; --l; } diff --git a/WebCore/css/CSSMutableStyleDeclaration.cpp b/WebCore/css/CSSMutableStyleDeclaration.cpp index 31c7507..327f398 100644 --- a/WebCore/css/CSSMutableStyleDeclaration.cpp +++ b/WebCore/css/CSSMutableStyleDeclaration.cpp @@ -627,9 +627,9 @@ void CSSMutableStyleDeclaration::setLengthProperty(int propertyId, const String& setStrictParsing(parseMode); } -unsigned CSSMutableStyleDeclaration::length() const +unsigned CSSMutableStyleDeclaration::virtualLength() const { - return m_properties.size(); + return length(); } String CSSMutableStyleDeclaration::item(unsigned i) const diff --git a/WebCore/css/CSSMutableStyleDeclaration.h b/WebCore/css/CSSMutableStyleDeclaration.h index 5eb8a27..f7759f4 100644 --- a/WebCore/css/CSSMutableStyleDeclaration.h +++ b/WebCore/css/CSSMutableStyleDeclaration.h @@ -88,7 +88,9 @@ public: virtual String cssText() const; virtual void setCssText(const String&, ExceptionCode&); - virtual unsigned length() const; + virtual unsigned virtualLength() const; + unsigned length() const { return m_properties.size(); } + virtual String item(unsigned index) const; virtual PassRefPtr<CSSValue> getPropertyCSSValue(int propertyID) const; diff --git a/WebCore/css/CSSPageRule.cpp b/WebCore/css/CSSPageRule.cpp index 6a37963..c85c1aa 100644 --- a/WebCore/css/CSSPageRule.cpp +++ b/WebCore/css/CSSPageRule.cpp @@ -23,12 +23,16 @@ #include "CSSPageRule.h" #include "CSSMutableStyleDeclaration.h" +#include <wtf/Vector.h> namespace WebCore { -CSSPageRule::CSSPageRule(CSSStyleSheet* parent) - : CSSRule(parent) +CSSPageRule::CSSPageRule(CSSStyleSheet* parent, CSSSelector* selector, int sourceLine) + : CSSStyleRule(parent, sourceLine) { + Vector<CSSSelector*> selectors; + selectors.append(selector); + adoptSelectorVector(selectors); } CSSPageRule::~CSSPageRule() @@ -37,19 +41,14 @@ CSSPageRule::~CSSPageRule() String CSSPageRule::selectorText() const { - // FIXME: Implement! - return String(); -} - -void CSSPageRule::setSelectorText(const String& /*selectorText*/, ExceptionCode& /*ec*/) -{ - // FIXME: Implement! -} - -String CSSPageRule::cssText() const -{ - // FIXME: Implement! - return String(); + String text = "@page"; + CSSSelector* selector = selectorList().first(); + if (selector) { + String pageSpecification = selector->selectorText(); + if (!pageSpecification.isEmpty() && pageSpecification != starAtom) + text += " " + pageSpecification; + } + return text; } } // namespace WebCore diff --git a/WebCore/css/CSSPageRule.h b/WebCore/css/CSSPageRule.h index 8e374a5..bdfb751 100644 --- a/WebCore/css/CSSPageRule.h +++ b/WebCore/css/CSSPageRule.h @@ -22,37 +22,34 @@ #ifndef CSSPageRule_h #define CSSPageRule_h -#include "CSSRule.h" +#include "CSSStyleRule.h" #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> namespace WebCore { class CSSMutableStyleDeclaration; +class CSSSelector; +class CSSSelectorList; -class CSSPageRule : public CSSRule { +class CSSPageRule : public CSSStyleRule { public: - static PassRefPtr<CSSPageRule> create(CSSStyleSheet* parent) + static PassRefPtr<CSSPageRule> create(CSSStyleSheet* parent, CSSSelector* selector, int sourceLine) { - return adoptRef(new CSSPageRule(parent)); + return adoptRef(new CSSPageRule(parent, selector, sourceLine)); } virtual ~CSSPageRule(); - String selectorText() const; - void setSelectorText(const String&, ExceptionCode&); - - CSSMutableStyleDeclaration* style() const { return m_style.get(); } - - virtual String cssText() const; + virtual String selectorText() const; private: - CSSPageRule(CSSStyleSheet* parent); + CSSPageRule(CSSStyleSheet* parent, CSSSelector* selector, int sourceLine); + + virtual bool isPageRule() { return true; } // Inherited from CSSRule virtual unsigned short type() const { return PAGE_RULE; } - - RefPtr<CSSMutableStyleDeclaration> m_style; }; } // namespace WebCore diff --git a/WebCore/css/CSSParser.cpp b/WebCore/css/CSSParser.cpp index 466e741..8983eeb 100644 --- a/WebCore/css/CSSParser.cpp +++ b/WebCore/css/CSSParser.cpp @@ -40,6 +40,7 @@ #include "CSSInitialValue.h" #include "CSSMediaRule.h" #include "CSSMutableStyleDeclaration.h" +#include "CSSPageRule.h" #include "CSSPrimitiveValue.h" #include "CSSProperty.h" #include "CSSPropertyNames.h" @@ -69,6 +70,7 @@ #include "WebKitCSSKeyframeRule.h" #include "WebKitCSSKeyframesRule.h" #include "WebKitCSSTransformValue.h" +#include <limits.h> #include <wtf/dtoa.h> #if ENABLE(DASHBOARD_SUPPORT) @@ -95,6 +97,8 @@ using namespace WTF; namespace WebCore { +static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX; + static bool equal(const CSSParserString& a, const char* b) { for (int i = 0; i < a.length; ++i) { @@ -139,6 +143,7 @@ CSSParser::CSSParser(bool strictParsing) , m_parsedProperties(static_cast<CSSProperty**>(fastMalloc(32 * sizeof(CSSProperty*)))) , m_numParsedProperties(0) , m_maxParsedProperties(32) + , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES) , m_inParseShorthand(0) , m_currentShorthand(0) , m_implicitShorthand(false) @@ -448,6 +453,7 @@ void CSSParser::clearProperties() for (unsigned i = 0; i < m_numParsedProperties; i++) delete m_parsedProperties[i]; m_numParsedProperties = 0; + m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES; m_hasFontFaceOnlyValues = false; } @@ -638,7 +644,9 @@ bool CSSParser::parseValue(int propId, bool important) * (see parseAuralValues). As we don't support them at all this seems reasonable. */ - case CSSPropertySize: // <length>{1,2} | auto | portrait | landscape | inherit + case CSSPropertySize: // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ] + return parseSize(propId, important); + case CSSPropertyQuotes: // [<string> <string>]+ | none | inherit if (id) validPrimitive = true; @@ -1738,18 +1746,28 @@ bool CSSParser::parseValue(int propId, bool important) return parseTransitionShorthand(important); case CSSPropertyInvalid: return false; - case CSSPropertyFontStretch: case CSSPropertyPage: + return parsePage(propId, important); + case CSSPropertyFontStretch: case CSSPropertyTextLineThrough: case CSSPropertyTextOverline: case CSSPropertyTextUnderline: case CSSPropertyWebkitVariableDeclarationBlock: return false; +<<<<<<< HEAD:WebCore/css/CSSParser.cpp #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR case CSSPropertyWebkitTapHighlightColor: parsedValue = parseColor(); if (parsedValue) m_valueList->next(); +======= +#if ENABLE(WCSS) + case CSSPropertyWapInputFormat: + validPrimitive = true; + break; + case CSSPropertyWapInputRequired: + parsedValue = parseWCSSInputProperty(); +>>>>>>> webkit.org at r58956:WebCore/css/CSSParser.cpp break; #endif @@ -1781,6 +1799,27 @@ bool CSSParser::parseValue(int propId, bool important) return false; } +#if ENABLE(WCSS) +PassRefPtr<CSSValue> CSSParser::parseWCSSInputProperty() +{ + RefPtr<CSSValue> parsedValue = 0; + CSSParserValue* value = m_valueList->current(); + String inputProperty; + if (value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT) + inputProperty = String(value->string); + + if (!inputProperty.isEmpty()) + parsedValue = CSSPrimitiveValue::create(inputProperty, CSSPrimitiveValue::CSS_STRING); + + while (m_valueList->next()) { + // pass all other values, if any. If we don't do this, + // the parser will think that it's not done and won't process this property + } + + return parsedValue; +} +#endif + void CSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval) { if (lval) { @@ -2164,6 +2203,101 @@ bool CSSParser::parse4Values(int propId, const int *properties, bool important) return true; } +// auto | <identifier> +bool CSSParser::parsePage(int propId, bool important) +{ + ASSERT(propId == CSSPropertyPage); + + if (m_valueList->size() != 1) + return false; + + CSSParserValue* value = m_valueList->current(); + if (!value) + return false; + + if (value->id == CSSValueAuto) { + addProperty(propId, CSSPrimitiveValue::createIdentifier(value->id), important); + return true; + } else if (value->id == 0 && value->unit == CSSPrimitiveValue::CSS_IDENT) { + addProperty(propId, CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_STRING), important); + return true; + } + return false; +} + +// <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ] +bool CSSParser::parseSize(int propId, bool important) +{ + ASSERT(propId == CSSPropertySize); + + if (m_valueList->size() > 2) + return false; + + CSSParserValue* value = m_valueList->current(); + if (!value) + return false; + + RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated(); + + // First parameter. + SizeParameterType paramType = parseSizeParameter(parsedValues.get(), value, None); + if (paramType == None) + return false; + + // Second parameter, if any. + value = m_valueList->next(); + if (value) { + paramType = parseSizeParameter(parsedValues.get(), value, paramType); + if (paramType == None) + return false; + } + + addProperty(propId, parsedValues.release(), important); + return true; +} + +CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType) +{ + switch (value->id) { + case CSSValueAuto: + if (prevParamType == None) { + parsedValues->append(CSSPrimitiveValue::createIdentifier(value->id)); + return Auto; + } + return None; + case CSSValueLandscape: + case CSSValuePortrait: + if (prevParamType == None || prevParamType == PageSize) { + parsedValues->append(CSSPrimitiveValue::createIdentifier(value->id)); + return Orientation; + } + return None; + case CSSValueA3: + case CSSValueA4: + case CSSValueA5: + case CSSValueB4: + case CSSValueB5: + case CSSValueLedger: + case CSSValueLegal: + case CSSValueLetter: + if (prevParamType == None || prevParamType == Orientation) { + // Normalize to Page Size then Orientation order by prepending. + // This is not specified by the CSS3 Paged Media specification, but for simpler processing hereafter. + parsedValues->prepend(CSSPrimitiveValue::createIdentifier(value->id)); + return PageSize; + } + return None; + case 0: + if (validUnit(value, FLength, m_strict) && (prevParamType == None || prevParamType == Length)) { + parsedValues->append(CSSPrimitiveValue::create(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit))); + return Length; + } + return None; + default: + return None; + } +} + // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit // in CSS 2.1 this got somewhat reduced: // [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit @@ -5253,6 +5387,43 @@ bool CSSParser::addVariableDeclarationBlock(const CSSParserString&) #endif +CSSRule* CSSParser::createPageRule(CSSSelector* pageSelector) +{ + // FIXME: Margin at-rules are ignored. + m_allowImportRules = m_allowNamespaceDeclarations = m_allowVariablesRules = false; + CSSPageRule* pageRule = 0; + if (pageSelector) { + RefPtr<CSSPageRule> rule = CSSPageRule::create(m_styleSheet, pageSelector, m_lastSelectorLine); + rule->setDeclaration(CSSMutableStyleDeclaration::create(rule.get(), m_parsedProperties, m_numParsedProperties)); + pageRule = rule.get(); + m_parsedStyleObjects.append(rule.release()); + } + clearProperties(); + return pageRule; +} + +CSSRule* CSSParser::createMarginAtRule(CSSSelector::MarginBoxType /* marginBox */) +{ + // FIXME: Implement margin at-rule here, using: + // - marginBox: margin box + // - m_parsedProperties: properties at [m_numParsedPropertiesBeforeMarginBox, m_numParsedProperties) are for this at-rule. + + endDeclarationsForMarginBox(); + return 0; // until this method is implemented. +} + +void CSSParser::startDeclarationsForMarginBox() +{ + m_numParsedPropertiesBeforeMarginBox = m_numParsedProperties; +} + +void CSSParser::endDeclarationsForMarginBox() +{ + ASSERT(m_numParsedPropertiesBeforeMarginBox != INVALID_NUM_PARSED_PROPERTIES); + rollbackLastProperties(m_numParsedProperties - m_numParsedPropertiesBeforeMarginBox); + m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES; +} + void CSSParser::clearVariables() { m_variableNames.clear(); diff --git a/WebCore/css/CSSParser.h b/WebCore/css/CSSParser.h index ca8c66a..6e0354e 100644 --- a/WebCore/css/CSSParser.h +++ b/WebCore/css/CSSParser.h @@ -2,6 +2,7 @@ * Copyright (C) 2003 Lars Knoll (knoll@kde.org) * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. * Copyright (C) 2008 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 - 2010 Torch Mobile (Beijing) Co. Ltd. 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 @@ -139,6 +140,10 @@ namespace WebCore { PassRefPtr<CSSValue> parseSVGStrokeDasharray(); #endif +#if ENABLE(WCSS) + PassRefPtr<CSSValue> parseWCSSInputProperty(); +#endif + // CSS3 Parsing Routines (for properties specific to CSS3) bool parseShadow(int propId, bool important); bool parseBorderImage(int propId, bool important, RefPtr<CSSValue>&); @@ -179,6 +184,10 @@ namespace WebCore { CSSRule* createStyleRule(Vector<CSSSelector*>* selectors); CSSRule* createFontFaceRule(); CSSRule* createVariablesRule(MediaList*, bool variablesKeyword); + CSSRule* createPageRule(CSSSelector* pageSelector); + CSSRule* createMarginAtRule(CSSSelector::MarginBoxType marginBox); + void startDeclarationsForMarginBox(); + void endDeclarationsForMarginBox(); MediaQueryExp* createFloatingMediaQueryExp(const AtomicString&, CSSParserValueList*); MediaQueryExp* sinkFloatingMediaQueryExp(MediaQueryExp*); @@ -212,6 +221,7 @@ namespace WebCore { CSSSelectorList* m_selectorListForParseSelector; unsigned m_numParsedProperties; unsigned m_maxParsedProperties; + unsigned m_numParsedPropertiesBeforeMarginBox; int m_inParseShorthand; int m_currentShorthand; @@ -247,6 +257,18 @@ namespace WebCore { void deleteFontFaceOnlyValues(); + enum SizeParameterType { + None, + Auto, + Length, + PageSize, + Orientation, + }; + + bool parsePage(int propId, bool important); + bool parseSize(int propId, bool important); + SizeParameterType parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType); + UChar* m_data; UChar* yytext; UChar* yy_c_buf_p; diff --git a/WebCore/css/CSSPrimitiveValueMappings.h b/WebCore/css/CSSPrimitiveValueMappings.h index 223b515..d5876e7 100644 --- a/WebCore/css/CSSPrimitiveValueMappings.h +++ b/WebCore/css/CSSPrimitiveValueMappings.h @@ -276,10 +276,15 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ControlPart e) m_value.ident = CSSValueOuterSpinButton; break; case ProgressBarPart: -#if ENABLE(PROGRESS_BAR) +#if ENABLE(PROGRESS_TAG) m_value.ident = CSSValueProgressBar; #endif break; + case ProgressBarValuePart: +#if ENABLE(PROGRESS_TAG) + m_value.ident = CSSValueProgressBarValue; +#endif + break; case SliderHorizontalPart: m_value.ident = CSSValueSliderHorizontal; break; diff --git a/WebCore/css/CSSPropertyNames.in b/WebCore/css/CSSPropertyNames.in index aed7063..6ed923a 100644 --- a/WebCore/css/CSSPropertyNames.in +++ b/WebCore/css/CSSPropertyNames.in @@ -8,6 +8,24 @@ # http://msdn.microsoft.com/workshop/author/css/reference/attributes.asp # +# high-priority property names have to be listed first, to simplify the check +# for applying them first. +color +direction +display +font +font-family +font-size +font-style +font-variant +font-weight +-webkit-text-size-adjust +zoom + +# line height needs to be right after the above high-priority properties +line-height + +# The remaining properties are listed in alphabetical order background background-attachment background-clip @@ -52,26 +70,16 @@ bottom caption-side clear clip -color content counter-increment counter-reset cursor -direction -display empty-cells float -font -font-family -font-size font-stretch -font-style -font-variant -font-weight height left letter-spacing -line-height list-style list-style-image list-style-position @@ -146,7 +154,6 @@ word-break word-spacing word-wrap z-index -zoom -webkit-animation -webkit-animation-delay -webkit-animation-direction @@ -241,7 +248,6 @@ zoom -webkit-text-decorations-in-effect -webkit-text-fill-color -webkit-text-security --webkit-text-size-adjust -webkit-text-stroke -webkit-text-stroke-color -webkit-text-stroke-width diff --git a/WebCore/css/CSSSelector.cpp b/WebCore/css/CSSSelector.cpp index 23a89f6..ee9c846 100644 --- a/WebCore/css/CSSSelector.cpp +++ b/WebCore/css/CSSSelector.cpp @@ -143,6 +143,13 @@ PseudoId CSSSelector::pseudoId(PseudoType type) return INNER_SPIN_BUTTON; case PseudoOuterSpinButton: return OUTER_SPIN_BUTTON; + case PseudoProgressBarValue: +#if ENABLE(PROGRESS_TAG) + return PROGRESS_BAR_VALUE; +#else + ASSERT_NOT_REACHED(); + return NOPSEUDO; +#endif case PseudoInputListButton: #if ENABLE(DATALIST) return INPUT_LIST_BUTTON; @@ -196,6 +203,9 @@ PseudoId CSSSelector::pseudoId(PseudoType type) case PseudoDoubleButton: case PseudoSingleButton: case PseudoNoButton: + case PseudoFirstPage: + case PseudoLeftPage: + case PseudoRightPage: return NOPSEUDO; case PseudoNotParsed: ASSERT_NOT_REACHED(); @@ -267,8 +277,8 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap( DEFINE_STATIC_LOCAL(AtomicString, onlyOfType, ("only-of-type")); DEFINE_STATIC_LOCAL(AtomicString, optional, ("optional")); DEFINE_STATIC_LOCAL(AtomicString, outerSpinButton, ("-webkit-outer-spin-button")); -#if ENABLE(PROGRESS_BAR) - DEFINE_STATIC_LOCAL(AtomicString, progressBar, ("-webkit-progress-bar")); +#if ENABLE(PROGRESS_TAG) + DEFINE_STATIC_LOCAL(AtomicString, progressBarValue, ("-webkit-progress-bar-value")); #endif DEFINE_STATIC_LOCAL(AtomicString, required, ("required")); DEFINE_STATIC_LOCAL(AtomicString, resizer, ("-webkit-resizer")); @@ -298,6 +308,10 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap( DEFINE_STATIC_LOCAL(AtomicString, singleButton, ("single-button")); DEFINE_STATIC_LOCAL(AtomicString, noButton, ("no-button")); DEFINE_STATIC_LOCAL(AtomicString, cornerPresent, ("corner-present")); + // Paged Media pseudo-classes + DEFINE_STATIC_LOCAL(AtomicString, firstPage, ("first")); + DEFINE_STATIC_LOCAL(AtomicString, leftPage, ("left")); + DEFINE_STATIC_LOCAL(AtomicString, rightPage, ("right")); static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoType = 0; if (!nameToPseudoType) { @@ -360,6 +374,9 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap( nameToPseudoType->set(nthLastChild.impl(), CSSSelector::PseudoNthLastChild); nameToPseudoType->set(nthLastOfType.impl(), CSSSelector::PseudoNthLastOfType); nameToPseudoType->set(outerSpinButton.impl(), CSSSelector::PseudoOuterSpinButton); +#if ENABLE(PROGRESS_TAG) + nameToPseudoType->set(progressBarValue.impl(), CSSSelector::PseudoProgressBarValue); +#endif nameToPseudoType->set(root.impl(), CSSSelector::PseudoRoot); nameToPseudoType->set(windowInactive.impl(), CSSSelector::PseudoWindowInactive); nameToPseudoType->set(decrement.impl(), CSSSelector::PseudoDecrement); @@ -389,6 +406,9 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap( nameToPseudoType->set(sliderThumb.impl(), CSSSelector::PseudoSliderThumb); nameToPseudoType->set(target.impl(), CSSSelector::PseudoTarget); nameToPseudoType->set(visited.impl(), CSSSelector::PseudoVisited); + nameToPseudoType->set(firstPage.impl(), CSSSelector::PseudoFirstPage); + nameToPseudoType->set(leftPage.impl(), CSSSelector::PseudoLeftPage); + nameToPseudoType->set(rightPage.impl(), CSSSelector::PseudoRightPage); } return nameToPseudoType; } @@ -439,6 +459,7 @@ void CSSSelector::extractPseudoType() const case PseudoMediaControlsTimelineContainer: case PseudoMediaControlsVolumeSliderContainer: case PseudoOuterSpinButton: + case PseudoProgressBarValue: case PseudoResizer: case PseudoScrollbar: case PseudoScrollbarCorner: @@ -505,6 +526,12 @@ void CSSSelector::extractPseudoType() const case PseudoNoButton: case PseudoNotParsed: break; + case PseudoFirstPage: + case PseudoLeftPage: + case PseudoRightPage: + // FIXME: These should only be allowed in @page rules. Disabled them altogether until that's implemented correctly. + m_pseudoType = PseudoUnknown; + return; } if (m_match == PseudoClass && element) { @@ -749,7 +776,8 @@ bool CSSSelector::RareData::parseNth() m_b = argument.substring(p + 1, argument.length() - p - 1).toInt(); else { p = argument.find('-', n); - m_b = -argument.substring(p + 1, argument.length() - p - 1).toInt(); + if (p != -1) + m_b = -argument.substring(p + 1, argument.length() - p - 1).toInt(); } } else m_b = argument.toInt(); diff --git a/WebCore/css/CSSSelector.h b/WebCore/css/CSSSelector.h index f8748c7..8f84b05 100644 --- a/WebCore/css/CSSSelector.h +++ b/WebCore/css/CSSSelector.h @@ -187,6 +187,29 @@ namespace WebCore { PseudoInputListButton, PseudoInnerSpinButton, PseudoOuterSpinButton, + PseudoProgressBarValue, + PseudoLeftPage, + PseudoRightPage, + PseudoFirstPage, + }; + + enum MarginBoxType { + TopLeftCornerMarginBox, + TopLeftMarginBox, + TopCenterMarginBox, + TopRightMarginBox, + TopRightCornerMarginBox, + BottomLeftCornerMarginBox, + BottomLeftMarginBox, + BottomCenterMarginBox, + BottomRightMarginBox, + BottomRightCornerMarginBox, + LeftTopMarginBox, + LeftMiddleMarginBox, + LeftBottomMarginBox, + RightTopMarginBox, + RightMiddleMarginBox, + RightBottomMarginBox, }; PseudoType pseudoType() const diff --git a/WebCore/css/CSSStyleDeclaration.h b/WebCore/css/CSSStyleDeclaration.h index 18493df..08b3bf0 100644 --- a/WebCore/css/CSSStyleDeclaration.h +++ b/WebCore/css/CSSStyleDeclaration.h @@ -42,7 +42,8 @@ public: virtual String cssText() const = 0; virtual void setCssText(const String&, ExceptionCode&) = 0; - virtual unsigned length() const = 0; + unsigned length() const { return virtualLength(); } + virtual unsigned virtualLength() const = 0; bool isEmpty() const { return !length(); } virtual String item(unsigned index) const = 0; diff --git a/WebCore/css/CSSStyleRule.h b/WebCore/css/CSSStyleRule.h index 835f2a2..d797c73 100644 --- a/WebCore/css/CSSStyleRule.h +++ b/WebCore/css/CSSStyleRule.h @@ -40,7 +40,7 @@ public: } virtual ~CSSStyleRule(); - String selectorText() const; + virtual String selectorText() const; void setSelectorText(const String&, ExceptionCode&); CSSMutableStyleDeclaration* style() const { return m_style.get(); } @@ -60,9 +60,10 @@ public: int sourceLine() { return m_sourceLine; } -private: +protected: CSSStyleRule(CSSStyleSheet* parent, int sourceLine); +private: virtual bool isStyleRule() { return true; } // Inherited from CSSRule diff --git a/WebCore/css/CSSStyleSelector.cpp b/WebCore/css/CSSStyleSelector.cpp index dd4fed9..389bd11 100644 --- a/WebCore/css/CSSStyleSelector.cpp +++ b/WebCore/css/CSSStyleSelector.cpp @@ -31,6 +31,7 @@ #include "CSSFontFaceRule.h" #include "CSSImportRule.h" #include "CSSMediaRule.h" +#include "CSSPageRule.h" #include "CSSParser.h" #include "CSSPrimitiveValueMappings.h" #include "CSSPropertyNames.h" @@ -358,6 +359,7 @@ public: void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0); void addRule(CSSStyleRule* rule, CSSSelector* sel); + void addPageRule(CSSStyleRule* rule, CSSSelector* sel); void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, CSSStyleRule* rule, CSSSelector* sel); @@ -365,13 +367,16 @@ public: CSSRuleDataList* getClassRules(AtomicStringImpl* key) { return m_classRules.get(key); } CSSRuleDataList* getTagRules(AtomicStringImpl* key) { return m_tagRules.get(key); } CSSRuleDataList* getUniversalRules() { return m_universalRules; } + CSSRuleDataList* getPageRules() { return m_pageRules; } public: AtomRuleMap m_idRules; AtomRuleMap m_classRules; AtomRuleMap m_tagRules; CSSRuleDataList* m_universalRules; + CSSRuleDataList* m_pageRules; unsigned m_ruleCount; + unsigned m_pageRuleCount; }; static CSSRuleSet* defaultStyle; @@ -486,6 +491,7 @@ void CSSStyleSelector::addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule) void CSSStyleSelector::init() { m_element = 0; + m_haveCachedLinkState = false; m_matchedDecls.clear(); m_ruleList = 0; m_rootDefaultStyle = 0; @@ -696,9 +702,7 @@ void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules, int& firstRuleI 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 (checkSelector(d->selector())) { // If the rule has no properties to apply, then ignore it. CSSMutableStyleDeclaration* decl = rule->declaration(); if (!decl || !decl->length()) @@ -800,13 +804,16 @@ void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end) m_matchedRules[i] = rulesMergeBuffer[i - start]; } -void CSSStyleSelector::initElement(Element* e) +inline void CSSStyleSelector::initElement(Element* e, bool helperCallForVisitedStyle = false) { + if (!helperCallForVisitedStyle) + m_haveCachedLinkState = false; + m_element = e; m_styledElement = m_element && m_element->isStyledElement() ? static_cast<StyledElement*>(m_element) : 0; } -void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID) +inline void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID) { m_checker.m_pseudoStyle = pseudoID; @@ -874,10 +881,17 @@ CSSStyleSelector::SelectorChecker::SelectorChecker(Document* document, bool stri { } -EInsideLink CSSStyleSelector::SelectorChecker::determineLinkState(Element* element) const +inline EInsideLink CSSStyleSelector::SelectorChecker::determineLinkState(Element* element) const { if (!element->isLink()) return NotInsideLink; + return determineLinkStateSlowCase(element); +} + + +EInsideLink CSSStyleSelector::SelectorChecker::determineLinkStateSlowCase(Element* element) const +{ + ASSERT(element->isLink()); const AtomicString* attr = linkAttribute(element); if (!attr || attr->isNull()) @@ -1025,7 +1039,7 @@ bool CSSStyleSelector::canShareStyleWithElement(Node* n) mappedAttrsMatch = s->mappedAttributes()->mapsEquivalent(m_styledElement->mappedAttributes()); if (mappedAttrsMatch) { if (s->isLink()) { - if (m_checker.determineLinkState(m_element) != style->insideLink()) + if (currentElementLinkState() != style->insideLink()) return false; } return true; @@ -1036,7 +1050,7 @@ bool CSSStyleSelector::canShareStyleWithElement(Node* n) return false; } -RenderStyle* CSSStyleSelector::locateSharedStyle() +ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle() { if (m_styledElement && !m_styledElement->inlineStyleDecl() && !m_styledElement->hasID() && !m_styledElement->document()->usesSiblingRules()) { // Check previous siblings. @@ -1118,13 +1132,13 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForDocument(Document* document) // 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 -PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault, bool matchVisitedRules) +PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault, bool helperCallForVisitedStyle) { // 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 = RenderStyle::create().releaseRef(); s_styleNotYetAvailable->ref(); s_styleNotYetAvailable->setDisplay(NONE); s_styleNotYetAvailable->font().update(m_fontSelector); @@ -1134,7 +1148,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl return s_styleNotYetAvailable; } - initElement(e); + initElement(e, helperCallForVisitedStyle); if (allowSharing) { RenderStyle* sharedStyle = locateSharedStyle(); if (sharedStyle) @@ -1144,7 +1158,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl // Compute our style allowing :visited to match first. RefPtr<RenderStyle> visitedStyle; - if (!matchVisitedRules && m_parentStyle && (m_parentStyle->insideLink() || e->isLink()) && e->document()->usesLinkRules()) { + if (!helperCallForVisitedStyle && m_parentStyle && (m_parentStyle->insideLink() || e->isLink()) && e->document()->usesLinkRules()) { // Fetch our parent style. RenderStyle* parentStyle = m_parentStyle; if (!e->isLink()) { @@ -1158,7 +1172,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl initForStyleResolve(e, defaultParent); } - m_checker.m_matchVisitedPseudoClass = matchVisitedRules; + m_checker.m_matchVisitedPseudoClass = helperCallForVisitedStyle; m_style = RenderStyle::create(); @@ -1169,7 +1183,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl if (e->isLink()) { m_style->setIsLink(true); - m_style->setInsideLink(m_checker.determineLinkState(e)); + m_style->setInsideLink(currentElementLinkState()); } if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(e)) @@ -1284,19 +1298,19 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl } // Reset the value back before applying properties, so that -webkit-link knows what color to use. - m_checker.m_matchVisitedPseudoClass = matchVisitedRules; + m_checker.m_matchVisitedPseudoClass = helperCallForVisitedStyle; // 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); + applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1); if (!resolveForRootDefault) { - applyDeclarations(true, true, firstAuthorRule, lastAuthorRule); - applyDeclarations(true, true, firstUserRule, lastUserRule); + applyDeclarations<true>(true, firstAuthorRule, lastAuthorRule); + applyDeclarations<true>(true, firstUserRule, lastUserRule); } - applyDeclarations(true, true, firstUARule, lastUARule); + applyDeclarations<true>(true, firstUARule, lastUARule); // If our font got dirtied, go ahead and update it now. if (m_fontDirty) @@ -1307,18 +1321,18 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl applyProperty(CSSPropertyLineHeight, m_lineHeightValue); // Now do the normal priority UA properties. - applyDeclarations(false, false, firstUARule, lastUARule); + 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>(false, lastUARule + 1, m_matchedDecls.size() - 1); + applyDeclarations<false>(true, firstAuthorRule, lastAuthorRule); + applyDeclarations<false>(true, firstUserRule, lastUserRule); } - applyDeclarations(false, true, firstUARule, lastUARule); + 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. @@ -1382,7 +1396,7 @@ void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* // We don't need to bother with !important. Since there is only ever one // decl, there's nothing to override. So just add the first properties. - applyDeclarations(true, false, 0, m_matchedDecls.size() - 1); + applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1); // If our font got dirtied, go ahead and update it now. if (m_fontDirty) @@ -1393,7 +1407,7 @@ void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* applyProperty(CSSPropertyLineHeight, m_lineHeightValue); // Now do rest of the properties. - applyDeclarations(false, false, 0, m_matchedDecls.size() - 1); + applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1); // If our font got dirtied by one of the non-essential font props, // go ahead and update it a second time. @@ -1431,7 +1445,7 @@ void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* list.clear(); } -PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle, bool matchVisitedLinks) +PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle, bool helperCallForVisitedStyle) { if (!e) return 0; @@ -1439,7 +1453,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, // Compute our :visited style first, so that we know whether or not we'll need to create a normal style just to hang it // off of. RefPtr<RenderStyle> visitedStyle; - if (!matchVisitedLinks && parentStyle && parentStyle->insideLink()) { + if (!helperCallForVisitedStyle && parentStyle && parentStyle->insideLink()) { // Fetch our parent style with :visited in effect. RenderStyle* parentVisitedStyle = parentStyle->getCachedPseudoStyle(VISITED_LINK); visitedStyle = pseudoStyleForElement(pseudo, e, parentVisitedStyle ? parentVisitedStyle : parentStyle, true); @@ -1447,11 +1461,11 @@ PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, visitedStyle->setStyleType(VISITED_LINK); } - initElement(e); + initElement(e, helperCallForVisitedStyle); initForStyleResolve(e, parentStyle, pseudo); m_style = parentStyle; - m_checker.m_matchVisitedPseudoClass = matchVisitedLinks; + m_checker.m_matchVisitedPseudoClass = helperCallForVisitedStyle; // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking // those rules. @@ -1477,13 +1491,13 @@ PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, m_lineHeightValue = 0; // Reset the value back before applying properties, so that -webkit-link knows what color to use. - m_checker.m_matchVisitedPseudoClass = matchVisitedLinks; + m_checker.m_matchVisitedPseudoClass = helperCallForVisitedStyle; // 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); + 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) @@ -1494,15 +1508,15 @@ PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, applyProperty(CSSPropertyLineHeight, m_lineHeightValue); // Now do the normal priority properties. - applyDeclarations(false, false, firstUARule, lastUARule); + 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); + 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. @@ -2540,6 +2554,11 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme break; return true; } + case CSSSelector::PseudoLeftPage: + case CSSSelector::PseudoRightPage: + case CSSSelector::PseudoFirstPage: + // Page media related pseudo-classes are not handled yet. + return false; case CSSSelector::PseudoUnknown: case CSSSelector::PseudoNotParsed: default: @@ -2666,7 +2685,9 @@ CSSValue* CSSStyleSelector::resolveVariableDependentValue(CSSVariableDependentVa CSSRuleSet::CSSRuleSet() { m_universalRules = 0; + m_pageRules = 0; m_ruleCount = 0; + m_pageRuleCount = 0; } CSSRuleSet::~CSSRuleSet() @@ -2676,6 +2697,7 @@ CSSRuleSet::~CSSRuleSet() deleteAllValues(m_tagRules); delete m_universalRules; + delete m_pageRules; } @@ -2715,6 +2737,14 @@ void CSSRuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel) m_universalRules->append(m_ruleCount++, rule, sel); } +void CSSRuleSet::addPageRule(CSSStyleRule* rule, CSSSelector* sel) +{ + if (!m_pageRules) + m_pageRules = new CSSRuleDataList(m_pageRuleCount++, rule, sel); + else + m_pageRules->append(m_pageRuleCount++, rule, sel); +} + void CSSRuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector) { if (!sheet) @@ -2730,9 +2760,14 @@ void CSSRuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluat 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->selectorList().first(); s; s = CSSSelectorList::next(s)) - addRule(rule, s); + if (item->isPageRule()) { + CSSPageRule* pageRule = static_cast<CSSPageRule*>(item); + addPageRule(pageRule, pageRule->selectorList().first()); + } else { + CSSStyleRule* rule = static_cast<CSSStyleRule*>(item); + for (CSSSelector* s = rule->selectorList().first(); s; s = CSSSelectorList::next(s)) + addRule(rule, s); + } } else if (item->isImportRule()) { CSSImportRule* import = static_cast<CSSImportRule*>(item); @@ -2806,8 +2841,8 @@ static Length convertToLength(CSSPrimitiveValue* primitiveValue, RenderStyle* st return l; } -void CSSStyleSelector::applyDeclarations(bool applyFirst, bool isImportant, - int startIndex, int endIndex) +template <bool applyFirst> +void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int endIndex) { if (startIndex == -1) return; @@ -2817,35 +2852,26 @@ void CSSStyleSelector::applyDeclarations(bool applyFirst, bool isImportant, CSSMutableStyleDeclaration::const_iterator end = decl->end(); for (CSSMutableStyleDeclaration::const_iterator it = decl->begin(); 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 properties. - first = true; - break; - default: - first = false; - break; + int property = current.id(); + + if (applyFirst) { + COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property); + COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 10, CSS_zoom_is_end_of_first_prop_range); + COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom); + + // give special priority to font-xxx, color properties, etc + if (property <= CSSPropertyLineHeight) { + // we apply line-height later + if (property == CSSPropertyLineHeight) + m_lineHeightValue = current.value(); + else + applyProperty(current.id(), current.value()); + } + } else { + if (property > CSSPropertyLineHeight) + applyProperty(current.id(), current.value()); } - if (first == applyFirst) - applyProperty(current.id(), current.value()); } } } @@ -5294,6 +5320,7 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) case CSSPropertyWebkitTextStroke: case CSSPropertyWebkitVariableDeclarationBlock: return; +<<<<<<< HEAD:WebCore/css/CSSStyleSelector.cpp #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR case CSSPropertyWebkitTapHighlightColor: { HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor); @@ -5305,6 +5332,25 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) return; } #endif +======= +#if ENABLE(WCSS) + case CSSPropertyWapInputFormat: + if (primitiveValue && m_element->hasTagName(WebCore::inputTag)) { + String mask = primitiveValue->getStringValue(); + static_cast<HTMLInputElement*>(m_element)->setWapInputFormat(mask); + } + return; + + case CSSPropertyWapInputRequired: + if (primitiveValue && m_element->isFormControlElement()) { + HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(m_element); + bool required = primitiveValue->getStringValue() == "true"; + element->setRequired(required); + } + return; +#endif + +>>>>>>> webkit.org at r58956:WebCore/css/CSSStyleSelector.cpp #if ENABLE(SVG) default: // Try the SVG properties diff --git a/WebCore/css/CSSStyleSelector.h b/WebCore/css/CSSStyleSelector.h index 80a186b..5089686 100644 --- a/WebCore/css/CSSStyleSelector.h +++ b/WebCore/css/CSSStyleSelector.h @@ -35,6 +35,7 @@ namespace WebCore { class CSSMutableStyleDeclaration; +class CSSPageRule; class CSSPrimitiveValue; class CSSProperty; class CSSFontFace; @@ -85,12 +86,11 @@ public: bool strictParsing, bool matchAuthorAndUserStyles); ~CSSStyleSelector(); - void initElement(Element*); void initForStyleResolve(Element*, RenderStyle* parentStyle = 0, PseudoId = NOPSEUDO); - PassRefPtr<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle = 0, bool allowSharing = true, bool resolveForRootDefault = false, bool matchVisitedLinks = false); + PassRefPtr<RenderStyle> styleForElement(Element* e, RenderStyle* parentStyle = 0, bool allowSharing = true, bool resolveForRootDefault = false) { return styleForElement(e, parentStyle, allowSharing, resolveForRootDefault, false); } void keyframeStylesForAnimation(Element*, const RenderStyle*, KeyframeList& list); - PassRefPtr<RenderStyle> pseudoStyleForElement(PseudoId, Element*, RenderStyle* parentStyle = 0, bool matchVisitedLinks = false); + PassRefPtr<RenderStyle> pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle = 0) { return pseudoStyleForElement(pseudo, e, parentStyle, false); } static PassRefPtr<RenderStyle> styleForDocument(Document*); @@ -101,6 +101,9 @@ public: #endif private: + PassRefPtr<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle, bool allowSharing, bool resolveForRootDefault, bool helperCallForVisitedStyle); + PassRefPtr<RenderStyle> pseudoStyleForElement(PseudoId, Element*, RenderStyle*, bool helperCallForVisitedStyle); + void initElement(Element*, bool); RenderStyle* locateSharedStyle(); Node* locateCousinList(Element* parent, unsigned depth = 1); bool canShareStyleWithElement(Node*); @@ -155,6 +158,7 @@ public: void resolveVariablesForDeclaration(CSSMutableStyleDeclaration* decl, CSSMutableStyleDeclaration* newDecl, HashSet<String>& usedBlockVariables); void addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule); + void addPageStyle(PassRefPtr<CSSPageRule>); static bool createTransformOperations(CSSValue* inValue, RenderStyle* inStyle, RenderStyle* rootStyle, TransformOperations& outOperations); @@ -175,7 +179,8 @@ public: void matchRulesForList(CSSRuleDataList*, int& firstRuleIndex, int& lastRuleIndex); void sortMatchedRules(unsigned start, unsigned end); - void applyDeclarations(bool firstPass, bool important, int startIndex, int endIndex); + template <bool firstPass> + void applyDeclarations(bool important, int startIndex, int endIndex); CSSRuleSet* m_authorStyle; CSSRuleSet* m_userStyle; @@ -201,6 +206,7 @@ public: bool checkScrollbarPseudoClass(CSSSelector*, PseudoId& dynamicPseudo) const; EInsideLink determineLinkState(Element* element) const; + EInsideLink determineLinkStateSlowCase(Element* element) const; void allVisitedStateChanged(); void visitedStateChanged(LinkHash visitedHash); @@ -252,6 +258,19 @@ public: StyleImage* styleImage(CSSValue* value); + + EInsideLink currentElementLinkState() const + { + if (!m_haveCachedLinkState) { + m_cachedLinkState = m_checker.determineLinkState(m_element); + m_haveCachedLinkState = true; + } + return m_cachedLinkState; + } + + mutable EInsideLink m_cachedLinkState; + mutable bool m_haveCachedLinkState; + // We collect the set of decls that match in |m_matchedDecls|. We then walk the // set of matched decls four times, once for those properties that others depend on (like font-size), // and then a second time for all the remaining properties. We then do the same two passes @@ -347,7 +366,7 @@ public: CSSRuleData* m_first; CSSRuleData* m_last; }; - + } // namespace WebCore #endif // CSSStyleSelector_h diff --git a/WebCore/css/CSSStyleSheet.cpp b/WebCore/css/CSSStyleSheet.cpp index fb25374..5949f96 100644 --- a/WebCore/css/CSSStyleSheet.cpp +++ b/WebCore/css/CSSStyleSheet.cpp @@ -28,7 +28,9 @@ #include "Document.h" #include "ExceptionCode.h" #include "Node.h" +#include "Page.h" #include "SecurityOrigin.h" +#include "Settings.h" #include "TextEncoding.h" #include <wtf/Deque.h> @@ -137,8 +139,23 @@ int CSSStyleSheet::addRule(const String& selector, const String& style, Exceptio PassRefPtr<CSSRuleList> CSSStyleSheet::cssRules(bool omitCharsetRules) { - if (doc() && !doc()->securityOrigin()->canRequest(baseURL())) - return 0; + if (doc() && !doc()->securityOrigin()->canRequest(baseURL())) { + + // The Safari welcome page runs afoul of the same-origin restriction on access to stylesheet rules + // that was added to address <https://bugs.webkit.org/show_bug.cgi?id=20527>. The following site- + // specific quirk relaxes this restriction for the particular cross-origin access that occurs on + // the Safari welcome page (<rdar://problem/7847573>). + + Settings* settings = doc()->settings(); + if (!settings || !settings->needsSiteSpecificQuirks()) + return 0; + + if (!equalIgnoringCase(baseURL().string(), "http://images.apple.com/safari/welcome/styles/safari.css")) + return 0; + + if (!doc()->url().string().contains("apple.com/safari/welcome/", false)) + return 0; + } return CSSRuleList::create(this, omitCharsetRules); } diff --git a/WebCore/css/CSSValueKeywords.in b/WebCore/css/CSSValueKeywords.in index 09d969a..06d966c 100644 --- a/WebCore/css/CSSValueKeywords.in +++ b/WebCore/css/CSSValueKeywords.in @@ -380,10 +380,15 @@ collapse # # Unordered rest # +a3 +a4 +a5 above absolute always avoid +b4 +b5 below bidi-override blink @@ -398,6 +403,9 @@ hide higher invert landscape +ledger +legal +letter level line-through local @@ -583,6 +591,7 @@ menulist-text menulist-textfield outer-spin-button progress-bar +progress-bar-value slider-horizontal slider-vertical sliderthumb-horizontal @@ -711,7 +720,8 @@ geometricPrecision sRGB # (-webkit-view-mode:) media feature: -mini floating -application fullscreen +maximized +minimized +windowed diff --git a/WebCore/css/MediaQueryEvaluator.cpp b/WebCore/css/MediaQueryEvaluator.cpp index ded40b5..20c7bb9 100644 --- a/WebCore/css/MediaQueryEvaluator.cpp +++ b/WebCore/css/MediaQueryEvaluator.cpp @@ -533,6 +533,9 @@ bool MediaQueryEvaluator::eval(const MediaQueryExp* expr) const if (!m_frame || !m_style) return m_expResult; + if (!expr->isValid()) + return false; + if (!gFunctionMap) createFunctionMap(); diff --git a/WebCore/css/MediaQueryExp.cpp b/WebCore/css/MediaQueryExp.cpp index 7ba6d84..53c0b73 100644 --- a/WebCore/css/MediaQueryExp.cpp +++ b/WebCore/css/MediaQueryExp.cpp @@ -37,6 +37,7 @@ namespace WebCore { MediaQueryExp::MediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* valueList) : m_mediaFeature(mediaFeature) , m_value(0) + , m_isValid(true) { if (valueList) { if (valueList->size() == 1) { @@ -73,6 +74,7 @@ MediaQueryExp::MediaQueryExp(const AtomicString& mediaFeature, CSSParserValueLis if (isValid) m_value = list.release(); } + m_isValid = m_value; } } diff --git a/WebCore/css/MediaQueryExp.h b/WebCore/css/MediaQueryExp.h index fd55cf6..9272402 100644 --- a/WebCore/css/MediaQueryExp.h +++ b/WebCore/css/MediaQueryExp.h @@ -52,6 +52,8 @@ public: || (other.m_value && m_value && other.m_value->cssText() == m_value->cssText())); } + bool isValid() const { return m_isValid; } + bool isViewportDependent() const { return m_mediaFeature == MediaFeatureNames::widthMediaFeature || m_mediaFeature == MediaFeatureNames::heightMediaFeature || m_mediaFeature == MediaFeatureNames::min_widthMediaFeature || @@ -65,6 +67,7 @@ public: private: AtomicString m_mediaFeature; RefPtr<CSSValue> m_value; + bool m_isValid; }; } // namespace diff --git a/WebCore/css/StyleBase.h b/WebCore/css/StyleBase.h index 5f9124d..521ee5d 100644 --- a/WebCore/css/StyleBase.h +++ b/WebCore/css/StyleBase.h @@ -54,6 +54,7 @@ namespace WebCore { virtual bool isKeyframesRule() { return false; } virtual bool isMediaRule() { return false; } virtual bool isVariablesRule() { return false; } + virtual bool isPageRule() { return false; } virtual bool isRule() { return false; } virtual bool isStyleRule() { return false; } diff --git a/WebCore/css/Media.cpp b/WebCore/css/StyleMedia.cpp index e238602..6cb662f 100644 --- a/WebCore/css/Media.cpp +++ b/WebCore/css/StyleMedia.cpp @@ -24,8 +24,8 @@ */ #include "config.h" +#include "StyleMedia.h" -#include "Media.h" #include "CSSStyleSelector.h" #include "Frame.h" #include "FrameView.h" @@ -34,12 +34,12 @@ namespace WebCore { -Media::Media(Frame* frame) +StyleMedia::StyleMedia(Frame* frame) : m_frame(frame) { } -String Media::type() const +String StyleMedia::type() const { FrameView* view = m_frame ? m_frame->view() : 0; if (view) @@ -48,7 +48,7 @@ String Media::type() const return String(); } -bool Media::matchMedium(const String& query) const +bool StyleMedia::matchMedium(const String& query) const { if (!m_frame) return false; diff --git a/WebCore/css/Media.h b/WebCore/css/StyleMedia.h index ee6961b..761e6a3 100644 --- a/WebCore/css/Media.h +++ b/WebCore/css/StyleMedia.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,18 +24,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Media_h -#define Media_h +#ifndef StyleMedia_h +#define StyleMedia_h #include "DOMWindow.h" namespace WebCore { -class Media : public RefCounted<Media> { +class StyleMedia : public RefCounted<StyleMedia> { public: - static PassRefPtr<Media> create(Frame* frame) + static PassRefPtr<StyleMedia> create(Frame* frame) { - return adoptRef(new Media(frame)); + return adoptRef(new StyleMedia(frame)); } void disconnectFrame() { m_frame = 0; } @@ -42,13 +43,13 @@ public: String type() const; bool matchMedium(const String&) const; - + private: - Media(Frame*); + StyleMedia(Frame*); Frame* m_frame; }; } // namespace -#endif // Media_h +#endif // StyleMedia_h diff --git a/WebCore/css/Media.idl b/WebCore/css/StyleMedia.idl index 1bf5900..7be35cc 100644 --- a/WebCore/css/Media.idl +++ b/WebCore/css/StyleMedia.idl @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,7 +25,7 @@ */ module view { - interface Media { + interface StyleMedia { readonly attribute DOMString type; boolean matchMedium(in DOMString mediaquery); }; diff --git a/WebCore/css/WCSSPropertyNames.in b/WebCore/css/WCSSPropertyNames.in index 704209f..66be83b 100644 --- a/WebCore/css/WCSSPropertyNames.in +++ b/WebCore/css/WCSSPropertyNames.in @@ -1,3 +1,5 @@ +-wap-input-format +-wap-input-required -wap-marquee-dir -wap-marquee-loop -wap-marquee-speed diff --git a/WebCore/css/WebKitCSSMatrix.cpp b/WebCore/css/WebKitCSSMatrix.cpp index aaf5c3d..3714760 100644 --- a/WebCore/css/WebKitCSSMatrix.cpp +++ b/WebCore/css/WebKitCSSMatrix.cpp @@ -93,14 +93,14 @@ void WebKitCSSMatrix::setMatrixValue(const String& string, ExceptionCode& ec) ec = SYNTAX_ERR; } -// This is a multRight (this = this * secondMatrix) +// Perform a concatenation of the matrices (this * secondMatrix) PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::multiply(WebKitCSSMatrix* secondMatrix) const { if (!secondMatrix) return 0; - TransformationMatrix tmp(m_matrix); - tmp.multiply(secondMatrix->m_matrix); + TransformationMatrix tmp(secondMatrix->m_matrix); + tmp.multiply(m_matrix); return WebKitCSSMatrix::create(tmp); } diff --git a/WebCore/css/html.css b/WebCore/css/html.css index 3f7818e..01103f4 100644 --- a/WebCore/css/html.css +++ b/WebCore/css/html.css @@ -362,12 +362,14 @@ input::-webkit-input-list-button { input::-webkit-inner-spin-button { -webkit-appearance: inner-spin-button; display: inline-block; + -webkit-user-select: none; } input::-webkit-outer-spin-button { -webkit-appearance: outer-spin-button; display: inline-block; margin-left: 2px; + -webkit-user-select: none; } textarea { diff --git a/WebCore/css/mathml.css b/WebCore/css/mathml.css index 8b4da3e..5c9038a 100644 --- a/WebCore/css/mathml.css +++ b/WebCore/css/mathml.css @@ -132,14 +132,23 @@ msqrt { mroot { display: inline-block; + position: relative; padding-top: 0.2em; padding-left: 0.2em; } mroot > * + * { font-size: 0.75em; - vertical-align: top; - padding-right: 0.3em; + vertical-align: bottom; + position: absolute; + left: 0px; + padding-right: 0.4em; + padding-left: 0.2em; + padding-bottom: 0.2em; +} + +mroot > * + mrow, mroot > * + mfenced { + padding-bottom: 0.4em; } mtable { diff --git a/WebCore/css/tokenizer.flex b/WebCore/css/tokenizer.flex index 3af725c..290c590 100644 --- a/WebCore/css/tokenizer.flex +++ b/WebCore/css/tokenizer.flex @@ -53,6 +53,22 @@ nth [\+-]?{intnum}*n([\+-]{intnum})? "@import" {BEGIN(mediaquery); yyTok = IMPORT_SYM; return yyTok;} "@page" {yyTok = PAGE_SYM; return yyTok;} +"@top-left-corner" {yyTok = TOPLEFTCORNER_SYM; return yyTok;} +"@top-left" {yyTok = TOPLEFT_SYM; return yyTok;} +"@top-center" {yyTok = TOPCENTER_SYM; return yyTok;} +"@top-right" {yyTok = TOPRIGHT_SYM; return yyTok;} +"@top-right-corner" {yyTok = TOPRIGHTCORNER_SYM; return yyTok;} +"@bottom-left-corner" {yyTok = BOTTOMLEFTCORNER_SYM; return yyTok;} +"@bottom-left" {yyTok = BOTTOMLEFT_SYM; return yyTok;} +"@bottom-center" {yyTok = BOTTOMCENTER_SYM; return yyTok;} +"@bottom-right" {yyTok = BOTTOMRIGHT_SYM; return yyTok;} +"@bottom-right-corner" {yyTok = BOTTOMRIGHTCORNER_SYM; return yyTok;} +"@left-top" {yyTok = LEFTTOP_SYM; return yyTok;} +"@left-middle" {yyTok = LEFTMIDDLE_SYM; return yyTok;} +"@left-bottom" {yyTok = LEFTBOTTOM_SYM; return yyTok;} +"@right-top" {yyTok = RIGHTTOP_SYM; return yyTok;} +"@right-middle" {yyTok = RIGHTMIDDLE_SYM; return yyTok;} +"@right-bottom" {yyTok = RIGHTBOTTOM_SYM; return yyTok;} "@media" {BEGIN(mediaquery); yyTok = MEDIA_SYM; return yyTok;} "@font-face" {yyTok = FONT_FACE_SYM; return yyTok;} "@charset" {yyTok = CHARSET_SYM; return yyTok;} diff --git a/WebCore/dom/CharacterData.cpp b/WebCore/dom/CharacterData.cpp index f5adb6c..9670988 100644 --- a/WebCore/dom/CharacterData.cpp +++ b/WebCore/dom/CharacterData.cpp @@ -29,13 +29,6 @@ namespace WebCore { -CharacterData::CharacterData(Document* document, const String& text, ConstructionType type) - : Node(document, type) - , m_data(text.impl() ? text.impl() : StringImpl::empty()) -{ - ASSERT(type == CreateOther || type == CreateText); -} - void CharacterData::setData(const String& data, ExceptionCode&) { StringImpl* dataImpl = data.impl() ? data.impl() : StringImpl::empty(); diff --git a/WebCore/dom/CharacterData.h b/WebCore/dom/CharacterData.h index 6c31933..5ca4b75 100644 --- a/WebCore/dom/CharacterData.h +++ b/WebCore/dom/CharacterData.h @@ -43,7 +43,12 @@ public: StringImpl* dataImpl() { return m_data.get(); } protected: - CharacterData(Document*, const String&, ConstructionType); + CharacterData(Document* document, const String& text, ConstructionType type) + : Node(document, type) + , m_data(text.impl() ? text.impl() : StringImpl::empty()) + { + ASSERT(type == CreateComment || type == CreateText); + } virtual bool rendererIsNeeded(RenderStyle*); diff --git a/WebCore/dom/ClassNodeList.cpp b/WebCore/dom/ClassNodeList.cpp index a7aefba..d482359 100644 --- a/WebCore/dom/ClassNodeList.cpp +++ b/WebCore/dom/ClassNodeList.cpp @@ -35,12 +35,18 @@ namespace WebCore { -ClassNodeList::ClassNodeList(PassRefPtr<Node> rootNode, const String& classNames, DynamicNodeList::Caches* caches) - : DynamicNodeList(rootNode, caches) +ClassNodeList::ClassNodeList(PassRefPtr<Node> rootNode, const String& classNames) + : DynamicNodeList(rootNode) , m_classNames(classNames, m_rootNode->document()->inCompatMode()) + , m_originalClassNames(classNames) { } +ClassNodeList::~ClassNodeList() +{ + m_rootNode->removeCachedClassNodeList(this, m_originalClassNames); +} + bool ClassNodeList::nodeMatches(Element* testNode) const { if (!testNode->hasClass()) diff --git a/WebCore/dom/ClassNodeList.h b/WebCore/dom/ClassNodeList.h index c519b3e..ea048a2 100644 --- a/WebCore/dom/ClassNodeList.h +++ b/WebCore/dom/ClassNodeList.h @@ -37,17 +37,20 @@ namespace WebCore { class ClassNodeList : public DynamicNodeList { public: - static PassRefPtr<ClassNodeList> create(PassRefPtr<Node> rootNode, const String& classNames, Caches* caches) + static PassRefPtr<ClassNodeList> create(PassRefPtr<Node> rootNode, const String& classNames) { - return adoptRef(new ClassNodeList(rootNode, classNames, caches)); + return adoptRef(new ClassNodeList(rootNode, classNames)); } + virtual ~ClassNodeList(); + private: - ClassNodeList(PassRefPtr<Node> rootNode, const String& classNames, Caches*); + ClassNodeList(PassRefPtr<Node> rootNode, const String& classNames); virtual bool nodeMatches(Element*) const; SpaceSplitString m_classNames; + String m_originalClassNames; }; } // namespace WebCore diff --git a/WebCore/dom/Comment.cpp b/WebCore/dom/Comment.cpp index 3dcde38..00f1724 100644 --- a/WebCore/dom/Comment.cpp +++ b/WebCore/dom/Comment.cpp @@ -22,10 +22,12 @@ #include "config.h" #include "Comment.h" +#include "Document.h" + namespace WebCore { inline Comment::Comment(Document* document, const String& text) - : CharacterData(document, text, CreateOther) + : CharacterData(document, text, CreateComment) { } diff --git a/WebCore/dom/Comment.h b/WebCore/dom/Comment.h index 680ffae..a0210c4 100644 --- a/WebCore/dom/Comment.h +++ b/WebCore/dom/Comment.h @@ -37,7 +37,6 @@ private: virtual String nodeName() const; virtual NodeType nodeType() const; virtual PassRefPtr<Node> cloneNode(bool deep); - virtual bool isCommentNode() const { return true; } virtual bool childTypeAllowed(NodeType); }; diff --git a/WebCore/dom/ContainerNode.cpp b/WebCore/dom/ContainerNode.cpp index f42b9cf..b063998 100644 --- a/WebCore/dom/ContainerNode.cpp +++ b/WebCore/dom/ContainerNode.cpp @@ -616,7 +616,7 @@ void ContainerNode::detach() { for (Node* child = m_firstChild; child; child = child->nextSibling()) child->detach(); - setChildNeedsStyleRecalc(false); + clearChildNeedsStyleRecalc(); Node::detach(); } @@ -633,7 +633,7 @@ void ContainerNode::removedFromDocument() Node::removedFromDocument(); if (document()->cssTarget() == this) document()->setCSSTarget(0); - setInDocument(false); + clearInDocument(); removedFromTree(false); for (Node* child = m_firstChild; child; child = child->nextSibling()) child->removedFromDocument(); diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp index ffbfd24..c6920bf 100644 --- a/WebCore/dom/Document.cpp +++ b/WebCore/dom/Document.cpp @@ -78,6 +78,7 @@ #include "HTMLParser.h" #include "HTMLStyleElement.h" #include "HTMLTitleElement.h" +#include "HTMLTokenizer.h" #include "HTTPParsers.h" #include "HistoryItem.h" #include "HitTestRequest.h" @@ -191,6 +192,9 @@ #endif #if ENABLE(TOUCH_EVENTS) +#if USE(V8) +#include "RuntimeEnabledFeatures.h" +#endif #include "TouchEvent.h" #endif @@ -219,6 +223,29 @@ namespace WebCore { using namespace HTMLNames; +class SynchronousHTMLTokenizerGuard { +public: + SynchronousHTMLTokenizerGuard(Tokenizer* tokenizer) + : m_htmlTokenizer(tokenizer->asHTMLTokenizer()) + , m_savedForceSynchronous(false) + { + if (m_htmlTokenizer) { + m_savedForceSynchronous = m_htmlTokenizer->forceSynchronous(); + m_htmlTokenizer->setForceSynchronous(true); + } + } + + ~SynchronousHTMLTokenizerGuard() + { + if (m_htmlTokenizer) + m_htmlTokenizer->setForceSynchronous(m_savedForceSynchronous); + } + +private: + HTMLTokenizer* m_htmlTokenizer; + bool m_savedForceSynchronous; +}; + // #define INSTRUMENT_LAYOUT_SCHEDULING 1 // This amount of time must have elapsed before we will even consider scheduling a layout without a delay. @@ -439,7 +466,7 @@ Document::Document(Frame* frame, bool isXHTML, bool isHTML) m_textColor = Color::black; m_listenerTypes = 0; - m_inDocument = true; + setInDocument(); m_inStyleRecalc = false; m_closeAfterStyleRecalc = false; @@ -1421,7 +1448,7 @@ void Document::recalcStyle(StyleChange change) bail_out: setNeedsStyleRecalc(NoStyleChange); - setChildNeedsStyleRecalc(false); + clearChildNeedsStyleRecalc(); unscheduleStyleRecalc(); if (view()) @@ -1997,8 +2024,11 @@ void Document::write(const SegmentedString& text, Document* ownerDocument) if (!m_tokenizer) open(ownerDocument); - ASSERT(m_tokenizer); - m_tokenizer->write(text, false); + { + ASSERT(m_tokenizer); + SynchronousHTMLTokenizerGuard tokenizerGuard(m_tokenizer.get()); + m_tokenizer->write(text, false); + } #ifdef INSTRUMENT_LAYOUT_SCHEDULING if (!ownerElement()) @@ -2891,7 +2921,7 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) m_focusedNode = 0; // Remove focus from the existing focus node (if any) - if (oldFocusedNode && !oldFocusedNode->m_inDetach) { + if (oldFocusedNode && !oldFocusedNode->inDetach()) { if (oldFocusedNode->active()) oldFocusedNode->setActive(false); @@ -2927,6 +2957,14 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) if (oldFocusedNode == oldFocusedNode->rootEditableElement()) frame()->editor()->didEndEditing(); + + if (view()) { + Widget* oldWidget = widgetForNode(oldFocusedNode.get()); + if (oldWidget) + oldWidget->setFocus(false); + else + view()->setFocus(false); + } } if (newFocusedNode) { @@ -2954,7 +2992,7 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) focusChangeBlocked = true; goto SetFocusedNodeDone; } - m_focusedNode->setFocus(); + m_focusedNode->setFocus(true); if (m_focusedNode == m_focusedNode->rootEditableElement()) frame()->editor()->didBeginEditing(); @@ -2972,9 +3010,9 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) focusWidget = widgetForNode(m_focusedNode.get()); } if (focusWidget) - focusWidget->setFocus(); + focusWidget->setFocus(true); else - view()->setFocus(); + view()->setFocus(true); } } @@ -3212,7 +3250,11 @@ PassRefPtr<Event> Document::createEvent(const String& eventType, ExceptionCode& event = SVGZoomEvent::create(); #endif #if ENABLE(TOUCH_EVENTS) +#if USE(V8) + else if (eventType == "TouchEvent" && RuntimeEnabledFeatures::touchEnabled()) +#else else if (eventType == "TouchEvent") +#endif event = TouchEvent::create(); #endif if (event) @@ -4543,6 +4585,8 @@ void Document::setIconURL(const String& iconURL, const String& type) m_iconURL = iconURL; else if (!type.isEmpty()) m_iconURL = iconURL; + if (Frame* f = frame()) + f->loader()->setIconURL(m_iconURL); } void Document::setUseSecureKeyboardEntryWhenActive(bool usesSecureKeyboard) @@ -4900,10 +4944,9 @@ void Document::enqueuePageshowEvent(PageshowEventPersistence persisted) void Document::enqueueHashchangeEvent(const String& /*oldURL*/, const String& /*newURL*/) { - // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36201 Hashchange event needs to fire asynchronously. // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36335 Hashchange event is now its own interface and takes two // URL arguments which we need to pass in here. - dispatchWindowEvent(Event::create(eventNames().hashchangeEvent, false, false)); + enqueueEvent(Event::create(eventNames().hashchangeEvent, false, false)); } void Document::enqueuePopstateEvent(PassRefPtr<SerializedScriptValue> stateObject) @@ -4921,7 +4964,7 @@ bool Document::isXHTMLMPDocument() const // MUST accept XHTMLMP document identified as "application/vnd.wap.xhtml+xml" // and SHOULD accept it identified as "application/xhtml+xml" , "application/xhtml+xml" is a // general MIME type for all XHTML documents, not only for XHTMLMP - return frame()->loader()->responseMIMEType() == "application/vnd.wap.xhtml+xml"; + return frame()->loader()->writer()->mimeType() == "application/vnd.wap.xhtml+xml"; } #endif diff --git a/WebCore/dom/Document.h b/WebCore/dom/Document.h index 6ac1f01..45031c3 100644 --- a/WebCore/dom/Document.h +++ b/WebCore/dom/Document.h @@ -958,6 +958,7 @@ public: #endif virtual bool isContextThread() const; + virtual bool isJSExecutionTerminated() const { return false; } void setUsingGeolocation(bool f) { m_usingGeolocation = f; } bool usingGeolocation() const { return m_usingGeolocation; }; @@ -1264,6 +1265,22 @@ inline bool Node::isDocumentNode() const return this == m_document; } +// here because it uses a Document method but we really want to inline it +inline Node::Node(Document* document, ConstructionType type) + : TreeShared<Node>(initialRefCount(type)) + , m_document(document) + , m_previous(0) + , m_next(0) + , m_renderer(0) + , m_nodeFlags(type) +{ + if (m_document) + m_document->selfOnlyRef(); +#if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS) + trackForDebugging(); +#endif +} + } // namespace WebCore #endif // Document_h diff --git a/WebCore/dom/Document.idl b/WebCore/dom/Document.idl index 88bd639..cd877b3 100644 --- a/WebCore/dom/Document.idl +++ b/WebCore/dom/Document.idl @@ -306,10 +306,10 @@ module core { attribute [DontEnum] EventListener onreset; attribute [DontEnum] EventListener onsearch; attribute [DontEnum] EventListener onselectstart; - attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchstart; - attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchmove; - attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchend; - attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchcancel; + attribute [DontEnum,Conditional=TOUCH_EVENTS,EnabledAtRuntime] EventListener ontouchstart; + attribute [DontEnum,Conditional=TOUCH_EVENTS,EnabledAtRuntime] EventListener ontouchmove; + attribute [DontEnum,Conditional=TOUCH_EVENTS,EnabledAtRuntime] EventListener ontouchend; + attribute [DontEnum,Conditional=TOUCH_EVENTS,EnabledAtRuntime] EventListener ontouchcancel; #endif }; diff --git a/WebCore/dom/DocumentFragment.cpp b/WebCore/dom/DocumentFragment.cpp index 3663e99..f7df8f6 100644 --- a/WebCore/dom/DocumentFragment.cpp +++ b/WebCore/dom/DocumentFragment.cpp @@ -23,6 +23,8 @@ #include "config.h" #include "DocumentFragment.h" +#include "Document.h" + namespace WebCore { inline DocumentFragment::DocumentFragment(Document* document) diff --git a/WebCore/dom/EditingText.cpp b/WebCore/dom/EditingText.cpp index b36931a..e412ad6 100644 --- a/WebCore/dom/EditingText.cpp +++ b/WebCore/dom/EditingText.cpp @@ -20,6 +20,8 @@ #include "config.h" #include "EditingText.h" +#include "Document.h" + // FIXME: Does this really require a class? Perhaps instead any text node // inside an editable element could have the "always create a renderer" behavior. diff --git a/WebCore/dom/Element.cpp b/WebCore/dom/Element.cpp index 3363e95..171a869 100644 --- a/WebCore/dom/Element.cpp +++ b/WebCore/dom/Element.cpp @@ -64,12 +64,6 @@ namespace WebCore { using namespace HTMLNames; using namespace XMLNames; -Element::Element(const QualifiedName& tagName, Document* document, ConstructionType type) - : ContainerNode(document, type) - , m_tagName(tagName) -{ -} - PassRefPtr<Element> Element::create(const QualifiedName& tagName, Document* document) { return adoptRef(new Element(tagName, document, CreateElement)); @@ -161,12 +155,12 @@ PassRefPtr<Element> Element::cloneElementWithoutChildren() // This is a sanity check as HTML overloads some of the DOM methods. ASSERT(isHTMLElement() == clone->isHTMLElement()); - clone->copyNonAttributeProperties(this); - // Clone attributes. if (namedAttrMap) clone->attributes()->setAttributes(*attributes(true)); // Call attributes(true) to force attribute synchronization to occur (for svg and style) before cloning happens. + clone->copyNonAttributeProperties(this); + return clone.release(); } @@ -225,11 +219,11 @@ bool Element::hasAttribute(const QualifiedName& name) const const AtomicString& Element::getAttribute(const QualifiedName& name) const { - if (name == styleAttr && !m_isStyleAttributeValid) + if (name == styleAttr && !isStyleAttributeValid()) updateStyleAttribute(); #if ENABLE(SVG) - if (!m_areSVGAttributesValid) + if (!areSVGAttributesValid()) updateAnimatedSVGAttribute(name); #endif @@ -532,11 +526,11 @@ const AtomicString& Element::getAttribute(const String& name) const bool ignoreCase = shouldIgnoreAttributeCase(this); // Update the 'style' attribute if it's invalid and being requested: - if (!m_isStyleAttributeValid && equalPossiblyIgnoringCase(name, styleAttr.localName(), ignoreCase)) + if (!isStyleAttributeValid() && equalPossiblyIgnoringCase(name, styleAttr.localName(), ignoreCase)) updateStyleAttribute(); #if ENABLE(SVG) - if (!m_areSVGAttributesValid) { + if (!areSVGAttributesValid()) { // We're not passing a namespace argument on purpose. SVGNames::*Attr are defined w/o namespaces as well. updateAnimatedSVGAttribute(QualifiedName(nullAtom, name, nullAtom)); } @@ -583,7 +577,7 @@ void Element::setAttribute(const AtomicString& name, const AtomicString& value, #if ENABLE(INSPECTOR) if (Page* page = document()->page()) { if (InspectorController* inspectorController = page->inspectorController()) { - if (!m_synchronizingStyleAttribute) + if (!isSynchronizingStyleAttribute()) inspectorController->didModifyDOMAttr(this); } } @@ -612,7 +606,7 @@ void Element::setAttribute(const QualifiedName& name, const AtomicString& value, #if ENABLE(INSPECTOR) if (Page* page = document()->page()) { if (InspectorController* inspectorController = page->inspectorController()) { - if (!m_synchronizingStyleAttribute) + if (!isSynchronizingStyleAttribute()) inspectorController->didModifyDOMAttr(this); } } @@ -718,11 +712,11 @@ void Element::setAttributeMap(PassRefPtr<NamedNodeMap> list, FragmentScriptingPe bool Element::hasAttributes() const { - if (!m_isStyleAttributeValid) + if (!isStyleAttributeValid()) updateStyleAttribute(); #if ENABLE(SVG) - if (!m_areSVGAttributesValid) + if (!areSVGAttributesValid()) updateAnimatedSVGAttribute(anyQName()); #endif @@ -916,7 +910,7 @@ void Element::recalcStyle(StyleChange change) attach(); // FIXME: The style gets computed twice by calling attach. We could do better if we passed the style along. // attach recalulates the style for all children. No need to do it twice. setNeedsStyleRecalc(NoStyleChange); - setChildNeedsStyleRecalc(false); + clearChildNeedsStyleRecalc(); return; } @@ -982,7 +976,7 @@ void Element::recalcStyle(StyleChange change) } setNeedsStyleRecalc(NoStyleChange); - setChildNeedsStyleRecalc(false); + clearChildNeedsStyleRecalc(); } bool Element::childTypeAllowed(NodeType type) @@ -1091,7 +1085,7 @@ void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* af void Element::finishParsingChildren() { ContainerNode::finishParsingChildren(); - m_parsingChildrenFinished = true; + setIsParsingChildrenFinished(); checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0); } diff --git a/WebCore/dom/Element.h b/WebCore/dom/Element.h index eefaeb1..3d02f1b 100644 --- a/WebCore/dom/Element.h +++ b/WebCore/dom/Element.h @@ -29,6 +29,7 @@ #include "Document.h" #include "HTMLNames.h" #include "MappedAttributeEntry.h" +#include "NamedNodeMap.h" #include "QualifiedName.h" #include "ScrollTypes.h" @@ -236,9 +237,9 @@ public: // Use Document::registerForMediaVolumeCallbacks() to subscribe to this virtual void mediaVolumeDidChange() { } - bool isFinishedParsingChildren() const { return m_parsingChildrenFinished; } + bool isFinishedParsingChildren() const { return isParsingChildrenFinished(); } virtual void finishParsingChildren(); - virtual void beginParsingChildren() { m_parsingChildrenFinished = false; } + virtual void beginParsingChildren() { clearIsParsingChildrenFinished(); } // ElementTraversal API Element* firstElementChild() const; @@ -252,6 +253,7 @@ public: virtual bool isFormControlElement() const { return false; } virtual bool isEnabledFormControl() const { return true; } virtual bool isReadOnlyFormControl() const { return false; } + virtual bool isSpinButtonElement() const { return false; } virtual bool isTextFormControl() const { return false; } virtual bool isOptionalFormControl() const { return false; } virtual bool isRequiredFormControl() const { return false; } @@ -272,7 +274,11 @@ public: virtual void dispatchFormControlChangeEvent() { } protected: - Element(const QualifiedName&, Document*, ConstructionType); + Element(const QualifiedName& tagName, Document* document, ConstructionType type) + : ContainerNode(document, type) + , m_tagName(tagName) + { + } virtual void insertedIntoDocument(); virtual void removedFromDocument(); @@ -356,11 +362,11 @@ inline const QualifiedName& Element::idAttributeName() const inline NamedNodeMap* Element::attributes(bool readonly) const { - if (!m_isStyleAttributeValid) + if (!isStyleAttributeValid()) updateStyleAttribute(); #if ENABLE(SVG) - if (!m_areSVGAttributesValid) + if (!areSVGAttributesValid()) updateAnimatedSVGAttribute(anyQName()); #endif diff --git a/WebCore/dom/Element.idl b/WebCore/dom/Element.idl index 1368503..977d15a 100644 --- a/WebCore/dom/Element.idl +++ b/WebCore/dom/Element.idl @@ -195,10 +195,10 @@ module core { attribute [DontEnum] EventListener onreset; attribute [DontEnum] EventListener onsearch; attribute [DontEnum] EventListener onselectstart; - attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchstart; - attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchmove; - attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchend; - attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchcancel; + attribute [DontEnum,Conditional=TOUCH_EVENTS,EnabledAtRuntime] EventListener ontouchstart; + attribute [DontEnum,Conditional=TOUCH_EVENTS,EnabledAtRuntime] EventListener ontouchmove; + attribute [DontEnum,Conditional=TOUCH_EVENTS,EnabledAtRuntime] EventListener ontouchend; + attribute [DontEnum,Conditional=TOUCH_EVENTS,EnabledAtRuntime] EventListener ontouchcancel; #endif }; diff --git a/WebCore/dom/EntityReference.cpp b/WebCore/dom/EntityReference.cpp index c4c292a..72944ec 100644 --- a/WebCore/dom/EntityReference.cpp +++ b/WebCore/dom/EntityReference.cpp @@ -21,6 +21,8 @@ #include "config.h" #include "EntityReference.h" +#include "Document.h" + namespace WebCore { inline EntityReference::EntityReference(Document* document, const String& entityName) diff --git a/WebCore/dom/EventNames.h b/WebCore/dom/EventNames.h index c50cfb2..ca2ae96 100644 --- a/WebCore/dom/EventNames.h +++ b/WebCore/dom/EventNames.h @@ -159,6 +159,8 @@ namespace WebCore { \ macro(success) \ \ + macro(loadend) \ + \ // end of DOM_EVENT_NAMES_FOR_EACH class EventNames : public Noncopyable { diff --git a/WebCore/dom/EventTarget.cpp b/WebCore/dom/EventTarget.cpp index 1598790..91a5d0c 100644 --- a/WebCore/dom/EventTarget.cpp +++ b/WebCore/dom/EventTarget.cpp @@ -156,6 +156,13 @@ Notification* EventTarget::toNotification() } #endif +#if ENABLE(FILE_READER) +FileReader* EventTarget::toFileReader() +{ + return 0; +} +#endif + bool EventTarget::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) { EventTargetData* d = ensureEventTargetData(); diff --git a/WebCore/dom/EventTarget.h b/WebCore/dom/EventTarget.h index da98d98..96d2d29 100644 --- a/WebCore/dom/EventTarget.h +++ b/WebCore/dom/EventTarget.h @@ -48,6 +48,7 @@ namespace WebCore { class Event; class EventListener; class EventSource; + class FileReader; class MessagePort; class Node; class Notification; @@ -118,6 +119,9 @@ namespace WebCore { #if ENABLE(NOTIFICATIONS) virtual Notification* toNotification(); #endif +#if ENABLE(FILE_READER) + virtual FileReader* toFileReader(); +#endif virtual ScriptExecutionContext* scriptExecutionContext() const = 0; diff --git a/WebCore/dom/ExceptionCode.h b/WebCore/dom/ExceptionCode.h index 573fb36..a5618f8 100644 --- a/WebCore/dom/ExceptionCode.h +++ b/WebCore/dom/ExceptionCode.h @@ -58,6 +58,13 @@ namespace WebCore { ABORT_ERR = 20, URL_MISMATCH_ERR = 21, QUOTA_EXCEEDED_ERR = 22, + + // Introduced in File API: + // http://www.w3.org/TR/file-upload/#dfn-fileerror +#if ENABLE(FILE_READER) || ENABLE(FILE_WRITER) + NOT_READABLE_ERR = 24, + ENCODING_ERR = 26, +#endif }; enum ExceptionType { diff --git a/WebCore/dom/InputElement.cpp b/WebCore/dom/InputElement.cpp index 52812f9..3459906 100644 --- a/WebCore/dom/InputElement.cpp +++ b/WebCore/dom/InputElement.cpp @@ -22,6 +22,15 @@ #include "InputElement.h" #include "BeforeTextInsertedEvent.h" + +#if ENABLE(WCSS) +#include "CSSPropertyNames.h" +#include "CSSRule.h" +#include "CSSRuleList.h" +#include "CSSStyleRule.h" +#include "CSSStyleSelector.h" +#endif + #include "Chrome.h" #include "ChromeClient.h" #include "Document.h" @@ -138,6 +147,14 @@ void InputElement::setValueFromRenderer(InputElementData& data, InputElement* in String InputElement::sanitizeValue(const InputElement* inputElement, const String& proposedValue) { +#if ENABLE(WCSS) + InputElementData data = const_cast<InputElement*>(inputElement)->data(); + if (!isConformToInputMask(data, proposedValue)) { + if (isConformToInputMask(data, data.value())) + return data.value(); + return String(); + } +#endif return InputElement::sanitizeUserInputValue(inputElement, proposedValue, s_maximumLength); } @@ -172,8 +189,12 @@ void InputElement::handleBeforeTextInsertedEvent(InputElementData& data, InputEl // RenderTextControlSingleLine::subtreeHasChanged() in some cases. unsigned oldLength = numGraphemeClusters(toRenderTextControlSingleLine(element->renderer())->text()); - // selection() may be a pre-edit text. - unsigned selectionLength = numGraphemeClusters(plainText(element->document()->frame()->selection()->selection().toNormalizedRange().get())); + // selectionLength represents the selection length of this text field to be + // removed by this insertion. + // If the text field has no focus, we don't need to take account of the + // selection length. The selection is the source of text drag-and-drop in + // that case, and nothing in the text field will be removed. + unsigned selectionLength = element->focused() ? numGraphemeClusters(plainText(element->document()->frame()->selection()->selection().toNormalizedRange().get())) : 0; ASSERT(oldLength >= selectionLength); // Selected characters will be removed by the next text event. @@ -183,6 +204,18 @@ void InputElement::handleBeforeTextInsertedEvent(InputElementData& data, InputEl // Truncate the inserted text to avoid violating the maxLength and other constraints. BeforeTextInsertedEvent* textEvent = static_cast<BeforeTextInsertedEvent*>(event); +#if ENABLE(WCSS) + RefPtr<Range> range = element->document()->frame()->selection()->selection().toNormalizedRange(); + String candidateString = toRenderTextControlSingleLine(element->renderer())->text(); + if (selectionLength) + candidateString.replace(range->startOffset(), range->endOffset(), textEvent->text()); + else + candidateString.insert(textEvent->text(), range->startOffset()); + if (!isConformToInputMask(inputElement->data(), candidateString)) { + textEvent->setText(""); + return; + } +#endif textEvent->setText(sanitizeUserInputValue(inputElement, textEvent->text(), appendableLength)); } @@ -234,6 +267,10 @@ InputElementData::InputElementData() , m_maxLength(InputElement::s_maximumLength) , m_cachedSelectionStart(-1) , m_cachedSelectionEnd(-1) +#if ENABLE(WCSS) + , m_inputFormatMask("*m") + , m_maxInputCharsAllowed(InputElement::s_maximumLength) +#endif { } @@ -255,4 +292,137 @@ InputElement* toInputElement(Element* element) return 0; } +#if ENABLE(WCSS) +static inline const AtomicString& formatCodes() +{ + DEFINE_STATIC_LOCAL(AtomicString, codes, ("AaNnXxMm")); + return codes; +} + +static unsigned cursorPositionToMaskIndex(const String& inputFormatMask, unsigned cursorPosition) +{ + UChar mask; + int index = -1; + do { + mask = inputFormatMask[++index]; + if (mask == '\\') + ++index; + else if (mask == '*' || (isASCIIDigit(mask) && mask != '0')) { + index = inputFormatMask.length() - 1; + break; + } + } while (cursorPosition--); + + return index; +} + +bool InputElement::isConformToInputMask(const InputElementData& data, const String& inputChars) +{ + for (unsigned i = 0; i < inputChars.length(); ++i) + if (!isConformToInputMask(data, inputChars[i], i)) + return false; + return true; +} + +bool InputElement::isConformToInputMask(const InputElementData& data, UChar inChar, unsigned cursorPosition) +{ + String inputFormatMask = data.inputFormatMask(); + + if (inputFormatMask.isEmpty() || inputFormatMask == "*M" || inputFormatMask == "*m") + return true; + + if (cursorPosition >= data.maxInputCharsAllowed()) + return false; + + unsigned maskIndex = cursorPositionToMaskIndex(inputFormatMask, cursorPosition); + bool ok = true; + UChar mask = inputFormatMask[maskIndex]; + // Match the inputed character with input mask + switch (mask) { + case 'A': + ok = !isASCIIDigit(inChar) && !isASCIILower(inChar) && isASCIIPrintable(inChar); + break; + case 'a': + ok = !isASCIIDigit(inChar) && !isASCIIUpper(inChar) && isASCIIPrintable(inChar); + break; + case 'N': + ok = isASCIIDigit(inChar); + break; + case 'n': + ok = !isASCIIAlpha(inChar) && isASCIIPrintable(inChar); + break; + case 'X': + ok = !isASCIILower(inChar) && isASCIIPrintable(inChar); + break; + case 'x': + ok = !isASCIIUpper(inChar) && isASCIIPrintable(inChar); + break; + case 'M': + case 'm': + ok = isASCIIPrintable(inChar); + break; + default: + ok = (mask == inChar); + break; + } + + return ok; +} + +String InputElement::validateInputMask(InputElementData& data, String& inputMask) +{ + inputMask.replace("\\\\", "\\"); + + bool isValid = true; + bool hasWildcard = false; + unsigned escapeCharCount = 0; + unsigned maskLength = inputMask.length(); + UChar formatCode; + for (unsigned i = 0; i < maskLength; ++i) { + formatCode = inputMask[i]; + if (formatCodes().find(formatCode) == -1) { + if (formatCode == '*' || (isASCIIDigit(formatCode) && formatCode != '0')) { + // Validate codes which ends with '*f' or 'nf' + formatCode = inputMask[++i]; + if ((i + 1 != maskLength) || formatCodes().find(formatCode) == -1) { + isValid = false; + break; + } + hasWildcard = true; + } else if (formatCode == '\\') { + // skip over the next mask character + ++i; + ++escapeCharCount; + } else { + isValid = false; + break; + } + } + } + + if (!isValid) + return String(); + // calculate the number of characters allowed to be entered by input mask + unsigned allowedLength = maskLength; + if (escapeCharCount) + allowedLength -= escapeCharCount; + + if (hasWildcard) { + formatCode = inputMask[maskLength - 2]; + if (formatCode == '*') + allowedLength = data.maxInputCharsAllowed(); + else { + unsigned leftLen = String(&formatCode).toInt(); + allowedLength = leftLen + allowedLength - 2; + } + } + + if (allowedLength < data.maxInputCharsAllowed()) + data.setMaxInputCharsAllowed(allowedLength); + + return inputMask; +} + +#endif + } diff --git a/WebCore/dom/InputElement.h b/WebCore/dom/InputElement.h index a24b438..bdd5645 100644 --- a/WebCore/dom/InputElement.h +++ b/WebCore/dom/InputElement.h @@ -43,6 +43,7 @@ public: virtual bool isPasswordField() const = 0; virtual bool isSearchField() const = 0; virtual bool isTextField() const = 0; + virtual bool hasSpinButton() const { return false; } virtual bool searchEventsShouldBeDispatched() const = 0; @@ -57,6 +58,10 @@ public: virtual void cacheSelection(int start, int end) = 0; virtual void select() = 0; + +#if ENABLE(WCSS) + virtual InputElementData data() const = 0; +#endif static const int s_maximumLength; static const int s_defaultSize; @@ -79,6 +84,11 @@ protected: static void parseMaxLengthAttribute(InputElementData&, InputElement*, Element*, MappedAttribute*); static void updateValueIfNeeded(InputElementData&, InputElement*); static void notifyFormStateChanged(Element*); +#if ENABLE(WCSS) + static bool isConformToInputMask(const InputElementData&, const String&); + static bool isConformToInputMask(const InputElementData&, UChar, unsigned); + static String validateInputMask(InputElementData&, String&); +#endif }; // HTML/WMLInputElement hold this struct as member variable @@ -108,6 +118,15 @@ public: int cachedSelectionEnd() const { return m_cachedSelectionEnd; } void setCachedSelectionEnd(int value) { m_cachedSelectionEnd = value; } +#if ENABLE(WCSS) + String inputFormatMask() const { return m_inputFormatMask; } + void setInputFormatMask(const String& mask) { m_inputFormatMask = mask; } + + unsigned maxInputCharsAllowed() const { return m_maxInputCharsAllowed; } + void setMaxInputCharsAllowed(unsigned maxLength) { m_maxInputCharsAllowed = maxLength; } + +#endif + private: AtomicString m_name; String m_value; @@ -116,6 +135,10 @@ private: int m_maxLength; int m_cachedSelectionStart; int m_cachedSelectionEnd; +#if ENABLE(WCSS) + String m_inputFormatMask; + unsigned m_maxInputCharsAllowed; +#endif }; InputElement* toInputElement(Element*); diff --git a/WebCore/dom/MessagePort.idl b/WebCore/dom/MessagePort.idl index 9312430..7bde45e 100644 --- a/WebCore/dom/MessagePort.idl +++ b/WebCore/dom/MessagePort.idl @@ -43,12 +43,12 @@ module events { attribute EventListener onmessage; // EventTarget interface - [JSCCustom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [JSCCustom] void removeEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); + void addEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); + void removeEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); boolean dispatchEvent(in Event evt) raises(EventException); #endif diff --git a/WebCore/dom/NameNodeList.cpp b/WebCore/dom/NameNodeList.cpp index 4d96de0..2ffa577 100644 --- a/WebCore/dom/NameNodeList.cpp +++ b/WebCore/dom/NameNodeList.cpp @@ -31,12 +31,17 @@ namespace WebCore { using namespace HTMLNames; -NameNodeList::NameNodeList(PassRefPtr<Node> rootNode, const String& name, DynamicNodeList::Caches* caches) - : DynamicNodeList(rootNode, caches) +NameNodeList::NameNodeList(PassRefPtr<Node> rootNode, const String& name) + : DynamicNodeList(rootNode) , m_nodeName(name) { } +NameNodeList::~NameNodeList() +{ + m_rootNode->removeCachedNameNodeList(this, m_nodeName); +} + bool NameNodeList::nodeMatches(Element* testNode) const { return testNode->getAttribute(nameAttr) == m_nodeName; diff --git a/WebCore/dom/NameNodeList.h b/WebCore/dom/NameNodeList.h index 2fdb43d..4f109b4 100644 --- a/WebCore/dom/NameNodeList.h +++ b/WebCore/dom/NameNodeList.h @@ -34,13 +34,15 @@ namespace WebCore { // NodeList which lists all Nodes in a Element with a given "name" attribute class NameNodeList : public DynamicNodeList { public: - static PassRefPtr<NameNodeList> create(PassRefPtr<Node> rootNode, const String& name, Caches* caches) + static PassRefPtr<NameNodeList> create(PassRefPtr<Node> rootNode, const String& name) { - return adoptRef(new NameNodeList(rootNode, name, caches)); + return adoptRef(new NameNodeList(rootNode, name)); } + virtual ~NameNodeList(); + private: - NameNodeList(PassRefPtr<Node> rootNode, const String& name, Caches*); + NameNodeList(PassRefPtr<Node> rootNode, const String& name); virtual bool nodeMatches(Element*) const; diff --git a/WebCore/dom/Node.cpp b/WebCore/dom/Node.cpp index a8ffc37..83aef21 100644 --- a/WebCore/dom/Node.cpp +++ b/WebCore/dom/Node.cpp @@ -103,8 +103,13 @@ #include "HTMLNoScriptElement.h" #endif +<<<<<<< HEAD:WebCore/dom/Node.cpp #if ENABLE(TOUCH_EVENTS) #include "ChromeClient.h" +======= +#if USE(JSC) +#include <runtime/JSGlobalData.h> +>>>>>>> webkit.org at r58956:WebCore/dom/Node.cpp #endif #define DUMP_NODE_STATISTICS 0 @@ -339,99 +344,8 @@ Node::StyleChange Node::diff(const RenderStyle* s1, const RenderStyle* s2) return ch; } -inline bool Node::initialRefCount(ConstructionType type) -{ - switch (type) { - case CreateContainer: - case CreateElement: - case CreateOther: - case CreateText: - return 1; - case CreateElementZeroRefCount: - return 0; - } - ASSERT_NOT_REACHED(); - return 1; -} - -inline bool Node::isContainer(ConstructionType type) +void Node::trackForDebugging() { - switch (type) { - case CreateContainer: - case CreateElement: - case CreateElementZeroRefCount: - return true; - case CreateOther: - case CreateText: - return false; - } - ASSERT_NOT_REACHED(); - return false; -} - -inline bool Node::isElement(ConstructionType type) -{ - switch (type) { - case CreateContainer: - case CreateOther: - case CreateText: - return false; - case CreateElement: - case CreateElementZeroRefCount: - return true; - } - ASSERT_NOT_REACHED(); - return false; -} - -inline bool Node::isText(ConstructionType type) -{ - switch (type) { - case CreateContainer: - case CreateElement: - case CreateElementZeroRefCount: - case CreateOther: - return false; - case CreateText: - return true; - } - ASSERT_NOT_REACHED(); - return false; -} - -Node::Node(Document* document, ConstructionType type) - : TreeShared<Node>(initialRefCount(type)) - , m_document(document) - , m_previous(0) - , m_next(0) - , m_renderer(0) - , m_styleChange(NoStyleChange) - , m_hasId(false) - , m_hasClass(false) - , m_attached(false) - , m_childNeedsStyleRecalc(false) - , m_inDocument(false) - , m_isLink(false) - , m_active(false) - , m_hovered(false) - , m_inActiveChain(false) - , m_inDetach(false) - , m_hasRareData(false) - , m_isElement(isElement(type)) - , m_isContainer(isContainer(type)) - , m_isText(isText(type)) - , m_parsingChildrenFinished(true) - , m_isStyleAttributeValid(true) - , m_synchronizingStyleAttribute(false) -#if ENABLE(SVG) - , m_areSVGAttributesValid(true) - , m_synchronizingSVGAttributes(false) - , m_hasRareSVGData(false) -#endif -{ - if (m_document) - m_document->selfOnlyRef(); - #ifndef NDEBUG if (shouldIgnoreLeaks) ignoreSet.add(this); @@ -555,7 +469,7 @@ NodeRareData* Node::ensureRareData() ASSERT(!NodeRareData::rareDataMap().contains(this)); NodeRareData* data = createRareData(); NodeRareData::rareDataMap().set(this, data); - m_hasRareData = true; + setFlag(HasRareDataFlag); return data; } @@ -771,17 +685,43 @@ IntRect Node::getRect() const return IntRect(); } +bool Node::hasNonEmptyBoundingBox() const +{ + // Before calling absoluteRects, check for the common case where the renderer + // is non-empty, since this is a faster check and almost always returns true. + RenderBoxModelObject* box = renderBoxModelObject(); + if (!box) + return false; + if (!box->borderBoundingBox().isEmpty()) + return true; + + Vector<IntRect> rects; + FloatPoint absPos = renderer()->localToAbsolute(); + renderer()->absoluteRects(rects, absPos.x(), absPos.y()); + size_t n = rects.size(); + for (size_t i = 0; i < n; ++i) + if (!rects[i].isEmpty()) + return true; + + return false; +} + +inline void Node::setStyleChange(StyleChangeType changeType) +{ + m_nodeFlags = (m_nodeFlags & ~StyleChangeMask) | changeType; +} + void Node::setNeedsStyleRecalc(StyleChangeType changeType) { if ((changeType != NoStyleChange) && !attached()) // changed compared to what? return; - if (!(changeType == InlineStyleChange && (m_styleChange == FullStyleChange || m_styleChange == SyntheticStyleChange))) - m_styleChange = changeType; + if (!(changeType == InlineStyleChange && (styleChangeType() == FullStyleChange || styleChangeType() == SyntheticStyleChange))) + setStyleChange(changeType); - if (m_styleChange != NoStyleChange) { + if (styleChangeType() != NoStyleChange) { for (Node* p = parentNode(); p && !p->childNeedsStyleRecalc(); p = p->parentNode()) - p->setChildNeedsStyleRecalc(true); + p->setChildNeedsStyleRecalc(); if (document()->childNeedsStyleRecalc()) document()->scheduleStyleRecalc(); } @@ -805,9 +745,9 @@ void Node::lazyAttach() } if (n->firstChild()) - n->setChildNeedsStyleRecalc(true); - n->m_styleChange = FullStyleChange; - n->m_attached = true; + n->setChildNeedsStyleRecalc(); + n->setStyleChange(FullStyleChange); + n->setAttached(); } if (mustDoFullAttach) { @@ -817,7 +757,7 @@ void Node::lazyAttach() lazyAttachedAncestor->attach(); } else { for (Node* p = parentNode(); p && !p->childNeedsStyleRecalc(); p = p->parentNode()) - p->setChildNeedsStyleRecalc(true); + p->setChildNeedsStyleRecalc(); if (document()->childNeedsStyleRecalc()) document()->scheduleStyleRecalc(); } @@ -965,6 +905,39 @@ void Node::notifyNodeListsChildrenChanged() n->notifyLocalNodeListsChildrenChanged(); } +void Node::removeCachedClassNodeList(ClassNodeList* list, const String& className) +{ + ASSERT(rareData()); + ASSERT(rareData()->nodeLists()); + ASSERT_UNUSED(list, list->hasOwnCaches()); + + NodeListsNodeData* data = rareData()->nodeLists(); + ASSERT_UNUSED(list, list == data->m_classNodeListCache.get(className)); + data->m_classNodeListCache.remove(className); +} + +void Node::removeCachedNameNodeList(NameNodeList* list, const String& nodeName) +{ + ASSERT(rareData()); + ASSERT(rareData()->nodeLists()); + ASSERT_UNUSED(list, list->hasOwnCaches()); + + NodeListsNodeData* data = rareData()->nodeLists(); + ASSERT_UNUSED(list, list == data->m_nameNodeListCache.get(nodeName)); + data->m_nameNodeListCache.remove(nodeName); +} + +void Node::removeCachedTagNodeList(TagNodeList* list, const QualifiedName& name) +{ + ASSERT(rareData()); + ASSERT(rareData()->nodeLists()); + ASSERT_UNUSED(list, list->hasOwnCaches()); + + NodeListsNodeData* data = rareData()->nodeLists(); + ASSERT_UNUSED(list, list == data->m_tagNodeListCache.get(name)); + data->m_tagNodeListCache.remove(name); +} + Node *Node::traverseNextNode(const Node *stayWithin) const { if (firstChild()) @@ -1247,7 +1220,7 @@ void Node::attach() } } - m_attached = true; + setAttached(); } void Node::willRemove() @@ -1256,23 +1229,24 @@ void Node::willRemove() void Node::detach() { - m_inDetach = true; + setFlag(InDetachFlag); if (renderer()) renderer()->destroy(); setRenderer(0); Document* doc = document(); - if (m_hovered) + if (hovered()) doc->hoveredNodeDetached(this); - if (m_inActiveChain) + if (inActiveChain()) doc->activeChainNodeDetached(this); - m_active = false; - m_hovered = false; - m_inActiveChain = false; - m_attached = false; - m_inDetach = false; + clearFlag(IsActiveFlag); + clearFlag(IsHoveredFlag); + clearFlag(InActiveChainFlag); + clearFlag(IsAttachedFlag); + + clearFlag(InDetachFlag); } Node *Node::previousEditable() const @@ -1595,11 +1569,13 @@ PassRefPtr<NodeList> Node::getElementsByTagNameNS(const AtomicString& namespaceU AtomicString localNameAtom = name; - pair<NodeListsNodeData::TagCacheMap::iterator, bool> result = data->nodeLists()->m_tagNodeListCaches.add(QualifiedName(nullAtom, localNameAtom, namespaceURI), 0); - if (result.second) - result.first->second = DynamicNodeList::Caches::create(); + pair<NodeListsNodeData::TagNodeListCache::iterator, bool> result = data->nodeLists()->m_tagNodeListCache.add(QualifiedName(nullAtom, localNameAtom, namespaceURI), 0); + if (!result.second) + return PassRefPtr<TagNodeList>(result.first->second); - return TagNodeList::create(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localNameAtom, result.first->second.get()); + RefPtr<TagNodeList> list = TagNodeList::create(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localNameAtom); + result.first->second = list.get(); + return list.release(); } PassRefPtr<NodeList> Node::getElementsByName(const String& elementName) @@ -1610,11 +1586,13 @@ PassRefPtr<NodeList> Node::getElementsByName(const String& elementName) document()->addNodeListCache(); } - pair<NodeListsNodeData::CacheMap::iterator, bool> result = data->nodeLists()->m_nameNodeListCaches.add(elementName, 0); - if (result.second) - result.first->second = DynamicNodeList::Caches::create(); - - return NameNodeList::create(this, elementName, result.first->second.get()); + pair<NodeListsNodeData::NameNodeListCache::iterator, bool> result = data->nodeLists()->m_nameNodeListCache.add(elementName, 0); + if (!result.second) + return PassRefPtr<NodeList>(result.first->second); + + RefPtr<NameNodeList> list = NameNodeList::create(this, elementName); + result.first->second = list.get(); + return list.release(); } PassRefPtr<NodeList> Node::getElementsByClassName(const String& classNames) @@ -1625,11 +1603,13 @@ PassRefPtr<NodeList> Node::getElementsByClassName(const String& classNames) document()->addNodeListCache(); } - pair<NodeListsNodeData::CacheMap::iterator, bool> result = data->nodeLists()->m_classNodeListCaches.add(classNames, 0); - if (result.second) - result.first->second = DynamicNodeList::Caches::create(); - - return ClassNodeList::create(this, classNames, result.first->second.get()); + pair<NodeListsNodeData::ClassNodeListCache::iterator, bool> result = data->nodeLists()->m_classNodeListCache.add(classNames, 0); + if (!result.second) + return PassRefPtr<NodeList>(result.first->second); + + RefPtr<ClassNodeList> list = ClassNodeList::create(this, classNames); + result.first->second = list.get(); + return list.release(); } PassRefPtr<Element> Node::querySelector(const String& selectors, ExceptionCode& ec) @@ -2271,21 +2251,21 @@ void Node::formatForDebugger(char* buffer, unsigned length) const void NodeListsNodeData::invalidateCaches() { m_childNodeListCaches->reset(); - TagCacheMap::const_iterator tagCachesEnd = m_tagNodeListCaches.end(); - for (TagCacheMap::const_iterator it = m_tagNodeListCaches.begin(); it != tagCachesEnd; ++it) - it->second->reset(); + TagNodeListCache::const_iterator tagCacheEnd = m_tagNodeListCache.end(); + for (TagNodeListCache::const_iterator it = m_tagNodeListCache.begin(); it != tagCacheEnd; ++it) + it->second->invalidateCache(); invalidateCachesThatDependOnAttributes(); } void NodeListsNodeData::invalidateCachesThatDependOnAttributes() { - CacheMap::iterator classCachesEnd = m_classNodeListCaches.end(); - for (CacheMap::iterator it = m_classNodeListCaches.begin(); it != classCachesEnd; ++it) - it->second->reset(); + ClassNodeListCache::iterator classCacheEnd = m_classNodeListCache.end(); + for (ClassNodeListCache::iterator it = m_classNodeListCache.begin(); it != classCacheEnd; ++it) + it->second->invalidateCache(); - CacheMap::iterator nameCachesEnd = m_nameNodeListCaches.end(); - for (CacheMap::iterator it = m_nameNodeListCaches.begin(); it != nameCachesEnd; ++it) - it->second->reset(); + NameNodeListCache::iterator nameCacheEnd = m_nameNodeListCache.end(); + for (NameNodeListCache::iterator it = m_nameNodeListCache.begin(); it != nameCacheEnd; ++it) + it->second->invalidateCache(); } bool NodeListsNodeData::isEmpty() const @@ -2296,20 +2276,20 @@ bool NodeListsNodeData::isEmpty() const if (m_childNodeListCaches->refCount()) return false; - TagCacheMap::const_iterator tagCachesEnd = m_tagNodeListCaches.end(); - for (TagCacheMap::const_iterator it = m_tagNodeListCaches.begin(); it != tagCachesEnd; ++it) { + TagNodeListCache::const_iterator tagCacheEnd = m_tagNodeListCache.end(); + for (TagNodeListCache::const_iterator it = m_tagNodeListCache.begin(); it != tagCacheEnd; ++it) { if (it->second->refCount()) return false; } - CacheMap::const_iterator classCachesEnd = m_classNodeListCaches.end(); - for (CacheMap::const_iterator it = m_classNodeListCaches.begin(); it != classCachesEnd; ++it) { + ClassNodeListCache::const_iterator classCacheEnd = m_classNodeListCache.end(); + for (ClassNodeListCache::const_iterator it = m_classNodeListCache.begin(); it != classCacheEnd; ++it) { if (it->second->refCount()) return false; } - CacheMap::const_iterator nameCachesEnd = m_nameNodeListCaches.end(); - for (CacheMap::const_iterator it = m_nameNodeListCaches.begin(); it != nameCachesEnd; ++it) { + NameNodeListCache::const_iterator nameCacheEnd = m_nameNodeListCache.end(); + for (NameNodeListCache::const_iterator it = m_nameNodeListCache.begin(); it != nameCacheEnd; ++it) { if (it->second->refCount()) return false; } @@ -2384,12 +2364,12 @@ ScriptExecutionContext* Node::scriptExecutionContext() const void Node::insertedIntoDocument() { - setInDocument(true); + setInDocument(); } void Node::removedFromDocument() { - setInDocument(false); + clearInDocument(); } void Node::willMoveToNewOwnerDocument() @@ -2569,6 +2549,28 @@ EventTargetData* Node::ensureEventTargetData() return ensureRareData()->ensureEventTargetData(); } +#if USE(JSC) + +template <class NodeListMap> +void markNodeLists(const NodeListMap& map, JSC::MarkStack& markStack, JSC::JSGlobalData& globalData) +{ + for (typename NodeListMap::const_iterator it = map.begin(); it != map.end(); ++it) + markDOMObjectWrapper(markStack, globalData, it->second); +} + +void Node::markCachedNodeListsSlow(JSC::MarkStack& markStack, JSC::JSGlobalData& globalData) +{ + NodeListsNodeData* nodeLists = rareData()->nodeLists(); + if (!nodeLists) + return; + + markNodeLists(nodeLists->m_classNodeListCache, markStack, globalData); + markNodeLists(nodeLists->m_nameNodeListCache, markStack, globalData); + markNodeLists(nodeLists->m_tagNodeListCache, markStack, globalData); +} + +#endif + void Node::handleLocalEvents(Event* event) { if (!hasRareData() || !rareData()->eventTargetData()) diff --git a/WebCore/dom/Node.h b/WebCore/dom/Node.h index b2af8fc..b165615 100644 --- a/WebCore/dom/Node.h +++ b/WebCore/dom/Node.h @@ -32,10 +32,20 @@ #include "TreeShared.h" #include <wtf/ListHashSet.h> +#if USE(JSC) +namespace JSC { + + class JSGlobalData; + class MarkStack; + +} +#endif + namespace WebCore { class AtomicString; class Attribute; +class ClassNodeList; class ContainerNode; class Document; class DynamicNodeList; @@ -48,6 +58,7 @@ class IntRect; class KeyboardEvent; class NSResolver; class NamedNodeMap; +class NameNodeList; class NodeList; class NodeRareData; class PlatformKeyboardEvent; @@ -61,13 +72,21 @@ class RenderBoxModelObject; class RenderObject; class RenderStyle; class StringBuilder; +class TagNodeList; typedef int ExceptionCode; +const int nodeStyleChangeShift = 24; + // SyntheticStyleChange means that we need to go through the entire style change logic even though // no style property has actually changed. It is used to restructure the tree when, for instance, // RenderLayers are created or destroyed due to animation changes. -enum StyleChangeType { NoStyleChange, InlineStyleChange, FullStyleChange, SyntheticStyleChange }; +enum StyleChangeType { + NoStyleChange = 0, + InlineStyleChange = 1 << nodeStyleChangeShift, + FullStyleChange = 2 << nodeStyleChangeShift, + SyntheticStyleChange = 3 << nodeStyleChangeShift +}; const unsigned short DOCUMENT_POSITION_EQUIVALENT = 0x00; const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01; @@ -162,17 +181,13 @@ public: // Other methods (not part of DOM) - bool isElementNode() const { return m_isElement; } - bool isContainerNode() const { return m_isContainer; } - bool isTextNode() const { return m_isText; } + bool isElementNode() const { return getFlag(IsElementFlag); } + bool isContainerNode() const { return getFlag(IsContainerFlag); } + bool isTextNode() const { return getFlag(IsTextFlag); } - virtual bool isHTMLElement() const { return false; } + bool isHTMLElement() const { return getFlag(IsHTMLFlag); } -#if ENABLE(SVG) - virtual bool isSVGElement() const { return false; } -#else - static bool isSVGElement() { return false; } -#endif + bool isSVGElement() const { return getFlag(IsSVGFlag); } #if ENABLE(WML) virtual bool isWMLElement() const { return false; } @@ -188,10 +203,10 @@ public: virtual bool isMediaControlElement() const { return false; } - virtual bool isStyledElement() const { return false; } + bool isStyledElement() const { return getFlag(IsStyledElementFlag); } virtual bool isFrameOwnerElement() const { return false; } virtual bool isAttributeNode() const { return false; } - virtual bool isCommentNode() const { return false; } + bool isCommentNode() const { return getFlag(IsCommentFlag); } virtual bool isCharacterDataNode() const { return false; } bool isDocumentNode() const; virtual bool isShadowNode() const { return false; } @@ -268,33 +283,40 @@ public: // For <link> and <style> elements. virtual bool sheetLoaded() { return true; } - bool hasID() const { return m_hasId; } - bool hasClass() const { return m_hasClass; } - bool active() const { return m_active; } - bool inActiveChain() const { return m_inActiveChain; } - bool inDetach() const { return m_inDetach; } - bool hovered() const { return m_hovered; } + bool hasID() const { return getFlag(HasIDFlag); } + bool hasClass() const { return getFlag(HasClassFlag); } + bool active() const { return getFlag(IsActiveFlag); } + bool inActiveChain() const { return getFlag(InActiveChainFlag); } + bool inDetach() const { return getFlag(InDetachFlag); } + bool hovered() const { return getFlag(IsHoveredFlag); } bool focused() const { return hasRareData() ? rareDataFocused() : false; } - bool attached() const { return m_attached; } - void setAttached(bool b = true) { m_attached = b; } - bool needsStyleRecalc() const { return m_styleChange != NoStyleChange; } - StyleChangeType styleChangeType() const { return static_cast<StyleChangeType>(m_styleChange); } - bool childNeedsStyleRecalc() const { return m_childNeedsStyleRecalc; } - bool isLink() const { return m_isLink; } - void setHasID(bool b = true) { m_hasId = b; } - void setHasClass(bool b = true) { m_hasClass = b; } - void setChildNeedsStyleRecalc(bool b = true) { m_childNeedsStyleRecalc = b; } - void setInDocument(bool b = true) { m_inDocument = b; } - void setInActiveChain(bool b = true) { m_inActiveChain = b; } + bool attached() const { return getFlag(IsAttachedFlag); } + void setAttached() { setFlag(IsAttachedFlag); } + bool needsStyleRecalc() const { return styleChangeType() != NoStyleChange; } + StyleChangeType styleChangeType() const { return static_cast<StyleChangeType>(m_nodeFlags & StyleChangeMask); } + bool childNeedsStyleRecalc() const { return getFlag(ChildNeedsStyleRecalcFlag); } + bool isLink() const { return getFlag(IsLinkFlag); } + + void setHasID(bool f) { setFlag(f, HasIDFlag); } + void setHasClass(bool f) { setFlag(f, HasClassFlag); } + void setChildNeedsStyleRecalc() { setFlag(ChildNeedsStyleRecalcFlag); } + void clearChildNeedsStyleRecalc() { clearFlag(ChildNeedsStyleRecalcFlag); } + void setInDocument() { setFlag(InDocumentFlag); } + void clearInDocument() { clearFlag(InDocumentFlag); } + + void setInActiveChain() { setFlag(InActiveChainFlag); } + void clearInActiveChain() { clearFlag(InActiveChainFlag); } void setNeedsStyleRecalc(StyleChangeType changeType = FullStyleChange); - void setIsLink(bool b = true) { m_isLink = b; } + void setIsLink(bool f) { setFlag(f, IsLinkFlag); } + void setIsLink() { setFlag(IsLinkFlag); } + void clearIsLink() { clearFlag(IsLinkFlag); } void lazyAttach(); virtual bool canLazyAttach(); virtual void setFocus(bool b = true); - virtual void setActive(bool b = true, bool /*pause*/ = false) { m_active = b; } - virtual void setHovered(bool b = true) { m_hovered = b; } + virtual void setActive(bool f = true, bool /*pause*/ = false) { setFlag(f, IsActiveFlag); } + virtual void setHovered(bool f = true) { setFlag(f, IsHoveredFlag); } virtual short tabIndex() const; @@ -311,6 +333,11 @@ public: virtual bool shouldUseInputMethod() const; virtual IntRect getRect() const; + // Returns true if the node has a non-empty bounding box in layout. + // This does not 100% guarantee the user can see it, but is pretty close. + // Note: This method only works properly after layout has occurred. + bool hasNonEmptyBoundingBox() const; + virtual void recalcStyle(StyleChange = NoChange) { } unsigned nodeIndex() const; @@ -333,8 +360,8 @@ public: // node tree, false otherwise. bool inDocument() const { - ASSERT(m_document || !m_inDocument); - return m_inDocument; + ASSERT(m_document || !getFlag(InDocumentFlag)); + return getFlag(InDocumentFlag); } bool isReadOnlyNode() const { return nodeType() == ENTITY_REFERENCE_NODE; } @@ -497,6 +524,9 @@ public: void notifyLocalNodeListsChildrenChanged(); void notifyNodeListsAttributeChanged(); void notifyLocalNodeListsAttributeChanged(); + void removeCachedClassNodeList(ClassNodeList*, const String&); + void removeCachedNameNodeList(NameNodeList*, const String&); + void removeCachedTagNodeList(TagNodeList*, const QualifiedName&); PassRefPtr<NodeList> getElementsByTagName(const String&); PassRefPtr<NodeList> getElementsByTagNameNS(const AtomicString& namespaceURI, const String& localName); @@ -571,10 +601,82 @@ public: virtual EventTargetData* eventTargetData(); virtual EventTargetData* ensureEventTargetData(); +#if USE(JSC) + void markCachedNodeLists(JSC::MarkStack& markStack, JSC::JSGlobalData& globalData) + { + // NodeLists may be present. If so, they need to be marked. + if (!hasRareData()) + return; + + markCachedNodeListsSlow(markStack, globalData); + } +#endif + +private: + enum NodeFlags { + IsTextFlag = 1, + IsCommentFlag = 1 << 1, + IsContainerFlag = 1 << 2, + IsElementFlag = 1 << 3, + IsStyledElementFlag = 1 << 4, + IsHTMLFlag = 1 << 5, + IsSVGFlag = 1 << 6, + HasIDFlag = 1 << 7, + HasClassFlag = 1 << 8, + IsAttachedFlag = 1 << 9, + ChildNeedsStyleRecalcFlag = 1 << 10, + InDocumentFlag = 1 << 11, + IsLinkFlag = 1 << 12, + IsActiveFlag = 1 << 13, + IsHoveredFlag = 1 << 14, + InActiveChainFlag = 1 << 15, + InDetachFlag = 1 << 16, + HasRareDataFlag = 1 << 17, + + // These bits are used by derived classes, pulled up here so they can + // be stored in the same memory word as the Node bits above. + IsParsingChildrenFinishedFlag = 1 << 18, // Element + IsStyleAttributeValidFlag = 1 << 19, // StyledElement + IsSynchronizingStyleAttributeFlag = 1 << 20, // StyledElement +#if ENABLE(SVG) + AreSVGAttributesValidFlag = 1 << 21, // Element + IsSynchronizingSVGAttributesFlag = 1 << 22, // SVGElement + HasSVGRareDataFlag = 1 << 23, // SVGElement +#endif + StyleChangeMask = 1 << nodeStyleChangeShift | 1 << (nodeStyleChangeShift + 1), + CreateWithZeroRefCountFlag = 1 << 26, + +#if ENABLE(SVG) + DefaultNodeFlags = IsParsingChildrenFinishedFlag | IsStyleAttributeValidFlag | AreSVGAttributesValidFlag +#else + DefaultNodeFlags = IsParsingChildrenFinishedFlag | IsStyleAttributeValidFlag +#endif + }; + + // 5 bits remaining + + bool getFlag(NodeFlags mask) const { return m_nodeFlags & mask; } + void setFlag(bool f, NodeFlags mask) const { m_nodeFlags = (m_nodeFlags & ~mask) | (-(int32_t)f & mask); } + void setFlag(NodeFlags mask) const { m_nodeFlags |= mask; } + void clearFlag(NodeFlags mask) const { m_nodeFlags &= ~mask; } + protected: // CreateElementZeroRefCount is deprecated and can be removed once we convert all element // classes to start with a reference count of 1. - enum ConstructionType { CreateContainer, CreateElement, CreateOther, CreateText, CreateElementZeroRefCount }; + enum ConstructionType { + CreateOther = DefaultNodeFlags, + CreateText = DefaultNodeFlags | IsTextFlag, + CreateComment = DefaultNodeFlags | IsCommentFlag, + CreateContainer = DefaultNodeFlags | IsContainerFlag, + CreateElement = CreateContainer | IsElementFlag, + CreateElementZeroRefCount = IsElementFlag | CreateWithZeroRefCountFlag, + CreateStyledElement = CreateElement | IsStyledElementFlag, + CreateStyledElementZeroRefCount = CreateStyledElement | CreateWithZeroRefCountFlag, + CreateHTMLElement = CreateStyledElement | IsHTMLFlag, + CreateHTMLElementZeroRefCount = CreateHTMLElement | CreateWithZeroRefCountFlag, + CreateSVGElement = CreateStyledElement | IsSVGFlag, + CreateSVGElementZeroRefCount = CreateSVGElement | CreateWithZeroRefCountFlag, + }; Node(Document*, ConstructionType); virtual void willMoveToNewOwnerDocument(); @@ -583,19 +685,18 @@ protected: virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const { } void setTabIndexExplicitly(short); - bool hasRareData() const { return m_hasRareData; } -#if ENABLE(SVG) - bool hasRareSVGData() const { return m_hasRareSVGData; } -#endif + bool hasRareData() const { return getFlag(HasRareDataFlag); } NodeRareData* rareData() const; NodeRareData* ensureRareData(); private: +#if USE(JSC) + void markCachedNodeListsSlow(JSC::MarkStack&, JSC::JSGlobalData&); +#endif + static bool initialRefCount(ConstructionType); - static bool isContainer(ConstructionType); - static bool isElement(ConstructionType); - static bool isText(ConstructionType); + void setStyleChange(StyleChangeType); virtual void refEventTarget() { ref(); } virtual void derefEventTarget() { deref(); } @@ -617,45 +718,45 @@ private: Element* ancestorElement() const; void appendTextContent(bool convertBRsToNewlines, StringBuilder&) const; + void trackForDebugging(); Document* m_document; Node* m_previous; Node* m_next; RenderObject* m_renderer; - - unsigned m_styleChange : 2; - bool m_hasId : 1; - bool m_hasClass : 1; - bool m_attached : 1; - bool m_childNeedsStyleRecalc : 1; - bool m_inDocument : 1; - bool m_isLink : 1; - bool m_active : 1; - bool m_hovered : 1; - bool m_inActiveChain : 1; - bool m_inDetach : 1; - bool m_hasRareData : 1; - const bool m_isElement : 1; - const bool m_isContainer : 1; - const bool m_isText : 1; - -protected: - // These bits are used by derived classes, pulled up here so they can - // be stored in the same memory word as the Node bits above. - - bool m_parsingChildrenFinished : 1; // Element - mutable bool m_isStyleAttributeValid : 1; // StyledElement - mutable bool m_synchronizingStyleAttribute : 1; // StyledElement + mutable uint32_t m_nodeFlags; + + protected: + bool isParsingChildrenFinished() const { return getFlag(IsParsingChildrenFinishedFlag); } + void setIsParsingChildrenFinished() { setFlag(IsParsingChildrenFinishedFlag); } + void clearIsParsingChildrenFinished() { clearFlag(IsParsingChildrenFinishedFlag); } + bool isStyleAttributeValid() const { return getFlag(IsStyleAttributeValidFlag); } + void setIsStyleAttributeValid(bool f) { setFlag(f, IsStyleAttributeValidFlag); } + void setIsStyleAttributeValid() const { setFlag(IsStyleAttributeValidFlag); } + void clearIsStyleAttributeValid() { clearFlag(IsStyleAttributeValidFlag); } + bool isSynchronizingStyleAttribute() const { return getFlag(IsSynchronizingStyleAttributeFlag); } + void setIsSynchronizingStyleAttribute(bool f) { setFlag(f, IsSynchronizingStyleAttributeFlag); } + void setIsSynchronizingStyleAttribute() const { setFlag(IsSynchronizingStyleAttributeFlag); } + void clearIsSynchronizingStyleAttribute() const { clearFlag(IsSynchronizingStyleAttributeFlag); } #if ENABLE(SVG) - mutable bool m_areSVGAttributesValid : 1; // Element - mutable bool m_synchronizingSVGAttributes : 1; // SVGElement - bool m_hasRareSVGData : 1; // SVGElement + bool areSVGAttributesValid() const { return getFlag(AreSVGAttributesValidFlag); } + void setAreSVGAttributesValid() const { setFlag(AreSVGAttributesValidFlag); } + void clearAreSVGAttributesValid() { clearFlag(AreSVGAttributesValidFlag); } + bool isSynchronizingSVGAttributes() const { return getFlag(IsSynchronizingSVGAttributesFlag); } + void setIsSynchronizingSVGAttributes() const { setFlag(IsSynchronizingSVGAttributesFlag); } + void clearIsSynchronizingSVGAttributes() const { clearFlag(IsSynchronizingSVGAttributesFlag); } + bool hasRareSVGData() const { return getFlag(HasSVGRareDataFlag); } + void setHasRareSVGData() { setFlag(HasSVGRareDataFlag); } + void clearHasRareSVGData() { clearFlag(HasSVGRareDataFlag); } #endif - - // 10 bits remaining }; +inline bool Node::initialRefCount(ConstructionType type) +{ + return !(type & CreateWithZeroRefCountFlag); +} + // Used in Node::addSubresourceAttributeURLs() and in addSubresourceStyleURLs() inline void addSubresourceURL(ListHashSet<KURL>& urls, const KURL& url) { diff --git a/WebCore/dom/Node.idl b/WebCore/dom/Node.idl index c0f159c..7bc6d1d 100644 --- a/WebCore/dom/Node.idl +++ b/WebCore/dom/Node.idl @@ -62,9 +62,7 @@ module core { readonly attribute Node previousSibling; readonly attribute Node nextSibling; readonly attribute NamedNodeMap attributes; -#if !defined(LANGUAGE_GOBJECT) || !LANGUAGE_GOBJECT readonly attribute Document ownerDocument; -#endif [OldStyleObjC, Custom] Node insertBefore(in [Return] Node newChild, in Node refChild) @@ -136,12 +134,12 @@ module core { #if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C #if !defined(LANGUAGE_GOBJECT) || !LANGUAGE_GOBJECT - [JSCCustom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [JSCCustom] void removeEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); + void addEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); + void removeEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); boolean dispatchEvent(in Event event) raises(EventException); #endif diff --git a/WebCore/dom/NodeFilter.idl b/WebCore/dom/NodeFilter.idl index d721f80..16f3f26 100644 --- a/WebCore/dom/NodeFilter.idl +++ b/WebCore/dom/NodeFilter.idl @@ -43,7 +43,7 @@ module traversal { const unsigned long SHOW_DOCUMENT_FRAGMENT = 0x00000400; const unsigned long SHOW_NOTATION = 0x00000800; - [Custom] short acceptNode(in Node n); + [CallWith=ScriptState] short acceptNode(in Node n); }; diff --git a/WebCore/dom/NodeIterator.idl b/WebCore/dom/NodeIterator.idl index e1818a1..9f59ae1 100644 --- a/WebCore/dom/NodeIterator.idl +++ b/WebCore/dom/NodeIterator.idl @@ -31,9 +31,9 @@ module traversal { readonly attribute Node referenceNode; readonly attribute boolean pointerBeforeReferenceNode; - [Custom] Node nextNode() + [CallWith=ScriptState] Node nextNode() raises (DOMException); - [Custom] Node previousNode() + [CallWith=ScriptState] Node previousNode() raises (DOMException); void detach(); }; diff --git a/WebCore/dom/NodeRareData.h b/WebCore/dom/NodeRareData.h index 6e9d0e4..3d2cf0c 100644 --- a/WebCore/dom/NodeRareData.h +++ b/WebCore/dom/NodeRareData.h @@ -22,11 +22,14 @@ #ifndef NodeRareData_h #define NodeRareData_h +#include "ClassNodeList.h" #include "DynamicNodeList.h" #include "EventListener.h" +#include "NameNodeList.h" +#include "QualifiedName.h" #include "RegisteredEventListener.h" #include "StringHash.h" -#include "QualifiedName.h" +#include "TagNodeList.h" #include <wtf/HashSet.h> #include <wtf/PassOwnPtr.h> #include <wtf/OwnPtr.h> @@ -39,12 +42,14 @@ struct NodeListsNodeData : Noncopyable { RefPtr<DynamicNodeList::Caches> m_childNodeListCaches; - typedef HashMap<String, RefPtr<DynamicNodeList::Caches> > CacheMap; - CacheMap m_classNodeListCaches; - CacheMap m_nameNodeListCaches; + typedef HashMap<String, ClassNodeList*> ClassNodeListCache; + ClassNodeListCache m_classNodeListCache; + + typedef HashMap<String, NameNodeList*> NameNodeListCache; + NameNodeListCache m_nameNodeListCache; - typedef HashMap<QualifiedName, RefPtr<DynamicNodeList::Caches> > TagCacheMap; - TagCacheMap m_tagNodeListCaches; + typedef HashMap<QualifiedName, TagNodeList*> TagNodeListCache; + TagNodeListCache m_tagNodeListCache; static PassOwnPtr<NodeListsNodeData> create() { diff --git a/WebCore/dom/Notation.cpp b/WebCore/dom/Notation.cpp index cade384..4b3ab28 100644 --- a/WebCore/dom/Notation.cpp +++ b/WebCore/dom/Notation.cpp @@ -21,6 +21,8 @@ #include "config.h" #include "Notation.h" +#include "Document.h" + namespace WebCore { Notation::Notation(Document* document, const String& name, const String& publicId, const String& systemId) diff --git a/WebCore/dom/PopStateEvent.idl b/WebCore/dom/PopStateEvent.idl index f9c9a71..28da9e6 100644 --- a/WebCore/dom/PopStateEvent.idl +++ b/WebCore/dom/PopStateEvent.idl @@ -27,11 +27,11 @@ module events { interface PopStateEvent : Event { - [Custom] void initPopStateEvent(in DOMString typeArg, + void initPopStateEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, - in any stateArg); - + in SerializedScriptValue stateArg); + readonly attribute [V8CustomGetter] any state; }; diff --git a/WebCore/dom/Position.cpp b/WebCore/dom/Position.cpp index fa994e3..fdcd7e5 100644 --- a/WebCore/dom/Position.cpp +++ b/WebCore/dom/Position.cpp @@ -986,27 +986,46 @@ static InlineTextBox* searchAheadForBetterMatch(RenderObject* renderer) return 0; } +static Position downstreamIgnoringEditingBoundaries(Position position) +{ + Position lastPosition; + while (position != lastPosition) { + lastPosition = position; + position = position.downstream(Position::CanCrossEditingBoundary); + } + return position; +} + +static Position upstreamIgnoringEditingBoundaries(Position position) +{ + Position lastPosition; + while (position != lastPosition) { + lastPosition = position; + position = position.upstream(Position::CanCrossEditingBoundary); + } + return position; +} + void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDirection, InlineBox*& inlineBox, int& caretOffset) const { caretOffset = m_offset; RenderObject* renderer = node()->renderer(); - + if (!renderer->isText()) { - if (!renderer->isRenderButton() && renderer->isBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(renderer)) { - bool lastPosition = caretOffset == lastOffsetInNode(node()); - Node* startNode = lastPosition ? node()->childNode(caretOffset - 1) : node()->childNode(caretOffset); - while (startNode && (!startNode->renderer() || (startNode->isTextNode() && toRenderText(startNode->renderer())->isAllCollapsibleWhitespace()))) - startNode = (lastPosition)? startNode->previousSibling(): startNode->nextSibling(); - if (startNode) { - Position pos(startNode, 0); - pos = pos.downstream(CanCrossEditingBoundary); - pos.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineBox, caretOffset); - if (lastPosition && inlineBox) - caretOffset = inlineBox->caretMaxOffset(); + inlineBox = 0; + if (canHaveChildrenForEditing(node()) && renderer->isBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(renderer)) { + // Try a visually equivalent position with possibly opposite editability. This helps in case |this| is in + // an editable block but surrounded by non-editable positions. It acts to negate the logic at the beginning + // of RenderObject::createVisiblePosition(). + Position equivalent = downstreamIgnoringEditingBoundaries(*this); + if (equivalent == *this) + equivalent = upstreamIgnoringEditingBoundaries(*this); + if (equivalent == *this) return; - } + + equivalent.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineBox, caretOffset); + return; } - inlineBox = 0; if (renderer->isBox()) { inlineBox = toRenderBox(renderer)->inlineBoxWrapper(); if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset())) diff --git a/WebCore/dom/QualifiedName.cpp b/WebCore/dom/QualifiedName.cpp index 6f5a74f..7cc809f 100644 --- a/WebCore/dom/QualifiedName.cpp +++ b/WebCore/dom/QualifiedName.cpp @@ -78,6 +78,7 @@ void QualifiedName::deref() if (!m_impl) return; #endif + ASSERT(!isHashTableDeletedValue()); if (m_impl->hasOneRef()) gNameCache->remove(m_impl); diff --git a/WebCore/dom/QualifiedName.h b/WebCore/dom/QualifiedName.h index 7581ba1..672a302 100644 --- a/WebCore/dom/QualifiedName.h +++ b/WebCore/dom/QualifiedName.h @@ -58,6 +58,8 @@ public: QualifiedName(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI); QualifiedName(const AtomicString& prefix, const char* localName, const AtomicString& namespaceURI); + QualifiedName(WTF::HashTableDeletedValueType) : m_impl(hashTableDeletedValue()) { } + bool isHashTableDeletedValue() const { return m_impl == hashTableDeletedValue(); } ~QualifiedName() { deref(); } #ifdef QNAME_DEFAULT_CONSTRUCTOR QualifiedName() : m_impl(0) { } @@ -92,6 +94,8 @@ private: void init(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI); void ref() const { m_impl->ref(); } void deref(); + + static QualifiedNameImpl* hashTableDeletedValue() { return RefPtr<QualifiedNameImpl>::hashTableDeletedValue(); } QualifiedNameImpl* m_impl; }; @@ -167,8 +171,8 @@ namespace WTF { template<> struct HashTraits<WebCore::QualifiedName> : GenericHashTraits<WebCore::QualifiedName> { static const bool emptyValueIsZero = false; static WebCore::QualifiedName emptyValue() { return WebCore::QualifiedName(WebCore::nullAtom, WebCore::nullAtom, WebCore::nullAtom); } - static void constructDeletedValue(WebCore::QualifiedName& slot) { new (&slot) WebCore::QualifiedName(WebCore::nullAtom, WebCore::AtomicString(HashTableDeletedValue), WebCore::nullAtom); } - static bool isDeletedValue(const WebCore::QualifiedName& slot) { return slot.localName().isHashTableDeletedValue(); } + static void constructDeletedValue(WebCore::QualifiedName& slot) { new (&slot) WebCore::QualifiedName(WTF::HashTableDeletedValue); } + static bool isDeletedValue(const WebCore::QualifiedName& slot) { return slot.isHashTableDeletedValue(); } }; } diff --git a/WebCore/dom/ScriptExecutionContext.h b/WebCore/dom/ScriptExecutionContext.h index d0f2e26..18e2cd0 100644 --- a/WebCore/dom/ScriptExecutionContext.h +++ b/WebCore/dom/ScriptExecutionContext.h @@ -76,6 +76,7 @@ namespace WebCore { void stopDatabases(DatabaseTaskSynchronizer*); #endif virtual bool isContextThread() const = 0; + virtual bool isJSExecutionTerminated() const = 0; const KURL& url() const { return virtualURL(); } KURL completeURL(const String& url) const { return virtualCompleteURL(url); } diff --git a/WebCore/dom/SelectElement.cpp b/WebCore/dom/SelectElement.cpp index 4af90c9..fb7d9a6 100644 --- a/WebCore/dom/SelectElement.cpp +++ b/WebCore/dom/SelectElement.cpp @@ -529,12 +529,8 @@ static int nextValidIndex(const Vector<Element*>& listItems, int listIndex, Skip } #endif -void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element* element, Event* event, HTMLFormElement* htmlForm) +void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element* element, Event* event) { -#if !ARROW_KEYS_POP_MENU - UNUSED_PARAM(htmlForm); -#endif - if (event->type() == eventNames().keydownEvent) { if (!element->renderer() || !event->isKeyboardEvent()) return; @@ -613,8 +609,6 @@ void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element handled = true; } else if (keyCode == '\r') { menuListOnChange(data, element); - if (htmlForm) - htmlForm->submitClick(event); handled = true; } #else @@ -693,7 +687,7 @@ void SelectElement::updateSelectedState(SelectElementData& data, Element* elemen updateListBoxSelection(data, element, !multiSelect); } -void SelectElement::listBoxDefaultEventHandler(SelectElementData& data, Element* element, Event* event, HTMLFormElement* htmlForm) +void SelectElement::listBoxDefaultEventHandler(SelectElementData& data, Element* element, Event* event) { const Vector<Element*>& listItems = data.listItems(element); @@ -759,29 +753,18 @@ void SelectElement::listBoxDefaultEventHandler(SelectElementData& data, Element* listBoxOnChange(data, element); event->setDefaultHandled(); } - } else if (event->type() == eventNames().keypressEvent) { - if (!event->isKeyboardEvent()) - return; - int keyCode = static_cast<KeyboardEvent*>(event)->keyCode(); - - if (keyCode == '\r') { - if (htmlForm) - htmlForm->submitClick(event); - event->setDefaultHandled(); - return; - } } } -void SelectElement::defaultEventHandler(SelectElementData& data, Element* element, Event* event, HTMLFormElement* htmlForm) +void SelectElement::defaultEventHandler(SelectElementData& data, Element* element, Event* event) { if (!element->renderer()) return; if (data.usesMenuList()) - menuListDefaultEventHandler(data, element, event, htmlForm); + menuListDefaultEventHandler(data, element, event); else - listBoxDefaultEventHandler(data, element, event, htmlForm); + listBoxDefaultEventHandler(data, element, event); if (event->defaultHandled()) return; diff --git a/WebCore/dom/SelectElement.h b/WebCore/dom/SelectElement.h index dcb6879..6db841e 100644 --- a/WebCore/dom/SelectElement.h +++ b/WebCore/dom/SelectElement.h @@ -92,7 +92,7 @@ protected: static void parseMultipleAttribute(SelectElementData&, Element*, MappedAttribute*); static bool appendFormData(SelectElementData&, Element*, FormDataList&); static void reset(SelectElementData&, Element*); - static void defaultEventHandler(SelectElementData&, Element*, Event*, HTMLFormElement* = 0); + static void defaultEventHandler(SelectElementData&, Element*, Event*); static int lastSelectedListIndex(const SelectElementData&, const Element*); static void typeAheadFind(SelectElementData&, Element*, KeyboardEvent*); static void insertedIntoTree(SelectElementData&, Element*); @@ -103,8 +103,8 @@ protected: bool multi, bool shift); private: - static void menuListDefaultEventHandler(SelectElementData&, Element*, Event*, HTMLFormElement*); - static void listBoxDefaultEventHandler(SelectElementData&, Element*, Event*, HTMLFormElement*); + static void menuListDefaultEventHandler(SelectElementData&, Element*, Event*); + static void listBoxDefaultEventHandler(SelectElementData&, Element*, Event*); static void setOptionsChangedOnRenderer(SelectElementData&, Element*); }; diff --git a/WebCore/dom/StyledElement.cpp b/WebCore/dom/StyledElement.cpp index 3607963..cd5f863 100644 --- a/WebCore/dom/StyledElement.cpp +++ b/WebCore/dom/StyledElement.cpp @@ -103,17 +103,12 @@ void StyledElement::removeMappedAttributeDecl(MappedAttributeEntry entryType, co void StyledElement::updateStyleAttribute() const { - ASSERT(!m_isStyleAttributeValid); - m_isStyleAttributeValid = true; - m_synchronizingStyleAttribute = true; + ASSERT(!isStyleAttributeValid()); + setIsStyleAttributeValid(); + setIsSynchronizingStyleAttribute(); if (m_inlineStyleDecl) const_cast<StyledElement*>(this)->setAttribute(styleAttr, m_inlineStyleDecl->cssText()); - m_synchronizingStyleAttribute = false; -} - -StyledElement::StyledElement(const QualifiedName& name, Document* document, ConstructionType type) - : Element(name, document, type) -{ + clearIsSynchronizingStyleAttribute(); } StyledElement::~StyledElement() @@ -208,7 +203,7 @@ bool StyledElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEnt { result = eNone; if (attrName == styleAttr) - return !m_synchronizingStyleAttribute; + return !isSynchronizingStyleAttribute(); return true; } @@ -253,7 +248,7 @@ void StyledElement::parseMappedAttribute(MappedAttribute *attr) destroyInlineStyleDecl(); else getInlineStyleDecl()->parseDeclaration(attr->value()); - m_isStyleAttributeValid = true; + setIsStyleAttributeValid(); setNeedsStyleRecalc(); } } @@ -476,8 +471,8 @@ void StyledElement::copyNonAttributeProperties(const Element *sourceElement) return; *getInlineStyleDecl() = *source->m_inlineStyleDecl; - m_isStyleAttributeValid = source->m_isStyleAttributeValid; - m_synchronizingStyleAttribute = source->m_synchronizingStyleAttribute; + setIsStyleAttributeValid(source->isStyleAttributeValid()); + setIsSynchronizingStyleAttribute(source->isSynchronizingStyleAttribute()); Element::copyNonAttributeProperties(sourceElement); } diff --git a/WebCore/dom/StyledElement.h b/WebCore/dom/StyledElement.h index 52bffd3..279282c 100644 --- a/WebCore/dom/StyledElement.h +++ b/WebCore/dom/StyledElement.h @@ -25,6 +25,7 @@ #ifndef StyledElement_h #define StyledElement_h +#include "CSSMutableStyleDeclaration.h" #include "CSSPrimitiveValue.h" #include "Element.h" #include "MappedAttributeEntry.h" @@ -33,7 +34,6 @@ namespace WebCore { class CSSMappedAttributeDeclaration; -class CSSMutableStyleDeclaration; class MappedAttribute; class StyledElement : public Element { @@ -73,7 +73,10 @@ public: virtual PassRefPtr<Attribute> createAttribute(const QualifiedName&, const AtomicString& value); protected: - StyledElement(const QualifiedName&, Document*, ConstructionType); + StyledElement(const QualifiedName& name, Document* document, ConstructionType type) + : Element(name, document, type) + { + } virtual void attributeChanged(Attribute*, bool preserveDecls = false); virtual void parseMappedAttribute(MappedAttribute*); @@ -89,8 +92,6 @@ protected: virtual void didMoveToNewOwnerDocument(); private: - virtual bool isStyledElement() const { return true; } - void createMappedDecl(MappedAttribute*); void createInlineStyleDecl(); @@ -104,7 +105,7 @@ private: inline void StyledElement::invalidateStyleAttribute() { - m_isStyleAttributeValid = false; + clearIsStyleAttributeValid(); } } //namespace diff --git a/WebCore/dom/TagNodeList.cpp b/WebCore/dom/TagNodeList.cpp index bec9b8e..4914e09 100644 --- a/WebCore/dom/TagNodeList.cpp +++ b/WebCore/dom/TagNodeList.cpp @@ -29,14 +29,19 @@ namespace WebCore { -TagNodeList::TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName, DynamicNodeList::Caches* caches) - : DynamicNodeList(rootNode, caches) +TagNodeList::TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName) + : DynamicNodeList(rootNode) , m_namespaceURI(namespaceURI) , m_localName(localName) { ASSERT(m_namespaceURI.isNull() || !m_namespaceURI.isEmpty()); } +TagNodeList::~TagNodeList() +{ + m_rootNode->removeCachedTagNodeList(this, QualifiedName(nullAtom, m_localName, m_namespaceURI)); +} + bool TagNodeList::nodeMatches(Element* testNode) const { if (m_namespaceURI != starAtom && m_namespaceURI != testNode->namespaceURI()) diff --git a/WebCore/dom/TagNodeList.h b/WebCore/dom/TagNodeList.h index 0031bad..1b1a038 100644 --- a/WebCore/dom/TagNodeList.h +++ b/WebCore/dom/TagNodeList.h @@ -32,13 +32,15 @@ namespace WebCore { // NodeList that limits to a particular tag. class TagNodeList : public DynamicNodeList { public: - static PassRefPtr<TagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName, DynamicNodeList::Caches* caches) + static PassRefPtr<TagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName) { - return adoptRef(new TagNodeList(rootNode, namespaceURI, localName, caches)); + return adoptRef(new TagNodeList(rootNode, namespaceURI, localName)); } + virtual ~TagNodeList(); + private: - TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName, DynamicNodeList::Caches* caches); + TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName); virtual bool nodeMatches(Element*) const; diff --git a/WebCore/dom/Text.cpp b/WebCore/dom/Text.cpp index cf98817..14da1a4 100644 --- a/WebCore/dom/Text.cpp +++ b/WebCore/dom/Text.cpp @@ -41,11 +41,6 @@ using namespace std; namespace WebCore { -Text::Text(Document* document, const String& data) - : CharacterData(document, data, CreateText) -{ -} - PassRefPtr<Text> Text::create(Document* document, const String& data) { return adoptRef(new Text(document, data)); diff --git a/WebCore/dom/Text.h b/WebCore/dom/Text.h index 4722736..45678ef 100644 --- a/WebCore/dom/Text.h +++ b/WebCore/dom/Text.h @@ -44,7 +44,10 @@ public: virtual void attach(); protected: - Text(Document*, const String&); + Text(Document* document, const String& data) + : CharacterData(document, data, CreateText) + { + } private: virtual String nodeName() const; diff --git a/WebCore/dom/Tokenizer.h b/WebCore/dom/Tokenizer.h index 9a9b7b3..939ac70 100644 --- a/WebCore/dom/Tokenizer.h +++ b/WebCore/dom/Tokenizer.h @@ -25,6 +25,7 @@ namespace WebCore { + class HTMLTokenizer; class SegmentedString; class XSSAuditor; @@ -57,6 +58,7 @@ namespace WebCore { virtual void executeScriptsWaitingForStylesheets() {} virtual bool isHTMLTokenizer() const { return false; } + virtual HTMLTokenizer* asHTMLTokenizer() { return 0; } XSSAuditor* xssAuditor() const { return m_XSSAuditor; } void setXSSAuditor(XSSAuditor* auditor) { m_XSSAuditor = auditor; } diff --git a/WebCore/bindings/v8/custom/V8NodeFilterCustom.cpp b/WebCore/dom/TreeDepthLimit.h index 7bb640b..e78e093 100644 --- a/WebCore/bindings/v8/custom/V8NodeFilterCustom.cpp +++ b/WebCore/dom/TreeDepthLimit.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2009 Google Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,21 +28,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "V8NodeFilter.h" +#ifndef TreeDepthLimit_h +#define TreeDepthLimit_h -#include "ExceptionCode.h" -#include "NodeFilter.h" +#ifndef MAX_DOM_TREE_DEPTH +#define MAX_DOM_TREE_DEPTH 5000 +#endif +const unsigned maxDOMTreeDepth = MAX_DOM_TREE_DEPTH; -#include "V8Binding.h" -#include "V8Proxy.h" +#endif // TreeDepthLimit.h -namespace WebCore { - -v8::Handle<v8::Value> V8NodeFilter::acceptNodeCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.NodeFilter.acceptNode()"); - return throwError(NOT_SUPPORTED_ERR); -} - -} // namespace WebCore diff --git a/WebCore/dom/TreeWalker.idl b/WebCore/dom/TreeWalker.idl index f591128..890e315 100644 --- a/WebCore/dom/TreeWalker.idl +++ b/WebCore/dom/TreeWalker.idl @@ -31,13 +31,13 @@ module traversal { attribute Node currentNode setter raises(DOMException); - [Custom] Node parentNode(); - [Custom] Node firstChild(); - [Custom] Node lastChild(); - [Custom] Node previousSibling(); - [Custom] Node nextSibling(); - [Custom] Node previousNode(); - [Custom] Node nextNode(); + [CallWith=ScriptState] Node parentNode(); + [CallWith=ScriptState] Node firstChild(); + [CallWith=ScriptState] Node lastChild(); + [CallWith=ScriptState] Node previousSibling(); + [CallWith=ScriptState] Node nextSibling(); + [CallWith=ScriptState] Node previousNode(); + [CallWith=ScriptState] Node nextNode(); }; } diff --git a/WebCore/dom/XMLTokenizer.cpp b/WebCore/dom/XMLTokenizer.cpp index 818dacd..1d98dfe 100644 --- a/WebCore/dom/XMLTokenizer.cpp +++ b/WebCore/dom/XMLTokenizer.cpp @@ -50,6 +50,7 @@ #include "ScriptSourceCode.h" #include "ScriptValue.h" #include "TextResourceDecoder.h" +#include "TreeDepthLimit.h" #include <wtf/text/CString.h> #include <wtf/StringExtras.h> #include <wtf/Threading.h> @@ -67,7 +68,6 @@ namespace WebCore { using namespace HTMLNames; const int maxErrors = 25; -const size_t maxNestingDepth = 4096; #if ENABLE(WML) bool XMLTokenizer::isWMLDocument() const @@ -87,7 +87,7 @@ void XMLTokenizer::pushCurrentNode(Node* n) n->ref(); m_currentNodeStack.append(m_currentNode); m_currentNode = n; - if (m_currentNodeStack.size() > maxNestingDepth) + if (m_currentNodeStack.size() > maxDOMTreeDepth) handleError(fatal, "Excessive node nesting.", lineNumber(), columnNumber()); } diff --git a/WebCore/editing/EditCommand.cpp b/WebCore/editing/EditCommand.cpp index 2301c54..db447a5 100644 --- a/WebCore/editing/EditCommand.cpp +++ b/WebCore/editing/EditCommand.cpp @@ -62,7 +62,7 @@ void EditCommand::apply() Frame* frame = m_document->frame(); - if (!m_parent) { + if (isTopLevelCommand()) { if (!endingSelection().isContentRichlyEditable()) { switch (editingAction()) { case EditActionTyping: @@ -83,7 +83,7 @@ void EditCommand::apply() // require a layout, as in <rdar://problem/5658603>. Low level operations, like // RemoveNodeCommand, don't require a layout because the high level operations that // use them perform one if one is necessary (like for the creation of VisiblePositions). - if (!m_parent) + if (isTopLevelCommand()) updateLayout(); DeleteButtonController* deleteButtonController = frame->editor()->deleteButtonController(); @@ -91,8 +91,7 @@ void EditCommand::apply() doApply(); deleteButtonController->enable(); - if (!m_parent) { - updateLayout(); + if (isTopLevelCommand()) { // Only need to call appliedEditing for top-level commands, and TypingCommands do it on their // own (see TypingCommand::typingAddedToOpenCommand). if (!isTypingCommand()) @@ -111,7 +110,7 @@ void EditCommand::unapply() // require a layout, as in <rdar://problem/5658603>. Low level operations, like // RemoveNodeCommand, don't require a layout because the high level operations that // use them perform one if one is necessary (like for the creation of VisiblePositions). - if (!m_parent) + if (isTopLevelCommand()) updateLayout(); DeleteButtonController* deleteButtonController = frame->editor()->deleteButtonController(); @@ -119,10 +118,8 @@ void EditCommand::unapply() doUnapply(); deleteButtonController->enable(); - if (!m_parent) { - updateLayout(); + if (isTopLevelCommand()) frame->editor()->unappliedEditing(this); - } } void EditCommand::reapply() @@ -136,7 +133,7 @@ void EditCommand::reapply() // require a layout, as in <rdar://problem/5658603>. Low level operations, like // RemoveNodeCommand, don't require a layout because the high level operations that // use them perform one if one is necessary (like for the creation of VisiblePositions). - if (!m_parent) + if (isTopLevelCommand()) updateLayout(); DeleteButtonController* deleteButtonController = frame->editor()->deleteButtonController(); @@ -144,10 +141,8 @@ void EditCommand::reapply() doReapply(); deleteButtonController->enable(); - if (!m_parent) { - updateLayout(); + if (isTopLevelCommand()) frame->editor()->reappliedEditing(this); - } } void EditCommand::doReapply() diff --git a/WebCore/editing/EditCommand.h b/WebCore/editing/EditCommand.h index 7dc4d92..e50e88d 100644 --- a/WebCore/editing/EditCommand.h +++ b/WebCore/editing/EditCommand.h @@ -57,6 +57,8 @@ public: virtual bool isTypingCommand() const; virtual bool preservesTypingStyle() const; + + bool isTopLevelCommand() const { return !m_parent; } protected: EditCommand(Document*); diff --git a/WebCore/editing/Editor.cpp b/WebCore/editing/Editor.cpp index e171ac1..be89846 100644 --- a/WebCore/editing/Editor.cpp +++ b/WebCore/editing/Editor.cpp @@ -867,6 +867,8 @@ static void dispatchEditableContentChangedEvents(const EditCommand& command) void Editor::appliedEditing(PassRefPtr<EditCommand> cmd) { + m_frame->document()->updateLayout(); + dispatchEditableContentChangedEvents(*cmd); VisibleSelection newSelection(cmd->endingSelection()); @@ -891,6 +893,8 @@ void Editor::appliedEditing(PassRefPtr<EditCommand> cmd) void Editor::unappliedEditing(PassRefPtr<EditCommand> cmd) { + m_frame->document()->updateLayout(); + dispatchEditableContentChangedEvents(*cmd); VisibleSelection newSelection(cmd->startingSelection()); @@ -904,6 +908,8 @@ void Editor::unappliedEditing(PassRefPtr<EditCommand> cmd) void Editor::reappliedEditing(PassRefPtr<EditCommand> cmd) { + m_frame->document()->updateLayout(); + dispatchEditableContentChangedEvents(*cmd); VisibleSelection newSelection(cmd->endingSelection()); diff --git a/WebCore/editing/EditorCommand.cpp b/WebCore/editing/EditorCommand.cpp index 34fa46d..4cb34ac 100644 --- a/WebCore/editing/EditorCommand.cpp +++ b/WebCore/editing/EditorCommand.cpp @@ -1069,6 +1069,21 @@ static bool supportedFromMenuOrKeyBinding(Frame*, EditorCommandSource source) return source == CommandFromMenuOrKeyBinding; } +static bool supportedCopyCut(Frame* frame, EditorCommandSource source) +{ + switch (source) { + case CommandFromMenuOrKeyBinding: + return true; + case CommandFromDOM: + case CommandFromDOMWithUserInterface: { + Settings* settings = frame ? frame->settings() : 0; + return settings && settings->javaScriptCanAccessClipboard(); + } + } + ASSERT_NOT_REACHED(); + return false; +} + static bool supportedPaste(Frame* frame, EditorCommandSource source) { switch (source) { @@ -1077,7 +1092,7 @@ static bool supportedPaste(Frame* frame, EditorCommandSource source) case CommandFromDOM: case CommandFromDOMWithUserInterface: { Settings* settings = frame ? frame->settings() : 0; - return settings && settings->isDOMPasteAllowed(); + return settings && (settings->javaScriptCanAccessClipboard() ? settings->isDOMPasteAllowed() : 0); } } ASSERT_NOT_REACHED(); @@ -1304,9 +1319,9 @@ static const CommandMap& createCommandMap() { "BackColor", { executeBackColor, supported, enabledInRichlyEditableText, stateNone, valueBackColor, notTextInsertion, doNotAllowExecutionWhenDisabled } }, { "BackwardDelete", { executeDeleteBackward, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } }, // FIXME: remove BackwardDelete when Safari for Windows stops using it. { "Bold", { executeToggleBold, supported, enabledInRichlyEditableText, stateBold, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } }, - { "Copy", { executeCopy, supported, enabledCopy, stateNone, valueNull, notTextInsertion, allowExecutionWhenDisabled } }, + { "Copy", { executeCopy, supportedCopyCut, enabledCopy, stateNone, valueNull, notTextInsertion, allowExecutionWhenDisabled } }, { "CreateLink", { executeCreateLink, supported, enabledInRichlyEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } }, - { "Cut", { executeCut, supported, enabledCut, stateNone, valueNull, notTextInsertion, allowExecutionWhenDisabled } }, + { "Cut", { executeCut, supportedCopyCut, enabledCut, stateNone, valueNull, notTextInsertion, allowExecutionWhenDisabled } }, { "Delete", { executeDelete, supported, enabledDelete, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } }, { "DeleteBackward", { executeDeleteBackward, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } }, { "DeleteBackwardByDecomposingPreviousCharacter", { executeDeleteBackwardByDecomposingPreviousCharacter, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } }, diff --git a/WebCore/editing/TextIterator.cpp b/WebCore/editing/TextIterator.cpp index e022e3b..f3bd9df 100644 --- a/WebCore/editing/TextIterator.cpp +++ b/WebCore/editing/TextIterator.cpp @@ -254,27 +254,12 @@ TextIterator::TextIterator() , m_textCharacters(0) , m_textLength(0) , m_lastCharacter(0) - , m_emitCharactersBetweenAllVisiblePositions(false) - , m_enterTextControls(false) + , m_emitsCharactersBetweenAllVisiblePositions(false) + , m_entersTextControls(false) , m_emitsTextWithoutTranscoding(false) { } -TextIterator::TextIterator(const Range* r, bool emitCharactersBetweenAllVisiblePositions, bool enterTextControls) - : m_startContainer(0) - , m_startOffset(0) - , m_endContainer(0) - , m_endOffset(0) - , m_positionNode(0) - , m_textCharacters(0) - , m_textLength(0) - , m_emitCharactersBetweenAllVisiblePositions(emitCharactersBetweenAllVisiblePositions) - , m_enterTextControls(enterTextControls) - , m_emitsTextWithoutTranscoding(false) -{ - init(r); -} - TextIterator::TextIterator(const Range* r, TextIteratorBehavior behavior) : m_startContainer(0) , m_startOffset(0) @@ -283,14 +268,9 @@ TextIterator::TextIterator(const Range* r, TextIteratorBehavior behavior) , m_positionNode(0) , m_textCharacters(0) , m_textLength(0) - , m_emitCharactersBetweenAllVisiblePositions(behavior & TextIteratorBehaviorEmitCharactersBetweenAllVisiblePositions) - , m_enterTextControls(behavior & TextIteratorBehaviorEnterTextControls) - , m_emitsTextWithoutTranscoding(behavior & TextIteratorBehaviorEmitsTextsWithoutTranscoding) -{ - init(r); -} - -void TextIterator::init(const Range* r) + , m_emitsCharactersBetweenAllVisiblePositions(behavior & TextIteratorEmitsCharactersBetweenAllVisiblePositions) + , m_entersTextControls(behavior & TextIteratorEntersTextControls) + , m_emitsTextWithoutTranscoding(behavior & TextIteratorEmitsTextsWithoutTranscoding) { if (!r) return; @@ -326,11 +306,11 @@ void TextIterator::init(const Range* r) m_pastEndNode = nextInPreOrderCrossingShadowBoundaries(endContainer, endOffset); // initialize node processing state - m_needAnotherNewline = false; + m_needsAnotherNewline = false; m_textBox = 0; // initialize record of previous node processing - m_haveEmitted = false; + m_hasEmitted = false; m_lastTextNode = 0; m_lastTextNodeEndedWithCollapsedSpace = false; m_lastCharacter = 0; @@ -351,16 +331,16 @@ void TextIterator::advance() m_textLength = 0; // handle remembered node that needed a newline after the text node's newline - if (m_needAnotherNewline) { + if (m_needsAnotherNewline) { // Emit the extra newline, and position it *inside* m_node, after m_node's // contents, in case it's a block, in the same way that we position the first // newline. The range for the emitted newline should start where the line // break begins. // FIXME: It would be cleaner if we emitted two newlines during the last - // iteration, instead of using m_needAnotherNewline. + // iteration, instead of using m_needsAnotherNewline. Node* baseNode = m_node->lastChild() ? m_node->lastChild() : m_node; emitCharacter('\n', baseNode->parentNode(), baseNode, 1, 1); - m_needAnotherNewline = false; + m_needsAnotherNewline = false; return; } @@ -494,7 +474,7 @@ bool TextIterator::handleTextNode() m_sortedTextBoxesPosition = 0; } - m_textBox = renderer->containsReversedText() ? m_sortedTextBoxes[0] : renderer->firstTextBox(); + m_textBox = renderer->containsReversedText() ? (m_sortedTextBoxes.isEmpty() ? 0 : m_sortedTextBoxes[0]) : renderer->firstTextBox(); handleTextBox(); return true; } @@ -585,7 +565,7 @@ bool TextIterator::handleReplacedElement() return false; } - if (m_enterTextControls && renderer->isTextControl()) { + if (m_entersTextControls && renderer->isTextControl()) { if (HTMLElement* innerTextElement = toRenderTextControl(renderer)->innerTextElement()) { m_node = innerTextElement->shadowTreeRootNode(); pushFullyClippedState(m_fullyClippedStack, m_node); @@ -594,9 +574,9 @@ bool TextIterator::handleReplacedElement() } } - m_haveEmitted = true; + m_hasEmitted = true; - if (m_emitCharactersBetweenAllVisiblePositions) { + if (m_emitsCharactersBetweenAllVisiblePositions) { // We want replaced elements to behave like punctuation for boundary // finding, and to simply take up space for the selection preservation // code in moveParagraphs, so we use a comma. @@ -758,7 +738,7 @@ static int maxOffsetIncludingCollapsedSpaces(Node* node) // Whether or not we should emit a character as we enter m_node (if it's a container) or as we hit it (if it's atomic). bool TextIterator::shouldRepresentNodeOffsetZero() { - if (m_emitCharactersBetweenAllVisiblePositions && m_node->renderer() && m_node->renderer()->isTable()) + if (m_emitsCharactersBetweenAllVisiblePositions && m_node->renderer() && m_node->renderer()->isTable()) return true; // Leave element positioned flush with start of a paragraph @@ -767,7 +747,7 @@ bool TextIterator::shouldRepresentNodeOffsetZero() return false; // Otherwise, show the position if we have emitted any characters - if (m_haveEmitted) + if (m_hasEmitted) return true; // We've not emitted anything yet. Generally, there is no need for any positioning then. @@ -789,7 +769,7 @@ bool TextIterator::shouldRepresentNodeOffsetZero() // If we started as m_startContainer offset 0 and the current node is a descendant of // the start container, we already had enough context to correctly decide whether to - // emit after a preceding block. We chose not to emit (m_haveEmitted is false), + // emit after a preceding block. We chose not to emit (m_hasEmitted is false), // so don't second guess that now. // NOTE: Is this really correct when m_node is not a leftmost descendant? Probably // immaterial since we likely would have already emitted something by now. @@ -813,7 +793,7 @@ bool TextIterator::shouldRepresentNodeOffsetZero() bool TextIterator::shouldEmitSpaceBeforeAndAfterNode(Node* node) { - return node->renderer() && node->renderer()->isTable() && (node->renderer()->isInline() || m_emitCharactersBetweenAllVisiblePositions); + return node->renderer() && node->renderer()->isTable() && (node->renderer()->isInline() || m_emitsCharactersBetweenAllVisiblePositions); } void TextIterator::representNodeOffsetZero() @@ -840,7 +820,7 @@ bool TextIterator::handleNonTextNode() { if (shouldEmitNewlineForNode(m_node)) emitCharacter('\n', m_node->parentNode(), m_node, 0, 1); - else if (m_emitCharactersBetweenAllVisiblePositions && m_node->renderer() && m_node->renderer()->isHR()) + else if (m_emitsCharactersBetweenAllVisiblePositions && m_node->renderer() && m_node->renderer()->isHR()) emitCharacter(' ', m_node->parentNode(), m_node, 0, 1); else representNodeOffsetZero(); @@ -851,10 +831,10 @@ bool TextIterator::handleNonTextNode() void TextIterator::exitNode() { // prevent emitting a newline when exiting a collapsed block at beginning of the range - // FIXME: !m_haveEmitted does not necessarily mean there was a collapsed block... it could + // FIXME: !m_hasEmitted does not necessarily mean there was a collapsed block... it could // have been an hr (e.g.). Also, a collapsed block could have height (e.g. a table) and // therefore look like a blank line. - if (!m_haveEmitted) + if (!m_hasEmitted) return; // Emit with a position *inside* m_node, after m_node's contents, in @@ -875,8 +855,8 @@ void TextIterator::exitNode() // insert a newline with a position following this block's contents. emitCharacter('\n', baseNode->parentNode(), baseNode, 1, 1); // remember whether to later add a newline for the current node - ASSERT(!m_needAnotherNewline); - m_needAnotherNewline = addNewline; + ASSERT(!m_needsAnotherNewline); + m_needsAnotherNewline = addNewline; } else if (addNewline) // insert a newline with a position following this block's contents. emitCharacter('\n', baseNode->parentNode(), baseNode, 1, 1); @@ -889,7 +869,7 @@ void TextIterator::exitNode() void TextIterator::emitCharacter(UChar c, Node* textNode, Node* offsetBaseNode, int textStartOffset, int textEndOffset) { - m_haveEmitted = true; + m_hasEmitted = true; // remember information with which to construct the TextIterator::range() // NOTE: textNode is often not a text node, so the range will specify child nodes of positionNode @@ -911,19 +891,19 @@ void TextIterator::emitCharacter(UChar c, Node* textNode, Node* offsetBaseNode, void TextIterator::emitText(Node* textNode, int textStartOffset, int textEndOffset) { RenderText* renderer = toRenderText(m_node->renderer()); - String str = m_emitsTextWithoutTranscoding ? renderer->textWithoutTranscoding() : renderer->text(); - ASSERT(str.characters()); + m_text = m_emitsTextWithoutTranscoding ? renderer->textWithoutTranscoding() : renderer->text(); + ASSERT(m_text.characters()); m_positionNode = textNode; m_positionOffsetBaseNode = 0; m_positionStartOffset = textStartOffset; m_positionEndOffset = textEndOffset; - m_textCharacters = str.characters() + textStartOffset; + m_textCharacters = m_text.characters() + textStartOffset; m_textLength = textEndOffset - textStartOffset; - m_lastCharacter = str[textEndOffset - 1]; + m_lastCharacter = m_text[textEndOffset - 1]; m_lastTextNodeEndedWithCollapsedSpace = false; - m_haveEmitted = true; + m_hasEmitted = true; } PassRefPtr<Range> TextIterator::range() const @@ -1174,11 +1154,11 @@ CharacterIterator::CharacterIterator() { } -CharacterIterator::CharacterIterator(const Range* r, bool emitCharactersBetweenAllVisiblePositions, bool enterTextControls) +CharacterIterator::CharacterIterator(const Range* r, TextIteratorBehavior behavior) : m_offset(0) , m_runOffset(0) , m_atBreak(true) - , m_textIterator(r, emitCharactersBetweenAllVisiblePositions, enterTextControls) + , m_textIterator(r, behavior) { while (!atEnd() && m_textIterator.length() == 0) m_textIterator.advance(); @@ -2013,7 +1993,7 @@ size_t SearchBuffer::length() const int TextIterator::rangeLength(const Range* r, bool forSelectionPreservation) { int length = 0; - for (TextIterator it(r, forSelectionPreservation); !it.atEnd(); it.advance()) + for (TextIterator it(r, forSelectionPreservation ? TextIteratorEmitsCharactersBetweenAllVisiblePositions : TextIteratorDefaultBehavior); !it.atEnd(); it.advance()) length += it.length(); return length; @@ -2035,7 +2015,7 @@ PassRefPtr<Range> TextIterator::rangeFromLocationAndLength(Element* scope, int r RefPtr<Range> textRunRange; - TextIterator it(rangeOfContents(scope).get(), forSelectionPreservation); + TextIterator it(rangeOfContents(scope).get(), forSelectionPreservation ? TextIteratorEmitsCharactersBetweenAllVisiblePositions : TextIteratorDefaultBehavior); // FIXME: the atEnd() check shouldn't be necessary, workaround for <http://bugs.webkit.org/show_bug.cgi?id=6289>. if (rangeLocation == 0 && rangeLength == 0 && it.atEnd()) { @@ -2138,7 +2118,7 @@ UChar* plainTextToMallocAllocatedBuffer(const Range* r, unsigned& bufferLength, Vector<TextSegment>* textSegments = 0; Vector<UChar> textBuffer; textBuffer.reserveInitialCapacity(cMaxSegmentSize); - for (TextIterator it(r, isDisplayString ? TextIteratorBehaviorDefault : TextIteratorBehaviorEmitsTextsWithoutTranscoding); !it.atEnd(); it.advance()) { + for (TextIterator it(r, isDisplayString ? TextIteratorDefaultBehavior : TextIteratorEmitsTextsWithoutTranscoding); !it.atEnd(); it.advance()) { if (textBuffer.size() && textBuffer.size() + it.length() > cMaxSegmentSize) { UChar* newSegmentBuffer = static_cast<UChar*>(malloc(textBuffer.size() * sizeof(UChar))); if (!newSegmentBuffer) @@ -2258,14 +2238,14 @@ PassRefPtr<Range> findPlainText(const Range* range, const String& target, bool f size_t matchStart; size_t matchLength; { - CharacterIterator findIterator(range, false, true); + CharacterIterator findIterator(range, TextIteratorEntersTextControls); matchLength = findPlainText(findIterator, target, forward, caseSensitive, matchStart); if (!matchLength) return collapsedToBoundary(range, forward); } // Then, find the document position of the start and the end of the text. - CharacterIterator computeRangeIterator(range, false, true); + CharacterIterator computeRangeIterator(range, TextIteratorEntersTextControls); return characterSubrange(computeRangeIterator, matchStart, matchLength); } diff --git a/WebCore/editing/TextIterator.h b/WebCore/editing/TextIterator.h index abd8161..ba381b9 100644 --- a/WebCore/editing/TextIterator.h +++ b/WebCore/editing/TextIterator.h @@ -69,17 +69,16 @@ private: // chunks so as to optimize for performance of the iteration. enum TextIteratorBehavior { - TextIteratorBehaviorDefault = 0, - TextIteratorBehaviorEmitCharactersBetweenAllVisiblePositions = 1 << 0, - TextIteratorBehaviorEnterTextControls = 1 << 1, - TextIteratorBehaviorEmitsTextsWithoutTranscoding = 1 << 2, + TextIteratorDefaultBehavior = 0, + TextIteratorEmitsCharactersBetweenAllVisiblePositions = 1 << 0, + TextIteratorEntersTextControls = 1 << 1, + TextIteratorEmitsTextsWithoutTranscoding = 1 << 2, }; class TextIterator { public: TextIterator(); - explicit TextIterator(const Range*, bool emitCharactersBetweenAllVisiblePositions = false, bool enterTextControls = false); - TextIterator(const Range*, TextIteratorBehavior); + explicit TextIterator(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior); bool atEnd() const { return !m_positionNode; } void advance(); @@ -95,7 +94,6 @@ public: static PassRefPtr<Range> subrange(Range* entireRange, int characterOffset, int characterCount); private: - void init(const Range*); void exitNode(); bool shouldRepresentNodeOffsetZero(); bool shouldEmitSpaceBeforeAndAfterNode(Node*); @@ -129,10 +127,12 @@ private: mutable int m_positionEndOffset; const UChar* m_textCharacters; int m_textLength; - + // Hold string m_textCharacters points to so we ensure it won't be deleted. + String m_text; + // Used when there is still some pending text from the current node; when these // are false and 0, we go back to normal iterating. - bool m_needAnotherNewline; + bool m_needsAnotherNewline; InlineTextBox* m_textBox; // Used to do the whitespace collapsing logic. @@ -148,14 +148,14 @@ private: size_t m_sortedTextBoxesPosition; // Used when deciding whether to emit a "positioning" (e.g. newline) before any other content - bool m_haveEmitted; + bool m_hasEmitted; // Used by selection preservation code. There should be one character emitted between every VisiblePosition // in the Range used to create the TextIterator. // FIXME <rdar://problem/6028818>: This functionality should eventually be phased out when we rewrite // moveParagraphs to not clone/destroy moved content. - bool m_emitCharactersBetweenAllVisiblePositions; - bool m_enterTextControls; + bool m_emitsCharactersBetweenAllVisiblePositions; + bool m_entersTextControls; // Used when we want texts for copying, pasting, and transposing. bool m_emitsTextWithoutTranscoding; @@ -222,7 +222,7 @@ private: class CharacterIterator { public: CharacterIterator(); - explicit CharacterIterator(const Range*, bool emitCharactersBetweenAllVisiblePositions = false, bool enterTextControls = false); + explicit CharacterIterator(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior); void advance(int numCharacters); diff --git a/WebCore/editing/VisibleSelection.cpp b/WebCore/editing/VisibleSelection.cpp index 6784631..4037670 100644 --- a/WebCore/editing/VisibleSelection.cpp +++ b/WebCore/editing/VisibleSelection.cpp @@ -226,7 +226,7 @@ void VisibleSelection::appendTrailingWhitespace() if (!searchRange) return; - CharacterIterator charIt(searchRange.get(), true); + CharacterIterator charIt(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions); for (; charIt.length(); charIt.advance(1)) { UChar c = charIt.characters()[0]; @@ -481,10 +481,8 @@ void VisibleSelection::adjustSelectionToAvoidCrossingEditingBoundaries() if (endRoot != baseRoot) { VisiblePosition last = lastEditablePositionBeforePositionInRoot(m_end, baseRoot); m_end = last.deepEquivalent(); - if (m_end.isNull()) { - ASSERT_NOT_REACHED(); + if (m_end.isNull()) m_end = m_start; - } } // The selection is based in non-editable content. } else { diff --git a/WebCore/editing/qt/SmartReplaceQt.cpp b/WebCore/editing/qt/SmartReplaceQt.cpp new file mode 100644 index 0000000..1436afe --- /dev/null +++ b/WebCore/editing/qt/SmartReplaceQt.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2010 Robert Hogan <robert@roberthogan.net>. All rights reserved. + * Copyright (C) 2007,2008,2009 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. + */ + +#include "config.h" +#include "SmartReplace.h" + +namespace WebCore { + +bool isCharacterSmartReplaceExempt(UChar32 c, bool isPreviousCharacter) +{ + QChar d(c); + if (d.isSpace()) + return true; + if (!isPreviousCharacter && d.isPunct()) + return true; + + if ((c >= 0x1100 && c <= (0x1100 + 256)) // Hangul Jamo (0x1100 - 0x11FF) + || (c >= 0x2E80 && c <= (0x2E80 + 352)) // CJK & Kangxi Radicals (0x2E80 - 0x2FDF) + || (c >= 0x2FF0 && c <= (0x2FF0 + 464)) // Ideograph Deseriptions, CJK Symbols, Hiragana, Katakana, Bopomofo, Hangul Compatibility Jamo, Kanbun, & Bopomofo Ext (0x2FF0 - 0x31BF) + || (c >= 0x3200 && c <= (0x3200 + 29392)) // Enclosed CJK, CJK Ideographs (Uni Han & Ext A), & Yi (0x3200 - 0xA4CF) + || (c >= 0xAC00 && c <= (0xAC00 + 11183)) // Hangul Syllables (0xAC00 - 0xD7AF) + || (c >= 0xF900 && c <= (0xF900 + 352)) // CJK Compatibility Ideographs (0xF900 - 0xFA5F) + || (c >= 0xFE30 && c <= (0xFE30 + 32)) // CJK Compatibility From (0xFE30 - 0xFE4F) + || (c >= 0xFF00 && c <= (0xFF00 + 240)) // Half/Full Width Form (0xFF00 - 0xFFEF) + || (c >= 0x20000 && c <= (0x20000 + 0xA6D7)) // CJK Ideograph Exntension B + || (c >= 0x2F800 && c <= (0x2F800 + 0x021E))) // CJK Compatibility Ideographs (0x2F800 - 0x2FA1D) + return true; + + const char prev[] = "([\"\'#$/-`{\0"; + const char next[] = ")].,;:?\'!\"%*-/}\0"; + const char* str = (isPreviousCharacter) ? prev : next; + for (int i = 0; i < strlen(str); ++i) { + if (str[i] == c) + return true; + } + + return false; +} + +} diff --git a/WebCore/editing/visible_units.cpp b/WebCore/editing/visible_units.cpp index 3d85ad1..c094aac 100644 --- a/WebCore/editing/visible_units.cpp +++ b/WebCore/editing/visible_units.cpp @@ -207,7 +207,7 @@ static VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunc searchRange->selectNodeContents(boundary, ec); searchRange->setStart(start.node(), start.deprecatedEditingOffset(), ec); - TextIterator it(searchRange.get(), true); + TextIterator it(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions); unsigned next = 0; bool inTextSecurityMode = start.node() && start.node()->renderer() && start.node()->renderer()->style()->textSecurity() != TSNONE; bool needMoreContext = false; @@ -238,7 +238,7 @@ static VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunc pos = it.range()->startPosition(); } else if (next != prefixLength) { // Use the character iterator to translate the next value into a DOM position. - CharacterIterator charIt(searchRange.get(), true); + CharacterIterator charIt(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions); charIt.advance(next - prefixLength - 1); pos = charIt.range()->endPosition(); diff --git a/WebCore/bindings/v8/custom/V8DatabaseCallback.h b/WebCore/html/FileError.h index 064a9a7..8190883 100644 --- a/WebCore/bindings/v8/custom/V8DatabaseCallback.h +++ b/WebCore/html/FileError.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,41 +28,33 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef V8DatabaseCallback_h -#define V8DatabaseCallback_h +#ifndef FileError_h +#define FileError_h -#if ENABLE(DATABASE) +#if ENABLE(FILE_READER) || ENABLE(FILE_WRITER) -#include "DatabaseCallback.h" -#include "WorldContextHandle.h" -#include <v8.h> -#include <wtf/Forward.h> +#include "ExceptionCode.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> namespace WebCore { -class Frame; - -class V8DatabaseCallback : public DatabaseCallback { +class FileError : public RefCounted<FileError> { public: - static PassRefPtr<V8DatabaseCallback> create(v8::Local<v8::Value> value, Frame* frame) - { - ASSERT(value->IsObject()); - return adoptRef(new V8DatabaseCallback(value->ToObject(), frame)); - } - virtual ~V8DatabaseCallback(); + static PassRefPtr<FileError> create(ExceptionCode code) { return adoptRef(new FileError(code)); } - virtual void handleEvent(ScriptExecutionContext*, Database*); + ExceptionCode code() const { return m_code; } private: - V8DatabaseCallback(v8::Local<v8::Object>, Frame*); + FileError(ExceptionCode code) + : m_code(code) + { } - v8::Persistent<v8::Object> m_callback; - RefPtr<Frame> m_frame; - WorldContextHandle m_worldContext; + ExceptionCode m_code; }; } // namespace WebCore -#endif +#endif // ENABLE(FILE_READER) || ENABLE(FILE_WRITER) -#endif // V8DatabaseCallback_h +#endif // FileError_h diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.h b/WebCore/html/FileError.idl index 31f53e4..6c2b08c 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.h +++ b/WebCore/html/FileError.idl @@ -1,10 +1,10 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. - * + * Copyright (C) 2010 Google 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: - * + * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above @@ -14,7 +14,7 @@ * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -28,40 +28,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef V8CustomSQLStatementCallback_h -#define V8CustomSQLStatementCallback_h - -#if ENABLE(DATABASE) - -#include "SQLStatementCallback.h" -#include "WorldContextHandle.h" -#include <v8.h> -#include <wtf/Forward.h> - -namespace WebCore { - -class Frame; - -class V8CustomSQLStatementCallback : public SQLStatementCallback { -public: - static PassRefPtr<V8CustomSQLStatementCallback> create(v8::Local<v8::Value> value, Frame* frame) - { - ASSERT(value->IsObject()); - return adoptRef(new V8CustomSQLStatementCallback(value->ToObject(), frame)); - } - virtual ~V8CustomSQLStatementCallback(); - - virtual void handleEvent(ScriptExecutionContext*, SQLTransaction*, SQLResultSet*, bool& raisedException); -private: - V8CustomSQLStatementCallback(v8::Local<v8::Object>, Frame*); - - v8::Persistent<v8::Object> m_callback; - RefPtr<Frame> m_frame; - WorldContextHandle m_worldContext; -}; - -} // namespace WebCore - -#endif - -#endif // V8CustomSQLStatementCallback_h +module html { + interface [ + Conditional=FILE_READER|FILE_WRITER + ] FileError { + const unsigned short NO_MODIFICATION_ALLOWED_ERR = 7; + const unsigned short NOT_FOUND_ERR = 8; + const unsigned short SECURITY_ERR = 18; + const unsigned short ABORT_ERR = 20; + const unsigned short NOT_READABLE_ERR = 24; + const unsigned short ENCODING_ERR = 26; + readonly attribute unsigned short code; + }; +} diff --git a/WebCore/html/FileReader.cpp b/WebCore/html/FileReader.cpp new file mode 100644 index 0000000..69e01ce --- /dev/null +++ b/WebCore/html/FileReader.cpp @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2010 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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" + +#if ENABLE(FILE_READER) + +#include "FileReader.h" + +#include "Base64.h" +#include "Blob.h" +#include "File.h" +#include "FileStreamProxy.h" +#include "Logging.h" +#include "ProgressEvent.h" +#include "ScriptExecutionContext.h" +#include <wtf/CurrentTime.h> + +namespace WebCore { + +const unsigned bufferSize = 1024; +const double progressNotificationIntervalMS = 50; + +FileReader::FileReader(ScriptExecutionContext* context) + : ActiveDOMObject(context, this) + , m_state(Empty) + , m_readType(ReadFileAsBinaryString) + , m_result("") + , m_isRawDataConverted(false) + , m_bytesLoaded(0) + , m_totalBytes(0) + , m_lastProgressNotificationTimeMS(0) + , m_alreadyStarted(false) +{ + m_buffer.resize(bufferSize); +} + +FileReader::~FileReader() +{ + terminate(); +} + +bool FileReader::hasPendingActivity() const +{ + return m_state == Loading || ActiveDOMObject::hasPendingActivity(); +} + +bool FileReader::canSuspend() const +{ + // FIXME: It is not currently possible to suspend a FileReader, so pages with FileReader can not go into page cache. + return false; +} + +void FileReader::stop() +{ + terminate(); +} + +void FileReader::readAsBinaryString(Blob* fileBlob) +{ + LOG(FileAPI, "FileReader: reading as binary: %s\n", fileBlob->path().utf8().data()); + + readInternal(fileBlob, ReadFileAsBinaryString); +} + +void FileReader::readAsText(Blob* fileBlob, const String& encoding) +{ + LOG(FileAPI, "FileReader: reading as text: %s\n", fileBlob->path().utf8().data()); + + if (!encoding.isEmpty()) + m_encoding = TextEncoding(encoding); + readInternal(fileBlob, ReadFileAsText); +} + +void FileReader::readAsDataURL(File* file) +{ + LOG(FileAPI, "FileReader: reading as data URL: %s\n", file->path().utf8().data()); + + m_fileType = file->type(); + readInternal(file, ReadFileAsDataURL); +} + +void FileReader::readInternal(Blob* fileBlob, ReadType type) +{ + // readAs*** methods() can be called multiple times. Only the last call before the actual reading happens is processed. + if (m_alreadyStarted) + return; + + m_fileBlob = fileBlob; + m_readType = type; + + // When FileStreamProxy is created, FileReader::didStart() will get notified on the File thread and we will start + // opening and reading the file since then. + if (!m_streamProxy.get()) + m_streamProxy = FileStreamProxy::create(scriptExecutionContext(), this); +} + +void FileReader::abort() +{ + LOG(FileAPI, "FileReader: aborting\n"); + + terminate(); + + m_result = ""; + m_error = FileError::create(ABORT_ERR); + + fireEvent(eventNames().errorEvent); + fireEvent(eventNames().abortEvent); + fireEvent(eventNames().loadendEvent); +} + +void FileReader::terminate() +{ + if (m_streamProxy) { + m_streamProxy->stop(); + m_streamProxy = 0; + } + m_state = Done; +} + +void FileReader::didStart() +{ + m_alreadyStarted = true; + m_streamProxy->openForRead(m_fileBlob.get()); +} + +void FileReader::didGetSize(long long size) +{ + m_state = Loading; + fireEvent(eventNames().loadstartEvent); + + m_totalBytes = size; + m_streamProxy->read(&m_buffer.at(0), m_buffer.size()); +} + +void FileReader::didRead(const char* data, int bytesRead) +{ + ASSERT(data && bytesRead); + + // Bail out if we have aborted the reading. + if (m_state == Done) + return; + + switch (m_readType) { + case ReadFileAsBinaryString: + m_result += String(data, static_cast<unsigned>(bytesRead)); + break; + case ReadFileAsText: + case ReadFileAsDataURL: + m_rawData.append(data, static_cast<unsigned>(bytesRead)); + m_isRawDataConverted = false; + break; + default: + ASSERT_NOT_REACHED(); + } + + m_bytesLoaded += bytesRead; + + // Fire the progress event at least every 50ms. + double now = WTF::currentTimeMS(); + if (!m_lastProgressNotificationTimeMS) + m_lastProgressNotificationTimeMS = now; + else if (now - m_lastProgressNotificationTimeMS > progressNotificationIntervalMS) { + fireEvent(eventNames().progressEvent); + m_lastProgressNotificationTimeMS = now; + } + + // Continue reading. + m_streamProxy->read(&m_buffer.at(0), m_buffer.size()); +} + +void FileReader::didFinish() +{ + m_state = Done; + + m_streamProxy->close(); + + fireEvent(eventNames().loadEvent); + fireEvent(eventNames().loadendEvent); +} + +void FileReader::didFail(ExceptionCode ec) +{ + m_state = Done; + m_error = FileError::create(ec); + + m_streamProxy->close(); + + fireEvent(eventNames().errorEvent); + fireEvent(eventNames().loadendEvent); +} + +void FileReader::fireEvent(const AtomicString& type) +{ + // FIXME: the current ProgressEvent uses "unsigned long" for total and loaded attributes. Need to talk with the spec writer to resolve the issue. + dispatchEvent(ProgressEvent::create(type, true, static_cast<unsigned>(m_bytesLoaded), static_cast<unsigned>(m_totalBytes))); +} + +const ScriptString& FileReader::result() +{ + // If reading as binary string, we can return the result immediately. + if (m_readType == ReadFileAsBinaryString) + return m_result; + + // If we already convert the raw data received so far, we can return the result now. + if (m_isRawDataConverted) + return m_result; + m_isRawDataConverted = true; + + if (m_readType == ReadFileAsText) + convertToText(); + // For data URL, we only do the coversion until we receive all the raw data. + else if (m_readType == ReadFileAsDataURL && m_state == Done) + convertToDataURL(); + + return m_result; +} + +void FileReader::convertToText() +{ + if (!m_rawData.size()) { + m_result = ""; + return; + } + + // Try to determine the encoding if it is not provided. + // FIXME: move the following logic to a more generic place. + int offset = 0; + if (!m_encoding.isValid()) { + if (m_rawData.size() >= 2 && m_rawData[0] == '\xFE' && m_rawData[1] == '\xFF') { + offset = 2; + m_encoding = UTF16BigEndianEncoding(); + } else if (m_rawData.size() >= 2 && m_rawData[0] == '\xFF' && m_rawData[1] == '\xFE') { + offset = 2; + m_encoding = UTF16LittleEndianEncoding(); + } else if (m_rawData.size() >= 2 && m_rawData[0] == '\xEF' && m_rawData[1] == '\xBB' && m_rawData[2] == '\xBF') { + offset = 3; + m_encoding = UTF8Encoding(); + } else + m_encoding = UTF8Encoding(); + } + + // Decode the data. + // FIXME: consider supporting incremental decoding to improve the perf. + m_result = m_encoding.decode(&m_rawData.at(0) + offset, m_rawData.size() - offset); +} + +void FileReader::convertToDataURL() +{ + m_result = "data:"; + + if (!m_rawData.size()) + return; + + m_result += m_fileType; + if (!m_fileType.isEmpty()) + m_result += ";"; + m_result += "base64,"; + + Vector<char> out; + base64Encode(m_rawData, out); + out.append('\0'); + m_result += out.data(); +} + +} // namespace WebCore + +#endif // ENABLE(FILE_READER) diff --git a/WebCore/html/FileReader.h b/WebCore/html/FileReader.h new file mode 100644 index 0000000..b30fad7 --- /dev/null +++ b/WebCore/html/FileReader.h @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2010 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 FileReader_h +#define FileReader_h + +#if ENABLE(FILE_READER) + +#include "ActiveDOMObject.h" +#include "EventTarget.h" +#include "FileError.h" +#include "FileStreamClient.h" +#include "PlatformString.h" +#include "ScriptString.h" +#include "TextEncoding.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> +#include <wtf/Vector.h> + +namespace WebCore { + +class Blob; +class File; +class FileStreamProxy; +class ScriptExecutionContext; + +class FileReader : public RefCounted<FileReader>, public ActiveDOMObject, public EventTarget, public FileStreamClient { +public: + static PassRefPtr<FileReader> create(ScriptExecutionContext* context) + { + return adoptRef(new FileReader(context)); + } + + virtual ~FileReader(); + + enum ReadyState { + Empty = 0, + Loading = 1, + Done = 2 + }; + + void readAsBinaryString(Blob*); + void readAsText(Blob*, const String& encoding = ""); + void readAsDataURL(File*); + void abort(); + + ReadyState readyState() const { return m_state; } + PassRefPtr<FileError> error() { return m_error; } + const ScriptString& result(); + + // ActiveDOMObject + virtual bool canSuspend() const; + virtual void stop(); + virtual bool hasPendingActivity() const; + + // EventTarget + virtual FileReader* toFileReader() { return this; } + virtual ScriptExecutionContext* scriptExecutionContext() const { return ActiveDOMObject::scriptExecutionContext(); } + + // FileStreamClient + virtual void didStart(); + virtual void didGetSize(long long); + virtual void didRead(const char*, int); + virtual void didFinish(); + virtual void didFail(ExceptionCode); + + using RefCounted<FileReader>::ref; + using RefCounted<FileReader>::deref; + + DEFINE_ATTRIBUTE_EVENT_LISTENER(loadstart); + DEFINE_ATTRIBUTE_EVENT_LISTENER(progress); + DEFINE_ATTRIBUTE_EVENT_LISTENER(load); + DEFINE_ATTRIBUTE_EVENT_LISTENER(abort); + DEFINE_ATTRIBUTE_EVENT_LISTENER(error); + DEFINE_ATTRIBUTE_EVENT_LISTENER(loadend); + +private: + enum ReadType { + ReadFileAsBinaryString, + ReadFileAsText, + ReadFileAsDataURL + }; + + FileReader(ScriptExecutionContext*); + + // EventTarget + virtual void refEventTarget() { ref(); } + virtual void derefEventTarget() { deref(); } + virtual EventTargetData* eventTargetData() { return &m_eventTargetData; } + virtual EventTargetData* ensureEventTargetData() { return &m_eventTargetData; } + + void terminate(); + void readInternal(Blob*, ReadType); + void fireEvent(const AtomicString& type); + void convertToText(); + void convertToDataURL(); + + ReadyState m_state; + EventTargetData m_eventTargetData; + + RefPtr<Blob> m_fileBlob; + ReadType m_readType; + + // Like XMLHttpRequest.m_responseText, we keep this as a ScriptString, not a WebCore::String. + // That's because these strings can easily get huge (they are filled from the file) and + // because JS can easily observe many intermediate states, so it's very useful to be + // able to share the buffer with JavaScript versions of the whole or partial string. + // In contrast, this string doesn't interact much with the rest of the engine so it's not that + // big a cost that it isn't a String. + ScriptString m_result; + + // The raw data. We have to keep track of all the raw data for it to be converted to text or data URL data. + Vector<char> m_rawData; + bool m_isRawDataConverted; + + // Encoding scheme used to decode the data. + TextEncoding m_encoding; + + // Needed to create data URL. + String m_fileType; + + RefPtr<FileStreamProxy> m_streamProxy; + Vector<char> m_buffer; + RefPtr<FileError> m_error; + long long m_bytesLoaded; + long long m_totalBytes; + double m_lastProgressNotificationTimeMS; + bool m_alreadyStarted; +}; + +} // namespace WebCore + +#endif + +#endif // FileReader_h diff --git a/WebCore/html/FileStream.cpp b/WebCore/html/FileStream.cpp index 84a28d6..7089f61 100644 --- a/WebCore/html/FileStream.cpp +++ b/WebCore/html/FileStream.cpp @@ -42,6 +42,8 @@ namespace WebCore { FileStream::FileStream(FileStreamClient* client) : m_client(client) , m_handle(invalidPlatformFileHandle) + , m_bytesProcessed(0) + , m_totalBytesToRead(0) { } @@ -63,10 +65,56 @@ void FileStream::stop() m_client->didStop(); } -void FileStream::openForRead(Blob*) +void FileStream::openForRead(Blob* blob) { ASSERT(!isMainThread()); - // FIXME: to be implemented. + + if (isHandleValid(m_handle)) + return; + + // Check if the file exists by querying its modification time. We choose not to call fileExists() in order to save an + // extra file system call when the modification time is needed to check the validity of the sliced file blob. + // Per the spec, we need to return different error codes to differentiate between non-existent file and permission error. + // openFile() could not tell use the failure reason. + time_t currentModificationTime; + if (!getFileModificationTime(blob->path(), currentModificationTime)) { + m_client->didFail(NOT_FOUND_ERR); + return; + } + + // Open the file blob. + m_handle = openFile(blob->path(), OpenForRead); + if (!isHandleValid(m_handle)) { + m_client->didFail(NOT_READABLE_ERR); + return; + } + +#if ENABLE(BLOB_SLICE) + // Check the modificationt time for the possible file change. + if (blob->modificationTime() != Blob::doNotCheckFileChange && static_cast<time_t>(blob->modificationTime()) != currentModificationTime) { + m_client->didFail(NOT_READABLE_ERR); + return; + } + + // Jump to the beginning position if the file has been sliced. + if (blob->start() > 0) { + if (!seekFile(m_handle, blob->start(), SeekFromBeginning)) { + m_client->didFail(NOT_READABLE_ERR); + return; + } + } +#endif + + // Get the size. +#if ENABLE(BLOB_SLICE) + m_totalBytesToRead = blob->length(); + if (m_totalBytesToRead == Blob::toEndOfFile) + m_totalBytesToRead = blob->size() - blob->start(); +#else + m_total = blob->size(); +#endif + + m_client->didGetSize(m_totalBytesToRead); } void FileStream::openForWrite(const String&) @@ -78,14 +126,41 @@ void FileStream::openForWrite(const String&) void FileStream::close() { ASSERT(!isMainThread()); - if (isHandleValid(m_handle)) + if (isHandleValid(m_handle)) { closeFile(m_handle); + m_handle = invalidPlatformFileHandle; + } } -void FileStream::read(char*, int) +void FileStream::read(char* buffer, int length) { ASSERT(!isMainThread()); - // FIXME: to be implemented. + + if (!isHandleValid(m_handle)) { + m_client->didFail(NOT_READABLE_ERR); + return; + } + + if (m_bytesProcessed >= m_totalBytesToRead) { + m_client->didFinish(); + return; + } + + long long remaining = m_totalBytesToRead - m_bytesProcessed; + int bytesToRead = (remaining < length) ? static_cast<int>(remaining) : length; + int bytesRead = readFromFile(m_handle, buffer, bytesToRead); + if (bytesRead < 0) { + m_client->didFail(NOT_READABLE_ERR); + return; + } + + if (!bytesRead) { + m_client->didFinish(); + return; + } + + m_bytesProcessed += bytesRead; + m_client->didRead(buffer, bytesRead); } void FileStream::write(Blob*, long long, int) @@ -102,4 +177,4 @@ void FileStream::truncate(long long) } // namespace WebCore -#endif // ENABLE(FILE_WRITER) || ENABLE_FILE_READER) +#endif // ENABLE(FILE_READER) || ENABLE(FILE_WRITER) diff --git a/WebCore/html/FileStream.h b/WebCore/html/FileStream.h index bda8fc7..9d3f7b8 100644 --- a/WebCore/html/FileStream.h +++ b/WebCore/html/FileStream.h @@ -67,6 +67,8 @@ private: FileStreamClient* m_client; PlatformFileHandle m_handle; + long long m_bytesProcessed; + long long m_totalBytesToRead; }; } // namespace WebCore diff --git a/WebCore/html/HTMLAnchorElement.cpp b/WebCore/html/HTMLAnchorElement.cpp index f636020..e3752c3 100644 --- a/WebCore/html/HTMLAnchorElement.cpp +++ b/WebCore/html/HTMLAnchorElement.cpp @@ -42,7 +42,7 @@ namespace WebCore { using namespace HTMLNames; HTMLAnchorElement::HTMLAnchorElement(const QualifiedName& tagName, Document* document) - : HTMLElement(tagName, document, CreateElement) + : HTMLElement(tagName, document, CreateHTMLElement) , m_wasShiftKeyDownOnMouseDown(false) , m_linkRelations(0) { @@ -102,24 +102,7 @@ bool HTMLAnchorElement::isKeyboardFocusable(KeyboardEvent* event) const if (!document()->frame()->eventHandler()->tabsToLinks(event)) return false; - if (!renderer() || !renderer()->isBoxModelObject()) - return false; - - // Before calling absoluteRects, check for the common case where the renderer - // is non-empty, since this is a faster check and almost always returns true. - RenderBoxModelObject* box = toRenderBoxModelObject(renderer()); - if (!box->borderBoundingBox().isEmpty()) - return true; - - Vector<IntRect> rects; - FloatPoint absPos = renderer()->localToAbsolute(); - renderer()->absoluteRects(rects, absPos.x(), absPos.y()); - size_t n = rects.size(); - for (size_t i = 0; i < n; ++i) - if (!rects[i].isEmpty()) - return true; - - return false; + return hasNonEmptyBoundingBox(); } void HTMLAnchorElement::defaultEventHandler(Event* evt) @@ -282,7 +265,7 @@ void HTMLAnchorElement::parseMappedAttribute(MappedAttribute *attr) ResourceHandle::prepareForURL(document()->completeURL(parsedURL)); } if (document()->page() && !document()->page()->javaScriptURLsAreAllowed() && protocolIsJavaScript(parsedURL)) { - setIsLink(false); + clearIsLink(); attr->setValue(nullAtom); } } diff --git a/WebCore/html/HTMLElement.cpp b/WebCore/html/HTMLElement.cpp index 816bb60..f2ffc16 100644 --- a/WebCore/html/HTMLElement.cpp +++ b/WebCore/html/HTMLElement.cpp @@ -58,7 +58,7 @@ using std::max; PassRefPtr<HTMLElement> HTMLElement::create(const QualifiedName& tagName, Document* document) { - return adoptRef(new HTMLElement(tagName, document, CreateElement)); + return adoptRef(new HTMLElement(tagName, document, CreateHTMLElement)); } String HTMLElement::nodeName() const diff --git a/WebCore/html/HTMLElement.h b/WebCore/html/HTMLElement.h index ccc9aa3..b51dba4 100644 --- a/WebCore/html/HTMLElement.h +++ b/WebCore/html/HTMLElement.h @@ -82,7 +82,7 @@ public: static void addHTMLAlignmentToStyledElement(StyledElement*, MappedAttribute*); protected: - HTMLElement(const QualifiedName& tagName, Document*, ConstructionType = CreateElementZeroRefCount); + HTMLElement(const QualifiedName& tagName, Document*, ConstructionType = CreateHTMLElementZeroRefCount); void addHTMLAlignment(MappedAttribute*); @@ -102,8 +102,6 @@ protected: HTMLFormElement* findFormAncestor() const; private: - virtual bool isHTMLElement() const { return true; } - virtual String nodeName() const; void setContentEditable(MappedAttribute*); diff --git a/WebCore/html/HTMLFormControlElement.cpp b/WebCore/html/HTMLFormControlElement.cpp index bcdf40d..7ae33d3 100644 --- a/WebCore/html/HTMLFormControlElement.cpp +++ b/WebCore/html/HTMLFormControlElement.cpp @@ -454,6 +454,16 @@ void HTMLFormControlElementWithState::finishParsingChildren() } } +void HTMLFormControlElementWithState::defaultEventHandler(Event* event) +{ + if (event->type() == eventNames().webkitEditableContentChangedEvent && renderer() && renderer()->isTextControl()) { + toRenderTextControl(renderer())->subtreeHasChanged(); + return; + } + + HTMLFormControlElement::defaultEventHandler(event); +} + HTMLTextFormControlElement::HTMLTextFormControlElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* form) : HTMLFormControlElementWithState(tagName, doc, form) { diff --git a/WebCore/html/HTMLFormControlElement.h b/WebCore/html/HTMLFormControlElement.h index 0045fbe..5b3a490 100644 --- a/WebCore/html/HTMLFormControlElement.h +++ b/WebCore/html/HTMLFormControlElement.h @@ -36,7 +36,7 @@ class VisibleSelection; class HTMLFormControlElement : public HTMLElement { public: - HTMLFormControlElement(const QualifiedName& tagName, Document*, HTMLFormElement*, ConstructionType = CreateElementZeroRefCount); + HTMLFormControlElement(const QualifiedName& tagName, Document*, HTMLFormElement*, ConstructionType = CreateHTMLElementZeroRefCount); virtual ~HTMLFormControlElement(); virtual HTMLTagStatus endTagRequirement() const { return TagStatusRequired; } @@ -160,6 +160,7 @@ public: protected: virtual void willMoveToNewOwnerDocument(); virtual void didMoveToNewOwnerDocument(); + virtual void defaultEventHandler(Event*); }; class HTMLTextFormControlElement : public HTMLFormControlElementWithState { diff --git a/WebCore/html/HTMLFormElement.cpp b/WebCore/html/HTMLFormElement.cpp index cafa3c9..d7f5d96 100644 --- a/WebCore/html/HTMLFormElement.cpp +++ b/WebCore/html/HTMLFormElement.cpp @@ -38,6 +38,7 @@ #include "FormState.h" #include "Frame.h" #include "FrameLoader.h" +#include "FrameLoaderClient.h" #include "HTMLDocument.h" #include "HTMLFormCollection.h" #include "HTMLImageElement.h" @@ -175,20 +176,21 @@ Node* HTMLFormElement::item(unsigned index) return elements()->item(index); } -void HTMLFormElement::submitClick(Event* event) +void HTMLFormElement::submitImplicitly(Event* event, bool fromTextField) { - bool submitFound = false; + int textControlCount = 0; for (unsigned i = 0; i < formElements.size(); ++i) { if (formElements[i]->hasLocalName(inputTag)) { HTMLInputElement* element = static_cast<HTMLInputElement*>(formElements[i]); if (element->isSuccessfulSubmitButton() && element->renderer()) { - submitFound = true; element->dispatchSimulatedClick(event); - break; - } - } + return; + } else if (element->isTextField()) + ++textControlCount; + } else if (formElements[i]->hasLocalName(isindexTag)) + ++textControlCount; } - if (!submitFound) // submit the form without a submit or image input + if (fromTextField && textControlCount == 1) prepareSubmit(event); } @@ -291,6 +293,8 @@ bool HTMLFormElement::prepareSubmit(Event* event) if (!validateInteractively(event)) return false; + frame->loader()->client()->dispatchWillSendSubmitEvent(this); + if (dispatchEvent(Event::create(eventNames().submitEvent, true, true)) && !m_doingsubmit) m_doingsubmit = true; diff --git a/WebCore/html/HTMLFormElement.h b/WebCore/html/HTMLFormElement.h index 923c734..a2142ec 100644 --- a/WebCore/html/HTMLFormElement.h +++ b/WebCore/html/HTMLFormElement.h @@ -91,7 +91,7 @@ public: virtual bool isURLAttribute(Attribute*) const; - void submitClick(Event*); + void submitImplicitly(Event*, bool fromTextField); bool formWouldHaveSecureSubmission(const String& url); String name() const; diff --git a/WebCore/html/HTMLFormElement.idl b/WebCore/html/HTMLFormElement.idl index d639c34..0654a7d 100644 --- a/WebCore/html/HTMLFormElement.idl +++ b/WebCore/html/HTMLFormElement.idl @@ -35,7 +35,7 @@ module html { attribute [ConvertNullToNullString] DOMString method; attribute [ConvertNullToNullString] DOMString target; - [Custom] void submit(); + [CallWith=DynamicFrame] void submit(); void reset(); boolean checkValidity(); }; diff --git a/WebCore/html/HTMLFrameOwnerElement.cpp b/WebCore/html/HTMLFrameOwnerElement.cpp index c3ae785..a9538fd 100644 --- a/WebCore/html/HTMLFrameOwnerElement.cpp +++ b/WebCore/html/HTMLFrameOwnerElement.cpp @@ -33,7 +33,7 @@ namespace WebCore { HTMLFrameOwnerElement::HTMLFrameOwnerElement(const QualifiedName& tagName, Document* document) - : HTMLElement(tagName, document, CreateElement) + : HTMLElement(tagName, document, CreateHTMLElement) , m_contentFrame(0) , m_sandboxFlags(SandboxNone) { diff --git a/WebCore/html/HTMLInputElement.cpp b/WebCore/html/HTMLInputElement.cpp index 60669ef..bbc9f43 100644 --- a/WebCore/html/HTMLInputElement.cpp +++ b/WebCore/html/HTMLInputElement.cpp @@ -46,7 +46,7 @@ #include "HTMLImageLoader.h" #include "HTMLNames.h" #include "HTMLOptionElement.h" -#include "ScriptEventListener.h" +#include "HTMLParser.h" #include "KeyboardEvent.h" #include "LocalizedStrings.h" #include "MappedAttribute.h" @@ -60,6 +60,7 @@ #include "RenderText.h" #include "RenderTextControlSingleLine.h" #include "RenderTheme.h" +#include "ScriptEventListener.h" #include "StepRange.h" #include "StringHash.h" #include "TextEvent.h" @@ -69,7 +70,6 @@ #include <wtf/HashMap.h> #include <wtf/MathExtras.h> #include <wtf/StdLibExtras.h> -#include <wtf/dtoa.h> using namespace std; @@ -168,41 +168,50 @@ static inline CheckedRadioButtons& checkedRadioButtons(const HTMLInputElement* e return element->document()->checkedRadioButtons(); } +void HTMLInputElement::updateCheckedRadioButtons() +{ + if (attached() && checked()) + checkedRadioButtons(this).addButton(this); + + if (renderer() && renderer()->style()->hasAppearance()) + renderer()->theme()->stateChanged(renderer(), CheckedState); +} + bool HTMLInputElement::valueMissing() const { if (!isRequiredFormControl() || readOnly() || disabled()) return false; switch (inputType()) { - case DATE: - case DATETIME: - case DATETIMELOCAL: - case EMAIL: - case FILE: - case MONTH: - case NUMBER: - case PASSWORD: - case SEARCH: - case TELEPHONE: - case TEXT: - case TIME: - case URL: - case WEEK: - return value().isEmpty(); - case CHECKBOX: - return !checked(); - case RADIO: - return !checkedRadioButtons(this).checkedButtonForGroup(name()); - case COLOR: - return false; - case BUTTON: - case HIDDEN: - case IMAGE: - case ISINDEX: - case RANGE: - case RESET: - case SUBMIT: - break; + case DATE: + case DATETIME: + case DATETIMELOCAL: + case EMAIL: + case FILE: + case MONTH: + case NUMBER: + case PASSWORD: + case SEARCH: + case TELEPHONE: + case TEXT: + case TIME: + case URL: + case WEEK: + return value().isEmpty(); + case CHECKBOX: + return !checked(); + case RADIO: + return !checkedRadioButtons(this).checkedButtonForGroup(name()); + case COLOR: + return false; + case BUTTON: + case HIDDEN: + case IMAGE: + case ISINDEX: + case RANGE: + case RESET: + case SUBMIT: + break; } ASSERT_NOT_REACHED(); @@ -212,46 +221,42 @@ bool HTMLInputElement::valueMissing() const bool HTMLInputElement::patternMismatch() const { switch (inputType()) { - case BUTTON: - case CHECKBOX: - case COLOR: - case DATE: - case DATETIME: - case DATETIMELOCAL: - case FILE: - case HIDDEN: - case IMAGE: - case ISINDEX: - case MONTH: - case NUMBER: - case RADIO: - case RANGE: - case RESET: - case SUBMIT: - case TIME: - case WEEK: + case BUTTON: + case CHECKBOX: + case COLOR: + case DATE: + case DATETIME: + case DATETIMELOCAL: + case FILE: + case HIDDEN: + case IMAGE: + case ISINDEX: + case MONTH: + case NUMBER: + case RADIO: + case RANGE: + case RESET: + case SUBMIT: + case TIME: + case WEEK: + return false; + case EMAIL: + case PASSWORD: + case SEARCH: + case TELEPHONE: + case TEXT: + case URL: + const AtomicString& pattern = getAttribute(patternAttr); + String value = this->value(); + // Empty values can't be mismatched + if (pattern.isEmpty() || value.isEmpty()) return false; - case EMAIL: - case PASSWORD: - case SEARCH: - case TELEPHONE: - case TEXT: - case URL: - const AtomicString& pattern = getAttribute(patternAttr); - String value = this->value(); - - // Empty values can't be mismatched - if (pattern.isEmpty() || value.isEmpty()) - return false; - - RegularExpression patternRegExp(pattern, TextCaseSensitive); - int matchLength = 0; - int valueLength = value.length(); - int matchOffset = patternRegExp.match(value, 0, &matchLength); - - return matchOffset != 0 || matchLength != valueLength; + RegularExpression patternRegExp(pattern, TextCaseSensitive); + int matchLength = 0; + int valueLength = value.length(); + int matchOffset = patternRegExp.match(value, 0, &matchLength); + return matchOffset || matchLength != valueLength; } - ASSERT_NOT_REACHED(); return false; } @@ -703,8 +708,7 @@ bool HTMLInputElement::isKeyboardFocusable(KeyboardEvent* event) const Node* currentFocusedNode = document()->focusedNode(); if (currentFocusedNode && currentFocusedNode->hasTagName(inputTag)) { HTMLInputElement* focusedInput = static_cast<HTMLInputElement*>(currentFocusedNode); - if (focusedInput->inputType() == RADIO && focusedInput->form() == form() && - focusedInput->name() == name()) + if (focusedInput->inputType() == RADIO && focusedInput->form() == form() && focusedInput->name() == name()) return false; } @@ -737,7 +741,11 @@ void HTMLInputElement::aboutToUnload() bool HTMLInputElement::shouldUseInputMethod() const { - return m_type == TEXT || m_type == SEARCH || m_type == ISINDEX; + // The reason IME's are disabled for the password field is because IMEs + // can access the underlying password and display it in clear text -- + // e.g. you can use it to access the stored password for any site + // with only trivial effort. + return isTextField() && inputType() != PASSWORD; } void HTMLInputElement::handleFocusEvent() @@ -913,39 +921,39 @@ const AtomicString& HTMLInputElement::formControlType() const bool HTMLInputElement::saveFormControlState(String& result) const { switch (inputType()) { - case BUTTON: - case COLOR: - case DATE: - case DATETIME: - case DATETIMELOCAL: - case EMAIL: - case FILE: - case HIDDEN: - case IMAGE: - case ISINDEX: - case MONTH: - case NUMBER: - case RANGE: - case RESET: - case SEARCH: - case SUBMIT: - case TELEPHONE: - case TEXT: - case TIME: - case URL: - case WEEK: { - String currentValue = value(); - if (currentValue == defaultValue()) - return false; - result = currentValue; - return true; - } - case CHECKBOX: - case RADIO: - result = checked() ? "on" : "off"; - return true; - case PASSWORD: + case BUTTON: + case COLOR: + case DATE: + case DATETIME: + case DATETIMELOCAL: + case EMAIL: + case FILE: + case HIDDEN: + case IMAGE: + case ISINDEX: + case MONTH: + case NUMBER: + case RANGE: + case RESET: + case SEARCH: + case SUBMIT: + case TELEPHONE: + case TEXT: + case TIME: + case URL: + case WEEK: { + String currentValue = value(); + if (currentValue == defaultValue()) return false; + result = currentValue; + return true; + } + case CHECKBOX: + case RADIO: + result = checked() ? "on" : "off"; + return true; + case PASSWORD: + return false; } ASSERT_NOT_REACHED(); return false; @@ -955,35 +963,35 @@ void HTMLInputElement::restoreFormControlState(const String& state) { ASSERT(inputType() != PASSWORD); // should never save/restore password fields switch (inputType()) { - case BUTTON: - case COLOR: - case DATE: - case DATETIME: - case DATETIMELOCAL: - case EMAIL: - case FILE: - case HIDDEN: - case IMAGE: - case ISINDEX: - case MONTH: - case NUMBER: - case RANGE: - case RESET: - case SEARCH: - case SUBMIT: - case TELEPHONE: - case TEXT: - case TIME: - case URL: - case WEEK: - setValue(state); - break; - case CHECKBOX: - case RADIO: - setChecked(state == "on"); - break; - case PASSWORD: - break; + case BUTTON: + case COLOR: + case DATE: + case DATETIME: + case DATETIMELOCAL: + case EMAIL: + case FILE: + case HIDDEN: + case IMAGE: + case ISINDEX: + case MONTH: + case NUMBER: + case RANGE: + case RESET: + case SEARCH: + case SUBMIT: + case TELEPHONE: + case TEXT: + case TIME: + case URL: + case WEEK: + setValue(state); + break; + case CHECKBOX: + case RADIO: + setChecked(state == "on"); + break; + case PASSWORD: + break; } } @@ -1002,47 +1010,47 @@ bool HTMLInputElement::canHaveSelection() const void HTMLInputElement::accessKeyAction(bool sendToAnyElement) { switch (inputType()) { - case BUTTON: - case CHECKBOX: - case FILE: - case IMAGE: - case RADIO: - case RANGE: - case RESET: - case SUBMIT: - focus(false); - // send the mouse button events iff the caller specified sendToAnyElement - dispatchSimulatedClick(0, sendToAnyElement); - break; - case HIDDEN: - // a no-op for this type - break; - case COLOR: - case DATE: - case DATETIME: - case DATETIMELOCAL: - case EMAIL: - case ISINDEX: - case MONTH: - case NUMBER: - case PASSWORD: - case SEARCH: - case TELEPHONE: - case TEXT: - case TIME: - case URL: - case WEEK: - // should never restore previous selection here - focus(false); - break; + case BUTTON: + case CHECKBOX: + case FILE: + case IMAGE: + case RADIO: + case RANGE: + case RESET: + case SUBMIT: + focus(false); + // send the mouse button events iff the caller specified sendToAnyElement + dispatchSimulatedClick(0, sendToAnyElement); + break; + case HIDDEN: + // a no-op for this type + break; + case COLOR: + case DATE: + case DATETIME: + case DATETIMELOCAL: + case EMAIL: + case ISINDEX: + case MONTH: + case NUMBER: + case PASSWORD: + case SEARCH: + case TELEPHONE: + case TEXT: + case TIME: + case URL: + case WEEK: + // should never restore previous selection here + focus(false); + break; } } bool HTMLInputElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const { - if (((attrName == heightAttr || attrName == widthAttr) && respectHeightAndWidthAttrs()) || - attrName == vspaceAttr || - attrName == hspaceAttr) { + if (((attrName == heightAttr || attrName == widthAttr) && respectHeightAndWidthAttrs()) + || attrName == vspaceAttr + || attrName == hspaceAttr) { result = eUniversal; return false; } @@ -1109,8 +1117,7 @@ void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr) m_imageLoader.set(new HTMLImageLoader(this)); m_imageLoader->updateFromElementIgnoringPreviousError(); } - } else if (attr->name() == usemapAttr || - attr->name() == accesskeyAttr) { + } else if (attr->name() == usemapAttr || attr->name() == accesskeyAttr) { // FIXME: ignore for the moment } else if (attr->name() == vspaceAttr) { addCSSLength(attr, CSSPropertyMarginTop, attr->value()); @@ -1127,10 +1134,8 @@ void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr) } else if (attr->name() == heightAttr) { if (respectHeightAndWidthAttrs()) addCSSLength(attr, CSSPropertyHeight, attr->value()); - } - // Search field and slider attributes all just cause updateFromElement to be called through style - // recalcing. - else if (attr->name() == onsearchAttr) { + } else if (attr->name() == onsearchAttr) { + // Search field and slider attributes all just cause updateFromElement to be called through style recalcing. setAttributeEventListener(eventNames().searchEvent, createAttributeEventListener(this, attr)); } else if (attr->name() == resultsAttr) { int oldResults = m_maxResults; @@ -1174,40 +1179,40 @@ bool HTMLInputElement::rendererIsNeeded(RenderStyle *style) return HTMLFormControlElementWithState::rendererIsNeeded(style); } -RenderObject *HTMLInputElement::createRenderer(RenderArena *arena, RenderStyle *style) +RenderObject* HTMLInputElement::createRenderer(RenderArena *arena, RenderStyle *style) { switch (inputType()) { - case BUTTON: - case RESET: - case SUBMIT: - return new (arena) RenderButton(this); - case CHECKBOX: - case RADIO: - return RenderObject::createObject(this, style); - case FILE: - return new (arena) RenderFileUploadControl(this); - case HIDDEN: - break; - case IMAGE: - return new (arena) RenderImage(this); - case RANGE: - return new (arena) RenderSlider(this); - case COLOR: - case DATE: - case DATETIME: - case DATETIMELOCAL: - case EMAIL: - case ISINDEX: - case MONTH: - case NUMBER: - case PASSWORD: - case SEARCH: - case TELEPHONE: - case TEXT: - case TIME: - case URL: - case WEEK: - return new (arena) RenderTextControlSingleLine(this, placeholderShouldBeVisible()); + case BUTTON: + case RESET: + case SUBMIT: + return new (arena) RenderButton(this); + case CHECKBOX: + case RADIO: + return RenderObject::createObject(this, style); + case FILE: + return new (arena) RenderFileUploadControl(this); + case HIDDEN: + break; + case IMAGE: + return new (arena) RenderImage(this); + case RANGE: + return new (arena) RenderSlider(this); + case COLOR: + case DATE: + case DATETIME: + case DATETIMELOCAL: + case EMAIL: + case ISINDEX: + case MONTH: + case NUMBER: + case PASSWORD: + case SEARCH: + case TELEPHONE: + case TEXT: + case TIME: + case URL: + case WEEK: + return new (arena) RenderTextControlSingleLine(this, placeholderShouldBeVisible()); } ASSERT(false); return 0; @@ -1238,6 +1243,9 @@ void HTMLInputElement::attach() } } + if (inputType() == RADIO) + updateCheckedRadioButtons(); + if (document()->focusedNode() == this) document()->updateFocusAppearanceSoon(true /* restore selection */); } @@ -1288,87 +1296,86 @@ bool HTMLInputElement::appendFormData(FormDataList& encoding, bool multipart) return false; switch (inputType()) { - case COLOR: - case DATE: - case DATETIME: - case DATETIMELOCAL: - case EMAIL: - case HIDDEN: - case ISINDEX: - case MONTH: - case NUMBER: - case PASSWORD: - case RANGE: - case SEARCH: - case TELEPHONE: - case TEXT: - case TIME: - case URL: - case WEEK: - // always successful + case COLOR: + case DATE: + case DATETIME: + case DATETIMELOCAL: + case EMAIL: + case HIDDEN: + case ISINDEX: + case MONTH: + case NUMBER: + case PASSWORD: + case RANGE: + case SEARCH: + case TELEPHONE: + case TEXT: + case TIME: + case URL: + case WEEK: + // always successful + encoding.appendData(name(), value()); + return true; + + case CHECKBOX: + case RADIO: + if (checked()) { encoding.appendData(name(), value()); return true; + } + break; - case CHECKBOX: - case RADIO: - if (checked()) { - encoding.appendData(name(), value()); - return true; - } - break; - - case BUTTON: - case RESET: - // these types of buttons are never successful - return false; - - case IMAGE: - if (m_activeSubmit) { - encoding.appendData(name().isEmpty() ? "x" : (name() + ".x"), m_xPos); - encoding.appendData(name().isEmpty() ? "y" : (name() + ".y"), m_yPos); - if (!name().isEmpty() && !value().isEmpty()) - encoding.appendData(name(), value()); - return true; - } - break; - - case SUBMIT: - if (m_activeSubmit) { - String enc_str = valueWithDefault(); - encoding.appendData(name(), enc_str); - return true; - } - break; - - case FILE: { - unsigned numFiles = m_fileList->length(); - if (!multipart) { - // Send only the basenames. - // 4.10.16.4 and 4.10.16.6 sections in HTML5. + case BUTTON: + case RESET: + // these types of buttons are never successful + return false; - // Unlike the multipart case, we have no special - // handling for the empty fileList because Netscape - // doesn't support for non-multipart submission of - // file inputs, and Firefox doesn't add "name=" query - // parameter. + case IMAGE: + if (m_activeSubmit) { + encoding.appendData(name().isEmpty() ? "x" : (name() + ".x"), m_xPos); + encoding.appendData(name().isEmpty() ? "y" : (name() + ".y"), m_yPos); + if (!name().isEmpty() && !value().isEmpty()) + encoding.appendData(name(), value()); + return true; + } + break; - for (unsigned i = 0; i < numFiles; ++i) { - encoding.appendData(name(), m_fileList->item(i)->fileName()); - } - return true; - } + case SUBMIT: + if (m_activeSubmit) { + String encstr = valueWithDefault(); + encoding.appendData(name(), encstr); + return true; + } + break; - // If no filename at all is entered, return successful but empty. - // Null would be more logical, but Netscape posts an empty file. Argh. - if (!numFiles) { - encoding.appendBlob(name(), File::create("")); - return true; - } + case FILE: { + unsigned numFiles = m_fileList->length(); + if (!multipart) { + // Send only the basenames. + // 4.10.16.4 and 4.10.16.6 sections in HTML5. + + // Unlike the multipart case, we have no special + // handling for the empty fileList because Netscape + // doesn't support for non-multipart submission of + // file inputs, and Firefox doesn't add "name=" query + // parameter. + + for (unsigned i = 0; i < numFiles; ++i) + encoding.appendData(name(), m_fileList->item(i)->fileName()); + return true; + } - for (unsigned i = 0; i < numFiles; ++i) - encoding.appendBlob(name(), m_fileList->item(i)); + // If no filename at all is entered, return successful but empty. + // Null would be more logical, but Netscape posts an empty file. Argh. + if (!numFiles) { + encoding.appendBlob(name(), File::create("")); return true; } + + for (unsigned i = 0; i < numFiles; ++i) + encoding.appendBlob(name(), m_fileList->item(i)); + return true; + } } return false; } @@ -1427,10 +1434,7 @@ void HTMLInputElement::setChecked(bool nowChecked, bool sendChangeEvent) m_checked = nowChecked; setNeedsStyleRecalc(); - checkedRadioButtons(this).addButton(this); - - if (renderer() && renderer()->style()->hasAppearance()) - renderer()->theme()->stateChanged(renderer(), CheckedState); + updateCheckedRadioButtons(); // Ideally we'd do this from the render tree (matching // RenderTextView), but it's not possible to do it at the moment @@ -1447,13 +1451,13 @@ void HTMLInputElement::setChecked(bool nowChecked, bool sendChangeEvent) dispatchFormControlChangeEvent(); } -void HTMLInputElement::setIndeterminate(bool _indeterminate) +void HTMLInputElement::setIndeterminate(bool newValue) { // Only checkboxes and radio buttons honor indeterminate. - if (!allowsIndeterminate() || indeterminate() == _indeterminate) + if (!allowsIndeterminate() || indeterminate() == newValue) return; - m_indeterminate = _indeterminate; + m_indeterminate = newValue; setNeedsStyleRecalc(); @@ -1499,7 +1503,7 @@ String HTMLInputElement::value() const if (value.isNull()) { if (inputType() == CHECKBOX || inputType() == RADIO) return checked() ? "on" : ""; - else if (inputType() == RANGE) + if (inputType() == RANGE) return serializeForNumberType(StepRange(this).defaultValue()); } } @@ -1512,35 +1516,35 @@ String HTMLInputElement::valueWithDefault() const String v = value(); if (v.isNull()) { switch (inputType()) { - case BUTTON: - case CHECKBOX: - case COLOR: - case DATE: - case DATETIME: - case DATETIMELOCAL: - case EMAIL: - case FILE: - case HIDDEN: - case IMAGE: - case ISINDEX: - case MONTH: - case NUMBER: - case PASSWORD: - case RADIO: - case RANGE: - case SEARCH: - case TELEPHONE: - case TEXT: - case TIME: - case URL: - case WEEK: - break; - case RESET: - v = resetButtonDefaultLabel(); - break; - case SUBMIT: - v = submitButtonDefaultLabel(); - break; + case BUTTON: + case CHECKBOX: + case COLOR: + case DATE: + case DATETIME: + case DATETIMELOCAL: + case EMAIL: + case FILE: + case HIDDEN: + case IMAGE: + case ISINDEX: + case MONTH: + case NUMBER: + case PASSWORD: + case RADIO: + case RANGE: + case SEARCH: + case TELEPHONE: + case TEXT: + case TIME: + case URL: + case WEEK: + break; + case RESET: + v = resetButtonDefaultLabel(); + break; + case SUBMIT: + v = submitButtonDefaultLabel(); + break; } } return v; @@ -1963,32 +1967,32 @@ void HTMLInputElement::setFileListFromRenderer(const Vector<String>& paths) bool HTMLInputElement::storesValueSeparateFromAttribute() const { switch (inputType()) { - case BUTTON: - case CHECKBOX: - case HIDDEN: - case IMAGE: - case RADIO: - case RESET: - case SUBMIT: - return false; - case COLOR: - case DATE: - case DATETIME: - case DATETIMELOCAL: - case EMAIL: - case FILE: - case ISINDEX: - case MONTH: - case NUMBER: - case PASSWORD: - case RANGE: - case SEARCH: - case TELEPHONE: - case TEXT: - case TIME: - case URL: - case WEEK: - return true; + case BUTTON: + case CHECKBOX: + case HIDDEN: + case IMAGE: + case RADIO: + case RESET: + case SUBMIT: + return false; + case COLOR: + case DATE: + case DATETIME: + case DATETIMELOCAL: + case EMAIL: + case FILE: + case ISINDEX: + case MONTH: + case NUMBER: + case PASSWORD: + case RANGE: + case SEARCH: + case TELEPHONE: + case TEXT: + case TIME: + case URL: + case WEEK: + return true; } return false; } @@ -2078,10 +2082,10 @@ void HTMLInputElement::defaultEventHandler(Event* evt) // FIXME: It would be better to refactor this for the different types of input element. // Having them all in one giant function makes this hard to read, and almost all the handling is type-specific. - bool clickDefaultFormButton = false; + bool implicitSubmission = false; if (isTextField() && evt->type() == eventNames().textInputEvent && evt->isTextEvent() && static_cast<TextEvent*>(evt)->data() == "\n") - clickDefaultFormButton = true; + implicitSubmission = true; if (inputType() == IMAGE && evt->isMouseEvent() && evt->type() == eventNames().clickEvent) { // record the mouse position for when we get the DOMActivate event @@ -2120,7 +2124,7 @@ void HTMLInputElement::defaultEventHandler(Event* evt) // Call the base event handler before any of our own event handling for almost all events in text fields. // Makes editing keyboard handling take precedence over the keydown and keypress handling in this function. - bool callBaseClassEarly = isTextField() && !clickDefaultFormButton + bool callBaseClassEarly = isTextField() && !implicitSubmission && (evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent); if (callBaseClassEarly) { HTMLFormControlElementWithState::defaultEventHandler(evt); @@ -2163,52 +2167,51 @@ void HTMLInputElement::defaultEventHandler(Event* evt) if (charCode == '\r') { switch (inputType()) { - case CHECKBOX: - case COLOR: - case DATE: - case DATETIME: - case DATETIMELOCAL: - case EMAIL: - case HIDDEN: - case ISINDEX: - case MONTH: - case NUMBER: - case PASSWORD: - case RANGE: - case SEARCH: - case TELEPHONE: - case TEXT: - case TIME: - case URL: - case WEEK: - // Simulate mouse click on the default form button for enter for these types of elements. - clickDefaultFormButton = true; - break; - case BUTTON: - case FILE: - case IMAGE: - case RESET: - case SUBMIT: - // Simulate mouse click for enter for these types of elements. - clickElement = true; - break; - case RADIO: - break; // Don't do anything for enter on a radio button. + case CHECKBOX: + case COLOR: + case DATE: + case DATETIME: + case DATETIMELOCAL: + case EMAIL: + case HIDDEN: + case ISINDEX: + case MONTH: + case NUMBER: + case PASSWORD: + case RADIO: + case RANGE: + case SEARCH: + case TELEPHONE: + case TEXT: + case TIME: + case URL: + case WEEK: + // Simulate mouse click on the default form button for enter for these types of elements. + implicitSubmission = true; + break; + case BUTTON: + case FILE: + case IMAGE: + case RESET: + case SUBMIT: + // Simulate mouse click for enter for these types of elements. + clickElement = true; + break; } } else if (charCode == ' ') { switch (inputType()) { - case BUTTON: - case CHECKBOX: - case FILE: - case IMAGE: - case RESET: - case SUBMIT: - case RADIO: - // Prevent scrolling down the page. - evt->setDefaultHandled(); - return; - default: - break; + case BUTTON: + case CHECKBOX: + case FILE: + case IMAGE: + case RESET: + case SUBMIT: + case RADIO: + // Prevent scrolling down the page. + evt->setDefaultHandled(); + return; + default: + break; } } @@ -2224,19 +2227,19 @@ void HTMLInputElement::defaultEventHandler(Event* evt) if (key == "U+0020") { switch (inputType()) { - case BUTTON: - case CHECKBOX: - case FILE: - case IMAGE: - case RESET: - case SUBMIT: - case RADIO: - setActive(true, true); - // No setDefaultHandled(), because IE dispatches a keypress in this case - // and the caller will only dispatch a keypress if we don't call setDefaultHandled. - return; - default: - break; + case BUTTON: + case CHECKBOX: + case FILE: + case IMAGE: + case RESET: + case SUBMIT: + case RADIO: + setActive(true, true); + // No setDefaultHandled(), because IE dispatches a keypress in this case + // and the caller will only dispatch a keypress if we don't call setDefaultHandled. + return; + default: + break; } } @@ -2283,40 +2286,40 @@ void HTMLInputElement::defaultEventHandler(Event* evt) if (key == "U+0020") { switch (inputType()) { - case BUTTON: - case CHECKBOX: - case FILE: - case IMAGE: - case RESET: - case SUBMIT: - // Simulate mouse click for spacebar for these types of elements. - // The AppKit already does this for some, but not all, of them. + case BUTTON: + case CHECKBOX: + case FILE: + case IMAGE: + case RESET: + case SUBMIT: + // Simulate mouse click for spacebar for these types of elements. + // The AppKit already does this for some, but not all, of them. + clickElement = true; + break; + case RADIO: + // If an unselected radio is tabbed into (because the entire group has nothing + // checked, or because of some explicit .focus() call), then allow space to check it. + if (!checked()) clickElement = true; - break; - case RADIO: - // If an unselected radio is tabbed into (because the entire group has nothing - // checked, or because of some explicit .focus() call), then allow space to check it. - if (!checked()) - clickElement = true; - break; - case COLOR: - case DATE: - case DATETIME: - case DATETIMELOCAL: - case EMAIL: - case HIDDEN: - case ISINDEX: - case MONTH: - case NUMBER: - case PASSWORD: - case RANGE: - case SEARCH: - case TELEPHONE: - case TEXT: - case TIME: - case URL: - case WEEK: - break; + break; + case COLOR: + case DATE: + case DATETIME: + case DATETIMELOCAL: + case EMAIL: + case HIDDEN: + case ISINDEX: + case MONTH: + case NUMBER: + case PASSWORD: + case RANGE: + case SEARCH: + case TELEPHONE: + case TEXT: + case TIME: + case URL: + case WEEK: + break; } } @@ -2328,7 +2331,7 @@ void HTMLInputElement::defaultEventHandler(Event* evt) } } - if (clickDefaultFormButton) { + if (implicitSubmission) { if (isSearchField()) { addSearchResult(); onSearch(); @@ -2350,7 +2353,7 @@ void HTMLInputElement::defaultEventHandler(Event* evt) // Form may never have been present, or may have been destroyed by code responding to the change event. if (formForSubmission) - formForSubmission->submitClick(evt); + formForSubmission->submitImplicitly(evt, isTextField()); evt->setDefaultHandled(); return; @@ -2475,9 +2478,9 @@ void HTMLInputElement::setMultiple(bool multiple) setAttribute(multipleAttr, multiple ? "" : 0); } -void HTMLInputElement::setSize(unsigned _size) +void HTMLInputElement::setSize(unsigned size) { - setAttribute(sizeAttr, String::number(_size)); + setAttribute(sizeAttr, String::number(size)); } KURL HTMLInputElement::src() const @@ -2553,32 +2556,32 @@ bool HTMLInputElement::isRequiredFormControl() const return false; switch (inputType()) { - case CHECKBOX: - case DATE: - case DATETIME: - case DATETIMELOCAL: - case EMAIL: - case FILE: - case MONTH: - case NUMBER: - case PASSWORD: - case RADIO: - case SEARCH: - case TELEPHONE: - case TEXT: - case TIME: - case URL: - case WEEK: - return true; - case BUTTON: - case COLOR: - case HIDDEN: - case IMAGE: - case ISINDEX: - case RANGE: - case RESET: - case SUBMIT: - return false; + case CHECKBOX: + case DATE: + case DATETIME: + case DATETIMELOCAL: + case EMAIL: + case FILE: + case MONTH: + case NUMBER: + case PASSWORD: + case RADIO: + case SEARCH: + case TELEPHONE: + case TEXT: + case TIME: + case URL: + case WEEK: + return true; + case BUTTON: + case COLOR: + case HIDDEN: + case IMAGE: + case ISINDEX: + case RANGE: + case RESET: + case SUBMIT: + return false; } ASSERT_NOT_REACHED(); @@ -2646,42 +2649,6 @@ bool HTMLInputElement::recalcWillValidate() const && inputType() != HIDDEN && inputType() != BUTTON && inputType() != RESET; } -String HTMLInputElement::serializeForNumberType(double number) -{ - // According to HTML5, "the best representation of the number n as a floating - // point number" is a string produced by applying ToString() to n. - DtoaBuffer buffer; - unsigned length; - doubleToStringInJavaScriptFormat(number, buffer, &length); - return String(buffer, length); -} - -bool HTMLInputElement::parseToDoubleForNumberType(const String& src, double* out) -{ - // See HTML5 2.4.4.3 `Real numbers.' - - if (src.isEmpty()) - return false; - // String::toDouble() accepts leading + \t \n \v \f \r and SPACE, which are invalid in HTML5. - // So, check the first character. - if (src[0] != '-' && (src[0] < '0' || src[0] > '9')) - return false; - - bool valid = false; - double value = src.toDouble(&valid); - if (!valid) - return false; - // NaN and Infinity are not valid numbers according to the standard. - if (!isfinite(value)) - return false; - // -0 -> 0 - if (!value) - value = 0; - if (out) - *out = value; - return true; -} - bool HTMLInputElement::parseToDateComponents(InputType type, const String& formString, DateComponents* out) { if (formString.isEmpty()) @@ -2777,6 +2744,41 @@ HTMLOptionElement* HTMLInputElement::selectedOption() const } return 0; } -#endif // ENABLE(DATALIST) +#endif // ENABLE(DATALIST) + +void HTMLInputElement::stepUpFromRenderer(int n) +{ + // The difference from stepUp()/stepDown() is: + // If the current value is invalid, the value will be + // - the minimum value if n > 0 + // - the maximum value if n < 0 + + ASSERT(hasSpinButton()); + if (!hasSpinButton()) + return; + ASSERT(n); + if (!n) + return; + + const double nan = numeric_limits<double>::quiet_NaN(); + double current = parseToDouble(value(), nan); + if (!isfinite(current)) { + setValue(serialize(n > 0 ? minimum() : maximum())); + return; + } + ExceptionCode ec; + stepUp(n, ec); +} + +#if ENABLE(WCSS) +void HTMLInputElement::setWapInputFormat(String& mask) +{ + String validateMask = validateInputMask(m_data, mask); + if (!validateMask.isEmpty()) + m_data.setInputFormatMask(validateMask); +} +#endif + + } // namespace diff --git a/WebCore/html/HTMLInputElement.h b/WebCore/html/HTMLInputElement.h index c3b0a73..e717628 100644 --- a/WebCore/html/HTMLInputElement.h +++ b/WebCore/html/HTMLInputElement.h @@ -121,6 +121,8 @@ public: void stepDown(int, ExceptionCode&); void stepUp(ExceptionCode& ec) { stepUp(1, ec); } void stepDown(ExceptionCode& ec) { stepDown(1, ec); } + // stepUp()/stepDown() for user-interaction. + void stepUpFromRenderer(int); bool isTextButton() const { return m_type == SUBMIT || m_type == RESET || m_type == BUTTON; } virtual bool isRadioButton() const { return m_type == RADIO; } @@ -128,6 +130,7 @@ public: virtual bool isSearchField() const { return m_type == SEARCH; } virtual bool isInputTypeHidden() const { return m_type == HIDDEN; } virtual bool isPasswordField() const { return m_type == PASSWORD; } + virtual bool hasSpinButton() const { return m_type == NUMBER || m_type == DATE || m_type == DATETIME || m_type == DATETIMELOCAL || m_type == MONTH || m_type == TIME || m_type == WEEK; } bool checked() const { return m_checked; } void setChecked(bool, bool sendChangeEvent = false); @@ -199,7 +202,6 @@ public: virtual void* preDispatchEventHandler(Event*); virtual void postDispatchEventHandler(Event*, void* dataFromPreDispatch); - virtual void defaultEventHandler(Event*); String altText() const; @@ -261,21 +263,20 @@ public: virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const; - // Converts the specified string to a floating number. - // If the conversion fails, the return value is false. Take care that leading or trailing unnecessary characters make failures. This returns false for an empty string input. - // The double* parameter may be 0. - static bool parseToDoubleForNumberType(const String&, double*); - // Converts the specified number to a string. This is an implementation of - // HTML5's "algorithm to convert a number to a string" for NUMBER/RANGE types. - static String serializeForNumberType(double); // Parses the specified string as the InputType, and returns true if it is successfully parsed. // An instance pointed by the DateComponents* parameter will have parsed values and be // modified even if the parsing fails. The DateComponents* parameter may be 0. static bool parseToDateComponents(InputType, const String&, DateComponents*); + +#if ENABLE(WCSS) + void setWapInputFormat(String& mask); + virtual InputElementData data() const { return m_data; } +#endif protected: virtual void willMoveToNewOwnerDocument(); virtual void didMoveToNewOwnerDocument(); + virtual void defaultEventHandler(Event*); private: bool storesValueSeparateFromAttribute() const; @@ -295,6 +296,8 @@ private: virtual bool isRequiredFormControl() const; virtual bool recalcWillValidate() const; + void updateCheckedRadioButtons(); + PassRefPtr<HTMLFormElement> createTemporaryFormForIsIndex(); // Helper for getAllowedValueStep(); bool getStepParameters(double* defaultStep, double* stepScaleFactor) const; diff --git a/WebCore/html/HTMLMediaElement.cpp b/WebCore/html/HTMLMediaElement.cpp index e8ab4e6..a0e9302 100644 --- a/WebCore/html/HTMLMediaElement.cpp +++ b/WebCore/html/HTMLMediaElement.cpp @@ -59,6 +59,7 @@ #include "RenderVideo.h" #include "RenderView.h" #include "ScriptEventListener.h" +#include "Settings.h" #include "TimeRanges.h" #include <limits> #include <wtf/CurrentTime.h> @@ -92,6 +93,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* doc) , m_webkitPreservesPitch(true) , m_networkState(NETWORK_EMPTY) , m_readyState(HAVE_NOTHING) + , m_readyStateMaximum(HAVE_NOTHING) , m_volume(1.0f) , m_lastSeekTime(0) , m_previousProgress(0) @@ -126,6 +128,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document* doc) #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) , m_needWidgetUpdate(false) #endif + , m_dispatchingCanPlayEvent(false) { document()->registerForDocumentActivationCallbacks(this); document()->registerForMediaVolumeCallbacks(this); @@ -358,8 +361,14 @@ void HTMLMediaElement::asyncEventTimerFired(Timer<HTMLMediaElement>*) m_pendingEvents.swap(pendingEvents); unsigned count = pendingEvents.size(); - for (unsigned ndx = 0; ndx < count; ++ndx) - dispatchEvent(pendingEvents[ndx].release(), ec); + for (unsigned ndx = 0; ndx < count; ++ndx) { + if (pendingEvents[ndx]->type() == eventNames().canplayEvent) { + m_dispatchingCanPlayEvent = true; + dispatchEvent(pendingEvents[ndx].release(), ec); + m_dispatchingCanPlayEvent = false; + } else + dispatchEvent(pendingEvents[ndx].release(), ec); + } } void HTMLMediaElement::loadTimerFired(Timer<HTMLMediaElement>*) @@ -493,6 +502,7 @@ void HTMLMediaElement::prepareForLoad() if (m_networkState != NETWORK_EMPTY) { m_networkState = NETWORK_EMPTY; m_readyState = HAVE_NOTHING; + m_readyStateMaximum = HAVE_NOTHING; m_paused = true; m_seeking = false; scheduleEvent(eventNames().emptiedEvent); @@ -858,6 +868,9 @@ void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state) if (m_readyState == oldState) return; + if (oldState > m_readyStateMaximum) + m_readyStateMaximum = oldState; + if (m_networkState == NETWORK_EMPTY) return; @@ -1190,6 +1203,17 @@ void HTMLMediaElement::play(bool isUserGesture) if (m_restrictions & RequireUserGestureForRateChangeRestriction && !isUserGesture) return; + Document* doc = document(); + Settings* settings = doc->settings(); + if (settings && settings->needsSiteSpecificQuirks() && m_dispatchingCanPlayEvent) { + // It should be impossible to be processing the canplay event while handling a user gesture + // since it is dispatched asynchronously. + ASSERT(!isUserGesture); + String host = doc->baseURL().host(); + if (host.endsWith(".npr.org", false) || equalIgnoringCase(host, "npr.org")) + return; + } + playInternal(); } @@ -1634,7 +1658,11 @@ PassRefPtr<TimeRanges> HTMLMediaElement::seekable() const bool HTMLMediaElement::potentiallyPlaying() const { - return m_readyState >= HAVE_FUTURE_DATA && couldPlayIfEnoughData(); + // "pausedToBuffer" means the media engine's rate is 0, but only because it had to stop playing + // when it ran out of buffered data. A movie is this state is "potentially playing", modulo the + // checks in couldPlayIfEnoughData(). + bool pausedToBuffer = m_readyStateMaximum >= HAVE_FUTURE_DATA && m_readyState < HAVE_FUTURE_DATA; + return (pausedToBuffer || m_readyState >= HAVE_FUTURE_DATA) && couldPlayIfEnoughData(); } bool HTMLMediaElement::couldPlayIfEnoughData() const diff --git a/WebCore/html/HTMLMediaElement.h b/WebCore/html/HTMLMediaElement.h index 83e1f2c..9c36438 100644 --- a/WebCore/html/HTMLMediaElement.h +++ b/WebCore/html/HTMLMediaElement.h @@ -296,6 +296,7 @@ private: bool m_webkitPreservesPitch; NetworkState m_networkState; ReadyState m_readyState; + ReadyState m_readyStateMaximum; String m_currentSrc; RefPtr<MediaError> m_error; @@ -361,6 +362,8 @@ private: #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) bool m_needWidgetUpdate : 1; #endif + + bool m_dispatchingCanPlayEvent : 1; }; } //namespace diff --git a/WebCore/html/HTMLOptionElement.cpp b/WebCore/html/HTMLOptionElement.cpp index 2752cbb..1280d32 100644 --- a/WebCore/html/HTMLOptionElement.cpp +++ b/WebCore/html/HTMLOptionElement.cpp @@ -190,11 +190,15 @@ void HTMLOptionElement::childrenChanged(bool changedByParser, Node* beforeChange HTMLSelectElement* HTMLOptionElement::ownerSelectElement() const { Node* select = parentNode(); +<<<<<<< HEAD:WebCore/html/HTMLOptionElement.cpp #ifdef ANDROID_FIX while (select && !(select->hasTagName(selectTag) || select->hasTagName(keygenTag))) #else while (select && !select->hasTagName(selectTag)) #endif +======= + while (select && !(select->hasTagName(selectTag) || select->hasTagName(keygenTag))) +>>>>>>> webkit.org at r58956:WebCore/html/HTMLOptionElement.cpp select = select->parentNode(); if (!select) diff --git a/WebCore/html/HTMLParser.cpp b/WebCore/html/HTMLParser.cpp index c5839a8..428e8d5 100644 --- a/WebCore/html/HTMLParser.cpp +++ b/WebCore/html/HTMLParser.cpp @@ -57,7 +57,9 @@ #include "Page.h" #include "Settings.h" #include "Text.h" +#include "TreeDepthLimit.h" #include <wtf/StdLibExtras.h> +#include <wtf/dtoa.h> namespace WebCore { @@ -132,6 +134,7 @@ HTMLParser::HTMLParser(HTMLDocument* doc, bool reportErrors) , m_didRefCurrent(false) , m_blockStack(0) , m_blocksInStack(0) + , m_treeDepth(0) , m_hasPElementInScope(NotInScope) , m_inBody(false) , m_haveContent(false) @@ -151,6 +154,7 @@ HTMLParser::HTMLParser(DocumentFragment* frag, FragmentScriptingPermission scrip , m_didRefCurrent(true) , m_blockStack(0) , m_blocksInStack(0) + , m_treeDepth(0) , m_hasPElementInScope(NotInScope) , m_inBody(true) , m_haveContent(false) @@ -181,6 +185,7 @@ void HTMLParser::reset() freeBlock(); + m_treeDepth = 0; m_inBody = false; m_haveFrameSet = false; m_haveContent = false; @@ -213,17 +218,19 @@ inline static int tagPriorityOfNode(Node* n) return n->isHTMLElement() ? static_cast<HTMLElement*>(n)->tagPriority() : 0; } -inline void HTMLParser::limitBlockDepth(int tagPriority) +inline void HTMLParser::limitDepth(int tagPriority) { + while (m_treeDepth >= maxDOMTreeDepth) + popBlock(m_blockStack->tagName); if (tagPriority >= minBlockLevelTagPriority) { while (m_blocksInStack >= cMaxBlockDepth) popBlock(m_blockStack->tagName); } } -inline bool HTMLParser::insertNodeAfterLimitBlockDepth(Node* n, bool flat) +inline bool HTMLParser::insertNodeAfterLimitDepth(Node* n, bool flat) { - limitBlockDepth(tagPriorityOfNode(n)); + limitDepth(tagPriorityOfNode(n)); return insertNode(n, flat); } @@ -265,7 +272,7 @@ PassRefPtr<Node> HTMLParser::parseToken(Token* t) while (charsLeft) { // split large blocks of text to nodes of manageable size n = Text::createWithLengthLimit(m_document, text, charsLeft); - if (!insertNodeAfterLimitBlockDepth(n.get(), t->selfClosingTag)) + if (!insertNodeAfterLimitDepth(n.get(), t->selfClosingTag)) return 0; } return n; @@ -296,7 +303,7 @@ PassRefPtr<Node> HTMLParser::parseToken(Token* t) } } - if (!insertNodeAfterLimitBlockDepth(n.get(), t->selfClosingTag)) { + if (!insertNodeAfterLimitDepth(n.get(), t->selfClosingTag)) { // we couldn't insert the node if (n->isElementNode()) { @@ -1188,8 +1195,8 @@ void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem) prevElem->node = currElem->node; prevElem->didRefNode = currElem->didRefNode; delete currElem; - } - else + m_treeDepth--; + } else prevElem = currElem; currElem = nextElem; } @@ -1290,6 +1297,7 @@ void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem) prevElem->derefNode(); prevElem->node = elem->node; prevElem->didRefNode = elem->didRefNode; + m_treeDepth--; if (!finished) { // Repurpose |elem| to represent |newNode| and insert it at the appropriate position // in the stack. We do not do this for the innermost block, because in that case the new @@ -1303,6 +1311,7 @@ void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem) prevMaxElem->node = newNodePtr; newNodePtr->ref(); prevMaxElem->didRefNode = true; + m_treeDepth++; } else delete elem; } @@ -1399,6 +1408,7 @@ void HTMLParser::pushBlock(const AtomicString& tagName, int level) m_blockStack = new HTMLStackElem(tagName, level, m_current, m_didRefCurrent, m_blockStack); if (level >= minBlockLevelTagPriority) m_blocksInStack++; + m_treeDepth++; m_didRefCurrent = false; if (tagName == pTag) m_hasPElementInScope = InScope; @@ -1508,6 +1518,7 @@ inline HTMLStackElem* HTMLParser::popOneBlockCommon() ASSERT(m_blocksInStack > 0); m_blocksInStack--; } + m_treeDepth--; m_blockStack = elem->next; m_current = elem->node; m_didRefCurrent = elem->didRefNode; @@ -1583,6 +1594,7 @@ void HTMLParser::freeBlock() while (m_blockStack) popOneBlock(); ASSERT(!m_blocksInStack); + ASSERT(!m_treeDepth); } void HTMLParser::createHead() @@ -1728,4 +1740,41 @@ bool shouldCreateImplicitHead(Document* document) } #endif + +String serializeForNumberType(double number) +{ + // According to HTML5, "the best representation of the number n as a floating + // point number" is a string produced by applying ToString() to n. + DtoaBuffer buffer; + unsigned length; + doubleToStringInJavaScriptFormat(number, buffer, &length); + return String(buffer, length); +} + +bool parseToDoubleForNumberType(const String& src, double* out) +{ + // See HTML5 2.4.4.3 `Real numbers.' + + if (src.isEmpty()) + return false; + // String::toDouble() accepts leading + \t \n \v \f \r and SPACE, which are invalid in HTML5. + // So, check the first character. + if (src[0] != '-' && (src[0] < '0' || src[0] > '9')) + return false; + + bool valid = false; + double value = src.toDouble(&valid); + if (!valid) + return false; + // NaN and Infinity are not valid numbers according to the standard. + if (!isfinite(value)) + return false; + // -0 -> 0 + if (!value) + value = 0; + if (out) + *out = value; + return true; +} + } diff --git a/WebCore/html/HTMLParser.h b/WebCore/html/HTMLParser.h index acb6a6f..028836c 100644 --- a/WebCore/html/HTMLParser.h +++ b/WebCore/html/HTMLParser.h @@ -112,9 +112,8 @@ private: void processCloseTag(Token*); - void limitBlockDepth(int tagPriority); - - bool insertNodeAfterLimitBlockDepth(Node*, bool flat = false); + void limitDepth(int tagPriority); + bool insertNodeAfterLimitDepth(Node*, bool flat = false); bool insertNode(Node*, bool flat = false); bool handleError(Node*, bool flat, const AtomicString& localName, int tagPriority); @@ -170,6 +169,8 @@ private: // currently in m_blockStack. The parser enforces a cap on this value by // adding such new elements as siblings instead of children once it is reached. size_t m_blocksInStack; + // Depth of the tree. + unsigned m_treeDepth; enum ElementInScopeState { NotInScope, InScope, Unknown }; ElementInScopeState m_hasPElementInScope; @@ -200,6 +201,14 @@ bool shouldCreateImplicitHead(Document*); inline bool shouldCreateImplicitHead(Document*) { return true; } #endif +// Converts the specified string to a floating number. +// If the conversion fails, the return value is false. Take care that leading or trailing unnecessary characters make failures. This returns false for an empty string input. +// The double* parameter may be 0. +bool parseToDoubleForNumberType(const String&, double*); +// Converts the specified number to a string. This is an implementation of +// HTML5's "algorithm to convert a number to a string" for NUMBER/RANGE types. +String serializeForNumberType(double); + } #endif // HTMLParser_h diff --git a/WebCore/html/HTMLProgressElement.cpp b/WebCore/html/HTMLProgressElement.cpp index 6fa8043..84a9794 100644 --- a/WebCore/html/HTMLProgressElement.cpp +++ b/WebCore/html/HTMLProgressElement.cpp @@ -26,6 +26,7 @@ #include "FormDataList.h" #include "HTMLFormElement.h" #include "HTMLNames.h" +#include "HTMLParser.h" #include "MappedAttribute.h" #include "RenderProgress.h" #include <wtf/StdLibExtras.h> @@ -35,7 +36,7 @@ namespace WebCore { using namespace HTMLNames; HTMLProgressElement::HTMLProgressElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form) - : HTMLFormControlElement(tagName, document, form, CreateElement) + : HTMLFormControlElement(tagName, document, form, CreateHTMLElement) { ASSERT(hasTagName(progressTag)); } @@ -71,29 +72,37 @@ void HTMLProgressElement::parseMappedAttribute(MappedAttribute* attribute) double HTMLProgressElement::value() const { const AtomicString& valueString = getAttribute(valueAttr); - bool ok; - double value = valueString.toDouble(&ok); + double value; + bool ok = parseToDoubleForNumberType(valueString, &value); if (!ok || value < 0) return valueString.isNull() ? 1 : 0; return (value > max()) ? max() : value; } -void HTMLProgressElement::setValue(double value) +void HTMLProgressElement::setValue(double value, ExceptionCode& ec) { + if (!isfinite(value)) { + ec = NOT_SUPPORTED_ERR; + return; + } setAttribute(valueAttr, String::number(value >= 0 ? value : 0)); } double HTMLProgressElement::max() const { - bool ok; - double max = getAttribute(maxAttr).toDouble(&ok); + double max; + bool ok = parseToDoubleForNumberType(getAttribute(maxAttr), &max); if (!ok || max <= 0) return 1; return max; } -void HTMLProgressElement::setMax(double max) +void HTMLProgressElement::setMax(double max, ExceptionCode& ec) { + if (!isfinite(max)) { + ec = NOT_SUPPORTED_ERR; + return; + } setAttribute(maxAttr, String::number(max > 0 ? max : 1)); } diff --git a/WebCore/html/HTMLProgressElement.h b/WebCore/html/HTMLProgressElement.h index a925fc5..eaf4ce9 100644 --- a/WebCore/html/HTMLProgressElement.h +++ b/WebCore/html/HTMLProgressElement.h @@ -31,10 +31,10 @@ public: static PassRefPtr<HTMLProgressElement> create(const QualifiedName&, Document*, HTMLFormElement* = 0); double value() const; - void setValue(double); + void setValue(double, ExceptionCode&); double max() const; - void setMax(double); + void setMax(double, ExceptionCode&); double position() const; diff --git a/WebCore/html/HTMLProgressElement.idl b/WebCore/html/HTMLProgressElement.idl index 8da62aa..935bd95 100644 --- a/WebCore/html/HTMLProgressElement.idl +++ b/WebCore/html/HTMLProgressElement.idl @@ -21,8 +21,10 @@ module html { interface [ Conditional=PROGRESS_TAG ] HTMLProgressElement : HTMLElement { - attribute double value; - attribute double max; + attribute double value + setter raises(DOMException); + attribute double max + setter raises(DOMException); readonly attribute double position; readonly attribute HTMLFormElement form; }; diff --git a/WebCore/html/HTMLSelectElement.cpp b/WebCore/html/HTMLSelectElement.cpp index de40ff7..12ec26f 100644 --- a/WebCore/html/HTMLSelectElement.cpp +++ b/WebCore/html/HTMLSelectElement.cpp @@ -323,7 +323,7 @@ void HTMLSelectElement::dispatchBlurEvent() void HTMLSelectElement::defaultEventHandler(Event* event) { - SelectElement::defaultEventHandler(m_data, this, event, form()); + SelectElement::defaultEventHandler(m_data, this, event); if (event->defaultHandled()) return; HTMLFormControlElementWithState::defaultEventHandler(event); diff --git a/WebCore/html/HTMLTextAreaElement.cpp b/WebCore/html/HTMLTextAreaElement.cpp index 2bfde03..cdb7cdb 100644 --- a/WebCore/html/HTMLTextAreaElement.cpp +++ b/WebCore/html/HTMLTextAreaElement.cpp @@ -245,7 +245,12 @@ void HTMLTextAreaElement::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent* unsigned unsignedMaxLength = static_cast<unsigned>(signedMaxLength); unsigned currentLength = numGraphemeClusters(toRenderTextControl(renderer())->text()); - unsigned selectionLength = numGraphemeClusters(plainText(document()->frame()->selection()->selection().toNormalizedRange().get())); + // selectionLength represents the selection length of this text field to be + // removed by this insertion. + // If the text field has no focus, we don't need to take account of the + // selection length. The selection is the source of text drag-and-drop in + // that case, and nothing in the text field will be removed. + unsigned selectionLength = focused() ? numGraphemeClusters(plainText(document()->frame()->selection()->selection().toNormalizedRange().get())) : 0; ASSERT(currentLength >= selectionLength); unsigned baseLength = currentLength - selectionLength; unsigned appendableLength = unsignedMaxLength > baseLength ? unsignedMaxLength - baseLength : 0; diff --git a/WebCore/html/HTMLTextAreaElement.h b/WebCore/html/HTMLTextAreaElement.h index 8d92a48..f75f076 100644 --- a/WebCore/html/HTMLTextAreaElement.h +++ b/WebCore/html/HTMLTextAreaElement.h @@ -60,7 +60,6 @@ public: virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); virtual bool appendFormData(FormDataList&, bool); virtual void reset(); - virtual void defaultEventHandler(Event*); virtual bool isMouseFocusable() const; virtual bool isKeyboardFocusable(KeyboardEvent*) const; virtual void updateFocusAppearance(bool restorePreviousSelection); @@ -104,6 +103,8 @@ private: virtual bool isOptionalFormControl() const { return !isRequiredFormControl(); } virtual bool isRequiredFormControl() const { return required(); } + virtual void defaultEventHandler(Event*); + int m_rows; int m_cols; WrapMethod m_wrap; diff --git a/WebCore/html/HTMLTokenizer.h b/WebCore/html/HTMLTokenizer.h index ef7cbfc..290fc5c 100644 --- a/WebCore/html/HTMLTokenizer.h +++ b/WebCore/html/HTMLTokenizer.h @@ -141,6 +141,7 @@ public: virtual void write(const SegmentedString&, bool appendData); virtual void finish(); + virtual bool forceSynchronous() const { return m_state.forceSynchronous(); } virtual void setForceSynchronous(bool force); virtual bool isWaitingForScripts() const; virtual void stopParsing(); @@ -155,6 +156,7 @@ public: virtual void executeScriptsWaitingForStylesheets(); virtual bool isHTMLTokenizer() const { return true; } + virtual HTMLTokenizer* asHTMLTokenizer() { return this; } HTMLParser* htmlParser() const { return m_parser.get(); } private: diff --git a/WebCore/html/StepRange.cpp b/WebCore/html/StepRange.cpp index 7c270f2..04f4ed3 100644 --- a/WebCore/html/StepRange.cpp +++ b/WebCore/html/StepRange.cpp @@ -23,6 +23,7 @@ #include "HTMLInputElement.h" #include "HTMLNames.h" +#include "HTMLParser.h" #include "PlatformString.h" #include <wtf/MathExtras.h> @@ -61,7 +62,7 @@ double StepRange::clampValue(double value) double StepRange::clampValue(const String& stringValue) { double value; - bool parseSuccess = HTMLInputElement::parseToDoubleForNumberType(stringValue, &value); + bool parseSuccess = parseToDoubleForNumberType(stringValue, &value); if (!parseSuccess) value = (minimum + maximum) / 2; return clampValue(value); @@ -70,7 +71,7 @@ double StepRange::clampValue(const String& stringValue) double StepRange::valueFromElement(HTMLInputElement* element, bool* wasClamped) { double oldValue; - bool parseSuccess = HTMLInputElement::parseToDoubleForNumberType(element->value(), &oldValue); + bool parseSuccess = parseToDoubleForNumberType(element->value(), &oldValue); if (!parseSuccess) oldValue = (minimum + maximum) / 2; double newValue = clampValue(oldValue); diff --git a/WebCore/html/TextMetrics.h b/WebCore/html/TextMetrics.h index 34a3378..14cdb67 100644 --- a/WebCore/html/TextMetrics.h +++ b/WebCore/html/TextMetrics.h @@ -34,6 +34,7 @@ class TextMetrics : public RefCounted<TextMetrics> { public: static PassRefPtr<TextMetrics> create() { return adoptRef(new TextMetrics); } + // FIXME: Is coercing to an integer value intentional? If so, there should be a static_cast<unsigned>() here. unsigned width() const { return m_width; } void setWidth(float w) { m_width = w; } diff --git a/WebCore/html/ValidityState.cpp b/WebCore/html/ValidityState.cpp index c6c58a5..fc60a22 100644 --- a/WebCore/html/ValidityState.cpp +++ b/WebCore/html/ValidityState.cpp @@ -26,6 +26,7 @@ #include "HTMLInputElement.h" #include "HTMLNames.h" +#include "HTMLParser.h" #include "KURL.h" #include "LocalizedStrings.h" #include "RegularExpression.h" @@ -80,7 +81,7 @@ bool ValidityState::typeMismatch() const case HTMLInputElement::COLOR: return !isValidColorString(value); case HTMLInputElement::NUMBER: - return !HTMLInputElement::parseToDoubleForNumberType(value, 0); + return !parseToDoubleForNumberType(value, 0); case HTMLInputElement::URL: return !KURL(KURL(), value).isValid(); case HTMLInputElement::EMAIL: { diff --git a/WebCore/html/canvas/CanvasObject.h b/WebCore/html/canvas/CanvasObject.h index b7b016a..6f89f12 100644 --- a/WebCore/html/canvas/CanvasObject.h +++ b/WebCore/html/canvas/CanvasObject.h @@ -51,6 +51,13 @@ namespace WebCore { WebGLRenderingContext* context() const { return m_context; } + virtual bool isBuffer() const { return false; } + virtual bool isFramebuffer() const { return false; } + virtual bool isProgram() const { return false; } + virtual bool isRenderbuffer() const { return false; } + virtual bool isShader() const { return false; } + virtual bool isTexture() const { return false; } + protected: CanvasObject(WebGLRenderingContext*); virtual void _deleteObject(Platform3DObject) = 0; diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/WebCore/html/canvas/CanvasRenderingContext2D.cpp index 3732487..615b45d 100644 --- a/WebCore/html/canvas/CanvasRenderingContext2D.cpp +++ b/WebCore/html/canvas/CanvasRenderingContext2D.cpp @@ -615,7 +615,10 @@ static bool validateRectForCanvas(float& x, float& y, float& width, float& heigh { if (!isfinite(x) | !isfinite(y) | !isfinite(width) | !isfinite(height)) return false; - + + if (!width && !height) + return false; + if (width < 0) { width = -width; x -= width; diff --git a/WebCore/html/canvas/WebGLBuffer.h b/WebCore/html/canvas/WebGLBuffer.h index bdb7052..f56d374 100644 --- a/WebCore/html/canvas/WebGLBuffer.h +++ b/WebCore/html/canvas/WebGLBuffer.h @@ -64,6 +64,8 @@ namespace WebCore { virtual void _deleteObject(Platform3DObject o); private: + virtual bool isBuffer() const { return true; } + RefPtr<WebGLArrayBuffer> m_elementArrayBuffer; unsigned m_elementArrayBufferByteLength; unsigned m_arrayBufferByteLength; diff --git a/WebCore/html/canvas/WebGLFramebuffer.h b/WebCore/html/canvas/WebGLFramebuffer.h index b9402a0..71e5a27 100644 --- a/WebCore/html/canvas/WebGLFramebuffer.h +++ b/WebCore/html/canvas/WebGLFramebuffer.h @@ -50,7 +50,9 @@ namespace WebCore { virtual void _deleteObject(Platform3DObject); - private: + private: + virtual bool isFramebuffer() const { return true; } + bool m_isDepthAttached; bool m_isStencilAttached; bool m_isDepthStencilAttached; diff --git a/WebCore/html/canvas/WebGLProgram.h b/WebCore/html/canvas/WebGLProgram.h index 56bce15..b13fc22 100644 --- a/WebCore/html/canvas/WebGLProgram.h +++ b/WebCore/html/canvas/WebGLProgram.h @@ -45,13 +45,15 @@ namespace WebCore { bool cacheActiveAttribLocations(); int numActiveAttribLocations(); int getActiveAttribLocation(int index); - + protected: WebGLProgram(WebGLRenderingContext*); virtual void _deleteObject(Platform3DObject); private: + virtual bool isProgram() const { return true; } + Vector<int> m_activeAttribLocations; }; diff --git a/WebCore/html/canvas/WebGLRenderbuffer.cpp b/WebCore/html/canvas/WebGLRenderbuffer.cpp index cad4298..0ac9c7e 100644 --- a/WebCore/html/canvas/WebGLRenderbuffer.cpp +++ b/WebCore/html/canvas/WebGLRenderbuffer.cpp @@ -37,11 +37,6 @@ PassRefPtr<WebGLRenderbuffer> WebGLRenderbuffer::create(WebGLRenderingContext* c return adoptRef(new WebGLRenderbuffer(ctx)); } -PassRefPtr<WebGLRenderbuffer> WebGLRenderbuffer::create(WebGLRenderingContext* ctx, Platform3DObject obj) -{ - return adoptRef(new WebGLRenderbuffer(ctx, obj)); -} - WebGLRenderbuffer::WebGLRenderbuffer(WebGLRenderingContext* ctx) : CanvasObject(ctx) , m_internalformat(GraphicsContext3D::RGBA4) @@ -49,13 +44,6 @@ WebGLRenderbuffer::WebGLRenderbuffer(WebGLRenderingContext* ctx) setObject(context()->graphicsContext3D()->createRenderbuffer()); } -WebGLRenderbuffer::WebGLRenderbuffer(WebGLRenderingContext* ctx, Platform3DObject obj) - : CanvasObject(ctx) - , m_internalformat(GraphicsContext3D::RGBA4) -{ - setObject(obj, false); -} - void WebGLRenderbuffer::_deleteObject(Platform3DObject object) { context()->graphicsContext3D()->deleteRenderbuffer(object); diff --git a/WebCore/html/canvas/WebGLRenderbuffer.h b/WebCore/html/canvas/WebGLRenderbuffer.h index 1bdf1b7..e399012 100644 --- a/WebCore/html/canvas/WebGLRenderbuffer.h +++ b/WebCore/html/canvas/WebGLRenderbuffer.h @@ -38,21 +38,18 @@ namespace WebCore { virtual ~WebGLRenderbuffer() { deleteObject(); } static PassRefPtr<WebGLRenderbuffer> create(WebGLRenderingContext*); - - // For querying previously created objects via e.g. getFramebufferAttachmentParameter - // FIXME: should consider canonicalizing these objects - static PassRefPtr<WebGLRenderbuffer> create(WebGLRenderingContext*, Platform3DObject renderbuffer); void setInternalformat(unsigned long internalformat) { m_internalformat = internalformat; } unsigned long getInternalformat() const { return m_internalformat; } protected: WebGLRenderbuffer(WebGLRenderingContext*); - WebGLRenderbuffer(WebGLRenderingContext*, Platform3DObject); virtual void _deleteObject(Platform3DObject); - private: + private: + virtual bool isRenderbuffer() const { return true; } + unsigned long m_internalformat; }; diff --git a/WebCore/html/canvas/WebGLRenderingContext.cpp b/WebCore/html/canvas/WebGLRenderingContext.cpp index d9af757..54ba17f 100644 --- a/WebCore/html/canvas/WebGLRenderingContext.cpp +++ b/WebCore/html/canvas/WebGLRenderingContext.cpp @@ -101,8 +101,6 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa m_implementationColorReadFormat = implementationColorReadFormat; int implementationColorReadType = GraphicsContext3D::UNSIGNED_BYTE; m_context->getIntegerv(GraphicsContext3D::IMPLEMENTATION_COLOR_READ_TYPE, &implementationColorReadType); - // FIXME: remove the getError() when IMPLEMENTATION_COLOR_READ_FORMAT/TYPE are supported. - m_context->getError(); m_implementationColorReadType = implementationColorReadType; m_context->reshape(canvas()->width(), canvas()->height()); m_context->viewport(0, 0, canvas()->width(), canvas()->height()); @@ -815,7 +813,7 @@ void WebGLRenderingContext::framebufferRenderbuffer(unsigned long target, unsign m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } - if (buffer->object()) { + if (buffer && buffer->object()) { bool isConflicted = false; bool isDepthOrStencil = true; switch (attachment) { @@ -981,18 +979,11 @@ WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(unsigned l m_context->getFramebufferAttachmentParameteriv(target, attachment, GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type); int value = 0; m_context->getFramebufferAttachmentParameteriv(target, attachment, GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &value); - // FIXME: should consider canonicalizing these objects switch (type) { - case GraphicsContext3D::RENDERBUFFER: { - RefPtr<WebGLRenderbuffer> tmp = WebGLRenderbuffer::create(this, value); - addObject(tmp.get()); - return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(tmp)); - } - case GraphicsContext3D::TEXTURE: { - RefPtr<WebGLTexture> tmp = WebGLTexture::create(this, value); - addObject(tmp.get()); - return WebGLGetInfo(PassRefPtr<WebGLTexture>(tmp)); - } + case GraphicsContext3D::RENDERBUFFER: + return WebGLGetInfo(findRenderbuffer(static_cast<Platform3DObject>(value))); + case GraphicsContext3D::TEXTURE: + return WebGLGetInfo(findTexture(static_cast<Platform3DObject>(value))); default: // FIXME: raise exception? return WebGLGetInfo(); @@ -1070,6 +1061,10 @@ WebGLGetInfo WebGLRenderingContext::getParameter(unsigned long pname, ExceptionC return getUnsignedLongParameter(pname); case GraphicsContext3D::GREEN_BITS: return getLongParameter(pname); + case GraphicsContext3D::IMPLEMENTATION_COLOR_READ_FORMAT: + return getLongParameter(pname); + case GraphicsContext3D::IMPLEMENTATION_COLOR_READ_TYPE: + return getLongParameter(pname); case GraphicsContext3D::LINE_WIDTH: return getFloatParameter(pname); case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS: @@ -1639,7 +1634,7 @@ PassRefPtr<WebGLArray> WebGLRenderingContext::readPixels(long x, long y, unsigne m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); return 0; } - if (!(format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE || format == m_implementationColorReadFormat && type == m_implementationColorReadFormat)) { + if (!((format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE) || (format == m_implementationColorReadFormat && type == m_implementationColorReadType))) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return 0; } @@ -1764,71 +1759,126 @@ void WebGLRenderingContext::stencilOpSeparate(unsigned long face, unsigned long cleanupAfterGraphicsCall(false); } -void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat, - unsigned width, unsigned height, unsigned border, - unsigned format, unsigned type, WebGLArray* pixels, ExceptionCode& ec) +void WebGLRenderingContext::texImage2DBase(unsigned target, unsigned level, unsigned internalformat, + unsigned width, unsigned height, unsigned border, + unsigned format, unsigned type, void* pixels, ExceptionCode& ec) { // FIXME: For now we ignore any errors returned - // FIXME: Need to make sure passed buffer has enough bytes to define the texture ec = 0; m_context->texImage2D(target, level, internalformat, width, height, - border, format, type, pixels ? pixels->baseAddress() : 0); + border, format, type, pixels); cleanupAfterGraphicsCall(false); } -void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, ImageData* pixels, +void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, Image* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec) { - // FIXME: For now we ignore any errors returned ec = 0; Vector<uint8_t> data; - m_context->extractImageData(pixels, flipY, premultiplyAlpha, data); - m_context->texImage2D(target, level, GraphicsContext3D::RGBA, pixels->width(), pixels->height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, data.data()); - cleanupAfterGraphicsCall(false); + unsigned int format, internalformat; + if (!m_context->extractImageData(image, flipY, premultiplyAlpha, data, &format, &internalformat)) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + texImage2DBase(target, level, internalformat, image->width(), image->height(), 0, + format, GraphicsContext3D::UNSIGNED_BYTE, data.data(), ec); } -void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLImageElement* image, +void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned internalformat, + unsigned width, unsigned height, unsigned border, + unsigned format, unsigned type, WebGLArray* pixels, ExceptionCode& ec) +{ + // FIXME: Need to make sure passed buffer has enough bytes to define the texture + texImage2DBase(target, level, internalformat, width, height, border, + format, type, pixels ? pixels->baseAddress() : 0, ec); +} + +void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, ImageData* pixels, + ExceptionCode& ec) +{ + texImage2D(target, level, pixels, 0, 0, ec); +} + +void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, ImageData* pixels, + bool flipY, ExceptionCode& ec) +{ + texImage2D(target, level, pixels, flipY, 0, ec); +} + +void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, ImageData* pixels, bool flipY, bool premultiplyAlpha, ExceptionCode& ec) { ec = 0; - if (!image) { + Vector<uint8_t> data; + if (!m_context->extractImageData(pixels, flipY, premultiplyAlpha, data)) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); return; } + texImage2DBase(target, level, GraphicsContext3D::RGBA, pixels->width(), pixels->height(), 0, + GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, data.data(), ec); +} + + +void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLImageElement* image, + ExceptionCode& ec) +{ + texImage2D(target, level, image, 0, 0, ec); +} + +void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLImageElement* image, + bool flipY, ExceptionCode& ec) +{ + texImage2D(target, level, image, flipY, 0, ec); +} - CachedImage* cachedImage = image->cachedImage(); - if (!cachedImage) { +void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLImageElement* image, + bool flipY, bool premultiplyAlpha, ExceptionCode& ec) +{ + ec = 0; + if (!image || !image->cachedImage()) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); return; } + texImage2D(target, level, image->cachedImage()->image(), flipY, premultiplyAlpha, ec); +} - // FIXME: For now we ignore any errors returned - m_context->texImage2D(target, level, cachedImage->image(), flipY, premultiplyAlpha); - cleanupAfterGraphicsCall(false); +void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas, + ExceptionCode& ec) +{ + texImage2D(target, level, canvas, 0, 0, ec); } void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas, - bool flipY, bool premultiplyAlpha, ExceptionCode& ec) + bool flipY, ExceptionCode& ec) +{ + texImage2D(target, level, canvas, flipY, 0, ec); +} + +void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas, + bool flipY, bool premultiplyAlpha, ExceptionCode& ec) { ec = 0; - if (!canvas) { + if (!canvas || !canvas->buffer()) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); return; } + texImage2D(target, level, canvas->buffer()->image(), flipY, premultiplyAlpha, ec); +} - ImageBuffer* buffer = canvas->buffer(); - if (!buffer) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); - return; - } +void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLVideoElement* video, + ExceptionCode& ec) +{ + texImage2D(target, level, video, 0, 0, ec); +} - // FIXME: For now we ignore any errors returned - m_context->texImage2D(target, level, buffer->image(), flipY, premultiplyAlpha); - cleanupAfterGraphicsCall(false); +void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLVideoElement* video, + bool flipY, ExceptionCode& ec) +{ + texImage2D(target, level, video, flipY, 0, ec); } void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, HTMLVideoElement* video, - bool flipY, bool premultiplyAlpha, ExceptionCode& ec) + bool flipY, bool premultiplyAlpha, ExceptionCode& ec) { // FIXME: Need implement this call UNUSED_PARAM(target); @@ -1853,66 +1903,121 @@ void WebGLRenderingContext::texParameteri(unsigned target, unsigned pname, int p cleanupAfterGraphicsCall(false); } -void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, - unsigned width, unsigned height, - unsigned format, unsigned type, WebGLArray* pixels, ExceptionCode& ec) +void WebGLRenderingContext::texSubImage2DBase(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, + unsigned width, unsigned height, + unsigned format, unsigned type, void* pixels, ExceptionCode& ec) { // FIXME: For now we ignore any errors returned - // FIXME: Need to make sure passed buffer has enough bytes to define the texture ec = 0; - m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels ? pixels->baseAddress() : 0); + m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); cleanupAfterGraphicsCall(false); } void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, - ImageData* pixels, bool flipY, bool premultiplyAlpha, ExceptionCode& ec) + Image* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec) { - // FIXME: For now we ignore any errors returned ec = 0; Vector<uint8_t> data; - m_context->extractImageData(pixels, flipY, premultiplyAlpha, data); - m_context->texSubImage2D(target, level, xoffset, yoffset, pixels->width(), pixels->height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, data.data()); - cleanupAfterGraphicsCall(false); + unsigned int format, internalformat; + if (!m_context->extractImageData(image, flipY, premultiplyAlpha, data, &format, &internalformat)) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); + return; + } + texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), + format, GraphicsContext3D::UNSIGNED_BYTE, data.data(), ec); } void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, - HTMLImageElement* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec) + unsigned width, unsigned height, + unsigned format, unsigned type, WebGLArray* pixels, ExceptionCode& ec) +{ + // FIXME: Need to make sure passed buffer has enough bytes to define the texture + texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, pixels ? pixels->baseAddress() : 0, ec); +} + +void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, + ImageData* pixels, ExceptionCode& ec) +{ + texSubImage2D(target, level, xoffset, yoffset, pixels, 0, 0, ec); +} + +void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, + ImageData* pixels, bool flipY, ExceptionCode& ec) +{ + texSubImage2D(target, level, xoffset, yoffset, pixels, flipY, 0, ec); +} + +void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, + ImageData* pixels, bool flipY, bool premultiplyAlpha, ExceptionCode& ec) { - // FIXME: For now we ignore any errors returned ec = 0; - if (!image) { + Vector<uint8_t> data; + if (!m_context->extractImageData(pixels, flipY, premultiplyAlpha, data)) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); return; } - - CachedImage* cachedImage = image->cachedImage(); - if (!cachedImage) { + texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), + GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, data.data(), ec); +} + +void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, + HTMLImageElement* image, ExceptionCode& ec) +{ + texSubImage2D(target, level, xoffset, yoffset, image, 0, 0, ec); +} + +void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, + HTMLImageElement* image, bool flipY, ExceptionCode& ec) +{ + texSubImage2D(target, level, xoffset, yoffset, image, flipY, 0, ec); +} + +void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, + HTMLImageElement* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec) +{ + ec = 0; + if (!image || !image->cachedImage()) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); return; } + texSubImage2D(target, level, xoffset, yoffset, image->cachedImage()->image(), + flipY, premultiplyAlpha, ec); +} - m_context->texSubImage2D(target, level, xoffset, yoffset, cachedImage->image(), flipY, premultiplyAlpha); - cleanupAfterGraphicsCall(false); +void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, + HTMLCanvasElement* canvas, ExceptionCode& ec) +{ + texSubImage2D(target, level, xoffset, yoffset, canvas, 0, 0, ec); +} + +void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, + HTMLCanvasElement* canvas, bool flipY, ExceptionCode& ec) +{ + texSubImage2D(target, level, xoffset, yoffset, canvas, flipY, 0, ec); } void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, HTMLCanvasElement* canvas, bool flipY, bool premultiplyAlpha, ExceptionCode& ec) { ec = 0; - if (!canvas) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); - return; - } - - ImageBuffer* buffer = canvas->buffer(); - if (!buffer) { + if (!canvas || !canvas->buffer()) { m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); return; } - - // FIXME: For now we ignore any errors returned - m_context->texSubImage2D(target, level, xoffset, yoffset, buffer->image(), flipY, premultiplyAlpha); - cleanupAfterGraphicsCall(false); + texSubImage2D(target, level, xoffset, yoffset, canvas->buffer()->image(), + flipY, premultiplyAlpha, ec); +} + +void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, + HTMLVideoElement* video, ExceptionCode& ec) +{ + texSubImage2D(target, level, xoffset, yoffset, video, 0, 0, ec); +} + +void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, + HTMLVideoElement* video, bool flipY, ExceptionCode& ec) +{ + texSubImage2D(target, level, xoffset, yoffset, video, flipY, 0, ec); } void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, @@ -2731,6 +2836,30 @@ void WebGLRenderingContext::detachAndRemoveAllObjects() m_canvasObjects.clear(); } +PassRefPtr<WebGLTexture> WebGLRenderingContext::findTexture(Platform3DObject obj) +{ + HashSet<RefPtr<CanvasObject> >::iterator pend = m_canvasObjects.end(); + for (HashSet<RefPtr<CanvasObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) { + if ((*it)->isTexture() && (*it)->object() == obj) { + RefPtr<WebGLTexture> tex = reinterpret_cast<WebGLTexture*>((*it).get()); + return tex.release(); + } + } + return 0; +} + +PassRefPtr<WebGLRenderbuffer> WebGLRenderingContext::findRenderbuffer(Platform3DObject obj) +{ + HashSet<RefPtr<CanvasObject> >::iterator pend = m_canvasObjects.end(); + for (HashSet<RefPtr<CanvasObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) { + if ((*it)->isRenderbuffer() && (*it)->object() == obj) { + RefPtr<WebGLRenderbuffer> buffer = reinterpret_cast<WebGLRenderbuffer*>((*it).get()); + return buffer.release(); + } + } + return 0; +} + WebGLGetInfo WebGLRenderingContext::getBooleanParameter(unsigned long pname) { unsigned char value; @@ -2819,6 +2948,11 @@ WebGLGetInfo WebGLRenderingContext::getWebGLUnsignedByteArrayParameter(unsigned return WebGLGetInfo(WebGLUnsignedByteArray::create(value, length)); } +bool WebGLRenderingContext::isGLES2Compliant() +{ + return m_context->isGLES2Compliant(); +} + } // namespace WebCore #endif // ENABLE(3D_CANVAS) diff --git a/WebCore/html/canvas/WebGLRenderingContext.h b/WebCore/html/canvas/WebGLRenderingContext.h index 9c58a53..aefa6cc 100644 --- a/WebCore/html/canvas/WebGLRenderingContext.h +++ b/WebCore/html/canvas/WebGLRenderingContext.h @@ -199,14 +199,18 @@ class WebKitCSSMatrix; void texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, WebGLArray* pixels, ExceptionCode&); - void texImage2D(unsigned target, unsigned level, ImageData* pixels, - bool flipY, bool premultiplyAlpha, ExceptionCode&); - void texImage2D(unsigned target, unsigned level, HTMLImageElement* image, - bool flipY, bool premultiplyAlpha, ExceptionCode&); - void texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas, - bool flipY, bool premultiplyAlpha, ExceptionCode&); - void texImage2D(unsigned target, unsigned level, HTMLVideoElement* video, - bool flipY, bool premultiplyAlpha, ExceptionCode&); + void texImage2D(unsigned target, unsigned level, ImageData* pixels, ExceptionCode&); + void texImage2D(unsigned target, unsigned level, ImageData* pixels, bool flipY, ExceptionCode&); + void texImage2D(unsigned target, unsigned level, ImageData* pixels, bool flipY, bool premultiplyAlpha, ExceptionCode&); + void texImage2D(unsigned target, unsigned level, HTMLImageElement* image, ExceptionCode&); + void texImage2D(unsigned target, unsigned level, HTMLImageElement* image, bool flipY, ExceptionCode&); + void texImage2D(unsigned target, unsigned level, HTMLImageElement* image, bool flipY, bool premultiplyAlpha, ExceptionCode&); + void texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas, ExceptionCode&); + void texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas, bool flipY, ExceptionCode&); + void texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas, bool flipY, bool premultiplyAlpha, ExceptionCode&); + void texImage2D(unsigned target, unsigned level, HTMLVideoElement* video, ExceptionCode&); + void texImage2D(unsigned target, unsigned level, HTMLVideoElement* video, bool flipY, ExceptionCode&); + void texImage2D(unsigned target, unsigned level, HTMLVideoElement* video, bool flipY, bool premultiplyAlpha, ExceptionCode&); void texParameterf(unsigned target, unsigned pname, float param); void texParameteri(unsigned target, unsigned pname, int param); @@ -214,14 +218,18 @@ class WebKitCSSMatrix; void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, unsigned width, unsigned height, unsigned format, unsigned type, WebGLArray* pixels, ExceptionCode&); - void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, - ImageData* pixels, bool flipY, bool premultiplyAlpha, ExceptionCode&); - void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, - HTMLImageElement* image, bool flipY, bool premultiplyAlpha, ExceptionCode&); - void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, - HTMLCanvasElement* canvas, bool flipY, bool premultiplyAlpha, ExceptionCode&); - void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, - HTMLVideoElement* video, bool flipY, bool premultiplyAlpha, ExceptionCode&); + void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, ImageData* pixels, ExceptionCode&); + void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, ImageData* pixels, bool flipY, ExceptionCode&); + void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, ImageData* pixels, bool flipY, bool premultiplyAlpha, ExceptionCode&); + void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, HTMLImageElement* image, ExceptionCode&); + void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, HTMLImageElement* image, bool flipY, ExceptionCode&); + void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, HTMLImageElement* image, bool flipY, bool premultiplyAlpha, ExceptionCode&); + void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, HTMLCanvasElement* canvas, ExceptionCode&); + void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, HTMLCanvasElement* canvas, bool flipY, ExceptionCode&); + void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, HTMLCanvasElement* canvas, bool flipY, bool premultiplyAlpha, ExceptionCode&); + void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, HTMLVideoElement* video, ExceptionCode&); + void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, HTMLVideoElement* video, bool flipY, ExceptionCode&); + void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, HTMLVideoElement* video, bool flipY, bool premultiplyAlpha, ExceptionCode&); void uniform1f(const WebGLUniformLocation* location, float x, ExceptionCode&); void uniform1fv(const WebGLUniformLocation* location, WebGLFloatArray* v, ExceptionCode&); @@ -291,6 +299,8 @@ class WebKitCSSMatrix; void addObject(CanvasObject*); void detachAndRemoveAllObjects(); + PassRefPtr<WebGLTexture> findTexture(Platform3DObject); + PassRefPtr<WebGLRenderbuffer> findRenderbuffer(Platform3DObject); void markContextChanged(); void cleanupAfterGraphicsCall(bool changed) @@ -298,6 +308,8 @@ class WebKitCSSMatrix; if (changed) markContextChanged(); } + + bool isGLES2Compliant(); // Basic validation of count and offset against number of elements in element array buffer bool validateElementArraySize(unsigned long count, unsigned long type, long offset); @@ -359,6 +371,17 @@ class WebKitCSSMatrix; WebGLGetInfo getWebGLIntArrayParameter(unsigned long pname); WebGLGetInfo getWebGLUnsignedByteArrayParameter(unsigned long pname); + void texImage2DBase(unsigned target, unsigned level, unsigned internalformat, + unsigned width, unsigned height, unsigned border, + unsigned format, unsigned type, void* pixels, ExceptionCode&); + void texImage2D(unsigned target, unsigned level, Image* image, + bool flipY, bool premultiplyAlpha, ExceptionCode&); + void texSubImage2DBase(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, + unsigned width, unsigned height, + unsigned format, unsigned type, void* pixels, ExceptionCode&); + void texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, + Image* image, bool flipY, bool premultiplyAlpha, ExceptionCode&); + friend class WebGLStateRestorer; }; diff --git a/WebCore/html/canvas/WebGLRenderingContext.idl b/WebCore/html/canvas/WebGLRenderingContext.idl index a257452..b775378 100644 --- a/WebCore/html/canvas/WebGLRenderingContext.idl +++ b/WebCore/html/canvas/WebGLRenderingContext.idl @@ -474,13 +474,15 @@ module html { void blendFunc(in unsigned long sfactor, in unsigned long dfactor); void blendFuncSeparate(in unsigned long srcRGB, in unsigned long dstRGB, in unsigned long srcAlpha, in unsigned long dstAlpha); - // Supported forms: - // void bufferData (in GLenum target, in GLsizei size, in GLenum usage); - // void bufferData (in GLenum target, in WebGLArray data, in GLenum usage); +#if defined(V8_BINDING) && V8_BINDING + void bufferData(in unsigned long target, in WebGLArray data, in unsigned long usage) raises (DOMException); + void bufferData(in unsigned long target, in long size, in unsigned long usage) raises (DOMException); + void bufferSubData(in unsigned long target, in long offset, in WebGLArray data) raises (DOMException); +#else + // FIXME: Unfork once JSC supports overload generation too. [Custom] void bufferData() raises(DOMException); - // Supported forms: - // void bufferSubData (in GLenum target, in GLsizeiptr offset, in WebGLArray data); [Custom] void bufferSubData() raises(DOMException); +#endif unsigned long checkFramebufferStatus(in unsigned long target); void clear(in unsigned long mask); @@ -611,32 +613,34 @@ module html { void texParameteri(in unsigned long target, in unsigned long pname, in long param); // Supported forms: - // void texImage2D(in GLenum target, in GLint level, in GLenum internalformat, in GLsizei width, in GLsizei height, - // in GLint border, in GLenum format, in GLenum type, in WebGLArray pixels); - // void texImage2D(in GLenum target, in GLint level, in ImageData pixels, - // [Optional] in GLboolean flipY, [Optional] in premultiplyAlpha); - // void texImage2D(in GLenum target, in GLint level, in HTMLImageElement image, - // [Optional] in GLboolean flipY, [Optional] in premultiplyAlpha); - // void texImage2D(in GLenum target, in GLint level, in HTMLCanvasElement canvas, - // [Optional] in GLboolean flipY, [Optional] in premultiplyAlpha); - // void texImage2D(in GLenum target, in GLint level, in HTMLVideoElement video, - // [Optional] in GLboolean flipY, [Optional] in premultiplyAlpha); +#if defined(V8_BINDING) && V8_BINDING + void texImage2D(in unsigned long target, in long level, in unsigned long internalformat, in long width, in long height, + in long border, in unsigned long format, in unsigned long type, in WebGLArray pixels) raises (DOMException); + void texImage2D(in unsigned long target, in long level, in ImageData pixels, + in [Optional] boolean flipY, in [Optional] boolean premultiplyAlpha) raises (DOMException); + void texImage2D(in unsigned long target, in long level, in HTMLImageElement image, + in [Optional] boolean flipY, in [Optional] boolean premultiplyAlpha) raises (DOMException); + void texImage2D(in unsigned long target, in long level, in HTMLCanvasElement canvas, + in [Optional] boolean flipY, in [Optional] boolean premultiplyAlpha) raises (DOMException); + void texImage2D(in unsigned long target, in long level, in HTMLVideoElement video, + in [Optional] boolean flipY, in [Optional] boolean premultiplyAlpha) raises (DOMException); + + void texSubImage2D(in unsigned long target, in long level, in long xoffset, in long yoffset, + in long width, in long height, + in unsigned long format, in unsigned long type, in WebGLArray pixels) raises (DOMException); + void texSubImage2D(in unsigned long target, in long level, in long xoffset, in long yoffset, + in ImageData pixels, in [Optional] boolean flipY, in [Optional] boolean premultiplyAlpha) raises (DOMException); + void texSubImage2D(in unsigned long target, in long level, in long xoffset, in long yoffset, + in HTMLImageElement image, in [Optional] boolean flipY, in [Optional] boolean premultiplyAlpha) raises (DOMException); + void texSubImage2D(in unsigned long target, in long level, in long xoffset, in long yoffset, + in HTMLCanvasElement canvas, in [Optional] boolean flipY, in [Optional] boolean premultiplyAlpha) raises (DOMException); + void texSubImage2D(in unsigned long target, in long level, in long xoffset, in long yoffset, + in HTMLVideoElement video, in [Optional] boolean flipY, in [Optional] boolean premultiplyAlpha) raises (DOMException); +#else + // FIXME: Unfork once JSC supports overload generation too. [Custom] void texImage2D(); - - // Supported forms: - // void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, - // in GLsizei width, in GLsizei height, - // in GLenum format, in GLenum type, in WebGLArray pixels); - // void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, - // in ImageData pixels, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); - // void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, - // in HTMLImageElement image, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); - // void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, - // in HTMLCanvasElement canvas, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); - // void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, - // in HTMLVideoElement video, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); [Custom] void texSubImage2D(); - +#endif void uniform1f(in WebGLUniformLocation location, in float x) raises(DOMException); [Custom] void uniform1fv(in WebGLUniformLocation location, in WebGLFloatArray v) raises(DOMException); void uniform1i(in WebGLUniformLocation location, in long x) raises(DOMException); diff --git a/WebCore/html/canvas/WebGLShader.h b/WebCore/html/canvas/WebGLShader.h index 1ef912c..d4006aa 100644 --- a/WebCore/html/canvas/WebGLShader.h +++ b/WebCore/html/canvas/WebGLShader.h @@ -38,11 +38,13 @@ namespace WebCore { virtual ~WebGLShader() { deleteObject(); } static PassRefPtr<WebGLShader> create(WebGLRenderingContext*, GraphicsContext3D::WebGLEnumType); - + private: WebGLShader(WebGLRenderingContext*, GraphicsContext3D::WebGLEnumType); virtual void _deleteObject(Platform3DObject); + + virtual bool isShader() const { return true; } }; } // namespace WebCore diff --git a/WebCore/html/canvas/WebGLTexture.cpp b/WebCore/html/canvas/WebGLTexture.cpp index ae09b48..0c58edb 100644 --- a/WebCore/html/canvas/WebGLTexture.cpp +++ b/WebCore/html/canvas/WebGLTexture.cpp @@ -37,11 +37,6 @@ PassRefPtr<WebGLTexture> WebGLTexture::create(WebGLRenderingContext* ctx) return adoptRef(new WebGLTexture(ctx)); } -PassRefPtr<WebGLTexture> WebGLTexture::create(WebGLRenderingContext* ctx, Platform3DObject obj) -{ - return adoptRef(new WebGLTexture(ctx, obj)); -} - WebGLTexture::WebGLTexture(WebGLRenderingContext* ctx) : CanvasObject(ctx) , cubeMapRWrapModeInitialized(false) @@ -49,13 +44,6 @@ WebGLTexture::WebGLTexture(WebGLRenderingContext* ctx) setObject(context()->graphicsContext3D()->createTexture()); } -WebGLTexture::WebGLTexture(WebGLRenderingContext* ctx, Platform3DObject obj) - : CanvasObject(ctx) - , cubeMapRWrapModeInitialized(false) -{ - setObject(obj, false); -} - void WebGLTexture::_deleteObject(Platform3DObject object) { context()->graphicsContext3D()->deleteTexture(object); diff --git a/WebCore/html/canvas/WebGLTexture.h b/WebCore/html/canvas/WebGLTexture.h index c64dd41..b3c1f05 100644 --- a/WebCore/html/canvas/WebGLTexture.h +++ b/WebCore/html/canvas/WebGLTexture.h @@ -38,10 +38,6 @@ namespace WebCore { virtual ~WebGLTexture() { deleteObject(); } static PassRefPtr<WebGLTexture> create(WebGLRenderingContext*); - - // For querying previously created objects via e.g. getFramebufferAttachmentParameter - // FIXME: should consider canonicalizing these objects - static PassRefPtr<WebGLTexture> create(WebGLRenderingContext*, Platform3DObject); bool isCubeMapRWrapModeInitialized() { return cubeMapRWrapModeInitialized; @@ -53,11 +49,12 @@ namespace WebCore { protected: WebGLTexture(WebGLRenderingContext*); - WebGLTexture(WebGLRenderingContext*, Platform3DObject); virtual void _deleteObject(Platform3DObject); private: + virtual bool isTexture() const { return true; } + bool cubeMapRWrapModeInitialized; }; diff --git a/WebCore/inspector/InjectedScriptHost.idl b/WebCore/inspector/InjectedScriptHost.idl index e3cd976..8b24157 100644 --- a/WebCore/inspector/InjectedScriptHost.idl +++ b/WebCore/inspector/InjectedScriptHost.idl @@ -43,7 +43,6 @@ module core { #if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER [Custom] DOMObject currentCallFrame(); - [Custom] boolean isActivation(in DOMObject object); #endif #if defined(ENABLE_DATABASE) && ENABLE_DATABASE diff --git a/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.h b/WebCore/inspector/InspectorCSSStore.cpp index b1b0792..e53688b 100644 --- a/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.h +++ b/WebCore/inspector/InspectorCSSStore.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,40 +26,32 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSCustomSQLStatementErrorCallback_h -#define JSCustomSQLStatementErrorCallback_h +#include "config.h" +#include "InspectorCSSStore.h" -#if ENABLE(DATABASE) - -#include "JSCallbackData.h" -#include "SQLStatementErrorCallback.h" -#include <wtf/Forward.h> +#include "CSSStyleDeclaration.h" +#include "CSSStyleRule.h" +#include "CSSStyleSheet.h" +#include "PlatformString.h" namespace WebCore { -class JSCallbackData; -class SQLError; - -class JSCustomSQLStatementErrorCallback : public SQLStatementErrorCallback { -public: - static PassRefPtr<JSCustomSQLStatementErrorCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject) - { - return adoptRef(new JSCustomSQLStatementErrorCallback(callback, globalObject)); - } - - virtual ~JSCustomSQLStatementErrorCallback(); - - virtual bool handleEvent(ScriptExecutionContext*, SQLTransaction*, SQLError*); - -private: - JSCustomSQLStatementErrorCallback(JSC::JSObject* callback, JSDOMGlobalObject*); - - JSCallbackData* m_data; - RefPtr<DOMWrapperWorld> m_isolatedWorld; -}; +InspectorCSSStore::InspectorCSSStore() +{ +} +InspectorCSSStore::~InspectorCSSStore() +{ } -#endif // ENABLE(DATABASE) +void InspectorCSSStore::reset() +{ + styleToId.clear(); + idToStyle.clear(); + ruleToId.clear(); + idToRule.clear(); + idToDisabledStyle.clear(); + inspectorStyleSheet = 0; +} -#endif // JSCustomSQLStatementErrorCallback_h +} // namespace WebCore diff --git a/WebCore/inspector/InspectorCSSStore.h b/WebCore/inspector/InspectorCSSStore.h new file mode 100644 index 0000000..d290fad --- /dev/null +++ b/WebCore/inspector/InspectorCSSStore.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2010 Google 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 InspectorCSSStore_h +#define InspectorCSSStore_h + +#include "StringHash.h" + +#include <wtf/HashMap.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CSSStyleDeclaration; +class CSSStyleRule; +class CSSStyleSheet; +class String; + +typedef std::pair<String, String> PropertyValueAndPriority; +typedef HashMap<String, PropertyValueAndPriority> DisabledStyleDeclaration; +typedef HashMap<CSSStyleDeclaration*, long> StyleToIdMap; +typedef HashMap<long, RefPtr<CSSStyleDeclaration> > IdToStyleMap; +typedef HashMap<CSSStyleRule*, long> RuleToIdMap; +typedef HashMap<long, RefPtr<CSSStyleRule> > IdToRuleMap; +typedef HashMap<long, DisabledStyleDeclaration> IdToDisabledStyleMap; + +struct InspectorCSSStore { + InspectorCSSStore(); + ~InspectorCSSStore(); + void reset(); + + StyleToIdMap styleToId; + IdToStyleMap idToStyle; + RuleToIdMap ruleToId; + IdToRuleMap idToRule; + IdToDisabledStyleMap idToDisabledStyle; + RefPtr<CSSStyleSheet> inspectorStyleSheet; +}; + +} // namespace WebCore + +#endif // !defined(InspectorCSSStore_h) diff --git a/WebCore/inspector/InspectorController.cpp b/WebCore/inspector/InspectorController.cpp index c54ee5b..23a991e 100644 --- a/WebCore/inspector/InspectorController.cpp +++ b/WebCore/inspector/InspectorController.cpp @@ -24,7 +24,7 @@ * 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. + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" @@ -55,6 +55,7 @@ #include "InjectedScript.h" #include "InjectedScriptHost.h" #include "InspectorBackend.h" +#include "InspectorCSSStore.h" #include "InspectorClient.h" #include "InspectorFrontendClient.h" #include "InspectorDOMStorageResource.h" @@ -144,6 +145,7 @@ InspectorController::InspectorController(Page* page, InspectorClient* client) : m_inspectedPage(page) , m_client(client) , m_openingFrontend(false) + , m_cssStore(new InspectorCSSStore()) , m_expiredConsoleMessageCount(0) , m_showAfterVisible(CurrentPanel) , m_groupLevel(0) @@ -427,7 +429,7 @@ void InspectorController::setFrontend(PassOwnPtr<InspectorFrontend> frontend) m_openingFrontend = false; m_frontend = frontend; releaseDOMAgent(); - m_domAgent = InspectorDOMAgent::create(m_frontend.get()); + m_domAgent = InspectorDOMAgent::create(m_cssStore.get(), m_frontend.get()); if (m_timelineAgent) m_timelineAgent->resetFrontendProxyObject(m_frontend.get()); #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) @@ -663,8 +665,11 @@ void InspectorController::didCommitLoad(DocumentLoader* loader) m_currentUserInitiatedProfileNumber = 1; m_nextUserInitiatedProfileNumber = 1; #endif - // resetScriptObjects should be called before database and DOM storage + // unbindAllResources should be called before database and DOM storage // resources are cleared so that it has a chance to unbind them. + unbindAllResources(); + + m_cssStore->reset(); if (m_frontend) { m_frontend->reset(); m_domAgent->reset(); @@ -892,15 +897,19 @@ void InspectorController::willSendRequest(unsigned long identifier, const Resour void InspectorController::didReceiveResponse(unsigned long identifier, const ResourceResponse& response) { - RefPtr<InspectorResource> resource = getTrackedResource(identifier); - if (!resource) - return; + if (RefPtr<InspectorResource> resource = getTrackedResource(identifier)) { + resource->updateResponse(response); + resource->markResponseReceivedTime(); - resource->updateResponse(response); - resource->markResponseReceivedTime(); + if (resource != m_mainResource && m_frontend) + resource->updateScriptObject(m_frontend.get()); + } + if (response.httpStatusCode() >= 400) { + // The ugly code below is due to that String::format() is not utf8-safe at the moment. + String message = String::format("Failed to load resource: the server responded with a status of %u (", response.httpStatusCode()) + response.httpStatusText() + ")"; - if (resource != m_mainResource && m_frontend) - resource->updateScriptObject(m_frontend.get()); + addMessageToConsole(OtherMessageSource, LogMessageType, ErrorMessageLevel, message, 0, response.url().string()); + } } void InspectorController::didReceiveContentLength(unsigned long identifier, int lengthReceived) @@ -931,11 +940,16 @@ void InspectorController::didFinishLoading(unsigned long identifier) resource->updateScriptObject(m_frontend.get()); } -void InspectorController::didFailLoading(unsigned long identifier, const ResourceError& /*error*/) +void InspectorController::didFailLoading(unsigned long identifier, const ResourceError& error) { if (m_timelineAgent) m_timelineAgent->didFinishLoadingResource(identifier, true); + String message = "Failed to load resource"; + if (!error.localizedDescription().isEmpty()) + message += ": " + error.localizedDescription(); + addMessageToConsole(OtherMessageSource, LogMessageType, ErrorMessageLevel, message, 0, error.failingURL()); + RefPtr<InspectorResource> resource = getTrackedResource(identifier); if (!resource) return; diff --git a/WebCore/inspector/InspectorController.h b/WebCore/inspector/InspectorController.h index 3c67975..a90b299 100644 --- a/WebCore/inspector/InspectorController.h +++ b/WebCore/inspector/InspectorController.h @@ -65,6 +65,7 @@ class InjectedScript; class InjectedScriptHost; class InspectorBackend; class InspectorClient; +struct InspectorCSSStore; class InspectorFrontend; class InspectorFrontendClient; class InspectorTimelineAgent; @@ -318,6 +319,7 @@ private: bool m_openingFrontend; OwnPtr<InspectorFrontend> m_frontend; RefPtr<InspectorDOMAgent> m_domAgent; + OwnPtr<InspectorCSSStore> m_cssStore; OwnPtr<InspectorTimelineAgent> m_timelineAgent; RefPtr<Node> m_nodeToFocus; RefPtr<InspectorResource> m_mainResource; diff --git a/WebCore/inspector/InspectorDOMAgent.cpp b/WebCore/inspector/InspectorDOMAgent.cpp index 31fad80..d12a6d7 100644 --- a/WebCore/inspector/InspectorDOMAgent.cpp +++ b/WebCore/inspector/InspectorDOMAgent.cpp @@ -73,8 +73,9 @@ namespace WebCore { -InspectorDOMAgent::InspectorDOMAgent(InspectorFrontend* frontend) +InspectorDOMAgent::InspectorDOMAgent(InspectorCSSStore* cssStore, InspectorFrontend* frontend) : EventListener(InspectorDOMAgentType) + , m_cssStore(cssStore) , m_frontend(frontend) , m_lastNodeId(1) , m_lastStyleId(1) @@ -236,12 +237,6 @@ void InspectorDOMAgent::discardBindings() m_idToNode.clear(); releaseDanglingNodes(); m_childrenRequested.clear(); - m_styleToId.clear(); - m_idToStyle.clear(); - m_ruleToId.clear(); - m_idToRule.clear(); - m_idToDisabledStyle.clear(); - m_inspectorStyleSheet = 0; } Node* InspectorDOMAgent::nodeForId(long id) @@ -628,7 +623,13 @@ ScriptObject InspectorDOMAgent::buildObjectForEventListener(const RegisteredEven value.set("useCapture", registeredEventListener.useCapture); value.set("isAttribute", eventListener->isAttribute()); value.set("nodeId", pushNodePathToFrontend(node)); - value.set("listener", getEventListenerHandlerBody(node->document(), m_frontend->scriptState(), eventListener.get())); + value.set("listenerBody", eventListenerHandlerBody(node->document(), m_frontend->scriptState(), eventListener.get())); + String sourceName; + int lineNumber; + if (eventListenerHandlerLocation(node->document(), m_frontend->scriptState(), eventListener.get(), sourceName, lineNumber)) { + value.set("sourceName", sourceName); + value.set("lineNumber", lineNumber); + } return value; } @@ -899,8 +900,8 @@ ScriptArray InspectorDOMAgent::buildArrayForPseudoElements(Element* element, boo void InspectorDOMAgent::applyStyleText(long callId, long styleId, const String& styleText, const String& propertyName) { - IdToStyleMap::iterator it = m_idToStyle.find(styleId); - if (it == m_idToStyle.end()) { + IdToStyleMap::iterator it = cssStore()->idToStyle.find(styleId); + if (it == cssStore()->idToStyle.end()) { m_frontend->didApplyStyleText(callId, false, ScriptValue::undefined(), m_frontend->newScriptArray()); return; } @@ -976,8 +977,8 @@ void InspectorDOMAgent::applyStyleText(long callId, long styleId, const String& void InspectorDOMAgent::setStyleText(long callId, long styleId, const String& cssText) { - IdToStyleMap::iterator it = m_idToStyle.find(styleId); - if (it == m_idToStyle.end()) { + IdToStyleMap::iterator it = cssStore()->idToStyle.find(styleId); + if (it == cssStore()->idToStyle.end()) { m_frontend->didSetStyleText(callId, false); return; } @@ -989,8 +990,8 @@ void InspectorDOMAgent::setStyleText(long callId, long styleId, const String& cs void InspectorDOMAgent::setStyleProperty(long callId, long styleId, const String& name, const String& value) { - IdToStyleMap::iterator it = m_idToStyle.find(styleId); - if (it == m_idToStyle.end()) { + IdToStyleMap::iterator it = cssStore()->idToStyle.find(styleId); + if (it == cssStore()->idToStyle.end()) { m_frontend->didSetStyleProperty(callId, false); return; } @@ -1003,16 +1004,16 @@ void InspectorDOMAgent::setStyleProperty(long callId, long styleId, const String void InspectorDOMAgent::toggleStyleEnabled(long callId, long styleId, const String& propertyName, bool disabled) { - IdToStyleMap::iterator it = m_idToStyle.find(styleId); - if (it == m_idToStyle.end()) { + IdToStyleMap::iterator it = cssStore()->idToStyle.find(styleId); + if (it == cssStore()->idToStyle.end()) { m_frontend->didToggleStyleEnabled(callId, ScriptValue::undefined()); return; } CSSStyleDeclaration* style = it->second.get(); - IdToDisabledStyleMap::iterator disabledIt = m_idToDisabledStyle.find(styleId); - if (disabledIt == m_idToDisabledStyle.end()) - disabledIt = m_idToDisabledStyle.set(styleId, DisabledStyleDeclaration()).first; + IdToDisabledStyleMap::iterator disabledIt = cssStore()->idToDisabledStyle.find(styleId); + if (disabledIt == cssStore()->idToDisabledStyle.end()) + disabledIt = cssStore()->idToDisabledStyle.set(styleId, DisabledStyleDeclaration()).first; // TODO: make sure this works with shorthands right. ExceptionCode ec = 0; @@ -1035,8 +1036,8 @@ void InspectorDOMAgent::toggleStyleEnabled(long callId, long styleId, const Stri void InspectorDOMAgent::setRuleSelector(long callId, long ruleId, const String& selector, long selectedNodeId) { - IdToRuleMap::iterator it = m_idToRule.find(ruleId); - if (it == m_idToRule.end()) { + IdToRuleMap::iterator it = cssStore()->idToRule.find(ruleId); + if (it == cssStore()->idToRule.end()) { m_frontend->didSetRuleSelector(callId, ScriptValue::undefined(), false); return; } @@ -1076,7 +1077,7 @@ void InspectorDOMAgent::addRule(long callId, const String& selector, long select return; } - if (!m_inspectorStyleSheet.get()) { + if (!cssStore()->inspectorStyleSheet.get()) { Document* ownerDocument = node->ownerDocument(); ExceptionCode ec = 0; RefPtr<Element> styleElement = ownerDocument->createElement("style", ec); @@ -1094,38 +1095,38 @@ void InspectorDOMAgent::addRule(long callId, const String& selector, long select m_frontend->didAddRule(callId, ScriptValue::undefined(), false); return; } - m_inspectorStyleSheet = static_cast<CSSStyleSheet*>(styleSheet); + cssStore()->inspectorStyleSheet = static_cast<CSSStyleSheet*>(styleSheet); } ExceptionCode ec = 0; - m_inspectorStyleSheet->addRule(selector, "", ec); + cssStore()->inspectorStyleSheet->addRule(selector, "", ec); if (ec) { m_frontend->didAddRule(callId, ScriptValue::undefined(), false); return; } - CSSStyleRule* newRule = static_cast<CSSStyleRule*>(m_inspectorStyleSheet->item(m_inspectorStyleSheet->length() - 1)); + CSSStyleRule* newRule = static_cast<CSSStyleRule*>(cssStore()->inspectorStyleSheet->item(cssStore()->inspectorStyleSheet->length() - 1)); m_frontend->didAddRule(callId, buildObjectForRule(newRule), ruleAffectsNode(newRule, node)); } long InspectorDOMAgent::bindStyle(CSSStyleDeclaration* style) { - long id = m_styleToId.get(style); + long id = cssStore()->styleToId.get(style); if (!id) { id = m_lastStyleId++; - m_idToStyle.set(id, style); - m_styleToId.set(style, id); + cssStore()->idToStyle.set(id, style); + cssStore()->styleToId.set(style, id); } return id; } long InspectorDOMAgent::bindRule(CSSStyleRule* rule) { - long id = m_ruleToId.get(rule); + long id = cssStore()->ruleToId.get(rule); if (!id) { id = m_lastRuleId++; - m_idToRule.set(id, rule); - m_ruleToId.set(rule, id); + cssStore()->idToRule.set(id, rule); + cssStore()->ruleToId.set(rule, id); } return id; } @@ -1137,8 +1138,8 @@ ScriptObject InspectorDOMAgent::buildObjectForStyle(CSSStyleDeclaration* style, long styleId = bindStyle(style); result.set("id", styleId); - IdToDisabledStyleMap::iterator disabledIt = m_idToDisabledStyle.find(styleId); - if (disabledIt != m_idToDisabledStyle.end()) + IdToDisabledStyleMap::iterator disabledIt = cssStore()->idToDisabledStyle.find(styleId); + if (disabledIt != cssStore()->idToDisabledStyle.end()) result.set("disabled", buildArrayForDisabledStyleProperties(disabledIt->second)); } result.set("width", style->getPropertyValue("width")); @@ -1224,7 +1225,7 @@ ScriptObject InspectorDOMAgent::buildObjectForRule(CSSStyleRule* rule) bool isUser = parentStyleSheet && parentStyleSheet->ownerNode() && parentStyleSheet->ownerNode()->nodeName() == "#document"; result.set("isUserAgent", isUserAgent); result.set("isUser", isUser); - result.set("isViaInspector", rule->parentStyleSheet() == m_inspectorStyleSheet.get()); + result.set("isViaInspector", rule->parentStyleSheet() == cssStore()->inspectorStyleSheet.get()); // Bind editable scripts only. bool bind = !isUserAgent && !isUser; diff --git a/WebCore/inspector/InspectorDOMAgent.h b/WebCore/inspector/InspectorDOMAgent.h index 7211ed2..c8a4e1a 100644 --- a/WebCore/inspector/InspectorDOMAgent.h +++ b/WebCore/inspector/InspectorDOMAgent.h @@ -33,6 +33,7 @@ #include "AtomicString.h" #include "EventListener.h" #include "EventTarget.h" +#include "InspectorCSSStore.h" #include "ScriptArray.h" #include "ScriptObject.h" #include "ScriptState.h" @@ -73,9 +74,9 @@ namespace WebCore { class InspectorDOMAgent : public EventListener { public: - static PassRefPtr<InspectorDOMAgent> create(InspectorFrontend* frontend) + static PassRefPtr<InspectorDOMAgent> create(InspectorCSSStore* cssStore, InspectorFrontend* frontend) { - return adoptRef(new InspectorDOMAgent(frontend)); + return adoptRef(new InspectorDOMAgent(cssStore, frontend)); } static const InspectorDOMAgent* cast(const EventListener* listener) @@ -85,7 +86,7 @@ namespace WebCore { : 0; } - InspectorDOMAgent(InspectorFrontend* frontend); + InspectorDOMAgent(InspectorCSSStore* cssStore, InspectorFrontend* frontend); ~InspectorDOMAgent(); void reset(); @@ -127,9 +128,6 @@ namespace WebCore { void pushChildNodesToFrontend(long nodeId); private: - typedef std::pair<String, String> PropertyValueAndPriority; - typedef HashMap<String, PropertyValueAndPriority> DisabledStyleDeclaration; - void startListening(Document* document); void stopListening(Document* document); @@ -162,6 +160,7 @@ namespace WebCore { Document* mainFrameDocument() const; String documentURLString(Document* document) const; + InspectorCSSStore* cssStore() { return m_cssStore; } long bindStyle(CSSStyleDeclaration*); long bindRule(CSSStyleRule*); @@ -178,6 +177,7 @@ namespace WebCore { void discardBindings(); + InspectorCSSStore* m_cssStore; InspectorFrontend* m_frontend; NodeToIdMap m_documentNodeToIdMap; // Owns node mappings for dangling nodes. @@ -186,19 +186,6 @@ namespace WebCore { HashMap<long, NodeToIdMap*> m_idToNodesMap; HashSet<long> m_childrenRequested; long m_lastNodeId; - - typedef HashMap<CSSStyleDeclaration*, long> StyleToIdMap; - typedef HashMap<long, RefPtr<CSSStyleDeclaration> > IdToStyleMap; - StyleToIdMap m_styleToId; - IdToStyleMap m_idToStyle; - typedef HashMap<CSSStyleRule*, long> RuleToIdMap; - typedef HashMap<long, RefPtr<CSSStyleRule> > IdToRuleMap; - RuleToIdMap m_ruleToId; - IdToRuleMap m_idToRule; - typedef HashMap<long, DisabledStyleDeclaration> IdToDisabledStyleMap; - IdToDisabledStyleMap m_idToDisabledStyle; - RefPtr<CSSStyleSheet> m_inspectorStyleSheet; - long m_lastStyleId; long m_lastRuleId; ListHashSet<RefPtr<Document> > m_documents; diff --git a/WebCore/inspector/InspectorFrontend.cpp b/WebCore/inspector/InspectorFrontend.cpp index d89ae71..d89ae71 100755..100644 --- a/WebCore/inspector/InspectorFrontend.cpp +++ b/WebCore/inspector/InspectorFrontend.cpp diff --git a/WebCore/inspector/InspectorTimelineAgent.cpp b/WebCore/inspector/InspectorTimelineAgent.cpp index c0278c2..b8471a8 100644 --- a/WebCore/inspector/InspectorTimelineAgent.cpp +++ b/WebCore/inspector/InspectorTimelineAgent.cpp @@ -56,13 +56,17 @@ InspectorTimelineAgent::InspectorTimelineAgent(InspectorFrontend* frontend) void InspectorTimelineAgent::pushGCEventRecords() { - for (GCEvents::iterator i = m_gcEvents.begin(); i != m_gcEvents.end(); ++i) { + if (!m_gcEvents.size()) + return; + + GCEvents events = m_gcEvents; + m_gcEvents.clear(); + for (GCEvents::iterator i = events.begin(); i != events.end(); ++i) { ScriptObject record = TimelineRecordFactory::createGenericRecord(m_frontend, i->startTime); record.set("data", TimelineRecordFactory::createGCEventData(m_frontend, i->collectedBytes)); record.set("endTime", i->endTime); addRecordToTimeline(record, GCEventTimelineRecordType); } - m_gcEvents.clear(); } void InspectorTimelineAgent::didGC(double startTime, double endTime, size_t collectedBytesCount) diff --git a/WebCore/inspector/front-end/AuditLauncherView.js b/WebCore/inspector/front-end/AuditLauncherView.js index 60b7c32..33d3872 100644 --- a/WebCore/inspector/front-end/AuditLauncherView.js +++ b/WebCore/inspector/front-end/AuditLauncherView.js @@ -70,13 +70,12 @@ WebInspector.AuditLauncherView.prototype = { if (!this._auditPresentStateLabelElement) return; - this._resetResourceCount(); - if (isTracking) { this._auditPresentStateLabelElement.nodeValue = WebInspector.UIString("Audit Present State"); this._auditPresentStateElement.disabled = false; this._auditPresentStateElement.parentElement.removeStyleClass("disabled"); } else { + this._resetResourceCount(); this._auditPresentStateLabelElement.nodeValue = WebInspector.UIString("Audit Present State (Resource Tracking must be enabled)"); this._auditPresentStateElement.disabled = true; this._auditPresentStateElement.parentElement.addStyleClass("disabled"); @@ -268,12 +267,12 @@ WebInspector.AuditLauncherView.prototype = { if (!this._resourceProgressContainer) return; - if (!this._auditRunning) + if (!this._auditRunning) { + this._resetResourceCount(); this._resourceProgressContainer.addStyleClass("hidden"); - else { + } else this._resourceProgressContainer.removeStyleClass("hidden"); - this._resourceProgressTextElement.textContent = WebInspector.UIString("Loading (%d of %d)", this.loadedResources, this.totalResources); - } + this._resourceProgressTextElement.textContent = WebInspector.UIString("Loading (%d of %d)", this.loadedResources, this.totalResources); }, _updateButton: function() diff --git a/WebCore/inspector/front-end/AuditRules.js b/WebCore/inspector/front-end/AuditRules.js index d2c5f09..a6976b1 100644 --- a/WebCore/inspector/front-end/AuditRules.js +++ b/WebCore/inspector/front-end/AuditRules.js @@ -647,10 +647,12 @@ WebInspector.AuditRules.ImageDimensionsRule.prototype = { const node = WebInspector.domAgent.nodeForId(imageId); var src = node.getAttribute("src"); - for (var frameOwnerCandidate = node; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) { - if (frameOwnerCandidate.documentURL) { - var completeSrc = WebInspector.completeURL(frameOwnerCandidate.documentURL, src); - break; + if (!WebInspector.URLRegExp.test(src)) { + for (var frameOwnerCandidate = node; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) { + if (frameOwnerCandidate.documentURL) { + var completeSrc = WebInspector.completeURL(frameOwnerCandidate.documentURL, src); + break; + } } } if (completeSrc) diff --git a/WebCore/inspector/front-end/ElementsPanel.js b/WebCore/inspector/front-end/ElementsPanel.js index e2ca838..d47a4cd 100644 --- a/WebCore/inspector/front-end/ElementsPanel.js +++ b/WebCore/inspector/front-end/ElementsPanel.js @@ -763,6 +763,15 @@ WebInspector.ElementsPanel.prototype = { parentElement.title = title; }, + linkifyNodeReference: function(node) + { + var link = document.createElement("span"); + link.className = "node-link"; + link.addEventListener("click", WebInspector.updateFocusedNode.bind(WebInspector, node.id), false); + this.decorateNodeLabel(node, link); + return link; + }, + updateBreadcrumbSizes: function(focusedCrumb) { if (!this.visible) @@ -1111,6 +1120,11 @@ WebInspector.ElementsPanel.prototype = { InspectorBackend.enableSearchingForNode(); else InspectorBackend.disableSearchingForNode(); + }, + + elementsToRestoreScrollPositionsFor: function() + { + return [ this.contentElement, this.sidebarElement ]; } } diff --git a/WebCore/inspector/front-end/ElementsTreeOutline.js b/WebCore/inspector/front-end/ElementsTreeOutline.js index 1add6cc..cd1bf23 100644 --- a/WebCore/inspector/front-end/ElementsTreeOutline.js +++ b/WebCore/inspector/front-end/ElementsTreeOutline.js @@ -285,6 +285,10 @@ WebInspector.ElementsTreeOutline.prototype = { if (element) { element.hovered = true; this._previousHoveredElement = element; + + // Lazily compute tag-specific tooltips. + if (element.representedObject && !element.tooltip) + element._createTooltipForNode(); } WebInspector.hoveredDOMNode = (element ? element.representedObject : null); @@ -424,27 +428,24 @@ WebInspector.ElementsTreeElement.prototype = { return this.expandedChildCount > index; }, - createTooltipForImageNode: function(node, callback) + _createTooltipForNode: function() { - if (this._elementCloseTag) + var node = this.representedObject; + if (!node.nodeName || node.nodeName.toLowerCase() !== "img") return; - - function createTooltipThenCallback(properties) + + function setTooltip(properties) { - if (!properties) { - callback(); + if (!properties) return; - } - var tooltipText = null; if (properties.offsetHeight === properties.naturalHeight && properties.offsetWidth === properties.naturalWidth) - tooltipText = WebInspector.UIString("%d × %d pixels", properties.offsetWidth, properties.offsetHeight); + this.tooltip = WebInspector.UIString("%d × %d pixels", properties.offsetWidth, properties.offsetHeight); else - tooltipText = WebInspector.UIString("%d × %d pixels (Natural: %d × %d pixels)", properties.offsetWidth, properties.offsetHeight, properties.naturalWidth, properties.naturalHeight); - callback(tooltipText); + this.tooltip = WebInspector.UIString("%d × %d pixels (Natural: %d × %d pixels)", properties.offsetWidth, properties.offsetHeight, properties.naturalWidth, properties.naturalHeight); } var objectProxy = new WebInspector.ObjectProxy(node.injectedScriptId, node.id); - WebInspector.ObjectProxy.getPropertiesAsync(objectProxy, ["naturalHeight", "naturalWidth", "offsetHeight", "offsetWidth"], createTooltipThenCallback); + WebInspector.ObjectProxy.getPropertiesAsync(objectProxy, ["naturalHeight", "naturalWidth", "offsetHeight", "offsetWidth"], setTooltip.bind(this)); }, updateSelection: function() @@ -1175,22 +1176,12 @@ WebInspector.ElementsTreeElement.prototype = { if (this._editing) return; - var self = this; - function callback(tooltipText) - { - var title = self._nodeTitleInfo(WebInspector.linkifyURL, tooltipText).title; - self.title = "<span class=\"highlight\">" + title + "</span>"; - delete self.selectionElement; - self.updateSelection(); - self._preventFollowingLinksOnDoubleClick(); - self._highlightSearchResults(); - }; - - // TODO: Replace with InjectedScriptAccess.getBasicProperties(obj, [names]). - if (this.representedObject.nodeName.toLowerCase() !== "img") - callback(); - else - this.createTooltipForImageNode(this.representedObject, callback); + var title = this._nodeTitleInfo(WebInspector.linkifyURL).title; + this.title = "<span class=\"highlight\">" + title + "</span>"; + delete this.selectionElement; + this.updateSelection(); + this._preventFollowingLinksOnDoubleClick(); + this._highlightSearchResults(); }, _rewriteAttrHref: function(node, hrefValue) @@ -1216,7 +1207,7 @@ WebInspector.ElementsTreeElement.prototype = { return hrefValue; }, - _attributeHTML: function(name, value, node, linkify, tooltipText) + _attributeHTML: function(name, value, node, linkify) { var hasText = (value.length > 0); var html = "<span class=\"webkit-html-attribute\"><span class=\"webkit-html-attribute-name\">" + name.escapeHTML() + "</span>"; @@ -1226,7 +1217,7 @@ WebInspector.ElementsTreeElement.prototype = { if (linkify && (name === "src" || name === "href")) { value = value.replace(/([\/;:\)\]\}])/g, "$1\u200B"); - html += linkify(this._rewriteAttrHref(node, value), value, "webkit-html-attribute-value", node.nodeName.toLowerCase() === "a", tooltipText); + html += linkify(this._rewriteAttrHref(node, value), value, "webkit-html-attribute-value", node.nodeName.toLowerCase() === "a"); } else { value = value.escapeHTML().replace(/([\/;:\)\]\}])/g, "$1​"); html += "<span class=\"webkit-html-attribute-value\">" + value + "</span>"; @@ -1239,7 +1230,7 @@ WebInspector.ElementsTreeElement.prototype = { return html; }, - _tagHTML: function(tagName, isClosingTag, isDistinctTreeElement, linkify, tooltipText) + _tagHTML: function(tagName, isClosingTag, isDistinctTreeElement, linkify) { var node = this.representedObject; var result = "<span class=\"webkit-html-tag" + (isClosingTag && isDistinctTreeElement ? " close" : "") + "\"><"; @@ -1247,7 +1238,7 @@ WebInspector.ElementsTreeElement.prototype = { if (!isClosingTag && node.hasAttributes()) { for (var i = 0; i < node.attributes.length; ++i) { var attr = node.attributes[i]; - result += " " + this._attributeHTML(attr.name, attr.value, node, linkify, tooltipText); + result += " " + this._attributeHTML(attr.name, attr.value, node, linkify); } } result += "></span>​"; @@ -1255,7 +1246,7 @@ WebInspector.ElementsTreeElement.prototype = { return result; }, - _nodeTitleInfo: function(linkify, tooltipText) + _nodeTitleInfo: function(linkify) { var node = this.representedObject; var info = {title: "", hasChildren: this.hasChildren}; @@ -1277,7 +1268,7 @@ WebInspector.ElementsTreeElement.prototype = { break; } - info.title = this._tagHTML(tagName, false, false, linkify, tooltipText); + info.title = this._tagHTML(tagName, false, false, linkify); var textChild = onlyTextChild.call(node); var showInlineText = textChild && textChild.textContent.length < Preferences.maxInlineTextChildLength; diff --git a/WebCore/inspector/front-end/EventListenersSidebarPane.js b/WebCore/inspector/front-end/EventListenersSidebarPane.js index e454256..045d29b 100644 --- a/WebCore/inspector/front-end/EventListenersSidebarPane.js +++ b/WebCore/inspector/front-end/EventListenersSidebarPane.js @@ -77,7 +77,7 @@ WebInspector.EventListenersSidebarPane.prototype = { var eventListener = eventListeners[i]; eventListener.node = WebInspector.domAgent.nodeForId(eventListener.nodeId); delete eventListener.nodeId; // no longer needed - if (/^function _inspectorCommandLineAPI_logEvent\(/.test(eventListener.listener.toString())) + if (/^function _inspectorCommandLineAPI_logEvent\(/.test(eventListener.listenerBody.toString())) continue; // ignore event listeners generated by monitorEvent var type = eventListener.type; var section = sectionMap[type]; @@ -155,7 +155,7 @@ WebInspector.EventListenersSection.prototype = { var length = filteredEventListeners.length; for (var i = 0; i < length; ++i) { var eventListener = filteredEventListeners[i]; - var eventListenerBar = new WebInspector.EventListenerBar(eventListener); + var eventListenerBar = new WebInspector.EventListenerBar(eventListener, this._nodeId); if (i < length - 1) { var connector = document.createElement("div"); connector.className = "event-bar-connector"; @@ -174,10 +174,13 @@ WebInspector.EventListenersSection.prototype = { WebInspector.EventListenersSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype; -WebInspector.EventListenerBar = function(eventListener) +WebInspector.EventListenerBar = function(eventListener, nodeId) { this.eventListener = eventListener; - WebInspector.ObjectPropertiesSection.call(this, null, this._getFunctionDisplayName(), this._getNodeDisplayName()); + this._nodeId = nodeId; + WebInspector.ObjectPropertiesSection.call(this); + this._setNodeTitle(); + this._setFunctionSubtitle(); this.editable = false; this.element.className = "event-bar"; /* Changed from "section" */ this.propertiesElement.className = "event-properties"; /* Changed from "properties" */ @@ -199,23 +202,39 @@ WebInspector.EventListenerBar.prototype = { this.updateProperties(properties); }, - _getNodeDisplayName: function() + _setNodeTitle: function() { var node = this.eventListener.node; if (!node) - return ""; + return; + + if (node.nodeType === Node.DOCUMENT_NODE) { + this.titleElement.textContent = "document"; + return; + } - if (node.nodeType === Node.DOCUMENT_NODE) - return "document"; + if (node.id === this._nodeId) { + this.titleElement.textContent = appropriateSelectorForNode(node); + return; + } - return appropriateSelectorForNode(node); + this.titleElement.removeChildren(); + this.titleElement.appendChild(WebInspector.panels.elements.linkifyNodeReference(this.eventListener.node)); }, - _getFunctionDisplayName: function() + _setFunctionSubtitle: function() { // Requires that Function.toString() return at least the function's signature. - var match = this.eventListener.listener.toString().match(/function ([^\(]+?)\(/); - return (match ? match[1] : WebInspector.UIString("(anonymous function)")); + if (this.eventListener.sourceName) { + this.subtitleElement.removeChildren(); + this.subtitleElement.appendChild(WebInspector.linkifyResourceAsNode(this.eventListener.sourceName, "scripts", this.eventListener.lineNumber)); + } else { + var match = this.eventListener.listenerBody.match(/function ([^\(]+?)\(/); + if (match) + this.subtitleElement.textContent = match[1]; + else + this.subtitleElement.textContent = WebInspector.UIString("(anonymous function)"); + } } } diff --git a/WebCore/inspector/front-end/FontView.js b/WebCore/inspector/front-end/FontView.js index 8468cc9..b011204 100644 --- a/WebCore/inspector/front-end/FontView.js +++ b/WebCore/inspector/front-end/FontView.js @@ -31,24 +31,35 @@ WebInspector.FontView = function(resource) WebInspector.ResourceView.call(this, resource); this.element.addStyleClass("font"); +} - var uniqueFontName = "WebInspectorFontPreview" + this.resource.identifier; +WebInspector.FontView.prototype = { + hasContentTab: function() + { + return true; + }, - this.fontStyleElement = document.createElement("style"); - this.fontStyleElement.textContent = "@font-face { font-family: \"" + uniqueFontName + "\"; src: url(" + this.resource.url + "); }"; - document.head.appendChild(this.fontStyleElement); + contentTabSelected: function() + { + if (this.fontPreviewElement) + return; - this.fontPreviewElement = document.createElement("div"); - this.fontPreviewElement.className = "preview"; - this.contentElement.appendChild(this.fontPreviewElement); + var uniqueFontName = "WebInspectorFontPreview" + this.resource.identifier; - this.fontPreviewElement.style.setProperty("font-family", uniqueFontName, null); - this.fontPreviewElement.innerHTML = "ABCDEFGHIJKLM<br>NOPQRSTUVWXYZ<br>abcdefghijklm<br>nopqrstuvwxyz<br>1234567890"; + this.fontStyleElement = document.createElement("style"); + this.fontStyleElement.textContent = "@font-face { font-family: \"" + uniqueFontName + "\"; src: url(" + this.resource.url + "); }"; + document.head.appendChild(this.fontStyleElement); - this.updateFontPreviewSize(); -} + this.fontPreviewElement = document.createElement("div"); + this.contentElement.appendChild(this.fontPreviewElement); + + this.fontPreviewElement.style.setProperty("font-family", uniqueFontName, null); + this.fontPreviewElement.innerHTML = "ABCDEFGHIJKLM<br>NOPQRSTUVWXYZ<br>abcdefghijklm<br>nopqrstuvwxyz<br>1234567890"; + this._lineCount = this.fontPreviewElement.getElementsByTagName("br").length + 1; + + this.updateFontPreviewSize(); + }, -WebInspector.FontView.prototype = { show: function(parentElement) { WebInspector.ResourceView.prototype.show.call(this, parentElement); @@ -60,44 +71,36 @@ WebInspector.FontView.prototype = { this.updateFontPreviewSize(); }, - updateFontPreviewSize: function () + updateFontPreviewSize: function() { if (!this.fontPreviewElement || !this.visible) return; - this.fontPreviewElement.removeStyleClass("preview"); - - var measureFontSize = 50; - this.fontPreviewElement.style.setProperty("position", "absolute", null); + const measureFontSize = 50; this.fontPreviewElement.style.setProperty("font-size", measureFontSize + "px", null); + this.fontPreviewElement.style.setProperty("position", "absolute", null); this.fontPreviewElement.style.removeProperty("height"); - var height = this.fontPreviewElement.offsetHeight; - var width = this.fontPreviewElement.offsetWidth; - - var containerWidth = this.contentElement.offsetWidth; + const height = this.fontPreviewElement.offsetHeight; + const width = this.fontPreviewElement.offsetWidth; // Subtract some padding. This should match the padding in the CSS plus room for the scrollbar. - containerWidth -= 40; + const containerWidth = this.contentElement.offsetWidth - 50; if (!height || !width || !containerWidth) { this.fontPreviewElement.style.removeProperty("font-size"); this.fontPreviewElement.style.removeProperty("position"); - this.fontPreviewElement.addStyleClass("preview"); return; } - var lineCount = this.fontPreviewElement.getElementsByTagName("br").length + 1; - var realLineHeight = Math.floor(height / lineCount); + var realLineHeight = Math.floor(height / this._lineCount); var fontSizeLineRatio = measureFontSize / realLineHeight; var widthRatio = containerWidth / width; - var finalFontSize = Math.floor(realLineHeight * widthRatio * fontSizeLineRatio) - 1; + var finalFontSize = Math.floor(realLineHeight * widthRatio * fontSizeLineRatio) - 2; this.fontPreviewElement.style.setProperty("font-size", finalFontSize + "px", null); this.fontPreviewElement.style.setProperty("height", this.fontPreviewElement.offsetHeight + "px", null); this.fontPreviewElement.style.removeProperty("position"); - - this.fontPreviewElement.addStyleClass("preview"); } } diff --git a/WebCore/inspector/front-end/ImageView.js b/WebCore/inspector/front-end/ImageView.js index c13c9a5..0c15a40 100644 --- a/WebCore/inspector/front-end/ImageView.js +++ b/WebCore/inspector/front-end/ImageView.js @@ -34,6 +34,11 @@ WebInspector.ImageView = function(resource) } WebInspector.ImageView.prototype = { + hasContentTab: function() + { + return true; + }, + contentTabSelected: function() { if (this._container) diff --git a/WebCore/inspector/front-end/InjectedScript.js b/WebCore/inspector/front-end/InjectedScript.js index 8984d0e..e3be6a3 100644 --- a/WebCore/inspector/front-end/InjectedScript.js +++ b/WebCore/inspector/front-end/InjectedScript.js @@ -841,9 +841,6 @@ InjectedScript.CallFrameProxy = function(id, callFrame) this.scopeChain = this._wrapScopeChain(callFrame); } -// FIXME(37663): unify scope chain representation and remove this if. -if (jsEngine === "v8") { - InjectedScript.CallFrameProxy.prototype = { _wrapScopeChain: function(callFrame) { @@ -855,12 +852,12 @@ InjectedScript.CallFrameProxy.prototype = { var scopeChain = callFrame.scopeChain; var scopeChainProxy = []; + var foundLocalScope = false; for (var i = 0; i < scopeChain.length; i++) { var scopeType = callFrame.scopeType(i); var scopeObject = scopeChain[i]; var scopeObjectProxy = InjectedScript.createProxyObject(scopeObject, { callFrame: this.id, chainIndex: i }, true); - var foundLocalScope = false; switch(scopeType) { case LOCAL_SCOPE: { foundLocalScope = true; @@ -874,57 +871,21 @@ InjectedScript.CallFrameProxy.prototype = { } case WITH_SCOPE: case CATCH_SCOPE: { - scopeObjectProxy.isWithBlock = true; + if (foundLocalScope && scopeObject instanceof inspectedWindow.Element) + scopeObjectProxy.isElement = true; + else if (foundLocalScope && scopeObject instanceof inspectedWindow.Document) + scopeObjectProxy.isDocument = true; + else + scopeObjectProxy.isWithBlock = true; break; } } - - if (foundLocalScope) { - if (scopeObject instanceof inspectedWindow.Element) - scopeObjectProxy.isElement = true; - else if (scopeObject instanceof inspectedWindow.Document) - scopeObjectProxy.isDocument = true; - } - - scopeChainProxy.push(scopeObjectProxy); - } - return scopeChainProxy; - } -} - -} else { - -InjectedScript.CallFrameProxy.prototype = { - _wrapScopeChain: function(callFrame) - { - var foundLocalScope = false; - var scopeChain = callFrame.scopeChain; - var scopeChainProxy = []; - for (var i = 0; i < scopeChain.length; ++i) { - var scopeObject = scopeChain[i]; - var scopeObjectProxy = InjectedScript.createProxyObject(scopeObject, { callFrame: this.id, chainIndex: i }, true); - - if (InjectedScriptHost.isActivation(scopeObject)) { - if (!foundLocalScope) - scopeObjectProxy.thisObject = InjectedScript.createProxyObject(callFrame.thisObject, { callFrame: this.id, thisObject: true }, true); - else - scopeObjectProxy.isClosure = true; - foundLocalScope = true; - scopeObjectProxy.isLocal = true; - } else if (foundLocalScope && scopeObject instanceof inspectedWindow.Element) - scopeObjectProxy.isElement = true; - else if (foundLocalScope && scopeObject instanceof inspectedWindow.Document) - scopeObjectProxy.isDocument = true; - else if (!foundLocalScope) - scopeObjectProxy.isWithBlock = true; scopeChainProxy.push(scopeObjectProxy); } return scopeChainProxy; } } -} - InjectedScript.executeSql = function(callId, databaseId, query) { function successCallback(tx, result) @@ -1052,8 +1013,19 @@ InjectedScript._toString = function(obj) InjectedScript._className = function(obj) { - var str = inspectedWindow.Object ? inspectedWindow.Object.prototype.toString.call(obj) : InjectedScript._toString(obj); - return str.replace(/^\[object (.*)\]$/i, "$1"); + // We can't use the same code for fetching class names of the dom bindings prototype chain. + // Both of the methods below result in "Object" names on the foreign engine bindings. + // I gave up and am using a check below to distinguish between the egine bingings. + + if (typeof Document === "object") { + // JSC + var str = inspectedWindow.Object ? inspectedWindow.Object.prototype.toString.call(obj) : InjectedScript._toString(obj); + return str.replace(/^\[object (.*)\]$/i, "$1"); + } + // V8 + if (typeof obj !== "object") + return "null"; + return obj.constructor.name; } InjectedScript._escapeCharacters = function(str, chars) diff --git a/WebCore/inspector/front-end/Panel.js b/WebCore/inspector/front-end/Panel.js index b916708..6dbc60e 100644 --- a/WebCore/inspector/front-end/Panel.js +++ b/WebCore/inspector/front-end/Panel.js @@ -84,10 +84,12 @@ WebInspector.Panel.prototype = { WebInspector.currentFocusElement = this.defaultFocusedElement; this.updateSidebarWidth(); + this._restoreScrollPositions(); }, hide: function() { + this._storeScrollPositions(); WebInspector.View.prototype.hide.call(this); if (this._statusBarItemContainer && this._statusBarItemContainer.parentNode) @@ -386,6 +388,30 @@ WebInspector.Panel.prototype = { searchIteratesOverViews: function() { return false; + }, + + elementsToRestoreScrollPositionsFor: function() + { + return []; + }, + + _storeScrollPositions: function() + { + var elements = this.elementsToRestoreScrollPositionsFor(); + for (var i = 0; i < elements.length; ++i) { + var container = elements[i]; + container._scrollTop = container.scrollTop; + } + }, + + _restoreScrollPositions: function() + { + var elements = this.elementsToRestoreScrollPositionsFor(); + for (var i = 0; i < elements.length; ++i) { + var container = elements[i]; + if (container._scrollTop) + container.scrollTop = container._scrollTop; + } } } diff --git a/WebCore/inspector/front-end/Popover.js b/WebCore/inspector/front-end/Popover.js index 848c99e..59b48f9 100644 --- a/WebCore/inspector/front-end/Popover.js +++ b/WebCore/inspector/front-end/Popover.js @@ -175,7 +175,7 @@ WebInspector.PopoverHelper.prototype = { var self = this; function doHide() { - self.hidePopup(); + self._hidePopup(); delete self._hidePopupTimer; } this._hidePopupTimer = setTimeout(doHide, 500); @@ -206,6 +206,12 @@ WebInspector.PopoverHelper.prototype = { hidePopup: function() { + this._resetHoverTimer(); + this._hidePopup(); + }, + + _hidePopup: function() + { if (!this._popup) return; diff --git a/WebCore/inspector/front-end/ProfilesPanel.js b/WebCore/inspector/front-end/ProfilesPanel.js index 2f9d38d..cca9e33 100644 --- a/WebCore/inspector/front-end/ProfilesPanel.js +++ b/WebCore/inspector/front-end/ProfilesPanel.js @@ -311,14 +311,37 @@ WebInspector.ProfilesPanel.prototype = { profile._profilesTreeElement = profileTreeElement; sidebarParent.appendChild(profileTreeElement); - this.welcomeView.hide(); - if (!this.visibleView) - this.showProfile(profile); + if (!profile.isTemporary) { + this.welcomeView.hide(); + if (!this.visibleView) + this.showProfile(profile); + } + }, + + removeProfileHeader: function(profile) + { + var typeId = profile.typeId; + var profileType = this.getProfileType(typeId); + var sidebarParent = profileType.treeElement; + + for (var i = 0; i < this._profiles.length; ++i) { + if (this._profiles[i].uid === profile.uid) { + profile = this._profiles[i]; + this._profiles.splice(i, 1); + break; + } + } + delete this._profilesIdMap[this._makeKey(profile.uid, typeId)]; + + var profileTitleKey = this._makeKey(profile.title, typeId); + delete this._profileGroups[profileTitleKey]; + + sidebarParent.removeChild(profile._profilesTreeElement); }, showProfile: function(profile) { - if (!profile) + if (!profile || profile.isTemporary) return; this.closeVisibleView(); diff --git a/WebCore/inspector/front-end/Resource.js b/WebCore/inspector/front-end/Resource.js index 4ee5f28..739dd73 100644 --- a/WebCore/inspector/front-end/Resource.js +++ b/WebCore/inspector/front-end/Resource.js @@ -536,6 +536,12 @@ WebInspector.Resource.prototype = { _mimeTypeIsConsistentWithType: function() { + // If status is an error, content is likely to be of an inconsistent type, + // as it's going to be an error message. We do not want to emit a warning + // for this, though, as this will already be reported as resource loading failure. + if (this.statusCode >= 400) + return true; + if (typeof this.type === "undefined" || this.type === WebInspector.Resource.Type.Other || this.type === WebInspector.Resource.Type.XHR) diff --git a/WebCore/inspector/front-end/ResourceView.js b/WebCore/inspector/front-end/ResourceView.js index 618a935..fac57b4 100644 --- a/WebCore/inspector/front-end/ResourceView.js +++ b/WebCore/inspector/front-end/ResourceView.js @@ -43,11 +43,12 @@ WebInspector.ResourceView = function(resource) this.headersTabElement.textContent = WebInspector.UIString("Headers"); this.contentTabElement = document.createElement("li"); this.contentTabElement.textContent = WebInspector.UIString("Content"); + this.tabsElement.appendChild(this.headersTabElement); this.tabsElement.appendChild(this.contentTabElement); - this.headersTabElement.addEventListener("click", this._selectHeadersTab.bind(this), false); - this.contentTabElement.addEventListener("click", this.selectContentTab.bind(this), false); + this.headersTabElement.addEventListener("click", this._selectHeadersTab.bind(this, true), false); + this.contentTabElement.addEventListener("click", this.selectContentTab.bind(this, true), false); this.headersElement = document.createElement("div"); this.headersElement.className = "resource-view-headers"; @@ -118,6 +119,8 @@ WebInspector.ResourceView = function(resource) this._refreshRequestHeaders(); this._refreshResponseHeaders(); this._refreshHTTPInformation(); + if (!this.hasContentTab()) + this.contentTabElement.addStyleClass("hidden"); this._selectTab(); } @@ -152,7 +155,7 @@ WebInspector.ResourceView.prototype = { _selectTab: function() { if (this._headersVisible) { - if (WebInspector.settings.resourceViewTab === "headers") + if (!this.hasContentTab() || WebInspector.settings.resourceViewTab === "headers") this._selectHeadersTab(); else this.selectContentTab(); @@ -160,21 +163,29 @@ WebInspector.ResourceView.prototype = { this._innerSelectContentTab(); }, - _selectHeadersTab: function() + _selectHeadersTab: function(updatePrefs) { - WebInspector.settings.resourceViewTab = "headers"; + if (updatePrefs) + WebInspector.settings.resourceViewTab = "headers"; this.headersTabElement.addStyleClass("selected"); this.contentTabElement.removeStyleClass("selected"); this.headersElement.removeStyleClass("hidden"); this.contentElement.addStyleClass("hidden"); }, - selectContentTab: function() + selectContentTab: function(updatePrefs) { - WebInspector.settings.resourceViewTab = "content"; + if (updatePrefs) + WebInspector.settings.resourceViewTab = "content"; this._innerSelectContentTab(); }, + hasContentTab: function() + { + // Derived classes should override this method and define this.contentTabSelected for content rendering. + return false; + }, + _innerSelectContentTab: function() { this.contentTabElement.addStyleClass("selected"); @@ -186,16 +197,6 @@ WebInspector.ResourceView.prototype = { this.contentTabSelected(); }, - contentTabSelected: function() - { - if (!this._contentPlaceholderElement) { - this._contentPlaceholderElement = document.createElement("div"); - this._contentPlaceholderElement.className = "resource-content-unavailable"; - this._contentPlaceholderElement.textContent = WebInspector.UIString("No Content Available"); - this.contentElement.appendChild(this._contentPlaceholderElement); - } - }, - _refreshURL: function() { this.urlTreeElement.title = "<div class=\"header-name\">" + WebInspector.UIString("Request URL") + ":</div>" + diff --git a/WebCore/inspector/front-end/ResourcesPanel.js b/WebCore/inspector/front-end/ResourcesPanel.js index 5284e68..a62994e 100644 --- a/WebCore/inspector/front-end/ResourcesPanel.js +++ b/WebCore/inspector/front-end/ResourcesPanel.js @@ -443,9 +443,6 @@ WebInspector.ResourcesPanel.prototype = { if (newView.__proto__ === resource._resourcesView.__proto__) return; - resource.warnings = 0; - resource.errors = 0; - if (!this.currentQuery && resource._itemsTreeElement) resource._itemsTreeElement.updateErrorsAndWarnings(); @@ -490,7 +487,7 @@ WebInspector.ResourcesPanel.prototype = { view.show(this.viewsContainerElement); if (line) { - view.selectContentTab(); + view.selectContentTab(true); if (view.revealLine) view.revealLine(line); if (view.highlightLine) @@ -574,6 +571,7 @@ WebInspector.ResourcesPanel.prototype = { return; } + this._timelineGrid.removeEventDividers(); if (this.mainResourceLoadTime !== -1) { var percent = this.calculator.computePercentageFromEventTime(this.mainResourceLoadTime); @@ -727,6 +725,11 @@ WebInspector.ResourcesPanel.prototype = { searchIteratesOverViews: function() { return true; + }, + + elementsToRestoreScrollPositionsFor: function() + { + return [ this.containerElement ]; } } diff --git a/WebCore/inspector/front-end/ScriptView.js b/WebCore/inspector/front-end/ScriptView.js index e55a685..cb10889 100644 --- a/WebCore/inspector/front-end/ScriptView.js +++ b/WebCore/inspector/front-end/ScriptView.js @@ -77,11 +77,6 @@ WebInspector.ScriptView.prototype = { WebInspector.panels.scripts.addBreakpoint(breakpoint); }, - _editLine: function(line, newContent) - { - WebInspector.panels.scripts.editScriptLine(this.script.sourceID, line, newContent, this._editLineComplete.bind(this)); - }, - _editLineComplete: function(newBody) { this.script.source = newBody; @@ -107,6 +102,7 @@ WebInspector.ScriptView.prototype = { _jumpToSearchResult: WebInspector.SourceView.prototype._jumpToSearchResult, _sourceFrameSetupFinished: WebInspector.SourceView.prototype._sourceFrameSetupFinished, _removeBreakpoint: WebInspector.SourceView.prototype._removeBreakpoint, + _editLine: WebInspector.SourceView.prototype._editLine, resize: WebInspector.SourceView.prototype.resize } diff --git a/WebCore/inspector/front-end/ScriptsPanel.js b/WebCore/inspector/front-end/ScriptsPanel.js index 987bdf2..6344554 100644 --- a/WebCore/inspector/front-end/ScriptsPanel.js +++ b/WebCore/inspector/front-end/ScriptsPanel.js @@ -248,6 +248,13 @@ WebInspector.ScriptsPanel.prototype = { delete this._attachDebuggerWhenShown; } }, + + hide: function() + { + WebInspector.Panel.prototype.hide.call(this); + if (this.visibleView) + this.visibleView.hide(); + }, get searchableViews() { @@ -352,10 +359,10 @@ WebInspector.ScriptsPanel.prototype = { canEditScripts: function() { - return !!InspectorBackend.editScriptLine; + return !!InspectorBackend.editScriptSource; }, - editScriptLine: function(sourceID, line, newContent, callback) + editScriptSource: function(sourceID, newContent, line, linesCountToShift, callback) { if (!this.canEditScripts()) return; @@ -369,7 +376,6 @@ WebInspector.ScriptsPanel.prototype = { newBreakpoints.push(breakpoint); } - var linesCountToShift = newContent.split("\n").length - 1; function mycallback(newBody) { callback(newBody); @@ -381,7 +387,7 @@ WebInspector.ScriptsPanel.prototype = { } }; var callbackId = WebInspector.Callback.wrap(mycallback.bind(this)) - InspectorBackend.editScriptLine(callbackId, sourceID, line, newContent); + InspectorBackend.editScriptSource(callbackId, sourceID, newContent); }, selectedCallFrameId: function() @@ -992,9 +998,14 @@ WebInspector.ScriptsPanel.prototype = { this.toggleBreakpointsButton.title = WebInspector.UIString("Activate all breakpoints."); document.getElementById("main-panels").addStyleClass("breakpoints-deactivated"); } + }, + + elementsToRestoreScrollPositionsFor: function() + { + return [ this.sidebarElement ]; } } WebInspector.ScriptsPanel.prototype.__proto__ = WebInspector.Panel.prototype; -WebInspector.didEditScriptLine = WebInspector.Callback.processCallback; +WebInspector.didEditScriptSource = WebInspector.Callback.processCallback; diff --git a/WebCore/inspector/front-end/SourceFrame.js b/WebCore/inspector/front-end/SourceFrame.js index 99280fc..2dec650 100644 --- a/WebCore/inspector/front-end/SourceFrame.js +++ b/WebCore/inspector/front-end/SourceFrame.js @@ -39,7 +39,6 @@ WebInspector.SourceFrame = function(parentElement, addBreakpointDelegate, remove this._rowMessages = {}; this._messageBubbles = {}; this.breakpoints = []; - this._shortcuts = {}; this._loaded = false; @@ -55,9 +54,12 @@ WebInspector.SourceFrame.prototype = { { this._visible = visible; this._createViewerIfNeeded(); - if (!visible && this._textViewer) - this._textViewer.freeCachedElements(); - + + if (!visible) { + this._hidePopup(); + if (this._textViewer) + this._textViewer.freeCachedElements(); + } }, get executionLine() @@ -149,6 +151,11 @@ WebInspector.SourceFrame.prototype = { this._textModel.setText(null, content); }, + get textModel() + { + return this._textModel; + }, + highlightLine: function(line) { if (this._textViewer) @@ -164,7 +171,6 @@ WebInspector.SourceFrame.prototype = { this._textViewer = new WebInspector.TextViewer(this._textModel, WebInspector.platform, this._url); var element = this._textViewer.element; - element.addEventListener("keydown", this._keyDown.bind(this), true); element.addEventListener("contextmenu", this._contextMenu.bind(this), true); element.addEventListener("mousedown", this._mouseDown.bind(this), true); element.addEventListener("mousemove", this._mouseMove.bind(this), true); @@ -669,17 +675,6 @@ WebInspector.SourceFrame.prototype = { return conditionElement; }, - _keyDown: function(event) - { - var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event); - var handler = this._shortcuts[shortcut]; - if (handler) { - handler(event); - event.preventDefault(); - } else - WebInspector.documentKeyDown(event); - }, - _evalSelectionInCallFrame: function(event) { if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused) @@ -689,7 +684,7 @@ WebInspector.SourceFrame.prototype = { if (!selection.rangeCount) return; - var expression = selection.getRangeAt(0).toString().trimWhitespace(); + var expression = selection.getRangeAt(0).toString().trim(); WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, "console", function(result, exception) { WebInspector.showConsole(); var commandMessage = new WebInspector.ConsoleCommand(expression); diff --git a/WebCore/inspector/front-end/SourceView.js b/WebCore/inspector/front-end/SourceView.js index 9fbd161..3621187 100644 --- a/WebCore/inspector/front-end/SourceView.js +++ b/WebCore/inspector/front-end/SourceView.js @@ -32,7 +32,8 @@ WebInspector.SourceView = function(resource) this.element.addStyleClass("source"); - this.sourceFrame = new WebInspector.SourceFrame(this.contentElement, this._addBreakpoint.bind(this), this._removeBreakpoint.bind(this)); + var canEditScripts = WebInspector.panels.scripts.canEditScripts() && resource.type === WebInspector.Resource.Type.Script; + this.sourceFrame = new WebInspector.SourceFrame(this.contentElement, this._addBreakpoint.bind(this), this._removeBreakpoint.bind(this), canEditScripts ? this._editLine.bind(this) : null); resource.addEventListener("finished", this._resourceLoadingFinished, this); this._frameNeedsSetup = true; } @@ -77,6 +78,11 @@ WebInspector.SourceView.prototype = { WebInspector.getResourceContent(this.resource.identifier, this._contentLoaded.bind(this)); }, + hasContentTab: function() + { + return true; + }, + contentTabSelected: function() { this.setupSourceFrameIfNeeded(); @@ -105,17 +111,7 @@ WebInspector.SourceView.prototype = { _addBreakpoint: function(line) { - var sourceID = null; - var closestStartingLine = 0; - var scripts = this.resource.scripts; - for (var i = 0; i < scripts.length; ++i) { - var script = scripts[i]; - if (script.startingLine <= line && script.startingLine >= closestStartingLine) { - closestStartingLine = script.startingLine; - sourceID = script.sourceID; - } - } - + var sourceID = this._sourceIDForLine(line); if (WebInspector.panels.scripts) { var breakpoint = new WebInspector.Breakpoint(this.resource.url, line, sourceID); WebInspector.panels.scripts.addBreakpoint(breakpoint); @@ -128,6 +124,41 @@ WebInspector.SourceView.prototype = { WebInspector.panels.scripts.removeBreakpoint(breakpoint); }, + _editLine: function(line, newContent) + { + var lines = []; + var textModel = this.sourceFrame.textModel; + for (var i = 0; i < textModel.linesCount; ++i) { + if (i === line) + lines.push(newContent); + else + lines.push(textModel.line(i)); + } + + var linesCountToShift = newContent.split("\n").length - 1; + WebInspector.panels.scripts.editScriptSource(this._sourceIDForLine(line), lines.join("\n"), line, linesCountToShift, this._editLineComplete.bind(this)); + }, + + _editLineComplete: function(newBody) + { + this.sourceFrame.updateContent(newBody); + }, + + _sourceIDForLine: function(line) + { + var sourceID = null; + var closestStartingLine = 0; + var scripts = this.resource.scripts; + for (var i = 0; i < scripts.length; ++i) { + var script = scripts[i]; + if (script.startingLine <= line && script.startingLine >= closestStartingLine) { + closestStartingLine = script.startingLine; + sourceID = script.sourceID; + } + } + return sourceID; + }, + // The rest of the methods in this prototype need to be generic enough to work with a ScriptView. // The ScriptView prototype pulls these methods into it's prototype to avoid duplicate code. diff --git a/WebCore/inspector/front-end/StylesSidebarPane.js b/WebCore/inspector/front-end/StylesSidebarPane.js index eb5e012..c280fbb 100644 --- a/WebCore/inspector/front-end/StylesSidebarPane.js +++ b/WebCore/inspector/front-end/StylesSidebarPane.js @@ -409,10 +409,7 @@ WebInspector.StylesSidebarPane.prototype = { var separatorElement = document.createElement("div"); separatorElement.className = "styles-sidebar-separator"; if (styleRule.node) { - var link = document.createElement("a"); - link.href = ""; - link.addEventListener("mousedown", this._selectNode.bind(this, styleRule.node.id), false); - WebInspector.panels.elements.decorateNodeLabel(styleRule.node, link); + var link = WebInspector.panels.elements.linkifyNodeReference(styleRule.node); separatorElement.appendChild(document.createTextNode(WebInspector.UIString("Inherited from") + " ")); separatorElement.appendChild(link); } else if ("pseudoId" in styleRule) { @@ -454,12 +451,6 @@ WebInspector.StylesSidebarPane.prototype = { return sections; }, - _selectNode: function(nodeId, e) - { - WebInspector.updateFocusedNode(nodeId); - e.preventDefault(); - }, - _containsInherited: function(payload) { var properties = []; @@ -1289,7 +1280,7 @@ WebInspector.StylePropertyTreeElement.prototype = { if (WebInspector.isBeingEdited(this.listItemElement) || (this.treeOutline.section && !this.treeOutline.section.editable)) return; - var context = { expanded: this.expanded, hasChildren: this.hasChildren }; + var context = { expanded: this.expanded, hasChildren: this.hasChildren, keyDownListener: this.editingKeyDown.bind(this) }; // Lie about our children to prevent expanding on double click and to collapse shorthands. this.hasChildren = false; @@ -1297,7 +1288,7 @@ WebInspector.StylePropertyTreeElement.prototype = { if (!selectElement) selectElement = this.listItemElement; - this.listItemElement.handleKeyEvent = this.editingKeyDown.bind(this); + this.listItemElement.addEventListener("keydown", context.keyDownListener, false); WebInspector.startEditing(this.listItemElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context); window.getSelection().setBaseAndExtent(selectElement, 0, selectElement, 1); @@ -1378,7 +1369,7 @@ WebInspector.StylePropertyTreeElement.prototype = { selection.removeAllRanges(); selection.addRange(finalSelectionRange); - event.handled = true; + event.preventDefault(); if (!this.originalCSSText) { // Remember the rule's original CSS text, so it can be restored @@ -1398,7 +1389,7 @@ WebInspector.StylePropertyTreeElement.prototype = { this.hasChildren = context.hasChildren; if (context.expanded) this.expand(); - delete this.listItemElement.handleKeyEvent; + this.listItemElement.removeEventListener("keydown", context.keyDownListener, false); delete this.originalCSSText; }, diff --git a/WebCore/inspector/front-end/SummaryBar.js b/WebCore/inspector/front-end/SummaryBar.js index 1c31449..4bd5c65 100644 --- a/WebCore/inspector/front-end/SummaryBar.js +++ b/WebCore/inspector/front-end/SummaryBar.js @@ -230,13 +230,13 @@ WebInspector.SummaryBar.prototype = { ctx.beginPath(); ctx.moveTo(x, y + r); ctx.lineTo(x, y + h - r); - ctx.quadraticCurveTo(x, y + h, x + r, y + h); + ctx.arc(x + r, y + h - r, r, Math.PI, Math.PI / 2, true); ctx.lineTo(x + w - r, y + h); - ctx.quadraticCurveTo(x + w, y + h, x + w, y + h - r); + ctx.arc(x + w - r, y + h - r, r, Math.PI / 2, 0, true); ctx.lineTo(x + w, y + r); - ctx.quadraticCurveTo(x + w, y, x + w - r, y); + ctx.arc(x + w - r, y + r, r, 0, 3 * Math.PI / 2, true); ctx.lineTo(x + r, y); - ctx.quadraticCurveTo(x, y, x, y + r); + ctx.arc(x + r, y + r, r, Math.PI / 2, Math.PI, true); ctx.closePath(); // Clip to the rounded rect path. diff --git a/WebCore/inspector/front-end/TextPrompt.js b/WebCore/inspector/front-end/TextPrompt.js index d179a9a..7fcce8c 100644 --- a/WebCore/inspector/front-end/TextPrompt.js +++ b/WebCore/inspector/front-end/TextPrompt.js @@ -29,6 +29,7 @@ WebInspector.TextPrompt = function(element, completions, stopCharacters) { this.element = element; + this.element.addStyleClass("text-prompt"); this.completions = completions; this.completionStopCharacters = stopCharacters; this.history = []; diff --git a/WebCore/inspector/front-end/TextViewer.js b/WebCore/inspector/front-end/TextViewer.js index de04641..eae7394 100644 --- a/WebCore/inspector/front-end/TextViewer.js +++ b/WebCore/inspector/front-end/TextViewer.js @@ -251,9 +251,14 @@ WebInspector.TextViewer.prototype = { if (!this._editCallback) return; - var lineRow = e.target.enclosingNodeOrSelfWithNodeName("TR"); - if (!lineRow) + var cell = e.target.enclosingNodeOrSelfWithNodeName("TD"); + if (!cell) return; + + var lineRow = cell.parentElement; + if (lineRow.firstChild === cell) + return; // Do not trigger editing from line numbers. + var oldContent = lineRow.lastChild.innerHTML; this._editingLine = WebInspector.startEditing(lineRow.lastChild, this._commitEditingLine.bind(this, lineRow.lineNumber, lineRow.lastChild), this._cancelEditingLine.bind(this, lineRow.lastChild, oldContent), null, true); }, diff --git a/WebCore/inspector/front-end/TimelineGrid.js b/WebCore/inspector/front-end/TimelineGrid.js index fb93b8f..3286e65 100644 --- a/WebCore/inspector/front-end/TimelineGrid.js +++ b/WebCore/inspector/front-end/TimelineGrid.js @@ -66,7 +66,6 @@ WebInspector.TimelineGrid.prototype = { paddingLeft = 0; this._currentDividerSlice = slice; - this._eventDividersElement.removeChildren(); // Reuse divider elements and labels. var divider = this._dividersElement.firstChild; var dividerLabelBar = this._dividersLabelBarElement.firstChild; @@ -135,6 +134,15 @@ WebInspector.TimelineGrid.prototype = { this._eventDividersElement.appendChild(divider); }, + addEventDividers: function(dividers) + { + this.element.removeChild(this._eventDividersElement); + for (var i = 0; i < dividers.length; ++i) + if (dividers[i]) + this._eventDividersElement.appendChild(dividers[i]); + this.element.appendChild(this._eventDividersElement); + }, + removeEventDividers: function() { this._eventDividersElement.removeChildren(); diff --git a/WebCore/inspector/front-end/TimelineOverviewPane.js b/WebCore/inspector/front-end/TimelineOverviewPane.js index 7191ef8..aaf2adb 100644 --- a/WebCore/inspector/front-end/TimelineOverviewPane.js +++ b/WebCore/inspector/front-end/TimelineOverviewPane.js @@ -54,6 +54,7 @@ WebInspector.TimelineOverviewPane = function(categories) this._overviewGrid = new WebInspector.TimelineGrid(); this._overviewGrid.element.id = "timeline-overview-grid"; this._overviewGrid.itemsGraphsElement.id = "timeline-overview-graphs"; + this._overviewGrid.element.addEventListener("mousedown", this._dragWindow.bind(this), true); this.element.appendChild(this._overviewGrid.element); this._categoryGraphs = {}; @@ -67,20 +68,25 @@ WebInspector.TimelineOverviewPane = function(categories) this._overviewWindowElement = document.createElement("div"); this._overviewWindowElement.id = "timeline-overview-window"; - this._overviewWindowElement.addEventListener("mousedown", this._dragWindow.bind(this), false); this._overviewGrid.element.appendChild(this._overviewWindowElement); + this._overviewWindowBordersElement = document.createElement("div"); + this._overviewWindowBordersElement.className = "timeline-overview-window-rulers"; + this._overviewGrid.element.appendChild(this._overviewWindowBordersElement); + + var overviewDividersBackground = document.createElement("div"); + overviewDividersBackground.className = "timeline-overview-dividers-background"; + this._overviewGrid.element.appendChild(overviewDividersBackground); + this._leftResizeElement = document.createElement("div"); this._leftResizeElement.className = "timeline-window-resizer"; this._leftResizeElement.style.left = 0; this._overviewGrid.element.appendChild(this._leftResizeElement); - this._leftResizeElement.addEventListener("mousedown", this._resizeWindow.bind(this, this._leftResizeElement), false); this._rightResizeElement = document.createElement("div"); this._rightResizeElement.className = "timeline-window-resizer timeline-window-resizer-right"; this._rightResizeElement.style.right = 0; this._overviewGrid.element.appendChild(this._rightResizeElement); - this._rightResizeElement.addEventListener("mousedown", this._resizeWindow.bind(this, this._rightResizeElement), false); this._overviewCalculator = new WebInspector.TimelineOverviewCalculator(); @@ -92,6 +98,8 @@ WebInspector.TimelineOverviewPane = function(categories) this.windowRight = 1.0; } +WebInspector.TimelineOverviewPane.minSelectableSize = 12; + WebInspector.TimelineOverviewPane.prototype = { _onCheckboxClicked: function (category, event) { if (event.target.checked) @@ -166,13 +174,18 @@ WebInspector.TimelineOverviewPane.prototype = { updateEventDividers: function(records, dividerConstructor) { this._overviewGrid.removeEventDividers(); + var dividers = []; for (var i = 0; i < records.length; ++i) { var record = records[i]; var positions = this._overviewCalculator.computeBarGraphPercentages(record); + var dividerPosition = Math.round(positions.start * 10); + if (dividers[dividerPosition]) + continue; var divider = dividerConstructor(record); divider.style.left = positions.start + "%"; - this._overviewGrid.addEventDivider(divider); + dividers[dividerPosition] = divider; } + this._overviewGrid.addEventDividers(dividers); }, setSidebarWidth: function(width) @@ -191,6 +204,8 @@ WebInspector.TimelineOverviewPane.prototype = { this.windowRight = 1.0; this._overviewWindowElement.style.left = "0%"; this._overviewWindowElement.style.width = "100%"; + this._overviewWindowBordersElement.style.left = "0%"; + this._overviewWindowBordersElement.style.right = "0%"; this._leftResizeElement.style.left = "0%"; this._rightResizeElement.style.left = "100%"; this._overviewCalculator.reset(); @@ -213,8 +228,42 @@ WebInspector.TimelineOverviewPane.prototype = { _dragWindow: function(event) { - WebInspector.elementDragStart(this._overviewWindowElement, this._windowDragging.bind(this, event.pageX, - this._leftResizeElement.offsetLeft, this._rightResizeElement.offsetLeft), this._endWindowDragging.bind(this), event, "ew-resize"); + var node = event.target; + while (node) { + if (node === this._overviewGrid._dividersLabelBarElement) { + WebInspector.elementDragStart(this._overviewWindowElement, this._windowDragging.bind(this, event.pageX, + this._leftResizeElement.offsetLeft, this._rightResizeElement.offsetLeft), this._endWindowDragging.bind(this), event, "ew-resize"); + break; + } else if (node === this._overviewGrid.element) { + var position = event.pageX - this._overviewGrid.element.offsetLeft; + this._overviewWindowSelector = new WebInspector.TimelinePanel.WindowSelector(this._overviewGrid.element, position, event); + WebInspector.elementDragStart(null, this._windowSelectorDragging.bind(this), this._endWindowSelectorDragging.bind(this), event, "col-resize"); + break; + } else if (node === this._leftResizeElement || node === this._rightResizeElement) { + this._resizeWindow(node, event); + break; + } + node = node.parentNode; + } + }, + + _windowSelectorDragging: function(event) + { + this._overviewWindowSelector._updatePosition(event.pageX - this._overviewGrid.element.offsetLeft); + event.preventDefault(); + }, + + _endWindowSelectorDragging: function(event) + { + WebInspector.elementDragEnd(event); + var window = this._overviewWindowSelector._close(event.pageX - this._overviewGrid.element.offsetLeft); + delete this._overviewWindowSelector; + if (window.end - window.start < WebInspector.TimelineOverviewPane.minSelectableSize) + if (this._overviewGrid.itemsGraphsElement.offsetWidth - window.end > WebInspector.TimelineOverviewPane.minSelectableSize) + window.end = window.start + WebInspector.TimelineOverviewPane.minSelectableSize; + else + window.start = window.end - WebInspector.TimelineOverviewPane.minSelectableSize; + this._setWindowPosition(window.start, window.end); }, _windowDragging: function(startX, windowLeft, windowRight, event) @@ -243,6 +292,8 @@ WebInspector.TimelineOverviewPane.prototype = { // Glue to edge. if (start < 10) start = 0; + else if (start > this._rightResizeElement.offsetLeft - 4) + start = this._rightResizeElement.offsetLeft - 4; this._setWindowPosition(start, null); }, @@ -251,27 +302,26 @@ WebInspector.TimelineOverviewPane.prototype = { // Glue to edge. if (end > this._overviewGrid.element.clientWidth - 10) end = this._overviewGrid.element.clientWidth; + else if (end < this._leftResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.minSelectableSize) + end = this._leftResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.minSelectableSize; this._setWindowPosition(null, end); }, _setWindowPosition: function(start, end) { + const rulerAdjustment = 1 / this._overviewGrid.element.clientWidth; if (typeof start === "number") { - if (start > this._rightResizeElement.offsetLeft - 4) - start = this._rightResizeElement.offsetLeft - 4; - this.windowLeft = start / this._overviewGrid.element.clientWidth; this._leftResizeElement.style.left = this.windowLeft * 100 + "%"; this._overviewWindowElement.style.left = this.windowLeft * 100 + "%"; + this._overviewWindowBordersElement.style.left = (this.windowLeft - rulerAdjustment) * 100 + "%"; } if (typeof end === "number") { - if (end < this._leftResizeElement.offsetLeft + 12) - end = this._leftResizeElement.offsetLeft + 12; - this.windowRight = end / this._overviewGrid.element.clientWidth; this._rightResizeElement.style.left = this.windowRight * 100 + "%"; } this._overviewWindowElement.style.width = (this.windowRight - this.windowLeft) * 100 + "%"; + this._overviewWindowBordersElement.style.right = (1 - this.windowRight + 2 * rulerAdjustment) * 100 + "%"; this.dispatchEventToListeners("window changed"); }, @@ -403,3 +453,48 @@ WebInspector.TimelineCategoryGraph.prototype = { this._barAreaElement.addStyleClass("timeline-category-" + this._category.name); } } + +WebInspector.TimelinePanel.WindowSelector = function(parent, position, event) +{ + this._startPosition = position; + this._width = parent.offsetWidth; + this._windowSelector = document.createElement("div"); + this._windowSelector.className = "timeline-window-selector"; + this._windowSelector.style.left = this._startPosition + "px"; + this._windowSelector.style.right = this._width - this._startPosition + + "px"; + parent.appendChild(this._windowSelector); +} + +WebInspector.TimelinePanel.WindowSelector.prototype = { + _createSelectorElement: function(parent, left, width, height) + { + var selectorElement = document.createElement("div"); + selectorElement.className = "timeline-window-selector"; + selectorElement.style.left = left + "px"; + selectorElement.style.width = width + "px"; + selectorElement.style.top = "0px"; + selectorElement.style.height = height + "px"; + parent.appendChild(selectorElement); + return selectorElement; + }, + + _close: function(position) + { + position = Math.max(0, Math.min(position, this._width)); + this._windowSelector.parentNode.removeChild(this._windowSelector); + return this._startPosition < position ? {start: this._startPosition, end: position} : {start: position, end: this._startPosition}; + }, + + _updatePosition: function(position) + { + position = Math.max(0, Math.min(position, this._width)); + if (position < this._startPosition) { + this._windowSelector.style.left = position + "px"; + this._windowSelector.style.right = this._width - this._startPosition + "px"; + } else { + this._windowSelector.style.left = this._startPosition + "px"; + this._windowSelector.style.right = this._width - position + "px"; + } + } +} + diff --git a/WebCore/inspector/front-end/TimelinePanel.js b/WebCore/inspector/front-end/TimelinePanel.js index 7b3e3b0..4ff9d5a 100644 --- a/WebCore/inspector/front-end/TimelinePanel.js +++ b/WebCore/inspector/front-end/TimelinePanel.js @@ -185,17 +185,18 @@ WebInspector.TimelinePanel.prototype = { { this._timelineGrid.removeEventDividers(); var clientWidth = this._graphRowsElement.offsetWidth - this._expandOffset; + var dividers = []; for (var i = 0; i < this._markTimelineRecords.length; ++i) { var record = this._markTimelineRecords[i]; var positions = this._calculator.computeBarGraphWindowPosition(record, clientWidth); - if (positions.left < 0 || positions.left >= clientWidth) + var dividerPosition = Math.round(positions.left); + if (dividerPosition < 0 || dividerPosition >= clientWidth || dividers[dividerPosition]) continue; - var divider = this._createEventDivider(record); - divider.style.left = (positions.left + this._expandOffset) + "px"; - - this._timelineGrid.addEventDivider(divider); + divider.style.left = (dividerPosition + this._expandOffset) + "px"; + dividers[dividerPosition] = divider; } + this._timelineGrid.addEventDividers(dividers); this._overviewPane.updateEventDividers(this._markTimelineRecords, this._createEventDivider.bind(this)); }, @@ -280,38 +281,56 @@ WebInspector.TimelinePanel.prototype = { _innerAddRecordToTimeline: function(record, parentRecord) { var connectedToOldRecord = false; - if (parentRecord === this._rootRecord) { + var recordTypes = WebInspector.TimelineAgent.RecordType; + if (record.type === recordTypes.MarkDOMContentEventType || record.type === recordTypes.MarkLoadEventType) + parentRecord = null; // No bar entry for load events. + else if (parentRecord === this._rootRecord) { var newParentRecord = this._findParentRecord(record); if (newParentRecord) { parentRecord = newParentRecord; connectedToOldRecord = true; } } - var recordTypes = WebInspector.TimelineAgent.RecordType; + + if (record.type == recordTypes.TimerFire && record.children && record.children.length === 1) { + var childRecord = record.children[0]; + if ( childRecord.type === recordTypes.FunctionCall) { + record.data.scriptName = childRecord.data.scriptName; + record.data.scriptLine = childRecord.data.scriptLine; + record.children = childRecord.children; + } + } var formattedRecord = new WebInspector.TimelinePanel.FormattedRecord(record, parentRecord, this._recordStyles, this._sendRequestRecords, this._timerRecords); if (record.type === recordTypes.MarkDOMContentEventType || record.type === recordTypes.MarkLoadEventType) { - // No bar entry for load events. this._markTimelineRecords.push(formattedRecord); return; } ++this._rootRecord._allRecordsCount; + formattedRecord.collapsed = (parentRecord === this._rootRecord); - if (parentRecord === this._rootRecord) - formattedRecord.collapsed = true; - - for (var i = 0; record.children && i < record.children.length; ++i) + var childrenCount = record.children ? record.children.length : 0; + for (var i = 0; i < childrenCount; ++i) this._innerAddRecordToTimeline(record.children[i], formattedRecord); + formattedRecord._calculateAggregatedStats(this.categories); + if (connectedToOldRecord) { var record = formattedRecord; - while (record.parent && record.parent._lastChildEndTime < record._lastChildEndTime) { - record.parent._lastChildEndTime = record._lastChildEndTime; - record = record.parent; - } - } + do { + var parent = record.parent; + parent._cpuTime += formattedRecord._cpuTime; + if (parent._lastChildEndTime < record._lastChildEndTime) + parent._lastChildEndTime = record._lastChildEndTime; + for (var category in formattedRecord._aggregatedStats) + parent._aggregatedStats[category] += formattedRecord._aggregatedStats[category]; + record = parent; + } while (record.parent); + } else + if (parentRecord !== this._rootRecord) + parentRecord._selfTime -= formattedRecord.endTime - formattedRecord.startTime; // Keep bar entry for mark timeline since nesting might be interesting to the user. if (record.type === recordTypes.MarkTimeline) @@ -344,6 +363,7 @@ WebInspector.TimelinePanel.prototype = { rootRecord.children = []; rootRecord._visibleRecordsCount = 0; rootRecord._allRecordsCount = 0; + rootRecord._aggregatedStats = {}; return rootRecord; }, @@ -365,8 +385,7 @@ WebInspector.TimelinePanel.prototype = { WebInspector.Panel.prototype.show.call(this); if (typeof this._scrollTop === "number") this._containerElement.scrollTop = this._scrollTop; - else if (this._needsRefresh) - this._refresh(); + this._refresh(); }, hide: function() @@ -394,22 +413,20 @@ WebInspector.TimelinePanel.prototype = { { this._closeRecordDetails(); this._boundariesAreValid &= preserveBoundaries; - if (this._needsRefresh) + + if (!this.visible) return; - this._needsRefresh = true; - if (this.visible && !("_refreshTimeout" in this)) { - if (preserveBoundaries) - this._refresh(); - else + if (preserveBoundaries) + this._refresh(); + else + if (!this._refreshTimeout) this._refreshTimeout = setTimeout(this._refresh.bind(this), 100); - } }, _refresh: function() { - this._needsRefresh = false; - if ("_refreshTimeout" in this) { + if (this._refreshTimeout) { clearTimeout(this._refreshTimeout); delete this._refreshTimeout; } @@ -417,7 +434,8 @@ WebInspector.TimelinePanel.prototype = { this._overviewPane.update(this._rootRecord.children, this._calculator._showShortEvents); this._refreshRecords(!this._boundariesAreValid); this._updateRecordsCounter(); - this._updateEventDividers(); + if(!this._boundariesAreValid) + this._updateEventDividers(); this._boundariesAreValid = true; }, @@ -550,7 +568,7 @@ WebInspector.TimelinePanel.prototype = { _showPopover: function(anchor) { var record = anchor.row._record; - var popover = new WebInspector.Popover(record._generatePopupContent(this._calculator)); + var popover = new WebInspector.Popover(record._generatePopupContent(this._calculator, this.categories)); popover.show(anchor); return popover; }, @@ -582,9 +600,10 @@ WebInspector.TimelineCalculator.prototype = { computeBarGraphPercentages: function(record) { var start = (record.startTime - this.minimumBoundary) / this.boundarySpan * 100; - var end = (record.endTime - this.minimumBoundary) / this.boundarySpan * 100; + var end = (record.startTime + record._selfTime - this.minimumBoundary) / this.boundarySpan * 100; var endWithChildren = (record._lastChildEndTime - this.minimumBoundary) / this.boundarySpan * 100; - return {start: start, end: end, endWithChildren: endWithChildren}; + var cpuWidth = record._cpuTime / this.boundarySpan * 100; + return {start: start, end: end, endWithChildren: endWithChildren, cpuWidth: cpuWidth}; }, computeBarGraphWindowPosition: function(record, clientWidth) @@ -596,9 +615,10 @@ WebInspector.TimelineCalculator.prototype = { var left = percentages.start / 100 * workingArea; var width = (percentages.end - percentages.start) / 100 * workingArea + minWidth; var widthWithChildren = (percentages.endWithChildren - percentages.start) / 100 * workingArea; + var cpuWidth = percentages.cpuWidth / 100 * workingArea + minWidth; if (percentages.endWithChildren > percentages.end) widthWithChildren += borderWidth + minWidth; - return {left: left, width: width, widthWithChildren: widthWithChildren}; + return {left: left, width: width, widthWithChildren: widthWithChildren, cpuWidth: cpuWidth}; }, calculateWindow: function() @@ -654,12 +674,8 @@ WebInspector.TimelineRecordListRow = function() this._dataElement = document.createElement("span"); this._dataElement.className = "data dimmed"; - this._repeatCountElement = document.createElement("span"); - this._repeatCountElement.className = "count"; - this.element.appendChild(separatorElement); this.element.appendChild(this._dataElement); - this.element.appendChild(this._repeatCountElement); } WebInspector.TimelineRecordListRow.prototype = { @@ -672,15 +688,18 @@ WebInspector.TimelineRecordListRow.prototype = { this.element.className = "timeline-tree-item timeline-category-" + record.category.name + (isEven ? " even" : ""); this._typeElement.textContent = record.title; - if (record.details) - this._dataElement.textContent = "(" + record.details + ")"; - else - this._dataElement.textContent = ""; - - if (record.count > 1) - this._repeatCountElement.textContent = "\u2009\u00d7\u2009" + record.count; - else - this._repeatCountElement.textContent = ""; + if (this._dataElement.firstChild) + this._dataElement.removeChildren(); + if (record.details) { + var detailsContainer = document.createElement("span"); + if (typeof record.details === "object") { + detailsContainer.appendChild(document.createTextNode("(")); + detailsContainer.appendChild(record.details); + detailsContainer.appendChild(document.createTextNode(")")); + } else + detailsContainer.textContent = "(" + record.details + ")"; + this._dataElement.appendChild(detailsContainer); + } }, dispose: function() @@ -703,6 +722,11 @@ WebInspector.TimelineRecordGraphRow = function(graphContainer, scheduleRefresh, this._barWithChildrenElement.row = this; this._barAreaElement.appendChild(this._barWithChildrenElement); + this._barCpuElement = document.createElement("div"); + this._barCpuElement.className = "timeline-graph-bar cpu" + this._barCpuElement.row = this; + this._barAreaElement.appendChild(this._barCpuElement); + this._barElement = document.createElement("div"); this._barElement.className = "timeline-graph-bar"; this._barElement.row = this; @@ -732,6 +756,8 @@ WebInspector.TimelineRecordGraphRow.prototype = { this._barWithChildrenElement.style.width = barPosition.widthWithChildren + "px"; this._barElement.style.left = barPosition.left + expandOffset + "px"; this._barElement.style.width = barPosition.width + "px"; + this._barCpuElement.style.left = barPosition.left + expandOffset + "px"; + this._barCpuElement.style.width = barPosition.cpuWidth + "px"; if (record._visibleChildrenCount || record._invisibleChildrenCount) { this._expandElement.style.top = index * this._rowHeight + "px"; @@ -771,14 +797,15 @@ WebInspector.TimelinePanel.FormattedRecord = function(record, parentRecord, reco var style = recordStyles[record.type]; this.parent = parentRecord; - parentRecord.children.push(this); + if (parentRecord) + parentRecord.children.push(this); this.category = style.category; this.title = style.title; this.startTime = record.startTime / 1000; this.data = record.data; - this.count = 1; this.type = record.type; this.endTime = (typeof record.endTime !== "undefined") ? record.endTime / 1000 : this.startTime; + this._selfTime = this.endTime - this.startTime; this._lastChildEndTime = this.endTime; this.originalRecordForTests = record; this.callerScriptName = record.callerScriptName; @@ -826,18 +853,6 @@ WebInspector.TimelinePanel.FormattedRecord.prototype = { return (this._lastChildEndTime - this.startTime) > WebInspector.TimelinePanel.shortRecordThreshold; }, - _createCell: function(content, styleName) - { - var text = document.createElement("label"); - text.appendChild(document.createTextNode(content)); - var cell = document.createElement("td"); - cell.className = "timeline-details"; - if (styleName) - cell.className += " " + styleName; - cell.textContent = content; - return cell; - }, - get children() { if (!this._children) @@ -845,88 +860,90 @@ WebInspector.TimelinePanel.FormattedRecord.prototype = { return this._children; }, - _createRow: function(title, content) + _generateAggregatedInfo: function() { - var row = document.createElement("tr"); - row.appendChild(this._createCell(title, "timeline-details-row-title")); - row.appendChild(this._createCell(content, "timeline-details-row-data")); - return row; + var cell = document.createElement("span"); + cell.className = "timeline-aggregated-info"; + for (var index in this._aggregatedStats) { + var label = document.createElement("div"); + label.className = "timeline-aggregated-category timeline-" + index; + cell.appendChild(label); + var text = document.createElement("span"); + text.textContent = Number.secondsToString(this._aggregatedStats[index] + 0.0001); + cell.appendChild(text); + } + return cell; }, - _createLinkRow: function(title, content) + _generatePopupContent: function(calculator, categories) { - var row = document.createElement("tr"); - row.appendChild(this._createCell(title, "timeline-details-row-title")); - var cell = document.createElement("td"); - cell.appendChild(content); - row.appendChild(cell); - return row; - }, + var contentHelper = new WebInspector.TimelinePanel.PopupContentHelper(this.title); - _generatePopupContent: function(calculator) - { - var recordContentTable = document.createElement("table"); - var titleCell = this._createCell(WebInspector.UIString("%s - Details", this.title), "timeline-details-title"); - titleCell.colSpan = 2; - var titleRow = document.createElement("tr"); - titleRow.appendChild(titleCell); - recordContentTable.appendChild(titleRow); - var text = Number.secondsToString(this.endTime - this.startTime) + " (@" + - calculator.formatValue(this.startTime - calculator.minimumBoundary) + ")"; - recordContentTable.appendChild(this._createRow(WebInspector.UIString("Duration"), text)); + if (this._children && this._children.length) { + contentHelper._appendTextRow("Self Time", Number.secondsToString(this._selfTime + 0.0001)); + contentHelper._appendElementRow("Aggregated Time", this._generateAggregatedInfo()); + } + var text = Number.secondsToString(this._lastChildEndTime - this.startTime) + " (@" + + calculator.formatValue(this.startTime - calculator.minimumBoundary) + ")"; + contentHelper._appendTextRow("Duration", text); const recordTypes = WebInspector.TimelineAgent.RecordType; - if (this.details) { - if (this.type === recordTypes.GCEvent ) - recordContentTable.appendChild(this._createRow(WebInspector.UIString("Collected"), Number.bytesToString(this.data.usedHeapSizeDelta))); - else if (this.type === recordTypes.TimerInstall || - this.type === recordTypes.TimerFire || - this.type === recordTypes.TimerRemove) { - recordContentTable.appendChild(this._createRow(WebInspector.UIString("Timer Id"), this.data.timerId)); + + switch (this.type) { + case recordTypes.GCEvent: + contentHelper._appendTextRow("Collected", Number.bytesToString(this.data.usedHeapSizeDelta)); + break; + case recordTypes.TimerInstall: + case recordTypes.TimerFire: + case recordTypes.TimerRemove: + contentHelper._appendTextRow("Timer Id", this.data.timerId); if (typeof this.timeout === "number") { - recordContentTable.appendChild(this._createRow(WebInspector.UIString("Timeout"), this.timeout)); - recordContentTable.appendChild(this._createRow(WebInspector.UIString("Repeats"), !this.singleShot)); + contentHelper._appendTextRow("Timeout", this.timeout); + contentHelper._appendTextRow("Repeats", !this.singleShot); } - if (typeof this.callSiteScriptLine === "number") { - var link = WebInspector.linkifyResourceAsNode(this.callSiteScriptName, "scripts", this.callSiteScriptLine, "timeline-details"); - recordContentTable.appendChild(this._createLinkRow(WebInspector.UIString("Call Site"), link)); - } - } else if (this.type === recordTypes.FunctionCall) { - var link = WebInspector.linkifyResourceAsNode(this.data.scriptName, "scripts", this.data.scriptLine, "timeline-details"); - recordContentTable.appendChild(this._createLinkRow(WebInspector.UIString("Location"), link)); - } else if (this.type === recordTypes.ResourceSendRequest || - this.type === recordTypes.ResourceReceiveResponse || - this.type === recordTypes.ResourceReceiveData || - this.type === recordTypes.ResourceFinish) { - var link = WebInspector.linkifyResourceAsNode(this.data.url, "resources", null, "timeline-details"); - recordContentTable.appendChild(this._createLinkRow(WebInspector.UIString("Resource"), link)); + if (typeof this.callSiteScriptLine === "number") + contentHelper._appendLinkRow("Call Site", this.callSiteScriptName, this.callSiteScriptLine); + break; + case recordTypes.FunctionCall: + contentHelper._appendLinkRow("Location", this.data.scriptName, this.data.scriptLine); + break; + case recordTypes.ResourceSendRequest: + case recordTypes.ResourceReceiveResponse: + case recordTypes.ResourceReceiveData: + case recordTypes.ResourceFinish: + contentHelper._appendLinkRow("Resource", this.data.url); if (this.data.requestMethod) - recordContentTable.appendChild(this._createRow(WebInspector.UIString("Request Method"), this.data.requestMethod)); + contentHelper._appendTextRow("Request Method", this.data.requestMethod); if (typeof this.data.statusCode === "number") - recordContentTable.appendChild(this._createRow(WebInspector.UIString("Status Code"), this.data.statusCode)); + contentHelper._appendTextRow("Status Code", this.data.statusCode); if (this.data.mimeType) - recordContentTable.appendChild(this._createRow(WebInspector.UIString("Mime Type"), this.data.mimeType)); + contentHelper._appendTextRow("Mime Type", this.data.mimeType); if (typeof this.data.expectedContentLength === "number" && this.data.expectedContentLength !== -1) - recordContentTable.appendChild(this._createRow(WebInspector.UIString("Expected Content Length"), this.data.expectedContentLength)); - } else if (this.type === recordTypes.EvaluateScript) { - var link = WebInspector.linkifyResourceAsNode(this.data.url, "scripts", null, "timeline-details"); - recordContentTable.appendChild(this._createLinkRow(WebInspector.UIString("Script"), link)); - } else if (this.type === recordTypes.Paint) { - recordContentTable.appendChild(this._createRow(WebInspector.UIString("Location"), this.data.x + "\u2009\u00d7\u2009" + this.data.y)); - recordContentTable.appendChild(this._createRow(WebInspector.UIString("Dimensions"), this.data.width + "\u2009\u00d7\u2009" + this.data.height)); - } else - recordContentTable.appendChild(this._createRow(WebInspector.UIString("Details"), this.details)); + contentHelper._appendTextRow("Expected Content Length", this.data.expectedContentLength); + break; + case recordTypes.EvaluateScript: + if (this.data && this.data.url) + contentHelper._appendLinkRow("Script", this.data.url, this.data.lineNumber); + break; + case recordTypes.Paint: + contentHelper._appendTextRow("Location", this.data.x + "\u2009\u00d7\u2009" + this.data.y); + contentHelper._appendTextRow("Dimensions", this.data.width + "\u2009\u00d7\u2009" + this.data.height); + default: + if (this.details) + contentHelper._appendTextRow("Details", this.details); + break; } - if (this.type !== recordTypes.GCEvent && this.callerScriptName) { - var link = WebInspector.linkifyResourceAsNode(this.callerScriptName, "scripts", this.callerScriptLine); - recordContentTable.appendChild(this._createLinkRow(WebInspector.UIString("Caller"), link)); - } - if (this.usedHeapSize) { - recordContentTable.appendChild(this._createRow(WebInspector.UIString("Used Heap Size"), Number.bytesToString(this.usedHeapSize))); - recordContentTable.appendChild(this._createRow(WebInspector.UIString("Total Heap Size"), Number.bytesToString(this.totalHeapSize))); - } - return recordContentTable; + if (this.data.scriptName && this.type !== recordTypes.FunctionCall) + contentHelper._appendLinkRow("Function Call", this.data.scriptName, this.data.scriptLine); + + if (this.callerScriptName && this.type !== recordTypes.GCEvent) + contentHelper._appendLinkRow("Caller", this.callerScriptName, this.callerScriptLine); + + if (this.usedHeapSize) + contentHelper._appendTextRow("Used Heap Size", WebInspector.UIString("%s of %s", Number.bytesToString(this.usedHeapSize), Number.bytesToString(this.totalHeapSize))); + + return contentHelper._contentTable; }, _getRecordDetails: function(record, sendRequestRecords) @@ -934,19 +951,24 @@ WebInspector.TimelinePanel.FormattedRecord.prototype = { switch (record.type) { case WebInspector.TimelineAgent.RecordType.GCEvent: return WebInspector.UIString("%s collected", Number.bytesToString(record.data.usedHeapSizeDelta)); + case WebInspector.TimelineAgent.RecordType.TimerFire: + return record.data.scriptName ? WebInspector.linkifyResourceAsNode(record.data.scriptName, "scripts", record.data.scriptLine) : record.data.timerId; case WebInspector.TimelineAgent.RecordType.FunctionCall: - return WebInspector.displayNameForURL(record.data.scriptName) + ":" + record.data.scriptLine; + return record.data.scriptName ? WebInspector.linkifyResourceAsNode(record.data.scriptName, "scripts", record.data.scriptLine) : null; case WebInspector.TimelineAgent.RecordType.EventDispatch: - return record.data ? record.data.type : ""; + return record.data ? record.data.type : null; case WebInspector.TimelineAgent.RecordType.Paint: return record.data.width + "\u2009\u00d7\u2009" + record.data.height; case WebInspector.TimelineAgent.RecordType.TimerInstall: case WebInspector.TimelineAgent.RecordType.TimerRemove: - case WebInspector.TimelineAgent.RecordType.TimerFire: - return record.data.timerId; + return this.callerScriptName ? WebInspector.linkifyResourceAsNode(this.callerScriptName, "scripts", this.callerScriptLine) : record.data.timerId; + case WebInspector.TimelineAgent.RecordType.ParseHTML: + case WebInspector.TimelineAgent.RecordType.RecalculateStyles: + return this.callerScriptName ? WebInspector.linkifyResourceAsNode(this.callerScriptName, "scripts", this.callerScriptLine) : null; + case WebInspector.TimelineAgent.RecordType.EvaluateScript: + return record.data.url ? WebInspector.linkifyResourceAsNode(record.data.url, "scripts", record.data.lineNumber) : null; case WebInspector.TimelineAgent.RecordType.XHRReadyStateChange: case WebInspector.TimelineAgent.RecordType.XHRLoad: - case WebInspector.TimelineAgent.RecordType.EvaluateScript: case WebInspector.TimelineAgent.RecordType.ResourceSendRequest: case WebInspector.TimelineAgent.RecordType.ResourceReceiveData: case WebInspector.TimelineAgent.RecordType.ResourceReceiveResponse: @@ -955,8 +977,74 @@ WebInspector.TimelinePanel.FormattedRecord.prototype = { case WebInspector.TimelineAgent.RecordType.MarkTimeline: return record.data.message; default: - return ""; + return null; + } + }, + + _calculateAggregatedStats: function(categories) + { + this._aggregatedStats = {}; + for (var category in categories) + this._aggregatedStats[category] = 0; + this._cpuTime = this._selfTime; + + if (this._children) { + for (var index = this._children.length; index; --index) { + var child = this._children[index - 1]; + this._aggregatedStats[child.category.name] += child._selfTime; + for (var category in categories) + this._aggregatedStats[category] += child._aggregatedStats[category]; + } + for (var category in this._aggregatedStats) + this._cpuTime += this._aggregatedStats[category]; } } } +WebInspector.TimelinePanel.PopupContentHelper = function(title) +{ + this._contentTable = document.createElement("table");; + var titleCell = this._createCell(WebInspector.UIString("%s - Details", title), "timeline-details-title"); + titleCell.colSpan = 2; + var titleRow = document.createElement("tr"); + titleRow.appendChild(titleCell); + this._contentTable.appendChild(titleRow); +} + +WebInspector.TimelinePanel.PopupContentHelper.prototype = { + _createCell: function(content, styleName) + { + var text = document.createElement("label"); + text.appendChild(document.createTextNode(content)); + var cell = document.createElement("td"); + cell.className = "timeline-details"; + if (styleName) + cell.className += " " + styleName; + cell.textContent = content; + return cell; + }, + + _appendTextRow: function(title, content) + { + var row = document.createElement("tr"); + row.appendChild(this._createCell(WebInspector.UIString(title), "timeline-details-row-title")); + row.appendChild(this._createCell(content, "timeline-details-row-data")); + this._contentTable.appendChild(row); + }, + + _appendElementRow: function(title, content) + { + var row = document.createElement("tr"); + row.appendChild(this._createCell(WebInspector.UIString(title), "timeline-details-row-title")); + var cell = document.createElement("td"); + cell.appendChild(content); + row.appendChild(cell); + this._contentTable.appendChild(row); + }, + + _appendLinkRow: function(title, scriptName, scriptLine) + { + var link = WebInspector.linkifyResourceAsNode(scriptName, "scripts", scriptLine, "timeline-details"); + this._appendElementRow(title, link); + } +} diff --git a/WebCore/inspector/front-end/inspector.css b/WebCore/inspector/front-end/inspector.css index 581c75a..199a3f3 100644 --- a/WebCore/inspector/front-end/inspector.css +++ b/WebCore/inspector/front-end/inspector.css @@ -3387,7 +3387,15 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches { bottom: 0px; left: 200px; right: 0px; - background-color: rgb(224, 224, 224); + background-color: rgb(255, 255, 255); +} + +.timeline-window-selector { + position: absolute; + top: 0; + bottom: 0; + background-color: rgba(125, 173, 217, 0.5); + z-index: 250; } #timeline-overview-window { @@ -3396,14 +3404,33 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches { left: 0; right: 0; top: 0; + bottom: 60px; + z-index: 150; +} + +.timeline-overview-dividers-background { + left: 0%; + right: 0%; + top: 0px; + bottom: 60px; + background-color: black; + position: absolute; +} + +.timeline-overview-window-rulers { + top: 0; bottom: 0; + position: absolute; + opacity: 0.2; + border-right: 1px solid black; + border-left: 1px solid black; z-index: 150; } .timeline-window-resizer { position: absolute; - top: 35px; - bottom: 15px; + top: 0px; + bottom: 60px; width: 5px; margin-left: -3px; margin-right: -2px; @@ -3605,7 +3632,11 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches { } .timeline-graph-bar.with-children { - opacity: 0.3; + opacity: 0.2; +} + +.timeline-graph-bar.cpu { + opacity: 0.6; } .timeline-graph-side.even { @@ -3624,6 +3655,32 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches { -webkit-border-image: url(Images/timelineBarPurple.png) 4 4 5 4; } +.timeline-aggregated-category { + display: inline-block; + height: 11px; + margin-right: 2px; + margin-left: 6px; + position: relative; + top: 2px; + width: 10px; +} + +.timeline-loading { + -webkit-border-image: url(Images/timelineBarBlue.png) 4 4 5 4; +} + +.timeline-scripting { + -webkit-border-image: url(Images/timelineBarOrange.png) 4 4 5 4; +} + +.timeline-rendering { + -webkit-border-image: url(Images/timelineBarPurple.png) 4 4 5 4; +} + +.popover .timeline-aggregated-category.timeline-loading { + margin-left: 0px; +} + .timeline-category-loading .timeline-tree-icon { background-position-y: 0px; } @@ -3651,7 +3708,11 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches { } .timeline-details-title { + border-bottom: 1px solid #B8B8B8; + font-size: 11px; font-weight: bold; + padding-bottom: 5px; + padding-top: 0px; white-space: nowrap; } @@ -3969,3 +4030,8 @@ a.worker-item:hover { text-align: center; padding: 32px; } + +.node-link { + text-decoration: underline; + cursor: pointer; +} diff --git a/WebCore/inspector/front-end/inspector.js b/WebCore/inspector/front-end/inspector.js index c75dd9c..edd54bd 100644 --- a/WebCore/inspector/front-end/inspector.js +++ b/WebCore/inspector/front-end/inspector.js @@ -190,8 +190,10 @@ var WebInspector = { } for (var panelName in WebInspector.panels) { - if (WebInspector.panels[panelName] == x) + if (WebInspector.panels[panelName] === x) { InspectorBackend.storeLastActivePanel(panelName); + this._panelHistory.setPanel(panelName); + } } }, @@ -244,6 +246,8 @@ var WebInspector = { body.addStyleClass("detached"); dockToggleButton.title = WebInspector.UIString("Dock to main window."); } + if (this.drawer) + this.drawer.resize(); }, get errors() @@ -458,6 +462,7 @@ WebInspector.loaded = function() this.panels = {}; this._createPanels(); + this._panelHistory = new WebInspector.PanelHistory(); var toolbarElement = document.getElementById("toolbar"); var previousToolbarItem = toolbarElement.children[0]; @@ -680,6 +685,7 @@ WebInspector.documentKeyDown = function(event) if (WebInspector.isEditingAnyField()) return; + var isInTextPrompt = event.target.enclosingNodeOrSelfWithClass("text-prompt"); if (this.currentFocusElement && this.currentFocusElement.handleKeyEvent) { this.currentFocusElement.handleKeyEvent(event); if (event.handled) { @@ -697,8 +703,23 @@ WebInspector.documentKeyDown = function(event) } var isMac = WebInspector.isMac(); - switch (event.keyIdentifier) { + case "Left": + var isBackKey = !isInTextPrompt && (isMac ? event.metaKey : event.ctrlKey); + if (isBackKey && this._panelHistory.canGoBack()) { + this._panelHistory.goBack(); + event.preventDefault(); + } + break; + + case "Right": + var isForwardKey = !isInTextPrompt && (isMac ? event.metaKey : event.ctrlKey); + if (isForwardKey && this._panelHistory.canGoForward()) { + this._panelHistory.goForward(); + event.preventDefault(); + } + break; + case "U+001B": // Escape key event.preventDefault(); if (this.drawer.fullPanel) @@ -1457,6 +1478,21 @@ WebInspector.addProfileHeader = function(profile) WebInspector.setRecordingProfile = function(isProfiling) { this.panels.profiles.getProfileType(WebInspector.CPUProfileType.TypeId).setRecordingProfile(isProfiling); + if (this._previousIsProfiling !== isProfiling) { + if (!this._temporaryRecordingProfile) { + this._temporaryRecordingProfile = { + typeId: WebInspector.CPUProfileType.TypeId, + title: WebInspector.UIString('Recording...'), + uid: -1, + isTemporary: true + }; + } + this._previousIsProfiling = isProfiling; + if (isProfiling) + this.panels.profiles.addProfileHeader(this._temporaryRecordingProfile); + else + this.panels.profiles.removeProfileHeader(this._temporaryRecordingProfile); + } this.panels.profiles.updateProfileTypeButtons(); } @@ -1950,3 +1986,46 @@ WebInspector.MIMETypes = { "text/jscript": {4: true}, "text/livescript": {4: true}, } + +WebInspector.PanelHistory = function() +{ + this._history = []; + this._historyIterator = -1; +} + +WebInspector.PanelHistory.prototype = { + canGoBack: function() + { + return this._historyIterator > 0; + }, + + goBack: function() + { + this._inHistory = true; + WebInspector.currentPanel = WebInspector.panels[this._history[--this._historyIterator]]; + delete this._inHistory; + }, + + canGoForward: function() + { + return this._historyIterator < this._history.length - 1; + }, + + goForward: function() + { + this._inHistory = true; + WebInspector.currentPanel = WebInspector.panels[this._history[++this._historyIterator]]; + delete this._inHistory; + }, + + setPanel: function(panelName) + { + if (this._inHistory) + return; + + this._history.splice(this._historyIterator + 1, this._history.length - this._historyIterator - 1); + if (!this._history.length || this._history[this._history.length - 1] !== panelName) + this._history.push(panelName); + this._historyIterator = this._history.length - 1; + } +} diff --git a/WebCore/inspector/front-end/textViewer.css b/WebCore/inspector/front-end/textViewer.css index b69545f..a24a75c 100644 --- a/WebCore/inspector/front-end/textViewer.css +++ b/WebCore/inspector/front-end/textViewer.css @@ -63,6 +63,7 @@ background-color: rgb(240, 240, 240); border-right: 1px solid rgb(187, 187, 187); text-align: right; + vertical-align: top; word-break: normal; -webkit-user-select: none; padding-right: 4px; diff --git a/WebCore/loader/DocumentLoader.cpp b/WebCore/loader/DocumentLoader.cpp index e835f80..21c2e27 100644 --- a/WebCore/loader/DocumentLoader.cpp +++ b/WebCore/loader/DocumentLoader.cpp @@ -617,6 +617,17 @@ void DocumentLoader::setTitle(const String& title) } } +void DocumentLoader::setIconURL(const String& iconURL) +{ + if (iconURL.isEmpty()) + return; + + if (m_pageIconURL != iconURL) { + m_pageIconURL = iconURL; + frameLoader()->didChangeIcons(this); + } +} + KURL DocumentLoader::urlForHistory() const { // Return the URL to be used for history and B/F list. diff --git a/WebCore/loader/DocumentLoader.h b/WebCore/loader/DocumentLoader.h index 440cfc4..1beed10 100644 --- a/WebCore/loader/DocumentLoader.h +++ b/WebCore/loader/DocumentLoader.h @@ -111,6 +111,7 @@ namespace WebCore { bool isLoadingInAPISense() const; void setPrimaryLoadComplete(bool); void setTitle(const String&); + void setIconURL(const String&); const String& overrideEncoding() const { return m_overrideEncoding; } #if PLATFORM(MAC) @@ -154,6 +155,7 @@ namespace WebCore { void stopRecordingResponses(); const String& title() const { return m_pageTitle; } + const String& iconURL() const { return m_pageIconURL; } KURL urlForHistory() const; bool urlForHistoryReflectsFailure() const; @@ -261,6 +263,7 @@ namespace WebCore { bool m_isClientRedirect; String m_pageTitle; + String m_pageIconURL; String m_overrideEncoding; diff --git a/WebCore/loader/DocumentThreadableLoader.cpp b/WebCore/loader/DocumentThreadableLoader.cpp index 3bebbe6..ee926b1 100644 --- a/WebCore/loader/DocumentThreadableLoader.cpp +++ b/WebCore/loader/DocumentThreadableLoader.cpp @@ -81,16 +81,19 @@ DocumentThreadableLoader::DocumentThreadableLoader(Document* document, Threadabl ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); - if (!m_options.forcePreflight && isSimpleCrossOriginAccessRequest(request.httpMethod(), request.httpHeaderFields())) - makeSimpleCrossOriginAccessRequest(request); + OwnPtr<ResourceRequest> crossOriginRequest(new ResourceRequest(request)); + crossOriginRequest->removeCredentials(); + crossOriginRequest->setAllowCookies(m_options.allowCredentials); + + if (!m_options.forcePreflight && isSimpleCrossOriginAccessRequest(crossOriginRequest->httpMethod(), crossOriginRequest->httpHeaderFields())) + makeSimpleCrossOriginAccessRequest(*crossOriginRequest); else { - m_actualRequest.set(new ResourceRequest(request)); - m_actualRequest->setAllowCookies(m_options.allowCredentials); + m_actualRequest.set(crossOriginRequest.release()); - if (CrossOriginPreflightResultCache::shared().canSkipPreflight(document->securityOrigin()->toString(), request.url(), m_options.allowCredentials, request.httpMethod(), request.httpHeaderFields())) + if (CrossOriginPreflightResultCache::shared().canSkipPreflight(document->securityOrigin()->toString(), m_actualRequest->url(), m_options.allowCredentials, m_actualRequest->httpMethod(), m_actualRequest->httpHeaderFields())) preflightSuccess(); else - makeCrossOriginAccessRequestWithPreflight(request); + makeCrossOriginAccessRequestWithPreflight(*m_actualRequest); } } @@ -106,8 +109,6 @@ void DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest(const Resource // Make a copy of the passed request so that we can modify some details. ResourceRequest crossOriginRequest(request); - crossOriginRequest.removeCredentials(); - crossOriginRequest.setAllowCookies(m_options.allowCredentials); crossOriginRequest.setHTTPOrigin(m_document->securityOrigin()->toString()); loadRequest(crossOriginRequest, DoSecurityCheck); @@ -297,6 +298,11 @@ void DocumentThreadableLoader::preflightFailure() void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, SecurityCheckPolicy securityCheck) { + // Any credential should have been removed from the cross-site requests. + const KURL& requestURL = request.url(); + ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); + ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); + if (m_async) { // Don't sniff content or send load callbacks for the preflight request. bool sendLoadCallbacks = m_options.sendLoadCallbacks && !m_actualRequest; @@ -320,15 +326,15 @@ void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Secur // No exception for file:/// resources, see <rdar://problem/4962298>. // Also, if we have an HTTP response, then it wasn't a network error in fact. - if (!error.isNull() && !request.url().isLocalFile() && response.httpStatusCode() <= 0) { + if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode() <= 0) { m_client->didFail(error); return; } // FIXME: FrameLoader::loadSynchronously() does not tell us whether a redirect happened or not, so we guess by comparing the // request and response URLs. This isn't a perfect test though, since a server can serve a redirect to the same URL that was - // requested. - if (request.url() != response.url() && !isAllowedRedirect(response.url())) { + // requested. Also comparing the request and response URLs as strings will fail if the requestURL still has its credentials. + if (requestURL != response.url() && !isAllowedRedirect(response.url())) { m_client->didFailRedirectCheck(); return; } diff --git a/WebCore/loader/EmptyClients.h b/WebCore/loader/EmptyClients.h index 3147a3b..982324a 100644 --- a/WebCore/loader/EmptyClients.h +++ b/WebCore/loader/EmptyClients.h @@ -198,6 +198,9 @@ public: virtual void dispatchWillSendRequest(DocumentLoader*, unsigned long, ResourceRequest&, const ResourceResponse&) { } virtual void dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long, const AuthenticationChallenge&) { } virtual void dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long, const AuthenticationChallenge&) { } +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + virtual bool canAuthenticateAgainstProtectionSpace(DocumentLoader*, unsigned long, const ProtectionSpace&) { return false; } +#endif virtual void dispatchDidReceiveResponse(DocumentLoader*, unsigned long, const ResourceResponse&) { } virtual void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long, int) { } virtual void dispatchDidFinishLoading(DocumentLoader*, unsigned long) { } @@ -216,6 +219,7 @@ public: virtual void dispatchDidReceiveIcon() { } virtual void dispatchDidStartProvisionalLoad() { } virtual void dispatchDidReceiveTitle(const String&) { } + virtual void dispatchDidChangeIcons() { } virtual void dispatchDidCommitLoad() { } virtual void dispatchDidFailProvisionalLoad(const ResourceError&) { } virtual void dispatchDidFailLoad(const ResourceError&) { } @@ -234,6 +238,7 @@ public: virtual void dispatchUnableToImplementPolicy(const ResourceError&) { } + virtual void dispatchWillSendSubmitEvent(HTMLFormElement*) { } virtual void dispatchWillSubmitForm(FramePolicyFunction, PassRefPtr<FormState>) { } virtual void dispatchDidLoadMainResource(DocumentLoader*) { } diff --git a/WebCore/loader/FrameLoader.cpp b/WebCore/loader/FrameLoader.cpp index 63b00e8..125ee9b 100644 --- a/WebCore/loader/FrameLoader.cpp +++ b/WebCore/loader/FrameLoader.cpp @@ -230,6 +230,10 @@ FrameLoader::~FrameLoader() void FrameLoader::init() { + // Propagate sandbox attributes to this Frameloader and its descendants. + // This needs to be done early, so that an initial document gets correct sandbox flags in its SecurityOrigin. + updateSandboxFlags(); + // this somewhat odd set of steps is needed to give the frame an initial empty document m_isDisplayingInitialEmptyDocument = false; m_creatingInitialEmptyDocument = true; @@ -243,9 +247,6 @@ void FrameLoader::init() m_frame->document()->cancelParsing(); m_creatingInitialEmptyDocument = false; m_didCallImplicitClose = true; - - // Propagate sandbox attributes to this Frameloader and its descendants. - updateSandboxFlags(); } void FrameLoader::setDefersLoading(bool defers) @@ -521,7 +522,7 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F m_submittedFormURL = u; } - formData->generateFiles(m_frame->page()->chrome()->client()); + formData->generateFiles(m_frame->document()); if (!m_outgoingReferrer.isEmpty()) frameRequest.resourceRequest().setHTTPReferrer(m_outgoingReferrer); @@ -1210,7 +1211,7 @@ ObjectContentType FrameLoader::defaultObjectContentType(const KURL& url, const S if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType)) return WebCore::ObjectContentImage; -#if !PLATFORM(MAC) && !PLATFORM(CHROMIUM) // Mac has no PluginDatabase, nor does Chromium +#if !PLATFORM(MAC) && !PLATFORM(CHROMIUM) && !PLATFORM(EFL) // Mac has no PluginDatabase, nor does Chromium or EFL if (PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType)) return WebCore::ObjectContentNetscapePlugin; #endif @@ -3745,7 +3746,7 @@ void FrameLoader::navigateToDifferentDocument(HistoryItem* item, FrameLoadType l // 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()); + formData->generateFiles(m_frame->document()); request.setHTTPMethod("POST"); request.setHTTPBody(formData); @@ -3878,11 +3879,23 @@ bool FrameLoader::shouldUseCredentialStorage(ResourceLoader* loader) return m_client->shouldUseCredentialStorage(loader->documentLoader(), loader->identifier()); } +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) +bool FrameLoader::canAuthenticateAgainstProtectionSpace(ResourceLoader* loader, const ProtectionSpace& protectionSpace) +{ + return m_client->canAuthenticateAgainstProtectionSpace(loader->documentLoader(), loader->identifier(), protectionSpace); +} +#endif + void FrameLoader::setTitle(const String& title) { documentLoader()->setTitle(title); } +void FrameLoader::setIconURL(const String& iconURL) +{ + documentLoader()->setIconURL(iconURL); +} + KURL FrameLoader::originalRequestURL() const { return activeDocumentLoader()->originalRequest().url(); @@ -4000,6 +4013,12 @@ void FrameLoader::didChangeTitle(DocumentLoader* loader) } } +void FrameLoader::didChangeIcons(DocumentLoader* loader) +{ + if (loader == m_documentLoader) + m_client->dispatchDidChangeIcons(); +} + void FrameLoader::dispatchDidCommitLoad() { if (m_creatingInitialEmptyDocument) diff --git a/WebCore/loader/FrameLoader.h b/WebCore/loader/FrameLoader.h index adfebd4..34d1ad1 100644 --- a/WebCore/loader/FrameLoader.h +++ b/WebCore/loader/FrameLoader.h @@ -71,6 +71,7 @@ class NavigationAction; #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) class Node; #endif +class ProtectionSpace; class RenderEmbeddedObject; class ResourceError; class ResourceLoader; @@ -155,6 +156,9 @@ public: static double timeOfLastCompletedLoad(); bool shouldUseCredentialStorage(ResourceLoader*); +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + bool canAuthenticateAgainstProtectionSpace(ResourceLoader* loader, const ProtectionSpace& protectionSpace); +#endif const ResourceRequest& originalRequest() const; const ResourceRequest& initialRequest() const; void receivedMainResourceError(const ResourceError&, bool isComplete); @@ -193,6 +197,7 @@ public: bool subframeIsLoading() const; void willChangeTitle(DocumentLoader*); void didChangeTitle(DocumentLoader*); + void didChangeIcons(DocumentLoader*); FrameLoadType loadType() const; CachePolicy subresourceCachePolicy() const; @@ -303,6 +308,7 @@ public: void cancelAndClear(); void setTitle(const String&); + void setIconURL(const String&); void commitProvisionalLoad(PassRefPtr<CachedPage>); bool isLoadingFromCachedPage() const { return m_loadingFromCachedPage; } diff --git a/WebCore/loader/FrameLoaderClient.h b/WebCore/loader/FrameLoaderClient.h index b2931c8..c74933b 100644 --- a/WebCore/loader/FrameLoaderClient.h +++ b/WebCore/loader/FrameLoaderClient.h @@ -54,6 +54,7 @@ namespace WebCore { class FrameLoader; class HistoryItem; class HTMLAppletElement; + class HTMLFormElement; class HTMLFrameOwnerElement; #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) class HTMLMediaElement; @@ -62,6 +63,7 @@ namespace WebCore { class IntSize; class KURL; class NavigationAction; + class ProtectionSpace; class PluginView; class PolicyChecker; class ResourceError; @@ -107,6 +109,9 @@ namespace WebCore { virtual bool shouldUseCredentialStorage(DocumentLoader*, unsigned long identifier) = 0; virtual void dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) = 0; virtual void dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) = 0; +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + virtual bool canAuthenticateAgainstProtectionSpace(DocumentLoader*, unsigned long identifier, const ProtectionSpace&) = 0; +#endif 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; @@ -126,6 +131,7 @@ namespace WebCore { virtual void dispatchDidReceiveIcon() = 0; virtual void dispatchDidStartProvisionalLoad() = 0; virtual void dispatchDidReceiveTitle(const String& title) = 0; + virtual void dispatchDidChangeIcons() = 0; virtual void dispatchDidCommitLoad() = 0; virtual void dispatchDidFailProvisionalLoad(const ResourceError&) = 0; virtual void dispatchDidFailLoad(const ResourceError&) = 0; @@ -144,6 +150,7 @@ namespace WebCore { virtual void dispatchUnableToImplementPolicy(const ResourceError&) = 0; + virtual void dispatchWillSendSubmitEvent(HTMLFormElement*) = 0; virtual void dispatchWillSubmitForm(FramePolicyFunction, PassRefPtr<FormState>) = 0; virtual void dispatchDidLoadMainResource(DocumentLoader*) = 0; @@ -251,7 +258,7 @@ namespace WebCore { #endif #if PLATFORM(MAC) -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) virtual jobject javaApplet(NSView*) { return 0; } #endif virtual NSCachedURLResponse* willCacheResponse(DocumentLoader*, unsigned long identifier, NSCachedURLResponse*) const = 0; diff --git a/WebCore/loader/ResourceLoader.cpp b/WebCore/loader/ResourceLoader.cpp index 183d2ce..7a95383 100644 --- a/WebCore/loader/ResourceLoader.cpp +++ b/WebCore/loader/ResourceLoader.cpp @@ -495,6 +495,14 @@ void ResourceLoader::didCancelAuthenticationChallenge(const AuthenticationChalle frameLoader()->notifier()->didCancelAuthenticationChallenge(this, challenge); } +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) +bool ResourceLoader::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace) +{ + RefPtr<ResourceLoader> protector(this); + return frameLoader()->canAuthenticateAgainstProtectionSpace(this, protectionSpace); +} +#endif + void ResourceLoader::receivedCancellation(const AuthenticationChallenge&) { cancel(); diff --git a/WebCore/loader/ResourceLoader.h b/WebCore/loader/ResourceLoader.h index 3178eb4..ef09471 100644 --- a/WebCore/loader/ResourceLoader.h +++ b/WebCore/loader/ResourceLoader.h @@ -44,6 +44,7 @@ namespace WebCore { class DocumentLoader; class Frame; class FrameLoader; + class ProtectionSpace; class ResourceHandle; class SharedBuffer; @@ -90,6 +91,9 @@ namespace WebCore { virtual bool shouldUseCredentialStorage(); virtual void didReceiveAuthenticationChallenge(const AuthenticationChallenge&); void didCancelAuthenticationChallenge(const AuthenticationChallenge&); +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + virtual bool canAuthenticateAgainstProtectionSpace(const ProtectionSpace&); +#endif virtual void receivedCancellation(const AuthenticationChallenge&); // ResourceHandleClient @@ -105,6 +109,9 @@ namespace WebCore { virtual bool shouldUseCredentialStorage(ResourceHandle*) { return shouldUseCredentialStorage(); } virtual void didReceiveAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge& challenge) { didReceiveAuthenticationChallenge(challenge); } virtual void didCancelAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge& challenge) { didCancelAuthenticationChallenge(challenge); } +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + virtual bool canAuthenticateAgainstProtectionSpace(ResourceHandle*, const ProtectionSpace& protectionSpace) { return canAuthenticateAgainstProtectionSpace(protectionSpace); } +#endif virtual void receivedCancellation(ResourceHandle*, const AuthenticationChallenge& challenge) { receivedCancellation(challenge); } virtual void willCacheResponse(ResourceHandle*, CacheStoragePolicy&); #if PLATFORM(MAC) diff --git a/WebCore/loader/appcache/DOMApplicationCache.idl b/WebCore/loader/appcache/DOMApplicationCache.idl index 9794baf..8525fe6 100644 --- a/WebCore/loader/appcache/DOMApplicationCache.idl +++ b/WebCore/loader/appcache/DOMApplicationCache.idl @@ -55,12 +55,12 @@ module offline { attribute EventListener onobsolete; // EventTarget interface - [JSCCustom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [JSCCustom] void removeEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); + void addEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); + void removeEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); boolean dispatchEvent(in Event evt) raises(EventException); }; diff --git a/WebCore/loader/appcache/ManifestParser.cpp b/WebCore/loader/appcache/ManifestParser.cpp index b001bff..f58a55d 100644 --- a/WebCore/loader/appcache/ManifestParser.cpp +++ b/WebCore/loader/appcache/ManifestParser.cpp @@ -127,6 +127,9 @@ bool parseManifest(const KURL& manifestURL, const char* data, int length, Manife if (!equalIgnoringCase(url.protocol(), manifestURL.protocol())) continue; + if (mode == Explicit && manifestURL.protocolIs("https") && !protocolHostAndPortAreEqual(manifestURL, url)) + continue; + if (mode == Explicit) manifest.explicitURLs.add(url.string()); else diff --git a/WebCore/manual-tests/NPN_Invoke/main.c b/WebCore/manual-tests/NPN_Invoke/main.c index f149f54..4a6d706 100644 --- a/WebCore/manual-tests/NPN_Invoke/main.c +++ b/WebCore/manual-tests/NPN_Invoke/main.c @@ -37,16 +37,16 @@ NPNetscapeFuncs *browser; -NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved); +NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved); NPError NPP_Destroy(NPP instance, NPSavedData** save); NPError NPP_SetWindow(NPP instance, NPWindow* window); -NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype); +NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype); NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason); -int32 NPP_WriteReady(NPP instance, NPStream* stream); -int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer); +int32_t NPP_WriteReady(NPP instance, NPStream* stream); +int32_t NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer); void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname); void NPP_Print(NPP instance, NPPrint* platformPrint); -int16 NPP_HandleEvent(NPP instance, void* event); +int16_t NPP_HandleEvent(NPP instance, void* event); void NPP_URLNotify(NPP instance, const char* URL, NPReason reason, void* notifyData); NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value); NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value); @@ -153,7 +153,7 @@ int main(NPNetscapeFuncs *browserFuncs, NPPluginFuncs *pluginFuncs, NPP_Shutdown return NPERR_NO_ERROR; } -NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved) +NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved) { // Call window.alert("Success!") NPError error; @@ -180,7 +180,7 @@ NPError NPP_SetWindow(NPP instance, NPWindow* window) return NPERR_NO_ERROR; } -NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype) +NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype) { *stype = NP_ASFILEONLY; return NPERR_NO_ERROR; @@ -191,12 +191,12 @@ NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) return NPERR_NO_ERROR; } -int32 NPP_WriteReady(NPP instance, NPStream* stream) +int32_t NPP_WriteReady(NPP instance, NPStream* stream) { return 0; } -int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer) +int32_t NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer) { return 0; } @@ -210,7 +210,7 @@ void NPP_Print(NPP instance, NPPrint* platformPrint) } -int16 NPP_HandleEvent(NPP instance, void* event) +int16_t NPP_HandleEvent(NPP instance, void* event) { return 1; } @@ -234,11 +234,11 @@ NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) FunctionPointer functionPointerForTVector(TransitionVector tvp) { - const uint32 temp[6] = {0x3D800000, 0x618C0000, 0x800C0000, 0x804C0004, 0x7C0903A6, 0x4E800420}; - uint32 *newGlue = NULL; + const uint32_t temp[6] = {0x3D800000, 0x618C0000, 0x800C0000, 0x804C0004, 0x7C0903A6, 0x4E800420}; + uint32_t *newGlue = NULL; if (tvp != NULL) { - newGlue = (uint32 *)malloc(sizeof(temp)); + newGlue = (uint32_t *)malloc(sizeof(temp)); if (newGlue != NULL) { unsigned i; for (i = 0; i < 6; i++) newGlue[i] = temp[i]; diff --git a/WebCore/manual-tests/chromium/suggestions-popup-font-change.html b/WebCore/manual-tests/chromium/suggestions-popup-font-change.html new file mode 100644 index 0000000..b85977a --- /dev/null +++ b/WebCore/manual-tests/chromium/suggestions-popup-font-change.html @@ -0,0 +1,21 @@ +<html> +<head> +</head> +<body> + <p>Verify that the font size in the suggestion popup matches the corresponding + input field, test passes if step 2 matches expected behavior.</p> + <ul> + <li>1. Type "abcd" in the text form and press enter.</li> + <li>2. Type "a" in the text form, suggestions popup should appear. + Verify that font size of text in suggestion popup is the same as in + the corresponding input form. + </li> + <li>3. Delete contents of input box, press Cntrl/+ [Command/+ on Mac] + to magnify the page contents. Repeat step 2, text size should still + match. </li> + </ul> + <form method="get" action="suggestions-popup-font-change.html" id="form"> + <input name="s" id="s" style="font-size:x-large"> + </form> +</body> +</html> diff --git a/WebCore/manual-tests/compositing/accel-comp-iframe-tab-repaint.html b/WebCore/manual-tests/compositing/accel-comp-iframe-tab-repaint.html new file mode 100644 index 0000000..35c9c34 --- /dev/null +++ b/WebCore/manual-tests/compositing/accel-comp-iframe-tab-repaint.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>Accelerated compositing tab repaint bug</title> +<style> +body { + background-color: yellow; +} +</style> +<h1>Accelerated compositing tab repaint bug</h1> +<p>This test case checks for a repaint bug resulting from accelerated +compositing of iframes on Mac. Follow these steps:</p> +<ol> +<li>Open <a href="resources/tab-repaint-part-2.html">this link</a> in a new tab.</li> +<li>Close this tab.</li> +<li>The new page should be blue.</li> +</ol> diff --git a/WebCore/manual-tests/compositing/resources/flash-frame.html b/WebCore/manual-tests/compositing/resources/flash-frame.html new file mode 100644 index 0000000..34d9290 --- /dev/null +++ b/WebCore/manual-tests/compositing/resources/flash-frame.html @@ -0,0 +1,3 @@ +<!DOCTYPE html> +<title>Flash frame for repaint test</title> +<embed src="../../resources/spinbox.swf"> diff --git a/WebCore/manual-tests/compositing/resources/tab-repaint-part-2.html b/WebCore/manual-tests/compositing/resources/tab-repaint-part-2.html new file mode 100644 index 0000000..17cb6e7 --- /dev/null +++ b/WebCore/manual-tests/compositing/resources/tab-repaint-part-2.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<title>Accelerated compositing tab repaint bug part 2</title> +<style> +body { + background-color: royalblue; +} +iframe { + border-width: 0px; + width: 400px; + height: 200px; +} +</style> +<body> +<ol> +<li>This page should have a blue background.</li> +</ol> +<iframe src="../resources/flash-frame.html"></iframe> +</body> diff --git a/WebCore/manual-tests/dom/document-write-synchronous-after-page-load.html b/WebCore/manual-tests/dom/document-write-synchronous-after-page-load.html new file mode 100644 index 0000000..f62fd68 --- /dev/null +++ b/WebCore/manual-tests/dom/document-write-synchronous-after-page-load.html @@ -0,0 +1,23 @@ +<p>This test ensures that document.write after page load is synchronous.</p> +<p>You will get a PASS or FAIL alert message after a few seconds.</p> +<script> +window.onload = function() { + + // Build a very long string to write. + var LIMIT = 17; + var str = '<p style="display:none">x</p>'; + for (var i=0; i<LIMIT; ++i) + str += str; + + // Write the string and check the DOM immediately and after a small delay. + var doc = document.implementation.createHTMLDocument(); + doc.write(str); + var immediateElementCount = doc.getElementsByTagName('*').length; + setTimeout(function() { + var delayedElementCount = doc.getElementsByTagName('*').length; + var passOrFail = (immediateElementCount === delayedElementCount ? "PASS" : "FAIL"); + alert(passOrFail); + }, 100); + +} +</script> diff --git a/WebCore/manual-tests/focus-change-between-key-events.html b/WebCore/manual-tests/focus-change-between-key-events.html new file mode 100644 index 0000000..8ceb575 --- /dev/null +++ b/WebCore/manual-tests/focus-change-between-key-events.html @@ -0,0 +1,24 @@ +<body onload="document.getElementById('dummy').focus();"> +<iframe src="data:text/html,<body onload='document.getElementsByTagName("input")[0].focus()'><input></body>" id=victim name=victim> +</iframe> +<script> + +var cur_pos = 0; + +function maybe_redirect(e) { + var evt = window.event ? event : e; + var cc = evt.charCode ? evt.charCode : evt.keyCode; + + document.getElementById('victim').focus(); + frames['victim'].focus(); + + document.getElementById('dummy').value += String.fromCharCode(cc).toLowerCase(); + + setTimeout('focus();document.getElementById("dummy").focus()',1); +} + + +</script> +<p>Type some text. It should only appear in the below input field.</p> +<input type=text onkeydown="maybe_redirect(event)" id=dummy> +</body> diff --git a/WebCore/manual-tests/onfocus-alert-blinking-caret.html b/WebCore/manual-tests/onfocus-alert-blinking-caret.html new file mode 100644 index 0000000..26b9812 --- /dev/null +++ b/WebCore/manual-tests/onfocus-alert-blinking-caret.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML> + +<body> +Focus the field below, then dismiss the alert. The field should retain the focus, +and the caret in the field should blink. +<br> +<input onfocus="alert('Test');"> +</body> diff --git a/WebCore/manual-tests/qt/qt-10loop-anim.gif b/WebCore/manual-tests/qt/qt-10loop-anim.gif Binary files differnew file mode 100644 index 0000000..ddb0006 --- /dev/null +++ b/WebCore/manual-tests/qt/qt-10loop-anim.gif diff --git a/WebCore/manual-tests/qt/qt-gif-test.html b/WebCore/manual-tests/qt/qt-gif-test.html index 06505f4..3412e1b 100644 --- a/WebCore/manual-tests/qt/qt-gif-test.html +++ b/WebCore/manual-tests/qt/qt-gif-test.html @@ -2,11 +2,15 @@ <body> <div> <img src="qt-anim.gif"> - <p>This should animate</p> + <p>This should animate.</p> </div> <div> <img src="qt-noanim.gif"> - <p>This should not animate and you should see a cross</p> + <p>This should not animate and you should see a cross.</p> +</div +<div> + <img src="qt-10loop-anim.gif"> + <p>This animation should loop 10 times.</p> </div </body> </html> diff --git a/WebCore/manual-tests/svg-tooltip.svg b/WebCore/manual-tests/svg-tooltip.svg new file mode 100644 index 0000000..84fe1d7 --- /dev/null +++ b/WebCore/manual-tests/svg-tooltip.svg @@ -0,0 +1,62 @@ +<?xml version="1.0"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <title>This string should not show up as a tooltip</title> + <desc> + This test verifies that tooltips are properly rendered for SVG content in a variety of + scenarios. Hovering over every shape should result in a tooltip of "PASS". + </desc> + <defs> + <ellipse id="e1" cx="100" cy="200" rx="50" ry="30" fill="blue"> + <title>PASS</title> + </ellipse> + <ellipse id="e2" cx="250" cy="200" rx="50" ry="30" fill="blue"> + <title>FAIL</title> + </ellipse> + <symbol id="e3"> + <ellipse cx="100" cy="300" rx="50" ry="30" fill="blue"> + <title>PASS</title> + </ellipse> + </symbol> + <symbol id="e4"> + <title>FAIL</title> + <ellipse cx="250" cy="300" rx="50" ry="30" fill="blue"> + </ellipse> + </symbol> + </defs> + + <text y="15" x="0">When hovered, all shapes should show a "PASS" tooltip. Anything else is a failure.</text> + + <ellipse cx="100" cy="100" rx="50" ry="30" fill="blue"> + <title>PASS</title> + </ellipse> + + <g> + <title>PASS</title> + <ellipse cx="250" cy="100" rx="50" ry="30" fill="blue"/> + </g> + + <a xlink:title="PASS" xlink:href="#"> + <title>FAIL</title> + <ellipse id="e4" cx="400" cy="100" rx="50" ry="30" fill="blue"/> + </a> + + <use xlink:href="#e1"/> + + <use xlink:href="#e2"> + <title>PASS</title> + </use> + + <g> + <title>FAIL</title> + <ellipse id="e8" cx="400" cy="200" rx="50" ry="30" fill="blue"> + <title>PASS</title> + </ellipse> + </g> + + <use xlink:href="#e3"/> + <use xlink:href="#e4"> + <title>PASS</title> + </use> + + +</svg> diff --git a/WebCore/manual-tests/visited-link-new-window.html b/WebCore/manual-tests/visited-link-new-window.html new file mode 100644 index 0000000..5e10a34 --- /dev/null +++ b/WebCore/manual-tests/visited-link-new-window.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html> +<head> +<title>Visited link coloring test</test> +<style> +:visited { + color: limegreen; +} +</style> +</head> +<body> +<h1>Visited link coloring test</h1> +<p>Make sure the link below is not colored as visited (delete the item +for visited-link.html from your history and restart if +necessary). Then cmd-click it. The link should turn lime green.</p> +<a href="resources/visited-link.html">Am I a visited link?</a> +</body> +</html> diff --git a/WebCore/mathml/MathMLElement.cpp b/WebCore/mathml/MathMLElement.cpp index b47f4a9..b84616f 100644 --- a/WebCore/mathml/MathMLElement.cpp +++ b/WebCore/mathml/MathMLElement.cpp @@ -37,7 +37,7 @@ namespace WebCore { using namespace MathMLNames; MathMLElement::MathMLElement(const QualifiedName& tagName, Document* document) - : StyledElement(tagName, document, CreateElementZeroRefCount) + : StyledElement(tagName, document, CreateStyledElementZeroRefCount) { } diff --git a/WebCore/mathml/MathMLInlineContainerElement.cpp b/WebCore/mathml/MathMLInlineContainerElement.cpp index 2d682a2..c5fcac9 100644 --- a/WebCore/mathml/MathMLInlineContainerElement.cpp +++ b/WebCore/mathml/MathMLInlineContainerElement.cpp @@ -33,7 +33,9 @@ #include "RenderMathMLBlock.h" #include "RenderMathMLFraction.h" #include "RenderMathMLMath.h" +#include "RenderMathMLRoot.h" #include "RenderMathMLRow.h" +#include "RenderMathMLSquareRoot.h" #include "RenderMathMLSubSup.h" #include "RenderMathMLUnderOver.h" @@ -72,6 +74,10 @@ RenderObject* MathMLInlineContainerElement::createRenderer(RenderArena *arena, R object = new (arena) RenderMathMLUnderOver(this); else if (hasLocalName(MathMLNames::mfracTag)) object = new (arena) RenderMathMLFraction(this); + else if (hasLocalName(MathMLNames::msqrtTag)) + object = new (arena) RenderMathMLSquareRoot(this); + else if (hasLocalName(MathMLNames::mrootTag)) + object = new (arena) RenderMathMLRoot(this); else object = new (arena) RenderMathMLBlock(this); object->setStyle(style); diff --git a/WebCore/mathml/RenderMathMLOperator.cpp b/WebCore/mathml/RenderMathMLOperator.cpp index da9e8ec..1ab3409 100644 --- a/WebCore/mathml/RenderMathMLOperator.cpp +++ b/WebCore/mathml/RenderMathMLOperator.cpp @@ -193,7 +193,7 @@ void RenderMathMLOperator::updateFromElement() text = new (renderArena()) RenderText(node(), StringImpl::create(&m_operator, 1)); else if (node()->nodeType() == Node::ELEMENT_NODE) if (Element* mo = static_cast<Element*>(node())) - text = new (renderArena()) RenderText(node(), StringImpl::create(mo->textContent())); + text = new (renderArena()) RenderText(node(), StringImpl::create(mo->textContent().characters(), mo->textContent().length())); // If we can't figure out the text, leave it blank. if (text) { text->setStyle(container->style()); diff --git a/WebCore/mathml/RenderMathMLRoot.cpp b/WebCore/mathml/RenderMathMLRoot.cpp new file mode 100644 index 0000000..23e3519 --- /dev/null +++ b/WebCore/mathml/RenderMathMLRoot.cpp @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2010 François Sausset (sausset@gmail.com). 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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" + +#if ENABLE(MATHML) + +#include "RenderMathMLRoot.h" + +#include "GraphicsContext.h" +#include "MathMLNames.h" + +namespace WebCore { + +using namespace MathMLNames; + +// Left margin of the radical (px) +const int gRadicalLeftMargin = 3; +// Bottom padding of the radical (px) +const int gRadicalBasePad = 3; +// Threshold above which the radical shape is modified to look nice with big bases (%) +const float gThresholdBaseHeight = 1.5; +// Radical width (%) +const float gRadicalWidth = 0.75; +// Horizontal position of the bottom point of the radical (%) +const float gRadicalBottomPointXPos= 0.5; +// Horizontal position of the top left point of the radical (%) +const float gRadicalTopLeftPointXPos = 0.8; +// Vertical position of the top left point of the radical (%) +const float gRadicalTopLeftPointYPos = 0.625; +// Vertical shift of the left end point of the radical (%) +const float gRadicalLeftEndYShift = 0.05; +// Root padding around the base (%) +const float gRootPadding = 0.2; +// Additional bottom root padding (%) +const float gRootBottomPadding = 0.2; + +// Radical line thickness (%) +const float gRadicalLineThickness = 0.02; +// Radical thick line thickness (%) +const float gRadicalThickLineThickness = 0.1; + +RenderMathMLRoot::RenderMathMLRoot(Node *expression) +: RenderMathMLBlock(expression) +{ +} + +void RenderMathMLRoot::addChild(RenderObject* child, RenderObject* ) +{ + if (isEmpty()) { + // Add a block for the index + RenderBlock* block = new (renderArena()) RenderBlock(node()); + RefPtr<RenderStyle> indexStyle = makeBlockStyle(); + indexStyle->setDisplay(INLINE_BLOCK); + block->setStyle(indexStyle.release()); + RenderBlock::addChild(block); + + // FIXME: the wrapping does not seem to be needed anymore. + // this is the base, so wrap it so we can pad it + block = new (renderArena()) RenderBlock(node()); + RefPtr<RenderStyle> baseStyle = makeBlockStyle(); + baseStyle->setDisplay(INLINE_BLOCK); + baseStyle->setPaddingLeft(Length(5 * gRadicalWidth , Percent)); + block->setStyle(baseStyle.release()); + RenderBlock::addChild(block); + block->addChild(child); + } else { + // always add to the index + firstChild()->addChild(child); + } +} + +void RenderMathMLRoot::paint(PaintInfo& info, int tx, int ty) +{ + RenderMathMLBlock::paint(info , tx , ty); + + tx += x(); + ty += y(); + + RenderBoxModelObject* indexBox = toRenderBoxModelObject(lastChild()); + + int maxHeight = indexBox->offsetHeight(); + // default to the font size in pixels if we're empty + if (!maxHeight) + maxHeight = style()->fontSize(); + int width = indexBox->offsetWidth(); + + int indexWidth = 0; + RenderObject* current = firstChild(); + while (current != lastChild()) { + if (current->isBoxModelObject()) { + RenderBoxModelObject* box = toRenderBoxModelObject(current); + indexWidth += box->offsetWidth(); + } + current = current->nextSibling(); + } + + int frontWidth = static_cast<int>(style()->fontSize() * gRadicalWidth); + int topStartShift = 0; + // Base height above which the shape of the root changes + int thresholdHeight = static_cast<int>(gThresholdBaseHeight * style()->fontSize()); + + if (maxHeight > thresholdHeight && thresholdHeight) { + float shift = (maxHeight - thresholdHeight) / static_cast<float>(thresholdHeight); + if (shift > 1.) + shift = 1.; + topStartShift = static_cast<int>(gRadicalBottomPointXPos * frontWidth * shift); + } + + width += topStartShift; + + int rootPad = static_cast<int>(gRootPadding * style()->fontSize()); + int start = tx + indexWidth + gRadicalLeftMargin + style()->paddingLeft().value() - rootPad; + ty += style()->paddingTop().value() - rootPad; + + FloatPoint topStart(start - topStartShift, ty); + FloatPoint bottomLeft(start - gRadicalBottomPointXPos * frontWidth , ty + maxHeight + gRadicalBasePad); + FloatPoint topLeft(start - gRadicalTopLeftPointXPos * frontWidth , ty + gRadicalTopLeftPointYPos * maxHeight); + FloatPoint leftEnd(start - frontWidth , topLeft.y() + gRadicalLeftEndYShift * style()->fontSize()); + + info.context->save(); + + info.context->setStrokeThickness(gRadicalLineThickness * style()->fontSize()); + info.context->setStrokeStyle(SolidStroke); + info.context->setStrokeColor(style()->color(), sRGBColorSpace); + info.context->setLineJoin(MiterJoin); + info.context->setMiterLimit(style()->fontSize()); + + Path root; + + root.moveTo(FloatPoint(topStart.x() + width, ty)); + // draw top + root.addLineTo(topStart); + // draw from top left corner to bottom point of radical + root.addLineTo(bottomLeft); + // draw from bottom point to top of left part of radical base "pocket" + root.addLineTo(topLeft); + // draw to end + root.addLineTo(leftEnd); + + info.context->beginPath(); + info.context->addPath(root); + info.context->strokePath(); + + info.context->save(); + + // Build a mask to draw the thick part of the root. + Path mask; + + mask.moveTo(topStart); + mask.addLineTo(bottomLeft); + mask.addLineTo(topLeft); + mask.addLineTo(FloatPoint(2 * topLeft.x() - leftEnd.x(), 2 * topLeft.y() - leftEnd.y())); + + info.context->beginPath(); + info.context->addPath(mask); + info.context->clip(mask); + + // Draw the thick part of the root. + info.context->setStrokeThickness(gRadicalThickLineThickness * style()->fontSize()); + info.context->setLineCap(SquareCap); + + Path line; + + line = line.createLine(bottomLeft, topLeft); + + info.context->beginPath(); + info.context->addPath(line); + info.context->strokePath(); + + info.context->restore(); + + info.context->restore(); + +} + +void RenderMathMLRoot::layout() +{ + RenderBlock::layout(); + + int maxHeight = toRenderBoxModelObject(lastChild())->offsetHeight(); + + RenderObject* current = lastChild()->firstChild(); + + toRenderMathMLBlock(current)->style()->setVerticalAlign(BASELINE); + + if (!maxHeight) + maxHeight = style()->fontSize(); + + // Base height above which the shape of the root changes + int thresholdHeight = static_cast<int>(gThresholdBaseHeight * style()->fontSize()); + int topStartShift = 0; + + if (maxHeight > thresholdHeight && thresholdHeight) { + float shift = (maxHeight - thresholdHeight) / static_cast<float>(thresholdHeight); + if (shift > 1.) + shift = 1.; + int frontWidth = static_cast<int>(style()->fontSize() * gRadicalWidth); + topStartShift = static_cast<int>(gRadicalBottomPointXPos * frontWidth * shift); + + style()->setPaddingBottom(Length(static_cast<int>(gRootBottomPadding * style()->fontSize()), Fixed)); + } + + // Positioning of the index + RenderBoxModelObject* indexBox = toRenderBoxModelObject(firstChild()->firstChild()); + + int indexShift = indexBox->offsetWidth() + topStartShift; + int radicalHeight = static_cast<int>((1 - gRadicalTopLeftPointYPos) * maxHeight); + int rootMarginTop = radicalHeight + style()->paddingBottom().value() + indexBox->offsetHeight() - (maxHeight + static_cast<int>(gRootPadding * style()->fontSize())); + + style()->setPaddingLeft(Length(indexShift, Fixed)); + if (rootMarginTop > 0) + style()->setPaddingTop(Length(rootMarginTop + static_cast<int>(gRootPadding * style()->fontSize()), Fixed)); + + setNeedsLayoutAndPrefWidthsRecalc(); + markContainingBlocksForLayout(); + RenderBlock::layout(); + + indexBox->style()->setBottom(Length(radicalHeight + style()->paddingBottom().value(), Fixed)); + + indexBox->layout(); +} + +} + +#endif // ENABLE(MATHML) + + diff --git a/WebCore/mathml/RenderMathMLRoot.h b/WebCore/mathml/RenderMathMLRoot.h new file mode 100644 index 0000000..80f56ac --- /dev/null +++ b/WebCore/mathml/RenderMathMLRoot.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 RenderMathMLRoot_h +#define RenderMathMLRoot_h + +#if ENABLE(MATHML) + +#include "RenderMathMLBlock.h" + +namespace WebCore { + +class RenderMathMLRoot : public RenderMathMLBlock { +public: + RenderMathMLRoot(Node* fraction); + virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0); + virtual void paint(PaintInfo&, int tx, int ty); +protected: + virtual void layout(); +}; + +} + +#endif // ENABLE(MATHML) + +#endif // RenderMathMLRoot_h diff --git a/WebCore/mathml/RenderMathMLSquareRoot.cpp b/WebCore/mathml/RenderMathMLSquareRoot.cpp new file mode 100644 index 0000000..fc0a16d --- /dev/null +++ b/WebCore/mathml/RenderMathMLSquareRoot.cpp @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. + * Copyright (C) 2010 François Sausset (sausset@gmail.com). 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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" + +#if ENABLE(MATHML) + +#include "RenderMathMLSquareRoot.h" + +#include "GraphicsContext.h" +#include "MathMLNames.h" +#include "Path.h" + +namespace WebCore { + +using namespace MathMLNames; + +// Bottom padding of the radical (px) +const int gRadicalBasePad = 3; +// Threshold above which the radical shape is modified to look nice with big bases (%) +const float gThresholdBaseHeight = 1.5; +// Radical width (%) +const float gRadicalWidth = 0.75; +// Horizontal position of the bottom point of the radical (%) +const float gRadicalBottomPointXPos= 0.5; +// Horizontal position of the top left point of the radical (%) +const float gRadicalTopLeftPointXPos = 0.2; +// Vertical position of the top left point of the radical (%) +const float gRadicalTopLeftPointYPos = 0.5; +// Vertical shift of the left end point of the radical (%) +const float gRadicalLeftEndYShift = 0.05; +// Additional bottom root padding (%) +const float gRootBottomPadding = 0.2; + +// Radical line thickness (%) +const float gRadicalLineThickness = 0.02; +// Radical thick line thickness (%) +const float gRadicalThickLineThickness = 0.1; + +RenderMathMLSquareRoot::RenderMathMLSquareRoot(Node *expression) + : RenderMathMLBlock(expression) +{ +} + +void RenderMathMLSquareRoot::paint(PaintInfo& info, int tx, int ty) +{ + RenderMathMLBlock::paint(info, tx, ty); + + tx += x(); + ty += y(); + + int maxHeight = 0; + int width = 0; + RenderObject* current = firstChild(); + while (current) { + if (current->isBoxModelObject()) { + + RenderBoxModelObject* box = toRenderBoxModelObject(current); + + // Check to see if this box has a larger height + if (box->offsetHeight() > maxHeight) + maxHeight = box->offsetHeight(); + width += box->offsetWidth(); + } + current = current->nextSibling(); + } + // default to the font size in pixels if we're empty + if (!maxHeight) + maxHeight = style()->fontSize(); + + int frontWidth = static_cast<int>(style()->fontSize() * gRadicalWidth); + int topStartShift = 0; + // Base height above which the shape of the root changes + int thresholdHeight = static_cast<int>(gThresholdBaseHeight * style()->fontSize()); + + if (maxHeight > thresholdHeight && thresholdHeight) { + float shift = (maxHeight - thresholdHeight) / static_cast<float>(thresholdHeight); + if (shift > 1.) + shift = 1.; + topStartShift = static_cast<int>(gRadicalBottomPointXPos * frontWidth * shift); + } + + width += topStartShift; + + FloatPoint topStart(tx + frontWidth - topStartShift, ty); + FloatPoint bottomLeft(tx + frontWidth * gRadicalBottomPointXPos , ty + maxHeight + gRadicalBasePad); + FloatPoint topLeft(tx + frontWidth * gRadicalTopLeftPointXPos , ty + gRadicalTopLeftPointYPos * maxHeight); + FloatPoint leftEnd(tx , topLeft.y() + gRadicalLeftEndYShift * style()->fontSize()); + + info.context->save(); + + info.context->setStrokeThickness(gRadicalLineThickness * style()->fontSize()); + info.context->setStrokeStyle(SolidStroke); + info.context->setStrokeColor(style()->color(), sRGBColorSpace); + info.context->setLineJoin(MiterJoin); + info.context->setMiterLimit(style()->fontSize()); + + Path root; + + root.moveTo(FloatPoint(topStart.x() + width , ty)); + // draw top + root.addLineTo(topStart); + // draw from top left corner to bottom point of radical + root.addLineTo(bottomLeft); + // draw from bottom point to top of left part of radical base "pocket" + root.addLineTo(topLeft); + // draw to end + root.addLineTo(leftEnd); + + info.context->beginPath(); + info.context->addPath(root); + info.context->strokePath(); + + info.context->save(); + + // Build a mask to draw the thick part of the root. + Path mask; + + mask.moveTo(topStart); + mask.addLineTo(bottomLeft); + mask.addLineTo(topLeft); + mask.addLineTo(FloatPoint(2 * topLeft.x() - leftEnd.x(), 2 * topLeft.y() - leftEnd.y())); + + info.context->beginPath(); + info.context->addPath(mask); + info.context->clip(mask); + + // Draw the thick part of the root. + info.context->setStrokeThickness(gRadicalThickLineThickness * style()->fontSize()); + info.context->setLineCap(SquareCap); + + Path line; + + line = line.createLine(bottomLeft, topLeft); + + info.context->beginPath(); + info.context->addPath(line); + info.context->strokePath(); + + info.context->restore(); + + info.context->restore(); +} + +void RenderMathMLSquareRoot::layout() +{ + int maxHeight = 0; + + RenderObject* current = firstChild(); + while (current) { + if (current->isBoxModelObject()) { + RenderBoxModelObject* box = toRenderBoxModelObject(current); + + if (box->offsetHeight() > maxHeight) + maxHeight = box->offsetHeight(); + + box->style()->setVerticalAlign(BASELINE); + } + current = current->nextSibling(); + } + + if (!maxHeight) + maxHeight = style()->fontSize(); + + + if (maxHeight > static_cast<int>(gThresholdBaseHeight * style()->fontSize())) + style()->setPaddingBottom(Length(static_cast<int>(gRootBottomPadding * style()->fontSize()), Fixed)); + + + RenderBlock::layout(); +} + +} + +#endif // ENABLE(MATHML) + + diff --git a/WebCore/mathml/RenderMathMLSquareRoot.h b/WebCore/mathml/RenderMathMLSquareRoot.h new file mode 100644 index 0000000..d40b1ba --- /dev/null +++ b/WebCore/mathml/RenderMathMLSquareRoot.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2009 Alex Milowski (alex@milowski.com). 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 RenderMathMLSquareRoot_h +#define RenderMathMLSquareRoot_h + +#if ENABLE(MATHML) + +#include "RenderMathMLBlock.h" + +namespace WebCore { + +class RenderMathMLSquareRoot : public RenderMathMLBlock { +public: + RenderMathMLSquareRoot(Node* fraction); + virtual void paint(PaintInfo&, int tx, int ty); +protected: + virtual void layout(); +}; + +} + +#endif // ENABLE(MATHML) + +#endif // RenderMathMLSquareRoot_h + + + diff --git a/WebCore/notifications/Notification.h b/WebCore/notifications/Notification.h index 98cbfdf..47de2a2 100644 --- a/WebCore/notifications/Notification.h +++ b/WebCore/notifications/Notification.h @@ -68,6 +68,11 @@ namespace WebCore { KURL iconURL() { return m_contents.icon(); } NotificationContents& contents() { return m_contents; } + String dir() const { return m_direction; } + void setDir(const String& dir) { m_direction = dir; } + String replaceId() const { return m_replaceId; } + void setReplaceId(const String& replaceId) { m_replaceId = replaceId; } + DEFINE_ATTRIBUTE_EVENT_LISTENER(display); DEFINE_ATTRIBUTE_EVENT_LISTENER(error); DEFINE_ATTRIBUTE_EVENT_LISTENER(close); @@ -93,6 +98,9 @@ namespace WebCore { KURL m_notificationURL; NotificationContents m_contents; + String m_direction; + String m_replaceId; + bool m_isShowing; NotificationPresenter* m_presenter; diff --git a/WebCore/notifications/Notification.idl b/WebCore/notifications/Notification.idl index b99da96..5ca84a5 100644 --- a/WebCore/notifications/Notification.idl +++ b/WebCore/notifications/Notification.idl @@ -42,13 +42,16 @@ module threads { attribute EventListener onerror; attribute EventListener onclose; + attribute DOMString dir; + attribute DOMString replaceId; + // EventTarget interface - [JSCCustom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [JSCCustom] void removeEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); + void addEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); + void removeEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); boolean dispatchEvent(in Event evt) raises(EventException); }; diff --git a/WebCore/page/AbstractView.idl b/WebCore/page/AbstractView.idl index 290bf48..e4ece0f 100644 --- a/WebCore/page/AbstractView.idl +++ b/WebCore/page/AbstractView.idl @@ -32,7 +32,7 @@ module views { OmitConstructor ] AbstractView { readonly attribute Document document; - readonly attribute Media media; + readonly attribute Media styleMedia; }; } diff --git a/WebCore/page/Chrome.cpp b/WebCore/page/Chrome.cpp index 841908d..799aaee 100644 --- a/WebCore/page/Chrome.cpp +++ b/WebCore/page/Chrome.cpp @@ -107,9 +107,10 @@ void Chrome::contentsSizeChanged(Frame* frame, const IntSize& size) const m_client->contentsSizeChanged(frame, size); } -void Chrome::scrollRectIntoView(const IntRect& rect, const ScrollView* scrollView) const +void Chrome::scrollRectIntoView(const IntRect& rect) const { - m_client->scrollRectIntoView(rect, scrollView); + // FIXME: The unused ScrollView* argument can and should be removed from ChromeClient::scrollRectIntoView. + m_client->scrollRectIntoView(rect, 0); } void Chrome::scrollbarsModeDidChange() const diff --git a/WebCore/page/Chrome.h b/WebCore/page/Chrome.h index 658404a..3882f5e 100644 --- a/WebCore/page/Chrome.h +++ b/WebCore/page/Chrome.h @@ -68,9 +68,10 @@ namespace WebCore { virtual IntPoint screenToWindow(const IntPoint&) const; virtual IntRect windowToScreen(const IntRect&) const; virtual PlatformPageClient platformPageClient() const; - virtual void scrollRectIntoView(const IntRect&, const ScrollView*) const; virtual void scrollbarsModeDidChange() const; + void scrollRectIntoView(const IntRect&) const; + void contentsSizeChanged(Frame*, const IntSize&) const; void setWindowRect(const FloatRect&) const; diff --git a/WebCore/page/Console.cpp b/WebCore/page/Console.cpp index d5ff7bc..864b834 100644 --- a/WebCore/page/Console.cpp +++ b/WebCore/page/Console.cpp @@ -289,6 +289,7 @@ void Console::markTimeline(ScriptCallStack* callStack) #if ENABLE(WML) String Console::lastWMLErrorMessage() const { +#if ENABLE(INSPECTOR) Page* page = this->page(); if (!page) return String(); @@ -307,7 +308,7 @@ String Console::lastWMLErrorMessage() const return message->message(); } - +#endif return String(); } #endif diff --git a/WebCore/page/DOMWindow.cpp b/WebCore/page/DOMWindow.cpp index c74cfaf..633feb6 100644 --- a/WebCore/page/DOMWindow.cpp +++ b/WebCore/page/DOMWindow.cpp @@ -58,7 +58,7 @@ #include "InspectorController.h" #include "InspectorTimelineAgent.h" #include "Location.h" -#include "Media.h" +#include "StyleMedia.h" #include "MessageEvent.h" #include "Navigator.h" #include "NotificationCenter.h" @@ -575,7 +575,7 @@ Location* DOMWindow::location() const } #if ENABLE(DOM_STORAGE) -Storage* DOMWindow::sessionStorage() const +Storage* DOMWindow::sessionStorage(ExceptionCode& ec) const { if (m_sessionStorage) return m_sessionStorage.get(); @@ -584,6 +584,11 @@ Storage* DOMWindow::sessionStorage() const if (!document) return 0; + if (!document->securityOrigin()->canAccessLocalStorage()) { + ec = SECURITY_ERR; + return 0; + } + Page* page = document->page(); if (!page) return 0; @@ -601,16 +606,16 @@ Storage* DOMWindow::localStorage(ExceptionCode& ec) const { if (m_localStorage) return m_localStorage.get(); - + Document* document = this->document(); if (!document) return 0; - + if (!document->securityOrigin()->canAccessLocalStorage()) { ec = SECURITY_ERR; return 0; } - + Page* page = document->page(); if (!page) return 0; @@ -1136,10 +1141,10 @@ Document* DOMWindow::document() const return m_frame->document(); } -PassRefPtr<Media> DOMWindow::media() const +PassRefPtr<StyleMedia> DOMWindow::styleMedia() const { if (!m_media) - m_media = Media::create(m_frame); + m_media = StyleMedia::create(m_frame); return m_media.get(); } diff --git a/WebCore/page/DOMWindow.h b/WebCore/page/DOMWindow.h index c3a781c..e4aa4cb 100644 --- a/WebCore/page/DOMWindow.h +++ b/WebCore/page/DOMWindow.h @@ -56,7 +56,7 @@ namespace WebCore { class IndexedDatabaseRequest; class InspectorTimelineAgent; class Location; - class Media; + class StyleMedia; class Navigator; class Node; class NotificationCenter; @@ -187,7 +187,7 @@ namespace WebCore { // DOM Level 2 AbstractView Interface Document* document() const; // CSSOM View Module - PassRefPtr<Media> media() const; + PassRefPtr<StyleMedia> styleMedia() const; // DOM Level 2 Style Interface PassRefPtr<CSSStyleDeclaration> getComputedStyle(Element*, const String& pseudoElt) const; @@ -206,7 +206,7 @@ namespace WebCore { #if ENABLE(DOM_STORAGE) // HTML 5 key/value storage - Storage* sessionStorage() const; + Storage* sessionStorage(ExceptionCode&) const; Storage* localStorage(ExceptionCode&) const; #endif @@ -353,7 +353,7 @@ namespace WebCore { Console* optionalConsole() const { return m_console.get(); } Navigator* optionalNavigator() const { return m_navigator.get(); } Location* optionalLocation() const { return m_location.get(); } - Media* optionalMedia() const { return m_media.get(); } + StyleMedia* optionalMedia() const { return m_media.get(); } #if ENABLE(DOM_STORAGE) Storage* optionalSessionStorage() const { return m_sessionStorage.get(); } Storage* optionalLocalStorage() const { return m_localStorage.get(); } @@ -390,7 +390,7 @@ namespace WebCore { mutable RefPtr<Console> m_console; mutable RefPtr<Navigator> m_navigator; mutable RefPtr<Location> m_location; - mutable RefPtr<Media> m_media; + mutable RefPtr<StyleMedia> m_media; #if ENABLE(DOM_STORAGE) mutable RefPtr<Storage> m_sessionStorage; mutable RefPtr<Storage> m_localStorage; diff --git a/WebCore/page/DOMWindow.idl b/WebCore/page/DOMWindow.idl index 018b4de..a1ce419 100644 --- a/WebCore/page/DOMWindow.idl +++ b/WebCore/page/DOMWindow.idl @@ -141,7 +141,7 @@ module window { readonly attribute Document document; // CSSOM View Module - readonly attribute Media media; + readonly attribute StyleMedia styleMedia; // DOM Level 2 Style Interface CSSStyleDeclaration getComputedStyle(in Element element, @@ -164,7 +164,8 @@ module window { raises(DOMException); #endif #if defined(ENABLE_DOM_STORAGE) && ENABLE_DOM_STORAGE - readonly attribute [EnabledAtRuntime] Storage sessionStorage; + readonly attribute [EnabledAtRuntime] Storage sessionStorage + getter raises(DOMException); readonly attribute [EnabledAtRuntime] Storage localStorage getter raises(DOMException); #endif @@ -294,10 +295,10 @@ module window { #if defined(ENABLE_ORIENTATION_EVENTS) && ENABLE_ORIENTATION_EVENTS attribute EventListener onorientationchange; #endif - attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchstart; - attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchmove; - attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchend; - attribute [DontEnum,Conditional=TOUCH_EVENTS] EventListener ontouchcancel; + attribute [DontEnum,Conditional=TOUCH_EVENTS,EnabledAtRuntime] EventListener ontouchstart; + attribute [DontEnum,Conditional=TOUCH_EVENTS,EnabledAtRuntime] EventListener ontouchmove; + attribute [DontEnum,Conditional=TOUCH_EVENTS,EnabledAtRuntime] EventListener ontouchend; + attribute [DontEnum,Conditional=TOUCH_EVENTS,EnabledAtRuntime] EventListener ontouchcancel; // EventTarget interface [Custom] void addEventListener(in DOMString type, @@ -715,6 +716,8 @@ module window { attribute DOMFormDataConstructor FormData; + attribute [Conditional=FILE_READER|FILE_WRITER] FileErrorConstructor FileError; + #endif // defined(LANGUAGE_JAVASCRIPT) #if defined(V8_BINDING) && V8_BINDING diff --git a/WebCore/page/DragController.cpp b/WebCore/page/DragController.cpp index f238b27..c603996 100644 --- a/WebCore/page/DragController.cpp +++ b/WebCore/page/DragController.cpp @@ -115,8 +115,15 @@ static PassRefPtr<DocumentFragment> documentFragmentFromDragData(DragData* dragD if (!url.isEmpty()) { RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::create(document); anchor->setHref(url); - ExceptionCode ec; + if (title.isEmpty()) { + // Try the plain text first because the url might be normalized or escaped. + if (dragData->containsPlainText()) + title = dragData->asPlainText(); + if (title.isEmpty()) + title = url; + } RefPtr<Node> anchorText = document->createTextNode(title); + ExceptionCode ec; anchor->appendChild(anchorText, ec); RefPtr<DocumentFragment> fragment = document->createDocumentFragment(); fragment->appendChild(anchor, ec); @@ -313,7 +320,7 @@ bool DragController::tryDocumentDrag(DragData* dragData, DragDestinationAction a } IntPoint point = frameView->windowToContents(dragData->clientPosition()); - Element* element = elementUnderMouse(m_documentUnderMouse, point); + Element* element = elementUnderMouse(m_documentUnderMouse.get(), point); if (!asFileInput(element)) { VisibleSelection dragCaret = m_documentUnderMouse->frame()->visiblePositionForPoint(point); m_page->dragCaretController()->setSelection(dragCaret); @@ -363,7 +370,7 @@ bool DragController::concludeEditDrag(DragData* dragData) return false; IntPoint point = m_documentUnderMouse->view()->windowToContents(dragData->clientPosition()); - Element* element = elementUnderMouse(m_documentUnderMouse, point); + Element* element = elementUnderMouse(m_documentUnderMouse.get(), point); Frame* innerFrame = element->ownerDocument()->frame(); ASSERT(innerFrame); @@ -439,7 +446,7 @@ bool DragController::concludeEditDrag(DragData* dragData) applyCommand(MoveSelectionCommand::create(fragment, dragCaret.base(), smartInsert, smartDelete)); } else { if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) - applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse, fragment, true, dragData->canSmartReplace(), chosePlainText)); + applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse.get(), fragment, true, dragData->canSmartReplace(), chosePlainText)); } } else { String text = dragData->asPlainText(); @@ -450,7 +457,7 @@ bool DragController::concludeEditDrag(DragData* dragData) m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData); if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) - applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse, createFragmentFromText(range.get(), text), true, false, true)); + applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse.get(), createFragmentFromText(range.get(), text), true, false, true)); } loader->setAllowStaleResources(false); diff --git a/WebCore/page/DragController.h b/WebCore/page/DragController.h index 3b2b083..712f9ab 100644 --- a/WebCore/page/DragController.h +++ b/WebCore/page/DragController.h @@ -67,13 +67,11 @@ namespace WebCore { DragOperation sourceDragOperation() const { return m_sourceDragOperation; } void setDraggingImageURL(const KURL& url) { m_draggingImageURL = url; } const KURL& draggingImageURL() const { return m_draggingImageURL; } - void setDragInitiator(Document* initiator) { m_dragInitiator = initiator; m_didInitiateDrag = true; } - Document* dragInitiator() const { return m_dragInitiator; } void setDragOffset(const IntPoint& offset) { m_dragOffset = offset; } const IntPoint& dragOffset() const { return m_dragOffset; } DragSourceAction dragSourceAction() const { return m_dragSourceAction; } - Document* documentUnderMouse() const { return m_documentUnderMouse; } + Document* documentUnderMouse() const { return m_documentUnderMouse.get(); } DragDestinationAction dragDestinationAction() const { return m_dragDestinationAction; } DragSourceAction delegateDragSourceAction(const IntPoint& pagePoint); @@ -114,8 +112,8 @@ namespace WebCore { Page* m_page; DragClient* m_client; - Document* m_documentUnderMouse; // The document the mouse was last dragged over. - Document* m_dragInitiator; // The Document (if any) that initiated the drag. + RefPtr<Document> m_documentUnderMouse; // The document the mouse was last dragged over. + RefPtr<Document> m_dragInitiator; // The Document (if any) that initiated the drag. DragDestinationAction m_dragDestinationAction; DragSourceAction m_dragSourceAction; diff --git a/WebCore/page/EventHandler.cpp b/WebCore/page/EventHandler.cpp index d775e89..8f63144 100644 --- a/WebCore/page/EventHandler.cpp +++ b/WebCore/page/EventHandler.cpp @@ -69,6 +69,7 @@ #include "SelectionController.h" #include "Settings.h" #include "TextEvent.h" +#include "TextIterator.h" #include "UserGestureIndicator.h" #include "WheelEvent.h" #include "htmlediting.h" // for comparePositions() @@ -145,7 +146,7 @@ static inline bool scrollNode(float delta, WheelEvent::Granularity granularity, return false; } -#if !PLATFORM(MAC) || ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) +#if !PLATFORM(MAC) inline bool EventHandler::eventLoopHandleMouseUp(const MouseEventWithHitTestResults&) { @@ -190,7 +191,7 @@ EventHandler::EventHandler(Frame* frame) , m_mouseDownTimestamp(0) , m_useLatchedWheelEventNode(false) , m_widgetIsLatched(false) -#if PLATFORM(MAC) && !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) +#if PLATFORM(MAC) , m_mouseDownView(nil) , m_sendingEventToSubview(false) , m_activationEventNumber(0) @@ -339,6 +340,12 @@ bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestR return true; } +static int textDistance(const Position& start, const Position& end) +{ + RefPtr<Range> range = Range::create(start.node()->document(), start, end); + return TextIterator::rangeLength(range.get(), true); +} + bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event) { Node* innerNode = event.targetNode(); @@ -369,14 +376,21 @@ bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestR if (extendSelection && newSelection.isCaretOrRange()) { m_frame->selection()->setIsDirectional(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(); - if (comparePositions(pos, start) <= 0) - newSelection = VisibleSelection(pos, end); - else - newSelection = VisibleSelection(start, pos); + ASSERT(m_frame->settings()); + if (m_frame->settings()->editingBehavior() == EditingMacBehavior) { + // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection + // was created right-to-left + Position start = newSelection.start(); + Position end = newSelection.end(); + int distanceToStart = textDistance(start, pos); + int distanceToEnd = textDistance(pos, end); + if (distanceToStart <= distanceToEnd) + newSelection = VisibleSelection(end, pos); + else + newSelection = VisibleSelection(start, pos); + } else { + newSelection.setExtent(pos); + } if (m_frame->selectionGranularity() != CharacterGranularity) { granularity = m_frame->selectionGranularity(); @@ -449,7 +463,6 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve #endif bool swallowEvent = false; - m_frame->selection()->setCaretBlinkingSuspended(true); m_mousePressed = true; m_beganSelectingText = false; @@ -466,6 +479,30 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve return swallowEvent; } +// There are two kinds of renderer that can autoscroll. +static bool canAutoscroll(RenderObject* renderer) +{ + if (!renderer->isBox()) + return false; + + // Check for a box that can be scrolled in its own right. + if (toRenderBox(renderer)->canBeScrolledAndHasScrollableArea()) + return true; + + // Check for a box that represents the top level of a web page. + // This can be scrolled by calling Chrome::scrollRectIntoView. + // This only has an effect on the Mac platform in applications + // that put web views into scrolling containers, such as Mac OS X Mail. + // The code for this is in RenderLayer::scrollRectToVisible. + if (renderer->node() != renderer->document()) + return false; + Frame* frame = renderer->document()->frame(); + if (!frame) + return false; + Page* page = frame->page(); + return page && page->mainFrame() == frame; +} + #if ENABLE(DRAG_SUPPORT) bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& event) { @@ -486,10 +523,9 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e 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. + // Find a renderer that can autoscroll. RenderObject* renderer = targetNode->renderer(); - while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeScrolledAndHasScrollableArea())) { + while (renderer && !canAutoscroll(renderer)) { if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement()) renderer = renderer->document()->ownerElement()->renderer(); else @@ -607,7 +643,12 @@ void EventHandler::updateSelectionForMouseDrag(Node* targetNode, const IntPoint& } } #endif // ENABLE(DRAG_SUPPORT) - + +void EventHandler::lostMouseCapture() +{ + m_frame->selection()->setCaretBlinkingSuspended(false); +} + bool EventHandler::handleMouseUp(const MouseEventWithHitTestResults& event) { if (eventLoopHandleMouseUp(event)) @@ -792,7 +833,7 @@ void EventHandler::updateAutoscrollRenderer() if (Node* nodeAtPoint = hitTest.innerNode()) m_autoscrollRenderer = nodeAtPoint->renderer(); - while (m_autoscrollRenderer && (!m_autoscrollRenderer->isBox() || !toRenderBox(m_autoscrollRenderer)->canBeScrolledAndHasScrollableArea())) + while (m_autoscrollRenderer && !canAutoscroll(m_autoscrollRenderer)) m_autoscrollRenderer = m_autoscrollRenderer->parent(); } @@ -1256,6 +1297,8 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) } } + m_frame->selection()->setCaretBlinkingSuspended(true); + bool swallowEvent = dispatchMouseEvent(eventNames().mousedownEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true); m_capturesDragging = !swallowEvent; @@ -1483,7 +1526,7 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) if (mouseEvent.button() == MiddleButton) m_panScrollButtonPressed = false; if (m_springLoadedPanScrollInProgress) - stopAutoscrollTimer(); + stopAutoscrollTimer(); #endif m_mousePressed = false; @@ -1666,7 +1709,7 @@ void EventHandler::clearDragState() m_dragTarget = 0; m_capturingMouseEventsNode = 0; m_shouldOnlyFireDragOverEvent = false; -#if PLATFORM(MAC) && !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) +#if PLATFORM(MAC) m_sendingEventToSubview = false; #endif } @@ -1790,8 +1833,15 @@ bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targe if (m_nodeUnderMouse) swallowEvent = m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventType, clickCount); - + if (!swallowEvent && eventType == eventNames().mousedownEvent) { + + // If clicking on a frame scrollbar, do not mess up with content focus. + if (FrameView* view = m_frame->view()) { + if (view->scrollbarAtPoint(mouseEvent.pos())) + return false; + } + // The layout needs to be up to date to determine if an element is focusable. m_frame->document()->updateLayoutIgnorePendingStylesheets(); @@ -2178,7 +2228,9 @@ bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent) if (initialKeyEvent.type() == PlatformKeyboardEvent::RawKeyDown) { node->dispatchEvent(keydown, ec); - return keydown->defaultHandled() || keydown->defaultPrevented(); + // If frame changed as a result of keydown dispatch, then return true to avoid sending a subsequent keypress message to the new frame. + bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->focusController()->focusedOrMainFrame(); + return keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame; } // Run input method in advance of DOM event handling. This may result in the IM @@ -2198,7 +2250,9 @@ bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent) } node->dispatchEvent(keydown, ec); - bool keydownResult = keydown->defaultHandled() || keydown->defaultPrevented(); + // If frame changed as a result of keydown dispatch, then return early to avoid sending a subsequent keypress message to the new frame. + bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->focusController()->focusedOrMainFrame(); + bool keydownResult = keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame; if (handledByInputMethod || (keydownResult && !backwardCompatibilityMode)) return keydownResult; diff --git a/WebCore/page/EventHandler.h b/WebCore/page/EventHandler.h index 282100d..c83925c 100644 --- a/WebCore/page/EventHandler.h +++ b/WebCore/page/EventHandler.h @@ -147,6 +147,8 @@ public: bool mouseMoved(const PlatformMouseEvent&); + void lostMouseCapture(); + bool handleMousePressEvent(const PlatformMouseEvent&); bool handleMouseMoveEvent(const PlatformMouseEvent&, HitTestResult* hoveredNode = 0); bool handleMouseReleaseEvent(const PlatformMouseEvent&); @@ -342,7 +344,7 @@ private: bool capturesDragging() const { return m_capturesDragging; } -#if PLATFORM(MAC) && defined(__OBJC__) && !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) +#if PLATFORM(MAC) && defined(__OBJC__) NSView *mouseDownViewIfStillGood(); PlatformMouseEvent currentPlatformMouseEvent() const; @@ -420,10 +422,8 @@ private: RefPtr<Node> m_previousWheelScrolledNode; #if PLATFORM(MAC) -#if !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) NSView *m_mouseDownView; bool m_sendingEventToSubview; -#endif int m_activationEventNumber; #endif #if ENABLE(TOUCH_EVENTS) diff --git a/WebCore/page/EventSource.idl b/WebCore/page/EventSource.idl index 57bd807..be01098 100644 --- a/WebCore/page/EventSource.idl +++ b/WebCore/page/EventSource.idl @@ -53,12 +53,12 @@ module window { void close(); // EventTarget interface - [JSCCustom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [JSCCustom] void removeEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); + void addEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); + void removeEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); boolean dispatchEvent(in Event evt) raises(EventException); diff --git a/WebCore/page/FocusController.cpp b/WebCore/page/FocusController.cpp index e07e2ea..372cb32 100644 --- a/WebCore/page/FocusController.cpp +++ b/WebCore/page/FocusController.cpp @@ -304,7 +304,7 @@ bool FocusController::advanceFocusDirectionally(FocusDirection direction, Keyboa frame = frame->tree()->top(); FocusCandidate focusCandidate; - findFocusableNodeInDirection(frame->document(), focusedNode, direction, event, focusCandidate); + findFocusableNodeInDirection(frame->document()->firstChild(), focusedNode, direction, event, focusCandidate); Node* node = focusCandidate.node; if (!node || !node->isElementNode()) { @@ -389,20 +389,23 @@ static void updateFocusCandidateIfCloser(Node* focusedNode, const FocusCandidate } } -void FocusController::findFocusableNodeInDirection(Document* document, Node* focusedNode, +void FocusController::findFocusableNodeInDirection(Node* outer, Node* focusedNode, FocusDirection direction, KeyboardEvent* event, FocusCandidate& closestFocusCandidate, const FocusCandidate& candidateParent) { - ASSERT(document); - ASSERT(candidateParent.isNull() || static_cast<HTMLFrameOwnerElement*>(candidateParent.node)); + ASSERT(outer); + ASSERT(candidateParent.isNull() + || candidateParent.node->hasTagName(frameTag) + || candidateParent.node->hasTagName(iframeTag)); // Walk all the child nodes and update closestFocusCandidate if we find a nearer node. - for (Node* candidate = document->firstChild(); candidate; candidate = candidate->traverseNextNode()) { + Node* candidate = outer; + while (candidate) { // Inner documents case. if (candidate->isFrameOwnerElement()) - deepFindFocusableNodeInDirection(focusedNode, candidate, direction, event, closestFocusCandidate); + deepFindFocusableNodeInDirection(candidate, focusedNode, direction, event, closestFocusCandidate); else if (candidate != focusedNode && candidate->isKeyboardFocusable(event)) { FocusCandidate currentFocusCandidate(candidate); @@ -410,8 +413,10 @@ void FocusController::findFocusableNodeInDirection(Document* document, Node* foc distanceDataForNode(direction, focusedNode, currentFocusCandidate); // Bail out if distance is maximum. - if (currentFocusCandidate.distance == maxDistance()) + if (currentFocusCandidate.distance == maxDistance()) { + candidate = candidate->traverseNextNode(outer->parent()); continue; + } // If candidateParent is not null, it means that we are in a recursive call // from deepFineFocusableNodeInDirection (i.e. processing an element in an iframe), @@ -423,33 +428,54 @@ void FocusController::findFocusableNodeInDirection(Document* document, Node* foc updateFocusCandidateIfCloser(focusedNode, currentFocusCandidate, closestFocusCandidate); } + + candidate = candidate->traverseNextNode(outer->parent()); } } -void FocusController::deepFindFocusableNodeInDirection(Node* focusedNode, Node* candidate, +void FocusController::deepFindFocusableNodeInDirection(Node* container, Node* focusedNode, FocusDirection direction, KeyboardEvent* event, FocusCandidate& closestFocusCandidate) { - HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(candidate); - if (!owner->contentFrame()) + ASSERT(container->hasTagName(frameTag) || container->hasTagName(iframeTag)); + + // Track if focusedNode is a descendant of the current container node being processed. + bool descendantOfContainer = false; + Node* firstChild = 0; + + // Iframe or Frame. + if (container->hasTagName(frameTag) || container->hasTagName(iframeTag)) { + + HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(container); + if (!owner->contentFrame()) + return; + + Document* innerDocument = owner->contentFrame()->document(); + if (!innerDocument) + return; + + descendantOfContainer = innerDocument == focusedNode->document(); + firstChild = innerDocument->firstChild(); + + } + + if (descendantOfContainer) { + findFocusableNodeInDirection(firstChild, focusedNode, direction, event, closestFocusCandidate); return; + } - Document* innerDocument = owner->contentFrame()->document(); - if (!innerDocument) + // Check if the current container element itself is a good candidate + // to move focus to. If it is, then we traverse its inner nodes. + FocusCandidate candidateParent = FocusCandidate(container); + distanceDataForNode(direction, focusedNode, candidateParent); + + // Bail out if distance is maximum. + if (candidateParent.distance == maxDistance()) return; - if (innerDocument == focusedNode->document()) - findFocusableNodeInDirection(innerDocument, focusedNode, direction, event, closestFocusCandidate); - else { - // Check if the current {i}frame element itself is a good candidate - // to move focus to. If it is, then we traverse its inner nodes. - FocusCandidate candidateParent = FocusCandidate(candidate); - distanceDataForNode(direction, focusedNode, candidateParent); - - // FIXME: Consider alignment? - if (candidateParent.distance < closestFocusCandidate.distance) - findFocusableNodeInDirection(innerDocument, focusedNode, direction, event, closestFocusCandidate, candidateParent); - } + // FIXME: Consider alignment? + if (candidateParent.distance < closestFocusCandidate.distance) + findFocusableNodeInDirection(firstChild, focusedNode, direction, event, closestFocusCandidate, candidateParent); } static bool relinquishesEditingFocus(Node *node) diff --git a/WebCore/page/FocusController.h b/WebCore/page/FocusController.h index dfa3780..4410833 100644 --- a/WebCore/page/FocusController.h +++ b/WebCore/page/FocusController.h @@ -63,9 +63,10 @@ private: bool advanceFocusDirectionally(FocusDirection, KeyboardEvent*); bool advanceFocusInDocumentOrder(FocusDirection, KeyboardEvent*, bool initialFocus); - void findFocusableNodeInDirection(Document*, Node*, FocusDirection, KeyboardEvent*, FocusCandidate& closestFocusCandidate, + void findFocusableNodeInDirection(Node* outter, Node*, FocusDirection, KeyboardEvent*, + FocusCandidate& closestFocusCandidate, const FocusCandidate& parentCandidate = FocusCandidate()); - void deepFindFocusableNodeInDirection(Node*, Node*, FocusDirection, KeyboardEvent*, FocusCandidate&); + void deepFindFocusableNodeInDirection(Node* container, Node* focused, FocusDirection, KeyboardEvent*, FocusCandidate&); Page* m_page; RefPtr<Frame> m_focusedFrame; diff --git a/WebCore/page/FrameView.cpp b/WebCore/page/FrameView.cpp index c69b514..d6b6e71 100644 --- a/WebCore/page/FrameView.cpp +++ b/WebCore/page/FrameView.cpp @@ -484,8 +484,19 @@ void FrameView::setNeedsOneShotDrawingSynchronization() if (page) page->chrome()->client()->setNeedsOneShotDrawingSynchronization(); } + #endif // USE(ACCELERATED_COMPOSITING) +bool FrameView::isEnclosedInCompositingLayer() const +{ +#if USE(ACCELERATED_COMPOSITING) + RenderObject* frameOwnerRenderer = m_frame->ownerRenderer(); + return frameOwnerRenderer && frameOwnerRenderer->containerForRepaint(); +#else + return false; +#endif +} + bool FrameView::syncCompositingStateRecursive() { #if USE(ACCELERATED_COMPOSITING) @@ -1009,15 +1020,6 @@ void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode) scrollToAnchor(); } -void FrameView::scrollRectIntoViewRecursively(const IntRect& r) -{ - bool wasInProgrammaticScroll = m_inProgrammaticScroll; - m_inProgrammaticScroll = true; - m_maintainScrollPositionAnchor = 0; - ScrollView::scrollRectIntoViewRecursively(r); - m_inProgrammaticScroll = wasInProgrammaticScroll; -} - void FrameView::setScrollPosition(const IntPoint& scrollPoint) { bool wasInProgrammaticScroll = m_inProgrammaticScroll; @@ -1460,7 +1462,7 @@ void FrameView::scrollToAnchor() if (AXObjectCache::accessibilityEnabled()) m_frame->document()->axObjectCache()->handleScrolledToAnchor(anchorNode.get()); - // scrollRectToVisible can call into scrollRectIntoViewRecursively(), which resets m_maintainScrollPositionAnchor. + // scrollRectToVisible can call into setScrollPosition(), which resets m_maintainScrollPositionAnchor. m_maintainScrollPositionAnchor = anchorNode; } @@ -1853,14 +1855,16 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) // m_nodeToDraw is used to draw only one element (and its descendants) RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0; - PaintBehavior paintBehavior = m_paintBehavior; - if (paintBehavior == PaintBehaviorNormal) + PaintBehavior oldPaintBehavior = m_paintBehavior; + if (m_paintBehavior == PaintBehaviorNormal) document->invalidateRenderedRectsForMarkersInRect(rect); if (document->printing()) - paintBehavior |= PaintBehaviorFlattenCompositingLayers; + m_paintBehavior |= PaintBehaviorFlattenCompositingLayers; - contentRenderer->layer()->paint(p, rect, paintBehavior, eltRenderer); + contentRenderer->layer()->paint(p, rect, m_paintBehavior, eltRenderer); + + m_paintBehavior = oldPaintBehavior; m_isPainting = false; m_lastPaintTime = currentTime(); diff --git a/WebCore/page/FrameView.h b/WebCore/page/FrameView.h index cbd0cb9..efceebe 100644 --- a/WebCore/page/FrameView.h +++ b/WebCore/page/FrameView.h @@ -104,6 +104,9 @@ public: // content rendered via the normal painting path. void setNeedsOneShotDrawingSynchronization(); #endif + + bool isEnclosedInCompositingLayer() const; + // Only used with accelerated compositing, but outside the #ifdef to make linkage easier. // Returns true if the sync was completed. bool syncCompositingStateRecursive(); @@ -137,9 +140,8 @@ public: virtual IntRect windowResizerRect() const; - virtual void scrollRectIntoViewRecursively(const IntRect&); - virtual void setScrollPosition(const IntPoint&); - void scrollPositionChanged(); + void setScrollPosition(const IntPoint&); + virtual void scrollPositionChanged(); String mediaType() const; void setMediaType(const String&); diff --git a/WebCore/page/Geolocation.cpp b/WebCore/page/Geolocation.cpp index 36e14f6..88e8941 100644 --- a/WebCore/page/Geolocation.cpp +++ b/WebCore/page/Geolocation.cpp @@ -710,6 +710,8 @@ void Geolocation::handleEvent(ScriptExecutionContext*, Event* event) namespace WebCore { +void Geolocation::clearWatch(int watchId) {} + void Geolocation::disconnectFrame() {} Geolocation::Geolocation(Frame*) {} diff --git a/WebCore/page/Page.cpp b/WebCore/page/Page.cpp index ee5c052..4d7aa7c 100644 --- a/WebCore/page/Page.cpp +++ b/WebCore/page/Page.cpp @@ -420,7 +420,6 @@ void Page::addMediaCanStartListener(MediaCanStartListener* listener) void Page::removeMediaCanStartListener(MediaCanStartListener* listener) { - ASSERT(!m_canStartMedia); ASSERT(m_mediaCanStartListeners.contains(listener)); m_mediaCanStartListeners.remove(listener); } @@ -432,16 +431,14 @@ void Page::setCanStartMedia(bool canStartMedia) m_canStartMedia = canStartMedia; - if (!m_canStartMedia || m_mediaCanStartListeners.isEmpty()) - return; - - Vector<MediaCanStartListener*> listeners; - copyToVector(m_mediaCanStartListeners, listeners); - m_mediaCanStartListeners.clear(); - - size_t size = listeners.size(); - for (size_t i = 0; i < size; ++i) - listeners[i]->mediaCanStart(); + while (m_canStartMedia) { + HashSet<MediaCanStartListener*>::iterator slot = m_mediaCanStartListeners.begin(); + if (slot == m_mediaCanStartListeners.end()) + break; + MediaCanStartListener* listener = *slot; + m_mediaCanStartListeners.remove(slot); + listener->mediaCanStart(); + } } static Frame* incrementFrame(Frame* curr, bool forward, bool wrapFlag) diff --git a/WebCore/page/PrintContext.cpp b/WebCore/page/PrintContext.cpp index e0235de..ffde0be 100644 --- a/WebCore/page/PrintContext.cpp +++ b/WebCore/page/PrintContext.cpp @@ -38,7 +38,8 @@ PrintContext::PrintContext(Frame* frame) PrintContext::~PrintContext() { - ASSERT(!m_isPrinting); + if (m_isPrinting) + end(); m_pageRects.clear(); } @@ -192,10 +193,9 @@ int PrintContext::pageNumberForElement(Element* element, const FloatSize& pageSi for (; pageNumber < printContext.pageCount(); pageNumber++) { const IntRect& page = printContext.pageRect(pageNumber); if (page.x() <= left && left < page.right() && page.y() <= top && top < page.bottom()) - break; + return pageNumber; } - printContext.end(); - return (pageNumber < printContext.pageCount() ? pageNumber : -1); + return -1; } int PrintContext::numberOfPages(Frame* frame, const FloatSize& pageSizeInPixels) @@ -206,7 +206,6 @@ int PrintContext::numberOfPages(Frame* frame, const FloatSize& pageSizeInPixels) PrintContext printContext(frame); printContext.begin(pageRect.width()); printContext.computePageRectsWithPageSize(pageSizeInPixels, false); - printContext.end(); return printContext.pageCount(); } diff --git a/WebCore/page/SecurityOrigin.cpp b/WebCore/page/SecurityOrigin.cpp index 265c643..aab8866 100644 --- a/WebCore/page/SecurityOrigin.cpp +++ b/WebCore/page/SecurityOrigin.cpp @@ -89,6 +89,20 @@ static URLSchemesMap& schemesWithUniqueOrigins() return schemesWithUniqueOrigins; } +static bool schemeRequiresAuthority(const String& scheme) +{ + DEFINE_STATIC_LOCAL(URLSchemesMap, schemes, ()); + + if (schemes.isEmpty()) { + schemes.add("http"); + schemes.add("https"); + schemes.add("ftp"); + } + + return schemes.contains(scheme); +} + + SecurityOrigin::SecurityOrigin(const KURL& url, SandboxFlags sandboxFlags) : m_sandboxFlags(sandboxFlags) , m_protocol(url.protocol().isNull() ? "" : url.protocol().lower()) @@ -103,6 +117,10 @@ SecurityOrigin::SecurityOrigin(const KURL& url, SandboxFlags sandboxFlags) if (m_protocol == "about" || m_protocol == "javascript") m_protocol = ""; + // For edge case URLs that were probably misparsed, make sure that the origin is unique. + if (schemeRequiresAuthority(m_protocol) && m_host.isEmpty()) + m_isUnique = true; + // document.domain starts as m_host, but can be set by the DOM. m_domain = m_host; diff --git a/WebCore/page/SecurityOrigin.h b/WebCore/page/SecurityOrigin.h index d732664..a6c3a7a 100644 --- a/WebCore/page/SecurityOrigin.h +++ b/WebCore/page/SecurityOrigin.h @@ -120,6 +120,11 @@ public: bool canAccessLocalStorage() const { return !isUnique(); } bool canAccessCookies() const { return !isUnique(); } + // Technically, we should always allow access to sessionStorage, but we + // currently don't handle creating a sessionStorage area for unique + // origins. + bool canAccessSessionStorage() const { return !isUnique(); } + bool isSecureTransitionTo(const KURL&) const; // The local SecurityOrigin is the most privileged SecurityOrigin. diff --git a/WebCore/page/Settings.cpp b/WebCore/page/Settings.cpp index 33c9c0d..58c9629 100644 --- a/WebCore/page/Settings.cpp +++ b/WebCore/page/Settings.cpp @@ -96,6 +96,7 @@ Settings::Settings(Page* page) , m_allowUniversalAccessFromFileURLs(true) , m_allowFileAccessFromFileURLs(true) , m_javaScriptCanOpenWindowsAutomatically(false) + , m_javaScriptCanAccessClipboard(false) , m_shouldPrintBackgrounds(false) , m_textAreasAreResizable(false) #if ENABLE(DASHBOARD_SUPPORT) @@ -333,6 +334,11 @@ void Settings::setJavaScriptCanOpenWindowsAutomatically(bool javaScriptCanOpenWi m_javaScriptCanOpenWindowsAutomatically = javaScriptCanOpenWindowsAutomatically; } +void Settings::setJavaScriptCanAccessClipboard(bool javaScriptCanAccessClipboard) +{ + m_javaScriptCanAccessClipboard = javaScriptCanAccessClipboard; +} + void Settings::setDefaultTextEncodingName(const String& defaultTextEncodingName) { m_defaultTextEncodingName = defaultTextEncodingName; diff --git a/WebCore/page/Settings.h b/WebCore/page/Settings.h index 04487b1..5f567c2 100644 --- a/WebCore/page/Settings.h +++ b/WebCore/page/Settings.h @@ -145,6 +145,9 @@ namespace WebCore { void setJavaScriptCanOpenWindowsAutomatically(bool); bool javaScriptCanOpenWindowsAutomatically() const { return m_javaScriptCanOpenWindowsAutomatically; } + void setJavaScriptCanAccessClipboard(bool); + bool javaScriptCanAccessClipboard() const { return m_javaScriptCanAccessClipboard; } + void setSpatialNavigationEnabled(bool); bool isSpatialNavigationEnabled() const { return m_isSpatialNavigationEnabled; } @@ -448,6 +451,7 @@ namespace WebCore { bool m_allowUniversalAccessFromFileURLs: 1; bool m_allowFileAccessFromFileURLs: 1; bool m_javaScriptCanOpenWindowsAutomatically : 1; + bool m_javaScriptCanAccessClipboard : 1; bool m_shouldPrintBackgrounds : 1; bool m_textAreasAreResizable : 1; #if ENABLE(DASHBOARD_SUPPORT) diff --git a/WebCore/page/WindowFeatures.cpp b/WebCore/page/WindowFeatures.cpp index c499a4a..1654ff5 100644 --- a/WebCore/page/WindowFeatures.cpp +++ b/WebCore/page/WindowFeatures.cpp @@ -155,6 +155,8 @@ void WindowFeatures::setWindowFeature(const String& keyString, const String& val fullscreen = value; else if (keyString == "scrollbars") scrollbarsVisible = value; + else if (value == 1) + additionalFeatures.append(keyString); } bool WindowFeatures::boolFeature(const HashMap<String, String>& features, const char* key, bool defaultValue) diff --git a/WebCore/page/WindowFeatures.h b/WebCore/page/WindowFeatures.h index a12cf05..a414552 100644 --- a/WebCore/page/WindowFeatures.h +++ b/WebCore/page/WindowFeatures.h @@ -76,6 +76,8 @@ namespace WebCore { bool fullscreen; bool dialog; + + Vector<String> additionalFeatures; }; } // namespace WebCore diff --git a/WebCore/page/animation/AnimationBase.cpp b/WebCore/page/animation/AnimationBase.cpp index d9282cb..a49c754 100644 --- a/WebCore/page/animation/AnimationBase.cpp +++ b/WebCore/page/animation/AnimationBase.cpp @@ -952,9 +952,6 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) overrideAnimations(); - // Send start event, if needed - onAnimationStart(0); // The elapsedTime is always 0 here - // Start the animation if (overridden()) { // We won't try to start accelerated animations if we are overridden and @@ -987,6 +984,9 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) m_startTime += m_animation->delay(); } + // Now that we know the start time, fire the start event. + onAnimationStart(0); // The elapsedTime is 0. + // Decide whether to go into looping or ending state goIntoEndingOrLoopingState(); diff --git a/WebCore/page/animation/AnimationController.cpp b/WebCore/page/animation/AnimationController.cpp index cb609a5..3761c5a 100644 --- a/WebCore/page/animation/AnimationController.cpp +++ b/WebCore/page/animation/AnimationController.cpp @@ -134,9 +134,16 @@ void AnimationControllerPrivate::updateAnimationTimer(bool callSetChanged/* = fa void AnimationControllerPrivate::updateStyleIfNeededDispatcherFired(Timer<AnimationControllerPrivate>*) { + fireEventsAndUpdateStyle(); +} + +void AnimationControllerPrivate::fireEventsAndUpdateStyle() +{ // Protect the frame from getting destroyed in the event handler RefPtr<Frame> protector = m_frame; + bool updateStyle = !m_eventsToDispatch.isEmpty() || !m_nodeChangesToDispatch.isEmpty(); + // fire all the events Vector<EventToDispatch>::const_iterator eventsToDispatchEnd = m_eventsToDispatch.end(); for (Vector<EventToDispatch>::const_iterator it = m_eventsToDispatch.begin(); it != eventsToDispatchEnd; ++it) { @@ -155,7 +162,7 @@ void AnimationControllerPrivate::updateStyleIfNeededDispatcherFired(Timer<Animat m_nodeChangesToDispatch.clear(); - if (m_frame) + if (updateStyle && m_frame) m_frame->document()->updateStyleIfNeeded(); } @@ -196,6 +203,10 @@ void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPr // When the timer fires, all we do is call setChanged on all DOM nodes with running animations and then do an immediate // updateStyleIfNeeded. It will then call back to us with new information. updateAnimationTimer(true); + + // Fire events right away, to avoid a flash of unanimated style after an animation completes, and before + // the 'end' event fires. + fireEventsAndUpdateStyle(); } bool AnimationControllerPrivate::isAnimatingPropertyOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const diff --git a/WebCore/page/animation/AnimationControllerPrivate.h b/WebCore/page/animation/AnimationControllerPrivate.h index 682dd75..5ef9098 100644 --- a/WebCore/page/animation/AnimationControllerPrivate.h +++ b/WebCore/page/animation/AnimationControllerPrivate.h @@ -92,6 +92,7 @@ public: private: void styleAvailable(); + void fireEventsAndUpdateStyle(); typedef HashMap<RenderObject*, RefPtr<CompositeAnimation> > RenderObjectAnimationMap; diff --git a/WebCore/page/animation/CompositeAnimation.cpp b/WebCore/page/animation/CompositeAnimation.cpp index 0f238fd..7619b1f 100644 --- a/WebCore/page/animation/CompositeAnimation.cpp +++ b/WebCore/page/animation/CompositeAnimation.cpp @@ -205,6 +205,8 @@ void CompositeAnimation::updateKeyframeAnimations(RenderObject* renderer, Render // Toss the animation order map. m_keyframeAnimationOrderMap.clear(); + + DEFINE_STATIC_LOCAL(const AtomicString, none, ("none")); // Now mark any still active animations as active and add any new animations. if (targetStyle->animations()) { @@ -232,7 +234,7 @@ void CompositeAnimation::updateKeyframeAnimations(RenderObject* renderer, Render // Set the saved animation to this new one, just in case the play state has changed. keyframeAnim->setAnimation(anim); keyframeAnim->setIndex(i); - } else if ((anim->duration() || anim->delay()) && anim->iterationCount()) { + } else if ((anim->duration() || anim->delay()) && anim->iterationCount() && animationName != none) { keyframeAnim = KeyframeAnimation::create(const_cast<Animation*>(anim), renderer, i, this, targetStyle); m_keyframeAnimations.set(keyframeAnim->name().impl(), keyframeAnim); } diff --git a/WebCore/page/chromium/EventHandlerChromium.cpp b/WebCore/page/chromium/EventHandlerChromium.cpp index ff161af..bf9acb7 100644 --- a/WebCore/page/chromium/EventHandlerChromium.cpp +++ b/WebCore/page/chromium/EventHandlerChromium.cpp @@ -54,11 +54,12 @@ const double EventHandler::TextDragDelay = 0.0; bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe) { + const PlatformMouseEvent& mouseEvent = mev.event(); // If we're clicking into a frame that is selected, the frame will appear // greyed out even though we're clicking on the selection. This looks // really strange (having the whole frame be greyed out), so we deselect the // selection. - IntPoint p = m_frame->view()->windowToContents(mev.event().pos()); + IntPoint p = m_frame->view()->windowToContents(mouseEvent.pos()); if (m_frame->selection()->contains(p)) { VisiblePosition visiblePos( mev.targetNode()->renderer()->positionForPoint(mev.localPoint())); @@ -67,7 +68,19 @@ bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& m m_frame->selection()->setSelection(newSelection); } - subframe->eventHandler()->handleMousePressEvent(mev.event()); + // If the click hits a scrollbar, we pass the mouse press event to the + // scrollbar directly. This prevents selected text from being unselected. + // This matches the WebKit mac code which passes the mouse press event + // to an NSScroller. + FrameView* view = subframe->view(); + Scrollbar* scrollbar = view ? view->scrollbarAtPoint(mouseEvent.pos()) : 0; + if (scrollbar) { + HitTestRequest request(HitTestRequest::Active); + IntPoint documentPoint = view->windowToContents(mouseEvent.pos()); + MouseEventWithHitTestResults subframeMouseEvent = subframe->document()->prepareMouseEvent(request, documentPoint, mouseEvent); + subframe->eventHandler()->passMousePressEventToScrollbar(subframeMouseEvent, scrollbar); + } else + subframe->eventHandler()->handleMousePressEvent(mouseEvent); return true; } diff --git a/WebCore/page/gtk/EventHandlerGtk.cpp b/WebCore/page/gtk/EventHandlerGtk.cpp index 7051391..0ff67d2 100644 --- a/WebCore/page/gtk/EventHandlerGtk.cpp +++ b/WebCore/page/gtk/EventHandlerGtk.cpp @@ -96,7 +96,7 @@ bool EventHandler::passWheelEventToWidget(PlatformWheelEvent& event, Widget* wid PassRefPtr<Clipboard> EventHandler::createDraggingClipboard() const { - return ClipboardGtk::create(ClipboardWritable, true); + return ClipboardGtk::create(ClipboardWritable, DataObjectGtk::create(), true); } bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe) diff --git a/WebCore/page/mac/DragControllerMac.mm b/WebCore/page/mac/DragControllerMac.mm index f080232..a09c418 100644 --- a/WebCore/page/mac/DragControllerMac.mm +++ b/WebCore/page/mac/DragControllerMac.mm @@ -42,20 +42,6 @@ const int DragController::DragIconBottomInset = 3; const float DragController::DragImageAlpha = 0.75f; -#if ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) - -DragOperation DragController::dragOperation(DragData*) -{ - return DragOperationNone; -} - -bool DragController::isCopyKeyDown() -{ - return false; -} - -#else - bool DragController::isCopyKeyDown() { return [[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask; @@ -74,8 +60,6 @@ DragOperation DragController::dragOperation(DragData* dragData) return DragOperationNone; } -#endif - const IntSize& DragController::maxDragImageSize() { static const IntSize maxDragImageSize(400, 400); diff --git a/WebCore/page/mac/EventHandlerMac.mm b/WebCore/page/mac/EventHandlerMac.mm index 650c0e1..8842e31 100644 --- a/WebCore/page/mac/EventHandlerMac.mm +++ b/WebCore/page/mac/EventHandlerMac.mm @@ -66,8 +66,6 @@ namespace WebCore { const double EventHandler::TextDragDelay = 0.15; #endif -#if !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) - static RetainPtr<NSEvent>& currentNSEventSlot() { DEFINE_STATIC_LOCAL(RetainPtr<NSEvent>, event, ()); @@ -661,119 +659,6 @@ bool EventHandler::eventActivatedView(const PlatformMouseEvent& event) const return m_activationEventNumber == event.eventNumber(); } -#else // ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) - -NSEvent *EventHandler::currentNSEvent() -{ - return 0; -} - -bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe) -{ - subframe->eventHandler()->handleMousePressEvent(mev.event()); - return true; -} - -bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe, HitTestResult* hoveredNode) -{ - if (m_mouseDownMayStartDrag && !m_mouseDownWasInSubframe) - return false; - subframe->eventHandler()->handleMouseMoveEvent(mev.event(), hoveredNode); - return true; -} - -bool EventHandler::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe) -{ - subframe->eventHandler()->handleMouseReleaseEvent(mev.event()); - return true; -} - -bool EventHandler::passWheelEventToWidget(PlatformWheelEvent& wheelEvent, Widget* widget) -{ - if (!widget->isFrameView()) - return false; - - return static_cast<FrameView*>(widget)->frame()->eventHandler()->handleWheelEvent(wheelEvent); -} - -void EventHandler::focusDocumentView() -{ - Page* page = m_frame->page(); - if (!page) - return; - page->focusController()->setFocusedFrame(m_frame); -} - -bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults&) -{ - notImplemented(); - return false; -} - -bool EventHandler::eventActivatedView(const PlatformMouseEvent&) const -{ - notImplemented(); - return false; -} - -PassRefPtr<KeyboardEvent> EventHandler::currentKeyboardEvent() const -{ - return 0; -} - -void EventHandler::mouseDown(NSEvent *) -{ - notImplemented(); -} - -void EventHandler::mouseDragged(NSEvent *) -{ - notImplemented(); -} - -void EventHandler::mouseUp(NSEvent *) -{ - notImplemented(); -} - -void EventHandler::mouseMoved(NSEvent *) -{ - notImplemented(); -} - -bool EventHandler::keyEvent(NSEvent *) -{ - notImplemented(); - return false; -} - -bool EventHandler::wheelEvent(NSEvent *) -{ - notImplemented(); - return false; -} - -#if ENABLE(CONTEXT_MENUS) -bool EventHandler::sendContextMenuEvent(NSEvent *) -{ - notImplemented(); - return false; -} -#endif - -bool EventHandler::eventMayStartDrag(NSEvent *) -{ - notImplemented(); - return false; -} - -void EventHandler::sendFakeEventsAfterWidgetTracking(NSEvent *) -{ -} - - -#endif - #if ENABLE(DRAG_SUPPORT) PassRefPtr<Clipboard> EventHandler::createDraggingClipboard() const diff --git a/WebCore/page/qt/EventHandlerQt.cpp b/WebCore/page/qt/EventHandlerQt.cpp index d7982fa..5b24eae 100644 --- a/WebCore/page/qt/EventHandlerQt.cpp +++ b/WebCore/page/qt/EventHandlerQt.cpp @@ -51,7 +51,7 @@ #include "NotImplemented.h" QT_BEGIN_NAMESPACE -extern Q_GUI_EXPORT bool qt_tab_all_widgets; // from qapplication.cpp +Q_GUI_EXPORT extern bool qt_tab_all_widgets; // from qapplication.cpp QT_END_NAMESPACE namespace WebCore { diff --git a/WebCore/platform/Arena.h b/WebCore/platform/Arena.h index 4c9ecf4..b485fc1 100644 --- a/WebCore/platform/Arena.h +++ b/WebCore/platform/Arena.h @@ -44,7 +44,7 @@ namespace WebCore { -typedef unsigned long uword; +typedef uintptr_t uword; struct Arena { Arena* next; // next arena diff --git a/WebCore/platform/HostWindow.h b/WebCore/platform/HostWindow.h index dc681a1..e7316a7 100644 --- a/WebCore/platform/HostWindow.h +++ b/WebCore/platform/HostWindow.h @@ -54,10 +54,6 @@ public: // Method for retrieving the native client of the page. virtual PlatformPageClient platformPageClient() const = 0; - // For scrolling a rect into view recursively. Useful in the cases where a WebView is embedded inside some containing - // platform-specific ScrollView. - virtual void scrollRectIntoView(const IntRect&, const ScrollView*) const = 0; - // To notify WebKit of scrollbar mode changes. virtual void scrollbarsModeDidChange() const = 0; }; diff --git a/WebCore/platform/KURL.cpp b/WebCore/platform/KURL.cpp index 12ba4a2..9ed900f 100644 --- a/WebCore/platform/KURL.cpp +++ b/WebCore/platform/KURL.cpp @@ -1353,27 +1353,29 @@ bool protocolHostAndPortAreEqual(const KURL& a, const KURL& b) { if (a.m_schemeEnd != b.m_schemeEnd) return false; + int hostStartA = a.hostStart(); + int hostLengthA = a.hostEnd() - hostStartA; int hostStartB = b.hostStart(); - if (a.m_hostEnd - hostStartA != b.m_hostEnd - hostStartB) + int hostLengthB = b.hostEnd() - b.hostStart(); + if (hostLengthA != hostLengthB) return false; // Check the scheme for (int i = 0; i < a.m_schemeEnd; ++i) if (a.string()[i] != b.string()[i]) return false; - + // And the host - for (int i = hostStartA; i < a.m_hostEnd; ++i) - if (a.string()[i] != b.string()[i]) + for (int i = 0; i < hostLengthA; ++i) + if (a.string()[hostStartA + i] != b.string()[hostStartB + i]) return false; - + if (a.port() != b.port()) return false; return true; } - String encodeWithURLEscapeSequences(const String& notEncodedString) { diff --git a/WebCore/platform/KURLGoogle.cpp b/WebCore/platform/KURLGoogle.cpp index 97446bd..b4c84a6 100644 --- a/WebCore/platform/KURLGoogle.cpp +++ b/WebCore/platform/KURLGoogle.cpp @@ -1144,8 +1144,10 @@ bool protocolHostAndPortAreEqual(const KURL& a, const KURL& b) return false; int hostStartA = a.hostStart(); + int hostLengthA = a.hostEnd() - hostStartA; int hostStartB = b.hostStart(); - if (a.hostEnd() - hostStartA != b.hostEnd() - hostStartB) + int hostLengthB = b.hostEnd() - b.hostStart(); + if (hostLengthA != hostLengthB) return false; // Check the scheme @@ -1154,8 +1156,8 @@ bool protocolHostAndPortAreEqual(const KURL& a, const KURL& b) return false; // And the host - for (int i = hostStartA; i < static_cast<int>(a.hostEnd()); ++i) - if (a.string()[i] != b.string()[i]) + for (int i = 0; i < hostLengthA; ++i) + if (a.string()[hostStartA + i] != b.string()[hostStartB + i]) return false; if (a.port() != b.port()) diff --git a/WebCore/platform/LinkHash.cpp b/WebCore/platform/LinkHash.cpp index 0bd589c..12437ab 100644 --- a/WebCore/platform/LinkHash.cpp +++ b/WebCore/platform/LinkHash.cpp @@ -147,12 +147,17 @@ static inline bool needsTrailingSlash(const UChar* characters, unsigned length) return pos == length; } +static ALWAYS_INLINE LinkHash visitedLinkHashInline(const UChar* url, unsigned length) +{ + return AlreadyHashed::avoidDeletedValue(StringImpl::computeHash(url, length)); +} + LinkHash visitedLinkHash(const UChar* url, unsigned length) { - return AlreadyHashed::avoidDeletedValue(StringImpl::computeHash(url, length)); + return visitedLinkHashInline(url, length); } -void visitedURL(const KURL& base, const AtomicString& attributeURL, Vector<UChar, 512>& buffer) +static ALWAYS_INLINE void visitedURLInline(const KURL& base, const AtomicString& attributeURL, Vector<UChar, 512>& buffer) { if (attributeURL.isNull()) return; @@ -213,14 +218,19 @@ void visitedURL(const KURL& base, const AtomicString& attributeURL, Vector<UChar return; } +void visitedURL(const KURL& base, const AtomicString& attributeURL, Vector<UChar, 512>& buffer) +{ + return visitedURLInline(base, attributeURL, buffer); +} + LinkHash visitedLinkHash(const KURL& base, const AtomicString& attributeURL) { Vector<UChar, 512> url; - visitedURL(base, attributeURL, url); + visitedURLInline(base, attributeURL, url); if (url.isEmpty()) return 0; - return visitedLinkHash(url.data(), url.size()); + return visitedLinkHashInline(url.data(), url.size()); } } // namespace WebCore diff --git a/WebCore/platform/ScrollView.cpp b/WebCore/platform/ScrollView.cpp index 28f9c2f..f0e705e 100644 --- a/WebCore/platform/ScrollView.cpp +++ b/WebCore/platform/ScrollView.cpp @@ -292,9 +292,11 @@ void ScrollView::valueChanged(Scrollbar* scrollbar) if (scrollbarsSuppressed()) return; + scrollPositionChanged(); scrollContents(scrollDelta); } +<<<<<<< HEAD:WebCore/platform/ScrollView.cpp void ScrollView::scrollRectIntoViewRecursively(const IntRect& r) { #if PLATFORM(ANDROID) @@ -325,6 +327,8 @@ void ScrollView::scrollRectIntoViewRecursively(const IntRect& r) hostWindow()->scrollRectIntoView(rect, this); } +======= +>>>>>>> webkit.org at r58956:WebCore/platform/ScrollView.cpp void ScrollView::setScrollPosition(const IntPoint& scrollPoint) { if (prohibitsScrolling()) diff --git a/WebCore/platform/ScrollView.h b/WebCore/platform/ScrollView.h index 52afbf9..b103d22 100644 --- a/WebCore/platform/ScrollView.h +++ b/WebCore/platform/ScrollView.h @@ -57,31 +57,31 @@ class ScrollView : public Widget, public ScrollbarClient { public: ~ScrollView(); - // ScrollbarClient method. FrameView overrides the other two. + // ScrollbarClient function. FrameView overrides the other two. virtual void valueChanged(Scrollbar*); - // The window thats hosts the ScrollView. The ScrollView will communicate scrolls and repaints to the + // The window thats hosts the ScrollView. The ScrollView will communicate scrolls and repaints to the // host window in the window's coordinate space. virtual HostWindow* hostWindow() const = 0; - // Returns a clip rect in host window coordinates. Used to clip the blit on a scroll. + // Returns a clip rect in host window coordinates. Used to clip the blit on a scroll. virtual IntRect windowClipRect(bool clipToContents = true) const = 0; - // Methods for child manipulation and inspection. + // Functions for child manipulation and inspection. const HashSet<RefPtr<Widget> >* children() const { return &m_children; } void addChild(PassRefPtr<Widget>); void removeChild(Widget*); - // If the scroll view does not use a native widget, then it will have cross-platform Scrollbars. These methods + // If the scroll view does not use a native widget, then it will have cross-platform Scrollbars. These functions // can be used to obtain those scrollbars. Scrollbar* horizontalScrollbar() const { return m_horizontalScrollbar.get(); } Scrollbar* verticalScrollbar() const { return m_verticalScrollbar.get(); } bool isScrollViewScrollbar(const Widget* child) const { return horizontalScrollbar() == child || verticalScrollbar() == child; } - // Methods for setting and retrieving the scrolling mode in each axis (horizontal/vertical). The mode has values of - // AlwaysOff, AlwaysOn, and Auto. AlwaysOff means never show a scrollbar, AlwaysOn means always show a scrollbar. + // Functions for setting and retrieving the scrolling mode in each axis (horizontal/vertical). The mode has values of + // AlwaysOff, AlwaysOn, and Auto. AlwaysOff means never show a scrollbar, AlwaysOn means always show a scrollbar. // Auto means show a scrollbar only when one is needed. - // Note that for platforms with native widgets, these modes are considered advisory. In other words the underlying native + // Note that for platforms with native widgets, these modes are considered advisory. In other words the underlying native // widget may choose not to honor the requested modes. void setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode, bool horizontalLock = false, bool verticalLock = false); void setHorizontalScrollbarMode(ScrollbarMode mode, bool lock = false) { setScrollbarModes(mode, verticalScrollbarMode(), lock, verticalScrollbarLock()); } @@ -103,7 +103,7 @@ public: virtual bool avoidScrollbarCreation() { return false; } // By default you only receive paint events for the area that is visible. In the case of using a - // tiled backing store, this method can be set, so that the view paints the entire contents. + // tiled backing store, this function can be set, so that the view paints the entire contents. bool paintsEntireContents() const { return m_paintsEntireContents; } void setPaintsEntireContents(bool); @@ -114,20 +114,20 @@ public: void setProhibitsScrolling(bool b) { m_prohibitsScrolling = b; } bool prohibitsScrolling() const { return m_prohibitsScrolling; } - // Whether or not a scroll view will blit visible contents when it is scrolled. Blitting is disabled in situations + // Whether or not a scroll view will blit visible contents when it is scrolled. Blitting is disabled in situations // where it would cause rendering glitches (such as with fixed backgrounds or when the view is partially transparent). void setCanBlitOnScroll(bool); bool canBlitOnScroll() const; // The visible content rect has a location that is the scrolled offset of the document. The width and height are the viewport width - // and height. By default the scrollbars themselves are excluded from this rectangle, but an optional boolean argument allows them to be + // and height. By default the scrollbars themselves are excluded from this rectangle, but an optional boolean argument allows them to be // included. IntRect visibleContentRect(bool includeScrollbars = false) const; int visibleWidth() const { return visibleContentRect().width(); } int visibleHeight() const { return visibleContentRect().height(); } - // Methods for getting/setting the size webkit should use to layout the contents. By default this is the same as the visible - // content size. Explicitly setting a layout size value will cause webkit to layout the contents using this size instead. + // Functions for getting/setting the size webkit should use to layout the contents. By default this is the same as the visible + // content size. Explicitly setting a layout size value will cause webkit to layout the contents using this size instead. int layoutWidth() const; int layoutHeight() const; IntSize fixedLayoutSize() const; @@ -135,27 +135,25 @@ public: bool useFixedLayout() const; void setUseFixedLayout(bool enable); - // Methods for getting/setting the size of the document contained inside the ScrollView (as an IntSize or as individual width and height + // Functions for getting/setting the size of the document contained inside the ScrollView (as an IntSize or as individual width and height // values). IntSize contentsSize() const; // Always at least as big as the visibleWidth()/visibleHeight(). int contentsWidth() const { return contentsSize().width(); } int contentsHeight() const { return contentsSize().height(); } virtual void setContentsSize(const IntSize&); - // Methods for querying the current scrolled position (both as a point, a size, or as individual X and Y values). + // Functions for querying the current scrolled position (both as a point, a size, or as individual X and Y values). IntPoint scrollPosition() const { return visibleContentRect().location(); } IntSize scrollOffset() const { return visibleContentRect().location() - IntPoint(); } // Gets the scrolled position as an IntSize. Convenient for adding to other sizes. IntPoint maximumScrollPosition() const; // The maximum position we can be scrolled to. int scrollX() const { return scrollPosition().x(); } int scrollY() const { return scrollPosition().y(); } - // Methods for scrolling the view. setScrollPosition is the only method that really scrolls the view. The other two methods are helper functions - // that ultimately end up calling setScrollPosition. + // Functions for scrolling the view. void setScrollPosition(const IntPoint&); void scrollBy(const IntSize& s) { return setScrollPosition(scrollPosition() + s); } - void scrollRectIntoViewRecursively(const IntRect&); - - // This method scrolls by lines, pages or pixels. + + // This function scrolls by lines, pages or pixels. bool scroll(ScrollDirection, ScrollGranularity); // Scroll the actual contents of the view (either blitting or invalidating as needed). @@ -173,15 +171,15 @@ public: IntRect windowToContents(const IntRect&) const; IntRect contentsToWindow(const IntRect&) const; - // Methods for converting to and from screen coordinates. + // Functions for converting to and from screen coordinates. IntRect contentsToScreen(const IntRect&) const; IntPoint screenToContents(const IntPoint&) const; - // The purpose of this method is to answer whether or not the scroll view is currently visible. Animations and painting updates can be suspended if + // The purpose of this function is to answer whether or not the scroll view is currently visible. Animations and painting updates can be suspended if // we know that we are either not in a window right now or if that window is not visible. bool isOffscreen() const; - // These methods are used to enable scrollbars to avoid window resizer controls that overlap the scroll view. This happens on Mac + // These functions are used to enable scrollbars to avoid window resizer controls that overlap the scroll view. This happens on Mac // for example. virtual IntRect windowResizerRect() const { return IntRect(); } bool containsScrollbarsAvoidingResizer() const; @@ -197,9 +195,9 @@ public: // For platforms that need to hit test scrollbars from within the engine's event handlers (like Win32). Scrollbar* scrollbarAtPoint(const IntPoint& windowPoint); - // This method exists for scrollviews that need to handle wheel events manually. + // This function exists for scrollviews that need to handle wheel events manually. // On Mac the underlying NSScrollView just does the scrolling, but on other platforms - // (like Windows), we need this method in order to do the scroll ourselves. + // (like Windows), we need this function in order to do the scroll ourselves. void wheelEvent(PlatformWheelEvent&); IntPoint convertChildToSelf(const Widget* child, const IntPoint& point) const @@ -220,7 +218,7 @@ public: return newPoint; } - // Widget override. Handles painting of the contents of the view as well as the scrollbars. + // Widget override. Handles painting of the contents of the view as well as the scrollbars. virtual void paint(GraphicsContext*, const IntRect&); void paintScrollbars(GraphicsContext*, const IntRect&); @@ -252,7 +250,7 @@ protected: virtual void contentsResized() = 0; virtual void visibleContentsResized() = 0; - // These methods are used to create/destroy scrollbars. + // These functions are used to create/destroy scrollbars. void setHasHorizontalScrollbar(bool); void setHasVerticalScrollbar(bool); @@ -299,6 +297,9 @@ private: // Called to update the scrollbars to accurately reflect the state of the view. void updateScrollbars(const IntSize& desiredOffset); + // Called when the scroll position within this view changes. FrameView overrides this to generate repaint invalidations. + virtual void scrollPositionChanged() {} + void platformInit(); void platformDestroy(); void platformAddChild(Widget*); diff --git a/WebCore/platform/ThemeTypes.h b/WebCore/platform/ThemeTypes.h index 07a11fb..de71899 100644 --- a/WebCore/platform/ThemeTypes.h +++ b/WebCore/platform/ThemeTypes.h @@ -52,7 +52,7 @@ enum ControlPart { MediaSeekForwardButtonPart, MediaRewindButtonPart, MediaReturnToRealtimeButtonPart, MediaToggleClosedCaptionsButtonPart, MediaSliderPart, MediaSliderThumbPart, MediaVolumeSliderContainerPart, MediaVolumeSliderPart, MediaVolumeSliderThumbPart, MediaControlsBackgroundPart, MediaCurrentTimePart, MediaTimeRemainingPart, - MenulistPart, MenulistButtonPart, MenulistTextPart, MenulistTextFieldPart, OuterSpinButtonPart, ProgressBarPart, + MenulistPart, MenulistButtonPart, MenulistTextPart, MenulistTextFieldPart, OuterSpinButtonPart, ProgressBarPart, ProgressBarValuePart, SliderHorizontalPart, SliderVerticalPart, SliderThumbHorizontalPart, SliderThumbVerticalPart, CaretPart, SearchFieldPart, SearchFieldDecorationPart, SearchFieldResultsDecorationPart, SearchFieldResultsButtonPart, diff --git a/WebCore/platform/ThreadGlobalData.cpp b/WebCore/platform/ThreadGlobalData.cpp index 434ee5a..99cd44a 100644 --- a/WebCore/platform/ThreadGlobalData.cpp +++ b/WebCore/platform/ThreadGlobalData.cpp @@ -69,7 +69,7 @@ ThreadGlobalData::ThreadGlobalData() #endif { // This constructor will have been called on the main thread before being called on - // any other thread, and is only called once per thread – this makes this a convenient + // any other thread, and is only called once per thread - this makes this a convenient // point to call methods that internally perform a one-time initialization that is not // threadsafe. wtfThreadData(); @@ -78,14 +78,25 @@ ThreadGlobalData::ThreadGlobalData() ThreadGlobalData::~ThreadGlobalData() { + destroy(); +} + +void ThreadGlobalData::destroy() +{ #if PLATFORM(MAC) delete m_cachedConverterTEC; + m_cachedConverterTEC = 0; #endif + #if USE(ICU_UNICODE) delete m_cachedConverterICU; + m_cachedConverterICU = 0; #endif + delete m_eventNames; + m_eventNames = 0; delete m_threadTimers; + m_threadTimers = 0; } } // namespace WebCore diff --git a/WebCore/platform/ThreadGlobalData.h b/WebCore/platform/ThreadGlobalData.h index 3d73932..c17fbeb 100644 --- a/WebCore/platform/ThreadGlobalData.h +++ b/WebCore/platform/ThreadGlobalData.h @@ -49,6 +49,7 @@ namespace WebCore { public: ThreadGlobalData(); ~ThreadGlobalData(); + void destroy(); // called on workers to clean up the ThreadGlobalData before the thread exits. EventNames& eventNames() { return *m_eventNames; } ThreadTimers& threadTimers() { return *m_threadTimers; } diff --git a/WebCore/platform/UUID.cpp b/WebCore/platform/UUID.cpp index d8ac749..852e3ae 100644 --- a/WebCore/platform/UUID.cpp +++ b/WebCore/platform/UUID.cpp @@ -33,6 +33,10 @@ #include "NotImplemented.h" +#if PLATFORM(QT) +#include <QUuid> +#endif + #if OS(WINDOWS) #include <objbase.h> #ifndef ARRAYSIZE @@ -51,7 +55,12 @@ static const int uuidVersionIdentifierIndex = 14; String createCanonicalUUIDString() { -#if OS(WINDOWS) +#if PLATFORM(QT) + QUuid uuid = QUuid::createUuid(); + String canonicalUuidStr = uuid.toString().mid(1, 36).toLower(); // remove opening and closing bracket and make it lower. + ASSERT(canonicalUuidStr[uuidVersionIdentifierIndex] == uuidVersionRequired); + return canonicalUuidStr; +#elif OS(WINDOWS) GUID uuid = { 0 }; HRESULT hr = CoCreateGuid(&uuid); if (FAILED(hr)) @@ -76,7 +85,8 @@ String createCanonicalUUIDString() if (!fptr) return String(); char uuidStr[37] = {0}; - fgets(uuidStr, sizeof(uuidStr) - 1, fptr); + if (!fgets(uuidStr, sizeof(uuidStr) - 1, fptr)) + return String(); fclose(fptr); String canonicalUuidStr = String(uuidStr).lower(); // make it lower. ASSERT(canonicalUuidStr[uuidVersionIdentifierIndex] == uuidVersionRequired); diff --git a/WebCore/platform/Widget.cpp b/WebCore/platform/Widget.cpp index 520eb6f..1370863 100644 --- a/WebCore/platform/Widget.cpp +++ b/WebCore/platform/Widget.cpp @@ -174,4 +174,10 @@ IntPoint Widget::convertFromContainingView(const IntPoint& parentPoint) const return parentPoint; } +#if !PLATFORM(EFL) +void Widget::frameRectsChanged() +{ +} +#endif + } // namespace WebCore diff --git a/WebCore/platform/Widget.h b/WebCore/platform/Widget.h index 2fce858..23d228e 100644 --- a/WebCore/platform/Widget.h +++ b/WebCore/platform/Widget.h @@ -77,6 +77,12 @@ typedef BView* PlatformWidget; #include "PlatformWidget.h" #endif +#if PLATFORM(EFL) +#include <Ecore_Evas.h> +#include <Evas.h> +typedef Evas_Object* PlatformWidget; +#endif + #if PLATFORM(QT) class QWebPageClient; typedef QWebPageClient* PlatformPageClient; @@ -99,6 +105,9 @@ class GraphicsContext; class PlatformMouseEvent; class ScrollView; class WidgetPrivate; +#if PLATFORM(EFL) +class String; +#endif // The Widget class serves as a base class for three kinds of objects: // (1) Scrollable areas (ScrollView) @@ -157,7 +166,7 @@ public: void invalidate() { invalidateRect(boundsRect()); } virtual void invalidateRect(const IntRect&) = 0; - virtual void setFocus(); + virtual void setFocus(bool); void setCursor(const Cursor&); @@ -194,7 +203,7 @@ public: IntPoint convertToContainingWindow(const IntPoint&) const; IntPoint convertFromContainingWindow(const IntPoint&) const; - virtual void frameRectsChanged() {} + virtual void frameRectsChanged(); // Notifies this widget that other widgets on the page have been repositioned. virtual void widgetPositionsUpdated() {} @@ -208,6 +217,20 @@ public: void removeFromSuperview(); #endif +#if PLATFORM(EFL) + // FIXME: These should really go to PlatformWidget. They're here currently since + // the EFL port considers that Evas_Object (a C object) is a PlatformWidget, but + // encapsulating that into a C++ class will make this header clean as it should be. + Evas* evas() const; + + void setEvasObject(Evas_Object*); + Evas_Object* evasObject() const; + + const String edjeTheme() const; + void setEdjeTheme(const String &); + const String edjeThemeRecursive() const; +#endif + // Virtual methods to convert points to/from the containing ScrollView virtual IntRect convertToContainingView(const IntRect&) const; virtual IntRect convertFromContainingView(const IntRect&) const; @@ -236,9 +259,18 @@ private: IntRect m_frame; // Not used when a native widget exists. -#if PLATFORM(MAC) +#if PLATFORM(EFL) + // FIXME: Please see the previous #if PLATFORM(EFL) block. + Ecore_Evas* ecoreEvas() const; + + void applyFallbackCursor(); + void applyCursor(); +#endif + +#if PLATFORM(MAC) || PLATFORM(EFL) WidgetPrivate* m_data; #endif + #if PLATFORM(HAIKU) PlatformWidget m_topLevelPlatformWidget; #endif diff --git a/WebCore/platform/android/FileSystemAndroid.cpp b/WebCore/platform/android/FileSystemAndroid.cpp index 3d841d7..520bc7d 100644 --- a/WebCore/platform/android/FileSystemAndroid.cpp +++ b/WebCore/platform/android/FileSystemAndroid.cpp @@ -75,6 +75,23 @@ bool unloadModule(PlatformModule module) return !dlclose(module); } +<<<<<<< HEAD:WebCore/platform/android/FileSystemAndroid.cpp +======= +int writeToFile(PlatformFileHandle handle, const char* data, int length) +{ + int totalBytesWritten = 0; + while (totalBytesWritten < length) { + int bytesWritten = write(handle, data, (size_t)(length - totalBytesWritten)); + if (bytesWritten < 0 && errno != EINTR) + return -1; + if (bytesWritten > 0) + totalBytesWritten += bytesWritten; + } + + return totalBytesWritten; +} + +>>>>>>> webkit.org at r58956:WebCore/platform/android/FileSystemAndroid.cpp String homeDirectoryPath() { return sPluginPath; diff --git a/WebCore/platform/android/WidgetAndroid.cpp b/WebCore/platform/android/WidgetAndroid.cpp index 9ab0b2c..14da0ca 100644 --- a/WebCore/platform/android/WidgetAndroid.cpp +++ b/WebCore/platform/android/WidgetAndroid.cpp @@ -54,7 +54,7 @@ IntRect Widget::frameRect() const return platformWidget()->getBounds(); } -void Widget::setFocus() +void Widget::setFocus(bool focused) { notImplemented(); } diff --git a/WebCore/platform/chromium/ChromiumBridge.h b/WebCore/platform/chromium/ChromiumBridge.h index e582241..6eca3eb 100644 --- a/WebCore/platform/chromium/ChromiumBridge.h +++ b/WebCore/platform/chromium/ChromiumBridge.h @@ -109,6 +109,12 @@ namespace WebCore { static String getAbsolutePath(const String&); static bool isDirectory(const String&); static KURL filePathToURL(const String&); + static PlatformFileHandle openFile(const String& path, FileOpenMode); + static void closeFile(PlatformFileHandle&); + static long long seekFile(PlatformFileHandle, long long offset, FileSeekOrigin); + static bool truncateFile(PlatformFileHandle, long long offset); + static int readFromFile(PlatformFileHandle, char* data, int length); + static int writeToFile(PlatformFileHandle, const char* data, int length); // Font --------------------------------------------------------------- #if OS(WINDOWS) diff --git a/WebCore/platform/chromium/ChromiumDataObject.h b/WebCore/platform/chromium/ChromiumDataObject.h index 625cb8c..af0a3fa 100644 --- a/WebCore/platform/chromium/ChromiumDataObject.h +++ b/WebCore/platform/chromium/ChromiumDataObject.h @@ -79,6 +79,8 @@ namespace WebCore { { url = newURL; uriList.clear(); + if (newURL.isEmpty()) + return; uriList.append(newURL.string()); } diff --git a/WebCore/platform/chromium/ClipboardChromium.cpp b/WebCore/platform/chromium/ClipboardChromium.cpp index 21d7edf..ab9f3c9 100644 --- a/WebCore/platform/chromium/ClipboardChromium.cpp +++ b/WebCore/platform/chromium/ClipboardChromium.cpp @@ -162,25 +162,21 @@ String ClipboardChromium::getData(const String& type, bool& success) const case ClipboardDataTypeNone: return String(); + // Hack for URLs. file URLs are used internally for drop's default action, but we don't want + // to expose them to the page, so we filter them out here. case ClipboardDataTypeURIList: { String text; for (size_t i = 0; i < m_dataObject->uriList.size(); ++i) { const String& uri = m_dataObject->uriList[i]; + if (protocolIs(uri, "file")) + continue; ASSERT(!uri.isEmpty()); if (!text.isEmpty()) text.append(textMIMETypeLineSeparator); // URIs have already been canonicalized, so copy everything verbatim. text.append(uri); } - // Also create file:// URLs out of the entries in the file list. - for (size_t i = 0; i < m_dataObject->filenames.size(); ++i) { - String fileURL = ChromiumBridge::filePathToURL(m_dataObject->filenames[i]); - ASSERT(!fileURL.isEmpty()); - if (!text.isEmpty()) - text.append(textMIMETypeLineSeparator); - text.append(fileURL); - } success = !text.isEmpty(); return text; } @@ -188,15 +184,10 @@ String ClipboardChromium::getData(const String& type, bool& success) const case ClipboardDataTypeURL: // In case of a previous setData('text/uri-list'), setData() has already // prepared the 'url' member, so we can just retrieve it here. - if (!m_dataObject->url.isEmpty()) { + if (!m_dataObject->url.isEmpty() && !m_dataObject->url.isLocalFile()) { success = true; return m_dataObject->url.string(); } - // Otherwise check if we have a file that we could convert to a file:// URL. - if (!m_dataObject->filenames.isEmpty()) { - success = true; - return ChromiumBridge::filePathToURL(m_dataObject->filenames[0]); - } return String(); case ClipboardDataTypeDownloadURL: @@ -326,20 +317,27 @@ HashSet<String> ClipboardChromium::types() const if (!m_dataObject) return results; - if (!m_dataObject->filenames.isEmpty()) { - results.add("text/uri-list"); + if (!m_dataObject->filenames.isEmpty()) results.add("Files"); - } - if (m_dataObject->url.isValid()) { + // Hack for URLs. file URLs are used internally for drop's default action, but we don't want + // to expose them to the page, so we filter them out here. + if (m_dataObject->url.isValid() && !m_dataObject->url.isLocalFile()) { ASSERT(!m_dataObject->uriList.isEmpty()); results.add("URL"); } if (!m_dataObject->uriList.isEmpty()) { - // Note that even if the URI list is not empty, it may not actually - // contain a valid URL, so we can't return "URL" here. - results.add("text/uri-list"); + // Verify that the URI list contains at least one non-file URL. + for (Vector<String>::const_iterator it = m_dataObject->uriList.begin(); + it != m_dataObject->uriList.end(); ++it) { + if (!protocolIs(*it, "file")) { + // Note that even if the URI list is not empty, it may not actually + // contain a valid URL, so we can't return "URL" here. + results.add("text/uri-list"); + break; + } + } } if (!m_dataObject->plainText.isEmpty()) { diff --git a/WebCore/platform/chromium/DragImageChromiumSkia.cpp b/WebCore/platform/chromium/DragImageChromiumSkia.cpp index 24bd8fd..e5c1cee 100644 --- a/WebCore/platform/chromium/DragImageChromiumSkia.cpp +++ b/WebCore/platform/chromium/DragImageChromiumSkia.cpp @@ -68,9 +68,26 @@ DragImageRef scaleDragImage(DragImageRef image, FloatSize scale) return scaledImage; } -DragImageRef dissolveDragImageToFraction(DragImageRef image, float) +DragImageRef dissolveDragImageToFraction(DragImageRef image, float fraction) { - notImplemented(); + if (!image) + return 0; + + image->setIsOpaque(false); + image->lockPixels(); + + for (int row = 0; row < image->height(); ++row) { + for (int column = 0; column < image->width(); ++column) { + uint32_t* pixel = image->getAddr32(column, row); + *pixel = SkPreMultiplyARGB(SkColorGetA(*pixel) * fraction, + SkColorGetR(*pixel), + SkColorGetG(*pixel), + SkColorGetB(*pixel)); + } + } + + image->unlockPixels(); + return image; } @@ -80,7 +97,12 @@ DragImageRef createDragImageFromImage(Image* image) return 0; NativeImageSkia* bitmap = image->nativeImageForCurrentFrame(); - return bitmap ? new SkBitmap(*bitmap) : 0; + if (!bitmap) + return 0; + + SkBitmap* dragImage = new SkBitmap(); + bitmap->copyTo(dragImage, SkBitmap::kARGB_8888_Config); + return dragImage; } DragImageRef createDragImageIconForCachedImage(CachedImage*) diff --git a/WebCore/platform/chromium/FileSystemChromium.cpp b/WebCore/platform/chromium/FileSystemChromium.cpp index 30674d9..975caf6 100644 --- a/WebCore/platform/chromium/FileSystemChromium.cpp +++ b/WebCore/platform/chromium/FileSystemChromium.cpp @@ -77,4 +77,34 @@ bool fileExists(const String& path) return ChromiumBridge::fileExists(path); } +PlatformFileHandle openFile(const String& path, FileOpenMode mode) +{ + return ChromiumBridge::openFile(path, mode); +} + +void closeFile(PlatformFileHandle& handle) +{ + return ChromiumBridge::closeFile(handle); +} + +long long seekFile(PlatformFileHandle handle, long long offset, FileSeekOrigin origin) +{ + return ChromiumBridge::seekFile(handle, offset, origin); +} + +bool truncateFile(PlatformFileHandle handle, long long offset) +{ + return ChromiumBridge::truncateFile(handle, offset); +} + +int readFromFile(PlatformFileHandle handle, char* data, int length) +{ + return ChromiumBridge::readFromFile(handle, data, length); +} + +int writeToFile(PlatformFileHandle handle, const char* data, int length) +{ + return ChromiumBridge::writeToFile(handle, data, length); +} + } // namespace WebCore diff --git a/WebCore/platform/chromium/WidgetChromium.cpp b/WebCore/platform/chromium/WidgetChromium.cpp index 4e16e68..94afa0d 100644 --- a/WebCore/platform/chromium/WidgetChromium.cpp +++ b/WebCore/platform/chromium/WidgetChromium.cpp @@ -63,9 +63,10 @@ void Widget::paint(GraphicsContext*, const IntRect&) { } -void Widget::setFocus() +void Widget::setFocus(bool focused) { - ChromiumBridge::widgetSetFocus(this); + if (focused) + ChromiumBridge::widgetSetFocus(this); } void Widget::setIsSelected(bool) diff --git a/WebCore/platform/efl/WidgetEfl.cpp b/WebCore/platform/efl/WidgetEfl.cpp index 168477a..c07c8c4 100644 --- a/WebCore/platform/efl/WidgetEfl.cpp +++ b/WebCore/platform/efl/WidgetEfl.cpp @@ -199,7 +199,7 @@ void Widget::frameRectsChanged() evas_object_resize(o, rect.width(), rect.height()); } -void Widget::setFocus() +void Widget::setFocus(bool focused) { } diff --git a/WebCore/platform/graphics/FloatSize.h b/WebCore/platform/graphics/FloatSize.h index 97ee00d..53a0071 100644 --- a/WebCore/platform/graphics/FloatSize.h +++ b/WebCore/platform/graphics/FloatSize.h @@ -31,7 +31,7 @@ #include "IntSize.h" #include <wtf/MathExtras.h> -#if PLATFORM(CG) +#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN)) typedef struct CGSize CGSize; #endif @@ -75,7 +75,7 @@ public: m_height < other.m_height ? m_height : other.m_height); } -#if PLATFORM(CG) +#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN)) explicit FloatSize(const CGSize&); // don't do this implicitly since it's lossy operator CGSize() const; #endif diff --git a/WebCore/platform/graphics/Font.cpp b/WebCore/platform/graphics/Font.cpp index 7bdefba..21380be 100644 --- a/WebCore/platform/graphics/Font.cpp +++ b/WebCore/platform/graphics/Font.cpp @@ -175,7 +175,7 @@ void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoi #endif #if USE(FONT_FAST_PATH) - if (canUseGlyphCache(run)) + if (codePath(run) != Complex) return drawSimpleText(context, run, point, from, to); #endif @@ -190,11 +190,12 @@ float Font::floatWidth(const TextRun& run, HashSet<const SimpleFontData*>* fallb #endif #if USE(FONT_FAST_PATH) - if (canUseGlyphCache(run)) { + CodePath codePathToUse = codePath(run); + if (codePathToUse != Complex) { // If the complex text implementation cannot return fallback fonts, avoid // returning them for simple text as well. static bool returnFallbackFonts = canReturnFallbackFontsForComplexText(); - return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0); + return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0, codePathToUse == SimpleWithGlyphOverflow ? glyphOverflow : 0); } #endif @@ -214,7 +215,7 @@ float Font::floatWidth(const TextRun& run, int extraCharsAvailable, int& charsCo glyphName = ""; #if USE(FONT_FAST_PATH) - if (canUseGlyphCache(run)) + if (codePath(run) != Complex) return floatWidthForSimpleText(run, 0); #endif @@ -231,7 +232,7 @@ FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& point, to = (to == -1 ? run.length() : to); #if USE(FONT_FAST_PATH) - if (canUseGlyphCache(run)) + if (codePath(run) != Complex) return selectionRectForSimpleText(run, point, h, from, to); #endif @@ -246,7 +247,7 @@ int Font::offsetForPosition(const TextRun& run, int x, bool includePartialGlyphs #endif #if USE(FONT_FAST_PATH) - if (canUseGlyphCache(run)) + if (codePath(run) != Complex) return offsetForPositionForSimpleText(run, x, includePartialGlyphs); #endif diff --git a/WebCore/platform/graphics/Font.h b/WebCore/platform/graphics/Font.h index 62525b0..da546f0 100644 --- a/WebCore/platform/graphics/Font.h +++ b/WebCore/platform/graphics/Font.h @@ -26,9 +26,9 @@ #define Font_h #include "CharacterNames.h" -#include "TextRun.h" #include "FontDescription.h" #include "SimpleFontData.h" +#include "TextRun.h" #include "TypesettingFeatures.h" #include <wtf/HashMap.h> #include <wtf/HashSet.h> @@ -83,9 +83,7 @@ public: Font& operator=(const Font&); bool operator==(const Font& other) const; - bool operator!=(const Font& other) const { - return !(*this == other); - } + bool operator!=(const Font& other) const { return !(*this == other); } const FontDescription& fontDescription() const { return m_fontDescription; } @@ -152,6 +150,10 @@ public: static void setShouldUseSmoothing(bool); static bool shouldUseSmoothing(); +#if USE(FONT_FAST_PATH) + enum CodePath { Auto, Simple, Complex, SimpleWithGlyphOverflow }; +#endif + private: #if ENABLE(SVG_FONTS) void drawTextUsingSVGFont(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const; @@ -162,11 +164,11 @@ private: #endif #if USE(FONT_FAST_PATH) - bool canUseGlyphCache(const TextRun&) const; + CodePath codePath(const TextRun&) const; void drawSimpleText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const; void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const; void drawGlyphBuffer(GraphicsContext*, const GlyphBuffer&, const TextRun&, const FloatPoint&) const; - float floatWidthForSimpleText(const TextRun&, GlyphBuffer*, HashSet<const SimpleFontData*>* fallbackFonts = 0) const; + float floatWidthForSimpleText(const TextRun&, GlyphBuffer*, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; int offsetForPositionForSimpleText(const TextRun&, int position, bool includePartialGlyphs) const; FloatRect selectionRectForSimpleText(const TextRun&, const IntPoint&, int h, int from, int to) const; @@ -183,7 +185,6 @@ private: public: // Useful for debugging the different font rendering code paths. #if USE(FONT_FAST_PATH) - enum CodePath { Auto, Simple, Complex }; static void setCodePath(CodePath); static CodePath codePath(); static CodePath s_codePath; @@ -197,7 +198,7 @@ public: FontSelector* fontSelector() const; static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == 0x00A0; } - static bool treatAsZeroWidthSpace(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || c == 0x200e || c == 0x200f || (c >= 0x202a && c <= 0x202e) || c == 0xFFFC; } + static bool treatAsZeroWidthSpace(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || (c >= 0x200c && c <= 0x200f) || (c >= 0x202a && c <= 0x202e) || c == 0xFFFC; } static inline UChar normalizeSpaces(UChar character) { diff --git a/WebCore/platform/graphics/FontFastPath.cpp b/WebCore/platform/graphics/FontFastPath.cpp index 6e2a744..f57ae5b 100644 --- a/WebCore/platform/graphics/FontFastPath.cpp +++ b/WebCore/platform/graphics/FontFastPath.cpp @@ -190,73 +190,64 @@ Font::CodePath Font::codePath() return s_codePath; } -bool Font::canUseGlyphCache(const TextRun& run) const +Font::CodePath Font::codePath(const TextRun& run) const { - switch (s_codePath) { - case Auto: - break; - case Simple: - return true; - case Complex: - return false; - } - + if (s_codePath != Auto) + return s_codePath; + // 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; + return Complex; 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; + return Complex; 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; + return Complex; 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; + return Complex; if (c < 0x1780) // U+1780 through U+18AF Khmer, Mongolian continue; if (c <= 0x18AF) - return false; + return Complex; if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0) continue; if (c <= 0x194F) - return false; + return Complex; - // FIXME: we should not use complex text path for these characters. - if (c < 0x1E00) // U+1E00 through U+2000 characters with diacritics and stacked diacritics continue; if (c <= 0x2000) - return false; + return SimpleWithGlyphOverflow; if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols continue; if (c <= 0x20FF) - return false; + return Complex; if (c < 0xFE20) // U+FE20 through U+FE2F Combining half marks continue; if (c <= 0xFE2F) - return false; + return Complex; } if (typesettingFeatures()) - return false; - - return true; + return Complex; + return Simple; } void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const @@ -321,10 +312,18 @@ void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuf drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint); } -float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts) const +float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const { - WidthIterator it(this, run, fallbackFonts); + WidthIterator it(this, run, fallbackFonts, glyphOverflow); it.advance(run.length(), glyphBuffer); + + if (glyphOverflow) { + glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - ascent()); + glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - descent()); + glyphOverflow->left = ceilf(it.firstGlyphOverflow()); + glyphOverflow->right = ceilf(it.lastGlyphOverflow()); + } + return it.m_runWidthSoFar; } diff --git a/WebCore/platform/graphics/GlyphBuffer.h b/WebCore/platform/graphics/GlyphBuffer.h index edb804c..6f1fe7b 100644 --- a/WebCore/platform/graphics/GlyphBuffer.h +++ b/WebCore/platform/graphics/GlyphBuffer.h @@ -34,7 +34,7 @@ #include <wtf/UnusedParam.h> #include <wtf/Vector.h> -#if PLATFORM(CG) +#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN)) #include <ApplicationServices/ApplicationServices.h> #endif @@ -58,7 +58,7 @@ typedef Glyph GlyphBufferGlyph; // CG uses CGSize instead of FloatSize so that the result of advances() // can be passed directly to CGContextShowGlyphsWithAdvances in FontMac.mm -#if PLATFORM(CG) +#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN)) typedef CGSize GlyphBufferAdvance; #elif OS(WINCE) // There is no cross-platform code that uses the height of GlyphBufferAdvance, @@ -122,7 +122,7 @@ public: float advanceAt(int index) const { -#if PLATFORM(CG) +#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN)) return m_advances[index].width; #elif OS(WINCE) return m_advances[index]; @@ -153,7 +153,7 @@ public: m_glyphs.append(glyph); #endif -#if PLATFORM(CG) +#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN)) CGSize advance = { width, 0 }; m_advances.append(advance); #elif OS(WINCE) diff --git a/WebCore/platform/graphics/GlyphMetricsMap.h b/WebCore/platform/graphics/GlyphMetricsMap.h index 49854be..5e13afe 100644 --- a/WebCore/platform/graphics/GlyphMetricsMap.h +++ b/WebCore/platform/graphics/GlyphMetricsMap.h @@ -29,7 +29,6 @@ #ifndef GlyphMetricsMap_h #define GlyphMetricsMap_h -#include "FloatRect.h" #include <wtf/HashMap.h> #include <wtf/OwnPtr.h> #include <wtf/unicode/Unicode.h> @@ -40,12 +39,7 @@ typedef unsigned short Glyph; const float cGlyphSizeUnknown = -1; -struct GlyphMetrics { - float horizontalAdvance; - FloatRect boundingBox; -}; - -class GlyphMetricsMap : public Noncopyable { +template<class T> class GlyphMetricsMap : public Noncopyable { public: GlyphMetricsMap() : m_filledPrimaryPage(false) { } ~GlyphMetricsMap() @@ -54,17 +48,12 @@ public: deleteAllValues(*m_pages); } - GlyphMetrics metricsForGlyph(Glyph glyph) + T metricsForGlyph(Glyph glyph) { return locatePage(glyph / GlyphMetricsPage::size)->metricsForGlyph(glyph); } - float widthForGlyph(Glyph glyph) - { - return locatePage(glyph / GlyphMetricsPage::size)->metricsForGlyph(glyph).horizontalAdvance; - } - - void setMetricsForGlyph(Glyph glyph, const GlyphMetrics& metrics) + void setMetricsForGlyph(Glyph glyph, const T& metrics) { locatePage(glyph / GlyphMetricsPage::size)->setMetricsForGlyph(glyph, metrics); } @@ -72,14 +61,14 @@ public: private: struct GlyphMetricsPage { static const size_t size = 256; // Usually covers Latin-1 in a single page. - GlyphMetrics m_metrics[size]; + T m_metrics[size]; - GlyphMetrics metricsForGlyph(Glyph glyph) const { return m_metrics[glyph % size]; } - void setMetricsForGlyph(Glyph glyph, const GlyphMetrics& metrics) + T metricsForGlyph(Glyph glyph) const { return m_metrics[glyph % size]; } + void setMetricsForGlyph(Glyph glyph, const T& metrics) { setMetricsForIndex(glyph % size, metrics); } - void setMetricsForIndex(unsigned index, const GlyphMetrics& metrics) + void setMetricsForIndex(unsigned index, const T& metrics) { m_metrics[index] = metrics; } @@ -94,11 +83,47 @@ private: GlyphMetricsPage* locatePageSlowCase(unsigned pageNumber); + static T unknownMetrics(); + bool m_filledPrimaryPage; GlyphMetricsPage m_primaryPage; // We optimize for the page that contains glyph indices 0-255. OwnPtr<HashMap<int, GlyphMetricsPage*> > m_pages; }; +template<> inline float GlyphMetricsMap<float>::unknownMetrics() +{ + return cGlyphSizeUnknown; +} + +template<> inline FloatRect GlyphMetricsMap<FloatRect>::unknownMetrics() +{ + return FloatRect(0, 0, cGlyphSizeUnknown, cGlyphSizeUnknown); +} + +template<class T> typename GlyphMetricsMap<T>::GlyphMetricsPage* GlyphMetricsMap<T>::locatePageSlowCase(unsigned pageNumber) +{ + GlyphMetricsPage* page; + if (!pageNumber) { + ASSERT(!m_filledPrimaryPage); + page = &m_primaryPage; + m_filledPrimaryPage = true; + } else { + if (m_pages) { + if ((page = m_pages->get(pageNumber))) + return page; + } else + m_pages.set(new HashMap<int, GlyphMetricsPage*>); + page = new GlyphMetricsPage; + m_pages->set(pageNumber, page); + } + + // Fill in the whole page with the unknown glyph information. + for (unsigned i = 0; i < GlyphMetricsPage::size; i++) + page->setMetricsForIndex(i, unknownMetrics()); + + return page; +} + } // namespace WebCore #endif diff --git a/WebCore/platform/graphics/GlyphPageTreeNode.cpp b/WebCore/platform/graphics/GlyphPageTreeNode.cpp index 59a5efb..dac26b3 100644 --- a/WebCore/platform/graphics/GlyphPageTreeNode.cpp +++ b/WebCore/platform/graphics/GlyphPageTreeNode.cpp @@ -124,6 +124,18 @@ GlyphPageTreeNode::~GlyphPageTreeNode() delete m_systemFallbackChild; } +static bool fill(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData) +{ + if (!fontData->isSVGFont()) + return pageToFill->fill(offset, length, buffer, bufferLength, fontData); + + // SVG Fonts do not use the glyph page cache. Zero fill the glyph + // positions and return false to indicate the glyphs were not found. + for (unsigned i = 0; i < length; ++i) + pageToFill->setGlyphDataForIndex(offset + i, 0, 0); + return false; +} + void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNumber) { ASSERT(!m_page); @@ -165,13 +177,15 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu buffer[(int)'\t'] = ' '; buffer[noBreakSpace] = ' '; } else if (start == (leftToRightMark & ~(GlyphPage::size - 1))) { - // LRM, RLM, LRE, RLE and PDF must not render at all. + // LRM, RLM, LRE, RLE, ZWNJ, ZWJ, and PDF must not render at all. buffer[leftToRightMark - start] = zeroWidthSpace; buffer[rightToLeftMark - start] = zeroWidthSpace; buffer[leftToRightEmbed - start] = zeroWidthSpace; buffer[rightToLeftEmbed - start] = zeroWidthSpace; buffer[leftToRightOverride - start] = zeroWidthSpace; buffer[rightToLeftOverride - start] = zeroWidthSpace; + buffer[zeroWidthNonJoiner - start] = zeroWidthSpace; + buffer[zeroWidthJoiner - start] = zeroWidthSpace; buffer[popDirectionalFormatting - start] = zeroWidthSpace; } else if (start == (objectReplacementCharacter & ~(GlyphPage::size - 1))) { // Object replacement character must not render at all. @@ -221,7 +235,7 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu } zeroFilled = true; } - haveGlyphs |= pageToFill->fill(from, to - from, buffer + from * (start < 0x10000 ? 1 : 2), (to - from) * (start < 0x10000 ? 1 : 2), range.fontData()); + haveGlyphs |= fill(pageToFill, from, to - from, buffer + from * (start < 0x10000 ? 1 : 2), (to - from) * (start < 0x10000 ? 1 : 2), range.fontData()); if (scratchPage) { ASSERT(to <= static_cast<int>(GlyphPage::size)); for (int j = from; j < to; j++) { @@ -232,7 +246,7 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu } } } else - haveGlyphs = m_page->fill(0, GlyphPage::size, buffer, bufferLength, static_cast<const SimpleFontData*>(fontData)); + haveGlyphs = fill(m_page.get(), 0, GlyphPage::size, buffer, bufferLength, static_cast<const SimpleFontData*>(fontData)); if (!haveGlyphs) m_page = 0; diff --git a/WebCore/platform/graphics/Gradient.cpp b/WebCore/platform/graphics/Gradient.cpp index daf4754..0e961ad 100644 --- a/WebCore/platform/graphics/Gradient.cpp +++ b/WebCore/platform/graphics/Gradient.cpp @@ -96,7 +96,14 @@ void Gradient::addColorStop(float value, const Color& color) m_stops.append(ColorStop(value, r, g, b, a)); m_stopsSorted = false; + platformDestroy(); +} +void Gradient::addColorStop(const Gradient::ColorStop& stop) +{ + m_stops.append(stop); + + m_stopsSorted = false; platformDestroy(); } diff --git a/WebCore/platform/graphics/Gradient.h b/WebCore/platform/graphics/Gradient.h index b6911f3..2c877af 100644 --- a/WebCore/platform/graphics/Gradient.h +++ b/WebCore/platform/graphics/Gradient.h @@ -87,6 +87,8 @@ namespace WebCore { } virtual ~Gradient(); + struct ColorStop; + void addColorStop(const ColorStop&); void addColorStop(float, const Color&); void getColor(float value, float* r, float* g, float* b, float* a) const; @@ -97,7 +99,6 @@ namespace WebCore { float r0() const { return m_r0; } float r1() const { return m_r1; } bool isRadial() const { return m_radial; } - struct ColorStop; const Vector<ColorStop>& getStops() const; #else #if PLATFORM(ANDROID) diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h index 45f6f06..b64e9d3 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.h +++ b/WebCore/platform/graphics/GraphicsContext3D.h @@ -479,6 +479,8 @@ namespace WebCore { bool flipVertically, AlphaOp alphaOp); + bool isGLES2Compliant() const; + //---------------------------------------------------------------------- // Entry points for WebGL. // @@ -607,16 +609,12 @@ namespace WebCore { void stencilOp(unsigned long fail, unsigned long zfail, unsigned long zpass); void stencilOpSeparate(unsigned long face, unsigned long fail, unsigned long zfail, unsigned long zpass); - // These next several functions return an error code (0 if no errors) rather than using an ExceptionCode. - // Currently they return -1 on any error. int texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels); - int texImage2D(unsigned target, unsigned level, Image* image, bool flipY, bool premultiplyAlpha); void texParameterf(unsigned target, unsigned pname, float param); void texParameteri(unsigned target, unsigned pname, int param); int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, unsigned width, unsigned height, unsigned format, unsigned type, void* pixels); - int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, Image* image, bool flipY, bool premultiplyAlpha); void uniform1f(long location, float x); void uniform1fv(long location, float* v, int size); @@ -659,6 +657,9 @@ namespace WebCore { // Helpers for notification about paint events void beginPaint(WebGLRenderingContext* context); void endPaint(); +#if PLATFORM(QT) + void paint(QPainter* painter, const QRect& rect) const; +#endif // Support for buffer creation and deletion unsigned createBuffer(); diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp index 55fa900..ee82083 100644 --- a/WebCore/platform/graphics/MediaPlayer.cpp +++ b/WebCore/platform/graphics/MediaPlayer.cpp @@ -50,7 +50,8 @@ #elif PLATFORM(GTK) #include "MediaPlayerPrivateGStreamer.h" #elif PLATFORM(QT) -#if QT_VERSION < 0x040700 +// QtMultimedia support is disabled currently. +#if 1 || (QT_VERSION < 0x040700) #include "MediaPlayerPrivatePhonon.h" #else #include "MediaPlayerPrivateQt.h" diff --git a/WebCore/platform/graphics/SimpleFontData.cpp b/WebCore/platform/graphics/SimpleFontData.cpp index 04b6ab1..1cc3b4c 100644 --- a/WebCore/platform/graphics/SimpleFontData.cpp +++ b/WebCore/platform/graphics/SimpleFontData.cpp @@ -92,6 +92,7 @@ SimpleFontData::SimpleFontData(const FontPlatformData& f, bool customFont, bool // FIXME: is there a way we can get the space glyph from the SVGGlyphIdentifier above? m_spaceGlyph = 0; + m_zeroWidthSpaceGlyph = 0; determinePitch(); m_adjustedSpaceWidth = roundf(m_spaceWidth); m_missingGlyphData.fontData = this; @@ -136,11 +137,14 @@ void SimpleFontData::platformGlyphInit() m_spaceWidth = 0; m_adjustedSpaceWidth = 0; determinePitch(); + m_zeroWidthSpaceGlyph = 0; m_missingGlyphData.fontData = this; m_missingGlyphData.glyph = 0; return; } + m_zeroWidthSpaceGlyph = glyphPageZero->glyphDataForCharacter(0).glyph; + // Nasty hack to determine if we should round or ceil space widths. // If the font is monospace or fake monospace we ceil to ensure that // every character and the space are the same width. Otherwise we round. @@ -155,14 +159,9 @@ void SimpleFontData::platformGlyphInit() // See <http://bugs.webkit.org/show_bug.cgi?id=13178> // Ask for the glyph for 0 to avoid paging in ZERO WIDTH SPACE. Control characters, including 0, // are mapped to the ZERO WIDTH SPACE glyph. - Glyph zeroWidthSpaceGlyph = glyphPageZero->glyphDataForCharacter(0).glyph; - if (zeroWidthSpaceGlyph) { - if (zeroWidthSpaceGlyph != m_spaceGlyph) { - GlyphMetrics metrics; - metrics.horizontalAdvance = 0; - m_glyphToMetricsMap.setMetricsForGlyph(zeroWidthSpaceGlyph, metrics); - } else - LOG_ERROR("Font maps SPACE and ZERO WIDTH SPACE to the same glyph. Glyph width not overridden."); + if (m_zeroWidthSpaceGlyph == m_spaceGlyph) { + m_zeroWidthSpaceGlyph = 0; + LOG_ERROR("Font maps SPACE and ZERO WIDTH SPACE to the same glyph. Glyph width will not be overridden."); } m_missingGlyphData.fontData = this; diff --git a/WebCore/platform/graphics/SimpleFontData.h b/WebCore/platform/graphics/SimpleFontData.h index efdbba4..4c34f2b 100644 --- a/WebCore/platform/graphics/SimpleFontData.h +++ b/WebCore/platform/graphics/SimpleFontData.h @@ -26,6 +26,7 @@ #include "FontData.h" #include "FontPlatformData.h" +#include "FloatRect.h" #include "GlyphMetricsMap.h" #include "GlyphPageTreeNode.h" #include "TypesettingFeatures.h" @@ -35,6 +36,11 @@ typedef struct OpaqueATSUStyle* ATSUStyle; #endif +#if USE(CORE_TEXT) +#include <ApplicationServices/ApplicationServices.h> +#include <wtf/RetainPtr.h> +#endif + #if (PLATFORM(WIN) && !OS(WINCE)) \ || (OS(WINDOWS) && PLATFORM(WX)) #include <usp10.h> @@ -60,7 +66,6 @@ class SharedBuffer; class SVGFontData; enum Pitch { UnknownPitch, FixedPitch, VariablePitch }; -enum GlyphMetricsMode { GlyphBoundingBox, GlyphWidthOnly }; class SimpleFontData : public FontData { public: @@ -81,14 +86,15 @@ public: float xHeight() const { return m_xHeight; } unsigned unitsPerEm() const { return m_unitsPerEm; } - float widthForGlyph(Glyph glyph) const { return metricsForGlyph(glyph, GlyphWidthOnly).horizontalAdvance; } - GlyphMetrics metricsForGlyph(Glyph, GlyphMetricsMode = GlyphBoundingBox) const; - GlyphMetrics platformMetricsForGlyph(Glyph, GlyphMetricsMode) const; + FloatRect boundsForGlyph(Glyph) const; + float widthForGlyph(Glyph glyph) const; + FloatRect platformBoundsForGlyph(Glyph) const; + float platformWidthForGlyph(Glyph) const; float spaceWidth() const { return m_spaceWidth; } float adjustedSpaceWidth() const { return m_adjustedSpaceWidth; } -#if PLATFORM(CG) || PLATFORM(CAIRO) || (OS(WINDOWS) && PLATFORM(WX)) +#if PLATFORM(CG) || PLATFORM(CAIRO) || PLATFORM(WX) float syntheticBoldOffset() const { return m_syntheticBoldOffset; } #endif @@ -119,6 +125,8 @@ public: #if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) NSFont* getNSFont() const { return m_platformData.font(); } +#elif (PLATFORM(WX) && OS(DARWIN)) + NSFont* getNSFont() const { return m_platformData.nsFont(); } #endif #if USE(CORE_TEXT) @@ -168,7 +176,8 @@ private: || (OS(WINDOWS) && PLATFORM(WX)) void initGDIFont(); void platformCommonDestroy(); - GlyphMetrics metricsForGDIGlyph(Glyph glyph) const; + FloatRect boundsForGDIGlyph(Glyph glyph) const; + float widthForGDIGlyph(Glyph glyph) const; #endif int m_ascent; @@ -182,7 +191,8 @@ private: FontPlatformData m_platformData; - mutable GlyphMetricsMap m_glyphToMetricsMap; + mutable GlyphMetricsMap<FloatRect> m_glyphToBoundsMap; + mutable GlyphMetricsMap<float> m_glyphToWidthMap; bool m_treatAsFixedPitch; @@ -197,11 +207,13 @@ private: float m_spaceWidth; float m_adjustedSpaceWidth; + Glyph m_zeroWidthSpaceGlyph; + GlyphData m_missingGlyphData; mutable SimpleFontData* m_smallCapsFontData; -#if PLATFORM(CG) || PLATFORM(CAIRO) || (OS(WINDOWS) && PLATFORM(WX)) +#if PLATFORM(CG) || PLATFORM(CAIRO) || PLATFORM(WX) float m_syntheticBoldOffset; #endif @@ -238,16 +250,32 @@ private: #if !PLATFORM(QT) -ALWAYS_INLINE GlyphMetrics SimpleFontData::metricsForGlyph(Glyph glyph, GlyphMetricsMode metricsMode) const +ALWAYS_INLINE FloatRect SimpleFontData::boundsForGlyph(Glyph glyph) const +{ + if (glyph == m_zeroWidthSpaceGlyph && glyph) + return FloatRect(); + + FloatRect bounds = m_glyphToBoundsMap.metricsForGlyph(glyph); + if (bounds.width() != cGlyphSizeUnknown) + return bounds; + + bounds = platformBoundsForGlyph(glyph); + m_glyphToBoundsMap.setMetricsForGlyph(glyph, bounds); + return bounds; +} + +ALWAYS_INLINE float SimpleFontData::widthForGlyph(Glyph glyph) const { - GlyphMetrics metrics = m_glyphToMetricsMap.metricsForGlyph(glyph); - if ((metricsMode == GlyphWidthOnly && metrics.horizontalAdvance != cGlyphSizeUnknown) || (metricsMode == GlyphBoundingBox && metrics.boundingBox.width() != cGlyphSizeUnknown)) - return metrics; + if (glyph == m_zeroWidthSpaceGlyph && glyph) + return 0; - metrics = platformMetricsForGlyph(glyph, metricsMode); - m_glyphToMetricsMap.setMetricsForGlyph(glyph, metrics); + float width = m_glyphToWidthMap.metricsForGlyph(glyph); + if (width != cGlyphSizeUnknown) + return width; - return metrics; + width = platformWidthForGlyph(glyph); + m_glyphToWidthMap.setMetricsForGlyph(glyph, width); + return width; } #endif diff --git a/WebCore/platform/graphics/TextRun.h b/WebCore/platform/graphics/TextRun.h index 166b047..03d7b9f 100644 --- a/WebCore/platform/graphics/TextRun.h +++ b/WebCore/platform/graphics/TextRun.h @@ -29,7 +29,7 @@ namespace WebCore { class RenderObject; -class SVGPaintServer; +class RenderSVGResource; class TextRun { public: @@ -47,7 +47,7 @@ public: , m_disableSpacing(false) #if ENABLE(SVG_FONTS) , m_referencingRenderObject(0) - , m_activePaintServer(0) + , m_activePaintingResource(0) #endif { } @@ -66,7 +66,7 @@ public: , m_disableSpacing(false) #if ENABLE(SVG_FONTS) , m_referencingRenderObject(0) - , m_activePaintServer(0) + , m_activePaintingResource(0) #endif { } @@ -98,8 +98,8 @@ public: RenderObject* referencingRenderObject() const { return m_referencingRenderObject; } void setReferencingRenderObject(RenderObject* object) { m_referencingRenderObject = object; } - SVGPaintServer* activePaintServer() const { return m_activePaintServer; } - void setActivePaintServer(SVGPaintServer* object) { m_activePaintServer = object; } + RenderSVGResource* activePaintingResource() const { return m_activePaintingResource; } + void setActivePaintingResource(RenderSVGResource* object) { m_activePaintingResource = object; } #endif private: @@ -117,7 +117,7 @@ private: #if ENABLE(SVG_FONTS) RenderObject* m_referencingRenderObject; - SVGPaintServer* m_activePaintServer; + RenderSVGResource* m_activePaintingResource; #endif }; diff --git a/WebCore/platform/graphics/WidthIterator.cpp b/WebCore/platform/graphics/WidthIterator.cpp index 9157310..996ce40 100644 --- a/WebCore/platform/graphics/WidthIterator.cpp +++ b/WebCore/platform/graphics/WidthIterator.cpp @@ -33,13 +33,14 @@ using namespace WTF; using namespace Unicode; +using namespace std; namespace WebCore { // According to http://www.unicode.org/Public/UNIDATA/UCD.html#Canonical_Combining_Class_Values static const uint8_t hiraganaKatakanaVoicingMarksCombiningClass = 8; -WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) +WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, bool accountForGlyphBounds) : m_font(font) , m_run(run) , m_end(run.length()) @@ -47,6 +48,11 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const , m_runWidthSoFar(0) , m_finalRoundingWidth(0) , m_fallbackFonts(fallbackFonts) + , m_accountForGlyphBounds(accountForGlyphBounds) + , m_maxGlyphBoundingBoxY(numeric_limits<float>::min()) + , m_minGlyphBoundingBoxY(numeric_limits<float>::max()) + , m_firstGlyphOverflow(0) + , m_lastGlyphOverflow(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. @@ -79,6 +85,7 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) float runWidthSoFar = m_runWidthSoFar; float lastRoundingWidth = m_finalRoundingWidth; + FloatRect bounds; const SimpleFontData* primaryFont = m_font->primaryFont(); const SimpleFontData* lastFontData = primaryFont; @@ -175,6 +182,12 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) } } + if (m_accountForGlyphBounds) { + bounds = fontData->boundsForGlyph(glyph); + if (!currentCharacter) + m_firstGlyphOverflow = max<float>(0, -bounds.x()); + } + // Advance past the character we just dealt with. cp += clusterLength; currentCharacter += clusterLength; @@ -205,6 +218,12 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) glyphBuffer->add(glyph, fontData, (rtl ? oldWidth + lastRoundingWidth : width)); lastRoundingWidth = width - oldWidth; + + if (m_accountForGlyphBounds) { + m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, bounds.bottom()); + m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, bounds.y()); + m_lastGlyphOverflow = max<float>(0, bounds.right() - width); + } } m_currentCharacter = currentCharacter; diff --git a/WebCore/platform/graphics/WidthIterator.h b/WebCore/platform/graphics/WidthIterator.h index 7ca4198..d42a0c5 100644 --- a/WebCore/platform/graphics/WidthIterator.h +++ b/WebCore/platform/graphics/WidthIterator.h @@ -33,11 +33,16 @@ class SimpleFontData; class TextRun; struct WidthIterator { - WidthIterator(const Font*, const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0); + WidthIterator(const Font*, const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, bool accountForGlyphBounds = false); void advance(int to, GlyphBuffer* = 0); bool advanceOneCharacter(float& width, GlyphBuffer* = 0); + float maxGlyphBoundingBoxY() const { ASSERT(m_accountForGlyphBounds); return m_maxGlyphBoundingBoxY; } + float minGlyphBoundingBoxY() const { ASSERT(m_accountForGlyphBounds); return m_minGlyphBoundingBoxY; } + float firstGlyphOverflow() const { ASSERT(m_accountForGlyphBounds); return m_firstGlyphOverflow; } + float lastGlyphOverflow() const { ASSERT(m_accountForGlyphBounds); return m_lastGlyphOverflow; } + const Font* m_font; const TextRun& m_run; @@ -51,7 +56,13 @@ struct WidthIterator { private: UChar32 normalizeVoicingMarks(int currentCharacter); + HashSet<const SimpleFontData*>* m_fallbackFonts; + bool m_accountForGlyphBounds; + float m_maxGlyphBoundingBoxY; + float m_minGlyphBoundingBoxY; + float m_firstGlyphOverflow; + float m_lastGlyphOverflow; }; } diff --git a/WebCore/platform/graphics/cairo/FontCacheCairo.cpp b/WebCore/platform/graphics/cairo/FontCacheCairo.cpp index d2b2f39..79b32b4 100644 --- a/WebCore/platform/graphics/cairo/FontCacheCairo.cpp +++ b/WebCore/platform/graphics/cairo/FontCacheCairo.cpp @@ -39,6 +39,11 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons FcResult fresult; FontPlatformData* prim = const_cast<FontPlatformData*>(&font.primaryFont()->platformData()); + // FIXME: This should not happen, apparently. We are null-checking + // for now just to avoid crashing. + if (!prim || !prim->m_pattern) + return 0; + if (!prim->m_fallbacks) prim->m_fallbacks = FcFontSort(NULL, prim->m_pattern, FcTrue, NULL, &fresult); diff --git a/WebCore/platform/graphics/cairo/FontPlatformData.h b/WebCore/platform/graphics/cairo/FontPlatformData.h index 3c926fe..d271f5b 100644 --- a/WebCore/platform/graphics/cairo/FontPlatformData.h +++ b/WebCore/platform/graphics/cairo/FontPlatformData.h @@ -28,9 +28,10 @@ #ifndef FontPlatformData_h #define FontPlatformData_h +#include <cairo.h> #include "FontDescription.h" #include "GlyphBuffer.h" -#include <cairo.h> + #if defined(USE_FREETYPE) #include <cairo-ft.h> #include <fontconfig/fcfreetype.h> @@ -38,7 +39,7 @@ #include <pango/pangocairo.h> #elif PLATFORM(WIN) #include <cairo-win32.h> -#include "RefCountedHFONT.h" +#include "RefCountedGDIHandle.h" #include "StringImpl.h" #else #error "Must defined a font backend" @@ -107,7 +108,7 @@ public: #if !PLATFORM(WIN) static bool init(); #else - HFONT hfont() const { return m_font->hfont(); } + HFONT hfont() const { return m_font->handle(); } bool useGDI() const { return m_useGDI; } cairo_font_face_t* fontFace() const { return m_fontFace; } #endif @@ -164,7 +165,7 @@ public: private: void platformDataInit(HFONT, float size, HDC, WCHAR* faceName); - RefPtr<RefCountedHFONT> m_font; + RefPtr<RefCountedGDIHandle<HFONT> > m_font; cairo_font_face_t* m_fontFace; bool m_useGDI; #else diff --git a/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp b/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp index 0be45f6..0055078 100644 --- a/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp +++ b/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp @@ -83,9 +83,9 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes { if (!m_smallCapsFontData) { FontDescription desc = FontDescription(fontDescription); - desc.setComputedSize(0.70f*fontDescription.computedSize()); - const FontPlatformData* pdata = new FontPlatformData(desc, desc.family().family()); - m_smallCapsFontData = new SimpleFontData(*pdata); + desc.setComputedSize(0.70f * fontDescription.computedSize()); + FontPlatformData platformData(desc, desc.family().family()); + m_smallCapsFontData = new SimpleFontData(platformData); } return m_smallCapsFontData; } @@ -114,7 +114,12 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = m_platformData.isFixedPitch(); } -GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const +{ + return FloatRect(); +} + +float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { ASSERT(m_platformData.m_scaledFont); @@ -125,10 +130,8 @@ GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMo float w = (float)m_spaceWidth; if (cairo_scaled_font_status(m_platformData.m_scaledFont) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0) w = (float)extents.x_advance; - - GlyphMetrics metrics; - metrics.horizontalAdvance = w; - return metrics; + + return w; } } diff --git a/WebCore/platform/graphics/cg/FontPlatformData.h b/WebCore/platform/graphics/cg/FontPlatformData.h index da2b7e3..1da8916 100644 --- a/WebCore/platform/graphics/cg/FontPlatformData.h +++ b/WebCore/platform/graphics/cg/FontPlatformData.h @@ -24,7 +24,7 @@ #ifndef FontPlatformData_h #define FontPlatformData_h -#include "RefCountedHFONT.h" +#include "RefCountedGDIHandle.h" #include "StringImpl.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> @@ -57,7 +57,7 @@ public: FontPlatformData(WTF::HashTableDeletedValueType) : m_font(WTF::HashTableDeletedValue) { } bool isHashTableDeletedValue() const { return m_font.isHashTableDeletedValue(); } - HFONT hfont() const { return m_font->hfont(); } + HFONT hfont() const { return m_font->handle(); } CGFontRef cgFont() const { return m_cgFont.get(); } float size() const { return m_size; } @@ -88,7 +88,7 @@ public: private: void platformDataInit(HFONT, float size, HDC, WCHAR* faceName); - RefPtr<RefCountedHFONT> m_font; + RefPtr<RefCountedGDIHandle<HFONT> > m_font; RetainPtr<CGFontRef> m_cgFont; float m_size; diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp index b4e1ca9..0b5f0b0 100644 --- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp +++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp @@ -130,10 +130,12 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived) if (!m_decoder) { m_decoder = CGImageSourceCreateIncremental(0); } else if (allDataReceived) { +#if !PLATFORM(WIN) // 10.6 bug workaround: image sources with final=false fail to draw into PDF contexts, so re-create image source // when data is complete. <rdar://problem/7874035> (<http://openradar.appspot.com/7874035>) CFRelease(m_decoder); m_decoder = CGImageSourceCreateIncremental(0); +#endif } // Create a CGDataProvider to wrap the SharedBuffer. data->ref(); diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp index fa549cd..700b3ed 100644 --- a/WebCore/platform/graphics/chromium/FontLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontLinux.cpp @@ -64,7 +64,7 @@ static bool isCanvasMultiLayered(SkCanvas* canvas) return !layerIterator.done(); } -static bool adjustTextRenderMode(SkPaint* paint, bool isCanvasMultiLayered) +static void adjustTextRenderMode(SkPaint* paint, bool isCanvasMultiLayered) { // Our layers only have a single alpha channel. This means that subpixel // rendered text cannot be compositied correctly when the layer is @@ -238,6 +238,23 @@ public: } else { if (!hb_utf16_script_run_next(&m_numCodePoints, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun)) return false; + + // It is actually wrong to consider script runs at all in this code. + // Other WebKit code (e.g. Mac) segments complex text just by finding + // the longest span of text covered by a single font. + // But we currently need to call hb_utf16_script_run_next anyway to fill + // in the harfbuzz data structures to e.g. pick the correct script's shaper. + // So we allow that to run first, then do a second pass over the range it + // found and take the largest subregion that stays within a single font. + const FontData* glyphData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false, false).fontData; + int endOfRun; + for (endOfRun = 1; endOfRun < m_item.item.length; ++endOfRun) { + const FontData* nextGlyphData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos + endOfRun], false, false).fontData; + if (nextGlyphData != glyphData) + break; + } + m_item.item.length = endOfRun; + m_indexOfNextScriptRun = m_item.item.pos + endOfRun; } setupFontForScriptRun(); @@ -358,9 +375,7 @@ private: void setupFontForScriptRun() { - const FontData* fontData = m_font->fontDataAt(0); - if (!fontData->containsCharacters(m_item.string + m_item.item.pos, m_item.item.length)) - fontData = m_font->fontDataForCharacters(m_item.string + m_item.item.pos, m_item.item.length); + const FontData* fontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false, false).fontData; const FontPlatformData& platformData = fontData->fontDataForCharacter(' ')->platformData(); m_item.face = platformData.harfbuzzFace(); void* opaquePlatformData = const_cast<FontPlatformData*>(&platformData); @@ -590,7 +605,7 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int x, if (walker.rtl()) basePosition -= walker.numCodePoints(); - if (x < walker.width()) { + if (x >= 0 && x < walker.width()) { // The x value in question is within this script run. We consider // each glyph in presentation order and stop when we find the one // covering this position. diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp index 2475e65..7b22bad 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp @@ -148,7 +148,7 @@ void FontPlatformData::setupPaint(SkPaint* paint) const paint->setFakeBoldText(m_fakeBold); paint->setTextSkewX(m_fakeItalic ? -SK_Scalar1 / 4 : 0); - if (m_style.useAntiAlias == 1 || m_style.useAntiAlias == FontRenderStyle::NoPreference && isSkiaAntiAlias) + if (m_style.useAntiAlias == 1 || (m_style.useAntiAlias == FontRenderStyle::NoPreference && isSkiaAntiAlias)) paint->setLCDRenderText(m_style.useSubpixel == FontRenderStyle::NoPreference ? isSkiaSubpixelGlyphs : m_style.useSubpixel); } diff --git a/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp b/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp index be3b0d0..4fd3ba0 100644 --- a/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp +++ b/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp @@ -139,7 +139,7 @@ static HB_Error getOutlinePoint(HB_Font hbFont, HB_Glyph glyph, int flags, hb_ui uint16_t glyph16 = glyph; SkPath path; paint.getTextPath(&glyph16, sizeof(glyph16), 0, 0, &path); - int numPoints = path.getPoints(NULL, 0); + int numPoints = path.getPoints(0, 0); if (point >= numPoints) return HB_Err_Invalid_SubTable; SkPoint* points = reinterpret_cast<SkPoint*>(fastMalloc(sizeof(SkPoint) * (point + 1))); diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp index 72bbfb4..f3d8b86 100644 --- a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp @@ -151,7 +151,12 @@ void SimpleFontData::determinePitch() ReleaseDC(0, dc); } -GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const +{ + return FloatRect(); +} + +float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { HDC dc = GetDC(0); HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont()); @@ -170,9 +175,7 @@ GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMo SelectObject(dc, oldFont); ReleaseDC(0, dc); - GlyphMetrics metrics; - metrics.horizontalAdvance = static_cast<float>(width); - return metrics; + return static_cast<float>(width); } } // namespace WebCore diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp index 8c639aa..d03c615 100644 --- a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp +++ b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp @@ -172,7 +172,12 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = platformData().isFixedPitch(); } -GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode /* metricsMode */) const +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const +{ + return FloatRect(); +} + +float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { SkASSERT(sizeof(glyph) == 2); // compile-time assert @@ -186,9 +191,7 @@ GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMo // Though WebKit supports non-integral advances, Skia only supports them // for "subpixel" (distinct from LCD subpixel antialiasing) text, which // we don't use. - GlyphMetrics metrics; - metrics.horizontalAdvance = round(SkScalarToFloat(width)); - return metrics; + return round(SkScalarToFloat(width)); } } // namespace WebCore diff --git a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp index 0afb971..8f6c9e0 100644 --- a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp @@ -1111,6 +1111,7 @@ void MediaPlayerPrivateGStreamer::didEnd() float now = currentTime(); if (now > 0) { m_mediaDuration = now; + m_mediaDurationKnown = true; m_player->durationChanged(); } diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp b/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp index 0ed5393..bdfe237 100644 --- a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp +++ b/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp @@ -84,9 +84,9 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes { if (!m_smallCapsFontData) { FontDescription desc = FontDescription(fontDescription); - desc.setSpecifiedSize(0.70f*fontDescription.computedSize()); - const FontPlatformData* pdata = new FontPlatformData(desc, desc.family().family()); - m_smallCapsFontData = new SimpleFontData(*pdata); + desc.setSpecifiedSize(0.70f * fontDescription.computedSize()); + FontPlatformData platformData(desc, desc.family().family()); + m_smallCapsFontData = new SimpleFontData(platformData); } return m_smallCapsFontData; } @@ -119,7 +119,12 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = m_platformData.isFixedPitch(); } -GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const +{ + return FloatRect(); +} + +float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { ASSERT(m_platformData.m_scaledFont); @@ -127,13 +132,11 @@ GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMo cairo_text_extents_t extents; cairo_scaled_font_glyph_extents(m_platformData.m_scaledFont, &cglyph, 1, &extents); - float w = (float)m_spaceWidth; + float width = (float)m_spaceWidth; if (cairo_scaled_font_status(m_platformData.m_scaledFont) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0) - w = (float)extents.x_advance; - - GlyphMetrics metrics; - metrics.horizontalAdvance = w; - return metrics; + width = (float)extents.x_advance; + + return width; } } diff --git a/WebCore/platform/graphics/haiku/ImageBufferData.h b/WebCore/platform/graphics/haiku/ImageBufferData.h index f978c34..7c676cd 100644 --- a/WebCore/platform/graphics/haiku/ImageBufferData.h +++ b/WebCore/platform/graphics/haiku/ImageBufferData.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Maxime Simon <simon.maxime@gmail.com> + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * All rights reserved. * @@ -28,16 +28,23 @@ #ifndef ImageBufferData_h #define ImageBufferData_h +#include <Bitmap.h> +#include <View.h> + namespace WebCore { - class IntSize; +class IntSize; + +class ImageBufferData { +public: + ImageBufferData(const IntSize&); + ~ImageBufferData(); - class ImageBufferData { - public: - ImageBufferData(const IntSize&); - }; + BBitmap m_bitmap; + BView m_view; +}; -} // namespace WebCore +} // namespace WebCore -#endif // ImageBufferData_h +#endif // ImageBufferData_h diff --git a/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp b/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp index 276c968..44943d7 100644 --- a/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp +++ b/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Maxime Simon <simon.maxime@gmail.com> + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -20,28 +20,56 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "ImageBuffer.h" +#include "Base64.h" #include "GraphicsContext.h" #include "ImageData.h" -#include "NotImplemented.h" - +#include "MIMETypeRegistry.h" +#include "StillImageHaiku.h" +#include <wtf/text/CString.h> +#include <BitmapStream.h> +#include <String.h> +#include <TranslatorRoster.h> namespace WebCore { -ImageBufferData::ImageBufferData(const IntSize&) +ImageBufferData::ImageBufferData(const IntSize& size) + : m_bitmap(BRect(0, 0, size.width() - 1, size.height() - 1), B_RGBA32, true) + , m_view(m_bitmap.Bounds(), "WebKit ImageBufferData", 0, 0) { + // Always keep the bitmap locked, we are the only client. + m_bitmap.Lock(); + m_bitmap.AddChild(&m_view); + + // Fill with completely transparent color. + memset(m_bitmap.Bits(), 0, m_bitmap.BitsLength()); + + // Since ImageBuffer is used mainly for Canvas, explicitly initialize + // its view's graphics state with the corresponding canvas defaults + // NOTE: keep in sync with CanvasRenderingContext2D::State + m_view.SetLineMode(B_BUTT_CAP, B_MITER_JOIN, 10); + m_view.SetDrawingMode(B_OP_ALPHA); + m_view.SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE); } -ImageBuffer::ImageBuffer(const IntSize&, ImageColorSpace imageColorSpace, bool& success) - : m_data(IntSize()) +ImageBufferData::~ImageBufferData() { - notImplemented(); - success = false; + // Remove the view from the bitmap, keeping it from being free'd twice. + m_view.RemoveSelf(); + m_bitmap.Unlock(); +} + +ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, bool& success) + : m_data(size) + , m_size(size) +{ + m_context.set(new GraphicsContext(&m_data.m_view)); + success = true; } ImageBuffer::~ImageBuffer() @@ -50,47 +78,296 @@ ImageBuffer::~ImageBuffer() GraphicsContext* ImageBuffer::context() const { - notImplemented(); - return 0; + ASSERT(m_data.m_view.Window()); + + return m_context.get(); } -PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const +Image* ImageBuffer::image() const { - notImplemented(); - return 0; + if (!m_image) { + // It's assumed that if image() is called, the actual rendering to the + // GraphicsContext must be done. + ASSERT(context()); + m_data.m_view.Sync(); + m_image = StillImage::create(m_data.m_bitmap); + } + + return m_image.get(); } -PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const +void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) { - notImplemented(); - return 0; + uint8* rowData = reinterpret_cast<uint8*>(m_data.m_bitmap.Bits()); + unsigned bytesPerRow = m_data.m_bitmap.BytesPerRow(); + unsigned rows = m_size.height(); + unsigned columns = m_size.width(); + for (unsigned y = 0; y < rows; y++) { + uint8* pixel = rowData; + for (unsigned x = 0; x < columns; x++) { + // lookUpTable doesn't seem to support a LUT for each color channel + // separately (judging from the other ports). We don't need to + // convert from/to pre-multiplied color space since BBitmap storage + // is not pre-multiplied. + pixel[0] = lookUpTable[pixel[0]]; + pixel[1] = lookUpTable[pixel[1]]; + pixel[2] = lookUpTable[pixel[2]]; + // alpha stays unmodified. + pixel += 4; + } + rowData += bytesPerRow; + } } -void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) +static inline void convertFromData(const uint8* sourceRows, unsigned sourceBytesPerRow, + uint8* destRows, unsigned destBytesPerRow, + unsigned rows, unsigned columns) { - notImplemented(); + for (unsigned y = 0; y < rows; y++) { + const uint8* sourcePixel = sourceRows; + uint8* destPixel = destRows; + for (unsigned x = 0; x < columns; x++) { + // RGBA -> BGRA or BGRA -> RGBA + destPixel[0] = sourcePixel[2]; + destPixel[1] = sourcePixel[1]; + destPixel[2] = sourcePixel[0]; + destPixel[3] = sourcePixel[3]; + destPixel += 4; + sourcePixel += 4; + } + sourceRows += sourceBytesPerRow; + destRows += destBytesPerRow; + } } -void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) +static inline void convertFromInternalData(const uint8* sourceRows, unsigned sourceBytesPerRow, + uint8* destRows, unsigned destBytesPerRow, + unsigned rows, unsigned columns, + bool premultiplied) { - notImplemented(); + if (premultiplied) { + // Internal storage is not pre-multiplied, pre-multiply on the fly. + for (unsigned y = 0; y < rows; y++) { + const uint8* sourcePixel = sourceRows; + uint8* destPixel = destRows; + for (unsigned x = 0; x < columns; x++) { + // RGBA -> BGRA or BGRA -> RGBA + destPixel[0] = static_cast<uint16>(sourcePixel[2]) * sourcePixel[3] / 255; + destPixel[1] = static_cast<uint16>(sourcePixel[1]) * sourcePixel[3] / 255; + destPixel[2] = static_cast<uint16>(sourcePixel[0]) * sourcePixel[3] / 255; + destPixel[3] = sourcePixel[3]; + destPixel += 4; + sourcePixel += 4; + } + sourceRows += sourceBytesPerRow; + destRows += destBytesPerRow; + } + } else { + convertFromData(sourceRows, sourceBytesPerRow, + destRows, destBytesPerRow, + rows, columns); + } } -String ImageBuffer::toDataURL(const String&) const +static inline void convertToInternalData(const uint8* sourceRows, unsigned sourceBytesPerRow, + uint8* destRows, unsigned destBytesPerRow, + unsigned rows, unsigned columns, + bool premultiplied) { - notImplemented(); - return String(); + if (premultiplied) { + // Internal storage is not pre-multiplied, de-multiply source data. + for (unsigned y = 0; y < rows; y++) { + const uint8* sourcePixel = sourceRows; + uint8* destPixel = destRows; + for (unsigned x = 0; x < columns; x++) { + // RGBA -> BGRA or BGRA -> RGBA + if (sourcePixel[3]) { + destPixel[0] = static_cast<uint16>(sourcePixel[2]) * 255 / sourcePixel[3]; + destPixel[1] = static_cast<uint16>(sourcePixel[1]) * 255 / sourcePixel[3]; + destPixel[2] = static_cast<uint16>(sourcePixel[0]) * 255 / sourcePixel[3]; + destPixel[3] = sourcePixel[3]; + } else { + destPixel[0] = 0; + destPixel[1] = 0; + destPixel[2] = 0; + destPixel[3] = 0; + } + destPixel += 4; + sourcePixel += 4; + } + sourceRows += sourceBytesPerRow; + destRows += destBytesPerRow; + } + } else { + convertFromData(sourceRows, sourceBytesPerRow, + destRows, destBytesPerRow, + rows, columns); + } } -Image* ImageBuffer::image() const +static PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size, bool premultiplied) +{ + PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height()); + unsigned char* data = result->data()->data()->data(); + + // If the destination image is larger than the source image, the outside + // regions need to be transparent. This way is simply, although with a + // a slight overhead for the inside region. + if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > size.width() || (rect.y() + rect.height()) > size.height()) + memset(data, 0, result->data()->length()); + + // If the requested image is outside the source image, we can return at + // this point. + if (rect.x() > size.width() || rect.y() > size.height() || rect.right() < 0 || rect.bottom() < 0) + return result; + + // Now we know there must be an intersection rect which we need to extract. + BRect sourceRect(0, 0, size.width() - 1, size.height() - 1); + sourceRect = BRect(rect) & sourceRect; + + unsigned destBytesPerRow = 4 * rect.width(); + unsigned char* destRows = data; + // Offset the destination pointer to point at the first pixel of the + // intersection rect. + destRows += (rect.x() - static_cast<int>(sourceRect.left)) * 4 + + (rect.y() - static_cast<int>(sourceRect.top)) * destBytesPerRow; + + const uint8* sourceRows = reinterpret_cast<const uint8*>(imageData.m_bitmap.Bits()); + uint32 sourceBytesPerRow = imageData.m_bitmap.BytesPerRow(); + // Offset the source pointer to point at the first pixel of the + // intersection rect. + sourceRows += static_cast<int>(sourceRect.left) * 4 + + static_cast<int>(sourceRect.top) * sourceBytesPerRow; + + unsigned rows = sourceRect.IntegerHeight() + 1; + unsigned columns = sourceRect.IntegerWidth() + 1; + convertFromInternalData(sourceRows, sourceBytesPerRow, destRows, destBytesPerRow, + rows, columns, premultiplied); + + return result; +} + + +PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const { - notImplemented(); - return 0; + // Make sure all asynchronous drawing has finished + m_data.m_view.Sync(); + return getImageData(rect, m_data, m_size, false); } -void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) +PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const +{ + // Make sure all asynchronous drawing has finished + m_data.m_view.Sync(); + return getImageData(rect, m_data, m_size, true); +} + +static void putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& imageData, const IntSize& size, bool premultiplied) +{ + // If the source image is outside the destination image, we can return at + // this point. + // FIXME: Check if this isn't already done in WebCore. + if (destPoint.x() > size.width() || destPoint.y() > size.height() + || destPoint.x() + sourceRect.width() < 0 + || destPoint.y() + sourceRect.height() < 0) { + return; + } + + const unsigned char* sourceRows = source->data()->data()->data(); + unsigned sourceBytesPerRow = 4 * source->width(); + // Offset the source pointer to the first pixel of the source rect. + sourceRows += sourceRect.x() * 4 + sourceRect.y() * sourceBytesPerRow; + + // We know there must be an intersection rect. + BRect destRect(destPoint.x(), destPoint.y(), sourceRect.width() - 1, sourceRect.height() - 1); + destRect = destRect & BRect(0, 0, size.width() - 1, size.height() - 1); + + unsigned char* destRows = reinterpret_cast<unsigned char*>(imageData.m_bitmap.Bits()); + uint32 destBytesPerRow = imageData.m_bitmap.BytesPerRow(); + // Offset the source pointer to point at the first pixel of the + // intersection rect. + destRows += static_cast<int>(destRect.left) * 4 + + static_cast<int>(destRect.top) * destBytesPerRow; + + unsigned rows = sourceRect.height(); + unsigned columns = sourceRect.width(); + convertToInternalData(sourceRows, sourceBytesPerRow, destRows, destBytesPerRow, + rows, columns, premultiplied); +} + +void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) +{ + // Make sure all asynchronous drawing has finished + m_data.m_view.Sync(); + putImageData(source, sourceRect, destPoint, m_data, m_size, false); +} + +void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) { - notImplemented(); + // Make sure all asynchronous drawing has finished + m_data.m_view.Sync(); + putImageData(source, sourceRect, destPoint, m_data, m_size, true); +} + +String ImageBuffer::toDataURL(const String& mimeType) const +{ + if (!MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)) + return "data:,"; + + BString mimeTypeString(mimeType); + + uint32 translatorType = 0; + + BTranslatorRoster* roster = BTranslatorRoster::Default(); + translator_id* translators; + int32 translatorCount; + roster->GetAllTranslators(&translators, &translatorCount); + for (int32 i = 0; i < translatorCount; i++) { + // Skip translators that don't support archived BBitmaps as input data. + const translation_format* inputFormats; + int32 formatCount; + roster->GetInputFormats(translators[i], &inputFormats, &formatCount); + bool supportsBitmaps = false; + for (int32 j = 0; j < formatCount; j++) { + if (inputFormats[j].type == B_TRANSLATOR_BITMAP) { + supportsBitmaps = true; + break; + } + } + if (!supportsBitmaps) + continue; + + const translation_format* outputFormats; + roster->GetOutputFormats(translators[i], &outputFormats, &formatCount); + for (int32 j = 0; j < formatCount; j++) { + if (outputFormats[j].group == B_TRANSLATOR_BITMAP + && mimeTypeString == outputFormats[j].MIME) { + translatorType = outputFormats[j].type; + } + } + if (translatorType) + break; + } + + + BMallocIO translatedStream; + BBitmap* bitmap = const_cast<BBitmap*>(&m_data.m_bitmap); + // BBitmapStream doesn't take "const Bitmap*"... + BBitmapStream bitmapStream(bitmap); + if (roster->Translate(&bitmapStream, 0, 0, &translatedStream, translatorType, + B_TRANSLATOR_BITMAP, mimeType.utf8().data()) != B_OK) { + bitmapStream.DetachBitmap(&bitmap); + return "data:,"; + } + + bitmapStream.DetachBitmap(&bitmap); + + Vector<char> encodedBuffer; + base64Encode(reinterpret_cast<const char*>(translatedStream.Buffer()), + translatedStream.BufferLength(), encodedBuffer); + + return String::format("data:%s;base64,%s", mimeType.utf8().data(), + encodedBuffer.data()); } } // namespace WebCore diff --git a/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp b/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp index f429ab5..96027cc 100644 --- a/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp +++ b/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp @@ -34,18 +34,15 @@ #include "FontCache.h" #include "FontDescription.h" #include "NotImplemented.h" -#include <Rect.h> -#include <unicode/uchar.h> -#include <unicode/unorm.h> +#include "TextEncoding.h" +#include <wtf/text/CString.h> -extern int charUnicodeToUTF8HACK(unsigned short, char*); - namespace WebCore { void SimpleFontData::platformInit() { - BFont* font = m_platformData.font(); + const BFont* font = m_platformData.font(); if (!font) return; @@ -76,8 +73,8 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes if (!m_smallCapsFontData) { FontDescription desc = FontDescription(fontDescription); desc.setSpecifiedSize(0.70f * fontDescription.computedSize()); - const FontPlatformData* fontPlatformData = new FontPlatformData(desc, desc.family().family()); - m_smallCapsFontData = new SimpleFontData(*fontPlatformData); + FontPlatformData fontPlatformData(desc, desc.family().family()); + m_smallCapsFontData = new SimpleFontData(fontPlatformData); } return m_smallCapsFontData; } @@ -95,15 +92,14 @@ void SimpleFontData::determinePitch() GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const { + GlyphMetrics metrics; if (!m_platformData.font()) - return 0; + return metrics; - char charArray[4]; + CString encoded = UTF8Encoding().encode(static_cast<UChar*>(&glyph), 1, + URLEncodedEntitiesForUnencodables); float escapements[1]; - - charUnicodeToUTF8HACK(glyph, charArray); - m_platformData.font()->GetEscapements(charArray, 1, escapements); - GlyphMetrics metrics; + m_platformData.font()->GetEscapements(encoded.data(), 1, escapements); metrics.horizontalAdvance = escapements[0] * m_platformData.font()->Size(); return metrics; } diff --git a/WebCore/platform/graphics/mac/ComplexTextController.cpp b/WebCore/platform/graphics/mac/ComplexTextController.cpp index b501293..efb92f8 100644 --- a/WebCore/platform/graphics/mac/ComplexTextController.cpp +++ b/WebCore/platform/graphics/mac/ComplexTextController.cpp @@ -25,7 +25,9 @@ #include "config.h" #include "ComplexTextController.h" +#include <ApplicationServices/ApplicationServices.h> #include "CharacterNames.h" +#include "FloatSize.h" #include "Font.h" #include "TextBreakIterator.h" @@ -547,12 +549,12 @@ void ComplexTextController::adjustGlyphsAndAdvances() m_adjustedAdvances.append(advance); m_adjustedGlyphs.append(glyph); - GlyphMetrics glyphMetrics = fontData->metricsForGlyph(glyph); - glyphMetrics.boundingBox.move(glyphOrigin.x, glyphOrigin.y); - m_minGlyphBoundingBoxX = min(m_minGlyphBoundingBoxX, glyphMetrics.boundingBox.x()); - m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphMetrics.boundingBox.right()); - m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, glyphMetrics.boundingBox.y()); - m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphMetrics.boundingBox.bottom()); + FloatRect glyphBounds = fontData->boundsForGlyph(glyph); + glyphBounds.move(glyphOrigin.x, glyphOrigin.y); + m_minGlyphBoundingBoxX = min(m_minGlyphBoundingBoxX, glyphBounds.x()); + m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphBounds.right()); + m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, glyphBounds.y()); + m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphBounds.bottom()); glyphOrigin.x += advance.width; glyphOrigin.y += advance.height; diff --git a/WebCore/platform/graphics/mac/ComplexTextController.h b/WebCore/platform/graphics/mac/ComplexTextController.h index 280327f..55cde29 100644 --- a/WebCore/platform/graphics/mac/ComplexTextController.h +++ b/WebCore/platform/graphics/mac/ComplexTextController.h @@ -25,6 +25,7 @@ #ifndef ComplexTextController_h #define ComplexTextController_h +#include <ApplicationServices/ApplicationServices.h> #include "GlyphBuffer.h" #include <wtf/HashSet.h> #include <wtf/PassRefPtr.h> diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp index 82c314e..af210df 100644 --- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp +++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp @@ -235,6 +235,11 @@ void GraphicsContext3D::endPaint() { } +bool GraphicsContext3D::isGLES2Compliant() const +{ + return false; +} + void GraphicsContext3D::reshape(int width, int height) { if (width == m_currentWidth && height == m_currentHeight || !m_contextObj) @@ -1141,8 +1146,20 @@ void GraphicsContext3D::getFramebufferAttachmentParameteriv(unsigned long target void GraphicsContext3D::getIntegerv(unsigned long pname, int* value) { - ensureContext(m_contextObj); - ::glGetIntegerv(pname, value); + // Need to emulate IMPLEMENTATION_COLOR_READ_FORMAT/TYPE for GL. Any valid + // combination should work, but GL_RGB/GL_UNSIGNED_BYTE might be the most + // useful for desktop WebGL users. + ensureContext(m_contextObj); + switch (pname) { + case IMPLEMENTATION_COLOR_READ_FORMAT: + *value = GL_RGB; + break; + case IMPLEMENTATION_COLOR_READ_TYPE: + *value = GL_UNSIGNED_BYTE; + break; + default: + ::glGetIntegerv(pname, value); + } } void GraphicsContext3D::getProgramiv(WebGLProgram* program, unsigned long pname, int* value) @@ -1278,39 +1295,18 @@ long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels) { - // FIXME: Need to do bounds checking on the buffer here. + ensureContext(m_contextObj); + ::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); return 0; } -int GraphicsContext3D::texImage2D(unsigned target, unsigned level, Image* image, bool flipY, bool premultiplyAlpha) -{ - ensureContext(m_contextObj); - Vector<uint8_t> imageData; - unsigned int format, internalFormat; - if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) - return -1; - ::glTexImage2D(target, level, internalFormat, image->width(), image->height(), 0, format, GL_UNSIGNED_BYTE, imageData.data()); - return 0; -} - int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, void* pixels) { - // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size - // FIXME: Need to do bounds checking on the buffer here. - ::glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels); - return 0; -} + ensureContext(m_contextObj); -int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, Image* image, bool flipY, bool premultiplyAlpha) -{ // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size - ensureContext(m_contextObj); - Vector<uint8_t> imageData; - unsigned int format, internalFormat; - if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) - return -1; - ::glTexSubImage2D(target, level, xoff, yoff, image->width(), image->height(), format, GL_UNSIGNED_BYTE, imageData.data()); + ::glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels); return 0; } diff --git a/WebCore/platform/graphics/mac/SimpleFontDataATSUI.mm b/WebCore/platform/graphics/mac/SimpleFontDataATSUI.mm new file mode 100644 index 0000000..beea018 --- /dev/null +++ b/WebCore/platform/graphics/mac/SimpleFontDataATSUI.mm @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Alexey Proskuryakov + * + * 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. + */ + +#import "config.h" +#import "SimpleFontData.h" + +#if USE(ATSUI) + +#import "Font.h" +#import "FontCache.h" +#import "FontDescription.h" +#import <ApplicationServices/ApplicationServices.h> +#import <AppKit/AppKit.h> +#import <wtf/Assertions.h> + +using namespace std; + +namespace WebCore { + +void SimpleFontData::checkShapesArabic() const +{ + ASSERT(!m_checkedShapesArabic); + + m_checkedShapesArabic = true; + + ATSUFontID fontID = m_platformData.m_atsuFontID; + if (!fontID) { + LOG_ERROR("unable to get ATSUFontID for %@", m_platformData.font()); + return; + } + + // This function is called only on fonts that contain Arabic glyphs. Our + // heuristic is that if such a font has a glyph metamorphosis table, then + // it includes shaping information for Arabic. + FourCharCode tables[] = { 'morx', 'mort' }; + for (unsigned i = 0; i < sizeof(tables) / sizeof(tables[0]); ++i) { + ByteCount tableSize; + OSStatus status = ATSFontGetTable(fontID, tables[i], 0, 0, 0, &tableSize); + if (status == noErr) { + m_shapesArabic = true; + return; + } + + if (status != kATSInvalidFontTableAccess) + LOG_ERROR("ATSFontGetTable failed (%d)", status); + } +} + +} // namespace WebCore + +#endif diff --git a/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp b/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp new file mode 100644 index 0000000..fc67a19 --- /dev/null +++ b/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Alexey Proskuryakov + * + * 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. + */ + +#import "config.h" +#import "SimpleFontData.h" + +#if USE(CORE_TEXT) + +#import "Font.h" +#import "FontCache.h" +#import "FontDescription.h" +#import <ApplicationServices/ApplicationServices.h> + +using namespace std; + +namespace WebCore { + +CTFontRef SimpleFontData::getCTFont() const +{ + if (getNSFont()) + return toCTFontRef(getNSFont()); + if (!m_CTFont) + m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_platformData.cgFont(), m_platformData.size(), 0, 0)); + return m_CTFont.get(); +} + +CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typesettingFeatures) const +{ + unsigned key = typesettingFeatures + 1; + pair<HashMap<unsigned, RetainPtr<CFDictionaryRef> >::iterator, bool> addResult = m_CFStringAttributes.add(key, RetainPtr<CFDictionaryRef>()); + RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.first->second; + if (!addResult.second) + return attributesDictionary.get(); + + bool allowLigatures = platformData().allowsLigatures() || (typesettingFeatures & Ligatures); + + static const int ligaturesNotAllowedValue = 0; + static CFNumberRef ligaturesNotAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesNotAllowedValue); + + static const int ligaturesAllowedValue = 1; + static CFNumberRef ligaturesAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesAllowedValue); + + if (!(typesettingFeatures & Kerning)) { + static const float kerningAdjustmentValue = 0; + static CFNumberRef kerningAdjustment = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &kerningAdjustmentValue); + static const void* keysWithKerningDisabled[] = { kCTFontAttributeName, kCTKernAttributeName, kCTLigatureAttributeName }; + const void* valuesWithKerningDisabled[] = { getCTFont(), kerningAdjustment, allowLigatures + ? ligaturesAllowed : ligaturesNotAllowed }; + attributesDictionary.adoptCF(CFDictionaryCreate(0, keysWithKerningDisabled, valuesWithKerningDisabled, + sizeof(keysWithKerningDisabled) / sizeof(*keysWithKerningDisabled), + &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + } else { + // By omitting the kCTKernAttributeName attribute, we get Core Text's standard kerning. + static const void* keysWithKerningEnabled[] = { kCTFontAttributeName, kCTLigatureAttributeName }; + const void* valuesWithKerningEnabled[] = { getCTFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed }; + attributesDictionary.adoptCF(CFDictionaryCreate(0, keysWithKerningEnabled, valuesWithKerningEnabled, + sizeof(keysWithKerningEnabled) / sizeof(*keysWithKerningEnabled), + &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + } + + return attributesDictionary.get(); +} + +} // namespace WebCore + +#endif diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm index 562f56e..7f1a72e 100644 --- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm +++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm @@ -45,6 +45,7 @@ #import <wtf/Assertions.h> #import <wtf/StdLibExtras.h> #import <wtf/RetainPtr.h> +#import <wtf/UnusedParam.h> @interface NSFont (WebAppKitSecretAPI) - (BOOL)_isFakeFixedPitch; @@ -407,7 +408,24 @@ void SimpleFontData::determinePitch() [name caseInsensitiveCompare:@"MonotypeCorsiva"] != NSOrderedSame; } -GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode metricsMode) const +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const +{ + FloatRect boundingBox; +#ifndef BUILDING_ON_TIGER + CGRect box; + CGFontGetGlyphBBoxes(platformData().cgFont(), &glyph, 1, &box); + float pointSize = platformData().m_size; + CGFloat scale = pointSize / unitsPerEm(); + boundingBox = CGRectApplyAffineTransform(box, CGAffineTransformMakeScale(scale, -scale)); + if (m_syntheticBoldOffset) + boundingBox.setWidth(boundingBox.width() + m_syntheticBoldOffset); +#else + UNUSED_PARAM(glyph); +#endif + return boundingBox; +} + +float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { NSFont* font = platformData().font(); float pointSize = platformData().m_size; @@ -417,99 +435,7 @@ GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMo LOG_ERROR("Unable to cache glyph widths for %@ %f", [font displayName], pointSize); advance.width = 0; } - GlyphMetrics metrics; - metrics.horizontalAdvance = advance.width + m_syntheticBoldOffset; - if (metricsMode == GlyphBoundingBox) { -#ifndef BUILDING_ON_TIGER - CGRect boundingBox; - CGFontGetGlyphBBoxes(platformData().cgFont(), &glyph, 1, &boundingBox); - CGFloat scale = pointSize / unitsPerEm(); - metrics.boundingBox = CGRectApplyAffineTransform(boundingBox, CGAffineTransformMakeScale(scale, -scale)); - if (m_syntheticBoldOffset) - metrics.boundingBox.setWidth(metrics.boundingBox.width() + m_syntheticBoldOffset); -#endif - } - return metrics; -} - -#if USE(ATSUI) -void SimpleFontData::checkShapesArabic() const -{ - ASSERT(!m_checkedShapesArabic); - - m_checkedShapesArabic = true; - - ATSUFontID fontID = m_platformData.m_atsuFontID; - if (!fontID) { - LOG_ERROR("unable to get ATSUFontID for %@", m_platformData.font()); - return; - } - - // This function is called only on fonts that contain Arabic glyphs. Our - // heuristic is that if such a font has a glyph metamorphosis table, then - // it includes shaping information for Arabic. - FourCharCode tables[] = { 'morx', 'mort' }; - for (unsigned i = 0; i < sizeof(tables) / sizeof(tables[0]); ++i) { - ByteCount tableSize; - OSStatus status = ATSFontGetTable(fontID, tables[i], 0, 0, 0, &tableSize); - if (status == noErr) { - m_shapesArabic = true; - return; - } - - if (status != kATSInvalidFontTableAccess) - LOG_ERROR("ATSFontGetTable failed (%d)", status); - } -} -#endif - -#if USE(CORE_TEXT) -CTFontRef SimpleFontData::getCTFont() const -{ - if (getNSFont()) - return toCTFontRef(getNSFont()); - if (!m_CTFont) - m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_platformData.cgFont(), m_platformData.size(), NULL, NULL)); - return m_CTFont.get(); -} - -CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typesettingFeatures) const -{ - unsigned key = typesettingFeatures + 1; - pair<HashMap<unsigned, RetainPtr<CFDictionaryRef> >::iterator, bool> addResult = m_CFStringAttributes.add(key, RetainPtr<CFDictionaryRef>()); - RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.first->second; - if (!addResult.second) - return attributesDictionary.get(); - - bool allowLigatures = platformData().allowsLigatures() || (typesettingFeatures & Ligatures); - - static const int ligaturesNotAllowedValue = 0; - static CFNumberRef ligaturesNotAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesNotAllowedValue); - - static const int ligaturesAllowedValue = 1; - static CFNumberRef ligaturesAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesAllowedValue); - - if (!(typesettingFeatures & Kerning)) { - static const float kerningAdjustmentValue = 0; - static CFNumberRef kerningAdjustment = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &kerningAdjustmentValue); - static const void* keysWithKerningDisabled[] = { kCTFontAttributeName, kCTKernAttributeName, kCTLigatureAttributeName }; - const void* valuesWithKerningDisabled[] = { getCTFont(), kerningAdjustment, allowLigatures - ? ligaturesAllowed : ligaturesNotAllowed }; - attributesDictionary.adoptCF(CFDictionaryCreate(NULL, keysWithKerningDisabled, valuesWithKerningDisabled, - sizeof(keysWithKerningDisabled) / sizeof(*keysWithKerningDisabled), - &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); - } else { - // By omitting the kCTKernAttributeName attribute, we get Core Text's standard kerning. - static const void* keysWithKerningEnabled[] = { kCTFontAttributeName, kCTLigatureAttributeName }; - const void* valuesWithKerningEnabled[] = { getCTFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed }; - attributesDictionary.adoptCF(CFDictionaryCreate(NULL, keysWithKerningEnabled, valuesWithKerningEnabled, - sizeof(keysWithKerningEnabled) / sizeof(*keysWithKerningEnabled), - &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); - } - - return attributesDictionary.get(); + return advance.width + m_syntheticBoldOffset; } -#endif - } // namespace WebCore diff --git a/WebCore/platform/graphics/opentype/OpenTypeSanitizer.cpp b/WebCore/platform/graphics/opentype/OpenTypeSanitizer.cpp index b4cdb09..14aed0d 100644 --- a/WebCore/platform/graphics/opentype/OpenTypeSanitizer.cpp +++ b/WebCore/platform/graphics/opentype/OpenTypeSanitizer.cpp @@ -52,15 +52,16 @@ PassRefPtr<SharedBuffer> OpenTypeSanitizer::sanitize() // A transcoded font is usually smaller than an original font. // However, it can be slightly bigger than the original one due to // name table replacement and/or padding for glyf table. - static const size_t padLen = 20 * 1024; // 20 kB + // + // With WOFF fonts, however, we'll be decompressing, so the result can be + // much larger than the original. - OwnArrayPtr<unsigned char> transcodeRawBuffer(new unsigned char[m_buffer->size() + padLen]); - ots::MemoryStream output(transcodeRawBuffer.get(), m_buffer->size() + padLen); + ots::ExpandingMemoryStream output(m_buffer->size(), maxWebFontSize); if (!ots::Process(&output, reinterpret_cast<const uint8_t*>(m_buffer->data()), m_buffer->size())) return 0; const size_t transcodeLen = output.Tell(); - return SharedBuffer::create(transcodeRawBuffer.get(), transcodeLen); + return SharedBuffer::create(static_cast<unsigned char*>(output.get()), transcodeLen); } } // namespace WebCore diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp index 974c179..946faeb 100644 --- a/WebCore/platform/graphics/qt/FontQt.cpp +++ b/WebCore/platform/graphics/qt/FontQt.cpp @@ -180,13 +180,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); QString string = fromRawDataWithoutRef(sanitized); - QTextLayout layout(string, font()); - QTextLine line = setupLayout(&layout, run); -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) - int w = int(line.horizontalAdvance()); -#else - int w = int(line.naturalTextWidth()); -#endif + int w = QFontMetrics(font()).width(string); // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does) if (treatAsSpace(run[0])) w -= m_wordSpacing; diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp index b0dd289..8dfb967 100644 --- a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp @@ -154,8 +154,7 @@ public: ~GraphicsContext3DInternal(); bool isContextValid() { return m_contextValid; } - - + QGLWidget* getOwnerGLWidget(QWebPageClient* webPageClient); glActiveTextureType activeTexture; glAttachShaderType attachShader; @@ -248,6 +247,7 @@ public: glVertexAttribPointerType vertexAttribPointer; GraphicsContext3D::Attributes m_attrs; + HostWindow* m_hostWindow; QGLWidget* m_glWidget; GLuint m_texture; GLuint m_mainFbo; @@ -258,7 +258,6 @@ public: private: - QGLWidget* getOwnerGLWidget(QWebPageClient* webPageClient); void* getProcAddress(const String& proc); bool m_contextValid; }; @@ -268,9 +267,20 @@ private: #else #define GET_PROC_ADDRESS(Proc) reinterpret_cast<Proc##Type>(getProcAddress(#Proc)); #endif + +bool GraphicsContext3D::isGLES2Compliant() const +{ +#if defined (QT_OPENGL_ES_2) + return true; +#else + return false; +#endif +} + GraphicsContext3DInternal::GraphicsContext3DInternal(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow) : m_attrs(attrs) + , m_hostWindow(hostWindow) , m_glWidget(0) , m_texture(0) , m_mainFbo(0) @@ -515,7 +525,7 @@ void GraphicsContext3D::beginPaint(WebGLRenderingContext* context) glReadPixels(/* x */ 0, /* y */ 0, m_currentWidth, m_currentHeight, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, m_internal->m_pixels.bits()); QPainter* p = imageBuffer->context()->platformContext(); - p->drawImage(/* x */ 0, /* y */ 0, m_internal->m_pixels.transformed(QMatrix().rotate(180))); + p->drawImage(/* x */ 0, /* y */ 0, m_internal->m_pixels.rgbSwapped().transformed(QMatrix().rotate(180))); m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_currentFbo); } @@ -524,6 +534,23 @@ void GraphicsContext3D::endPaint() { } +void GraphicsContext3D::paint(QPainter* painter, const QRect& rect) const +{ +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + QWebPageClient* webPageClient = m_internal->m_hostWindow->platformPageClient(); + QGLWidget* ownerGLWidget = m_internal->getOwnerGLWidget(webPageClient); + if (ownerGLWidget) { + ownerGLWidget->drawTexture(QPointF(0, 0), m_internal->m_texture); + return; + } +#endif + m_internal->m_glWidget->makeCurrent(); + m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_mainFbo); + glReadPixels(/* x */ 0, /* y */ 0, m_currentWidth, m_currentHeight, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, m_internal->m_pixels.bits()); + painter->drawImage(/* x */ 0, /* y */ 0, m_internal->m_pixels.rgbSwapped().transformed(QMatrix().rotate(180))); + m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_currentFbo); +} + void GraphicsContext3D::reshape(int width, int height) { if (((width == m_currentWidth) && (height == m_currentHeight)) || (!m_internal)) @@ -1466,56 +1493,19 @@ long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels) { + m_internal->m_glWidget->makeCurrent(); glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); return 0; } -int GraphicsContext3D::texImage2D(unsigned target, unsigned level, Image* image, bool flipY, bool premultiplyAlpha) -{ - ASSERT(image); - - m_internal->m_glWidget->makeCurrent(); - - Vector<uint8_t> imageData; - GLuint format; - GLuint internalFormat; - - if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) { - LOG_ERROR("GraphicsContext3D::texImage2D: could not extract Image data"); - return -1; - } - - glTexImage2D(target, level, internalFormat, image->width(), image->height(), - /* border */ 0, format, GraphicsContext3D::UNSIGNED_BYTE, imageData.data()); - - return 0; -} - + int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, void* pixels) { + m_internal->m_glWidget->makeCurrent(); glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels); return 0; } -int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, Image* image, bool flipY, bool premultiplyAlpha) -{ - ASSERT(image); - - Vector<uint8_t> imageData; - GLuint format; - GLuint internalFormat; - - if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) { - LOG_ERROR("GraphicsContext3D::texSubImage2D: could not extract Image data"); - return -1; - } - - glTexSubImage2D(target, level, xoff, yoff, image->width(), image->height(), - format, GraphicsContext3D::UNSIGNED_BYTE, imageData.data()); - - return 0; -} - unsigned GraphicsContext3D::createBuffer() { m_internal->m_glWidget->makeCurrent(); @@ -1630,18 +1620,17 @@ bool GraphicsContext3D::getImageData(Image* image, AlphaOp* neededAlphaOp, unsigned int* format) { - QImage::Format imageFormat = (!premultiplyAlpha) ? - QImage::Format_ARGB32 : - QImage::Format_ARGB32_Premultiplied; - - QPixmap* nativePixmap = image->nativeImageForCurrentFrame(); *hasAlphaChannel = true; - *neededAlphaOp = kAlphaDoNothing; *format = GraphicsContext3D::RGBA; - QImage nativeImage = nativePixmap->toImage().convertToFormat(imageFormat); - outputVector.append(nativeImage.bits(), nativeImage.byteCount()); + *neededAlphaOp = kAlphaDoNothing; + if (!premultiplyAlpha && *hasAlphaChannel) + *neededAlphaOp = kAlphaDoUnmultiply; + + QPixmap* nativePixmap = image->nativeImageForCurrentFrame(); + QImage nativeImage = nativePixmap->toImage().convertToFormat(QImage::Format_ARGB32); + outputVector.append(nativeImage.rgbSwapped().bits(), nativeImage.byteCount()); return true; } diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index edac268..0100b72 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -641,12 +641,12 @@ void GraphicsContext::fillRect(const FloatRect& rect) } } -void GraphicsContext::fillRect(const FloatRect& rect, const Color& c, ColorSpace colorSpace) +void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) { - if (paintingDisabled()) + if (paintingDisabled() || !color.isValid()) return; - m_data->solidColor.setColor(c); + m_data->solidColor.setColor(color); QPainter* p = m_data->p(); if (m_common->state.shadowColor.isValid()) drawBorderlessRectShadow(this, p, rect); @@ -655,7 +655,7 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& c, ColorSpace void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace) { - if (paintingDisabled() || !color.alpha()) + if (paintingDisabled() || !color.isValid() || !color.alpha()) return; Path path = Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight); @@ -717,7 +717,7 @@ void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int of */ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int /* width */, int /* offset */, const Color& color) { - if (paintingDisabled()) + if (paintingDisabled() || !color.isValid()) return; unsigned rectCount = rects.size(); @@ -1141,8 +1141,9 @@ void GraphicsContext::setURLForRect(const KURL&, const IntRect&) void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace) { - if (paintingDisabled()) + if (paintingDisabled() || !color.isValid()) return; + QPainter* p = m_data->p(); QPen newPen(p->pen()); m_data->solidColor.setColor(color); @@ -1172,8 +1173,9 @@ void GraphicsContext::setPlatformStrokeThickness(float thickness) void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace) { - if (paintingDisabled()) + if (paintingDisabled() || !color.isValid()) return; + m_data->solidColor.setColor(color); m_data->p()->setBrush(m_data->solidColor); } diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp index 834cd4f..86c01de 100644 --- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp @@ -32,15 +32,13 @@ #include <QtCore/qmetaobject.h> #include <QtCore/qset.h> #include <QtCore/qtimer.h> -#include <QtGui/qbitmap.h> #include <QtGui/qcolor.h> #include <QtGui/qgraphicseffect.h> #include <QtGui/qgraphicsitem.h> #include <QtGui/qgraphicsscene.h> -#include <QtGui/qmatrix4x4.h> #include <QtGui/qpainter.h> -#include <QtGui/qpalette.h> #include <QtGui/qpixmap.h> +#include <QtGui/qpixmapcache.h> #include <QtGui/qstyleoption.h> namespace WebCore { @@ -132,7 +130,9 @@ public: }; // the compositor lets us special-case images and colors, so we try to do so - enum StaticContentType { HTMLContentType, PixmapContentType, ColorContentType, MediaContentType}; + enum StaticContentType { HTMLContentType, PixmapContentType, ColorContentType, MediaContentType, Canvas3DContentType}; + + const GraphicsLayerQtImpl* rootLayer() const; GraphicsLayerQtImpl(GraphicsLayerQt* newLayer); virtual ~GraphicsLayerQtImpl(); @@ -142,24 +142,25 @@ public: virtual QRectF boundingRect() const; virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*); - // we manage transforms ourselves because transform-origin acts differently in webkit and in Qt + // We manage transforms ourselves because transform-origin acts differently in webkit and in Qt, and we need it as a fallback in case we encounter an un-invertible matrix void setBaseTransform(const TransformationMatrix&); - QTransform computeTransform(const TransformationMatrix& baseTransform) const; void updateTransform(); // let the compositor-API tell us which properties were changed void notifyChange(ChangeMask); + // actual rendering of the web-content into a QPixmap + // We prefer to use our own caching because it gives us a higher level of granularity than QGraphicsItem cache modes - + // sometimes we need to cache the contents even `though the item needs to be updated, e.g. when the background-color is changed. + // TODO: investigate if QGraphicsItem caching can be improved to support that out of the box. + QPixmap recache(const QRegion&); + // called when the compositor is ready for us to show the changes on screen // this is called indirectly from ChromeClientQt::setNeedsOneShotDrawingSynchronization // (meaning the sync would happen together with the next draw) // or ChromeClientQt::scheduleCompositingLayerSync (meaning the sync will happen ASAP) void flushChanges(bool recursive = true, bool forceTransformUpdate = false); - // optimization: returns true if this or an ancestor has a transform animation running. - // this enables us to use ItemCoordinatesCache while the animation is running, otherwise we have to recache for every frame - bool isTransformAnimationRunning() const; - public slots: // we need to notify the client (aka the layer compositor) when the animation actually starts void notifyAnimationStarted(); @@ -175,6 +176,7 @@ public: GraphicsLayerQt* m_layer; TransformationMatrix m_baseTransform; + TransformationMatrix m_transformRelativeToRootLayer; bool m_transformAnimationRunning; bool m_opacityAnimationRunning; QWeakPointer<MaskEffectQt> m_maskEffect; @@ -203,6 +205,7 @@ public: int m_changeMask; QSizeF m_size; + QPixmapCache::Key m_backingStoreKey; #ifndef QT_NO_ANIMATION QList<QWeakPointer<QAbstractAnimation> > m_animations; #endif @@ -236,6 +239,10 @@ public: } } m_state; +#if ENABLE(3D_CANVAS) + const GraphicsContext3D* m_gc3D; +#endif + #ifndef QT_NO_ANIMATION friend class AnimationQtBase; #endif @@ -247,6 +254,9 @@ GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer) , m_transformAnimationRunning(false) , m_opacityAnimationRunning(false) , m_changeMask(NoChanges) +#if ENABLE(3D_CANVAS) + , m_gc3D(0) +#endif { // we use graphics-view for compositing, not for interactivity setAcceptedMouseButtons(Qt::NoButton); @@ -255,9 +265,6 @@ GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer) // they are ignored and passed to the item below. setEnabled(true); - // we'll set the cache when we know what's going on - setCacheMode(ItemCoordinateCache); - connect(this, SIGNAL(notifyAnimationStartedAsync()), this, SLOT(notifyAnimationStarted()), Qt::QueuedConnection); } @@ -283,65 +290,138 @@ GraphicsLayerQtImpl::~GraphicsLayerQtImpl() #endif } -void GraphicsLayerQtImpl::updateTransform() +const GraphicsLayerQtImpl* GraphicsLayerQtImpl::rootLayer() const { - setBaseTransform(isTransformAnimationRunning() ? m_baseTransform : m_layer->transform()); + if (const GraphicsLayerQtImpl* parent = qobject_cast<const GraphicsLayerQtImpl*>(parentObject())) + return parent->rootLayer(); + return this; } -void GraphicsLayerQtImpl::setBaseTransform(const TransformationMatrix& baseTransform) -{ - m_baseTransform = baseTransform; - setTransform(computeTransform(baseTransform)); -} -QTransform GraphicsLayerQtImpl::computeTransform(const TransformationMatrix& baseTransform) const + +QPixmap GraphicsLayerQtImpl::recache(const QRegion& regionToUpdate) { - if (!m_layer) - return baseTransform; + if (!m_layer->drawsContent()) + return QPixmap(); - TransformationMatrix computedTransform; + QRegion region = regionToUpdate; + QPixmap pixmap; - // The origin for childrenTransform is always the center of the ancestor which contains the childrenTransform. - // this has to do with how WebCore implements -webkit-perspective and -webkit-perspective-origin, which are the CSS - // attribute that call setChildrenTransform - QPointF offset = -pos() - boundingRect().bottomRight() / 2; + // We might be drawing into an existing cache. + if (!QPixmapCache::find(m_backingStoreKey, &pixmap)) + region = QRegion(QRect(0, 0, m_size.width(), m_size.height())); - for (const GraphicsLayerQtImpl* ancestor = this; (ancestor = qobject_cast<GraphicsLayerQtImpl*>(ancestor->parentObject())); ) { - if (!ancestor->m_state.childrenTransform.isIdentity()) { - const QPointF offset = mapFromItem(ancestor, QPointF(ancestor->m_size.width() / 2, ancestor->m_size.height() / 2)); - computedTransform - .translate(offset.x(), offset.y()) - .multLeft(ancestor->m_state.childrenTransform) - .translate(-offset.x(), -offset.y()); - break; - } + if (m_size != pixmap.size()) { + pixmap = QPixmap(m_size.toSize()); + if (!m_layer->contentsOpaque()) + pixmap.fill(Qt::transparent); + m_pendingContent.regionToUpdate = QRegion(QRect(QPoint(0, 0), m_size.toSize())); } + QPainter painter(&pixmap); + GraphicsContext gc(&painter); + + // Clear the area in cache that we're drawing into + painter.setCompositionMode(QPainter::CompositionMode_Clear); + painter.fillRect(region.boundingRect(), Qt::transparent); + + // Render the actual contents into the cache + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + m_layer->paintGraphicsLayerContents(gc, region.boundingRect()); + + m_backingStoreKey = QPixmapCache::insert(pixmap); + return pixmap; +} + +void GraphicsLayerQtImpl::updateTransform() +{ + if (!m_transformAnimationRunning) + m_baseTransform = m_layer->transform(); + + TransformationMatrix localTransform; + + GraphicsLayerQtImpl* parent = qobject_cast<GraphicsLayerQtImpl*>(parentObject()); + // webkit has relative-to-size originPoint, graphics-view has a pixel originPoint, here we convert // we have to manage this ourselves because QGraphicsView's transformOrigin is incompatible const qreal originX = m_state.anchorPoint.x() * m_size.width(); const qreal originY = m_state.anchorPoint.y() * m_size.height(); - computedTransform - .translate3d(originX, originY, m_state.anchorPoint.z()) - .multLeft(baseTransform) + + // We ignore QGraphicsItem::pos completely, and use only transforms - because we have to maintain that ourselves for 3D. + localTransform + .translate3d(originX + m_state.pos.x(), originY + m_state.pos.y(), m_state.anchorPoint.z()) + .multLeft(m_baseTransform) .translate3d(-originX, -originY, -m_state.anchorPoint.z()); - // now we project to 2D - return QTransform(computedTransform); + // This is the actual 3D transform of this item, with the ancestors' transform baked in. + m_transformRelativeToRootLayer = TransformationMatrix(parent ? parent->m_transformRelativeToRootLayer : TransformationMatrix()) + .multLeft(localTransform); + + // Now we have enough information to determine if the layer is facing backwards. + if (!m_state.backfaceVisibility && m_transformRelativeToRootLayer.inverse().m33() < 0) { + setVisible(false); + // No point in making extra calculations for invisible elements. + return; + } + + // Simplistic depth test - we stack the item behind its parent if its computed z is lower than the parent's computed z at the item's center point. + if (parent) { + const QPointF centerPointMappedToRoot = rootLayer()->mapFromItem(this, m_size.width() / 2, m_size.height() / 2); + setFlag(ItemStacksBehindParent, + m_transformRelativeToRootLayer.mapPoint(FloatPoint3D(centerPointMappedToRoot.x(), centerPointMappedToRoot.y(), 0)).z() < + parent->m_transformRelativeToRootLayer.mapPoint(FloatPoint3D(centerPointMappedToRoot.x(), centerPointMappedToRoot.y(), 0)).z()); + } + + // The item is front-facing or backface-visibility is on. + setVisible(true); + + // Flatten to 2D-space of this item if it doesn't preserve 3D. + if (!m_state.preserves3D) { + m_transformRelativeToRootLayer.setM13(0); + m_transformRelativeToRootLayer.setM23(0); + m_transformRelativeToRootLayer.setM31(0); + m_transformRelativeToRootLayer.setM32(0); + m_transformRelativeToRootLayer.setM33(1); + m_transformRelativeToRootLayer.setM34(0); + m_transformRelativeToRootLayer.setM43(0); + } + + // Apply perspective for the use of this item's children. Perspective is always applied from the item's center. + if (!m_state.childrenTransform.isIdentity()) + m_transformRelativeToRootLayer + .translate(m_size.width() / 2, m_size.height() /2) + .multLeft(m_state.childrenTransform) + .translate(-m_size.width() / 2, -m_size.height() /2); + + bool inverseOk = true; + // Use QTransform::inverse to extrapolate the relative transform of this item, based on the parent's transform relative to + // the root layer and the desired transform for this item relative to the root layer. + const QTransform parentTransform = parent ? parent->itemTransform(rootLayer()) : QTransform(); + const QTransform transform2D = QTransform(m_transformRelativeToRootLayer) * parentTransform.inverted(&inverseOk); + + // In rare cases the transformation cannot be inversed - in that case we don't apply the transformation at all, otherwise we'd flicker. + // FIXME: This should be amended when Qt moves to a real 3D scene-graph. + if (!inverseOk) + return; + + setTransform(transform2D); + + const QList<QGraphicsItem*> children = childItems(); + for (QList<QGraphicsItem*>::const_iterator it = children.begin(); it != children.end(); ++it) + if (GraphicsLayerQtImpl* layer= qobject_cast<GraphicsLayerQtImpl*>((*it)->toGraphicsObject())) + layer->updateTransform(); } -bool GraphicsLayerQtImpl::isTransformAnimationRunning() const +void GraphicsLayerQtImpl::setBaseTransform(const TransformationMatrix& baseTransform) { - if (m_transformAnimationRunning) - return true; - if (GraphicsLayerQtImpl* parent = qobject_cast<GraphicsLayerQtImpl*>(parentObject())) - return parent->isTransformAnimationRunning(); - return false; + m_baseTransform = baseTransform; + updateTransform(); } QPainterPath GraphicsLayerQtImpl::opaqueArea() const { QPainterPath painterPath; + // we try out best to return the opaque area, maybe it will help graphics-view render less items if (m_currentContent.backgroundColor.isValid() && m_currentContent.backgroundColor.alpha() == 0xff) painterPath.addRect(boundingRect()); @@ -370,9 +450,11 @@ void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsIte switch (m_currentContent.contentType) { case HTMLContentType: if (m_state.drawsContent) { - // this is the expensive bit. we try to minimize calls to this area by proper caching - GraphicsContext gc(painter); - m_layer->paintGraphicsLayerContents(gc, option->rect); + QPixmap backingStore; + // We might need to recache, in case we try to paint and the cache was purged (e.g. if it was full). + if (!QPixmapCache::find(m_backingStoreKey, &backingStore) || backingStore.size() != m_size.toSize()) + backingStore = recache(QRegion(m_state.contentsRect)); + painter->drawPixmap(0, 0, backingStore); } break; case PixmapContentType: @@ -384,6 +466,11 @@ void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsIte case MediaContentType: // we don't need to paint anything: we have a QGraphicsItem from the media element break; +#if ENABLE(3D_CANVAS) + case Canvas3DContentType: + m_gc3D->paint(painter, option->rect); + break; +#endif } } @@ -457,9 +544,6 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform } } - if ((m_changeMask & PositionChange) && (m_layer->position() != m_state.pos)) - setPos(m_layer->position().x(), m_layer->position().y()); - if (m_changeMask & SizeChange) { if (m_layer->size() != m_state.size) { prepareGeometryChange(); @@ -472,7 +556,7 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform if (scene()) scene()->update(); - if (m_changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange)) { + if (m_changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange | BackfaceVisibilityChange | PositionChange)) { // due to the differences between the way WebCore handles transforms and the way Qt handles transforms, // all these elements affect the transforms of all the descendants. forceUpdateTransform = true; @@ -484,19 +568,13 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform update(); setFlag(ItemHasNoContents, false); - // no point in caching a directly composited pixmap into another pixmap - setCacheMode(NoCache); - break; case MediaContentType: setFlag(ItemHasNoContents, true); - setCacheMode(NoCache); m_pendingContent.mediaLayer.data()->setParentItem(this); break; case ColorContentType: - // no point in caching a solid-color rectangle - setCacheMode(NoCache); if (m_pendingContent.contentType != m_currentContent.contentType || m_pendingContent.contentsBackgroundColor != m_currentContent.contentsBackgroundColor) update(); m_state.drawsContent = false; @@ -509,15 +587,21 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform case HTMLContentType: if (m_pendingContent.contentType != m_currentContent.contentType) update(); - if (!m_state.drawsContent && m_layer->drawsContent()) { + if (!m_state.drawsContent && m_layer->drawsContent()) update(); - if (m_layer->drawsContent() && !m_maskEffect) - setCacheMode(ItemCoordinateCache); - } else if (!m_layer->drawsContent()) - setCacheMode(NoCache); setFlag(ItemHasNoContents, !m_layer->drawsContent()); break; + +#if ENABLE(3D_CANVAS) + case Canvas3DContentType: + if (m_pendingContent.contentType != m_currentContent.contentType) + update(); + + setCacheMode(NoCache); + setFlag(ItemHasNoContents, false); + break; +#endif } } @@ -544,15 +628,16 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform if (m_maskEffect) m_maskEffect.data()->update(); - else if (m_changeMask & DisplayChange) + else if (m_changeMask & DisplayChange) { + // Recache now: all the content is ready and we don't want to wait until the paint event. + recache(m_pendingContent.regionToUpdate); update(m_pendingContent.regionToUpdate.boundingRect()); + m_pendingContent.regionToUpdate = QRegion(); + } if ((m_changeMask & BackgroundColorChange) && (m_pendingContent.backgroundColor != m_currentContent.backgroundColor)) update(); - // FIXME: the following flags are currently not handled, as they don't have a clear test or are in low priority - // GeometryOrientationChange, ContentsOrientationChange, BackfaceVisibilityChange, ChildrenTransformChange, Preserves3DChange - m_state.maskLayer = m_layer->maskLayer(); m_state.pos = m_layer->position(); m_state.anchorPoint = m_layer->anchorPoint(); @@ -572,7 +657,6 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform m_currentContent.contentType = m_pendingContent.contentType; m_currentContent.mediaLayer = m_pendingContent.mediaLayer; m_currentContent.backgroundColor = m_pendingContent.backgroundColor; - m_currentContent.regionToUpdate |= m_pendingContent.regionToUpdate; m_currentContent.contentsBackgroundColor = m_pendingContent.contentsBackgroundColor; m_pendingContent.regionToUpdate = QRegion(); m_changeMask = NoChanges; @@ -871,6 +955,23 @@ void GraphicsLayerQt::setContentsBackgroundColor(const Color& color) GraphicsLayer::setContentsBackgroundColor(color); } +#if ENABLE(3D_CANVAS) +void GraphicsLayerQt::setContentsToGraphicsContext3D(const GraphicsContext3D* ctx) +{ + if (ctx == m_impl->m_gc3D) + return; + + m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::Canvas3DContentType; + m_impl->m_gc3D = ctx; + m_impl->notifyChange(GraphicsLayerQtImpl::ContentChange); +} + +void GraphicsLayerQt::setGraphicsContext3DNeedsDisplay() +{ + setNeedsDisplay(); +} +#endif + void GraphicsLayerQt::setContentsToMedia(PlatformLayer* media) { if (media) { @@ -1106,8 +1207,6 @@ public: { if (m_fillsForwards) setCurrentTime(1); - else if (m_layer && m_layer.data()->m_layer) - m_layer.data()->setBaseTransform(m_layer.data()->m_layer->transform()); } // the idea is that we let WebCore manage the transform-operations @@ -1118,33 +1217,25 @@ public: { TransformationMatrix transformMatrix; - // sometimes the animation values from WebCore are misleading and we have to use the actual matrix as source - // The Mac implementation simply doesn't try to accelerate those (e.g. 360deg rotation), but we do. - if (progress == 1 || !targetOperations.size() || sourceOperations == targetOperations) { - TransformationMatrix sourceMatrix; - sourceOperations.apply(m_boxSize, sourceMatrix); - transformMatrix = m_sourceMatrix; - transformMatrix.blend(sourceMatrix, 1 - progress); - } else { - bool validTransformLists = true; - const int sourceOperationCount = sourceOperations.size(); - if (sourceOperationCount) { - if (targetOperations.size() != sourceOperationCount) - validTransformLists = false; - else - for (size_t j = 0; j < sourceOperationCount && validTransformLists; ++j) - if (!sourceOperations.operations()[j]->isSameType(*targetOperations.operations()[j])) - validTransformLists = false; - } + bool validTransformLists = true; + const int sourceOperationCount = sourceOperations.size(); + if (sourceOperationCount) { + if (targetOperations.size() != sourceOperationCount) + validTransformLists = false; + else + for (size_t j = 0; j < sourceOperationCount && validTransformLists; ++j) + if (!sourceOperations.operations()[j]->isSameType(*targetOperations.operations()[j])) + validTransformLists = false; + } - if (validTransformLists) { - for (size_t i = 0; i < targetOperations.size(); ++i) - targetOperations.operations()[i]->blend(sourceOperations.at(i), progress)->apply(transformMatrix, m_boxSize); - } else { - targetOperations.apply(m_boxSize, transformMatrix); - transformMatrix.blend(m_sourceMatrix, progress); - } + if (validTransformLists) { + for (size_t i = 0; i < targetOperations.size(); ++i) + targetOperations.operations()[i]->blend(sourceOperations.at(i), progress)->apply(transformMatrix, m_boxSize); + } else { + targetOperations.apply(m_boxSize, transformMatrix); + transformMatrix.blend(m_sourceMatrix, progress); } + m_layer.data()->setBaseTransform(transformMatrix); if (m_fillsForwards) m_layer.data()->m_layer->setTransform(m_layer.data()->m_baseTransform); @@ -1163,7 +1254,10 @@ public: m_sourceMatrix = m_layer.data()->m_layer->transform(); m_layer.data()->m_transformAnimationRunning = true; } else if (newState == QAbstractAnimation::Stopped) { + // We update the transform back to the default. This already takes fill-modes into account. m_layer.data()->m_transformAnimationRunning = false; + if (m_layer && m_layer.data()->m_layer) + m_layer.data()->setBaseTransform(m_layer.data()->m_layer->transform()); } } @@ -1181,8 +1275,6 @@ public: { if (m_fillsForwards) setCurrentTime(1); - else if (m_layer && m_layer.data()->m_layer) - m_layer.data()->setOpacity(m_layer.data()->m_layer->opacity()); } virtual void applyFrame(const qreal& fromValue, const qreal& toValue, qreal progress) { @@ -1204,6 +1296,12 @@ public: if (m_layer) m_layer.data()->m_opacityAnimationRunning = (newState == QAbstractAnimation::Running); + + // If stopped, we update the opacity back to the default. This already takes fill-modes into account. + if (newState == Stopped) + if (m_layer && m_layer.data()->m_layer) + m_layer.data()->setOpacity(m_layer.data()->m_layer->opacity()); + } }; @@ -1269,6 +1367,8 @@ void GraphicsLayerQt::removeAnimationsForProperty(AnimatedPropertyID id) if (*it) { AnimationQtBase* anim = static_cast<AnimationQtBase*>(it->data()); if (anim && anim->m_webkitPropertyID == id) { + // We need to stop the animation right away, or it might flicker before it's deleted. + anim->stop(); anim->deleteLater(); it = m_impl->m_animations.erase(it); --it; @@ -1283,7 +1383,9 @@ void GraphicsLayerQt::removeAnimationsForKeyframes(const String& name) if (*it) { AnimationQtBase* anim = static_cast<AnimationQtBase*>((*it).data()); if (anim && anim->m_keyframesName == QString(name)) { - (*it).data()->deleteLater(); + // We need to stop the animation right away, or it might flicker before it's deleted. + anim->stop(); + anim->deleteLater(); it = m_impl->m_animations.erase(it); --it; } diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.h b/WebCore/platform/graphics/qt/GraphicsLayerQt.h index 9e5832f..6de5a6e 100644 --- a/WebCore/platform/graphics/qt/GraphicsLayerQt.h +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.h @@ -74,6 +74,10 @@ public: virtual void setContentsToImage(Image*); virtual void setContentsToMedia(PlatformLayer*); virtual void setContentsBackgroundColor(const Color&); +#if ENABLE(3D_CANVAS) + virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*); + virtual void setGraphicsContext3DNeedsDisplay(); +#endif virtual void setGeometryOrientation(CompositingCoordinatesOrientation orientation); virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation); virtual void distributeOpacity(float); diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp index b48b278..a8110ca 100644 --- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp +++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp @@ -123,12 +123,14 @@ int ImageDecoderQt::repetitionCount() const // Qt | WebCore | description // -1 | 0 | infinite animation // 0 | cAnimationLoopOnce | show every frame once - // n | n | no idea if that is supported + // n | n+1 | Qt returns the # of iterations - 1 // n/a | cAnimationNone | show only the first frame if (m_repetitionCount == -1) m_repetitionCount = 0; else if (m_repetitionCount == 0) m_repetitionCount = cAnimationLoopOnce; + else + ++m_repetitionCount; } return m_repetitionCount; diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp index bdac2a4..4d7b7b0 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp @@ -77,7 +77,7 @@ MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& mime, c if (!mime.startsWith("audio/") && !mime.startsWith("video/")) return MediaPlayer::IsNotSupported; - if (QMediaPlayer::hasSupport(mime, QStringList(codec)) >= QtMultimedia::ProbablySupported) + if (QMediaPlayer::hasSupport(mime, QStringList(codec)) >= QtMediaServices::ProbablySupported) return MediaPlayer::IsSupported; return MediaPlayer::MayBeSupported; @@ -344,8 +344,8 @@ unsigned MediaPlayerPrivate::bytesLoaded() const unsigned MediaPlayerPrivate::totalBytes() const { - if (m_mediaPlayer->availableMetaData().contains(QtMultimedia::Size)) - return m_mediaPlayer->metaData(QtMultimedia::Size).toInt(); + if (m_mediaPlayer->availableMetaData().contains(QtMediaServices::Size)) + return m_mediaPlayer->metaData(QtMediaServices::Size).toInt(); return 100; } diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp index ee4af7f..4b0c21f 100644 --- a/WebCore/platform/graphics/qt/PathQt.cpp +++ b/WebCore/platform/graphics/qt/PathQt.cpp @@ -69,12 +69,41 @@ Path& Path::operator=(const Path& other) return *this; } +// Check whether a point is on the border +bool isPointOnPathBorder(const QPolygonF& border, const QPointF& p) +{ + QPointF p1 = border.at(0); + QPointF p2; + + for (int i = 1; i < border.size(); ++i) { + p2 = border.at(i); + // (x1<=x<=x2||x1=>x>=x2) && (y1<=y<=y2||y1=>y>=y2) && (y2-y1)(x-x1) == (y-y1)(x2-x1) + // In which, (y2-y1)(x-x1) == (y-y1)(x2-x1) is from (y2-y1)/(x2-x1) == (y-y1)/(x-x1) + // it want to check the slope between p1 and p2 is same with slope between p and p1, + // if so then the three points lie on the same line. + // In which, (x1<=x<=x2||x1=>x>=x2) && (y1<=y<=y2||y1=>y>=y2) want to make sure p is + // between p1 and p2, not outside. + if (((p.x() <= p1.x() && p.x() >= p2.x()) || (p.x() >= p1.x() && p.x() <= p2.x())) + && ((p.y() <= p1.y() && p.y() >= p2.y()) || (p.y() >= p1.y() && p.y() <= p2.y())) + && (p2.y() - p1.y()) * (p.x() - p1.x()) == (p.y() - p1.y()) * (p2.x() - p1.x())) { + return true; + } + p1 = p2; + } + return false; +} + bool Path::contains(const FloatPoint& point, WindRule rule) const { Qt::FillRule savedRule = m_path.fillRule(); const_cast<QPainterPath*>(&m_path)->setFillRule(rule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill); bool contains = m_path.contains(point); + + if (!contains) { + // check whether the point is on the border + contains = isPointOnPathBorder(m_path.toFillPolygon(), point); + } const_cast<QPainterPath*>(&m_path)->setFillRule(savedRule); return contains; diff --git a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp index cc4ca2e..e76ed7b 100644 --- a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp @@ -55,10 +55,9 @@ bool GraphicsContext3D::getImageData(Image* image, return false; SkBitmap& skiaImageRef = *skiaImage; SkAutoLockPixels lock(skiaImageRef); - int width = skiaImage->width(); int height = skiaImage->height(); int rowBytes = skiaImage->rowBytes(); - ASSERT(rowBytes == width * 4); + ASSERT(rowBytes == skiaImage->width() * 4); uint8_t* pixels = reinterpret_cast<uint8_t*>(skiaImage->getPixels()); outputVector.resize(rowBytes * height); int size = rowBytes * height; diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index 8986685..e16b373 100644 --- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -91,9 +91,9 @@ inline float square(float n) // bugs. Leaving the code in for now, so we can revert easily if necessary. // #define ENSURE_VALUE_SAFETY_FOR_SKIA +#ifdef ENSURE_VALUE_SAFETY_FOR_SKIA static bool isCoordinateSkiaSafe(float coord) { -#ifdef ENSURE_VALUE_SAFETY_FOR_SKIA // First check for valid floats. #if defined(_MSC_VER) if (!_finite(coord)) @@ -110,10 +110,8 @@ static bool isCoordinateSkiaSafe(float coord) return false; return true; -#else - return true; -#endif } +#endif static bool isPointSkiaSafe(const SkMatrix& transform, const SkPoint& pt) { @@ -734,8 +732,6 @@ void GraphicsContext::fillRect(const FloatRect& rect) ClipRectToCanvas(*platformContext()->canvas(), r, &r); } - const GraphicsContextState& state = m_common->state; - SkPaint paint; platformContext()->setupPaintForFilling(&paint); platformContext()->canvas()->drawRect(r, paint); @@ -1122,11 +1118,8 @@ void GraphicsContext::strokePath() if (!isPathSkiaSafe(getCTM(), path)) return; - const GraphicsContextState& state = m_common->state; - SkPaint paint; platformContext()->setupPaintForStroking(&paint, 0, 0); - platformContext()->canvas()->drawPath(path, paint); } @@ -1138,12 +1131,9 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) if (!isRectSkiaSafe(getCTM(), rect)) return; - const GraphicsContextState& state = m_common->state; - SkPaint paint; platformContext()->setupPaintForStroking(&paint, 0, 0); paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth)); - platformContext()->canvas()->drawRect(rect, paint); } diff --git a/WebCore/platform/graphics/transforms/TransformationMatrix.cpp b/WebCore/platform/graphics/transforms/TransformationMatrix.cpp index 0400d40..10c7f70 100644 --- a/WebCore/platform/graphics/transforms/TransformationMatrix.cpp +++ b/WebCore/platform/graphics/transforms/TransformationMatrix.cpp @@ -54,6 +54,22 @@ namespace WebCore { // webmasters - are to be held responsible. Basically, don't be a jerk, and remember that anything free comes // with no guarantee. +// A Note About row-major vs. column major matrixes +// +// The clients of this class (CSSMatrix and SVGMatrix) assume a column-major ordering. +// That means that when the matrix is initialized with 16 values, the first 4 values +// go in the 4 rows of the first column, etc. And in the dereferencing calls, the first +// digit is the column (e.g., m23() is column 2 row 3). Because C++ uses row-major arrays +// the internal matrix is stored in row-major order, so m[2][0] means row 2, column 0. This +// has no bearing on how the matrix is viewed on the outside, since all access is done +// with function calls. But it does help make the code more clear if you know that. +// +// FIXME: Multiply calls are named for what they do in the internal, row-major world. +// multLeft is actually a multRight in a column-major world, and multiply is a multLeft +// in a column-major world. For now I've left it that way to avoid too many confusing +// changes to the code. In particular AffineTransform uses these same terms for the +// opposite operations. So we have to be VERY careful when we change them. + typedef double Vector4[4]; typedef double Vector3[3]; diff --git a/WebCore/platform/graphics/transforms/TransformationMatrix.h b/WebCore/platform/graphics/transforms/TransformationMatrix.h index cdf101d..96b4baa 100644 --- a/WebCore/platform/graphics/transforms/TransformationMatrix.h +++ b/WebCore/platform/graphics/transforms/TransformationMatrix.h @@ -47,7 +47,7 @@ #endif #if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)) || (PLATFORM(WX) && OS(WINDOWS)) -#if COMPILER(MINGW) +#if COMPILER(MINGW) && !COMPILER(MINGW64) typedef struct _XFORM XFORM; #else typedef struct tagXFORM XFORM; diff --git a/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp index ed9073f..a804432 100644 --- a/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp +++ b/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp @@ -115,7 +115,7 @@ void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR* } FontPlatformData::FontPlatformData(HFONT hfont, CGFontRef font, float size, bool bold, bool oblique, bool useGDI) - : m_font(RefCountedHFONT::create(hfont)) + : m_font(RefCountedGDIHandle<HFONT>::create(hfont)) , m_size(size) , m_cgFont(font) , m_syntheticBold(bold) diff --git a/WebCore/platform/graphics/win/FontPlatformDataWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataWin.cpp index cc02c4c..99f364c 100644 --- a/WebCore/platform/graphics/win/FontPlatformDataWin.cpp +++ b/WebCore/platform/graphics/win/FontPlatformDataWin.cpp @@ -36,7 +36,7 @@ using std::min; namespace WebCore { FontPlatformData::FontPlatformData(HFONT font, float size, bool bold, bool oblique, bool useGDI) - : m_font(RefCountedHFONT::create(font)) + : m_font(RefCountedGDIHandle<HFONT>::create(font)) , m_size(size) #if PLATFORM(CG) , m_cgFont(0) diff --git a/WebCore/platform/graphics/win/GraphicsContextWin.cpp b/WebCore/platform/graphics/win/GraphicsContextWin.cpp index b110145..161b9c6 100644 --- a/WebCore/platform/graphics/win/GraphicsContextWin.cpp +++ b/WebCore/platform/graphics/win/GraphicsContextWin.cpp @@ -43,8 +43,6 @@ using namespace std; namespace WebCore { -class SVGResourceImage; - static void fillWithClearColor(HBITMAP bitmap) { BITMAP bmpInfo; @@ -199,13 +197,4 @@ void GraphicsContextPlatformPrivate::concatCTM(const AffineTransform& transform) ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY); } -#if ENABLE(SVG) -GraphicsContext* contextForImage(SVGResourceImage*) -{ - // FIXME: This should go in GraphicsContextCG.cpp - notImplemented(); - return 0; -} -#endif - } diff --git a/WebCore/platform/graphics/win/RefCountedHFONT.h b/WebCore/platform/graphics/win/RefCountedGDIHandle.h index b1b691b..65f66f1 100755 --- a/WebCore/platform/graphics/win/RefCountedHFONT.h +++ b/WebCore/platform/graphics/win/RefCountedGDIHandle.h @@ -17,40 +17,54 @@ * Boston, MA 02110-1301, USA. * */ -#ifndef RefCountedHFONT_h -#define RefCountedHFONT_h -#include "StringImpl.h" +#ifndef RefCountedGDIHandle_h +#define RefCountedGDIHandle_h + +#include <windows.h> +#include <wtf/HashFunctions.h> +#include <wtf/OwnPtr.h> #include <wtf/RefCounted.h> namespace WebCore { -class RefCountedHFONT : public RefCounted<RefCountedHFONT> { +template <typename T> class RefCountedGDIHandle : public RefCounted<RefCountedGDIHandle<T> > { public: - static PassRefPtr<RefCountedHFONT> create(HFONT hfont) { return adoptRef(new RefCountedHFONT(hfont)); } - static PassRefPtr<RefCountedHFONT> createDeleted() { return adoptRef(new RefCountedHFONT(reinterpret_cast<HFONT>(-1))); } + static PassRefPtr<RefCountedGDIHandle> create(T handle) + { + return adoptRef(new RefCountedGDIHandle<T>(handle)); + } + + static PassRefPtr<RefCountedGDIHandle<T> > createDeleted() + { + return adoptRef(new RefCountedGDIHandle<T>(reinterpret_cast<T>(-1))); + } + + ~RefCountedGDIHandle() + { + if (m_handle != reinterpret_cast<T>(-1)) + WTF::deleteOwnedPtr(m_handle); + } - ~RefCountedHFONT() + T handle() const { - if (m_hfont != reinterpret_cast<HFONT>(-1)) - DeleteObject(m_hfont); + return m_handle; } - HFONT hfont() const { return m_hfont; } unsigned hash() const { - return StringImpl::computeHash(reinterpret_cast<const UChar*>(&m_hfont), sizeof(HFONT) / sizeof(UChar)); + return WTF::PtrHash<T>::hash(m_handle); } private: - RefCountedHFONT(HFONT hfont) - : m_hfont(hfont) + RefCountedGDIHandle(T handle) + : m_handle(handle) { } - HFONT m_hfont; + T m_handle; }; -} +} // namespace WebCore -#endif +#endif // RefCountedGDIHandle_h diff --git a/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp index ee3a980..20d42ff 100644 --- a/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp +++ b/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp @@ -125,11 +125,26 @@ void SimpleFontData::platformCharWidthInit() initCharWidths(); } } +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const +{ + if (m_platformData.useGDI()) + return boundsForGDIGlyph(glyph); + + CGRect box; + CGFontGetGlyphBBoxes(m_platformData.cgFont(), &glyph, 1, &box); + float pointSize = m_platformData.size(); + CGFloat scale = pointSize / unitsPerEm(); + FloatRect boundingBox = CGRectApplyAffineTransform(box, CGAffineTransformMakeScale(scale, -scale)); + if (m_syntheticBoldOffset) + boundingBox.setWidth(boundingBox.width() + m_syntheticBoldOffset); -GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode metricsMode) const + return boundingBox; +} + +float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { if (m_platformData.useGDI()) - return metricsForGDIGlyph(glyph); + return widthForGDIGlyph(glyph); CGFontRef font = m_platformData.cgFont(); float pointSize = m_platformData.size(); @@ -139,18 +154,8 @@ GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMo // FIXME: Need to add real support for printer fonts. bool isPrinterFont = false; wkGetGlyphAdvances(font, m, m_isSystemFont, isPrinterFont, glyph, advance); - GlyphMetrics metrics; - metrics.horizontalAdvance = advance.width + m_syntheticBoldOffset; - - if (metricsMode == GlyphBoundingBox) { - CGRect boundingBox; - CGFontGetGlyphBBoxes(font, &glyph, 1, &boundingBox); - CGFloat scale = pointSize / unitsPerEm(); - metrics.boundingBox = CGRectApplyAffineTransform(boundingBox, CGAffineTransformMakeScale(scale, -scale)); - if (m_syntheticBoldOffset) - metrics.boundingBox.setWidth(metrics.boundingBox.width() + m_syntheticBoldOffset); - } - return metrics; + + return advance.width + m_syntheticBoldOffset; } } diff --git a/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp index e845d85..62ea060 100644 --- a/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp +++ b/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp @@ -96,6 +96,14 @@ void SimpleFontData::platformCharWidthInit() // charwidths are set in platformInit. } +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const +{ + if (m_platformData.useGDI()) + return boundsForGDIGlyph(glyph); + //FIXME: Implement this + return FloatRect(); +} + float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { if (m_platformData.useGDI()) diff --git a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp index f85f9ba..7010c8a 100644 --- a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp +++ b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp @@ -179,7 +179,24 @@ void SimpleFontData::determinePitch() ReleaseDC(0, dc); } -GlyphMetrics SimpleFontData::metricsForGDIGlyph(Glyph glyph) const +FloatRect SimpleFontData::boundsForGDIGlyph(Glyph glyph) const +{ + HDC hdc = GetDC(0); + SetGraphicsMode(hdc, GM_ADVANCED); + HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont()); + + GLYPHMETRICS gdiMetrics; + static const MAT2 identity = { 0, 1, 0, 0, 0, 0, 0, 1 }; + GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0, &identity); + + SelectObject(hdc, oldFont); + ReleaseDC(0, hdc); + + return FloatRect(gdiMetrics.gmptGlyphOrigin.x, -gdiMetrics.gmptGlyphOrigin.y, + gdiMetrics.gmBlackBoxX + m_syntheticBoldOffset, gdiMetrics.gmBlackBoxY); +} + +float SimpleFontData::widthForGDIGlyph(Glyph glyph) const { HDC hdc = GetDC(0); SetGraphicsMode(hdc, GM_ADVANCED); @@ -192,12 +209,7 @@ GlyphMetrics SimpleFontData::metricsForGDIGlyph(Glyph glyph) const SelectObject(hdc, oldFont); ReleaseDC(0, hdc); - GlyphMetrics glyphMetrics; - glyphMetrics.horizontalAdvance = gdiMetrics.gmCellIncX + m_syntheticBoldOffset; - glyphMetrics.boundingBox = FloatRect(gdiMetrics.gmptGlyphOrigin.x, -gdiMetrics.gmptGlyphOrigin.y, - gdiMetrics.gmBlackBoxX + m_syntheticBoldOffset, gdiMetrics.gmBlackBoxY); - - return glyphMetrics; + return gdiMetrics.gmCellIncX + m_syntheticBoldOffset; } SCRIPT_FONTPROPERTIES* SimpleFontData::scriptFontProperties() const diff --git a/WebCore/platform/graphics/win/UniscribeController.cpp b/WebCore/platform/graphics/win/UniscribeController.cpp index cfa15a2..bcf7578 100644 --- a/WebCore/platform/graphics/win/UniscribeController.cpp +++ b/WebCore/platform/graphics/win/UniscribeController.cpp @@ -380,12 +380,12 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const S glyphBuffer->add(glyph, fontData, advance, &size); } - GlyphMetrics glyphMetrics = fontData->metricsForGlyph(glyph); - glyphMetrics.boundingBox.move(m_glyphOrigin.x(), m_glyphOrigin.y()); - m_minGlyphBoundingBoxX = min(m_minGlyphBoundingBoxX, glyphMetrics.boundingBox.x()); - m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphMetrics.boundingBox.right()); - m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, glyphMetrics.boundingBox.y()); - m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphMetrics.boundingBox.bottom()); + FloatRect glyphBounds = fontData->boundsForGlyph(glyph); + glyphBounds.move(m_glyphOrigin.x(), m_glyphOrigin.y()); + m_minGlyphBoundingBoxX = min(m_minGlyphBoundingBoxX, glyphBounds.x()); + m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphBounds.right()); + m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, glyphBounds.y()); + m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphBounds.bottom()); m_glyphOrigin.move(advance + offsetX, -offsetY); // Mutate the glyph array to contain our altered advances. diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp index 1b14846..714a4ac 100644 --- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp +++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp @@ -275,6 +275,13 @@ void WKCACFLayerRenderer::setRootContents(CGImageRef image) renderSoon(); } +void WKCACFLayerRenderer::setRootContentsAndDisplay(CGImageRef image) +{ + ASSERT(m_rootLayer); + m_rootLayer->setContents(image); + paint(); +} + void WKCACFLayerRenderer::setRootChildLayer(WKCACFLayer* layer) { if (!m_scrollLayer) diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h index ea710b6..b708464 100644 --- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h +++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h @@ -62,6 +62,7 @@ public: void setScrollFrame(const IntPoint&, const IntSize&); void setRootContents(CGImageRef); + void setRootContentsAndDisplay(CGImageRef); void setRootChildLayer(WKCACFLayer* layer); void setNeedsDisplay(); void setHostWindow(HWND window) { m_hostWindow = window; } diff --git a/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp b/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp index d5f8a5a..f8a1e26 100644 --- a/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp +++ b/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp @@ -63,7 +63,7 @@ static String createUniqueFontName() unsigned int* ptr = reinterpret_cast<unsigned int*>(fontUuid.data()); for (int i = 0; i < sizeof(GUID) / sizeof(int) ; ++i) - *(ptr + i) = static_cast<unsigned int>(WTF::randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)); + *(ptr + i) = static_cast<unsigned int>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)); Vector<char> fontNameVector; base64Encode(fontUuid, fontNameVector); diff --git a/WebCore/platform/graphics/wince/SimpleFontDataWince.cpp b/WebCore/platform/graphics/wince/SimpleFontDataWince.cpp index 1195294..6c815fc 100644 --- a/WebCore/platform/graphics/wince/SimpleFontDataWince.cpp +++ b/WebCore/platform/graphics/wince/SimpleFontDataWince.cpp @@ -131,6 +131,11 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH); } +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const +{ + return FloatRect(); +} + float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { if (m_platformData.isDisabled()) diff --git a/WebCore/platform/graphics/wx/FontCacheWx.cpp b/WebCore/platform/graphics/wx/FontCacheWx.cpp index b2dea2e..5b02bdb 100644 --- a/WebCore/platform/graphics/wx/FontCacheWx.cpp +++ b/WebCore/platform/graphics/wx/FontCacheWx.cpp @@ -42,7 +42,13 @@ void FontCache::platformInit() const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { SimpleFontData* fontData = 0; - fontData = new SimpleFontData(FontPlatformData(font.fontDescription(), font.family().family())); + fontData = getCachedFontData(font.fontDescription(), font.family().family()); + if (!fontData->containsCharacters(characters, length)) + fontData = getSimilarFontPlatformData(font); + if (!fontData->containsCharacters(characters, length)) + fontData = getLastResortFallbackFont(font.fontDescription()); + + ASSERT(fontData->containsCharacters(characters, length)); return fontData; } @@ -55,8 +61,15 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& font { // FIXME: Would be even better to somehow get the user's default font here. For now we'll pick // the default that the user would get without changing any prefs. - static AtomicString timesStr("systemfont"); - return getCachedFontData(fontDescription, timesStr); + SimpleFontData* fallback = 0; +#if OS(WINDOWS) || (OS(DARWIN) && !defined(BUILDING_ON_TIGER)) + static AtomicString fallbackName("Arial Unicode MS"); +#else + static AtomicString fallbackName("Times New Roman"); +#endif + fallback = getCachedFontData(fontDescription, fallbackName); + + return fallback; } FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) diff --git a/WebCore/platform/graphics/wx/FontPlatformData.h b/WebCore/platform/graphics/wx/FontPlatformData.h index ecb957e..94585e6 100644 --- a/WebCore/platform/graphics/wx/FontPlatformData.h +++ b/WebCore/platform/graphics/wx/FontPlatformData.h @@ -37,6 +37,22 @@ #include <wx/defs.h> #include <wx/font.h> +#include <wx/gdicmn.h> + +#if OS(DARWIN) +#include <ApplicationServices/ApplicationServices.h> + +#if __OBJC__ +@class NSFont; +#else +class NSFont; +#endif + +#ifndef BUILDING_ON_TIGER +inline CTFontRef toCTFontRef(NSFont *nsFont) { return reinterpret_cast<CTFontRef>(nsFont); } +#endif + +#endif namespace WebCore { @@ -64,9 +80,12 @@ public: enum FontState { UNINITIALIZED, DELETED, VALID }; FontPlatformData(WTF::HashTableDeletedValueType) - : m_fontState(DELETED), - m_font(0), - m_size(0) + : m_fontState(DELETED) + , m_font(0) + , m_size(0) +#if OS(DARWIN) + , m_atsuFontID(0) +#endif { } ~FontPlatformData(); @@ -77,6 +96,9 @@ public: : m_fontState(UNINITIALIZED) , m_font(0) , m_size(size) +#if OS(DARWIN) + , m_atsuFontID(0) +#endif { } @@ -84,6 +106,9 @@ public: : m_fontState(UNINITIALIZED) , m_font(0) , m_size(0) +#if OS(DARWIN) + , m_atsuFontID(0) +#endif { } @@ -121,11 +146,23 @@ public: bool roundsGlyphAdvances() const { return false; } + bool allowsLigatures() const { return false; } + #if OS(WINDOWS) bool useGDI() const; HFONT hfont() const; #endif +#if OS(DARWIN) + ATSUFontID m_atsuFontID; + CGFontRef cgFont() const; + NSFont* nsFont() const; + void cacheNSFont(); + +#endif + + float m_size; + #ifndef NDEBUG String description() const; #endif @@ -133,7 +170,9 @@ public: private: WTF::RefPtr<FontHolder> m_font; FontState m_fontState; - float m_size; +#if OS(DARWIN) + NSFont* m_nsFont; +#endif }; } diff --git a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp index a75d244..601d6b4 100644 --- a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp +++ b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp @@ -99,6 +99,11 @@ FontPlatformData::FontPlatformData(const FontDescription& desc, const AtomicStri ) ); #endif +#if OS(DARWIN) + m_atsuFontID = m_font->font()->MacGetATSUFontID(); + cacheNSFont(); +#endif + m_size = desc.computedPixelSize(); m_fontState = VALID; m_size = desc.computedPixelSize(); @@ -142,4 +147,24 @@ HFONT FontPlatformData::hfont() const } #endif +#if OS(DARWIN) +CGFontRef FontPlatformData::cgFont() const +{ + CGFontRef cgFont = 0; +#ifdef wxOSX_USE_CORE_TEXT && wxOSX_USE_CORE_TEXT + cgFont = CTFontCopyGraphicsFont((CTFontRef)m_font->font()->OSXGetCTFont(), 0); +#else + ATSFontRef fontRef; + + fontRef = FMGetATSFontRefFromFont(m_atsuFontID); + + if (fontRef) + cgFont = CGFontCreateWithPlatformFont((void*)&fontRef); +#endif + return cgFont; +} +#endif + + + } diff --git a/WebCore/platform/graphics/GlyphMetricsMap.cpp b/WebCore/platform/graphics/wx/FontPlatformDataWxMac.mm index d3c3180..b719656 100644 --- a/WebCore/platform/graphics/GlyphMetricsMap.cpp +++ b/WebCore/platform/graphics/wx/FontPlatformDataWxMac.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2010 Kevin Ollivier All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,38 +25,26 @@ * (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 "GlyphMetricsMap.h" +#include "FontPlatformData.h" + +#include <wx/defs.h> +#include <wx/font.h> namespace WebCore { -GlyphMetricsMap::GlyphMetricsPage* GlyphMetricsMap::locatePageSlowCase(unsigned pageNumber) +NSFont* FontPlatformData::nsFont() const { - GlyphMetricsPage* page; - if (!pageNumber) { - ASSERT(!m_filledPrimaryPage); - page = &m_primaryPage; - m_filledPrimaryPage = true; - } else { - if (m_pages) { - if ((page = m_pages->get(pageNumber))) - return page; - } else - m_pages.set(new HashMap<int, GlyphMetricsPage*>); - page = new GlyphMetricsPage; - m_pages->set(pageNumber, page); - } +#if wxCHECK_VERSION(2,9,1) && wxOSX_USE_COCOA + if (m_font && m_font->font()) + return (NSFont*)m_font->font()->OSXGetNSFont(); +#endif +} - GlyphMetrics unknownMetrics; - unknownMetrics.horizontalAdvance = cGlyphSizeUnknown; - unknownMetrics.boundingBox.setWidth(cGlyphSizeUnknown); - unknownMetrics.boundingBox.setHeight(cGlyphSizeUnknown); - // Fill in the whole page with the unknown glyph information. - for (unsigned i = 0; i < GlyphMetricsPage::size; i++) - page->setMetricsForIndex(i, unknownMetrics); +void FontPlatformData::cacheNSFont() +{ - return page; } } diff --git a/WebCore/platform/graphics/wx/FontWx.cpp b/WebCore/platform/graphics/wx/FontWx.cpp index dce3841..c00c622 100644 --- a/WebCore/platform/graphics/wx/FontWx.cpp +++ b/WebCore/platform/graphics/wx/FontWx.cpp @@ -35,6 +35,11 @@ #if OS(WINDOWS) #include "UniscribeController.h" +typedef UniscribeController ComplexTextController +#endif + +#if OS(DARWIN) +#include "mac/ComplexTextController.h" #endif #include <wx/dcclient.h> @@ -45,7 +50,7 @@ namespace WebCore { bool Font::canReturnFallbackFontsForComplexText() { -#if OS(WINDOWS) +#if OS(WINDOWS) || OS(DARWIN) return true; #else return false; @@ -67,8 +72,8 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const { -#if OS(WINDOWS) - UniscribeController it(this, run); +#if OS(WINDOWS) || OS(DARWIN) + ComplexTextController it(this, run); it.advance(from); float beforeWidth = it.runWidthSoFar(); it.advance(to); @@ -76,9 +81,14 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning if (run.rtl()) { +#if OS(WINDOWS) it.advance(run.length()); float totalWidth = it.runWidthSoFar(); return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h); +#else + float totalWidth = it.totalWidth(); + return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h); +#endif } return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h); @@ -90,12 +100,12 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const { -#if OS(WINDOWS) +#if OS(WINDOWS) || OS(DARWIN) // This glyph buffer holds our glyphs + advances + font data for each glyph. GlyphBuffer glyphBuffer; float startX = point.x(); - UniscribeController controller(this, run); + ComplexTextController controller(this, run); controller.advance(from); float beforeWidth = controller.runWidthSoFar(); controller.advance(to, &glyphBuffer); @@ -107,8 +117,14 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F float afterWidth = controller.runWidthSoFar(); if (run.rtl()) { +#if OS(WINDOWS) controller.advance(run.length()); startX += controller.runWidthSoFar() - afterWidth; +#else + startX += controller.totalWidth() + controller.finalRoundingWidth() - afterWidth; + for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end) + glyphBuffer.swap(i, end); +#endif } else startX += beforeWidth; @@ -123,11 +139,15 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow*) const { +#if OS(WINDOWS) || OS(DARWIN) + ComplexTextController controller(this, run, fallbackFonts); #if OS(WINDOWS) - UniscribeController controller(this, run, fallbackFonts); controller.advance(run.length()); return controller.runWidthSoFar(); #else + return controller.totalWidth(); +#endif +#else notImplemented(); return 0; #endif @@ -135,8 +155,8 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const { -#if OS(WINDOWS) - UniscribeController controller(this, run); +#if OS(WINDOWS) || OS(DARWIN) + ComplexTextController controller(this, run); return controller.offsetForPosition(x, includePartialGlyphs); #else notImplemented(); diff --git a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp index 3c8a1da..e899715 100644 --- a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp +++ b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp @@ -36,8 +36,13 @@ #include <unicode/uchar.h> #include <unicode/unorm.h> +#if OS(DARWIN) +#include "WebCoreSystemInterface.h" +#endif + #include <wx/defs.h> #include <wx/dcscreen.h> +#include <wx/string.h> #include "fontprops.h" namespace WebCore @@ -56,11 +61,12 @@ void SimpleFontData::platformInit() m_lineGap = props.GetLineGap(); } + m_syntheticBoldOffset = 0.0f; + #if OS(WINDOWS) m_scriptCache = 0; m_scriptFontProperties = 0; m_isSystemFont = false; - m_syntheticBoldOffset = 0.0f; #endif } @@ -91,9 +97,9 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes { if (!m_smallCapsFontData){ FontDescription desc = FontDescription(fontDescription); - desc.setSpecifiedSize(0.70f*fontDescription.computedSize()); - const FontPlatformData* pdata = new FontPlatformData(desc, desc.family().family()); - m_smallCapsFontData = new SimpleFontData(*pdata); + desc.setSpecifiedSize(0.70f * fontDescription.computedSize()); + FontPlatformData platformData(desc, desc.family().family()); + m_smallCapsFontData = new SimpleFontData(platformData); } return m_smallCapsFontData; } @@ -101,7 +107,12 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes bool SimpleFontData::containsCharacters(const UChar* characters, int length) const { // FIXME: We will need to implement this to load non-ASCII encoding sites - return wxFontContainsCharacters(*m_platformData.font(), characters, length); +#if OS(WINDOWS) + return wxFontContainsCharacters(m_platformData.hfont(), characters, length); +#elif OS(DARWIN) + return wxFontContainsCharacters(m_platformData.nsFont(), characters, length); +#endif + return true; } void SimpleFontData::determinePitch() @@ -112,19 +123,32 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = false; } -GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const +{ + return FloatRect(); +} + +float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { - GlyphMetrics metrics; #if __WXMSW__ // under Windows / wxMSW we currently always use GDI fonts. - metrics.horizontalAdvance = widthForGDIGlyph(glyph); + return widthForGDIGlyph(glyph); +#elif OS(DARWIN) + float pointSize = m_platformData.size(); + CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize); + CGSize advance; + NSFont* nsfont = (NSFont*)m_platformData.nsFont(); + if (!wkGetGlyphTransformedAdvances(m_platformData.cgFont(), nsfont, &m, &glyph, &advance)) { + // LOG_ERROR("Unable to cache glyph widths for %@ %f", [nsfont displayName], pointSize); + advance.width = 0; + } + return advance.width + m_syntheticBoldOffset; #else // TODO: fix this! Make GetTextExtents a method of wxFont in 2.9 int width = 10; GetTextExtent(*m_platformData.font(), (wxChar)glyph, &width, NULL); - metrics.horizontalAdvance = width; + return width; #endif - return metrics; } #if OS(WINDOWS) diff --git a/WebCore/platform/gtk/ClipboardGtk.cpp b/WebCore/platform/gtk/ClipboardGtk.cpp index 93a21e2..9bee55a 100644 --- a/WebCore/platform/gtk/ClipboardGtk.cpp +++ b/WebCore/platform/gtk/ClipboardGtk.cpp @@ -24,6 +24,8 @@ #include "Frame.h" #include "Image.h" #include "NotImplemented.h" +#include "Pasteboard.h" +#include "PasteboardHelper.h" #include "RenderImage.h" #include "StringHash.h" #include "markup.h" @@ -32,13 +34,33 @@ namespace WebCore { +enum ClipboardType { + ClipboardTypeText, + ClipboardTypeMarkup, + ClipboardTypeURIList, + ClipboardTypeURL, + ClipboardTypeImage, + ClipboardTypeUnknown +}; + PassRefPtr<Clipboard> Editor::newGeneralClipboard(ClipboardAccessPolicy policy) { - return ClipboardGtk::create(policy, false); + return ClipboardGtk::create(policy, gtk_clipboard_get_for_display(gdk_display_get_default(), GDK_SELECTION_CLIPBOARD), false); +} + +ClipboardGtk::ClipboardGtk(ClipboardAccessPolicy policy, GtkClipboard* clipboard) + : Clipboard(policy, false) + , m_dataObject(DataObjectGtk::forClipboard(clipboard)) + , m_clipboard(clipboard) + , m_helper(Pasteboard::generalPasteboard()->helper()) +{ } -ClipboardGtk::ClipboardGtk(ClipboardAccessPolicy policy, bool forDragging) +ClipboardGtk::ClipboardGtk(ClipboardAccessPolicy policy, PassRefPtr<DataObjectGtk> dataObject, bool forDragging) : Clipboard(policy, forDragging) + , m_dataObject(dataObject) + , m_clipboard(0) + , m_helper(Pasteboard::generalPasteboard()->helper()) { } @@ -46,39 +68,197 @@ ClipboardGtk::~ClipboardGtk() { } -void ClipboardGtk::clearData(const String&) +static ClipboardType dataObjectTypeFromHTMLClipboardType(const String& rawType) { - notImplemented(); + String type(rawType.stripWhiteSpace()); + + // Two special cases for IE compatibility + if (type == "Text") + return ClipboardTypeText; + if (type == "URL") + return ClipboardTypeURL; + + // From the Mac port: Ignore any trailing charset - JS strings are + // Unicode, which encapsulates the charset issue. + if (type == "text/plain" || type.startsWith("text/plain;")) + return ClipboardTypeText; + if (type == "text/html" || type.startsWith("text/html;")) + return ClipboardTypeMarkup; + if (type == "Files" || type == "text/uri-list" || type.startsWith("text/uri-list;")) + return ClipboardTypeURIList; + + // Not a known type, so just default to using the text portion. + return ClipboardTypeUnknown; } +void ClipboardGtk::clearData(const String& typeString) +{ + if (policy() != ClipboardWritable) + return; + + ClipboardType type = dataObjectTypeFromHTMLClipboardType(typeString); + switch (type) { + case ClipboardTypeURIList: + case ClipboardTypeURL: + m_dataObject->clearURIList(); + break; + case ClipboardTypeMarkup: + m_dataObject->clearMarkup(); + break; + case ClipboardTypeText: + m_dataObject->clearText(); + break; + case ClipboardTypeUnknown: + default: + m_dataObject->clear(); + } + + if (m_clipboard) + m_helper->writeClipboardContents(m_clipboard); +} + + void ClipboardGtk::clearAllData() { - notImplemented(); + if (policy() != ClipboardWritable) + return; + + m_dataObject->clear(); + + if (m_clipboard) + m_helper->writeClipboardContents(m_clipboard); } -String ClipboardGtk::getData(const String&, bool &success) const +static String joinURIList(Vector<KURL> uriList) { - notImplemented(); - success = false; + if (uriList.isEmpty()) + return String(); + + String joined(uriList[0].string()); + for (size_t i = 1; i < uriList.size(); i++) { + joined.append("\r\n"); + joined.append(uriList[i].string()); + } + + return joined; +} + +String ClipboardGtk::getData(const String& typeString, bool& success) const +{ + success = false; // Pessimism. + if (policy() != ClipboardReadable || !m_dataObject) + return String(); + + if (m_clipboard) + m_helper->getClipboardContents(m_clipboard); + + ClipboardType type = dataObjectTypeFromHTMLClipboardType(typeString); + if (type == ClipboardTypeURIList) { + if (!m_dataObject->hasURIList()) + return String(); + success = true; + return joinURIList(m_dataObject->uriList()); + } + + if (type == ClipboardTypeURL) { + if (!m_dataObject->hasURL()) + return String(); + success = true; + return m_dataObject->url(); + } + + if (type == ClipboardTypeMarkup) { + if (!m_dataObject->hasMarkup()) + return String(); + success = true; + return m_dataObject->markup(); + } + + if (type == ClipboardTypeText) { + if (!m_dataObject->hasText()) + return String(); + success = true; + return m_dataObject->text(); + } + return String(); } -bool ClipboardGtk::setData(const String&, const String&) +bool ClipboardGtk::setData(const String& typeString, const String& data) { - notImplemented(); - return false; + if (policy() != ClipboardWritable) + return false; + + bool success = false; + ClipboardType type = dataObjectTypeFromHTMLClipboardType(typeString); + if (type == ClipboardTypeURIList || type == ClipboardTypeURL) { + Vector<KURL> uriList; + gchar** uris = g_uri_list_extract_uris(data.utf8().data()); + if (uris) { + gchar** currentURI = uris; + while (*currentURI) { + uriList.append(KURL(KURL(), *currentURI)); + currentURI++; + } + g_strfreev(uris); + m_dataObject->setURIList(uriList); + success = true; + } + } else if (type == ClipboardTypeMarkup) { + m_dataObject->setMarkup(data); + success = true; + } else if (type == ClipboardTypeText) { + m_dataObject->setText(data); + success = true; + } + + if (success && m_clipboard) + m_helper->writeClipboardContents(m_clipboard); + + return success; } HashSet<String> ClipboardGtk::types() const { - notImplemented(); - return HashSet<String>(); + if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable) + return HashSet<String>(); + + if (m_clipboard) + m_helper->getClipboardContents(m_clipboard); + + HashSet<String> types; + if (m_dataObject->hasText()) { + types.add("text/plain"); + types.add("Text"); + } + + if (m_dataObject->hasMarkup()) + types.add("text/html"); + + if (m_dataObject->hasURIList()) { + types.add("text/uri-list"); + types.add("URL"); + types.add("Files"); + } + + return types; } PassRefPtr<FileList> ClipboardGtk::files() const { - notImplemented(); - return 0; + if (policy() != ClipboardReadable) + return FileList::create(); + + if (m_clipboard) + m_helper->getClipboardContents(m_clipboard); + + RefPtr<FileList> fileList = FileList::create(); + Vector<String> fileVector(m_dataObject->files()); + + for (size_t i = 0; i < fileVector.size(); i++) + fileList->append(File::create(fileVector[i])); + + return fileList.release(); } IntPoint ClipboardGtk::dragLocation() const @@ -151,44 +331,54 @@ void ClipboardGtk::declareAndWriteDragImage(Element* element, const KURL& url, c void ClipboardGtk::writeURL(const KURL& url, const String& label, Frame*) { - GtkClipboard* textClipboard = gtk_clipboard_get(gdk_atom_intern_static_string("WebKitClipboardText")); - GtkClipboard* urlClipboard = gtk_clipboard_get(gdk_atom_intern_static_string("WebKitClipboardUrl")); - GtkClipboard* urlLabelClipboard = gtk_clipboard_get(gdk_atom_intern_static_string("WebKitClipboardUrlLabel")); - - gtk_clipboard_clear(textClipboard); - gtk_clipboard_clear(urlClipboard); - gtk_clipboard_clear(urlLabelClipboard); - - gtk_clipboard_set_text(textClipboard, url.string().utf8().data(), -1); - gtk_clipboard_set_text(urlClipboard, url.string().utf8().data(), -1); - gtk_clipboard_set_text(urlLabelClipboard, label.utf8().data(), -1); + String actualLabel(label); + if (actualLabel.isEmpty()) + actualLabel = url; + + m_dataObject->setText(url.string()); + + Vector<UChar> markup; + append(markup, "<a href=\""); + append(markup, url.string()); + append(markup, "\">"); + append(markup, label); + append(markup, "</a>"); + m_dataObject->setMarkup(String::adopt(markup)); + + Vector<KURL> uriList; + uriList.append(url); + m_dataObject->setURIList(uriList); + + if (m_clipboard) + m_helper->writeClipboardContents(m_clipboard); } void ClipboardGtk::writeRange(Range* range, Frame* frame) { - GtkClipboard* textClipboard = gtk_clipboard_get(gdk_atom_intern_static_string("WebKitClipboardText")); - GtkClipboard* htmlClipboard = gtk_clipboard_get(gdk_atom_intern_static_string("WebKitClipboardHtml")); + ASSERT(range); - gtk_clipboard_clear(textClipboard); - gtk_clipboard_clear(htmlClipboard); + m_dataObject->setText(frame->selectedText()); + m_dataObject->setMarkup(createMarkup(range, 0, AnnotateForInterchange)); - gtk_clipboard_set_text(textClipboard, frame->selectedText().utf8().data(), -1); - gtk_clipboard_set_text(htmlClipboard, createMarkup(range, 0, AnnotateForInterchange).utf8().data(), -1); + if (m_clipboard) + m_helper->writeClipboardContents(m_clipboard); } void ClipboardGtk::writePlainText(const String& text) { - GtkClipboard* textClipboard = gtk_clipboard_get(gdk_atom_intern_static_string("WebKitClipboardText")); - - gtk_clipboard_clear(textClipboard); - - gtk_clipboard_set_text(textClipboard, text.utf8().data(), -1); + m_dataObject->setText(text); + + if (m_clipboard) + m_helper->writeClipboardContents(m_clipboard); } - + bool ClipboardGtk::hasData() { - notImplemented(); - return false; + if (m_clipboard) + m_helper->getClipboardContents(m_clipboard); + + return m_dataObject->hasText() || m_dataObject->hasMarkup() + || m_dataObject->hasURIList() || m_dataObject->hasImage(); } } diff --git a/WebCore/platform/gtk/ClipboardGtk.h b/WebCore/platform/gtk/ClipboardGtk.h index 74e36b1..c3438c4 100644 --- a/WebCore/platform/gtk/ClipboardGtk.h +++ b/WebCore/platform/gtk/ClipboardGtk.h @@ -28,17 +28,26 @@ #define ClipboardGtk_h #include "Clipboard.h" +#include "DataObjectGtk.h" + +typedef struct _GtkClipboard GtkClipboard; namespace WebCore { class CachedImage; + class PasteboardHelper; // State available during IE's events for drag and drop and copy/paste // Created from the EventHandlerGtk to be used by the dom class ClipboardGtk : public Clipboard { public: - static PassRefPtr<ClipboardGtk> create(ClipboardAccessPolicy policy, bool isForDragging) + static PassRefPtr<ClipboardGtk> create(ClipboardAccessPolicy policy, GtkClipboard* clipboard, bool isForDragging) + { + return adoptRef(new ClipboardGtk(policy, clipboard)); + } + + static PassRefPtr<ClipboardGtk> create(ClipboardAccessPolicy policy, PassRefPtr<DataObjectGtk> dataObject, bool isForDragging) { - return adoptRef(new ClipboardGtk(policy, isForDragging)); + return adoptRef(new ClipboardGtk(policy, dataObject, isForDragging)); } virtual ~ClipboardGtk(); @@ -64,8 +73,16 @@ namespace WebCore { virtual bool hasData(); + PasteboardHelper* helper() { return m_helper; } + PassRefPtr<DataObjectGtk> dataObject() { return m_dataObject; } + private: - ClipboardGtk(ClipboardAccessPolicy, bool); + ClipboardGtk(ClipboardAccessPolicy, GtkClipboard*); + ClipboardGtk(ClipboardAccessPolicy, PassRefPtr<DataObjectGtk>, bool); + + RefPtr<DataObjectGtk> m_dataObject; + GtkClipboard* m_clipboard; + PasteboardHelper* m_helper; }; } diff --git a/WebCore/platform/gtk/CursorGtk.cpp b/WebCore/platform/gtk/CursorGtk.cpp index 1c669f3..705c2ae 100644 --- a/WebCore/platform/gtk/CursorGtk.cpp +++ b/WebCore/platform/gtk/CursorGtk.cpp @@ -88,13 +88,15 @@ Cursor::Cursor(GdkCursor* c) : m_impl(c) { m_impl = c; - ASSERT(c); - gdk_cursor_ref(c); + + // The GdkCursor may be NULL - the default cursor for the window. + if (c) + gdk_cursor_ref(c); } const Cursor& pointerCursor() { - static Cursor c = gdk_cursor_new(GDK_LEFT_PTR); + static Cursor c = 0; return c; } diff --git a/WebCore/platform/gtk/DataObjectGtk.cpp b/WebCore/platform/gtk/DataObjectGtk.cpp index 900fe8e..57d920c 100644 --- a/WebCore/platform/gtk/DataObjectGtk.cpp +++ b/WebCore/platform/gtk/DataObjectGtk.cpp @@ -24,6 +24,13 @@ namespace WebCore { +static void replaceNonBreakingSpaceWithSpace(String& str) +{ + static const UChar NonBreakingSpaceCharacter = 0xA0; + static const UChar SpaceCharacter = ' '; + str.replace(NonBreakingSpaceCharacter, SpaceCharacter); +} + String DataObjectGtk::text() { if (m_range) @@ -34,7 +41,7 @@ String DataObjectGtk::text() String DataObjectGtk::markup() { if (m_range) - createMarkup(m_range.get(), 0, AnnotateForInterchange); + return createMarkup(m_range.get(), 0, AnnotateForInterchange); return m_markup; } @@ -42,6 +49,7 @@ void DataObjectGtk::setText(const String& newText) { m_range = 0; m_text = newText; + replaceNonBreakingSpaceWithSpace(m_text); } void DataObjectGtk::setMarkup(const String& newMarkup) @@ -50,6 +58,18 @@ void DataObjectGtk::setMarkup(const String& newMarkup) m_markup = newMarkup; } +void DataObjectGtk::clearText() +{ + m_range = 0; + m_text = ""; +} + +void DataObjectGtk::clearMarkup() +{ + m_range = 0; + m_markup = ""; +} + Vector<String> DataObjectGtk::files() { Vector<KURL> uris(uriList()); diff --git a/WebCore/platform/gtk/DataObjectGtk.h b/WebCore/platform/gtk/DataObjectGtk.h index 22158d4..41f8f49 100644 --- a/WebCore/platform/gtk/DataObjectGtk.h +++ b/WebCore/platform/gtk/DataObjectGtk.h @@ -50,6 +50,8 @@ public: bool hasMarkup() { return m_range || !m_markup.isEmpty(); } bool hasURIList() { return !m_uriList.isEmpty(); } bool hasImage() { return m_image; } + void clearURIList() { m_uriList.clear(); } + void clearImage() { m_image = 0; } GdkDragContext* dragContext() { return m_dragContext.get(); } String text(); @@ -61,6 +63,8 @@ public: String url(); String urlLabel(); void clear(); + void clearText(); + void clearMarkup(); static DataObjectGtk* forClipboard(GtkClipboard*); diff --git a/WebCore/platform/gtk/PasteboardGtk.cpp b/WebCore/platform/gtk/PasteboardGtk.cpp index 907a55e..9e7b23a 100644 --- a/WebCore/platform/gtk/PasteboardGtk.cpp +++ b/WebCore/platform/gtk/PasteboardGtk.cpp @@ -61,7 +61,7 @@ static void clipboard_get_contents_cb(GtkClipboard *clipboard, GtkSelectionData if (info == Pasteboard::generalPasteboard()->helper()->getIdForTargetType(PasteboardHelper::TargetTypeMarkup)) gtk_selection_data_set(selection_data, selection_data->target, 8, reinterpret_cast<const guchar*>(clipboardData->markup()), - g_utf8_strlen(clipboardData->markup(), -1)); + strlen(clipboardData->markup())); else gtk_selection_data_set_text(selection_data, clipboardData->text(), -1); } diff --git a/WebCore/platform/gtk/PasteboardHelper.cpp b/WebCore/platform/gtk/PasteboardHelper.cpp index be32ea5..3dc4cc0 100644 --- a/WebCore/platform/gtk/PasteboardHelper.cpp +++ b/WebCore/platform/gtk/PasteboardHelper.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Martin Robinson <mrobinson@webkit.org> + * Copyright (C) Igalia S.L. * All rights reserved. * * This library is free software; you can redistribute it and/or @@ -26,12 +27,15 @@ #include "Frame.h" #include "Page.h" #include "Pasteboard.h" +#include "TextResourceDecoder.h" #include <gtk/gtk.h> #include <wtf/gobject/GOwnPtr.h> namespace WebCore { static GdkAtom gdkMarkupAtom = gdk_atom_intern("text/html", FALSE); +static GdkAtom netscapeURLAtom = gdk_atom_intern("_NETSCAPE_URL", FALSE); +static GdkAtom uriListAtom = gdk_atom_intern("text/uri-list", FALSE); PasteboardHelper::PasteboardHelper() : m_targetList(gtk_target_list_new(0, 0)) @@ -48,6 +52,8 @@ void PasteboardHelper::initializeTargetList() { gtk_target_list_add_text_targets(m_targetList, getIdForTargetType(TargetTypeText)); gtk_target_list_add(m_targetList, gdkMarkupAtom, 0, getIdForTargetType(TargetTypeMarkup)); + gtk_target_list_add_uri_targets(m_targetList, getIdForTargetType(TargetTypeURIList)); + gtk_target_list_add(m_targetList, netscapeURLAtom, 0, getIdForTargetType(TargetTypeNetscapeURL)); } static inline GtkWidget* widgetFromFrame(Frame* frame) @@ -84,16 +90,85 @@ GtkTargetList* PasteboardHelper::targetList() const return m_targetList; } +static Vector<KURL> urisToKURLVector(gchar** uris) +{ + ASSERT(uris); + + Vector<KURL> uriList; + for (int i = 0; *(uris + i); i++) + uriList.append(KURL(KURL(), *(uris + i))); + + return uriList; +} + +void PasteboardHelper::getClipboardContents(GtkClipboard* clipboard) +{ + DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard); + ASSERT(dataObject); + + if (gtk_clipboard_wait_is_text_available(clipboard)) { + GOwnPtr<gchar> textData(gtk_clipboard_wait_for_text(clipboard)); + if (textData) + dataObject->setText(String::fromUTF8(textData.get())); + } + + if (gtk_clipboard_wait_is_target_available(clipboard, gdkMarkupAtom)) { + if (GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, gdkMarkupAtom)) { + RefPtr<TextResourceDecoder> decoder(TextResourceDecoder::create("text/plain", "UTF-8", true)); + String markup(decoder->decode(reinterpret_cast<char*>(data->data), data->length)); + markup += decoder->flush(); + dataObject->setMarkup(markup); + gtk_selection_data_free(data); + } + } + + if (gtk_clipboard_wait_is_target_available(clipboard, uriListAtom)) { + if (GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, uriListAtom)) { + gchar** uris = gtk_selection_data_get_uris(data); + if (uris) { + dataObject->setURIList(urisToKURLVector(uris)); + g_strfreev(uris); + } + gtk_selection_data_free(data); + } + } +} + void PasteboardHelper::fillSelectionData(GtkSelectionData* selectionData, guint info, DataObjectGtk* dataObject) { if (info == getIdForTargetType(TargetTypeText)) gtk_selection_data_set_text(selectionData, dataObject->text().utf8().data(), -1); + else if (info == getIdForTargetType(TargetTypeMarkup)) { GOwnPtr<gchar> markup(g_strdup(dataObject->markup().utf8().data())); gtk_selection_data_set(selectionData, selectionData->target, 8, - reinterpret_cast<const guchar*>(markup.get()), - strlen(markup.get())); - } + reinterpret_cast<const guchar*>(markup.get()), strlen(markup.get())); + + } else if (info == getIdForTargetType(TargetTypeURIList)) { + Vector<KURL> uriList(dataObject->uriList()); + gchar** uris = g_new0(gchar*, uriList.size() + 1); + for (size_t i = 0; i < uriList.size(); i++) + uris[i] = g_strdup(uriList[i].string().utf8().data()); + + gtk_selection_data_set_uris(selectionData, uris); + g_strfreev(uris); + + } else if (info == getIdForTargetType(TargetTypeNetscapeURL) && dataObject->hasURL()) { + String url(dataObject->url()); + String result(url); + result.append("\n"); + + if (dataObject->hasText()) + result.append(dataObject->text()); + else + result.append(url); + + GOwnPtr<gchar> resultData(g_strdup(result.utf8().data())); + gtk_selection_data_set(selectionData, selectionData->target, 8, + reinterpret_cast<const guchar*>(resultData.get()), strlen(resultData.get())); + + } else if (info == getIdForTargetType(TargetTypeImage)) + gtk_selection_data_set_pixbuf(selectionData, dataObject->image()); } GtkTargetList* PasteboardHelper::targetListForDataObject(DataObjectGtk* dataObject) @@ -106,6 +181,14 @@ GtkTargetList* PasteboardHelper::targetListForDataObject(DataObjectGtk* dataObje if (dataObject->hasMarkup()) gtk_target_list_add(list, gdkMarkupAtom, 0, getIdForTargetType(TargetTypeMarkup)); + if (dataObject->hasURIList()) { + gtk_target_list_add_uri_targets(list, getIdForTargetType(TargetTypeURIList)); + gtk_target_list_add(list, netscapeURLAtom, 0, getIdForTargetType(TargetTypeNetscapeURL)); + } + + if (dataObject->hasImage()) + gtk_target_list_add_image_targets(list, getIdForTargetType(TargetTypeImage), TRUE); + return list; } diff --git a/WebCore/platform/gtk/PasteboardHelper.h b/WebCore/platform/gtk/PasteboardHelper.h index 6e5d366..2d46adc 100644 --- a/WebCore/platform/gtk/PasteboardHelper.h +++ b/WebCore/platform/gtk/PasteboardHelper.h @@ -2,6 +2,7 @@ * Copyright (C) 2007 Luca Bruno <lethalman88@gmail.com> * Copyright (C) 2009 Holger Hans Peter Freyther * Copyright (C) 2010 Martin Robinson <mrobinson@webkit.org> + * Copyright (C) 2010 Igalia S.L. * All rights reserved. * * This library is free software; you can redistribute it and/or @@ -49,8 +50,10 @@ public: GtkClipboard* getClipboard(Frame*) const; GtkClipboard* getPrimarySelectionClipboard(Frame*) const; GtkTargetList* targetList() const; + GtkTargetList* targetListForDataObject(DataObjectGtk*); void fillSelectionData(GtkSelectionData*, guint, DataObjectGtk*); - void writeClipboardContents(GtkClipboard*, GClosure*); + void writeClipboardContents(GtkClipboard*, GClosure* closure = 0); + void getClipboardContents(GtkClipboard*); enum PasteboardTargetType { TargetTypeText, TargetTypeMarkup, TargetTypeURIList, TargetTypeNetscapeURL, TargetTypeImage, TargetTypeUnknown }; virtual guint getIdForTargetType(PasteboardTargetType) = 0; @@ -61,7 +64,6 @@ protected: private: GtkTargetList* m_targetList; - GtkTargetList* targetListForDataObject(DataObjectGtk*); }; } diff --git a/WebCore/platform/gtk/RenderThemeGtk.cpp b/WebCore/platform/gtk/RenderThemeGtk.cpp index 93794ff..31af1a9 100644 --- a/WebCore/platform/gtk/RenderThemeGtk.cpp +++ b/WebCore/platform/gtk/RenderThemeGtk.cpp @@ -92,8 +92,11 @@ void RenderThemeGtk::initMediaStyling(GtkStyle* style, bool force) m_seekForwardButton.clear(); m_fullscreenButton = Image::loadPlatformThemeIcon("gtk-fullscreen", m_mediaIconSize); - m_muteButton = Image::loadPlatformThemeIcon("audio-volume-muted", m_mediaIconSize); - m_unmuteButton = Image::loadPlatformThemeIcon("audio-volume-high", m_mediaIconSize); + // Note that the muteButton and unmuteButton take icons reflecting + // the *current* state. Hence, the unmuteButton represents the *muted* + // status, the muteButton represents the then current *unmuted* status. + m_muteButton = Image::loadPlatformThemeIcon("audio-volume-high", m_mediaIconSize); + m_unmuteButton = Image::loadPlatformThemeIcon("audio-volume-muted", m_mediaIconSize); m_playButton = Image::loadPlatformThemeIcon(reinterpret_cast<const char*>(playButtonIconName), m_mediaIconSize); m_pauseButton = Image::loadPlatformThemeIcon("gtk-media-pause", m_mediaIconSize).releaseRef(); m_seekBackButton = Image::loadPlatformThemeIcon(reinterpret_cast<const char*>(seekBackButtonIconName), m_mediaIconSize); diff --git a/WebCore/platform/gtk/ScrollViewGtk.cpp b/WebCore/platform/gtk/ScrollViewGtk.cpp index 3df3cb5..5c258ad 100644 --- a/WebCore/platform/gtk/ScrollViewGtk.cpp +++ b/WebCore/platform/gtk/ScrollViewGtk.cpp @@ -72,6 +72,29 @@ PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientati return Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar); } +#if !GTK_CHECK_VERSION(2, 14, 0) +#define gtk_adjustment_configure AdjustmentConfigure + +static void AdjustmentConfigure(GtkAdjustment* adjustment, gdouble value, gdouble lower, gdouble upper, + gdouble stepIncrement, gdouble pageIncrement, gdouble pageSize) +{ + g_object_freeze_notify(G_OBJECT(adjustment)); + + g_object_set(adjustment, + "lower", lower, + "upper", upper, + "step-increment", stepIncrement, + "page-increment", pageIncrement, + "page-size", pageSize, + NULL); + + g_object_thaw_notify(G_OBJECT(adjustment)); + + gtk_adjustment_changed(adjustment); + gtk_adjustment_value_changed(adjustment); +} +#endif + /* * The following is assumed: * (hadj && vadj) || (!hadj && !vadj) @@ -100,17 +123,22 @@ void ScrollView::setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj, boo // set in the normal case), we make sure they are up-to-date // here. This is needed for the parent scrolling widget to be // able to report correct values. - m_horizontalAdjustment->lower = 0; - m_horizontalAdjustment->upper = resetValues ? 0 : frameRect().width(); - m_horizontalAdjustment->value = resetValues ? 0 : scrollOffset().width(); - gtk_adjustment_changed(m_horizontalAdjustment); - gtk_adjustment_value_changed(m_horizontalAdjustment); - - m_verticalAdjustment->lower = 0; - m_verticalAdjustment->upper = resetValues ? 0 : frameRect().height(); - m_verticalAdjustment->value = resetValues ? 0 : scrollOffset().height(); - gtk_adjustment_changed(m_verticalAdjustment); - gtk_adjustment_value_changed(m_verticalAdjustment); + + int horizontalPageStep = max(max<int>(frameRect().width() * Scrollbar::minFractionToStepWhenPaging(), frameRect().width() - Scrollbar::maxOverlapBetweenPages()), 1); + gtk_adjustment_configure(m_horizontalAdjustment, + resetValues ? 0 : scrollOffset().width(), 0, + resetValues ? 0 : contentsSize().width(), + resetValues ? 0 : Scrollbar::pixelsPerLineStep(), + resetValues ? 0 : horizontalPageStep, + resetValues ? 0 : frameRect().width()); + + int verticalPageStep = max(max<int>(frameRect().height() * Scrollbar::minFractionToStepWhenPaging(), frameRect().height() - Scrollbar::maxOverlapBetweenPages()), 1); + gtk_adjustment_configure(m_verticalAdjustment, + resetValues ? 0 : scrollOffset().height(), 0, + resetValues ? 0 : contentsSize().height(), + resetValues ? 0 : Scrollbar::pixelsPerLineStep(), + resetValues ? 0 : verticalPageStep, + resetValues ? 0 : frameRect().height()); } else { ScrollbarGtk* hScrollbar = reinterpret_cast<ScrollbarGtk*>(horizontalScrollbar()); if (hScrollbar) diff --git a/WebCore/platform/gtk/WidgetGtk.cpp b/WebCore/platform/gtk/WidgetGtk.cpp index 834c21a..71addfd 100644 --- a/WebCore/platform/gtk/WidgetGtk.cpp +++ b/WebCore/platform/gtk/WidgetGtk.cpp @@ -53,9 +53,10 @@ Widget::~Widget() releasePlatformWidget(); } -void Widget::setFocus() +void Widget::setFocus(bool focused) { - gtk_widget_grab_focus(platformWidget() ? platformWidget() : GTK_WIDGET(root()->hostWindow()->platformPageClient())); + if (focused) + gtk_widget_grab_focus(platformWidget() ? platformWidget() : GTK_WIDGET(root()->hostWindow()->platformPageClient())); } static GdkDrawable* gdkDrawable(PlatformWidget widget) diff --git a/WebCore/platform/haiku/WidgetHaiku.cpp b/WebCore/platform/haiku/WidgetHaiku.cpp index 5ff504f..3663d67 100644 --- a/WebCore/platform/haiku/WidgetHaiku.cpp +++ b/WebCore/platform/haiku/WidgetHaiku.cpp @@ -80,11 +80,13 @@ void Widget::setFrameRect(const IntRect& rect) m_frame = rect; } -void Widget::setFocus() +void Widget::setFocus(bool focused) { - AutoPlatformWidgetLocker locker(topLevelPlatformWidget()); - if (locker.isLocked()) - topLevelPlatformWidget()->MakeFocus(); + if (focused) { + AutoPlatformWidgetLocker locker(topLevelPlatformWidget()); + if (locker.isLocked()) + topLevelPlatformWidget()->MakeFocus(); + } } void Widget::setCursor(const Cursor& cursor) diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp index 5965ae4..147085f 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp +++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp @@ -235,13 +235,13 @@ bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex, unsigned char* rowBuff return true; } -void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod) +bool GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod) { // Initialize the frame if necessary. Some GIFs insert do-nothing frames, // in which case we never reach haveDecodedRow() before getting here. RGBA32Buffer& buffer = m_frameBufferCache[frameIndex]; if ((buffer.status() == RGBA32Buffer::FrameEmpty) && !initFrameBuffer(frameIndex)) - return; + return false; // initFrameBuffer() has already called setFailed(). buffer.setStatus(RGBA32Buffer::FrameComplete); buffer.setDuration(frameDuration); @@ -277,6 +277,8 @@ void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, buffer.setHasAlpha(false); } } + + return true; } void GIFImageDecoder::gifComplete() @@ -294,7 +296,9 @@ void GIFImageDecoder::decode(unsigned haltAtFrame, GIFQuery query) if (!m_reader) m_reader.set(new GIFImageReader(this)); - if (!m_reader->read((const unsigned char*)m_data->data() + m_readOffset, m_data->size() - m_readOffset, query, haltAtFrame)) + // If we couldn't decode the image but we've received all the data, decoding + // has failed. + if (!m_reader->read((const unsigned char*)m_data->data() + m_readOffset, m_data->size() - m_readOffset, query, haltAtFrame) && isAllDataReceived()) setFailed(); if (failed()) diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h index 28a9a59..1c3378c 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h +++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h @@ -54,13 +54,14 @@ namespace WebCore { // Callbacks from the GIF reader. void decodingHalted(unsigned bytesLeft); bool haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber, unsigned repeatCount, bool writeTransparentPixels); - void frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod); + bool frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod); void gifComplete(); private: // If the query is GIFFullQuery, decodes the image up to (but not // including) |haltAtFrame|. Otherwise, decodes as much as is needed to - // answer the query, ignoring bitmap data. + // answer the query, ignoring bitmap data. If decoding fails but there + // is no more data coming, sets the "decode failure" flag. void decode(unsigned haltAtFrame, GIFQuery); // Called to initialize the frame buffer with the given index, based on diff --git a/WebCore/platform/image-decoders/gif/GIFImageReader.cpp b/WebCore/platform/image-decoders/gif/GIFImageReader.cpp index 677853e..be77426 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageReader.cpp +++ b/WebCore/platform/image-decoders/gif/GIFImageReader.cpp @@ -290,7 +290,9 @@ bool GIFImageReader::do_lzw(const unsigned char *q) /* Check for explicit end-of-stream code */ if (code == (clear_code + 1)) { /* end-of-stream should only appear after all image data */ - return !rows_remaining; + if (!rows_remaining) + return true; + return clientptr ? clientptr->setFailed() : false; } if (oldcode == -1) { @@ -308,13 +310,13 @@ bool GIFImageReader::do_lzw(const unsigned char *q) code = oldcode; if (stackp == stack + MAX_BITS) - return false; + return clientptr ? clientptr->setFailed() : false; } while (code >= clear_code) { if (code >= MAX_BITS || code == prefix[code]) - return false; + return clientptr ? clientptr->setFailed() : false; // Even though suffix[] only holds characters through suffix[avail - 1], // allowing code >= avail here lets us be more tolerant of malformed @@ -324,7 +326,7 @@ bool GIFImageReader::do_lzw(const unsigned char *q) code = prefix[code]; if (stackp == stack + MAX_BITS) - return false; + return clientptr ? clientptr->setFailed() : false; } *stackp++ = firstchar = suffix[code]; @@ -415,7 +417,7 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, bytes_to_consume -= l; if (clientptr) clientptr->decodingHalted(0); - return true; + return false; } // Reset hold buffer count bytes_in_hold = 0; @@ -440,10 +442,9 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, switch (state) { case gif_lzw: - if (!do_lzw(q)) { - state = gif_error; - break; - } + if (!do_lzw(q)) + return false; // If do_lzw() encountered an error, it has already called + // clientptr->setFailed(). GETN(1, gif_sub_block); break; @@ -454,15 +455,11 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, // Since we use a codesize of 1 more than the datasize, we need to ensure // that our datasize is strictly less than the MAX_LZW_BITS value (12). // This sets the largest possible codemask correctly at 4095. - if (datasize >= MAX_LZW_BITS) { - state = gif_error; - break; - } + if (datasize >= MAX_LZW_BITS) + return clientptr ? clientptr->setFailed() : false; int clear_code = 1 << datasize; - if (clear_code >= MAX_BITS) { - state = gif_error; - break; - } + if (clear_code >= MAX_BITS) + return clientptr ? clientptr->setFailed() : false; if (frame_reader) { frame_reader->datasize = datasize; @@ -498,10 +495,8 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, version = 89; else if (!strncmp((char*)q, "GIF87a", 6)) version = 87; - else { - state = gif_error; - break; - } + else + return clientptr ? clientptr->setFailed() : false; GETN(7, gif_global_header); } break; @@ -586,7 +581,7 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, state = gif_done; } else { /* No images decoded, there is nothing to display. */ - state = gif_error; + return clientptr ? clientptr->setFailed() : false; } break; } else @@ -714,7 +709,7 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, GETN(1, gif_netscape_extension_block); } else { // 0,3-7 are yet to be defined netscape extension codes - state = gif_error; + return clientptr ? clientptr->setFailed() : false; } break; @@ -755,10 +750,8 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, if (!height || !width) { height = screen_height; width = screen_width; - if (!height || !width) { - state = gif_error; - break; - } + if (!height || !width) + return clientptr ? clientptr->setFailed() : false; } if (query == GIFImageDecoder::GIFSizeQuery || haltAtFrame == images_decoded) { @@ -794,10 +787,8 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, frame_reader->rowbuf = new unsigned char[screen_width]; } - if (!frame_reader->rowbuf) { - state = gif_oom; - break; - } + if (!frame_reader->rowbuf) + return clientptr ? clientptr->setFailed() : false; if (screen_height < height) screen_height = height; @@ -838,10 +829,8 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, if (frame_reader && (!map || (num_colors > frame_reader->local_colormap_size))) { delete []map; map = new unsigned char[size]; - if (!map) { - state = gif_oom; - break; - } + if (!map) + return clientptr ? clientptr->setFailed() : false; } /* Switch to the new local palette after it loads */ @@ -893,8 +882,9 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, images_decoded++; // CALLBACK: The frame is now complete. - if (clientptr && frame_reader) - clientptr->frameComplete(images_decoded - 1, frame_reader->delay_time, frame_reader->disposal_method); + if (clientptr && frame_reader && !clientptr->frameComplete(images_decoded - 1, frame_reader->delay_time, frame_reader->disposal_method)) + return false; // frameComplete() has already called + // clientptr->setFailed(). /* Clear state from this image */ if (frame_reader) { @@ -913,14 +903,6 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, clientptr->gifComplete(); return true; - // Handle out of memory errors - case gif_oom: - return false; - - // Handle general errors - case gif_error: - return false; - // We shouldn't ever get here. default: break; @@ -945,5 +927,5 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, if (clientptr) clientptr->decodingHalted(0); - return true; + return false; } diff --git a/WebCore/platform/image-decoders/gif/GIFImageReader.h b/WebCore/platform/image-decoders/gif/GIFImageReader.h index 5982827..be5be19 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageReader.h +++ b/WebCore/platform/image-decoders/gif/GIFImageReader.h @@ -69,8 +69,6 @@ typedef enum { gif_consume_block, gif_skip_block, gif_done, - gif_oom, - gif_error, gif_comment_extension, gif_application_extension, gif_netscape_extension_block, diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp index 3d9fb8e..8375693 100644 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp +++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp @@ -69,7 +69,6 @@ enum jstate { JPEG_DECOMPRESS_PROGRESSIVE, // Output progressive pixels JPEG_DECOMPRESS_SEQUENTIAL, // Output sequential pixels JPEG_DONE, - JPEG_SINK_NON_JPEG_TRAILER, // Some image files have a non-JPEG trailer JPEG_ERROR }; @@ -169,16 +168,15 @@ public: // We need to do the setjmp here. Otherwise bad things will happen if (setjmp(m_err.setjmp_buffer)) { - m_state = JPEG_SINK_NON_JPEG_TRAILER; close(); - return false; + return m_decoder->setFailed(); } switch (m_state) { case JPEG_HEADER: // Read file parameters with jpeg_read_header(). if (jpeg_read_header(&m_info, true) == JPEG_SUSPENDED) - return true; // I/O suspension. + return false; // I/O suspension. // Let libjpeg take care of gray->RGB and YCbCr->RGB conversions. switch (m_info.jpeg_color_space) { @@ -194,7 +192,7 @@ public: m_info.out_color_space = JCS_CMYK; break; default: - return false; + return m_decoder->setFailed(); } // Don't allocate a giant and superfluous memory buffer when the @@ -214,7 +212,7 @@ public: // We can fill in the size now that the header is available. if (!m_decoder->setSize(m_info.image_width, m_info.image_height)) - return false; + return m_decoder->setFailed(); if (m_decodingSizeOnly) { // We can stop here. Reduce our buffer length and available @@ -237,7 +235,7 @@ public: // Start decompressor. if (!jpeg_start_decompress(&m_info)) - return true; // I/O suspension. + return false; // I/O suspension. // If this is a progressive JPEG ... m_state = (m_info.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE : JPEG_DECOMPRESS_SEQUENTIAL; @@ -247,7 +245,7 @@ public: if (m_state == JPEG_DECOMPRESS_SEQUENTIAL) { if (!m_decoder->outputScanlines()) - return true; // I/O suspension. + return false; // I/O suspension. // If we've completed image output... ASSERT(m_info.output_scanline == m_info.output_height); @@ -273,7 +271,7 @@ public: --scan; if (!jpeg_start_output(&m_info, scan)) - return true; // I/O suspension. + return false; // I/O suspension. } if (m_info.output_scanline == 0xffffff) @@ -285,12 +283,12 @@ public: // don't call jpeg_start_output() multiple times for // the same scan. m_info.output_scanline = 0xffffff; - return true; // I/O suspension. + return false; // I/O suspension. } if (m_info.output_scanline == m_info.output_height) { if (!jpeg_finish_output(&m_info)) - return true; // I/O suspension. + return false; // I/O suspension. if (jpeg_input_complete(&m_info) && (m_info.input_scan_number == m_info.output_scan_number)) break; @@ -305,15 +303,8 @@ public: case JPEG_DONE: // Finish decompression. - if (!jpeg_finish_decompress(&m_info)) - return true; // I/O suspension. - - m_state = JPEG_SINK_NON_JPEG_TRAILER; - break; + return jpeg_finish_decompress(&m_info); - case JPEG_SINK_NON_JPEG_TRAILER: - break; - case JPEG_ERROR: // We can get here if the constructor failed. return m_decoder->setFailed(); @@ -487,7 +478,9 @@ void JPEGImageDecoder::decode(bool onlySize) if (!m_reader) m_reader.set(new JPEGImageReader(this)); - if (!m_reader->decode(m_data->buffer(), onlySize)) + // If we couldn't decode the image but we've received all the data, decoding + // has failed. + if (!m_reader->decode(m_data->buffer(), onlySize) && isAllDataReceived()) setFailed(); if (failed() || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h index 45e14bc..79bad47 100644 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h +++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h @@ -52,7 +52,8 @@ namespace WebCore { private: // Decodes the image. If |onlySize| is true, stops decoding after - // calculating the image size. + // calculating the image size. If decoding fails but there is no more + // data coming, sets the "decode failure" flag. void decode(bool onlySize); OwnPtr<JPEGImageReader> m_reader; diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp index de01d55..1dcf6c7 100644 --- a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp +++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp @@ -119,7 +119,7 @@ public: unsigned currentBufferSize() const { return m_currentBufferSize; } - void decode(const SharedBuffer& data, bool sizeOnly) + bool decode(const SharedBuffer& data, bool sizeOnly) { m_decodingSizeOnly = sizeOnly; PNGImageDecoder* decoder = static_cast<PNGImageDecoder*>(png_get_progressive_ptr(m_png)); @@ -127,8 +127,7 @@ public: // We need to do the setjmp here. Otherwise bad things will happen. if (setjmp(m_png->jmpbuf)) { close(); - decoder->setFailed(); - return; + return decoder->setFailed(); } const char* segment; @@ -140,10 +139,9 @@ public: // merely want to check if we've managed to set the size, not // (recursively) trigger additional decoding if we haven't. if (sizeOnly ? decoder->ImageDecoder::isSizeAvailable() : decoder->isComplete()) - return; + return true; } - if (!decoder->isComplete() && decoder->isAllDataReceived()) - decoder->pngComplete(); + return false; } bool decodingSizeOnly() const { return m_decodingSizeOnly; } @@ -371,7 +369,10 @@ void PNGImageDecoder::decode(bool onlySize) if (!m_reader) m_reader.set(new PNGImageReader(this)); - m_reader->decode(*m_data, onlySize); + // If we couldn't decode the image but we've received all the data, decoding + // has failed. + if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived()) + setFailed(); if (failed() || isComplete()) m_reader.clear(); diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.h b/WebCore/platform/image-decoders/png/PNGImageDecoder.h index 3f0602c..287a794 100644 --- a/WebCore/platform/image-decoders/png/PNGImageDecoder.h +++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.h @@ -57,7 +57,8 @@ namespace WebCore { private: // Decodes the image. If |onlySize| is true, stops decoding after - // calculating the image size. + // calculating the image size. If decoding fails but there is no more + // data coming, sets the "decode failure" flag. void decode(bool onlySize); OwnPtr<PNGImageReader> m_reader; diff --git a/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp b/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp index aa20c62..19363c8 100644 --- a/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp +++ b/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp @@ -129,10 +129,7 @@ bool PNGImageEncoder::encode(const unsigned char* input, const IntSize& size, return false; } - png_struct* pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, - png_voidp_NULL, - png_error_ptr_NULL, - png_error_ptr_NULL); + png_struct* pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!pngPtr) return false; diff --git a/WebCore/platform/mac/KeyEventMac.mm b/WebCore/platform/mac/KeyEventMac.mm index b8bf500..7b8b2ce 100644 --- a/WebCore/platform/mac/KeyEventMac.mm +++ b/WebCore/platform/mac/KeyEventMac.mm @@ -169,7 +169,14 @@ static int windowsKeyCodeForKeyEvent(NSEvent *event) // 3. Certain punctuation keys. On Windows, these are also remapped depending on current keyboard layout, // but see comment in windowsKeyCodeForCharCode(). if ([event type] == NSKeyDown || [event type] == NSKeyUp) { - NSString* s = [event characters]; // Cannot use charactersIgnoringModifiers, because Cmd switches Roman letters for Dvorak-QWERTY layout. + // Cmd switches Roman letters for Dvorak-QWERTY layout, so try modified characters first. + NSString* s = [event characters]; + code = [s length] > 0 ? windowsKeyCodeForCharCode([s characterAtIndex:0]) : 0; + if (code) + return code; + + // Ctrl+A on an AZERTY keyboard would get VK_Q keyCode if we relied on -[NSEvent keyCode] below. + s = [event charactersIgnoringModifiers]; code = [s length] > 0 ? windowsKeyCodeForCharCode([s characterAtIndex:0]) : 0; if (code) return code; diff --git a/WebCore/platform/mac/PopupMenuMac.mm b/WebCore/platform/mac/PopupMenuMac.mm index 0ecaa13..6c067b9 100644 --- a/WebCore/platform/mac/PopupMenuMac.mm +++ b/WebCore/platform/mac/PopupMenuMac.mm @@ -114,8 +114,6 @@ void PopupMenu::populate() [[m_popup.get() menu] setMenuChangedMessagesEnabled:messagesEnabled]; } -#if !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) - void PopupMenu::show(const IntRect& r, FrameView* v, int index) { populate(); @@ -196,14 +194,6 @@ void PopupMenu::show(const IntRect& r, FrameView* v, int index) [event release]; } -#else - -void PopupMenu::show(const IntRect&, FrameView*, int) -{ -} - -#endif - void PopupMenu::hide() { [m_popup.get() dismissPopUp]; diff --git a/WebCore/platform/mac/SharedBufferMac.mm b/WebCore/platform/mac/SharedBufferMac.mm index c4e7528..3f5e5d4 100644 --- a/WebCore/platform/mac/SharedBufferMac.mm +++ b/WebCore/platform/mac/SharedBufferMac.mm @@ -50,6 +50,7 @@ using namespace WebCore; + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebCore/platform/mac/ThemeMac.mm b/WebCore/platform/mac/ThemeMac.mm index bbc6d6b..7cc913f 100644 --- a/WebCore/platform/mac/ThemeMac.mm +++ b/WebCore/platform/mac/ThemeMac.mm @@ -46,6 +46,11 @@ using namespace std; return YES; } +- (NSText *)currentEditor +{ + return nil; +} + @end // FIXME: Default buttons really should be more like push buttons and not like buttons. @@ -77,9 +82,9 @@ static NSControlSize controlSizeForFont(const Font& font) return NSMiniControlSize; } -static LengthSize sizeFromFont(const Font& font, const LengthSize& zoomedSize, float zoomFactor, const IntSize* sizes) +static LengthSize sizeFromNSControlSize(NSControlSize nsControlSize, const LengthSize& zoomedSize, float zoomFactor, const IntSize* sizes) { - IntSize controlSize = sizes[controlSizeForFont(font)]; + IntSize controlSize = sizes[nsControlSize]; if (zoomFactor != 1.0f) controlSize = IntSize(controlSize.width() * zoomFactor, controlSize.height() * zoomFactor); LengthSize result = zoomedSize; @@ -90,6 +95,11 @@ static LengthSize sizeFromFont(const Font& font, const LengthSize& zoomedSize, f return result; } +static LengthSize sizeFromFont(const Font& font, const LengthSize& zoomedSize, float zoomFactor, const IntSize* sizes) +{ + return sizeFromNSControlSize(controlSizeForFont(font), zoomedSize, zoomFactor, sizes); +} + static void setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minZoomedSize, float zoomFactor) { NSControlSize size; @@ -439,6 +449,65 @@ static void paintButton(ControlPart part, ControlStates states, GraphicsContext* END_BLOCK_OBJC_EXCEPTIONS } +// Stepper + +static const IntSize* stepperSizes() +{ + static const IntSize sizes[3] = { IntSize(19, 27), IntSize(15, 22), IntSize(13, 15) }; + return sizes; +} + +// We don't use controlSizeForFont() for steppers because the stepper height +// should be equal to or less than the corresponding text field height, +static NSControlSize stepperControlSizeForFont(const Font& font) +{ + int fontSize = font.pixelSize(); + if (fontSize >= 18) + return NSRegularControlSize; + if (fontSize >= 13) + return NSSmallControlSize; + return NSMiniControlSize; +} + +static NSStepperCell* stepper(ControlStates states, const IntRect& zoomedRect, float zoomFactor) +{ + static NSStepperCell* cell = [[NSStepperCell alloc] init]; + setControlSize(cell, stepperSizes(), zoomedRect.size(), zoomFactor); + + updateStates(cell, states); + if (states & PressedState && states & SpinUpState) { + // FIXME: There is no way to draw a NSSteperCell with the up button hilighted. + // Disables the hilight of the down button if the up button is pressed. + [cell setHighlighted:NO]; + } + return cell; +} + +static void paintStepper(ControlStates states, GraphicsContext* context, const IntRect& zoomedRect, float zoomFactor, ScrollView* scrollView) +{ + NSStepperCell* cell = stepper(states, zoomedRect, zoomFactor); + + context->save(); + NSControlSize controlSize = [cell controlSize]; + IntSize zoomedSize = stepperSizes()[controlSize]; + IntRect rect(zoomedRect); + + if (zoomFactor != 1.0f) { + rect.setWidth(rect.width() / zoomFactor); + rect.setHeight(rect.height() / zoomFactor); + context->translate(rect.x(), rect.y()); + context->scale(FloatSize(zoomFactor, zoomFactor)); + context->translate(-rect.x(), -rect.y()); + } + + BEGIN_BLOCK_OBJC_EXCEPTIONS + [cell drawWithFrame:NSRect(rect) inView:ThemeMac::ensuredView(scrollView)]; + [cell setControlView:nil]; + END_BLOCK_OBJC_EXCEPTIONS + + context->restore(); +} + // This will ensure that we always return a valid NSView, even if ScrollView doesn't have an associated document NSView. // If the ScrollView doesn't have an NSView, we will return a fake NSView whose sole purpose is to tell AppKit that it's flipped. NSView *ThemeMac::ensuredView(ScrollView* scrollView) @@ -494,6 +563,13 @@ LengthSize ThemeMac::controlSize(ControlPart part, const Font& font, const Lengt case ListButtonPart: return sizeFromFont(font, LengthSize(zoomedSize.width(), Length()), zoomFactor, listButtonSizes()); #endif + case InnerSpinButtonPart: + // We don't use inner spin buttons on Mac. + return LengthSize(Length(Fixed), Length(Fixed)); + case OuterSpinButtonPart: + if (!zoomedSize.width().isIntrinsicOrAuto() && !zoomedSize.height().isIntrinsicOrAuto()) + return zoomedSize; + return sizeFromNSControlSize(stepperControlSizeForFont(font), zoomedSize, zoomFactor, stepperSizes()); default: return zoomedSize; } @@ -507,6 +583,14 @@ LengthSize ThemeMac::minimumControlSize(ControlPart part, const Font& font, floa case ButtonPart: case ListButtonPart: return LengthSize(Length(0, Fixed), Length(static_cast<int>(15 * zoomFactor), Fixed)); + case InnerSpinButtonPart: + // We don't use inner spin buttons on Mac. + return LengthSize(Length(Fixed), Length(Fixed)); + case OuterSpinButtonPart: { + IntSize base = stepperSizes()[NSMiniControlSize]; + return LengthSize(Length(static_cast<int>(base.width() * zoomFactor), Fixed), + Length(static_cast<int>(base.height() * zoomFactor), Fixed)); + } default: return Theme::minimumControlSize(part, font, zoomFactor); } @@ -583,6 +667,16 @@ void ThemeMac::inflateControlPaintRect(ControlPart part, ControlStates states, I } break; } + case OuterSpinButtonPart: { + static const int stepperMargin[4] = { 0, 0, 0, 0}; + NSCell *cell = stepper(states, zoomedRect, zoomFactor); + NSControlSize controlSize = [cell controlSize]; + IntSize zoomedSize = stepperSizes()[controlSize]; + zoomedSize.setHeight(zoomedSize.height() * zoomFactor); + zoomedSize.setWidth(zoomedSize.width() * zoomFactor); + zoomedRect = inflateRect(zoomedRect, zoomedSize, stepperMargin, zoomFactor); + break; + } default: break; } @@ -605,6 +699,9 @@ void ThemeMac::paint(ControlPart part, ControlStates states, GraphicsContext* co case ListButtonPart: paintButton(part, states, context, zoomedRect, zoomFactor, scrollView); break; + case OuterSpinButtonPart: + paintStepper(states, context, zoomedRect, zoomFactor, scrollView); + break; default: break; } diff --git a/WebCore/platform/mac/WebCoreObjCExtras.mm b/WebCore/platform/mac/WebCoreObjCExtras.mm index 4fc757c..05d3e01 100644 --- a/WebCore/platform/mac/WebCoreObjCExtras.mm +++ b/WebCore/platform/mac/WebCoreObjCExtras.mm @@ -71,14 +71,9 @@ static void deallocCallback(void* context) bool WebCoreObjCScheduleDeallocateOnMainThread(Class cls, id object) { ASSERT([object isKindOfClass:cls]); - -#if USE(WEB_THREAD) + if (isMainThread()) return false; -#else - if (pthread_main_np() != 0) - return false; -#endif ClassAndIdPair* pair = new ClassAndIdPair(cls, object); callOnMainThread(deallocCallback, pair); diff --git a/WebCore/platform/mac/WidgetMac.mm b/WebCore/platform/mac/WidgetMac.mm index 1aad76f..37c9e9f 100644 --- a/WebCore/platform/mac/WidgetMac.mm +++ b/WebCore/platform/mac/WidgetMac.mm @@ -105,8 +105,11 @@ Widget::~Widget() } // FIXME: Should move this to Chrome; bad layering that this knows about Frame. -void Widget::setFocus() +void Widget::setFocus(bool focused) { + if (!focused) + return; + Frame* frame = Frame::frameForWidget(this); if (!frame) return; diff --git a/WebCore/platform/network/FormData.cpp b/WebCore/platform/network/FormData.cpp index 4ad82fb..918002a 100644 --- a/WebCore/platform/network/FormData.cpp +++ b/WebCore/platform/network/FormData.cpp @@ -286,13 +286,18 @@ String FormData::flattenToString() const return Latin1Encoding().decode(bytes.data(), bytes.size()); } -void FormData::generateFiles(ChromeClient* client) +void FormData::generateFiles(Document* document) { ASSERT(!m_hasGeneratedFiles); if (m_hasGeneratedFiles) return; + Page* page = document->page(); + if (!page) + return; + ChromeClient* client = page->chrome()->client(); + size_t n = m_elements.size(); for (size_t i = 0; i < n; ++i) { FormDataElement& e = m_elements[i]; diff --git a/WebCore/platform/network/FormData.h b/WebCore/platform/network/FormData.h index f89dad7..a439023 100644 --- a/WebCore/platform/network/FormData.h +++ b/WebCore/platform/network/FormData.h @@ -26,7 +26,6 @@ namespace WebCore { -class ChromeClient; class DOMFormData; class Document; @@ -101,7 +100,7 @@ public: const Vector<FormDataElement>& elements() const { return m_elements; } const Vector<char>& boundary() const { return m_boundary; } - void generateFiles(ChromeClient*); + void generateFiles(Document*); void removeGeneratedFilesIfNeeded(); bool alwaysStream() const { return m_alwaysStream; } diff --git a/WebCore/platform/network/FormDataBuilder.cpp b/WebCore/platform/network/FormDataBuilder.cpp index 436dc8b..13a457b 100644 --- a/WebCore/platform/network/FormDataBuilder.cpp +++ b/WebCore/platform/network/FormDataBuilder.cpp @@ -162,7 +162,7 @@ Vector<char> FormDataBuilder::generateUniqueBoundaryString() Vector<char> randomBytes; for (unsigned i = 0; i < 4; ++i) { - unsigned randomness = static_cast<unsigned>(WTF::randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)); + unsigned randomness = static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)); randomBytes.append(alphaNumericEncodingMap[(randomness >> 24) & 0x3F]); randomBytes.append(alphaNumericEncodingMap[(randomness >> 16) & 0x3F]); randomBytes.append(alphaNumericEncodingMap[(randomness >> 8) & 0x3F]); diff --git a/WebCore/platform/network/NetworkStateNotifier.h b/WebCore/platform/network/NetworkStateNotifier.h index 7b94ac8..ade27fd 100644 --- a/WebCore/platform/network/NetworkStateNotifier.h +++ b/WebCore/platform/network/NetworkStateNotifier.h @@ -48,6 +48,15 @@ typedef const struct __SCDynamicStore * SCDynamicStoreRef; #include <windows.h> +#elif PLATFORM(QT) + +#include <QtCore/qglobal.h> + +#ifdef QT_NO_BEARERMANAGEMENT +#undef ENABLE_QT_BEARER +#define ENABLE_QT_BEARER 0 +#endif + #endif namespace WebCore { diff --git a/WebCore/platform/network/ProtectionSpace.h b/WebCore/platform/network/ProtectionSpace.h index 42cbc8a..deb59d2 100644 --- a/WebCore/platform/network/ProtectionSpace.h +++ b/WebCore/platform/network/ProtectionSpace.h @@ -30,26 +30,28 @@ namespace WebCore { enum ProtectionSpaceServerType { - ProtectionSpaceServerHTTP = 1, - ProtectionSpaceServerHTTPS = 2, - ProtectionSpaceServerFTP = 3, - ProtectionSpaceServerFTPS = 4, - ProtectionSpaceProxyHTTP = 5, - ProtectionSpaceProxyHTTPS = 6, - ProtectionSpaceProxyFTP = 7, - ProtectionSpaceProxySOCKS = 8 + ProtectionSpaceServerHTTP = 1, + ProtectionSpaceServerHTTPS = 2, + ProtectionSpaceServerFTP = 3, + ProtectionSpaceServerFTPS = 4, + ProtectionSpaceProxyHTTP = 5, + ProtectionSpaceProxyHTTPS = 6, + ProtectionSpaceProxyFTP = 7, + ProtectionSpaceProxySOCKS = 8 }; enum ProtectionSpaceAuthenticationScheme { - ProtectionSpaceAuthenticationSchemeDefault = 1, - ProtectionSpaceAuthenticationSchemeHTTPBasic = 2, - ProtectionSpaceAuthenticationSchemeHTTPDigest = 3, - ProtectionSpaceAuthenticationSchemeHTMLForm = 4, - ProtectionSpaceAuthenticationSchemeNTLM = 5, - ProtectionSpaceAuthenticationSchemeNegotiate = 6, - ProtectionSpaceAuthenticationSchemeUnknown = 100, + ProtectionSpaceAuthenticationSchemeDefault = 1, + ProtectionSpaceAuthenticationSchemeHTTPBasic = 2, + ProtectionSpaceAuthenticationSchemeHTTPDigest = 3, + ProtectionSpaceAuthenticationSchemeHTMLForm = 4, + ProtectionSpaceAuthenticationSchemeNTLM = 5, + ProtectionSpaceAuthenticationSchemeNegotiate = 6, + ProtectionSpaceAuthenticationSchemeClientCertificateRequested = 7, + ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested = 8, + ProtectionSpaceAuthenticationSchemeUnknown = 100, }; - + class ProtectionSpace { public: diff --git a/WebCore/platform/network/ResourceHandle.h b/WebCore/platform/network/ResourceHandle.h index 24decd5..b86c922 100644 --- a/WebCore/platform/network/ResourceHandle.h +++ b/WebCore/platform/network/ResourceHandle.h @@ -82,6 +82,7 @@ class Credential; class FormData; class Frame; class KURL; +class ProtectionSpace; class ResourceError; class ResourceHandleClient; class ResourceHandleInternal; @@ -131,6 +132,9 @@ public: #if PLATFORM(MAC) void didCancelAuthenticationChallenge(const AuthenticationChallenge&); +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + bool canAuthenticateAgainstProtectionSpace(const ProtectionSpace&); +#endif NSURLConnection *connection() const; WebCoreResourceHandleAsDelegate *delegate(); void releaseDelegate(); diff --git a/WebCore/platform/network/ResourceHandleClient.h b/WebCore/platform/network/ResourceHandleClient.h index 0fe77a1..bbc3cf8 100644 --- a/WebCore/platform/network/ResourceHandleClient.h +++ b/WebCore/platform/network/ResourceHandleClient.h @@ -47,6 +47,7 @@ namespace WebCore { class AuthenticationChallenge; class Credential; class KURL; + class ProtectionSpace; class ResourceHandle; class ResourceError; class ResourceRequest; @@ -78,6 +79,9 @@ namespace WebCore { virtual bool shouldUseCredentialStorage(ResourceHandle*) { return false; } virtual void didReceiveAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge&) { } virtual void didCancelAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge&) { } +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + virtual bool canAuthenticateAgainstProtectionSpace(ResourceHandle*, const ProtectionSpace&) { return false; } +#endif virtual void receivedCancellation(ResourceHandle*, const AuthenticationChallenge&) { } #if PLATFORM(MAC) diff --git a/WebCore/platform/network/ResourceRequestBase.cpp b/WebCore/platform/network/ResourceRequestBase.cpp index 42c1c6e..fd8832f 100644 --- a/WebCore/platform/network/ResourceRequestBase.cpp +++ b/WebCore/platform/network/ResourceRequestBase.cpp @@ -45,6 +45,7 @@ PassOwnPtr<ResourceRequest> ResourceRequestBase::adopt(PassOwnPtr<CrossThreadRes request->setTimeoutInterval(data->m_timeoutInterval); request->setFirstPartyForCookies(data->m_firstPartyForCookies); request->setHTTPMethod(data->m_httpMethod); + request->setTargetType(data->m_targetType); request->updateResourceRequest(); request->m_httpHeaderFields.adopt(data->m_httpHeaders.release()); @@ -76,6 +77,7 @@ PassOwnPtr<CrossThreadResourceRequestData> ResourceRequestBase::copyData() const data->m_firstPartyForCookies = firstPartyForCookies().copy(); data->m_httpMethod = httpMethod().crossThreadString(); data->m_httpHeaders = httpHeaderFields().copyData(); + data->m_targetType = m_targetType; data->m_responseContentDispositionEncodingFallbackArray.reserveInitialCapacity(m_responseContentDispositionEncodingFallbackArray.size()); size_t encodingArraySize = m_responseContentDispositionEncodingFallbackArray.size(); diff --git a/WebCore/platform/network/ResourceRequestBase.h b/WebCore/platform/network/ResourceRequestBase.h index 2ca5d7d..0b634cb 100644 --- a/WebCore/platform/network/ResourceRequestBase.h +++ b/WebCore/platform/network/ResourceRequestBase.h @@ -61,7 +61,9 @@ namespace WebCore { TargetIsFontResource, TargetIsImage, TargetIsObject, - TargetIsMedia + TargetIsMedia, + TargetIsWorker, + TargetIsSharedWorker }; static PassOwnPtr<ResourceRequest> adopt(PassOwnPtr<CrossThreadResourceRequestData>); @@ -195,6 +197,7 @@ namespace WebCore { Vector<String> m_responseContentDispositionEncodingFallbackArray; RefPtr<FormData> m_httpBody; bool m_allowCookies; + ResourceRequestBase::TargetType m_targetType; }; unsigned initializeMaximumHTTPConnectionCountPerHost(); diff --git a/WebCore/platform/network/mac/AuthenticationMac.mm b/WebCore/platform/network/mac/AuthenticationMac.mm index 077a53d..1c05917 100644 --- a/WebCore/platform/network/mac/AuthenticationMac.mm +++ b/WebCore/platform/network/mac/AuthenticationMac.mm @@ -197,6 +197,14 @@ NSURLProtectionSpace *mac(const ProtectionSpace& coreSpace) case ProtectionSpaceAuthenticationSchemeNTLM: method = NSURLAuthenticationMethodNTLM; break; +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + case ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested: + method = NSURLAuthenticationMethodServerTrust; + break; + case ProtectionSpaceAuthenticationSchemeClientCertificateRequested: + method = NSURLAuthenticationMethodClientCertificate; + break; +#endif default: ASSERT_NOT_REACHED(); } @@ -295,6 +303,12 @@ ProtectionSpace core(NSURLProtectionSpace *macSpace) scheme = ProtectionSpaceAuthenticationSchemeHTMLForm; else if ([method isEqualToString:NSURLAuthenticationMethodNTLM]) scheme = ProtectionSpaceAuthenticationSchemeNTLM; +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + else if ([method isEqualToString:NSURLAuthenticationMethodClientCertificate]) + scheme = ProtectionSpaceAuthenticationSchemeClientCertificateRequested; + else if ([method isEqualToString:NSURLAuthenticationMethodServerTrust]) + scheme = ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested; +#endif else { scheme = ProtectionSpaceAuthenticationSchemeUnknown; ASSERT_NOT_REACHED(); diff --git a/WebCore/platform/network/mac/ResourceHandleMac.mm b/WebCore/platform/network/mac/ResourceHandleMac.mm index 3ea29c5..a70da68 100644 --- a/WebCore/platform/network/mac/ResourceHandleMac.mm +++ b/WebCore/platform/network/mac/ResourceHandleMac.mm @@ -567,11 +567,26 @@ void ResourceHandle::didCancelAuthenticationChallenge(const AuthenticationChalle client()->didCancelAuthenticationChallenge(this, challenge); } +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) +bool ResourceHandle::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace) +{ + if (client()) + return client()->canAuthenticateAgainstProtectionSpace(this, protectionSpace); + + return false; +} +#endif + void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge, const Credential& credential) { ASSERT(!challenge.isNull()); if (challenge != d->m_currentWebChallenge) return; + + if (credential.isEmpty()) { + receivedRequestToContinueWithoutCredential(challenge); + return; + } #ifdef BUILDING_ON_TIGER if (credential.persistence() == CredentialPersistenceNone) { @@ -734,6 +749,19 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen m_handle->didCancelAuthenticationChallenge(core(challenge)); } +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) +- (BOOL)connection:(NSURLConnection *)unusedConnection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace +{ + UNUSED_PARAM(unusedConnection); + + if (!m_handle) + return NO; + + CallbackGuard guard; + return m_handle->canAuthenticateAgainstProtectionSpace(core(protectionSpace)); +} +#endif + - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)r { UNUSED_PARAM(connection); @@ -744,7 +772,10 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen return; CallbackGuard guard; - [r adjustMIMETypeIfNecessary]; + // Avoid MIME type sniffing if the response comes back as 304 Not Modified. + int statusCode = [r respondsToSelector:@selector(statusCode)] ? [(id)r statusCode] : 0; + if (statusCode != 304) + [r adjustMIMETypeIfNecessary]; if ([m_handle->request().nsURLRequest() _propertyForKey:@"ForceHTMLMIMEType"]) [r _setMIMEType:@"text/html"]; diff --git a/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp b/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp index 52512aa..3aae92a 100644 --- a/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp +++ b/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp @@ -20,6 +20,8 @@ #include "config.h" #include "NetworkStateNotifier.h" +#if PLATFORM(QT) && ENABLE(QT_BEARER) + #include "NetworkStateNotifierPrivate.h" #include "qnetworkconfigmanager.h" @@ -89,4 +91,6 @@ void NetworkStateNotifier::setNetworkAccessAllowed(bool isAllowed) } // namespace WebCore +#endif + #include "moc_NetworkStateNotifierPrivate.cpp" diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp index 27b57b7..e52dd1d 100644 --- a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp +++ b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp @@ -41,8 +41,9 @@ // What type of connection should be used for the signals of the // QNetworkReply? This depends on if Qt has a bugfix for this or not. -// It is fixed in Qt 4.6.1. See https://bugs.webkit.org/show_bug.cgi?id=32113 -#if QT_VERSION > QT_VERSION_CHECK(4, 6, 0) +// It is fixed in Qt 4.6.3. See https://bugs.webkit.org/show_bug.cgi?id=32113 +// and https://bugs.webkit.org/show_bug.cgi?id=36755 +#if QT_VERSION > QT_VERSION_CHECK(4, 6, 2) #define SIGNAL_CONN Qt::DirectConnection #else #define SIGNAL_CONN Qt::QueuedConnection diff --git a/WebCore/platform/network/qt/ResourceRequestQt.cpp b/WebCore/platform/network/qt/ResourceRequestQt.cpp index 341e6ae..fea64a0 100644 --- a/WebCore/platform/network/qt/ResourceRequestQt.cpp +++ b/WebCore/platform/network/qt/ResourceRequestQt.cpp @@ -32,12 +32,14 @@ namespace WebCore { // To achieve the best result we want WebKit to schedule the jobs so we // are using the limit as found in Qt. To allow Qt to fill its queue // and prepare jobs we will schedule two more downloads. +// Per TCP connection there is 1 current processed, 3 possibly pipelined +// and 2 ready to re-fill the pipeline. unsigned initializeMaximumHTTPConnectionCountPerHost() { #ifdef Q_OS_SYMBIAN - return 3 + 2; + return 3 * (1 + 3 + 2); #else - return 6 + 2; + return 6 * (1 + 3 + 2); #endif } diff --git a/WebCore/platform/posix/FileSystemPOSIX.cpp b/WebCore/platform/posix/FileSystemPOSIX.cpp index ac8c7fa..ba17d39 100644 --- a/WebCore/platform/posix/FileSystemPOSIX.cpp +++ b/WebCore/platform/posix/FileSystemPOSIX.cpp @@ -116,6 +116,7 @@ bool truncateFile(PlatformFileHandle handle, long long offset) return !ftruncate(handle, offset); } +#if !PLATFORM(ANDROID) int writeToFile(PlatformFileHandle handle, const char* data, int length) { do { @@ -125,6 +126,7 @@ int writeToFile(PlatformFileHandle handle, const char* data, int length) } while (errno == EINTR); return -1; } +#endif int readFromFile(PlatformFileHandle handle, char* data, int length) { diff --git a/WebCore/platform/qt/PasteboardQt.cpp b/WebCore/platform/qt/PasteboardQt.cpp index 70ec546..484fa60 100644 --- a/WebCore/platform/qt/PasteboardQt.cpp +++ b/WebCore/platform/qt/PasteboardQt.cpp @@ -58,7 +58,7 @@ Pasteboard* Pasteboard::generalPasteboard() return pasteboard; } -void Pasteboard::writeSelection(Range* selectedRange, bool, Frame* frame) +void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame) { QMimeData* md = new QMimeData; QString text = frame->selectedText(); @@ -74,10 +74,14 @@ void Pasteboard::writeSelection(Range* selectedRange, bool, Frame* frame) QApplication::clipboard()->setMimeData(md, m_selectionMode ? QClipboard::Selection : QClipboard::Clipboard); #endif + if (canSmartCopyOrDelete) + md->setData("application/vnd.qtwebkit.smartpaste", QByteArray()); } bool Pasteboard::canSmartReplace() { + if (QApplication::clipboard()->mimeData()->hasFormat((QLatin1String("application/vnd.qtwebkit.smartpaste")))) + return true; return false; } diff --git a/WebCore/platform/qt/QWebPageClient.h b/WebCore/platform/qt/QWebPageClient.h index 467941f..a9a81eb 100644 --- a/WebCore/platform/qt/QWebPageClient.h +++ b/WebCore/platform/qt/QWebPageClient.h @@ -61,24 +61,23 @@ public: #if QT_VERSION >= 0x040600 virtual void setInputMethodHint(Qt::InputMethodHint hint, bool enable) = 0; #endif + +#ifndef QT_NO_CURSOR inline void resetCursor() { -#ifndef QT_NO_CURSOR if (!cursor().bitmap() && cursor().shape() == m_lastCursor.shape()) return; updateCursor(m_lastCursor); -#endif } inline void setCursor(const QCursor& cursor) { -#ifndef QT_NO_CURSOR m_lastCursor = cursor; if (!cursor.bitmap() && cursor.shape() == this->cursor().shape()) return; updateCursor(cursor); -#endif } +#endif virtual QPalette palette() const = 0; virtual int screenNumber() const = 0; diff --git a/WebCore/platform/qt/RenderThemeQt.cpp b/WebCore/platform/qt/RenderThemeQt.cpp index 9cc32ad..ee66a35 100644 --- a/WebCore/platform/qt/RenderThemeQt.cpp +++ b/WebCore/platform/qt/RenderThemeQt.cpp @@ -42,7 +42,7 @@ #include "HTMLInputElement.h" #include "HTMLMediaElement.h" #include "HTMLNames.h" -#ifdef Q_WS_MAEMO_5 +#if USE(QT_MOBILE_THEME) #include "Maemo5Webstyle.h" #endif #include "NotImplemented.h" @@ -153,7 +153,7 @@ RenderThemeQt::RenderThemeQt(Page* page) m_buttonFontPixelSize = fontInfo.pixelSize(); #endif -#ifdef Q_WS_MAEMO_5 +#if USE(QT_MOBILE_THEME) m_fallbackStyle = new Maemo5WebStyle; #else m_fallbackStyle = QStyleFactory::create(QLatin1String("windows")); @@ -163,10 +163,12 @@ RenderThemeQt::RenderThemeQt(Page* page) RenderThemeQt::~RenderThemeQt() { delete m_fallbackStyle; +#ifndef QT_NO_LINEEDIT delete m_lineEdit; +#endif } -#ifdef Q_WS_MAEMO_5 +#if USE(QT_MOBILE_THEME) bool RenderThemeQt::isControlStyled(const RenderStyle* style, const BorderData& border, const FillLayer& fill, const Color& backgroundColor) const { switch (style->appearance()) { @@ -198,7 +200,7 @@ QStyle* RenderThemeQt::fallbackStyle() const QStyle* RenderThemeQt::qStyle() const { -#ifdef Q_WS_MAEMO_5 +#if USE(QT_MOBILE_THEME) return fallbackStyle(); #endif @@ -218,7 +220,7 @@ String RenderThemeQt::extraDefaultStyleSheet() #if ENABLE(NO_LISTBOX_RENDERING) result += String(themeQtNoListboxesUserAgentStyleSheet, sizeof(themeQtNoListboxesUserAgentStyleSheet)); #endif -#ifdef Q_WS_MAEMO_5 +#if USE(QT_MOBILE_THEME) result += String(themeQtMaemo5UserAgentStyleSheet, sizeof(themeQtMaemo5UserAgentStyleSheet)); #endif return result; @@ -264,11 +266,17 @@ bool RenderThemeQt::supportsControlTints() const int RenderThemeQt::findFrameLineWidth(QStyle* style) const { +#ifndef QT_NO_LINEEDIT if (!m_lineEdit) m_lineEdit = new QLineEdit(); +#endif QStyleOptionFrameV2 opt; - return style->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, m_lineEdit); + QWidget* widget = 0; +#ifndef QT_NO_LINEEDIT + widget = m_lineEdit; +#endif + return style->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, widget); } static QRect inflateButtonRect(const QRect& originalRect, QStyle* style) @@ -648,7 +656,9 @@ bool RenderThemeQt::paintMenuList(RenderObject* o, const RenderObject::PaintInfo void RenderThemeQt::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const { -#ifndef Q_WS_MAEMO_5 +#if USE(QT_MOBILE_THEME) + // Mobile theme uses border radius. +#else // WORKAROUND because html.css specifies -webkit-border-radius for <select> so we override it here // see also http://bugs.webkit.org/show_bug.cgi?id=18399 style->resetBorderRadius(); @@ -898,7 +908,7 @@ bool RenderThemeQt::supportsFocus(ControlPart appearance) const void RenderThemeQt::setPaletteFromPageClientIfExists(QPalette& palette) const { -#ifdef Q_WS_MAEMO_5 +#if USE(QT_MOBILE_THEME) static QPalette lightGrayPalette(Qt::lightGray); palette = lightGrayPalette; return; @@ -960,7 +970,7 @@ ControlPart RenderThemeQt::initializeCommonQStyleOptions(QStyleOption& option, R case SearchFieldCancelButtonPart: { if (isPressed(o)) option.state |= QStyle::State_Sunken; - else if (result == PushButtonPart) + else if (result == PushButtonPart || result == ButtonPart) option.state |= QStyle::State_Raised; break; } diff --git a/WebCore/platform/qt/RenderThemeQt.h b/WebCore/platform/qt/RenderThemeQt.h index c10659a..fdd8d6b 100644 --- a/WebCore/platform/qt/RenderThemeQt.h +++ b/WebCore/platform/qt/RenderThemeQt.h @@ -78,7 +78,7 @@ public: virtual double caretBlinkInterval() const; -#ifdef Q_WS_MAEMO_5 +#if USE(QT_MOBILE_THEME) virtual bool isControlStyled(const RenderStyle*, const BorderData&, const FillLayer&, const Color& backgroundColor) const; virtual int popupInternalPaddingBottom(RenderStyle*) const; #endif diff --git a/WebCore/platform/qt/TemporaryLinkStubs.cpp b/WebCore/platform/qt/TemporaryLinkStubsQt.cpp index 432bd2b..432bd2b 100644 --- a/WebCore/platform/qt/TemporaryLinkStubs.cpp +++ b/WebCore/platform/qt/TemporaryLinkStubsQt.cpp diff --git a/WebCore/platform/qt/WidgetQt.cpp b/WebCore/platform/qt/WidgetQt.cpp index 252bdb4..43252a8 100644 --- a/WebCore/platform/qt/WidgetQt.cpp +++ b/WebCore/platform/qt/WidgetQt.cpp @@ -75,7 +75,7 @@ void Widget::setFrameRect(const IntRect& rect) frameRectsChanged(); } -void Widget::setFocus() +void Widget::setFocus(bool focused) { } diff --git a/WebCore/platform/sql/SQLiteDatabase.cpp b/WebCore/platform/sql/SQLiteDatabase.cpp index 58fdc7c..75fc032 100644 --- a/WebCore/platform/sql/SQLiteDatabase.cpp +++ b/WebCore/platform/sql/SQLiteDatabase.cpp @@ -102,14 +102,17 @@ void SQLiteDatabase::setFullsync(bool fsync) int64_t SQLiteDatabase::maximumSize() { - MutexLocker locker(m_authorizerLock); - enableAuthorizer(false); - - SQLiteStatement statement(*this, "PRAGMA max_page_count"); - int64_t size = statement.getColumnInt64(0) * pageSize(); - - enableAuthorizer(true); - return size; + int64_t maxPageCount = 0; + + { + MutexLocker locker(m_authorizerLock); + enableAuthorizer(false); + SQLiteStatement statement(*this, "PRAGMA max_page_count"); + maxPageCount = statement.getColumnInt64(0); + enableAuthorizer(true); + } + + return maxPageCount * pageSize(); } void SQLiteDatabase::setMaximumSize(int64_t size) @@ -128,7 +131,7 @@ void SQLiteDatabase::setMaximumSize(int64_t size) SQLiteStatement statement(*this, "PRAGMA max_page_count = " + String::number(newMaxPageCount)); statement.prepare(); if (statement.step() != SQLResultRow) - LOG_ERROR("Failed to set maximum size of database to %lli bytes", size); + LOG_ERROR("Failed to set maximum size of database to %lli bytes", static_cast<long long>(size)); enableAuthorizer(true); @@ -153,14 +156,33 @@ int SQLiteDatabase::pageSize() int64_t SQLiteDatabase::freeSpaceSize() { - MutexLocker locker(m_authorizerLock); - enableAuthorizer(false); - // Note: freelist_count was added in SQLite 3.4.1. - SQLiteStatement statement(*this, "PRAGMA freelist_count"); - int64_t size = statement.getColumnInt64(0) * pageSize(); + int64_t freelistCount = 0; - enableAuthorizer(true); - return size; + { + MutexLocker locker(m_authorizerLock); + enableAuthorizer(false); + // Note: freelist_count was added in SQLite 3.4.1. + SQLiteStatement statement(*this, "PRAGMA freelist_count"); + freelistCount = statement.getColumnInt64(0); + enableAuthorizer(true); + } + + return freelistCount * pageSize(); +} + +int64_t SQLiteDatabase::totalSize() +{ + int64_t pageCount = 0; + + { + MutexLocker locker(m_authorizerLock); + enableAuthorizer(false); + SQLiteStatement statement(*this, "PRAGMA page_count"); + pageCount = statement.getColumnInt64(0); + enableAuthorizer(true); + } + + return pageCount * pageSize(); } void SQLiteDatabase::setSynchronous(SynchronousPragma sync) @@ -229,6 +251,17 @@ void SQLiteDatabase::runVacuumCommand() LOG(SQLDatabase, "Unable to vacuum database - %s", lastErrorMsg()); } +void SQLiteDatabase::runIncrementalVacuumCommand() +{ + MutexLocker locker(m_authorizerLock); + enableAuthorizer(false); + + if (!executeCommand("PRAGMA incremental_vacuum")) + LOG(SQLDatabase, "Unable to run incremental vacuum - %s", lastErrorMsg()); + + enableAuthorizer(true); +} + int64_t SQLiteDatabase::lastInsertRowID() { if (!m_db) @@ -379,4 +412,34 @@ bool SQLiteDatabase::isAutoCommitOn() const return sqlite3_get_autocommit(m_db); } +bool SQLiteDatabase::turnOnIncrementalAutoVacuum() +{ + SQLiteStatement statement(*this, "PRAGMA auto_vacuum"); + int autoVacuumMode = statement.getColumnInt(0); + int error = lastError(); + + // Check if we got an error while trying to get the value of the auto_vacuum flag. + // If we got a SQLITE_BUSY error, then there's probably another transaction in + // progress on this database. In this case, keep the current value of the + // auto_vacuum flag and try to set it to INCREMENTAL the next time we open this + // database. If the error is not SQLITE_BUSY, then we probably ran into a more + // serious problem and should return false (to log an error message). + if (error != SQLITE_ROW) + return false; + + switch (autoVacuumMode) { + case AutoVacuumIncremental: + return true; + case AutoVacuumFull: + return executeCommand("PRAGMA auto_vacuum = 2"); + case AutoVacuumNone: + default: + if (!executeCommand("PRAGMA auto_vacuum = 2")) + return false; + runVacuumCommand(); + error = lastError(); + return (error == SQLITE_OK); + } +} + } // namespace WebCore diff --git a/WebCore/platform/sql/SQLiteDatabase.h b/WebCore/platform/sql/SQLiteDatabase.h index bc58a32..c5924c0 100644 --- a/WebCore/platform/sql/SQLiteDatabase.h +++ b/WebCore/platform/sql/SQLiteDatabase.h @@ -65,6 +65,7 @@ public: bool tableExists(const String&); void clearAllTables(); void runVacuumCommand(); + void runIncrementalVacuumCommand(); bool transactionInProgress() const { return m_transactionInProgress; } @@ -85,6 +86,7 @@ public: // Gets the number of unused bytes in the database file. int64_t freeSpaceSize(); + int64_t totalSize(); // The SQLite SYNCHRONOUS pragma can be either FULL, NORMAL, or OFF // FULL - Any writing calls to the DB block until the data is actually on the disk surface @@ -108,6 +110,18 @@ public: void unlock(); bool isAutoCommitOn() const; + // The SQLite AUTO_VACUUM pragma can be either NONE, FULL, or INCREMENTAL. + // NONE - SQLite does not do any vacuuming + // FULL - SQLite moves all empty pages to the end of the DB file and truncates + // the file to remove those pages after every transaction. This option + // requires SQLite to store additional information about each page in + // the database file. + // INCREMENTAL - SQLite stores extra information for each page in the database + // file, but removes the empty pages only when PRAGMA INCREMANTAL_VACUUM + // is called. + enum AutoVacuumPragma { AutoVacuumNone = 0, AutoVacuumFull = 1, AutoVacuumIncremental = 2 }; + bool turnOnIncrementalAutoVacuum(); + // Set this flag to allow access from multiple threads. Not all multi-threaded accesses are safe! // See http://www.sqlite.org/cvstrac/wiki?p=MultiThreading for more info. #ifndef NDEBUG diff --git a/WebCore/platform/sql/SQLiteStatement.cpp b/WebCore/platform/sql/SQLiteStatement.cpp index 8963adb..cd2a467 100644 --- a/WebCore/platform/sql/SQLiteStatement.cpp +++ b/WebCore/platform/sql/SQLiteStatement.cpp @@ -65,6 +65,15 @@ int SQLiteStatement::prepare() LOG(SQLDatabase, "SQL - prepare - %s", m_query.ascii().data()); String strippedQuery = m_query.stripWhiteSpace(); int error = sqlite3_prepare16_v2(m_database.sqlite3Handle(), strippedQuery.charactersWithNullTermination(), -1, &m_statement, &tail); + + // Starting with version 3.6.16, sqlite has a patch (http://www.sqlite.org/src/ci/256ec3c6af) + // that should make sure sqlite3_prepare16_v2 doesn't return a SQLITE_SCHEMA error. + // If we're using an older sqlite version, try to emulate the patch. + if (error == SQLITE_SCHEMA) { + sqlite3_finalize(m_statement); + error = sqlite3_prepare16_v2(m_database.sqlite3Handle(), m_query.charactersWithNullTermination(), -1, &m_statement, &tail); + } + if (error != SQLITE_OK) LOG(SQLDatabase, "sqlite3_prepare16 failed (%i)\n%s\n%s", error, m_query.ascii().data(), sqlite3_errmsg(m_database.sqlite3Handle())); const UChar* ch = static_cast<const UChar*>(tail); @@ -87,6 +96,7 @@ int SQLiteStatement::step() LOG(SQLDatabase, "sqlite3_step failed (%i)\nQuery - %s\nError - %s", error, m_query.ascii().data(), sqlite3_errmsg(m_database.sqlite3Handle())); } + return error; } diff --git a/WebCore/platform/text/CharacterNames.h b/WebCore/platform/text/CharacterNames.h index c0b1750..fbb9466 100644 --- a/WebCore/platform/text/CharacterNames.h +++ b/WebCore/platform/text/CharacterNames.h @@ -30,40 +30,42 @@ namespace WebCore { - // Names here are taken from the Unicode standard. +// Names here are taken from the Unicode standard. - // Note, these are UChar constants, not UChar32, which makes them - // more convenient for WebCore code that mostly uses UTF-16. +// Note, these are UChar constants, not UChar32, which makes them +// more convenient for WebCore code that mostly uses UTF-16. - const UChar blackSquare = 0x25A0; - const UChar bullet = 0x2022; - const UChar ethiopicPrefaceColon = 0x1366; - const UChar hebrewPunctuationGeresh = 0x05F3; - const UChar hebrewPunctuationGershayim = 0x05F4; - const UChar horizontalEllipsis = 0x2026; - const UChar hyphenMinus = 0x002D; - const UChar ideographicComma = 0x3001; - const UChar ideographicFullStop = 0x3002; - const UChar ideographicSpace = 0x3000; - const UChar leftDoubleQuotationMark = 0x201C; - const UChar leftSingleQuotationMark = 0x2018; - const UChar leftToRightEmbed = 0x202A; - const UChar leftToRightMark = 0x200E; - const UChar leftToRightOverride = 0x202D; - const UChar newlineCharacter = 0x000A; - const UChar noBreakSpace = 0x00A0; - const UChar objectReplacementCharacter = 0xFFFC; - const UChar popDirectionalFormatting = 0x202C; - const UChar replacementCharacter = 0xFFFD; - const UChar rightDoubleQuotationMark = 0x201D; - const UChar rightSingleQuotationMark = 0x2019; - const UChar rightToLeftEmbed = 0x202B; - const UChar rightToLeftMark = 0x200F; - const UChar rightToLeftOverride = 0x202E; - const UChar softHyphen = 0x00AD; - const UChar space = 0x0020; - const UChar whiteBullet = 0x25E6; - const UChar zeroWidthSpace = 0x200B; +const UChar blackSquare = 0x25A0; +const UChar bullet = 0x2022; +const UChar ethiopicPrefaceColon = 0x1366; +const UChar hebrewPunctuationGeresh = 0x05F3; +const UChar hebrewPunctuationGershayim = 0x05F4; +const UChar horizontalEllipsis = 0x2026; +const UChar hyphenMinus = 0x002D; +const UChar ideographicComma = 0x3001; +const UChar ideographicFullStop = 0x3002; +const UChar ideographicSpace = 0x3000; +const UChar leftDoubleQuotationMark = 0x201C; +const UChar leftSingleQuotationMark = 0x2018; +const UChar leftToRightEmbed = 0x202A; +const UChar leftToRightMark = 0x200E; +const UChar leftToRightOverride = 0x202D; +const UChar newlineCharacter = 0x000A; +const UChar noBreakSpace = 0x00A0; +const UChar objectReplacementCharacter = 0xFFFC; +const UChar popDirectionalFormatting = 0x202C; +const UChar replacementCharacter = 0xFFFD; +const UChar rightDoubleQuotationMark = 0x201D; +const UChar rightSingleQuotationMark = 0x2019; +const UChar rightToLeftEmbed = 0x202B; +const UChar rightToLeftMark = 0x200F; +const UChar rightToLeftOverride = 0x202E; +const UChar softHyphen = 0x00AD; +const UChar space = 0x0020; +const UChar whiteBullet = 0x25E6; +const UChar zeroWidthJoiner = 0x200D; +const UChar zeroWidthNonJoiner = 0x200C; +const UChar zeroWidthSpace = 0x200B; } diff --git a/WebCore/platform/text/TextEncodingRegistry.cpp b/WebCore/platform/text/TextEncodingRegistry.cpp index 00ad2c9..dad0f39 100644 --- a/WebCore/platform/text/TextEncodingRegistry.cpp +++ b/WebCore/platform/text/TextEncodingRegistry.cpp @@ -316,4 +316,19 @@ bool noExtendedTextEncodingNameUsed() return !didExtendTextCodecMaps; } +#ifndef NDEBUG +void dumpTextEncodingNameMap() +{ + unsigned size = textEncodingNameMap->size(); + fprintf(stderr, "Dumping %u entries in WebCore::textEncodingNameMap...\n", size); + + MutexLocker lock(encodingRegistryMutex()); + + TextEncodingNameMap::const_iterator it = textEncodingNameMap->begin(); + TextEncodingNameMap::const_iterator end = textEncodingNameMap->end(); + for (; it != end; ++it) + fprintf(stderr, "'%s' => '%s'\n", it->first, it->second); +} +#endif + } // namespace WebCore diff --git a/WebCore/platform/text/TextEncodingRegistry.h b/WebCore/platform/text/TextEncodingRegistry.h index e6950cf..81b7c4c 100644 --- a/WebCore/platform/text/TextEncodingRegistry.h +++ b/WebCore/platform/text/TextEncodingRegistry.h @@ -46,6 +46,9 @@ namespace WebCore { // Only TextEncoding should use this function directly. bool noExtendedTextEncodingNameUsed(); +#ifndef NDEBUG + void dumpTextEncodingNameMap(); +#endif } #endif // TextEncodingRegistry_h diff --git a/WebCore/platform/text/TextStream.cpp b/WebCore/platform/text/TextStream.cpp index 4386059..646de3f 100644 --- a/WebCore/platform/text/TextStream.cpp +++ b/WebCore/platform/text/TextStream.cpp @@ -108,7 +108,7 @@ String TextStream::release() return String::adopt(m_text); } -#if OS(WINDOWS) && PLATFORM(X86_64) && COMPILER(MSVC) +#if OS(WINDOWS) && CPU(X86_64) TextStream& TextStream::operator<<(__int64 i) { char buffer[printBufferSize]; diff --git a/WebCore/platform/text/TextStream.h b/WebCore/platform/text/TextStream.h index d69e34b..f5e512c 100644 --- a/WebCore/platform/text/TextStream.h +++ b/WebCore/platform/text/TextStream.h @@ -45,7 +45,7 @@ public: TextStream& operator<<(const char*); TextStream& operator<<(const void*); TextStream& operator<<(const String&); -#if OS(WINDOWS) && PLATFORM(X86_64) && COMPILER(MSVC) +#if OS(WINDOWS) && CPU(X86_64) TextStream& operator<<(unsigned __int64); TextStream& operator<<(__int64); #endif diff --git a/WebCore/platform/win/WidgetWin.cpp b/WebCore/platform/win/WidgetWin.cpp index 74a22f6..607c0d8 100644 --- a/WebCore/platform/win/WidgetWin.cpp +++ b/WebCore/platform/win/WidgetWin.cpp @@ -101,7 +101,7 @@ void Widget::paint(GraphicsContext*, const IntRect&) { } -void Widget::setFocus() +void Widget::setFocus(bool focused) { } diff --git a/WebCore/platform/wince/SharedTimerWince.cpp b/WebCore/platform/wince/SharedTimerWince.cpp index 5f6a386..2328017 100644 --- a/WebCore/platform/wince/SharedTimerWince.cpp +++ b/WebCore/platform/wince/SharedTimerWince.cpp @@ -36,7 +36,7 @@ #include <windows.h> namespace JSC { -extern void* g_stackBase; +JS_EXPORTDATA extern void* g_stackBase; } namespace WebCore { diff --git a/WebCore/platform/wx/WidgetWx.cpp b/WebCore/platform/wx/WidgetWx.cpp index a384914..9de4c3d 100644 --- a/WebCore/platform/wx/WidgetWx.cpp +++ b/WebCore/platform/wx/WidgetWx.cpp @@ -44,10 +44,12 @@ Widget::~Widget() { } -void Widget::setFocus() +void Widget::setFocus(bool focused) { - if (PlatformWidget widget = platformWidget()) - widget->SetFocus(); + if (focused) { + if (PlatformWidget widget = platformWidget()) + widget->SetFocus(); + } } void Widget::setCursor(const Cursor& cursor) diff --git a/WebCore/platform/wx/wxcode/fontprops.h b/WebCore/platform/wx/wxcode/fontprops.h index 3f99462..7702db2 100644 --- a/WebCore/platform/wx/wxcode/fontprops.h +++ b/WebCore/platform/wx/wxcode/fontprops.h @@ -48,4 +48,4 @@ private: }; -bool wxFontContainsCharacters(const wxFont& font, const UChar* characters, int length); +bool wxFontContainsCharacters(void* font, const UChar* characters, int length); diff --git a/WebCore/platform/wx/wxcode/mac/carbon/fontprops.mm b/WebCore/platform/wx/wxcode/mac/carbon/fontprops.mm index ff4c18a..9da47fd 100644 --- a/WebCore/platform/wx/wxcode/mac/carbon/fontprops.mm +++ b/WebCore/platform/wx/wxcode/mac/carbon/fontprops.mm @@ -28,6 +28,7 @@ #include <wtf/unicode/Unicode.h> #include "fontprops.h" +#include "WebCoreSystemInterface.h" #include <ApplicationServices/ApplicationServices.h> @@ -35,10 +36,6 @@ #include <wx/gdicmn.h> #include <wx/graphics.h> -#ifdef BUILDING_ON_TIGER -void (*wkGetFontMetrics)(CGFontRef, int* ascent, int* descent, int* lineGap, unsigned* unitsPerEm); -#endif - const float smallCapsFontSizeMultiplier = 0.7f; const float contextDPI = 72.0f; static inline float scaleEmToUnits(float x, unsigned unitsPerEm) { return x * (contextDPI / (contextDPI * unitsPerEm)); } @@ -92,23 +89,20 @@ m_ascent(0), m_descent(0), m_lineGap(0), m_lineSpacing(0), m_xHeight(0) } -bool wxFontContainsCharacters(const wxFont& font, const UChar* characters, int length) +bool wxFontContainsCharacters(void* font, const UChar* characters, int length) { -#if wxOSX_USE_COCOA NSString* string = [[NSString alloc] initWithCharactersNoCopy:const_cast<unichar*>(characters) length:length freeWhenDone:NO]; - NSCharacterSet* set = [[font.OSXGetNSFont() coveredCharacterSet] invertedSet]; + NSCharacterSet* set = [[(NSFont*)font coveredCharacterSet] invertedSet]; bool result = set && [string rangeOfCharacterFromSet:set].location == NSNotFound; [string release]; return result; -#else - return true; -#endif } void GetTextExtent( const wxFont& font, const wxString& str, wxCoord *width, wxCoord *height, wxCoord *descent, wxCoord *externalLeading ) { wxGraphicsContext * const gc = wxGraphicsContext::Create(); + gc->SetFont(font, *wxBLACK); // colour doesn't matter but must be specified struct GCTextExtent { diff --git a/WebCore/platform/wx/wxcode/mac/carbon/non-kerned-drawing.cpp b/WebCore/platform/wx/wxcode/mac/carbon/non-kerned-drawing.cpp index 47eb1f8..82259f4 100644 --- a/WebCore/platform/wx/wxcode/mac/carbon/non-kerned-drawing.cpp +++ b/WebCore/platform/wx/wxcode/mac/carbon/non-kerned-drawing.cpp @@ -39,14 +39,6 @@ #include <wx/dcgraph.h> #include <wx/gdicmn.h> - -// Unfortunately we need access to a private function to get the character -> glyph conversion needed to -// allow us to use CGContextShowGlyphsWithAdvances -// Note that on < 10.5, the function is called CGFontGetGlyphsForUnicodes, so we need to detect and deal -// with this. -typedef void (*CGFontGetGlyphsForUnicharsPtr)(CGFontRef, const UniChar[], const CGGlyph[], size_t); -static CGFontGetGlyphsForUnicharsPtr CGFontGetGlyphsForUnichars = (CGFontGetGlyphsForUnicharsPtr)dlsym(RTLD_DEFAULT, "CGFontGetGlyphsForUnichars"); - namespace WebCore { void drawTextWithSpacing(GraphicsContext* graphicsContext, const SimpleFontData* font, const wxColour& color, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) @@ -60,18 +52,7 @@ void drawTextWithSpacing(GraphicsContext* graphicsContext, const SimpleFontData* CGContextRef cgContext = static_cast<CGContextRef>(dc->GetGraphicsContext()->GetNativeContext()); - CGFontRef cgFont; - -#ifdef wxOSX_USE_CORE_TEXT && wxOSX_USE_CORE_TEXT - cgFont = CTFontCopyGraphicsFont((CTFontRef)wxfont->OSXGetCTFont(), NULL); -#else - ATSFontRef fontRef; - - fontRef = FMGetATSFontRefFromFont(wxfont->MacGetATSUFontID()); - - if (fontRef) - cgFont = CGFontCreateWithPlatformFont((void*)&fontRef); -#endif + CGFontRef cgFont = font->platformData().cgFont(); CGContextSetFont(cgContext, cgFont); @@ -89,26 +70,7 @@ void drawTextWithSpacing(GraphicsContext* graphicsContext, const SimpleFontData* CGContextSetTextPosition(cgContext, point.x(), point.y()); - const FloatSize* advanceSizes = static_cast<const FloatSize*>(glyphBuffer.advances(from)); - int size = glyphBuffer.size() - from; - CGSize sizes[size]; - CGGlyph glyphs[numGlyphs]; - - // if the function doesn't exist, we're probably on tiger and need to grab the - // function under its old name, CGFontGetGlyphsForUnicodes - if (!CGFontGetGlyphsForUnichars) - CGFontGetGlyphsForUnichars = (CGFontGetGlyphsForUnicharsPtr)dlsym(RTLD_DEFAULT, "CGFontGetGlyphsForUnicodes"); - - // Let's make sure we got the function under one name or another! - ASSERT(CGFontGetGlyphsForUnichars); - CGFontGetGlyphsForUnichars(cgFont, glyphBuffer.glyphs(from), glyphs, numGlyphs); - - for (int i = 0; i < size; i++) { - FloatSize fsize = advanceSizes[i]; - sizes[i] = CGSizeMake(fsize.width(), fsize.height()); - } - - CGContextShowGlyphsWithAdvances(cgContext, glyphs, sizes, numGlyphs); + CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); if (cgFont) CGFontRelease(cgFont); diff --git a/WebCore/platform/wx/wxcode/win/fontprops.cpp b/WebCore/platform/wx/wxcode/win/fontprops.cpp index d6ba964..f3e4fda 100644 --- a/WebCore/platform/wx/wxcode/win/fontprops.cpp +++ b/WebCore/platform/wx/wxcode/win/fontprops.cpp @@ -66,7 +66,7 @@ m_ascent(0), m_descent(0), m_lineGap(0), m_lineSpacing(0), m_xHeight(0) ReleaseDC(0, dc); } -bool wxFontContainsCharacters(const wxFont& font, const UChar* characters, int length) +bool wxFontContainsCharacters(void* font, const UChar* characters, int length) { // FIXME: Microsoft documentation seems to imply that characters can be output using a given font and DC // merely by testing code page intersection. This seems suspect though. Can't a font only partially @@ -89,7 +89,7 @@ bool wxFontContainsCharacters(const wxFont& font, const UChar* characters, int l langFontLink->CodePageToCodePages(CP_ACP, &acpCodePages); DWORD fontCodePages; - langFontLink->GetFontCodePages(dc, static_cast<HFONT>(font.GetHFONT()), &fontCodePages); + langFontLink->GetFontCodePages(dc, (HFONT)font, &fontCodePages); DWORD actualCodePages; long numCharactersProcessed; diff --git a/WebCore/plugins/PluginPackage.h b/WebCore/plugins/PluginPackage.h index aa2d272..4fc9341 100644 --- a/WebCore/plugins/PluginPackage.h +++ b/WebCore/plugins/PluginPackage.h @@ -55,7 +55,7 @@ namespace WebCore { const String& path() const { return m_path; } const String& fileName() const { return m_fileName; } const String& parentDirectory() const { return m_parentDirectory; } - uint16 NPVersion() const; + uint16_t NPVersion() const; time_t lastModified() const { return m_lastModified; } const MIMEToDescriptionsMap& mimeToDescriptions() const { return m_mimeToDescriptions; } diff --git a/WebCore/plugins/PluginStream.cpp b/WebCore/plugins/PluginStream.cpp index 9bd497a..bdf7a40 100644 --- a/WebCore/plugins/PluginStream.cpp +++ b/WebCore/plugins/PluginStream.cpp @@ -336,13 +336,13 @@ void PluginStream::deliverData() if (!m_stream.ndata || m_deliveryData->size() == 0) return; - int32 totalBytes = m_deliveryData->size(); - int32 totalBytesDelivered = 0; + int32_t totalBytes = m_deliveryData->size(); + int32_t totalBytesDelivered = 0; if (m_loader) m_loader->setDefersLoading(true); while (totalBytesDelivered < totalBytes) { - int32 deliveryBytes = m_pluginFuncs->writeready(m_instance, &m_stream); + int32_t deliveryBytes = m_pluginFuncs->writeready(m_instance, &m_stream); if (deliveryBytes <= 0) { #if PLATFORM(ANDROID) @@ -359,7 +359,7 @@ void PluginStream::deliverData() break; } else { deliveryBytes = min(deliveryBytes, totalBytes - totalBytesDelivered); - int32 dataLength = deliveryBytes; + int32_t dataLength = deliveryBytes; char* data = m_deliveryData->data() + totalBytesDelivered; // Write the data diff --git a/WebCore/plugins/PluginStream.h b/WebCore/plugins/PluginStream.h index c0487e3..b937ff0 100644 --- a/WebCore/plugins/PluginStream.h +++ b/WebCore/plugins/PluginStream.h @@ -111,8 +111,8 @@ namespace WebCore { const NPPluginFuncs* m_pluginFuncs; NPP m_instance; - uint16 m_transferMode; - int32 m_offset; + uint16_t m_transferMode; + int32_t m_offset; WTF::CString m_headers; WTF::CString m_path; NPReason m_reason; diff --git a/WebCore/plugins/PluginView.cpp b/WebCore/plugins/PluginView.cpp index 889afe0..b9eca2a 100644 --- a/WebCore/plugins/PluginView.cpp +++ b/WebCore/plugins/PluginView.cpp @@ -377,7 +377,7 @@ void PluginView::stop() WNDPROC currentWndProc = (WNDPROC)GetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC); if (currentWndProc == PluginViewWndProc) - SetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC, (LONG)m_pluginWndProc); + SetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC, (LONG_PTR)m_pluginWndProc); #endif } #endif // XP_WIN @@ -638,12 +638,12 @@ NPError PluginView::getURL(const char* url, const char* target) return load(frameLoadRequest, false, 0); } -NPError PluginView::postURLNotify(const char* url, const char* target, uint32 len, const char* buf, NPBool file, void* notifyData) +NPError PluginView::postURLNotify(const char* url, const char* target, uint32_t len, const char* buf, NPBool file, void* notifyData) { return handlePost(url, target, len, buf, file, notifyData, true, true); } -NPError PluginView::postURL(const char* url, const char* target, uint32 len, const char* buf, NPBool file) +NPError PluginView::postURL(const char* url, const char* target, uint32_t len, const char* buf, NPBool file) { // As documented, only allow headers to be specified via NPP_PostURL when using a file. return handlePost(url, target, len, buf, file, 0, false, file); @@ -656,7 +656,7 @@ NPError PluginView::newStream(NPMIMEType type, const char* target, NPStream** st return NPERR_GENERIC_ERROR; } -int32 PluginView::write(NPStream* stream, int32 len, void* buffer) +int32_t PluginView::write(NPStream* stream, int32_t len, void* buffer) { notImplemented(); // Unsupported @@ -1234,7 +1234,7 @@ static inline HTTPHeaderMap parseRFC822HeaderFields(const Vector<char>& buffer, return headerFields; } -NPError PluginView::handlePost(const char* url, const char* target, uint32 len, const char* buf, bool file, void* notifyData, bool sendNotification, bool allowHeaders) +NPError PluginView::handlePost(const char* url, const char* target, uint32_t len, const char* buf, bool file, void* notifyData, bool sendNotification, bool allowHeaders) { if (!url || !len || !buf) return NPERR_INVALID_PARAM; @@ -1409,7 +1409,6 @@ void PluginView::keepAlive(NPP instance) view->keepAlive(); } -#endif NPError PluginView::getValueStatic(NPNVariable variable, void* value) { @@ -1434,7 +1433,6 @@ NPError PluginView::getValue(NPNVariable variable, void* value) return result; switch (variable) { -#if ENABLE(NETSCAPE_PLUGIN_API) case NPNVWindowNPObject: { if (m_isJavaScriptPaused) return NPERR_GENERIC_ERROR; @@ -1469,7 +1467,6 @@ NPError PluginView::getValue(NPNVariable variable, void* value) return NPERR_NO_ERROR; } -#endif case NPNVprivateModeBool: { Page* page = m_parentFrame->page(); @@ -1483,6 +1480,7 @@ NPError PluginView::getValue(NPNVariable variable, void* value) return NPERR_GENERIC_ERROR; } } +#endif void PluginView::privateBrowsingStateChanged(bool privateBrowsingEnabled) { diff --git a/WebCore/plugins/PluginView.h b/WebCore/plugins/PluginView.h index d769581..6042b0f 100644 --- a/WebCore/plugins/PluginView.h +++ b/WebCore/plugins/PluginView.h @@ -149,18 +149,19 @@ namespace WebCore { // NPN functions NPError getURLNotify(const char* url, const char* target, void* notifyData); NPError getURL(const char* url, const char* target); - NPError postURLNotify(const char* url, const char* target, uint32 len, const char* but, NPBool file, void* notifyData); - NPError postURL(const char* url, const char* target, uint32 len, const char* but, NPBool file); + NPError postURLNotify(const char* url, const char* target, uint32_t len, const char* but, NPBool file, void* notifyData); + NPError postURL(const char* url, const char* target, uint32_t len, const char* but, NPBool file); NPError newStream(NPMIMEType type, const char* target, NPStream** stream); - int32 write(NPStream* stream, int32 len, void* buffer); + int32_t write(NPStream* stream, int32_t len, void* buffer); NPError destroyStream(NPStream* stream, NPReason reason); const char* userAgent(); #if ENABLE(NETSCAPE_PLUGIN_API) static const char* userAgentStatic(); #endif void status(const char* message); - NPError getValue(NPNVariable variable, void* value); + #if ENABLE(NETSCAPE_PLUGIN_API) + NPError getValue(NPNVariable variable, void* value); static NPError getValueStatic(NPNVariable variable, void* value); #endif NPError setValue(NPPVariable variable, void* value); @@ -189,7 +190,7 @@ namespace WebCore { // Widget functions virtual void setFrameRect(const IntRect&); virtual void frameRectsChanged(); - virtual void setFocus(); + virtual void setFocus(bool); virtual void show(); virtual void hide(); virtual void paint(GraphicsContext*, const IntRect&); @@ -260,8 +261,8 @@ namespace WebCore { void platformDestroy(); static void setCurrentPluginView(PluginView*); NPError load(const FrameLoadRequest&, bool sendNotification, void* notifyData); - NPError handlePost(const char* url, const char* target, uint32 len, const char* buf, bool file, void* notifyData, bool sendNotification, bool allowHeaders); - NPError handlePostReadFile(Vector<char>& buffer, uint32 len, const char* buf); + NPError handlePost(const char* url, const char* target, uint32_t len, const char* buf, bool file, void* notifyData, bool sendNotification, bool allowHeaders); + NPError handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf); static void freeStringArray(char** stringArray, int length); void setCallingPlugin(bool) const; diff --git a/WebCore/plugins/PluginViewNone.cpp b/WebCore/plugins/PluginViewNone.cpp index bb27357..d7b03ca 100644 --- a/WebCore/plugins/PluginViewNone.cpp +++ b/WebCore/plugins/PluginViewNone.cpp @@ -30,7 +30,7 @@ using namespace WTF; namespace WebCore { -void PluginView::setFocus() +void PluginView::setFocus(bool) { } @@ -62,17 +62,17 @@ void PluginView::setNPWindowRect(const IntRect&) { } -NPError PluginView::handlePostReadFile(Vector<char>&, uint32, const char*) +NPError PluginView::handlePostReadFile(Vector<char>&, uint32_t, const char*) { return 0; } +#if ENABLE(NETSCAPE_PLUGIN_API) bool PluginView::platformGetValue(NPNVariable, void*, NPError*) { return false; } -#if ENABLE(NETSCAPE_PLUGIN_API) bool PluginView::platformGetValueStatic(NPNVariable, void*, NPError*) { return false; @@ -126,6 +126,7 @@ void PluginView::keepAlive(NPP) } #endif +#if PLATFORM(MAC) || PLATFORM(CHROMIUM) || PLATFORM(EFL) void PluginView::privateBrowsingStateChanged(bool) { } @@ -133,6 +134,7 @@ void PluginView::privateBrowsingStateChanged(bool) void PluginView::setJavaScriptPaused(bool) { } +#endif #if defined(XP_UNIX) && ENABLE(NETSCAPE_PLUGIN_API) void PluginView::handleFocusInEvent() diff --git a/WebCore/plugins/gtk/PluginPackageGtk.cpp b/WebCore/plugins/gtk/PluginPackageGtk.cpp index d975666..97553a1 100644 --- a/WebCore/plugins/gtk/PluginPackageGtk.cpp +++ b/WebCore/plugins/gtk/PluginPackageGtk.cpp @@ -168,7 +168,7 @@ abort: return false; } -uint16 PluginPackage::NPVersion() const +uint16_t PluginPackage::NPVersion() const { return NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL; } diff --git a/WebCore/plugins/gtk/PluginViewGtk.cpp b/WebCore/plugins/gtk/PluginViewGtk.cpp index 8de63e0..400ba6f 100644 --- a/WebCore/plugins/gtk/PluginViewGtk.cpp +++ b/WebCore/plugins/gtk/PluginViewGtk.cpp @@ -148,10 +148,10 @@ void PluginView::updatePluginWidget() setNPWindowIfNeeded(); } -void PluginView::setFocus() +void PluginView::setFocus(bool focused) { ASSERT(platformPluginWidget() == platformWidget()); - Widget::setFocus(); + Widget::setFocus(focused); } void PluginView::show() @@ -558,7 +558,7 @@ void PluginView::setParentVisible(bool visible) } } -NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32 len, const char* buf) +NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf) { String filename(buf, len); @@ -592,9 +592,9 @@ bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPErr switch (variable) { case NPNVToolkit: #if defined(XP_UNIX) - *static_cast<uint32*>(value) = 2; + *static_cast<uint32_t*>(value) = 2; #else - *static_cast<uint32*>(value) = 0; + *static_cast<uint32_t*>(value) = 0; #endif *result = NPERR_NO_ERROR; return true; diff --git a/WebCore/plugins/mac/PluginPackageMac.cpp b/WebCore/plugins/mac/PluginPackageMac.cpp index 9a297de..865ea32 100644 --- a/WebCore/plugins/mac/PluginPackageMac.cpp +++ b/WebCore/plugins/mac/PluginPackageMac.cpp @@ -300,7 +300,7 @@ abort: return false; } -uint16 PluginPackage::NPVersion() const +uint16_t PluginPackage::NPVersion() const { return NP_VERSION_MINOR; } diff --git a/WebCore/plugins/mac/PluginViewMac.cpp b/WebCore/plugins/mac/PluginViewMac.cpp index 1fd4676..562e975 100644 --- a/WebCore/plugins/mac/PluginViewMac.cpp +++ b/WebCore/plugins/mac/PluginViewMac.cpp @@ -254,7 +254,7 @@ bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPErr { switch (variable) { case NPNVToolkit: - *static_cast<uint32*>(value) = 0; + *static_cast<uint32_t*>(value) = 0; *result = NPERR_NO_ERROR; return true; @@ -332,9 +332,13 @@ void PluginView::hide() Widget::hide(); } -void PluginView::setFocus() +void PluginView::setFocus(bool focused) { - LOG(Plugins, "PluginView::setFocus()"); + LOG(Plugins, "PluginView::setFocus(%d)", focused); + if (!focused) { + Widget::setFocus(focused); + return; + } if (platformPluginWidget()) #if PLATFORM(QT) @@ -343,7 +347,7 @@ void PluginView::setFocus() platformPluginWidget()->SetFocus(); #endif else - Widget::setFocus(); + Widget::setFocus(focused); // TODO: Also handle and pass on blur events (focus lost) @@ -356,7 +360,7 @@ void PluginView::setFocus() record.modifiers = GetCurrentKeyModifiers(); if (!dispatchNPEvent(record)) - LOG(Events, "PluginView::setFocus(): Get-focus event not accepted"); + LOG(Events, "PluginView::setFocus(%d): Focus event not accepted", focused); #endif } @@ -794,7 +798,7 @@ bool PluginView::dispatchNPEvent(NPEvent& event) // ------------------- Miscellaneous ------------------ -NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32 len, const char* buf) +NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf) { String filename(buf, len); diff --git a/WebCore/plugins/npapi.cpp b/WebCore/plugins/npapi.cpp index 05d7c06..d5ab757 100644 --- a/WebCore/plugins/npapi.cpp +++ b/WebCore/plugins/npapi.cpp @@ -43,7 +43,7 @@ static PluginView* pluginViewForInstance(NPP instance) return PluginView::currentPluginView(); } -void* NPN_MemAlloc(uint32 size) +void* NPN_MemAlloc(uint32_t size) { return malloc(size); } @@ -53,7 +53,7 @@ void NPN_MemFree(void* ptr) free(ptr); } -uint32 NPN_MemFlush(uint32 size) +uint32_t NPN_MemFlush(uint32_t size) { // Do nothing return 0; @@ -79,12 +79,12 @@ NPError NPN_GetURL(NPP instance, const char* url, const char* target) return pluginViewForInstance(instance)->getURL(url, target); } -NPError NPN_PostURLNotify(NPP instance, const char* url, const char* target, uint32 len, const char* buf, NPBool file, void* notifyData) +NPError NPN_PostURLNotify(NPP instance, const char* url, const char* target, uint32_t len, const char* buf, NPBool file, void* notifyData) { return pluginViewForInstance(instance)->postURLNotify(url, target, len, buf, file, notifyData); } -NPError NPN_PostURL(NPP instance, const char* url, const char* target, uint32 len, const char* buf, NPBool file) +NPError NPN_PostURL(NPP instance, const char* url, const char* target, uint32_t len, const char* buf, NPBool file) { return pluginViewForInstance(instance)->postURL(url, target, len, buf, file); } @@ -94,7 +94,7 @@ NPError NPN_NewStream(NPP instance, NPMIMEType type, const char* target, NPStrea return pluginViewForInstance(instance)->newStream(type, target, stream); } -int32 NPN_Write(NPP instance, NPStream* stream, int32 len, void* buffer) +int32_t NPN_Write(NPP instance, NPStream* stream, int32_t len, void* buffer) { return pluginViewForInstance(instance)->write(stream, len, buffer); } diff --git a/WebCore/plugins/npfunctions.h b/WebCore/plugins/npfunctions.h index 8bf5acb..675ccb9 100644 --- a/WebCore/plugins/npfunctions.h +++ b/WebCore/plugins/npfunctions.h @@ -43,16 +43,16 @@ extern "C" { #endif typedef NPError (*NPN_GetURLNotifyProcPtr)(NPP instance, const char* URL, const char* window, void* notifyData); -typedef NPError (*NPN_PostURLNotifyProcPtr)(NPP instance, const char* URL, const char* window, uint32 len, const char* buf, NPBool file, void* notifyData); +typedef NPError (*NPN_PostURLNotifyProcPtr)(NPP instance, const char* URL, const char* window, uint32_t len, const char* buf, NPBool file, void* notifyData); typedef NPError (*NPN_RequestReadProcPtr)(NPStream* stream, NPByteRange* rangeList); typedef NPError (*NPN_NewStreamProcPtr)(NPP instance, NPMIMEType type, const char* window, NPStream** stream); -typedef int32 (*NPN_WriteProcPtr)(NPP instance, NPStream* stream, int32 len, void* buffer); +typedef int32_t (*NPN_WriteProcPtr)(NPP instance, NPStream* stream, int32_t len, void* buffer); typedef NPError (*NPN_DestroyStreamProcPtr)(NPP instance, NPStream* stream, NPReason reason); typedef void (*NPN_StatusProcPtr)(NPP instance, const char* message); typedef const char*(*NPN_UserAgentProcPtr)(NPP instance); -typedef void* (*NPN_MemAllocProcPtr)(uint32 size); +typedef void* (*NPN_MemAllocProcPtr)(uint32_t size); typedef void (*NPN_MemFreeProcPtr)(void* ptr); -typedef uint32 (*NPN_MemFlushProcPtr)(uint32 size); +typedef uint32_t (*NPN_MemFlushProcPtr)(uint32_t size); typedef void (*NPN_ReloadPluginsProcPtr)(NPBool reloadPages); typedef NPError (*NPN_GetValueProcPtr)(NPP instance, NPNVariable variable, void *ret_value); typedef NPError (*NPN_SetValueProcPtr)(NPP instance, NPPVariable variable, void *value); @@ -60,18 +60,18 @@ typedef void (*NPN_InvalidateRectProcPtr)(NPP instance, NPRect *rect); typedef void (*NPN_InvalidateRegionProcPtr)(NPP instance, NPRegion region); typedef void (*NPN_ForceRedrawProcPtr)(NPP instance); typedef NPError (*NPN_GetURLProcPtr)(NPP instance, const char* URL, const char* window); -typedef NPError (*NPN_PostURLProcPtr)(NPP instance, const char* URL, const char* window, uint32 len, const char* buf, NPBool file); +typedef NPError (*NPN_PostURLProcPtr)(NPP instance, const char* URL, const char* window, uint32_t len, const char* buf, NPBool file); typedef void* (*NPN_GetJavaEnvProcPtr)(void); typedef void* (*NPN_GetJavaPeerProcPtr)(NPP instance); typedef void (*NPN_PushPopupsEnabledStateProcPtr)(NPP instance, NPBool enabled); typedef void (*NPN_PopPopupsEnabledStateProcPtr)(NPP instance); typedef void (*NPN_PluginThreadAsyncCallProcPtr)(NPP npp, void (*func)(void *), void *userData); -typedef NPError (*NPN_GetValueForURLProcPtr)(NPP npp, NPNURLVariable variable, const char* url, char** value, uint32* len); -typedef NPError (*NPN_SetValueForURLProcPtr)(NPP npp, NPNURLVariable variable, const char* url, const char* value, uint32 len); -typedef NPError (*NPN_GetAuthenticationInfoProcPtr)(NPP npp, const char* protocol, const char* host, int32 port, const char* scheme, const char *realm, char** username, uint32* ulen, char** password, uint32* plen); +typedef NPError (*NPN_GetValueForURLProcPtr)(NPP npp, NPNURLVariable variable, const char* url, char** value, uint32_t* len); +typedef NPError (*NPN_SetValueForURLProcPtr)(NPP npp, NPNURLVariable variable, const char* url, const char* value, uint32_t len); +typedef NPError (*NPN_GetAuthenticationInfoProcPtr)(NPP npp, const char* protocol, const char* host, int32_t port, const char* scheme, const char *realm, char** username, uint32_t* ulen, char** password, uint32_t* plen); -typedef uint32 (*NPN_ScheduleTimerProcPtr)(NPP npp, uint32 interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32 timerID)); -typedef void (*NPN_UnscheduleTimerProcPtr)(NPP npp, uint32 timerID); +typedef uint32_t (*NPN_ScheduleTimerProcPtr)(NPP npp, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID)); +typedef void (*NPN_UnscheduleTimerProcPtr)(NPP npp, uint32_t timerID); typedef NPError (*NPN_PopUpContextMenuProcPtr)(NPP instance, NPMenu* menu); typedef NPBool (*NPN_ConvertPointProcPtr)(NPP npp, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace); @@ -99,16 +99,16 @@ typedef void (*NPN_SetExceptionProcPtr) (NPObject *obj, const NPUTF8 *message); typedef bool (*NPN_EnumerateProcPtr) (NPP npp, NPObject *npobj, NPIdentifier **identifier, uint32_t *count); typedef bool (*NPN_ConstructProcPtr)(NPP npp, NPObject* obj, const NPVariant *args, uint32_t argCount, NPVariant *result); -typedef NPError (*NPP_NewProcPtr)(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved); +typedef NPError (*NPP_NewProcPtr)(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved); typedef NPError (*NPP_DestroyProcPtr)(NPP instance, NPSavedData** save); typedef NPError (*NPP_SetWindowProcPtr)(NPP instance, NPWindow* window); -typedef NPError (*NPP_NewStreamProcPtr)(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype); +typedef NPError (*NPP_NewStreamProcPtr)(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype); typedef NPError (*NPP_DestroyStreamProcPtr)(NPP instance, NPStream* stream, NPReason reason); typedef void (*NPP_StreamAsFileProcPtr)(NPP instance, NPStream* stream, const char* fname); -typedef int32 (*NPP_WriteReadyProcPtr)(NPP instance, NPStream* stream); -typedef int32 (*NPP_WriteProcPtr)(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer); +typedef int32_t (*NPP_WriteReadyProcPtr)(NPP instance, NPStream* stream); +typedef int32_t (*NPP_WriteProcPtr)(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer); typedef void (*NPP_PrintProcPtr)(NPP instance, NPPrint* platformPrint); -typedef int16 (*NPP_HandleEventProcPtr)(NPP instance, void* event); +typedef int16_t (*NPP_HandleEventProcPtr)(NPP instance, void* event); typedef void (*NPP_URLNotifyProcPtr)(NPP instance, const char* URL, NPReason reason, void* notifyData); typedef NPError (*NPP_GetValueProcPtr)(NPP instance, NPPVariable variable, void *ret_value); typedef NPError (*NPP_SetValueProcPtr)(NPP instance, NPNVariable variable, void *value); @@ -117,8 +117,8 @@ typedef void *(*NPP_GetJavaClassProcPtr)(void); typedef void* JRIGlobalRef; //not using this right now typedef struct _NPNetscapeFuncs { - uint16 size; - uint16 version; + uint16_t size; + uint16_t version; NPN_GetURLProcPtr geturl; NPN_PostURLProcPtr posturl; @@ -176,8 +176,8 @@ typedef struct _NPNetscapeFuncs { } NPNetscapeFuncs; typedef struct _NPPluginFuncs { - uint16 size; - uint16 version; + uint16_t size; + uint16_t version; NPP_NewProcPtr newp; NPP_DestroyProcPtr destroy; NPP_SetWindowProcPtr setwindow; diff --git a/WebCore/plugins/qt/PluginPackageQt.cpp b/WebCore/plugins/qt/PluginPackageQt.cpp index 018c64f..5694148 100644 --- a/WebCore/plugins/qt/PluginPackageQt.cpp +++ b/WebCore/plugins/qt/PluginPackageQt.cpp @@ -83,7 +83,7 @@ bool PluginPackage::fetchInfo() static NPError staticPluginQuirkRequiresGtkToolKit_NPN_GetValue(NPP instance, NPNVariable variable, void* value) { if (variable == NPNVToolkit) { - *static_cast<uint32*>(value) = 2; + *static_cast<uint32_t*>(value) = 2; return NPERR_NO_ERROR; } @@ -143,7 +143,7 @@ abort: return false; } -uint16 PluginPackage::NPVersion() const +uint16_t PluginPackage::NPVersion() const { return NP_VERSION_MINOR; } diff --git a/WebCore/plugins/qt/PluginViewQt.cpp b/WebCore/plugins/qt/PluginViewQt.cpp index fb88b87..ff52070 100644 --- a/WebCore/plugins/qt/PluginViewQt.cpp +++ b/WebCore/plugins/qt/PluginViewQt.cpp @@ -134,12 +134,14 @@ void PluginView::updatePluginWidget() invalidate(); } -void PluginView::setFocus() +void PluginView::setFocus(bool focused) { - if (platformPluginWidget()) - platformPluginWidget()->setFocus(Qt::OtherFocusReason); - else - Widget::setFocus(); + if (platformPluginWidget()) { + if (focused) + platformPluginWidget()->setFocus(Qt::OtherFocusReason); + } else { + Widget::setFocus(focused); + } } void PluginView::show() @@ -527,7 +529,7 @@ void PluginView::setParentVisible(bool visible) platformPluginWidget()->setVisible(visible); } -NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32 len, const char* buf) +NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf) { String filename(buf, len); @@ -557,7 +559,7 @@ bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPErr { switch (variable) { case NPNVToolkit: - *static_cast<uint32*>(value) = 0; + *static_cast<uint32_t*>(value) = 0; *result = NPERR_NO_ERROR; return true; @@ -603,7 +605,7 @@ bool PluginView::platformGetValue(NPNVariable variable, void* value, NPError* re case NPNVToolkit: if (m_plugin->quirks().contains(PluginQuirkRequiresGtkToolKit)) { - *((uint32 *)value) = 2; + *((uint32_t *)value) = 2; *result = NPERR_NO_ERROR; return true; } diff --git a/WebCore/plugins/symbian/PluginPackageSymbian.cpp b/WebCore/plugins/symbian/PluginPackageSymbian.cpp index d30f80e..7fca625 100644 --- a/WebCore/plugins/symbian/PluginPackageSymbian.cpp +++ b/WebCore/plugins/symbian/PluginPackageSymbian.cpp @@ -174,7 +174,7 @@ void PluginPackage::unload() m_pluginLoader = 0; } -uint16 PluginPackage::NPVersion() const +uint16_t PluginPackage::NPVersion() const { return NP_VERSION_MINOR; } diff --git a/WebCore/plugins/symbian/PluginViewSymbian.cpp b/WebCore/plugins/symbian/PluginViewSymbian.cpp index bae3b7f..361f946 100644 --- a/WebCore/plugins/symbian/PluginViewSymbian.cpp +++ b/WebCore/plugins/symbian/PluginViewSymbian.cpp @@ -101,12 +101,14 @@ void PluginView::updatePluginWidget() setNPWindowIfNeeded(); } -void PluginView::setFocus() +void PluginView::setFocus(bool focused) { - if (platformPluginWidget()) - platformPluginWidget()->setFocus(Qt::OtherFocusReason); - else - Widget::setFocus(); + if (platformPluginWidget()) { + if (focused) + platformPluginWidget()->setFocus(Qt::OtherFocusReason); + } else { + Widget::setFocus(focused); + } } void PluginView::show() @@ -304,7 +306,7 @@ void PluginView::setParentVisible(bool visible) platformPluginWidget()->setVisible(visible); } -NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32 len, const char* buf) +NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf) { notImplemented(); return NPERR_NO_ERROR; @@ -414,11 +416,11 @@ bool PluginView::platformStart() void PluginView::platformDestroy() { - QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient(); - if (client && qobject_cast<QGraphicsWebView*>(client->pluginParent())) - delete static_cast<PluginContainerSymbian*>(platformPluginWidget())->proxy(); - else - delete platformPluginWidget(); + if (platformPluginWidget()) { + PluginContainerSymbian* container = static_cast<PluginContainerSymbian*>(platformPluginWidget()); + delete container->proxy(); + delete container; + } } void PluginView::halt() diff --git a/WebCore/plugins/win/PluginPackageWin.cpp b/WebCore/plugins/win/PluginPackageWin.cpp index e70c2c2..80dea93 100644 --- a/WebCore/plugins/win/PluginPackageWin.cpp +++ b/WebCore/plugins/win/PluginPackageWin.cpp @@ -335,7 +335,7 @@ bool PluginPackage::equal(const PluginPackage& a, const PluginPackage& b) return true; } -uint16 PluginPackage::NPVersion() const +uint16_t PluginPackage::NPVersion() const { return NP_VERSION_MINOR; } diff --git a/WebCore/plugins/win/PluginViewWin.cpp b/WebCore/plugins/win/PluginViewWin.cpp index 01e425f..96fa9e4 100644 --- a/WebCore/plugins/win/PluginViewWin.cpp +++ b/WebCore/plugins/win/PluginViewWin.cpp @@ -140,7 +140,7 @@ static BYTE* endPaint; typedef HDC (WINAPI *PtrBeginPaint)(HWND, PAINTSTRUCT*); typedef BOOL (WINAPI *PtrEndPaint)(HWND, const PAINTSTRUCT*); -#if OS(WINDOWS) && PLATFORM(X86_64) && COMPILER(MSVC) +#if OS(WINDOWS) && CPU(X86_64) && COMPILER(MSVC) extern "C" HDC __stdcall _HBeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint); extern "C" BOOL __stdcall _HEndPaint(HWND hWnd, const PAINTSTRUCT* lpPaint); #endif @@ -463,12 +463,12 @@ void PluginView::updatePluginWidget() } } -void PluginView::setFocus() +void PluginView::setFocus(bool focused) { - if (platformPluginWidget()) + if (focused && platformPluginWidget()) SetFocus(platformPluginWidget()); - Widget::setFocus(); + Widget::setFocus(focused); } void PluginView::show() @@ -544,7 +544,7 @@ void PluginView::paintIntoTransformedContext(HDC hdc) NPEvent npEvent; npEvent.event = WM_WINDOWPOSCHANGED; - npEvent.lParam = reinterpret_cast<uint32>(&windowpos); + npEvent.lParam = reinterpret_cast<uintptr_t>(&windowpos); npEvent.wParam = 0; dispatchNPEvent(npEvent); @@ -552,7 +552,7 @@ void PluginView::paintIntoTransformedContext(HDC hdc) setNPWindowRect(frameRect()); npEvent.event = WM_PAINT; - npEvent.wParam = reinterpret_cast<uint32>(hdc); + npEvent.wParam = reinterpret_cast<uintptr_t>(hdc); // This is supposed to be a pointer to the dirty rect, but it seems that the Flash plugin // ignores it so we just pass null. @@ -829,12 +829,12 @@ void PluginView::setNPWindowRect(const IntRect& rect) #else WNDPROC currentWndProc = (WNDPROC)GetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC); if (currentWndProc != PluginViewWndProc) - m_pluginWndProc = (WNDPROC)SetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC, (LONG)PluginViewWndProc); + m_pluginWndProc = (WNDPROC)SetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC, (LONG_PTR)PluginViewWndProc); #endif } } -NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32 len, const char* buf) +NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf) { String filename(buf, len); @@ -978,7 +978,7 @@ bool PluginView::platformStart() // Calling SetWindowLongPtrA here makes the window proc ASCII, which is required by at least // the Shockwave Director plug-in. -#if OS(WINDOWS) && PLATFORM(X86_64) && COMPILER(MSVC) +#if OS(WINDOWS) && CPU(X86_64) ::SetWindowLongPtrA(platformPluginWidget(), GWLP_WNDPROC, (LONG_PTR)DefWindowProcA); #elif OS(WINCE) ::SetWindowLong(platformPluginWidget(), GWL_WNDPROC, (LONG)DefWindowProc); diff --git a/WebCore/rendering/InlineBox.cpp b/WebCore/rendering/InlineBox.cpp index 2575fb7..213737c 100644 --- a/WebCore/rendering/InlineBox.cpp +++ b/WebCore/rendering/InlineBox.cpp @@ -102,7 +102,7 @@ int InlineBox::height() const const Font& font = renderer()->style(m_firstLine)->font(); int result = font.height(); if (parent()) - result += flowObject->borderTop() + flowObject->paddingTop() + flowObject->borderBottom() + flowObject->paddingBottom(); + result += flowObject->borderAndPaddingHeight(); return result; } diff --git a/WebCore/rendering/MediaControlElements.cpp b/WebCore/rendering/MediaControlElements.cpp index 569f214..16827f5 100644 --- a/WebCore/rendering/MediaControlElements.cpp +++ b/WebCore/rendering/MediaControlElements.cpp @@ -74,7 +74,7 @@ MediaControlShadowRootElement::MediaControlShadowRootElement(Document* document, renderer->setStyle(rootStyle.release()); setRenderer(renderer); setAttached(); - setInDocument(true); + setInDocument(); } void MediaControlShadowRootElement::updateStyle() @@ -92,7 +92,7 @@ MediaControlElement::MediaControlElement(Document* document, PseudoId pseudo, HT , m_mediaElement(mediaElement) , m_pseudoStyleId(pseudo) { - setInDocument(true); + setInDocument(); switch (pseudo) { case MEDIA_CONTROLS_CURRENT_TIME_DISPLAY: m_displayType = MediaCurrentTimeDisplay; @@ -318,7 +318,7 @@ MediaControlInputElement::MediaControlInputElement(Document* document, PseudoId , m_pseudoStyleId(pseudo) { setInputType(type); - setInDocument(true); + setInDocument(); switch (pseudo) { case MEDIA_CONTROLS_MUTE_BUTTON: diff --git a/WebCore/rendering/RenderApplet.cpp b/WebCore/rendering/RenderApplet.cpp index 062641e..7411c54 100644 --- a/WebCore/rendering/RenderApplet.cpp +++ b/WebCore/rendering/RenderApplet.cpp @@ -59,9 +59,9 @@ void RenderApplet::createWidgetIfNecessary() // use fixed widths/heights from the style system when we can, since the widget might // not have an accurate m_width/m_height. int contentWidth = style()->width().isFixed() ? style()->width().value() : - width() - borderLeft() - borderRight() - paddingLeft() - paddingRight(); + width() - borderAndPaddingWidth(); int contentHeight = style()->height().isFixed() ? style()->height().value() : - height() - borderTop() - borderBottom() - paddingTop() - paddingBottom(); + height() - borderAndPaddingHeight(); for (Node* child = element->firstChild(); child; child = child->nextSibling()) { if (child->hasTagName(paramTag)) { HTMLParamElement* p = static_cast<HTMLParamElement*>(child); diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index 3f53456..cf4101b 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -589,10 +589,10 @@ bool RenderBlock::isSelfCollapsingBlock() const // (c) have border/padding, // (d) have a min-height // (e) have specified that one of our margins can't collapse using a CSS extension - if (height() > 0 || - isTable() || (borderBottom() + paddingBottom() + borderTop() + paddingTop()) != 0 || - style()->minHeight().isPositive() || - style()->marginTopCollapse() == MSEPARATE || style()->marginBottomCollapse() == MSEPARATE) + if (height() > 0 + || isTable() || borderAndPaddingHeight() + || style()->minHeight().isPositive() + || style()->marginTopCollapse() == MSEPARATE || style()->marginBottomCollapse() == MSEPARATE) return false; bool hasAutoHeight = style()->height().isAuto(); @@ -4011,7 +4011,7 @@ void RenderBlock::calcPrefWidths() } int toAdd = 0; - toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight(); + toAdd = borderAndPaddingWidth(); if (hasOverflowClip() && style()->overflowY() == OSCROLL) toAdd += verticalScrollbarWidth(); diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index bd82683..e38cf25 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -514,7 +514,7 @@ int RenderBox::overrideHeight() const int RenderBox::calcBorderBoxWidth(int width) const { - int bordersPlusPadding = borderLeft() + borderRight() + paddingLeft() + paddingRight(); + int bordersPlusPadding = borderAndPaddingWidth(); if (style()->boxSizing() == CONTENT_BOX) return width + bordersPlusPadding; return max(width, bordersPlusPadding); @@ -522,7 +522,7 @@ int RenderBox::calcBorderBoxWidth(int width) const int RenderBox::calcBorderBoxHeight(int height) const { - int bordersPlusPadding = borderTop() + borderBottom() + paddingTop() + paddingBottom(); + int bordersPlusPadding = borderAndPaddingHeight(); if (style()->boxSizing() == CONTENT_BOX) return height + bordersPlusPadding; return max(height, bordersPlusPadding); @@ -531,14 +531,14 @@ int RenderBox::calcBorderBoxHeight(int height) const int RenderBox::calcContentBoxWidth(int width) const { if (style()->boxSizing() == BORDER_BOX) - width -= (borderLeft() + borderRight() + paddingLeft() + paddingRight()); + width -= borderAndPaddingWidth(); return max(0, width); } int RenderBox::calcContentBoxHeight(int height) const { if (style()->boxSizing() == BORDER_BOX) - height -= (borderTop() + borderBottom() + paddingTop() + paddingBottom()); + height -= borderAndPaddingHeight(); return max(0, height); } @@ -635,34 +635,36 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty) return; } - int w = width(); - int h = height(); + return paintBoxDecorationsWithSize(paintInfo, tx, ty, width(), height()); +} +void RenderBox::paintBoxDecorationsWithSize(PaintInfo& paintInfo, int tx, int ty, int width, int height) +{ // border-fit can adjust where we paint our border and background. If set, we snugly fit our line box descendants. (The iChat // balloon layout is an example of this). - borderFitAdjust(tx, w); + borderFitAdjust(tx, width); // FIXME: Should eventually give the theme control over whether the box shadow should paint, since controls could have // custom shadows of their own. - paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Normal); + paintBoxShadow(paintInfo.context, tx, ty, width, height, style(), Normal); // If we have a native theme appearance, paint that before painting our background. // The theme will tell us whether or not we should also paint the CSS background. - bool themePainted = style()->hasAppearance() && !theme()->paint(this, paintInfo, IntRect(tx, ty, w, h)); + bool themePainted = style()->hasAppearance() && !theme()->paint(this, paintInfo, IntRect(tx, ty, width, height)); if (!themePainted) { // The <body> only paints its background if the root element has defined a background // independent of the body. Go through the DOM to get to the root element's render object, // since the root could be inline and wrapped in an anonymous block. if (!isBody() || document()->documentElement()->renderer()->style()->hasBackground()) - paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), tx, ty, w, h); + paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), tx, ty, width, height); if (style()->hasAppearance()) - theme()->paintDecorations(this, paintInfo, IntRect(tx, ty, w, h)); + theme()->paintDecorations(this, paintInfo, IntRect(tx, ty, width, height)); } - paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Inset); + paintBoxShadow(paintInfo.context, tx, ty, width, height, style(), Inset); // The theme will tell us whether or not we should also paint the CSS border. - if ((!style()->hasAppearance() || (!themePainted && theme()->paintBorderOnly(this, paintInfo, IntRect(tx, ty, w, h)))) && style()->hasBorder()) - paintBorder(paintInfo.context, tx, ty, w, h, style()); + if ((!style()->hasAppearance() || (!themePainted && theme()->paintBorderOnly(this, paintInfo, IntRect(tx, ty, width, height)))) && style()->hasBorder()) + paintBorder(paintInfo.context, tx, ty, width, height, style()); } void RenderBox::paintMask(PaintInfo& paintInfo, int tx, int ty) @@ -1318,8 +1320,12 @@ void RenderBox::calcWidth() if (treatAsReplaced) { #else if (treatAsReplaced) +<<<<<<< HEAD:WebCore/rendering/RenderBox.cpp #endif setWidth(max(w.value() + borderLeft() + borderRight() + paddingLeft() + paddingRight(), minPrefWidth())); +======= + setWidth(max(w.value() + borderAndPaddingWidth(), minPrefWidth())); +>>>>>>> webkit.org at r58956:WebCore/rendering/RenderBox.cpp #ifdef ANDROID_LAYOUT // in SSR mode with replaced box, if the box width is wider than the container width, @@ -1337,7 +1343,7 @@ void RenderBox::calcWidth() // Width calculations if (treatAsReplaced) - setWidth(w.value() + borderLeft() + borderRight() + paddingLeft() + paddingRight()); + setWidth(w.value() + borderAndPaddingWidth()); else { // Calculate Width setWidth(calcWidthUsing(Width, containerWidth)); @@ -1508,7 +1514,7 @@ void RenderBox::calcHeight() // grab our cached flexible height. if (hasOverrideSize() && parent()->isFlexibleBox() && parent()->style()->boxOrient() == VERTICAL && parent()->isFlexingChildren()) - h = Length(overrideSize() - borderTop() - borderBottom() - paddingTop() - paddingBottom(), Fixed); + h = Length(overrideSize() - borderAndPaddingHeight(), Fixed); else if (treatAsReplaced) h = Length(calcReplacedHeight(), Fixed); else { @@ -1519,8 +1525,7 @@ void RenderBox::calcHeight() // Block children of horizontal flexible boxes fill the height of the box. if (h.isAuto() && parent()->isFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL && parent()->isStretchingChildren()) { - h = Length(parentBox()->contentHeight() - marginTop() - marginBottom() - - borderTop() - paddingTop() - borderBottom() - paddingBottom(), Fixed); + h = Length(parentBox()->contentHeight() - marginTop() - marginBottom() - borderAndPaddingHeight(), Fixed); checkMinMaxHeight = false; } @@ -1545,7 +1550,7 @@ void RenderBox::calcHeight() // The only times we don't check min/max height are when a fixed length has // been given as an override. Just use that. The value has already been adjusted // for box-sizing. - heightResult = h.value() + borderTop() + borderBottom() + paddingTop() + paddingBottom(); + heightResult = h.value() + borderAndPaddingHeight(); } setHeight(heightResult); @@ -1564,9 +1569,7 @@ void RenderBox::calcHeight() if (isRoot()) setHeight(max(height(), visHeight - margins)); else { - int marginsBordersPadding = margins + parentBox()->marginTop() + parentBox()->marginBottom() - + parentBox()->borderTop() + parentBox()->borderBottom() - + parentBox()->paddingTop() + parentBox()->paddingBottom(); + int marginsBordersPadding = margins + parentBox()->marginTop() + parentBox()->marginBottom() + parentBox()->borderAndPaddingHeight(); setHeight(max(height(), visHeight - marginsBordersPadding)); } } @@ -1660,7 +1663,7 @@ int RenderBox::calcPercentageHeight(const Length& height) // It is necessary to use the border-box to match WinIE's broken // box model. This is essential for sizing inside // table cells using percentage heights. - result -= (borderTop() + paddingTop() + borderBottom() + paddingBottom()); + result -= borderAndPaddingHeight(); result = max(0, result); } } @@ -1733,8 +1736,7 @@ int RenderBox::calcReplacedHeightUsing(Length height) const // Don't let table cells squeeze percent-height replaced elements // <http://bugs.webkit.org/show_bug.cgi?id=15359> availableHeight = max(availableHeight, intrinsicSize().height()); - return height.calcValue(availableHeight - (borderTop() + borderBottom() - + paddingTop() + paddingBottom())); + return height.calcValue(availableHeight - borderAndPaddingHeight()); } return calcContentBoxHeight(height.calcValue(availableHeight)); @@ -1761,7 +1763,7 @@ int RenderBox::availableHeightUsing(const Length& h) const // artificially. We're going to rely on this cell getting expanded to some new // height, and then when we lay out again we'll use the calculation below. if (isTableCell() && (h.isAuto() || h.isPercent())) - return overrideSize() - (borderLeft() + borderRight() + paddingLeft() + paddingRight()); + return overrideSize() - borderAndPaddingWidth(); if (h.isPercent()) return calcContentBoxHeight(h.calcValue(containingBlock()->availableHeight())); @@ -1878,7 +1880,7 @@ void RenderBox::calcAbsoluteHorizontal() // instead of the the container block's. TextDirection containerDirection = (style()->htmlHacks()) ? parent()->style()->direction() : containerBlock->style()->direction(); - const int bordersPlusPadding = borderLeft() + borderRight() + paddingLeft() + paddingRight(); + const int bordersPlusPadding = borderAndPaddingWidth(); const Length marginLeft = style()->marginLeft(); const Length marginRight = style()->marginRight(); Length left = style()->left(); @@ -2187,7 +2189,7 @@ void RenderBox::calcAbsoluteVertical() const int containerHeight = containingBlockHeightForPositioned(containerBlock); - const int bordersPlusPadding = borderTop() + borderBottom() + paddingTop() + paddingBottom(); + const int bordersPlusPadding = borderAndPaddingHeight(); const Length marginTop = style()->marginTop(); const Length marginBottom = style()->marginBottom(); Length top = style()->top(); @@ -2428,7 +2430,7 @@ void RenderBox::calcAbsoluteHorizontalReplaced() // NOTE: This value of width is FINAL in that the min/max width calculations // are dealt with in calcReplacedWidth(). This means that the steps to produce // correct max/min in the non-replaced version, are not necessary. - setWidth(calcReplacedWidth() + borderLeft() + borderRight() + paddingLeft() + paddingRight()); + setWidth(calcReplacedWidth() + borderAndPaddingWidth()); const int availableSpace = containerWidth - width(); /*-----------------------------------------------------------------------*\ @@ -2601,7 +2603,7 @@ void RenderBox::calcAbsoluteVerticalReplaced() // NOTE: This value of height is FINAL in that the min/max height calculations // are dealt with in calcReplacedHeight(). This means that the steps to produce // correct max/min in the non-replaced version, are not necessary. - setHeight(calcReplacedHeight() + borderTop() + borderBottom() + paddingTop() + paddingBottom()); + setHeight(calcReplacedHeight() + borderAndPaddingHeight()); const int availableSpace = containerHeight - height(); /*-----------------------------------------------------------------------*\ @@ -2787,8 +2789,8 @@ VisiblePosition RenderBox::positionForPoint(const IntPoint& point) int yPos = point.y(); if (isTable() && node()) { - int right = contentWidth() + borderRight() + paddingRight() + borderLeft() + paddingLeft(); - int bottom = contentHeight() + borderTop() + paddingTop() + borderBottom() + paddingBottom(); + int right = contentWidth() + borderAndPaddingWidth(); + int bottom = contentHeight() + borderAndPaddingHeight(); if (xPos < 0 || xPos > right || yPos < 0 || yPos > bottom) { if (xPos <= right / 2) diff --git a/WebCore/rendering/RenderBox.h b/WebCore/rendering/RenderBox.h index 68bbd51..1c766aa 100644 --- a/WebCore/rendering/RenderBox.h +++ b/WebCore/rendering/RenderBox.h @@ -308,6 +308,7 @@ protected: void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, CompositeOperator op, RenderObject* backgroundObject); void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, CompositeOperator = CompositeSourceOver, RenderObject* backgroundObject = 0); + void paintBoxDecorationsWithSize(PaintInfo&, int tx, int ty, int width, int height); void paintMaskImages(const PaintInfo&, int tx, int ty, int width, int height); #if PLATFORM(MAC) diff --git a/WebCore/rendering/RenderBoxModelObject.h b/WebCore/rendering/RenderBoxModelObject.h index db7538d..a4cf54a 100644 --- a/WebCore/rendering/RenderBoxModelObject.h +++ b/WebCore/rendering/RenderBoxModelObject.h @@ -75,6 +75,9 @@ public: virtual int borderLeft() const { return style()->borderLeftWidth(); } virtual int borderRight() const { return style()->borderRightWidth(); } + int borderAndPaddingHeight() const { return borderTop() + borderBottom() + paddingTop() + paddingBottom(); } + int borderAndPaddingWidth() const { return borderLeft() + borderRight() + paddingLeft() + paddingRight(); } + virtual int marginTop() const = 0; virtual int marginBottom() const = 0; virtual int marginLeft() const = 0; diff --git a/WebCore/rendering/RenderDataGrid.cpp b/WebCore/rendering/RenderDataGrid.cpp index bdf723f..00cbd7c 100644 --- a/WebCore/rendering/RenderDataGrid.cpp +++ b/WebCore/rendering/RenderDataGrid.cpp @@ -111,7 +111,7 @@ void RenderDataGrid::calcPrefWidths() m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value())); } - int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight(); + int toAdd = borderAndPaddingWidth(); m_minPrefWidth += toAdd; m_maxPrefWidth += toAdd; diff --git a/WebCore/rendering/RenderFieldset.cpp b/WebCore/rendering/RenderFieldset.cpp index d8cbd00..306e111 100644 --- a/WebCore/rendering/RenderFieldset.cpp +++ b/WebCore/rendering/RenderFieldset.cpp @@ -59,7 +59,7 @@ void RenderFieldset::calcPrefWidths() if (legendMarginRight.isFixed()) legendMinWidth += legendMarginRight.value(); - m_minPrefWidth = max(m_minPrefWidth, legendMinWidth + paddingLeft() + paddingRight() + borderLeft() + borderRight()); + m_minPrefWidth = max(m_minPrefWidth, legendMinWidth + borderAndPaddingWidth()); } } diff --git a/WebCore/rendering/RenderFileUploadControl.cpp b/WebCore/rendering/RenderFileUploadControl.cpp index 6a5c1e0..fa2a998 100644 --- a/WebCore/rendering/RenderFileUploadControl.cpp +++ b/WebCore/rendering/RenderFileUploadControl.cpp @@ -152,7 +152,7 @@ void RenderFileUploadControl::updateFromElement() renderer->setStyle(buttonStyle.release()); renderer->updateFromElement(); m_button->setAttached(); - m_button->setInDocument(true); + m_button->setInDocument(); addChild(renderer); } @@ -285,7 +285,7 @@ void RenderFileUploadControl::calcPrefWidths() m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value())); } - int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight(); + int toAdd = borderAndPaddingWidth(); m_minPrefWidth += toAdd; m_maxPrefWidth += toAdd; diff --git a/WebCore/rendering/RenderFlexibleBox.cpp b/WebCore/rendering/RenderFlexibleBox.cpp index 6882097..d0222cb 100644 --- a/WebCore/rendering/RenderFlexibleBox.cpp +++ b/WebCore/rendering/RenderFlexibleBox.cpp @@ -195,7 +195,7 @@ void RenderFlexibleBox::calcPrefWidths() m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value())); } - int toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight(); + int toAdd = borderAndPaddingWidth(); if (hasOverflowClip() && style()->overflowY() == OSCROLL) toAdd += verticalScrollbarWidth(); @@ -1035,7 +1035,7 @@ int RenderFlexibleBox::allowedChildFlex(RenderBox* child, bool expanding, unsign if (isHorizontal()) { // FIXME: For now just handle fixed values. int maxW = INT_MAX; - int w = child->overrideWidth() - (child->borderLeft() + child->borderRight() + child->paddingLeft() + child->paddingRight()); + int w = child->overrideWidth() - child->borderAndPaddingWidth(); if (!child->style()->maxWidth().isUndefined() && child->style()->maxWidth().isFixed()) maxW = child->style()->maxWidth().value(); @@ -1049,7 +1049,7 @@ int RenderFlexibleBox::allowedChildFlex(RenderBox* child, bool expanding, unsign } else { // FIXME: For now just handle fixed values. int maxH = INT_MAX; - int h = child->overrideHeight() - (child->borderTop() + child->borderBottom() + child->paddingTop() + child->paddingBottom()); + int h = child->overrideHeight() - child->borderAndPaddingHeight(); if (!child->style()->maxHeight().isUndefined() && child->style()->maxHeight().isFixed()) maxH = child->style()->maxHeight().value(); @@ -1062,7 +1062,7 @@ int RenderFlexibleBox::allowedChildFlex(RenderBox* child, bool expanding, unsign // FIXME: For now just handle fixed values. if (isHorizontal()) { int minW = child->minPrefWidth(); - int w = child->overrideWidth() - (child->borderLeft() + child->borderRight() + child->paddingLeft() + child->paddingRight()); + int w = child->overrideWidth() - child->borderAndPaddingWidth(); if (child->style()->minWidth().isFixed()) minW = child->style()->minWidth().value(); else if (child->style()->minWidth().type() == Intrinsic) @@ -1075,7 +1075,7 @@ int RenderFlexibleBox::allowedChildFlex(RenderBox* child, bool expanding, unsign } else { if (child->style()->minHeight().isFixed()) { int minH = child->style()->minHeight().value(); - int h = child->overrideHeight() - (child->borderLeft() + child->borderRight() + child->paddingLeft() + child->paddingRight()); + int h = child->overrideHeight() - child->borderAndPaddingHeight(); int allowedShrinkage = min(0, minH - h); return allowedShrinkage; } diff --git a/WebCore/rendering/RenderIFrame.cpp b/WebCore/rendering/RenderIFrame.cpp index 5852468..90cac14 100644 --- a/WebCore/rendering/RenderIFrame.cpp +++ b/WebCore/rendering/RenderIFrame.cpp @@ -77,6 +77,8 @@ void RenderIFrame::calcHeight() if (isScrollable || !style()->height().isFixed()) { FrameView* view = static_cast<FrameView*>(widget()); + if (!view) + return; int border = borderTop() + borderBottom(); setHeight(max(height(), view->contentsHeight() + border)); } @@ -126,6 +128,8 @@ void RenderIFrame::calcWidth() if (isScrollable || !style()->width().isFixed()) { FrameView* view = static_cast<FrameView*>(widget()); + if (!view) + return; int border = borderLeft() + borderRight(); setWidth(max(width(), view->contentsWidth() + border)); } diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp index a2052fe..73cf73c 100644 --- a/WebCore/rendering/RenderImage.cpp +++ b/WebCore/rendering/RenderImage.cpp @@ -679,11 +679,11 @@ void RenderImage::calcPrefWidths() { ASSERT(prefWidthsDirty()); - int paddingAndBorders = paddingLeft() + paddingRight() + borderLeft() + borderRight(); - m_maxPrefWidth = calcReplacedWidth(false) + paddingAndBorders; + int borderAndPadding = borderAndPaddingWidth(); + m_maxPrefWidth = calcReplacedWidth(false) + borderAndPadding; if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) - m_maxPrefWidth = min(m_maxPrefWidth, style()->maxWidth().value() + (style()->boxSizing() == CONTENT_BOX ? paddingAndBorders : 0)); + m_maxPrefWidth = min(m_maxPrefWidth, style()->maxWidth().value() + (style()->boxSizing() == CONTENT_BOX ? borderAndPadding : 0)); if (style()->width().isPercent() || style()->height().isPercent() || style()->maxWidth().isPercent() || style()->maxHeight().isPercent() || diff --git a/WebCore/rendering/RenderInline.cpp b/WebCore/rendering/RenderInline.cpp index 6d3f462..69e6eab 100644 --- a/WebCore/rendering/RenderInline.cpp +++ b/WebCore/rendering/RenderInline.cpp @@ -274,7 +274,7 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock, // has to move into the inline continuation. Call updateBeforeAfterContent to ensure that the inline's :after // content gets properly destroyed. if (document()->usesBeforeAfterRules()) - inlineCurr->children()->updateBeforeAfterContent(this, AFTER); + inlineCurr->children()->updateBeforeAfterContent(inlineCurr, AFTER); // Now we need to take all of the children starting from the first child // *after* currChild and append them all to the clone. diff --git a/WebCore/rendering/RenderInline.h b/WebCore/rendering/RenderInline.h index 7fcb516..4084b6e 100644 --- a/WebCore/rendering/RenderInline.h +++ b/WebCore/rendering/RenderInline.h @@ -71,6 +71,8 @@ public: int verticalPositionFromCache(bool firstLine) const; void invalidateVerticalPosition() { m_verticalPosition = PositionUndefined; } + RenderInline* inlineContinuation() const; + private: virtual RenderObjectChildList* virtualChildren() { return children(); } virtual const RenderObjectChildList* virtualChildren() const { return children(); } @@ -126,7 +128,6 @@ private: virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const; - RenderInline* inlineContinuation() const; void setContinuation(RenderBoxModelObject* c) { m_continuation = c; } virtual void childBecameNonInline(RenderObject* child); diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index 7994325..ea29087 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -47,6 +47,7 @@ #include "CSSPropertyNames.h" #include "CSSStyleDeclaration.h" #include "CSSStyleSelector.h" +#include "Chrome.h" #include "Document.h" #include "EventHandler.h" #include "EventNames.h" @@ -79,12 +80,12 @@ #include "ScrollbarTheme.h" #include "SelectionController.h" #include "TextStream.h" -#include "TransformationMatrix.h" #include "TransformState.h" +#include "TransformationMatrix.h" #include "TranslateTransformOperation.h" -#include <wtf/text/CString.h> #include <wtf/StdLibExtras.h> #include <wtf/UnusedParam.h> +#include <wtf/text/CString.h> #if USE(ACCELERATED_COMPOSITING) #include "RenderLayerBacking.h" @@ -1277,17 +1278,6 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) child->updateLayerPositions(0); -#if USE(ACCELERATED_COMPOSITING) - if (compositor()->inCompositingMode()) { - // Our stacking context is guaranteed to contain all of our descendants that may need - // repositioning, so update compositing layers from there. - if (RenderLayer* compositingAncestor = stackingContext()->enclosingCompositingLayer()) { - bool isUpdateRoot = true; - compositingAncestor->backing()->updateAfterLayout(RenderLayerBacking::AllDescendants, isUpdateRoot); - } - } -#endif - RenderView* view = renderer()->view(); // We should have a RenderView if we're trying to scroll. @@ -1302,6 +1292,21 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai view->updateWidgetPositions(); } +#if USE(ACCELERATED_COMPOSITING) + if (compositor()->inCompositingMode()) { + // Our stacking context is guaranteed to contain all of our descendants that may need + // repositioning, so update compositing layers from there. + if (RenderLayer* compositingAncestor = stackingContext()->enclosingCompositingLayer()) { + if (compositor()->compositingConsultsOverlap()) + compositor()->updateCompositingLayers(CompositingUpdateOnScroll, compositingAncestor); + else { + bool isUpdateRoot = true; + compositingAncestor->backing()->updateAfterLayout(RenderLayerBacking::AllDescendants, isUpdateRoot); + } + } + } +#endif + RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint(); IntRect rectForRepaint = renderer()->clippedOverflowRectForRepaint(repaintContainer); @@ -1334,7 +1339,7 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai } } -void RenderLayer::scrollRectToVisible(const IntRect &rect, bool scrollToAnchor, const ScrollAlignment& alignX, const ScrollAlignment& alignY) +void RenderLayer::scrollRectToVisible(const IntRect& rect, bool scrollToAnchor, const ScrollAlignment& alignX, const ScrollAlignment& alignY) { RenderLayer* parentLayer = 0; IntRect newRect = rect; @@ -1399,9 +1404,17 @@ void RenderLayer::scrollRectToVisible(const IntRect &rect, bool scrollToAnchor, IntRect viewRect = frameView->visibleContentRect(true); IntRect r = getRectToExpose(viewRect, rect, alignX, alignY); - // If this is the outermost view that RenderLayer needs to scroll, then we should scroll the view recursively - // Other apps, like Mail, rely on this feature. - frameView->scrollRectIntoViewRecursively(r); + frameView->setScrollPosition(r.location()); + + // This is the outermost view of a web page, so after scrolling this view we + // scroll its container by calling Page::scrollRectIntoView. + // This only has an effect on the Mac platform in applications + // that put web views into scrolling containers, such as Mac OS X Mail. + // The canAutoscroll function in EventHandler also knows about this. + if (Frame* frame = frameView->frame()) { + if (Page* page = frame->page()) + page->chrome()->scrollRectIntoView(rect); + } } } } @@ -1548,8 +1561,7 @@ void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset style->setProperty(CSSPropertyMarginLeft, String::number(renderer->marginLeft() / zoomFactor) + "px", false, ec); style->setProperty(CSSPropertyMarginRight, String::number(renderer->marginRight() / zoomFactor) + "px", false, ec); } - int baseWidth = renderer->width() - (isBoxSizingBorder ? 0 - : renderer->borderLeft() + renderer->paddingLeft() + renderer->borderRight() + renderer->paddingRight()); + int baseWidth = renderer->width() - (isBoxSizingBorder ? 0 : renderer->borderAndPaddingWidth()); baseWidth = baseWidth / zoomFactor; style->setProperty(CSSPropertyWidth, String::number(baseWidth + difference.width()) + "px", false, ec); } @@ -1560,8 +1572,7 @@ void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset style->setProperty(CSSPropertyMarginTop, String::number(renderer->marginTop() / zoomFactor) + "px", false, ec); style->setProperty(CSSPropertyMarginBottom, String::number(renderer->marginBottom() / zoomFactor) + "px", false, ec); } - int baseHeight = renderer->height() - (isBoxSizingBorder ? 0 - : renderer->borderTop() + renderer->paddingTop() + renderer->borderBottom() + renderer->paddingBottom()); + int baseHeight = renderer->height() - (isBoxSizingBorder ? 0 : renderer->borderAndPaddingHeight()); baseHeight = baseHeight / zoomFactor; style->setProperty(CSSPropertyHeight, String::number(baseHeight + difference.height()) + "px", false, ec); } @@ -3186,7 +3197,7 @@ void RenderLayer::updateHoverActiveState(const HitTestRequest& request, HitTestR // We are clearing the :active chain because the mouse has been released. for (RenderObject* curr = activeNode->renderer(); curr; curr = curr->parent()) { if (curr->node() && !curr->isText()) - curr->node()->setInActiveChain(false); + curr->node()->clearInActiveChain(); } doc->setActiveNode(0); } else { @@ -3196,7 +3207,7 @@ void RenderLayer::updateHoverActiveState(const HitTestRequest& request, HitTestR // will need to reference this chain. for (RenderObject* curr = newActiveNode->renderer(); curr; curr = curr->parent()) { if (curr->node() && !curr->isText()) { - curr->node()->setInActiveChain(true); + curr->node()->setInActiveChain(); } } doc->setActiveNode(newActiveNode); diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp index b5f74c6..b857420 100644 --- a/WebCore/rendering/RenderLayerBacking.cpp +++ b/WebCore/rendering/RenderLayerBacking.cpp @@ -38,6 +38,7 @@ #include "GraphicsLayer.h" #include "HTMLCanvasElement.h" #include "HTMLElement.h" +#include "HTMLIFrameElement.h" #include "HTMLMediaElement.h" #include "HTMLNames.h" #include "InspectorTimelineAgent.h" @@ -384,6 +385,24 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() m_graphicsLayer->setContentsRect(contentsBox()); m_graphicsLayer->setDrawsContent(containsPaintedContent()); + + // If this is an iframe parent, update the iframe content's box + RenderLayerCompositor* innerCompositor = innerRenderLayerCompositor(); + if (innerCompositor) + innerCompositor->setRootPlatformLayerClippingBox(contentsBox()); +} + +RenderLayerCompositor* RenderLayerBacking::innerRenderLayerCompositor() const +{ + if (renderer()->isRenderIFrame()) { + HTMLIFrameElement* element = static_cast<HTMLIFrameElement*>(renderer()->node()); + if (Document* contentDocument = element->contentDocument()) { + if (RenderView* view = contentDocument->renderView()) + return view->compositor(); + } + } + + return 0; } void RenderLayerBacking::updateInternalHierarchy() @@ -823,7 +842,11 @@ FloatPoint RenderLayerBacking::contentsToGraphicsLayerCoordinates(const Graphics bool RenderLayerBacking::paintingGoesToWindow() const { - return m_owningLayer->isRootLayer(); + if (!m_owningLayer->isRootLayer()) + return false; + + // Iframe root layers paint into backing store. + return !toRenderView(renderer())->document()->ownerElement(); } void RenderLayerBacking::setContentsNeedDisplay() diff --git a/WebCore/rendering/RenderLayerBacking.h b/WebCore/rendering/RenderLayerBacking.h index a6907e7..8e0ee23 100644 --- a/WebCore/rendering/RenderLayerBacking.h +++ b/WebCore/rendering/RenderLayerBacking.h @@ -124,6 +124,8 @@ public: IntRect contentsBox() const; + RenderLayerCompositor* innerRenderLayerCompositor() const; + private: void createGraphicsLayer(); void destroyGraphicsLayer(); diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp index 25d8eda..e96e375 100644 --- a/WebCore/rendering/RenderLayerCompositor.cpp +++ b/WebCore/rendering/RenderLayerCompositor.cpp @@ -37,6 +37,7 @@ #include "GraphicsLayer.h" #include "HitTestResult.h" #include "HTMLCanvasElement.h" +#include "HTMLIFrameElement.h" #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) #include "HTMLMediaElement.h" #include "HTMLNames.h" @@ -124,7 +125,12 @@ void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */) else destroyRootPlatformLayer(); - m_renderView->compositingStateChanged(m_compositing); + if (shouldPropagateCompositingToIFrameParent()) { + if (Element* ownerElement = m_renderView->document()->ownerElement()) { + // Trigger a recalcStyle in the parent document, to update compositing in that document. + ownerElement->setNeedsStyleRecalc(SyntheticStyleChange); + } + } } } @@ -592,6 +598,7 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O childState.m_compositingAncestor = layer; if (overlapMap) addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds); + willBeComposited = true; } } } @@ -622,6 +629,8 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O } } + ASSERT(willBeComposited == needsToBeComposited(layer)); + // If we have a software transform, and we have layers under us, we need to also // be composited. Also, if we have opacity < 1, then we need to be a layer so that // the child layers are opaque, then rendered with opacity on this layer. @@ -699,19 +708,6 @@ void RenderLayerCompositor::removeCompositedChildren(RenderLayer* layer) hostingLayer->removeAllChildren(); } -void RenderLayerCompositor::parentInRootLayer(RenderLayer* layer) -{ - ASSERT(layer->isComposited()); - - GraphicsLayer* layerAnchor = layer->backing()->childForSuperlayers(); - - if (layerAnchor->parent() != m_rootPlatformLayer) { - layerAnchor->removeFromParent(); - if (m_rootPlatformLayer) - m_rootPlatformLayer->addChild(layerAnchor); - } -} - #if ENABLE(VIDEO) bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo* o) const { @@ -799,11 +795,30 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, cons } if (layerBacking) { - layerBacking->parentForSublayers()->setChildren(layerChildren); + if (shouldPropagateCompositingToIFrameParent() && layer->renderer()->isRenderIFrame()) { + // This is an iframe parent. Make it the parent of the iframe document's root + layerBacking->parentForSublayers()->removeAllChildren(); + + RenderLayerCompositor* innerCompositor = layerBacking->innerRenderLayerCompositor(); + if (innerCompositor) { + GraphicsLayer* innerRootLayer = innerCompositor->rootPlatformLayer(); + if (innerRootLayer) + layerBacking->parentForSublayers()->addChild(innerRootLayer); + } + } else + layerBacking->parentForSublayers()->setChildren(layerChildren); childLayersOfEnclosingLayer.append(layerBacking->childForSuperlayers()); } } +void RenderLayerCompositor::setRootPlatformLayerClippingBox(const IntRect& contentsBox) +{ + if (m_clippingLayer) { + m_clippingLayer->setPosition(FloatPoint(contentsBox.x(), contentsBox.y())); + m_clippingLayer->setSize(FloatSize(contentsBox.width(), contentsBox.height())); + } +} + // This just updates layer geometry without changing the hierarchy. void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer* layer) { @@ -957,7 +972,7 @@ RenderLayer* RenderLayerCompositor::rootRenderLayer() const GraphicsLayer* RenderLayerCompositor::rootPlatformLayer() const { - return m_rootPlatformLayer.get(); + return m_clippingLayer ? m_clippingLayer.get() : m_rootPlatformLayer.get(); } void RenderLayerCompositor::didMoveOnscreen() @@ -965,13 +980,28 @@ void RenderLayerCompositor::didMoveOnscreen() if (!m_rootPlatformLayer) return; - Frame* frame = m_renderView->frameView()->frame(); - Page* page = frame ? frame->page() : 0; - if (!page) - return; + bool attached = false; + if (shouldPropagateCompositingToIFrameParent()) { + if (Element* ownerElement = m_renderView->document()->ownerElement()) { + RenderObject* renderer = ownerElement->renderer(); + if (renderer && renderer->isRenderIFrame()) { + // The layer will get hooked up via RenderLayerBacking::updateGraphicsLayerConfiguration() + // for the iframe's renderer in the parent document. + ownerElement->setNeedsStyleRecalc(SyntheticStyleChange); + attached = true; + } + } + } + + if (!attached) { + Frame* frame = m_renderView->frameView()->frame(); + Page* page = frame ? frame->page() : 0; + if (!page) + return; - page->chrome()->client()->attachRootGraphicsLayer(frame, m_rootPlatformLayer.get()); - m_rootLayerAttached = true; + page->chrome()->client()->attachRootGraphicsLayer(frame, m_rootPlatformLayer.get()); + } + m_rootLayerAttached = true; } void RenderLayerCompositor::willMoveOffscreen() @@ -979,19 +1009,45 @@ void RenderLayerCompositor::willMoveOffscreen() if (!m_rootPlatformLayer || !m_rootLayerAttached) return; - Frame* frame = m_renderView->frameView()->frame(); - Page* page = frame ? frame->page() : 0; - if (!page) - return; + bool detached = false; + if (shouldPropagateCompositingToIFrameParent()) { + if (Element* ownerElement = m_renderView->document()->ownerElement()) { + RenderObject* renderer = ownerElement->renderer(); + if (renderer->isRenderIFrame()) { + // The layer will get hooked up via RenderLayerBacking::updateGraphicsLayerConfiguration() + // for the iframe's renderer in the parent document. + ownerElement->setNeedsStyleRecalc(SyntheticStyleChange); + detached = true; + } + } + } + + if (!detached) { + Frame* frame = m_renderView->frameView()->frame(); + Page* page = frame ? frame->page() : 0; + if (!page) + return; - page->chrome()->client()->attachRootGraphicsLayer(frame, 0); + page->chrome()->client()->attachRootGraphicsLayer(frame, 0); + } m_rootLayerAttached = false; } void RenderLayerCompositor::updateRootLayerPosition() { - if (m_rootPlatformLayer) - m_rootPlatformLayer->setSize(FloatSize(m_renderView->rightLayoutOverflow(), m_renderView->bottomLayoutOverflow())); + if (m_rootPlatformLayer) { + // FIXME: Adjust the y position of the m_rootPlatformLayer if we are clipping by its top edge + // Eventually this will be taken care of by scrolling logic + // https://bugs.webkit.org/show_bug.cgi?id=38518 + float height = m_renderView->bottomLayoutOverflow(); + float yOffset = 0; + + if (m_clippingLayer && height > m_clippingLayer->size().height()) + yOffset = m_clippingLayer->size().height() - height; + + m_rootPlatformLayer->setPosition(FloatPoint(0, yOffset)); + m_rootPlatformLayer->setSize(FloatSize(m_renderView->rightLayoutOverflow(), height)); + } } void RenderLayerCompositor::didStartAcceleratedAnimation() @@ -1007,6 +1063,18 @@ bool RenderLayerCompositor::has3DContent() const return layerHas3DContent(rootRenderLayer()); } +bool RenderLayerCompositor::shouldPropagateCompositingToIFrameParent() +{ + // Parent document content needs to be able to render on top of a composited iframe, so correct behavior + // is to have the parent document become composited too. However, this can cause problems on platforms that + // use native views for frames (like Mac), so disable that behavior on those platforms for now. +#if !PLATFORM(MAC) + return true; +#else + return false; +#endif +} + bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const { if (!canBeComposited(layer)) @@ -1194,7 +1262,9 @@ bool RenderLayerCompositor::requiresCompositingForPlugin(RenderObject* renderer) bool RenderLayerCompositor::requiresCompositingForIFrame(RenderObject* renderer) const { - return renderer->isRenderIFrame() && toRenderIFrame(renderer)->requiresAcceleratedCompositing(); + return shouldPropagateCompositingToIFrameParent() + && renderer->isRenderIFrame() + && toRenderIFrame(renderer)->requiresAcceleratedCompositing(); } bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* renderer) const @@ -1226,13 +1296,31 @@ void RenderLayerCompositor::ensureRootPlatformLayer() m_rootPlatformLayer = GraphicsLayer::create(0); m_rootPlatformLayer->setSize(FloatSize(m_renderView->rightLayoutOverflow(), m_renderView->bottomLayoutOverflow())); - m_rootPlatformLayer->setPosition(FloatPoint(0, 0)); + m_rootPlatformLayer->setPosition(FloatPoint()); + // The root layer does flipping if we need it on this platform. m_rootPlatformLayer->setGeometryOrientation(GraphicsLayer::compositingCoordinatesOrientation()); // Need to clip to prevent transformed content showing outside this frame m_rootPlatformLayer->setMasksToBounds(true); + if (shouldPropagateCompositingToIFrameParent()) { + // Create a clipping layer if this is an iframe + if (Element* ownerElement = m_renderView->document()->ownerElement()) { + RenderObject* renderer = ownerElement->renderer(); + if (renderer && renderer->isRenderIFrame()) { + m_clippingLayer = GraphicsLayer::create(0); + m_clippingLayer->setGeometryOrientation(GraphicsLayer::compositingCoordinatesOrientation()); +#ifndef NDEBUG + m_clippingLayer->setName("iframe Clipping"); +#endif + m_clippingLayer->setMasksToBounds(true); + m_clippingLayer->setAnchorPoint(FloatPoint()); + m_clippingLayer->addChild(m_rootPlatformLayer.get()); + } + } + } + didMoveOnscreen(); } diff --git a/WebCore/rendering/RenderLayerCompositor.h b/WebCore/rendering/RenderLayerCompositor.h index 43b8a17..36f7c15 100644 --- a/WebCore/rendering/RenderLayerCompositor.h +++ b/WebCore/rendering/RenderLayerCompositor.h @@ -136,6 +136,12 @@ public: // Walk the tree looking for layers with 3d transforms. Useful in case you need // to know if there is non-affine content, e.g. for drawing into an image. bool has3DContent() const; + + // Some platforms may wish to connect compositing layer trees between iframes and + // their parent document. + static bool shouldPropagateCompositingToIFrameParent(); + + void setRootPlatformLayerClippingBox(const IntRect& contentsBox); private: // Whether the given RL needs a compositing layer. @@ -168,8 +174,6 @@ private: void setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer); void removeCompositedChildren(RenderLayer*); - void parentInRootLayer(RenderLayer*); - bool layerHas3DContent(const RenderLayer*) const; void ensureRootPlatformLayer(); @@ -199,6 +203,9 @@ private: bool m_compositing; bool m_rootLayerAttached; bool m_compositingLayersNeedRebuild; + + // Enclosing clipping layer for iframe content + OwnPtr<GraphicsLayer> m_clippingLayer; #if PROFILE_LAYER_REBUILD int m_rootLayerUpdateCount; diff --git a/WebCore/rendering/RenderListBox.cpp b/WebCore/rendering/RenderListBox.cpp index 15c652c..68591d6 100644 --- a/WebCore/rendering/RenderListBox.cpp +++ b/WebCore/rendering/RenderListBox.cpp @@ -188,7 +188,7 @@ void RenderListBox::calcPrefWidths() m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value())); } - int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight(); + int toAdd = borderAndPaddingWidth(); m_minPrefWidth += toAdd; m_maxPrefWidth += toAdd; @@ -221,7 +221,7 @@ int RenderListBox::listHeight() const void RenderListBox::calcHeight() { - int toAdd = paddingTop() + paddingBottom() + borderTop() + borderBottom(); + int toAdd = borderAndPaddingHeight(); int itemHeight = RenderListBox::itemHeight(); setHeight(itemHeight * size() - rowSpacing + toAdd); diff --git a/WebCore/rendering/RenderMenuList.cpp b/WebCore/rendering/RenderMenuList.cpp index 518925a..e2c6fd5 100644 --- a/WebCore/rendering/RenderMenuList.cpp +++ b/WebCore/rendering/RenderMenuList.cpp @@ -262,7 +262,7 @@ void RenderMenuList::calcPrefWidths() m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value())); } - int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight(); + int toAdd = borderAndPaddingWidth(); m_minPrefWidth += toAdd; m_maxPrefWidth += toAdd; diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp index d63997a..1c93ac4 100644 --- a/WebCore/rendering/RenderObject.cpp +++ b/WebCore/rendering/RenderObject.cpp @@ -69,7 +69,7 @@ #endif #if ENABLE(SVG) -#include "RenderSVGResource.h" +#include "RenderSVGResourceContainer.h" #include "SVGRenderSupport.h" #endif @@ -2494,19 +2494,19 @@ VisiblePosition RenderObject::createVisiblePosition(const Position& position) } #if ENABLE(SVG) -const SVGRenderBase* RenderObject::toSVGRenderBase() const +RenderSVGResourceContainer* RenderObject::toRenderSVGResourceContainer() { ASSERT_NOT_REACHED(); return 0; } -RenderSVGResource* RenderObject::toRenderSVGResource() +FloatRect RenderObject::objectBoundingBox() const { ASSERT_NOT_REACHED(); - return 0; + return FloatRect(); } -FloatRect RenderObject::objectBoundingBox() const +FloatRect RenderObject::strokeBoundingBox() const { ASSERT_NOT_REACHED(); return FloatRect(); diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h index ae12758..9d8a306 100644 --- a/WebCore/rendering/RenderObject.h +++ b/WebCore/rendering/RenderObject.h @@ -54,8 +54,7 @@ class RenderTheme; class TransformState; class VisiblePosition; #if ENABLE(SVG) -class RenderSVGResource; -class SVGRenderBase; +class RenderSVGResourceContainer; #endif /* @@ -332,16 +331,16 @@ public: // to add SVG renderer methods to RenderObject with an ASSERT_NOT_REACHED() default implementation. virtual bool isSVGRoot() const { return false; } virtual bool isSVGContainer() const { return false; } + virtual bool isSVGGradientStop() const { return false; } virtual bool isSVGHiddenContainer() const { return false; } virtual bool isRenderPath() const { return false; } virtual bool isSVGText() const { return false; } virtual bool isSVGImage() const { return false; } virtual bool isSVGForeignObject() const { return false; } - virtual bool isSVGResource() const { return false; } + virtual bool isSVGResourceContainer() const { return false; } virtual bool isSVGShadowTreeRootContainer() const { return false; } - virtual const SVGRenderBase* toSVGRenderBase() const; - virtual RenderSVGResource* toRenderSVGResource(); + virtual RenderSVGResourceContainer* toRenderSVGResourceContainer(); // FIXME: Those belong into a SVG specific base-class for all renderers (see above) // Unfortunately we don't have such a class yet, because it's not possible for all renderers @@ -356,6 +355,7 @@ public: // objectBoundingBox is returned local coordinates. // The name objectBoundingBox is taken from the SVG 1.1 spec. virtual FloatRect objectBoundingBox() const; + virtual FloatRect strokeBoundingBox() const; // Returns the smallest rectangle enclosing all of the painted content // respecting clipping, masking, filters, opacity, stroke-width and markers diff --git a/WebCore/rendering/RenderPath.cpp b/WebCore/rendering/RenderPath.cpp index b1e2a8f..ccb9562 100644 --- a/WebCore/rendering/RenderPath.cpp +++ b/WebCore/rendering/RenderPath.cpp @@ -4,6 +4,7 @@ 2005, 2007 Eric Seidel <eric@webkit.org> 2009 Google, Inc. 2009 Dirk Schulze <krit@webkit.org> + Copyright (C) Research In Motion Limited 2010. 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 @@ -34,7 +35,6 @@ #include "RenderSVGResourceFilter.h" #include "RenderSVGResourceMarker.h" #include "StrokeStyleApplier.h" -#include "SVGPaintServer.h" #include "SVGRenderSupport.h" #include "SVGStyledTransformableElement.h" #include "SVGTransformList.h" @@ -65,7 +65,7 @@ private: RenderPath::RenderPath(SVGStyledTransformableElement* node) : RenderSVGModelObject(node) - , m_needsBoundariesUpdate(false) // default is false, as this is only used when a RenderSVGResource tells us that the boundaries need to be recached + , m_needsBoundariesUpdate(false) // default is false, the cached rects are empty from the beginning , m_needsPathUpdate(true) // default is true, so we grab a Path object once from SVGStyledTransformableElement , m_needsTransformUpdate(true) // default is true, so we grab a AffineTransform object once from SVGStyledTransformableElement { @@ -73,10 +73,10 @@ RenderPath::RenderPath(SVGStyledTransformableElement* node) bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill) const { - if (m_path.isEmpty()) + if (!m_fillBoundingBox.contains(point)) return false; - if (requiresFill && !SVGPaintServer::fillPaintServer(style(), this)) + if (requiresFill && !RenderSVGResource::fillPaintingResource(this, style())) return false; return m_path.contains(point, style()->svgStyle()->fillRule()); @@ -84,87 +84,16 @@ bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill) const bool RenderPath::strokeContains(const FloatPoint& point, bool requiresStroke) const { - if (m_path.isEmpty()) + if (!m_strokeAndMarkerBoundingBox.contains(point)) return false; - if (requiresStroke && !SVGPaintServer::strokePaintServer(style(), this)) + if (requiresStroke && !RenderSVGResource::strokePaintingResource(this, style())) return false; BoundingRectStrokeStyleApplier strokeStyle(this, style()); return m_path.strokeContains(&strokeStyle, point); } -FloatRect RenderPath::objectBoundingBox() const -{ - if (m_path.isEmpty()) - return FloatRect(); - - if (m_cachedLocalFillBBox.isEmpty()) - m_cachedLocalFillBBox = m_path.boundingRect(); - - return m_cachedLocalFillBBox; -} - -FloatRect RenderPath::strokeBoundingBox() const -{ - if (m_path.isEmpty()) - return FloatRect(); - - if (!m_cachedLocalStrokeBBox.isEmpty()) - return m_cachedLocalStrokeBBox; - - m_cachedLocalStrokeBBox = objectBoundingBox(); - if (style()->svgStyle()->hasStroke()) { - BoundingRectStrokeStyleApplier strokeStyle(this, style()); - m_cachedLocalStrokeBBox.unite(m_path.strokeBoundingRect(&strokeStyle)); - } - - return m_cachedLocalStrokeBBox; -} - -FloatRect RenderPath::markerBoundingBox() const -{ - if (m_path.isEmpty()) - return FloatRect(); - - if (m_cachedLocalMarkerBBox.isEmpty()) - calculateMarkerBoundsIfNeeded(); - - return m_cachedLocalMarkerBBox; -} - -FloatRect RenderPath::repaintRectInLocalCoordinates() const -{ - if (m_path.isEmpty()) - return FloatRect(); - - // If we already have a cached repaint rect, return that - if (!m_cachedLocalRepaintRect.isEmpty()) - return m_cachedLocalRepaintRect; - - // FIXME: We need to be careful here. We assume that there is no filter, - // clipper, marker or masker if the rects are empty. - FloatRect rect = filterBoundingBoxForRenderer(this); - if (!rect.isEmpty()) - m_cachedLocalRepaintRect = rect; - else { - m_cachedLocalRepaintRect = strokeBoundingBox(); - m_cachedLocalRepaintRect.unite(markerBoundingBox()); - } - - rect = clipperBoundingBoxForRenderer(this); - if (!rect.isEmpty()) - m_cachedLocalRepaintRect.intersect(rect); - - rect = maskerBoundingBoxForRenderer(this); - if (!rect.isEmpty()) - m_cachedLocalRepaintRect.intersect(rect); - - style()->svgStyle()->inflateForShadow(m_cachedLocalRepaintRect); - - return m_cachedLocalRepaintRect; -} - void RenderPath::layout() { LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout()); @@ -173,15 +102,11 @@ void RenderPath::layout() // We need to update the Path object whenever the underlying SVGStyledTransformableElement uses relative values // as the viewport size may have changed. It would be nice to optimize this to detect these changes, and only // update when needed, even when using relative values. - if (!m_needsPathUpdate && element->hasRelativeValues()) - m_needsPathUpdate = true; - - bool needsUpdate = m_needsPathUpdate || m_needsTransformUpdate || m_needsBoundariesUpdate; + bool needsPathUpdate = m_needsPathUpdate; + if (!needsPathUpdate && element->hasRelativeValues()) + needsPathUpdate = true; - if (m_needsBoundariesUpdate) - m_needsBoundariesUpdate = false; - - if (m_needsPathUpdate) { + if (needsPathUpdate) { m_path = element->toPathData(); m_needsPathUpdate = false; } @@ -191,27 +116,31 @@ void RenderPath::layout() m_needsTransformUpdate = false; } - if (needsUpdate) - invalidateCachedBoundaries(); + // At this point LayoutRepainter already grabbed the old bounds, + // recalculate them now so repaintAfterLayout() uses the new bounds + if (needsPathUpdate || m_needsBoundariesUpdate) { + updateCachedBoundaries(); + m_needsBoundariesUpdate = false; + } repainter.repaintAfterLayout(); setNeedsLayout(false); } -static inline void fillAndStrokePath(const Path& path, GraphicsContext* context, RenderStyle* style, RenderPath* object) +static inline void fillAndStrokePath(const Path& path, GraphicsContext* context, RenderPath* object) { context->beginPath(); - SVGPaintServer* fillPaintServer = SVGPaintServer::fillPaintServer(style, object); - if (fillPaintServer) { + if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(object, object->style())) { context->addPath(path); - fillPaintServer->draw(context, object, ApplyToFillTargetType); + if (fillPaintingResource->applyResource(object, object->style(), context, ApplyToFillMode)) + fillPaintingResource->postApplyResource(object, context, ApplyToFillMode); } - - SVGPaintServer* strokePaintServer = SVGPaintServer::strokePaintServer(style, object); - if (strokePaintServer) { - context->addPath(path); // path is cleared when filled. - strokePaintServer->draw(context, object, ApplyToStrokeTargetType); + + if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(object, object->style())) { + context->addPath(path); + if (strokePaintingResource->applyResource(object, object->style(), context, ApplyToStrokeMode)) + strokePaintingResource->postApplyResource(object, context, ApplyToStrokeMode); } } @@ -222,10 +151,7 @@ void RenderPath::paint(PaintInfo& paintInfo, int, int) FloatRect boundingBox = repaintRectInLocalCoordinates(); FloatRect nonLocalBoundingBox = m_localTransform.mapRect(boundingBox); - // FIXME: The empty rect check is to deal with incorrect initial clip in renderSubtreeToImage - // unfortunately fixing that problem is fairly complex unless we were willing to just futz the - // rect to something "close enough" - if (!nonLocalBoundingBox.intersects(paintInfo.rect) && !paintInfo.rect.isEmpty()) + if (!nonLocalBoundingBox.intersects(paintInfo.rect)) return; PaintInfo childPaintInfo(paintInfo); @@ -239,13 +165,16 @@ void RenderPath::paint(PaintInfo& paintInfo, int, int) PaintInfo savedInfo(childPaintInfo); if (prepareToRenderSVGContent(this, childPaintInfo, boundingBox, filter)) { - if (style()->svgStyle()->shapeRendering() == SR_CRISPEDGES) + const SVGRenderStyle* svgStyle = style()->svgStyle(); + if (svgStyle->shapeRendering() == SR_CRISPEDGES) childPaintInfo.context->setShouldAntialias(false); - fillAndStrokePath(m_path, childPaintInfo.context, style(), this); - if (static_cast<SVGStyledElement*>(node())->supportsMarkers()) + fillAndStrokePath(m_path, childPaintInfo.context, this); + + if (svgStyle->hasMarkers()) m_markerLayoutInfo.drawMarkers(childPaintInfo); } + finishRenderSVGContent(this, childPaintInfo, filter, savedInfo.context); } @@ -288,20 +217,22 @@ bool RenderPath::nodeAtFloatPoint(const HitTestRequest&, HitTestResult& result, return false; } -void RenderPath::calculateMarkerBoundsIfNeeded() const +FloatRect RenderPath::calculateMarkerBoundsIfNeeded() { Document* doc = document(); SVGElement* svgElement = static_cast<SVGElement*>(node()); ASSERT(svgElement && svgElement->document()); if (!svgElement->isStyled()) - return; + return FloatRect(); SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); if (!styledElement->supportsMarkers()) - return; + return FloatRect(); const SVGRenderStyle* svgStyle = style()->svgStyle(); + ASSERT(svgStyle->hasMarkers()); + AtomicString startMarkerId(svgStyle->markerStartResource()); AtomicString midMarkerId(svgStyle->markerMidResource()); AtomicString endMarkerId(svgStyle->markerEndResource()); @@ -326,24 +257,63 @@ void RenderPath::calculateMarkerBoundsIfNeeded() const endMarker->addClient(this); if (!startMarker && !midMarker && !endMarker) - return; + return FloatRect(); float strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, svgStyle->strokeWidth(), 1.0f); - m_cachedLocalMarkerBBox = m_markerLayoutInfo.calculateBoundaries(startMarker, midMarker, endMarker, strokeWidth, m_path); + return m_markerLayoutInfo.calculateBoundaries(startMarker, midMarker, endMarker, strokeWidth, m_path); } -void RenderPath::invalidateCachedBoundaries() +void RenderPath::styleWillChange(StyleDifference diff, const RenderStyle* newStyle) { - m_cachedLocalRepaintRect = FloatRect(); - m_cachedLocalStrokeBBox = FloatRect(); - m_cachedLocalFillBBox = FloatRect(); - m_cachedLocalMarkerBBox = FloatRect(); + setNeedsBoundariesUpdate(); + RenderSVGModelObject::styleWillChange(diff, newStyle); } -void RenderPath::styleWillChange(StyleDifference diff, const RenderStyle* newStyle) +void RenderPath::updateCachedBoundaries() { - invalidateCachedBoundaries(); - RenderSVGModelObject::styleWillChange(diff, newStyle); + if (m_path.isEmpty()) { + m_fillBoundingBox = FloatRect(); + m_strokeAndMarkerBoundingBox = FloatRect(); + m_repaintBoundingBox = FloatRect(); + return; + } + + // Cache _unclipped_ fill bounding box, used for calculations in resources + m_fillBoundingBox = m_path.boundingRect(); + + // Cache _unclipped_ stroke bounding box, used for calculations in resources (includes marker boundaries) + m_strokeAndMarkerBoundingBox = m_fillBoundingBox; + + const SVGRenderStyle* svgStyle = style()->svgStyle(); + if (svgStyle->hasStroke()) { + BoundingRectStrokeStyleApplier strokeStyle(this, style()); + m_strokeAndMarkerBoundingBox.unite(m_path.strokeBoundingRect(&strokeStyle)); + } + + if (svgStyle->hasMarkers()) { + FloatRect markerBounds = calculateMarkerBoundsIfNeeded(); + if (!markerBounds.isEmpty()) + m_strokeAndMarkerBoundingBox.unite(markerBounds); + } + + // Cache smallest possible repaint rectangle + + // FIXME: We need to be careful here. We assume that there is no resource, if the rect is empty. + FloatRect rect = filterBoundingBoxForRenderer(this); + if (rect.isEmpty()) + m_repaintBoundingBox = m_strokeAndMarkerBoundingBox; + else + m_repaintBoundingBox = rect; + + rect = clipperBoundingBoxForRenderer(this); + if (!rect.isEmpty()) + m_repaintBoundingBox.intersect(rect); + + rect = maskerBoundingBoxForRenderer(this); + if (!rect.isEmpty()) + m_repaintBoundingBox.intersect(rect); + + svgStyle->inflateForShadow(m_repaintBoundingBox); } } diff --git a/WebCore/rendering/RenderPath.h b/WebCore/rendering/RenderPath.h index ea4de40..5509057 100644 --- a/WebCore/rendering/RenderPath.h +++ b/WebCore/rendering/RenderPath.h @@ -50,11 +50,9 @@ private: bool fillContains(const FloatPoint&, bool requiresFill = true) const; bool strokeContains(const FloatPoint&, bool requiresStroke = true) const; - virtual FloatRect objectBoundingBox() const; - virtual FloatRect strokeBoundingBox() const; - virtual FloatRect markerBoundingBox() const; - virtual FloatRect repaintRectInLocalCoordinates() const; - + virtual FloatRect objectBoundingBox() const { return m_fillBoundingBox; } + virtual FloatRect strokeBoundingBox() const { return m_strokeAndMarkerBoundingBox; } + virtual FloatRect repaintRectInLocalCoordinates() const { return m_repaintBoundingBox; } virtual const AffineTransform& localToParentTransform() const { return m_localTransform; } virtual bool isRenderPath() const { return true; } @@ -67,8 +65,8 @@ private: virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); virtual void styleWillChange(StyleDifference, const RenderStyle*); - void calculateMarkerBoundsIfNeeded() const; - void invalidateCachedBoundaries(); + FloatRect calculateMarkerBoundsIfNeeded(); + void updateCachedBoundaries(); private: virtual AffineTransform localTransform() const { return m_localTransform; } @@ -78,11 +76,10 @@ private: bool m_needsTransformUpdate : 1; mutable Path m_path; - mutable FloatRect m_cachedLocalFillBBox; - mutable FloatRect m_cachedLocalStrokeBBox; - mutable FloatRect m_cachedLocalRepaintRect; - mutable FloatRect m_cachedLocalMarkerBBox; - mutable SVGMarkerLayoutInfo m_markerLayoutInfo; + FloatRect m_fillBoundingBox; + FloatRect m_strokeAndMarkerBoundingBox; + FloatRect m_repaintBoundingBox; + SVGMarkerLayoutInfo m_markerLayoutInfo; AffineTransform m_localTransform; }; diff --git a/WebCore/rendering/RenderProgress.cpp b/WebCore/rendering/RenderProgress.cpp index a9dbfe8..b42cc8b 100644 --- a/WebCore/rendering/RenderProgress.cpp +++ b/WebCore/rendering/RenderProgress.cpp @@ -23,9 +23,12 @@ #include "RenderProgress.h" +#include "HTMLDivElement.h" #include "HTMLProgressElement.h" #include "RenderTheme.h" +#include "RenderView.h" #include <wtf/CurrentTime.h> +#include <wtf/RefPtr.h> using namespace std; @@ -33,6 +36,23 @@ namespace WebCore { using namespace HTMLNames; +class ProgressValueElement : public HTMLDivElement { +public: + ProgressValueElement(Document*, Node* shadowParent); + +private: + virtual bool isShadowNode() const { return true; } + virtual Node* shadowParentNode() { return m_shadowParent; } + + Node* m_shadowParent; +}; + +ProgressValueElement::ProgressValueElement(Document* document, Node* shadowParent) +: HTMLDivElement(divTag, document) +, m_shadowParent(shadowParent) +{ +} + RenderProgress::RenderProgress(HTMLProgressElement* element) : RenderBlock(element) , m_position(-1) @@ -41,19 +61,48 @@ RenderProgress::RenderProgress(HTMLProgressElement* element) , m_animationDuration(0) , m_animating(false) , m_animationTimer(this, &RenderProgress::animationTimerFired) + , m_valuePart(0) { } +RenderProgress::~RenderProgress() +{ + if (m_valuePart) + m_valuePart->detach(); +} + void RenderProgress::layout() { ASSERT(needsLayout()); LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); + IntSize oldSize = size(); + calcWidth(); calcHeight(); - - m_overflow.clear(); + if (m_valuePart) { + IntRect valuePartRect(borderLeft() + paddingLeft(), borderTop() + paddingTop(), lround((width() - borderLeft() - paddingLeft() - borderRight() - paddingRight()) * position()), height() - borderTop() - paddingTop() - borderBottom() - paddingBottom()); + if (style()->direction() == RTL) + valuePartRect.setX(width() - borderRight() - paddingRight() - valuePartRect.width()); + toRenderBox(m_valuePart->renderer())->setFrameRect(valuePartRect); + + if (oldSize != size()) + m_valuePart->renderer()->setChildNeedsLayout(true, false); + + LayoutStateMaintainer statePusher(view(), this, size()); + + IntRect oldRect = toRenderBox(m_valuePart->renderer())->frameRect(); + + m_valuePart->renderer()->layoutIfNeeded(); + + toRenderBox(m_valuePart->renderer())->setFrameRect(valuePartRect); + if (m_valuePart->renderer()->checkForRepaintDuringLayout()) + m_valuePart->renderer()->repaintDuringLayoutIfMoved(oldRect); + + statePusher.pop(); + addOverflowFromChild(toRenderBox(m_valuePart->renderer())); + } updateAnimationState(); @@ -62,6 +111,13 @@ void RenderProgress::layout() setNeedsLayout(false); } +void RenderProgress::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) +{ + RenderBlock::styleDidChange(diff, oldStyle); + + updateValuePartState(); +} + void RenderProgress::updateFromElement() { HTMLProgressElement* element = progressElement(); @@ -71,9 +127,46 @@ void RenderProgress::updateFromElement() updateAnimationState(); + updateValuePartState(); + repaint(); } +void RenderProgress::updateValuePartState() +{ + bool needLayout = !style()->hasAppearance() || m_valuePart; + if (!style()->hasAppearance() && !m_valuePart) { + m_valuePart = new ProgressValueElement(document(), node()); + RefPtr<RenderStyle> styleForValuePart = createStyleForValuePart(style()); + m_valuePart->setRenderer(m_valuePart->createRenderer(renderArena(), styleForValuePart.get())); + m_valuePart->renderer()->setStyle(styleForValuePart.release()); + m_valuePart->setAttached(); + m_valuePart->setInDocument(); + addChild(m_valuePart->renderer()); + } else if (style()->hasAppearance() && m_valuePart) { + m_valuePart->detach(); + m_valuePart = 0; + } + if (needLayout) + setNeedsLayout(true); +} + +PassRefPtr<RenderStyle> RenderProgress::createStyleForValuePart(RenderStyle* parentStyle) +{ + RefPtr<RenderStyle> styleForValuePart; + RenderStyle* pseudoStyle = getCachedPseudoStyle(PROGRESS_BAR_VALUE); + if (pseudoStyle) + styleForValuePart = RenderStyle::clone(pseudoStyle); + else + styleForValuePart = RenderStyle::create(); + + if (parentStyle) + styleForValuePart->inheritFrom(parentStyle); + styleForValuePart->setDisplay(BLOCK); + styleForValuePart->setAppearance(ProgressBarValuePart); + return styleForValuePart.release(); +} + double RenderProgress::animationProgress() { return m_animating ? (fmod((currentTime() - m_animationStartTime), m_animationDuration) / m_animationDuration) : 0; @@ -99,7 +192,7 @@ void RenderProgress::updateAnimationState() m_animationDuration = theme()->animationDurationForProgressBar(this); m_animationRepeatInterval = theme()->animationRepeatIntervalForProgressBar(this); - bool animating = m_animationDuration > 0; + bool animating = style()->hasAppearance() && m_animationDuration > 0; if (animating == m_animating) return; diff --git a/WebCore/rendering/RenderProgress.h b/WebCore/rendering/RenderProgress.h index d6f5078..0d93ae7 100644 --- a/WebCore/rendering/RenderProgress.h +++ b/WebCore/rendering/RenderProgress.h @@ -27,10 +27,13 @@ namespace WebCore { class HTMLProgressElement; +class ProgressValueElement; class RenderProgress : public RenderBlock { public: RenderProgress(HTMLProgressElement*); + virtual ~RenderProgress(); + double position() { return m_position; } double animationProgress(); @@ -42,9 +45,12 @@ private: virtual void layout(); virtual void updateFromElement(); virtual void paint(PaintInfo&, int tx, int ty); + virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); void animationTimerFired(Timer<RenderProgress>*); void updateAnimationState(); + void updateValuePartState(); + PassRefPtr<RenderStyle> createStyleForValuePart(RenderStyle*); double m_position; double m_animationStartTime; @@ -52,6 +58,7 @@ private: double m_animationDuration; bool m_animating; Timer<RenderProgress> m_animationTimer; + RefPtr<ProgressValueElement> m_valuePart; }; inline RenderProgress* toRenderProgress(RenderObject* object) diff --git a/WebCore/rendering/RenderReplaced.cpp b/WebCore/rendering/RenderReplaced.cpp index 0ba99f5..d579b99 100644 --- a/WebCore/rendering/RenderReplaced.cpp +++ b/WebCore/rendering/RenderReplaced.cpp @@ -196,11 +196,11 @@ void RenderReplaced::calcPrefWidths() { ASSERT(prefWidthsDirty()); - int paddingAndBorders = paddingLeft() + paddingRight() + borderLeft() + borderRight(); - int width = calcReplacedWidth(false) + paddingAndBorders; + int borderAndPadding = borderAndPaddingWidth(); + int width = calcReplacedWidth(false) + borderAndPadding; if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) - width = min(width, style()->maxWidth().value() + (style()->boxSizing() == CONTENT_BOX ? paddingAndBorders : 0)); + width = min(width, style()->maxWidth().value() + (style()->boxSizing() == CONTENT_BOX ? borderAndPadding : 0)); if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent())) { m_minPrefWidth = 0; diff --git a/WebCore/rendering/RenderSVGBlock.h b/WebCore/rendering/RenderSVGBlock.h index 19cac62..a250c00 100644 --- a/WebCore/rendering/RenderSVGBlock.h +++ b/WebCore/rendering/RenderSVGBlock.h @@ -33,8 +33,6 @@ class RenderSVGBlock : public RenderBlock, protected SVGRenderBase { public: RenderSVGBlock(SVGElement*); - virtual const SVGRenderBase* toSVGRenderBase() const { return this; } - private: virtual void setStyle(PassRefPtr<RenderStyle>); virtual void updateBoxModelInfoFromStyle(); diff --git a/WebCore/rendering/RenderSVGGradientStop.cpp b/WebCore/rendering/RenderSVGGradientStop.cpp index 66391c8..754f31f 100644 --- a/WebCore/rendering/RenderSVGGradientStop.cpp +++ b/WebCore/rendering/RenderSVGGradientStop.cpp @@ -48,10 +48,8 @@ void RenderSVGGradientStop::styleDidChange(StyleDifference diff, const RenderSty // <stop> elements should only be allowed to make renderers under gradient elements // but I can imagine a few cases we might not be catching, so let's not crash if our parent isn't a gradient. - if (SVGGradientElement* gradient = gradientElement()) { - if (SVGResource* resource = gradient->canvasResource(this)) - resource->invalidate(); - } + if (SVGGradientElement* gradient = gradientElement()) + gradient->invalidateResourceClients(); } void RenderSVGGradientStop::layout() diff --git a/WebCore/rendering/RenderSVGGradientStop.h b/WebCore/rendering/RenderSVGGradientStop.h index 1d0858d..45da7b4 100644 --- a/WebCore/rendering/RenderSVGGradientStop.h +++ b/WebCore/rendering/RenderSVGGradientStop.h @@ -27,32 +27,40 @@ namespace WebCore { - class SVGGradientElement; - class SVGStopElement; - - // This class exists mostly so we can hear about gradient stop style changes - class RenderSVGGradientStop : public RenderObject { - public: - RenderSVGGradientStop(SVGStopElement*); - virtual ~RenderSVGGradientStop(); +class SVGGradientElement; +class SVGStopElement; + +// This class exists mostly so we can hear about gradient stop style changes +class RenderSVGGradientStop : public RenderObject { +public: + RenderSVGGradientStop(SVGStopElement*); + virtual ~RenderSVGGradientStop(); + + virtual bool isSVGGradientStop() const { return true; } + virtual const char* renderName() const { return "RenderSVGGradientStop"; } - virtual const char* renderName() const { return "RenderSVGGradientStop"; } + virtual void layout(); - virtual void layout(); + // This overrides are needed to prevent ASSERTs on <svg><stop /></svg> + // RenderObject's default implementations ASSERT_NOT_REACHED() + // https://bugs.webkit.org/show_bug.cgi?id=20400 + virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject*) { return IntRect(); } + virtual FloatRect objectBoundingBox() const { return FloatRect(); } + virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(); } - // This overrides are needed to prevent ASSERTs on <svg><stop /></svg> - // RenderObject's default implementations ASSERT_NOT_REACHED() - // https://bugs.webkit.org/show_bug.cgi?id=20400 - virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject*) { return IntRect(); } - virtual FloatRect objectBoundingBox() const { return FloatRect(); } - virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(); } +protected: + virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); - protected: - virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); +private: + SVGGradientElement* gradientElement() const; +}; + +inline const RenderSVGGradientStop* toRenderSVGGradientStop(const RenderObject* object) +{ + ASSERT(!object || object->isSVGGradientStop()); + return static_cast<const RenderSVGGradientStop*>(object); +} - private: - SVGGradientElement* gradientElement() const; - }; } #endif // ENABLE(SVG) diff --git a/WebCore/rendering/RenderSVGImage.h b/WebCore/rendering/RenderSVGImage.h index 120ac72..512892c 100644 --- a/WebCore/rendering/RenderSVGImage.h +++ b/WebCore/rendering/RenderSVGImage.h @@ -41,7 +41,6 @@ public: virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; } private: - virtual const SVGRenderBase* toSVGRenderBase() const { return this; } virtual const char* renderName() const { return "RenderSVGImage"; } virtual bool isSVGImage() const { return true; } diff --git a/WebCore/rendering/RenderSVGInline.cpp b/WebCore/rendering/RenderSVGInline.cpp index 33459ce..85d148e 100644 --- a/WebCore/rendering/RenderSVGInline.cpp +++ b/WebCore/rendering/RenderSVGInline.cpp @@ -75,14 +75,10 @@ FloatRect RenderSVGInline::objectBoundingBox() const FloatRect RenderSVGInline::strokeBoundingBox() const { - const RenderObject* object = findTextRootObject(this); - ASSERT(object); - - const SVGRenderBase* renderer = object->toSVGRenderBase(); - if (!renderer) - return FloatRect(); + if (const RenderObject* object = findTextRootObject(this)) + return object->strokeBoundingBox(); - return renderer->strokeBoundingBox(); + return FloatRect(); } FloatRect RenderSVGInline::repaintRectInLocalCoordinates() const diff --git a/WebCore/rendering/RenderSVGInline.h b/WebCore/rendering/RenderSVGInline.h index e57b936..1afbb97 100644 --- a/WebCore/rendering/RenderSVGInline.h +++ b/WebCore/rendering/RenderSVGInline.h @@ -35,8 +35,6 @@ class RenderSVGInline : public RenderInline, protected SVGRenderBase { public: RenderSVGInline(Node*); - virtual const SVGRenderBase* toSVGRenderBase() const { return this; } - virtual const char* renderName() const { return "RenderSVGInline"; } virtual bool requiresLayer() const { return false; } diff --git a/WebCore/rendering/RenderSVGModelObject.h b/WebCore/rendering/RenderSVGModelObject.h index 760e79a..affa18d 100644 --- a/WebCore/rendering/RenderSVGModelObject.h +++ b/WebCore/rendering/RenderSVGModelObject.h @@ -49,8 +49,6 @@ class RenderSVGModelObject : public RenderObject, protected SVGRenderBase { public: RenderSVGModelObject(SVGStyledElement*); - virtual const SVGRenderBase* toSVGRenderBase() const { return this; } - virtual bool requiresLayer() const { return false; } virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); diff --git a/WebCore/rendering/RenderSVGResource.cpp b/WebCore/rendering/RenderSVGResource.cpp new file mode 100644 index 0000000..821e58a --- /dev/null +++ b/WebCore/rendering/RenderSVGResource.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * 2007 Rob Buis <buis@kde.org> + * 2008 Dirk Schulze <krit@webkit.org> + * Copyright (C) Research In Motion Limited 2010. 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" + +#if ENABLE(SVG) +#include "RenderSVGResource.h" + +#include "RenderSVGResourceContainer.h" +#include "RenderSVGResourceSolidColor.h" +#include "SVGURIReference.h" + +namespace WebCore { + +static inline void registerPendingResource(const AtomicString& id, const SVGPaint::SVGPaintType& paintType, const RenderObject* object) +{ + if (paintType != SVGPaint::SVG_PAINTTYPE_URI) + return; + + SVGElement* svgElement = static_cast<SVGElement*>(object->node()); + ASSERT(svgElement); + ASSERT(svgElement->isStyled()); + + object->document()->accessSVGExtensions()->addPendingResource(id, static_cast<SVGStyledElement*>(svgElement)); +} + +static inline void adjustColorForPseudoRules(const RenderStyle* style, bool useFillPaint, Color& color) +{ + if (style->insideLink() != InsideVisitedLink) + return; + + RenderStyle* visitedStyle = style->getCachedPseudoStyle(VISITED_LINK); + SVGPaint* visitedPaint = useFillPaint ? visitedStyle->svgStyle()->fillPaint() : visitedStyle->svgStyle()->strokePaint(); + if (visitedPaint->paintType() == SVGPaint::SVG_PAINTTYPE_URI) + return; + + Color visitedColor; + if (visitedPaint->paintType() == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR) + visitedColor = visitedStyle->color(); + else + visitedColor = visitedPaint->color(); + + if (visitedColor.isValid()) + color = Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), color.alpha()); +} + +// FIXME: This method and strokePaintingResource() should be refactored, to share even more code +RenderSVGResource* RenderSVGResource::fillPaintingResource(const RenderObject* object, const RenderStyle* style) +{ + ASSERT(object); + ASSERT(style); + + const SVGRenderStyle* svgStyle = style->svgStyle(); + if (!svgStyle || !svgStyle->hasFill()) + return 0; + + SVGPaint* fillPaint = svgStyle->fillPaint(); + ASSERT(fillPaint); + + RenderSVGResource* fillPaintingResource = 0; + + SVGPaint::SVGPaintType paintType = fillPaint->paintType(); + if (paintType == SVGPaint::SVG_PAINTTYPE_URI + || paintType == SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR) { + AtomicString id(SVGURIReference::getTarget(fillPaint->uri())); + fillPaintingResource = getRenderSVGResourceContainerById(object->document(), id); + + if (!fillPaintingResource) + registerPendingResource(id, paintType, object); + } + + if (paintType != SVGPaint::SVG_PAINTTYPE_URI && !fillPaintingResource) { + RenderSVGResourceSolidColor* solidResource = sharedSolidPaintingResource(); + fillPaintingResource = solidResource; + + Color fillColor; + if (fillPaint->paintType() == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR) + fillColor = style->color(); + else + fillColor = fillPaint->color(); + + adjustColorForPseudoRules(style, true /* useFillPaint */, fillColor); + + // FIXME: Ideally invalid colors would never get set on the RenderStyle and this could turn into an ASSERT + if (fillColor.isValid()) + solidResource->setColor(fillColor); + else + fillPaintingResource = 0; + } + + if (!fillPaintingResource) { + // default value (black), see bug 11017 + RenderSVGResourceSolidColor* solidResource = sharedSolidPaintingResource(); + solidResource->setColor(Color::black); + fillPaintingResource = solidResource; + } + + return fillPaintingResource; +} + +RenderSVGResource* RenderSVGResource::strokePaintingResource(const RenderObject* object, const RenderStyle* style) +{ + ASSERT(object); + ASSERT(style); + + const SVGRenderStyle* svgStyle = style->svgStyle(); + if (!svgStyle || !svgStyle->hasStroke()) + return 0; + + SVGPaint* strokePaint = svgStyle->strokePaint(); + ASSERT(strokePaint); + + RenderSVGResource* strokePaintingResource = 0; + FloatRect objectBoundingBox = object->objectBoundingBox(); + + SVGPaint::SVGPaintType paintType = strokePaint->paintType(); + if (!objectBoundingBox.isEmpty() + && (paintType == SVGPaint::SVG_PAINTTYPE_URI || paintType == SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR)) { + AtomicString id(SVGURIReference::getTarget(strokePaint->uri())); + strokePaintingResource = getRenderSVGResourceContainerById(object->document(), id); + + if (!strokePaintingResource) + registerPendingResource(id, paintType, object); + } + + if (paintType != SVGPaint::SVG_PAINTTYPE_URI && !strokePaintingResource) { + RenderSVGResourceSolidColor* solidResource = sharedSolidPaintingResource(); + strokePaintingResource = solidResource; + + Color strokeColor; + if (strokePaint->paintType() == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR) + strokeColor = style->color(); + else + strokeColor = strokePaint->color(); + + adjustColorForPseudoRules(style, false /* useFillPaint */, strokeColor); + + // FIXME: Ideally invalid colors would never get set on the RenderStyle and this could turn into an ASSERT + if (strokeColor.isValid()) + solidResource->setColor(strokeColor); + else + strokePaintingResource = 0; + } + + if (!strokePaintingResource) { + // default value (black), see bug 11017 + RenderSVGResourceSolidColor* solidResource = sharedSolidPaintingResource(); + solidResource->setColor(Color::black); + strokePaintingResource = solidResource; + } + + return strokePaintingResource; +} + +RenderSVGResourceSolidColor* RenderSVGResource::sharedSolidPaintingResource() +{ + static RenderSVGResourceSolidColor* s_sharedSolidPaintingResource = 0; + if (!s_sharedSolidPaintingResource) + s_sharedSolidPaintingResource = new RenderSVGResourceSolidColor; + return s_sharedSolidPaintingResource; +} + +void RenderSVGResource::markForLayoutAndResourceInvalidation(RenderObject* object) +{ + ASSERT(object); + ASSERT(object->node()); + ASSERT(object->node()->isSVGElement()); + + // Mark the renderer for layout + object->setNeedsLayout(true); + + // Notify any resources in the ancestor chain, that we've been invalidated + SVGElement* element = static_cast<SVGElement*>(object->node()); + if (!element->isStyled()) + return; + + static_cast<SVGStyledElement*>(element)->invalidateResourcesInAncestorChain(); +} + +} + +#endif diff --git a/WebCore/rendering/RenderSVGResource.h b/WebCore/rendering/RenderSVGResource.h index 1665404..f14fa4a 100644 --- a/WebCore/rendering/RenderSVGResource.h +++ b/WebCore/rendering/RenderSVGResource.h @@ -22,64 +22,47 @@ #define RenderSVGResource_h #if ENABLE(SVG) -#include "FloatRect.h" -#include "RenderSVGHiddenContainer.h" +#include "SVGDocumentExtensions.h" namespace WebCore { enum RenderSVGResourceType { MaskerResourceType, MarkerResourceType, + PatternResourceType, + LinearGradientResourceType, + RadialGradientResourceType, + SolidColorResourceType, FilterResourceType, ClipperResourceType }; -class RenderSVGResource : public RenderSVGHiddenContainer { -public: - RenderSVGResource(SVGStyledElement* node) - : RenderSVGHiddenContainer(node) - , m_id(node->getIDAttribute()) - { - ASSERT(node->document()); - node->document()->accessSVGExtensions()->addResource(m_id, this); - } - - virtual ~RenderSVGResource() - { - ASSERT(node()); - ASSERT(node()->document()); - node()->document()->accessSVGExtensions()->removeResource(m_id); - } - - void idChanged() - { - ASSERT(node()); - ASSERT(node()->document()); - SVGDocumentExtensions* extensions = node()->document()->accessSVGExtensions(); - - // Remove old id, that is guaranteed to be present in cache - extensions->removeResource(m_id); +enum RenderSVGResourceMode { + ApplyToDefaultMode = 1 << 0, // used for all resources except gradient/pattern + ApplyToFillMode = 1 << 1, + ApplyToStrokeMode = 1 << 2, + ApplyToTextMode = 1 << 3 // used in combination with ApplyTo{Fill|Stroke}Mode +}; - m_id = static_cast<Element*>(node())->getIDAttribute(); +class FloatRect; +class GraphicsContext; +class RenderObject; +class RenderStyle; +class RenderSVGResourceSolidColor; - // It's possible that an element is referencing us with the new id, and has to be notified that we're existing now - if (extensions->isPendingResource(m_id)) { - OwnPtr<HashSet<SVGStyledElement*> > clients(extensions->removePendingResource(m_id)); - if (clients->isEmpty()) - return; +class RenderSVGResource { +public: + RenderSVGResource() { } + virtual ~RenderSVGResource() { } - HashSet<SVGStyledElement*>::const_iterator it = clients->begin(); - const HashSet<SVGStyledElement*>::const_iterator end = clients->end(); + virtual void invalidateClients() = 0; + virtual void invalidateClient(RenderObject*) = 0; - for (; it != end; ++it) { - if (RenderObject* renderer = (*it)->renderer()) - renderer->setNeedsLayout(true); - } - } + virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) = 0; + virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short) { } + virtual FloatRect resourceBoundingBox(const FloatRect&) const = 0; - // Recache us with the new id - extensions->addResource(m_id, this); - } + virtual RenderSVGResourceType resourceType() const = 0; template<class Renderer> Renderer* cast() @@ -90,35 +73,15 @@ public: return 0; } - virtual RenderSVGResource* toRenderSVGResource() { return this; } - virtual bool isSVGResource() const { return true; } - virtual bool drawsContents() { return false; } - - virtual void invalidateClients() = 0; - virtual void invalidateClient(RenderObject*) = 0; - - virtual bool applyResource(RenderObject*, GraphicsContext*&) = 0; - virtual void postApplyResource(RenderObject*, GraphicsContext*&) { } - virtual FloatRect resourceBoundingBox(const FloatRect&) const = 0; - - virtual RenderSVGResourceType resourceType() const = 0; + // Helper utilities used in the render tree to access resources used for painting shapes/text (gradients & patterns only) + static RenderSVGResource* fillPaintingResource(const RenderObject*, const RenderStyle*); + static RenderSVGResource* strokePaintingResource(const RenderObject*, const RenderStyle*); + static RenderSVGResourceSolidColor* sharedSolidPaintingResource(); -private: - AtomicString m_id; +protected: + void markForLayoutAndResourceInvalidation(RenderObject*); }; -template<typename Renderer> -Renderer* getRenderSVGResourceById(Document* document, const AtomicString& id) -{ - if (id.isEmpty()) - return 0; - - if (RenderSVGResource* renderResource = document->accessSVGExtensions()->resourceById(id)) - return renderResource->cast<Renderer>(); - - return 0; -} - } #endif diff --git a/WebCore/rendering/RenderSVGResourceClipper.cpp b/WebCore/rendering/RenderSVGResourceClipper.cpp index ccb7397..2759976 100644 --- a/WebCore/rendering/RenderSVGResourceClipper.cpp +++ b/WebCore/rendering/RenderSVGResourceClipper.cpp @@ -38,13 +38,14 @@ #include "SVGStyledTransformableElement.h" #include "SVGUnitTypes.h" #include "SVGUseElement.h" +#include <wtf/UnusedParam.h> namespace WebCore { RenderSVGResourceType RenderSVGResourceClipper::s_resourceType = ClipperResourceType; -RenderSVGResourceClipper::RenderSVGResourceClipper(SVGStyledElement* node) - : RenderSVGResource(node) +RenderSVGResourceClipper::RenderSVGResourceClipper(SVGClipPathElement* node) + : RenderSVGResourceContainer(node) { } @@ -78,10 +79,18 @@ void RenderSVGResourceClipper::invalidateClient(RenderObject* object) return; delete m_clipper.take(object); + markForLayoutAndResourceInvalidation(object); } -bool RenderSVGResourceClipper::applyResource(RenderObject* object, GraphicsContext*& context) +bool RenderSVGResourceClipper::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode) { + ASSERT(object); + ASSERT(context); +#ifndef NDEBUG + ASSERT(resourceMode == ApplyToDefaultMode); +#else + UNUSED_PARAM(resourceMode); +#endif applyClippingToContext(object, object->objectBoundingBox(), object->repaintRectInLocalCoordinates(), context); return true; } @@ -142,9 +151,6 @@ bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* object, const FloatRect& objectBoundingBox, const FloatRect& repaintRect, GraphicsContext* context) { - ASSERT(object); - ASSERT(context); - if (!m_clipper.contains(object)) m_clipper.set(object, new ClipperData); diff --git a/WebCore/rendering/RenderSVGResourceClipper.h b/WebCore/rendering/RenderSVGResourceClipper.h index 8de17d4..0b6f2b3 100644 --- a/WebCore/rendering/RenderSVGResourceClipper.h +++ b/WebCore/rendering/RenderSVGResourceClipper.h @@ -27,7 +27,7 @@ #include "ImageBuffer.h" #include "IntSize.h" #include "Path.h" -#include "RenderSVGResource.h" +#include "RenderSVGResourceContainer.h" #include "SVGClipPathElement.h" #include "SVGUnitTypes.h" @@ -40,10 +40,9 @@ struct ClipperData { OwnPtr<ImageBuffer> clipMaskImage; }; -class RenderSVGResourceClipper : public RenderSVGResource { - +class RenderSVGResourceClipper : public RenderSVGResourceContainer { public: - RenderSVGResourceClipper(SVGStyledElement*); + RenderSVGResourceClipper(SVGClipPathElement*); virtual ~RenderSVGResourceClipper(); virtual const char* renderName() const { return "RenderSVGResourceClipper"; } @@ -51,7 +50,7 @@ public: virtual void invalidateClients(); virtual void invalidateClient(RenderObject*); - virtual bool applyResource(RenderObject*, GraphicsContext*&); + virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); virtual FloatRect resourceBoundingBox(const FloatRect&) const; virtual RenderSVGResourceType resourceType() const { return ClipperResourceType; } diff --git a/WebCore/rendering/RenderSVGResourceContainer.h b/WebCore/rendering/RenderSVGResourceContainer.h new file mode 100644 index 0000000..b63575d --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceContainer.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) Research In Motion Limited 2010. 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 RenderSVGResourceContainer_h +#define RenderSVGResourceContainer_h + +#if ENABLE(SVG) +#include "RenderSVGHiddenContainer.h" +#include "RenderSVGResource.h" + +namespace WebCore { + +class RenderSVGResourceContainer : public RenderSVGHiddenContainer, + public RenderSVGResource { +public: + RenderSVGResourceContainer(SVGStyledElement* node) + : RenderSVGHiddenContainer(node) + , RenderSVGResource() + , m_id(node->getIDAttribute()) + { + ASSERT(node->document()); + node->document()->accessSVGExtensions()->addResource(m_id, this); + } + + virtual ~RenderSVGResourceContainer() + { + ASSERT(node()); + ASSERT(node()->document()); + node()->document()->accessSVGExtensions()->removeResource(m_id); + } + + void idChanged() + { + ASSERT(node()); + ASSERT(node()->document()); + SVGDocumentExtensions* extensions = node()->document()->accessSVGExtensions(); + + // Remove old id, that is guaranteed to be present in cache + extensions->removeResource(m_id); + + m_id = static_cast<Element*>(node())->getIDAttribute(); + + // It's possible that an element is referencing us with the new id, and has to be notified that we're existing now + if (extensions->isPendingResource(m_id)) { + OwnPtr<HashSet<SVGStyledElement*> > clients(extensions->removePendingResource(m_id)); + if (clients->isEmpty()) + return; + + HashSet<SVGStyledElement*>::const_iterator it = clients->begin(); + const HashSet<SVGStyledElement*>::const_iterator end = clients->end(); + + for (; it != end; ++it) { + if (RenderObject* renderer = (*it)->renderer()) + renderer->setNeedsLayout(true); + } + } + + // Recache us with the new id + extensions->addResource(m_id, this); + } + + virtual bool isSVGResourceContainer() const { return true; } + virtual bool drawsContents() { return false; } + + virtual RenderSVGResourceContainer* toRenderSVGResourceContainer() { return this; } + +private: + AtomicString m_id; +}; + +inline RenderSVGResourceContainer* getRenderSVGResourceContainerById(Document* document, const AtomicString& id) +{ + if (id.isEmpty()) + return 0; + + if (RenderSVGResourceContainer* renderResource = document->accessSVGExtensions()->resourceById(id)) + return renderResource; + + return 0; +} + +template<typename Renderer> +Renderer* getRenderSVGResourceById(Document* document, const AtomicString& id) +{ + if (RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(document, id)) + return container->cast<Renderer>(); + + return 0; +} + +} + +#endif +#endif diff --git a/WebCore/rendering/RenderSVGResourceFilter.cpp b/WebCore/rendering/RenderSVGResourceFilter.cpp index cbedfe3..ac3ea49 100644 --- a/WebCore/rendering/RenderSVGResourceFilter.cpp +++ b/WebCore/rendering/RenderSVGResourceFilter.cpp @@ -43,6 +43,7 @@ #include "SVGStyledElement.h" #include "SVGUnitTypes.h" #include <wtf/Vector.h> +#include <wtf/UnusedParam.h> static const float kMaxFilterSize = 5000.0f; @@ -52,8 +53,8 @@ namespace WebCore { RenderSVGResourceType RenderSVGResourceFilter::s_resourceType = FilterResourceType; -RenderSVGResourceFilter::RenderSVGResourceFilter(SVGStyledElement* node) - : RenderSVGResource(node) +RenderSVGResourceFilter::RenderSVGResourceFilter(SVGFilterElement* node) + : RenderSVGResourceContainer(node) , m_savedContext(0) , m_sourceGraphicBuffer(0) { @@ -88,7 +89,8 @@ void RenderSVGResourceFilter::invalidateClient(RenderObject* object) if (!m_filter.contains(object)) return; - delete m_filter.take(object); + delete m_filter.take(object); + markForLayoutAndResourceInvalidation(object); } PassOwnPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives() @@ -134,10 +136,15 @@ bool RenderSVGResourceFilter::fitsInMaximumImageSize(const FloatSize& size, Floa return matchesFilterSize; } -bool RenderSVGResourceFilter::applyResource(RenderObject* object, GraphicsContext*& context) +bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode) { ASSERT(object); ASSERT(context); +#ifndef NDEBUG + ASSERT(resourceMode == ApplyToDefaultMode); +#else + UNUSED_PARAM(resourceMode); +#endif // Returning false here, to avoid drawings onto the context. We just want to // draw the stored filter output, not the unfiltered object as well. @@ -154,12 +161,7 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, GraphicsContex if (!filterData->builder) return false; - const SVGRenderBase* renderer = object->toSVGRenderBase(); - if (!renderer) - return false; - - FloatRect paintRect = renderer->strokeBoundingBox(); - paintRect.unite(renderer->markerBoundingBox()); + FloatRect paintRect = object->strokeBoundingBox(); // Calculate the scale factor for the use of filterRes. // Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion @@ -228,10 +230,15 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, GraphicsContex return true; } -void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsContext*& context) +void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode) { ASSERT(object); ASSERT(context); +#ifndef NDEBUG + ASSERT(resourceMode == ApplyToDefaultMode); +#else + UNUSED_PARAM(resourceMode); +#endif if (!m_filter.contains(object)) return; diff --git a/WebCore/rendering/RenderSVGResourceFilter.h b/WebCore/rendering/RenderSVGResourceFilter.h index 2cd4b6c..ce4a7e1 100644 --- a/WebCore/rendering/RenderSVGResourceFilter.h +++ b/WebCore/rendering/RenderSVGResourceFilter.h @@ -28,7 +28,7 @@ #if ENABLE(SVG) && ENABLE(FILTERS) #include "FloatRect.h" #include "ImageBuffer.h" -#include "RenderSVGResource.h" +#include "RenderSVGResourceContainer.h" #include "SVGFilter.h" #include "SVGFilterBuilder.h" #include "SVGFilterElement.h" @@ -55,9 +55,9 @@ struct FilterData { class GraphicsContext; -class RenderSVGResourceFilter : public RenderSVGResource { +class RenderSVGResourceFilter : public RenderSVGResourceContainer { public: - RenderSVGResourceFilter(SVGStyledElement*); + RenderSVGResourceFilter(SVGFilterElement*); virtual ~RenderSVGResourceFilter(); virtual const char* renderName() const { return "RenderSVGResourceFilter"; } @@ -65,8 +65,8 @@ public: virtual void invalidateClients(); virtual void invalidateClient(RenderObject*); - virtual bool applyResource(RenderObject*, GraphicsContext*&); - virtual void postApplyResource(RenderObject*, GraphicsContext*&); + virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); + virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); virtual FloatRect resourceBoundingBox(const FloatRect&) const; diff --git a/WebCore/rendering/RenderSVGResourceGradient.cpp b/WebCore/rendering/RenderSVGResourceGradient.cpp new file mode 100644 index 0000000..6c9d784 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceGradient.cpp @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * 2008 Eric Seidel <eric@webkit.org> + * 2008 Dirk Schulze <krit@webkit.org> + * Copyright (C) Research In Motion Limited 2010. 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" + +#if ENABLE(SVG) +#include "RenderSVGResourceGradient.h" + +#include "GradientAttributes.h" +#include "GraphicsContext.h" +#include "SVGRenderSupport.h" +#include <wtf/UnusedParam.h> + +namespace WebCore { + +RenderSVGResourceGradient::RenderSVGResourceGradient(SVGGradientElement* node) + : RenderSVGResourceContainer(node) +#if PLATFORM(CG) + , m_savedContext(0) +#endif +{ +} + +RenderSVGResourceGradient::~RenderSVGResourceGradient() +{ + deleteAllValues(m_gradient); + m_gradient.clear(); +} + +void RenderSVGResourceGradient::invalidateClients() +{ + const HashMap<RenderObject*, GradientData*>::const_iterator end = m_gradient.end(); + for (HashMap<RenderObject*, GradientData*>::const_iterator it = m_gradient.begin(); it != end; ++it) + markForLayoutAndResourceInvalidation(it->first); + + deleteAllValues(m_gradient); + m_gradient.clear(); +} + +void RenderSVGResourceGradient::invalidateClient(RenderObject* object) +{ + ASSERT(object); + + // FIXME: The HashMap should always contain the object on calling invalidateClient. A race condition + // during the parsing can causes a call of invalidateClient right before the call of applyResource. + // We return earlier for the moment. This bug should be fixed in: + // https://bugs.webkit.org/show_bug.cgi?id=35181 + if (!m_gradient.contains(object)) + return; + + delete m_gradient.take(object); + markForLayoutAndResourceInvalidation(object); +} + +#if PLATFORM(CG) +static inline AffineTransform absoluteTransformForRenderer(const RenderObject* object) +{ + AffineTransform absoluteTransform; + + const RenderObject* currentObject = object; + while (currentObject) { + absoluteTransform = currentObject->localToParentTransform() * absoluteTransform; + currentObject = currentObject->parent(); + } + + return absoluteTransform; +} + +static inline bool createMaskAndSwapContextForTextGradient(GraphicsContext*& context, + GraphicsContext*& savedContext, + OwnPtr<ImageBuffer>& imageBuffer, + const RenderObject* object) +{ + const RenderObject* textRootBlock = findTextRootObject(object); + + AffineTransform transform = absoluteTransformForRenderer(textRootBlock); + FloatRect maskAbsoluteBoundingBox = transform.mapRect(textRootBlock->repaintRectInLocalCoordinates()); + + IntRect maskImageRect = enclosingIntRect(maskAbsoluteBoundingBox); + if (maskImageRect.isEmpty()) + return false; + + // Allocate an image buffer as big as the absolute unclipped size of the object + OwnPtr<ImageBuffer> maskImage = ImageBuffer::create(maskImageRect.size()); + if (!maskImage) + return false; + + GraphicsContext* maskImageContext = maskImage->context(); + + // Transform the mask image coordinate system to absolute screen coordinates + maskImageContext->translate(-maskAbsoluteBoundingBox.x(), -maskAbsoluteBoundingBox.y()); + maskImageContext->concatCTM(transform); + + imageBuffer.set(maskImage.release()); + savedContext = context; + context = maskImageContext; + + return true; +} + +static inline AffineTransform clipToTextMask(GraphicsContext* context, + OwnPtr<ImageBuffer>& imageBuffer, + const RenderObject* object, + GradientData* gradientData) +{ + const RenderObject* textRootBlock = findTextRootObject(object); + context->clipToImageBuffer(textRootBlock->repaintRectInLocalCoordinates(), imageBuffer.get()); + + AffineTransform matrix; + if (gradientData->boundingBoxMode) { + FloatRect maskBoundingBox = textRootBlock->objectBoundingBox(); + matrix.translate(maskBoundingBox.x(), maskBoundingBox.y()); + matrix.scaleNonUniform(maskBoundingBox.width(), maskBoundingBox.height()); + } + matrix.multiply(gradientData->transform); + return matrix; +} +#endif + +bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode) +{ + ASSERT(object); + ASSERT(style); + ASSERT(context); + ASSERT(resourceMode != ApplyToDefaultMode); + + // Be sure to synchronize all SVG properties on the gradientElement _before_ processing any further. + // Otherwhise the call to collectGradientAttributes() in createTileImage(), may cause the SVG DOM property + // synchronization to kick in, which causes invalidateClients() to be called, which in turn deletes our + // GradientData object! Leaving out the line below will cause svg/dynamic-updates/SVG*GradientElement-svgdom* to crash. + SVGGradientElement* gradientElement = static_cast<SVGGradientElement*>(node()); + if (!gradientElement) + return false; + + gradientElement->updateAnimatedSVGAttribute(anyQName()); + + if (!m_gradient.contains(object)) + m_gradient.set(object, new GradientData); + + GradientData* gradientData = m_gradient.get(object); + + // Create gradient object + if (!gradientData->gradient) + buildGradient(gradientData, gradientElement); + + if (!gradientData->gradient) + return false; + + // Draw gradient + context->save(); + + bool isPaintingText = resourceMode & ApplyToTextMode; + if (isPaintingText) { +#if PLATFORM(CG) + if (!createMaskAndSwapContextForTextGradient(context, m_savedContext, m_imageBuffer, object)) { + context->restore(); + return false; + } +#endif + + context->setTextDrawingMode(resourceMode & ApplyToFillMode ? cTextFill : cTextStroke); + } + + AffineTransform transform; + + // CG platforms will handle the gradient space transform for text after applying the + // resource, so don't apply it here. For non-CG platforms, we want the text bounding + // box applied to the gradient space transform now, so the gradient shader can use it. +#if PLATFORM(CG) + if (gradientData->boundingBoxMode && !isPaintingText) { +#else + if (gradientData->boundingBoxMode) { +#endif + FloatRect objectBoundingBox = object->objectBoundingBox(); + transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); + transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); + } + + transform.multiply(gradientData->transform); + gradientData->gradient->setGradientSpaceTransform(transform); + + const SVGRenderStyle* svgStyle = style->svgStyle(); + ASSERT(svgStyle); + + if (resourceMode & ApplyToFillMode) { + context->setAlpha(svgStyle->fillOpacity()); + context->setFillGradient(gradientData->gradient); + context->setFillRule(svgStyle->fillRule()); + } else if (resourceMode & ApplyToStrokeMode) { + context->setAlpha(svgStyle->strokeOpacity()); + context->setStrokeGradient(gradientData->gradient); + applyStrokeStyleToContext(context, style, object); + } + + return true; +} + +void RenderSVGResourceGradient::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode) +{ + ASSERT(context); + ASSERT(resourceMode != ApplyToDefaultMode); + + if (resourceMode & ApplyToTextMode) { +#if PLATFORM(CG) + // CG requires special handling for gradient on text + if (m_savedContext && m_gradient.contains(object)) { + GradientData* gradientData = m_gradient.get(object); + + // Restore on-screen drawing context + context = m_savedContext; + m_savedContext = 0; + + gradientData->gradient->setGradientSpaceTransform(clipToTextMask(context, m_imageBuffer, object, gradientData)); + context->setFillGradient(gradientData->gradient); + + const RenderObject* textRootBlock = findTextRootObject(object); + context->fillRect(textRootBlock->repaintRectInLocalCoordinates()); + + m_imageBuffer.clear(); + } +#else + UNUSED_PARAM(object); +#endif + } else { + if (resourceMode & ApplyToFillMode) + context->fillPath(); + else if (resourceMode & ApplyToStrokeMode) + context->strokePath(); + } + + context->restore(); +} + +void RenderSVGResourceGradient::addStops(GradientData* gradientData, const Vector<Gradient::ColorStop>& stops) const +{ + ASSERT(gradientData->gradient); + + const Vector<Gradient::ColorStop>::const_iterator end = stops.end(); + for (Vector<Gradient::ColorStop>::const_iterator it = stops.begin(); it != end; ++it) + gradientData->gradient->addColorStop(*it); +} + +} + +#endif diff --git a/WebCore/rendering/RenderSVGResourceGradient.h b/WebCore/rendering/RenderSVGResourceGradient.h new file mode 100644 index 0000000..2fd9cf4 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceGradient.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * 2008 Eric Seidel <eric@webkit.org> + * Copyright (C) Research In Motion Limited 2010. 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 RenderSVGResourceGradient_h +#define RenderSVGResourceGradient_h + +#if ENABLE(SVG) +#include "AffineTransform.h" +#include "FloatRect.h" +#include "Gradient.h" +#include "ImageBuffer.h" +#include "RenderSVGResourceContainer.h" +#include "SVGGradientElement.h" + +#include <wtf/HashMap.h> + +namespace WebCore { + +struct GradientData { + RefPtr<Gradient> gradient; + + bool boundingBoxMode; + AffineTransform transform; +}; + +class GraphicsContext; + +class RenderSVGResourceGradient : public RenderSVGResourceContainer { +public: + RenderSVGResourceGradient(SVGGradientElement*); + virtual ~RenderSVGResourceGradient(); + + virtual void invalidateClients(); + virtual void invalidateClient(RenderObject*); + + virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); + virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); + virtual FloatRect resourceBoundingBox(const FloatRect&) const { return FloatRect(); } + +protected: + void addStops(GradientData*, const Vector<Gradient::ColorStop>&) const; + virtual void buildGradient(GradientData*, SVGGradientElement*) const = 0; + +private: + HashMap<RenderObject*, GradientData*> m_gradient; + +#if PLATFORM(CG) + GraphicsContext* m_savedContext; + OwnPtr<ImageBuffer> m_imageBuffer; +#endif +}; + +} + +#endif +#endif diff --git a/WebCore/rendering/RenderSVGResourceLinearGradient.cpp b/WebCore/rendering/RenderSVGResourceLinearGradient.cpp new file mode 100644 index 0000000..e34e524 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceLinearGradient.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) Research In Motion Limited 2010. 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" + +#if ENABLE(SVG) +#include "RenderSVGResourceLinearGradient.h" + +#include "LinearGradientAttributes.h" +#include "SVGLinearGradientElement.h" + +namespace WebCore { + +RenderSVGResourceType RenderSVGResourceLinearGradient::s_resourceType = LinearGradientResourceType; + +RenderSVGResourceLinearGradient::RenderSVGResourceLinearGradient(SVGLinearGradientElement* node) + : RenderSVGResourceGradient(node) +{ +} + +RenderSVGResourceLinearGradient::~RenderSVGResourceLinearGradient() +{ +} + +void RenderSVGResourceLinearGradient::buildGradient(GradientData* gradientData, SVGGradientElement* gradientElement) const +{ + SVGLinearGradientElement* linearGradientElement = static_cast<SVGLinearGradientElement*>(gradientElement); + LinearGradientAttributes attributes = linearGradientElement->collectGradientProperties(); + + // Determine gradient start/end points + FloatPoint startPoint; + FloatPoint endPoint; + linearGradientElement->calculateStartEndPoints(attributes, startPoint, endPoint); + + gradientData->gradient = Gradient::create(startPoint, endPoint); + gradientData->gradient->setSpreadMethod(attributes.spreadMethod()); + + // Record current gradient transform + gradientData->transform = attributes.gradientTransform(); + gradientData->boundingBoxMode = attributes.boundingBoxMode(); + + // Add stops + addStops(gradientData, attributes.stops()); +} + +} + +#endif diff --git a/WebCore/rendering/RenderSVGResourceLinearGradient.h b/WebCore/rendering/RenderSVGResourceLinearGradient.h new file mode 100644 index 0000000..c1f84c2 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceLinearGradient.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) Research In Motion Limited 2010. 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 RenderSVGResourceLinearGradient_h +#define RenderSVGResourceLinearGradient_h + +#if ENABLE(SVG) +#include "RenderSVGResourceGradient.h" + +namespace WebCore { + +class SVGLinearGradientElement; + +class RenderSVGResourceLinearGradient : public RenderSVGResourceGradient { +public: + RenderSVGResourceLinearGradient(SVGLinearGradientElement*); + virtual ~RenderSVGResourceLinearGradient(); + + virtual const char* renderName() const { return "RenderSVGResourceLinearGradient"; } + + virtual RenderSVGResourceType resourceType() const { return s_resourceType; } + static RenderSVGResourceType s_resourceType; + + virtual void buildGradient(GradientData*, SVGGradientElement*) const; +}; + +} + +#endif +#endif diff --git a/WebCore/rendering/RenderSVGResourceMarker.cpp b/WebCore/rendering/RenderSVGResourceMarker.cpp index c526962..460239b 100644 --- a/WebCore/rendering/RenderSVGResourceMarker.cpp +++ b/WebCore/rendering/RenderSVGResourceMarker.cpp @@ -35,8 +35,8 @@ namespace WebCore { RenderSVGResourceType RenderSVGResourceMarker::s_resourceType = MarkerResourceType; -RenderSVGResourceMarker::RenderSVGResourceMarker(SVGStyledElement* node) - : RenderSVGResource(node) +RenderSVGResourceMarker::RenderSVGResourceMarker(SVGMarkerElement* node) + : RenderSVGResourceContainer(node) { } @@ -82,6 +82,7 @@ void RenderSVGResourceMarker::invalidateClient(RenderObject* object) return; m_marker.remove(object); + markForLayoutAndResourceInvalidation(object); } void RenderSVGResourceMarker::applyViewportClip(PaintInfo& paintInfo) diff --git a/WebCore/rendering/RenderSVGResourceMarker.h b/WebCore/rendering/RenderSVGResourceMarker.h index 9e39b99..efbbdfa 100644 --- a/WebCore/rendering/RenderSVGResourceMarker.h +++ b/WebCore/rendering/RenderSVGResourceMarker.h @@ -24,7 +24,7 @@ #if ENABLE(SVG) #include "FloatRect.h" #include "RenderObject.h" -#include "RenderSVGResource.h" +#include "RenderSVGResourceContainer.h" #include "SVGMarkerElement.h" #include "SVGStyledElement.h" @@ -34,10 +34,9 @@ namespace WebCore { class AffineTransform; -class RenderSVGResourceMarker : public RenderSVGResource { - +class RenderSVGResourceMarker : public RenderSVGResourceContainer { public: - RenderSVGResourceMarker(SVGStyledElement*); + RenderSVGResourceMarker(SVGMarkerElement*); virtual ~RenderSVGResourceMarker(); virtual const char* renderName() const { return "RenderSVGResourceMarker"; } @@ -58,7 +57,7 @@ public: virtual const AffineTransform& localToParentTransform() const; AffineTransform markerTransformation(const FloatPoint& origin, float angle, float strokeWidth) const; - virtual bool applyResource(RenderObject*, GraphicsContext*&) { return false; } + virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short) { return false; } virtual FloatRect resourceBoundingBox(const FloatRect&) const { return FloatRect(); } FloatPoint referencePoint() const; diff --git a/WebCore/rendering/RenderSVGResourceMasker.cpp b/WebCore/rendering/RenderSVGResourceMasker.cpp index 8bb16de..abf8e48 100644 --- a/WebCore/rendering/RenderSVGResourceMasker.cpp +++ b/WebCore/rendering/RenderSVGResourceMasker.cpp @@ -37,13 +37,14 @@ #include "SVGStyledElement.h" #include "SVGUnitTypes.h" #include <wtf/Vector.h> +#include <wtf/UnusedParam.h> namespace WebCore { RenderSVGResourceType RenderSVGResourceMasker::s_resourceType = MaskerResourceType; -RenderSVGResourceMasker::RenderSVGResourceMasker(SVGStyledElement* node) - : RenderSVGResource(node) +RenderSVGResourceMasker::RenderSVGResourceMasker(SVGMaskElement* node) + : RenderSVGResourceContainer(node) { } @@ -77,13 +78,19 @@ void RenderSVGResourceMasker::invalidateClient(RenderObject* object) if (!m_masker.contains(object)) return; - delete m_masker.take(object); + delete m_masker.take(object); + markForLayoutAndResourceInvalidation(object); } -bool RenderSVGResourceMasker::applyResource(RenderObject* object, GraphicsContext*& context) +bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode) { ASSERT(object); ASSERT(context); +#ifndef NDEBUG + ASSERT(resourceMode == ApplyToDefaultMode); +#else + UNUSED_PARAM(resourceMode); +#endif if (!m_masker.contains(object)) m_masker.set(object, new MaskerData); @@ -151,7 +158,7 @@ void RenderSVGResourceMasker::createMaskImage(MaskerData* maskerData, const SVGM maskImageRect.setLocation(IntPoint()); // Don't create ImageBuffers with image size of 0 - if (!maskImageRect.width() || !maskImageRect.height()) { + if (maskImageRect.isEmpty()) { maskerData->emptyMask = true; return; } diff --git a/WebCore/rendering/RenderSVGResourceMasker.h b/WebCore/rendering/RenderSVGResourceMasker.h index 3127e3c..b022f7b 100644 --- a/WebCore/rendering/RenderSVGResourceMasker.h +++ b/WebCore/rendering/RenderSVGResourceMasker.h @@ -26,7 +26,7 @@ #include "GraphicsContext.h" #include "ImageBuffer.h" #include "IntSize.h" -#include "RenderSVGResource.h" +#include "RenderSVGResourceContainer.h" #include "SVGMaskElement.h" #include "SVGUnitTypes.h" @@ -36,9 +36,8 @@ namespace WebCore { struct MaskerData { - MaskerData(FloatRect rect = FloatRect(), bool emptyObject = false) - : maskRect(rect) - , emptyMask(emptyObject) + MaskerData() + : emptyMask(false) { } @@ -47,10 +46,9 @@ struct MaskerData { bool emptyMask; }; -class RenderSVGResourceMasker : public RenderSVGResource { - +class RenderSVGResourceMasker : public RenderSVGResourceContainer { public: - RenderSVGResourceMasker(SVGStyledElement*); + RenderSVGResourceMasker(SVGMaskElement*); virtual ~RenderSVGResourceMasker(); virtual const char* renderName() const { return "RenderSVGResourceMasker"; } @@ -58,7 +56,7 @@ public: virtual void invalidateClients(); virtual void invalidateClient(RenderObject*); - virtual bool applyResource(RenderObject*, GraphicsContext*&); + virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); virtual FloatRect resourceBoundingBox(const FloatRect&) const; SVGUnitTypes::SVGUnitType maskUnits() const { return toUnitType(static_cast<SVGMaskElement*>(node())->maskUnits()); } diff --git a/WebCore/rendering/RenderSVGResourcePattern.cpp b/WebCore/rendering/RenderSVGResourcePattern.cpp new file mode 100644 index 0000000..8302030 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourcePattern.cpp @@ -0,0 +1,329 @@ +/* + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) Research In Motion Limited 2010. 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" + +#if ENABLE(SVG) +#include "RenderSVGResourcePattern.h" + +#include "GraphicsContext.h" +#include "PatternAttributes.h" +#include "SVGRenderSupport.h" + +namespace WebCore { + +RenderSVGResourceType RenderSVGResourcePattern::s_resourceType = PatternResourceType; + +RenderSVGResourcePattern::RenderSVGResourcePattern(SVGPatternElement* node) + : RenderSVGResourceContainer(node) +{ +} + +RenderSVGResourcePattern::~RenderSVGResourcePattern() +{ + deleteAllValues(m_pattern); + m_pattern.clear(); +} + +void RenderSVGResourcePattern::invalidateClients() +{ + const HashMap<RenderObject*, PatternData*>::const_iterator end = m_pattern.end(); + for (HashMap<RenderObject*, PatternData*>::const_iterator it = m_pattern.begin(); it != end; ++it) + markForLayoutAndResourceInvalidation(it->first); + + deleteAllValues(m_pattern); + m_pattern.clear(); +} + +void RenderSVGResourcePattern::invalidateClient(RenderObject* object) +{ + ASSERT(object); + + // FIXME: The HashMap should always contain the object on calling invalidateClient. A race condition + // during the parsing can causes a call of invalidateClient right before the call of applyResource. + // We return earlier for the moment. This bug should be fixed in: + // https://bugs.webkit.org/show_bug.cgi?id=35181 + if (!m_pattern.contains(object)) + return; + + delete m_pattern.take(object); + markForLayoutAndResourceInvalidation(object); +} + +bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode) +{ + ASSERT(object); + ASSERT(style); + ASSERT(context); + ASSERT(resourceMode != ApplyToDefaultMode); + + // Be sure to synchronize all SVG properties on the patternElement _before_ processing any further. + // Otherwhise the call to collectPatternAttributes() in createTileImage(), may cause the SVG DOM property + // synchronization to kick in, which causes invalidateClients() to be called, which in turn deletes our + // PatternData object! Leaving out the line below will cause svg/dynamic-updates/SVGPatternElement-svgdom* to crash. + SVGPatternElement* patternElement = static_cast<SVGPatternElement*>(node()); + if (!patternElement) + return false; + + patternElement->updateAnimatedSVGAttribute(anyQName()); + + if (!m_pattern.contains(object)) + m_pattern.set(object, new PatternData); + + PatternData* patternData = m_pattern.get(object); + if (!patternData->pattern) { + FloatRect patternBoundaries; + AffineTransform patternTransform; + + // Create tile image + OwnPtr<ImageBuffer> tileImage = createTileImage(patternBoundaries, patternTransform, patternElement, object); + if (!tileImage) + return false; + + // Create pattern object + buildPattern(patternData, patternBoundaries, tileImage.release()); + + if (!patternData->pattern) + return false; + + // Compute pattern transformation + AffineTransform transform; + transform.translate(patternBoundaries.x(), patternBoundaries.y()); + transform.multiply(patternTransform); + patternData->pattern->setPatternSpaceTransform(transform); + } + + // Draw pattern + context->save(); + + const SVGRenderStyle* svgStyle = style->svgStyle(); + ASSERT(svgStyle); + + if (resourceMode & ApplyToFillMode) { + context->setAlpha(svgStyle->fillOpacity()); + context->setFillPattern(patternData->pattern); + context->setFillRule(svgStyle->fillRule()); + } else if (resourceMode & ApplyToStrokeMode) { + context->setAlpha(svgStyle->strokeOpacity()); + context->setStrokePattern(patternData->pattern); + applyStrokeStyleToContext(context, style, object); + } + + if (resourceMode & ApplyToTextMode) { + if (resourceMode & ApplyToFillMode) { + context->setTextDrawingMode(cTextFill); + +#if PLATFORM(CG) + context->applyFillPattern(); +#endif + } else if (resourceMode & ApplyToStrokeMode) { + context->setTextDrawingMode(cTextStroke); + +#if PLATFORM(CG) + context->applyStrokePattern(); +#endif + } + } + + return true; +} + +void RenderSVGResourcePattern::postApplyResource(RenderObject*, GraphicsContext*& context, unsigned short resourceMode) +{ + ASSERT(context); + ASSERT(resourceMode != ApplyToDefaultMode); + + if (!(resourceMode & ApplyToTextMode)) { + if (resourceMode & ApplyToFillMode) + context->fillPath(); + else if (resourceMode & ApplyToStrokeMode) + context->strokePath(); + } + + context->restore(); +} + +static inline FloatRect calculatePatternBoundaries(PatternAttributes& attributes, + const FloatRect& objectBoundingBox, + const SVGPatternElement* patternElement) +{ + if (attributes.boundingBoxMode()) + return FloatRect(attributes.x().valueAsPercentage() * objectBoundingBox.width(), + attributes.y().valueAsPercentage() * objectBoundingBox.height(), + attributes.width().valueAsPercentage() * objectBoundingBox.width(), + attributes.height().valueAsPercentage() * objectBoundingBox.height()); + + return FloatRect(attributes.x().value(patternElement), + attributes.y().value(patternElement), + attributes.width().value(patternElement), + attributes.height().value(patternElement)); +} + +FloatRect RenderSVGResourcePattern::calculatePatternBoundariesIncludingOverflow(PatternAttributes& attributes, + const FloatRect& objectBoundingBox, + const AffineTransform& viewBoxCTM, + const FloatRect& patternBoundaries) const +{ + // Eventually calculate the pattern content boundaries (only needed with overflow="visible"). + FloatRect patternContentBoundaries; + + const RenderStyle* style = this->style(); + if (style->overflowX() == OVISIBLE && style->overflowY() == OVISIBLE) { + for (Node* node = attributes.patternContentElement()->firstChild(); node; node = node->nextSibling()) { + if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyledTransformable() || !node->renderer()) + continue; + patternContentBoundaries.unite(node->renderer()->repaintRectInLocalCoordinates()); + } + } + + if (patternContentBoundaries.isEmpty()) + return patternBoundaries; + + FloatRect patternBoundariesIncludingOverflow = patternBoundaries; + + // Respect objectBoundingBoxMode for patternContentUnits, if viewBox is not set. + if (!viewBoxCTM.isIdentity()) + patternContentBoundaries = viewBoxCTM.mapRect(patternContentBoundaries); + else if (attributes.boundingBoxModeContent()) + patternContentBoundaries = FloatRect(patternContentBoundaries.x() * objectBoundingBox.width(), + patternContentBoundaries.y() * objectBoundingBox.height(), + patternContentBoundaries.width() * objectBoundingBox.width(), + patternContentBoundaries.height() * objectBoundingBox.height()); + + patternBoundariesIncludingOverflow.unite(patternContentBoundaries); + return patternBoundariesIncludingOverflow; +} + +PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(FloatRect& patternBoundaries, + AffineTransform& patternTransform, + const SVGPatternElement* patternElement, + RenderObject* object) const +{ + PatternAttributes attributes = patternElement->collectPatternProperties(); + + // If we couldn't determine the pattern content element root, stop here. + if (!attributes.patternContentElement()) + return 0; + + FloatRect objectBoundingBox = object->objectBoundingBox(); + patternBoundaries = calculatePatternBoundaries(attributes, objectBoundingBox, patternElement); + patternTransform = attributes.patternTransform(); + + AffineTransform viewBoxCTM = patternElement->viewBoxToViewTransform(patternElement->viewBox(), + patternElement->preserveAspectRatio(), + patternBoundaries.width(), + patternBoundaries.height()); + + FloatRect patternBoundariesIncludingOverflow = calculatePatternBoundariesIncludingOverflow(attributes, + objectBoundingBox, + viewBoxCTM, + patternBoundaries); + + IntSize imageSize(lroundf(patternBoundariesIncludingOverflow.width()), lroundf(patternBoundariesIncludingOverflow.height())); + + // FIXME: We should be able to clip this more, needs investigation + clampImageBufferSizeToViewport(object->document()->view(), imageSize); + + // Don't create ImageBuffers with image size of 0 + if (imageSize.isEmpty()) + return 0; + + OwnPtr<ImageBuffer> tileImage = ImageBuffer::create(imageSize); + + GraphicsContext* context = tileImage->context(); + ASSERT(context); + + context->save(); + + // Translate to pattern start origin + if (patternBoundariesIncludingOverflow.location() != patternBoundaries.location()) { + context->translate(patternBoundaries.x() - patternBoundariesIncludingOverflow.x(), + patternBoundaries.y() - patternBoundariesIncludingOverflow.y()); + + patternBoundaries.setLocation(patternBoundariesIncludingOverflow.location()); + } + + // Process viewBox or boundingBoxModeContent correction + if (!viewBoxCTM.isIdentity()) + context->concatCTM(viewBoxCTM); + else if (attributes.boundingBoxModeContent()) { + context->translate(objectBoundingBox.x(), objectBoundingBox.y()); + context->scale(FloatSize(objectBoundingBox.width(), objectBoundingBox.height())); + } + + // Render subtree into ImageBuffer + for (Node* node = attributes.patternContentElement()->firstChild(); node; node = node->nextSibling()) { + if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyled() || !node->renderer()) + continue; + renderSubtreeToImage(tileImage.get(), node->renderer()); + } + + context->restore(); + return tileImage.release(); +} + +void RenderSVGResourcePattern::buildPattern(PatternData* patternData, const FloatRect& patternBoundaries, PassOwnPtr<ImageBuffer> tileImage) const +{ + if (!tileImage->image()) { + patternData->pattern = 0; + return; + } + + IntRect tileRect = tileImage->image()->rect(); + if (tileRect.width() <= patternBoundaries.width() && tileRect.height() <= patternBoundaries.height()) { + patternData->pattern = Pattern::create(tileImage->image(), true, true); + return; + } + + // Draw the first cell of the pattern manually to support overflow="visible" on all platforms. + int tileWidth = static_cast<int>(patternBoundaries.width() + 0.5f); + int tileHeight = static_cast<int>(patternBoundaries.height() + 0.5f); + + // Don't create ImageBuffers with image size of 0 + if (!tileWidth || !tileHeight) { + patternData->pattern = 0; + return; + } + + OwnPtr<ImageBuffer> newTileImage = ImageBuffer::create(IntSize(tileWidth, tileHeight)); + GraphicsContext* newTileImageContext = newTileImage->context(); + + int numY = static_cast<int>(ceilf(tileRect.height() / tileHeight)) + 1; + int numX = static_cast<int>(ceilf(tileRect.width() / tileWidth)) + 1; + + newTileImageContext->save(); + newTileImageContext->translate(-patternBoundaries.width() * numX, -patternBoundaries.height() * numY); + for (int i = numY; i > 0; --i) { + newTileImageContext->translate(0, patternBoundaries.height()); + for (int j = numX; j > 0; --j) { + newTileImageContext->translate(patternBoundaries.width(), 0); + newTileImageContext->drawImage(tileImage->image(), style()->colorSpace(), tileRect, tileRect); + } + newTileImageContext->translate(-patternBoundaries.width() * numX, 0); + } + newTileImageContext->restore(); + + patternData->pattern = Pattern::create(newTileImage->image(), true, true); +} + +} + +#endif diff --git a/WebCore/rendering/RenderSVGResourcePattern.h b/WebCore/rendering/RenderSVGResourcePattern.h new file mode 100644 index 0000000..2f9d553 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourcePattern.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) Research In Motion Limited 2010. 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 RenderSVGResourcePattern_h +#define RenderSVGResourcePattern_h + +#if ENABLE(SVG) +#include "AffineTransform.h" +#include "FloatRect.h" +#include "ImageBuffer.h" +#include "Pattern.h" +#include "RenderSVGResourceContainer.h" +#include "SVGPatternElement.h" +#include "SVGUnitTypes.h" + +#include <wtf/HashMap.h> +#include <wtf/OwnPtr.h> + +namespace WebCore { + +struct PatternData { + RefPtr<Pattern> pattern; +}; + +struct PatternAttributes; + +class RenderSVGResourcePattern : public RenderSVGResourceContainer { +public: + RenderSVGResourcePattern(SVGPatternElement*); + virtual ~RenderSVGResourcePattern(); + + virtual const char* renderName() const { return "RenderSVGResourcePattern"; } + + virtual void invalidateClients(); + virtual void invalidateClient(RenderObject*); + + virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); + virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); + virtual FloatRect resourceBoundingBox(const FloatRect&) const { return FloatRect(); } + + virtual RenderSVGResourceType resourceType() const { return s_resourceType; } + static RenderSVGResourceType s_resourceType; + +private: + PassOwnPtr<ImageBuffer> createTileImage(FloatRect& patternBoundaries, AffineTransform& patternTransform, const SVGPatternElement*, RenderObject*) const; + void buildPattern(PatternData*, const FloatRect& patternBoundaries, PassOwnPtr<ImageBuffer> tileImage) const; + FloatRect calculatePatternBoundariesIncludingOverflow(PatternAttributes&, const FloatRect& objectBoundingBox, + const AffineTransform& viewBoxCTM, const FloatRect& patternBoundaries) const; + + HashMap<RenderObject*, PatternData*> m_pattern; +}; + +} + +#endif +#endif diff --git a/WebCore/rendering/RenderSVGResourceRadialGradient.cpp b/WebCore/rendering/RenderSVGResourceRadialGradient.cpp new file mode 100644 index 0000000..a8904c8 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceRadialGradient.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) Research In Motion Limited 2010. 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" + +#if ENABLE(SVG) +#include "RenderSVGResourceRadialGradient.h" + +#include "RadialGradientAttributes.h" +#include "SVGRadialGradientElement.h" + +namespace WebCore { + +RenderSVGResourceType RenderSVGResourceRadialGradient::s_resourceType = RadialGradientResourceType; + +RenderSVGResourceRadialGradient::RenderSVGResourceRadialGradient(SVGRadialGradientElement* node) + : RenderSVGResourceGradient(node) +{ +} + +RenderSVGResourceRadialGradient::~RenderSVGResourceRadialGradient() +{ +} + +void RenderSVGResourceRadialGradient::buildGradient(GradientData* gradientData, SVGGradientElement* gradientElement) const +{ + SVGRadialGradientElement* radialGradientElement = static_cast<SVGRadialGradientElement*>(gradientElement); + RadialGradientAttributes attributes = radialGradientElement->collectGradientProperties(); + + // Determine gradient focal/center points and radius + FloatPoint focalPoint; + FloatPoint centerPoint; + float radius; + radialGradientElement->calculateFocalCenterPointsAndRadius(attributes, focalPoint, centerPoint, radius); + + gradientData->gradient = Gradient::create(focalPoint, + 0.0f, // SVG does not support a "focus radius" + centerPoint, + radius); + + gradientData->gradient->setSpreadMethod(attributes.spreadMethod()); + + // Record current gradient transform + gradientData->transform = attributes.gradientTransform(); + gradientData->boundingBoxMode = attributes.boundingBoxMode(); + + // Add stops + addStops(gradientData, attributes.stops()); +} + +} + +#endif diff --git a/WebCore/rendering/RenderSVGResourceRadialGradient.h b/WebCore/rendering/RenderSVGResourceRadialGradient.h new file mode 100644 index 0000000..0583f99 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceRadialGradient.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) Research In Motion Limited 2010. 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 RenderSVGResourceRadialGradient_h +#define RenderSVGResourceRadialGradient_h + +#if ENABLE(SVG) +#include "RenderSVGResourceGradient.h" + +namespace WebCore { + +class SVGRadialGradientElement; + +class RenderSVGResourceRadialGradient : public RenderSVGResourceGradient { +public: + RenderSVGResourceRadialGradient(SVGRadialGradientElement*); + virtual ~RenderSVGResourceRadialGradient(); + + virtual const char* renderName() const { return "RenderSVGResourceRadialGradient"; } + + virtual RenderSVGResourceType resourceType() const { return s_resourceType; } + static RenderSVGResourceType s_resourceType; + + virtual void buildGradient(GradientData*, SVGGradientElement*) const; +}; + +} + +#endif +#endif diff --git a/WebCore/rendering/RenderSVGResourceSolidColor.cpp b/WebCore/rendering/RenderSVGResourceSolidColor.cpp new file mode 100644 index 0000000..9d34d79 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceSolidColor.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) Research In Motion Limited 2010. 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" + +#if ENABLE(SVG) +#include "RenderSVGResourceSolidColor.h" + +#include "GraphicsContext.h" +#include "SVGRenderSupport.h" + +#if PLATFORM(SKIA) +#include "PlatformContextSkia.h" +#endif + +namespace WebCore { + +RenderSVGResourceType RenderSVGResourceSolidColor::s_resourceType = SolidColorResourceType; + +RenderSVGResourceSolidColor::RenderSVGResourceSolidColor() +{ +} + +RenderSVGResourceSolidColor::~RenderSVGResourceSolidColor() +{ +} + +bool RenderSVGResourceSolidColor::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode) +{ + // We are NOT allowed to ASSERT(object) here, unlike all other resources. + // RenderSVGResourceSolidColor is the only resource which may be used from HTML, when rendering + // SVG Fonts for a HTML document. This will be indicated by a null RenderObject pointer. + ASSERT(context); + ASSERT(resourceMode != ApplyToDefaultMode); + + const SVGRenderStyle* svgStyle = style ? style->svgStyle() : 0; + ColorSpace colorSpace = style ? style->colorSpace() : DeviceColorSpace; + + if (resourceMode & ApplyToFillMode) { + context->setAlpha(svgStyle ? svgStyle->fillOpacity() : 1.0f); + context->setFillColor(m_color, colorSpace); + context->setFillRule(svgStyle ? svgStyle->fillRule() : RULE_NONZERO); + + if (resourceMode & ApplyToTextMode) + context->setTextDrawingMode(cTextFill); + } else if (resourceMode & ApplyToStrokeMode) { + context->setAlpha(svgStyle ? svgStyle->strokeOpacity() : 1.0f); + context->setStrokeColor(m_color, colorSpace); + + if (style) + applyStrokeStyleToContext(context, style, object); + + if (resourceMode & ApplyToTextMode) + context->setTextDrawingMode(cTextStroke); + } + + return true; +} + +void RenderSVGResourceSolidColor::postApplyResource(RenderObject*, GraphicsContext*& context, unsigned short resourceMode) +{ + ASSERT(context); + ASSERT(resourceMode != ApplyToDefaultMode); + + if (!(resourceMode & ApplyToTextMode)) { + if (resourceMode & ApplyToFillMode) + context->fillPath(); + else if (resourceMode & ApplyToStrokeMode) + context->strokePath(); + } + +#if PLATFORM(SKIA) + // FIXME: Move this into the GraphicsContext + // WebKit implicitly expects us to reset the path. + // For example in fillAndStrokePath() of RenderPath.cpp the path is + // added back to the context after filling. This is because internally it + // calls CGContextFillPath() which closes the path. + context->beginPath(); + context->platformContext()->setFillShader(0); + context->platformContext()->setStrokeShader(0); +#endif +} + +} + +#endif diff --git a/WebCore/rendering/RenderSVGResourceSolidColor.h b/WebCore/rendering/RenderSVGResourceSolidColor.h new file mode 100644 index 0000000..a1a8863 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceSolidColor.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) Research In Motion Limited 2010. 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 RenderSVGResourceSolidColor_h +#define RenderSVGResourceSolidColor_h + +#if ENABLE(SVG) +#include "Color.h" +#include "FloatRect.h" +#include "RenderSVGResource.h" + +namespace WebCore { + +class RenderSVGResourceSolidColor : public RenderSVGResource { +public: + RenderSVGResourceSolidColor(); + virtual ~RenderSVGResourceSolidColor(); + + virtual void invalidateClients() { } + virtual void invalidateClient(RenderObject*) { } + + virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); + virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); + virtual FloatRect resourceBoundingBox(const FloatRect&) const { return FloatRect(); } + + virtual RenderSVGResourceType resourceType() const { return s_resourceType; } + static RenderSVGResourceType s_resourceType; + + const Color& color() const { return m_color; } + void setColor(const Color& color) { m_color = color; } + +private: + Color m_color; +}; + +} + +#endif +#endif diff --git a/WebCore/rendering/RenderSVGRoot.cpp b/WebCore/rendering/RenderSVGRoot.cpp index 5ed0871..67a3b2a 100644 --- a/WebCore/rendering/RenderSVGRoot.cpp +++ b/WebCore/rendering/RenderSVGRoot.cpp @@ -62,11 +62,11 @@ void RenderSVGRoot::calcPrefWidths() { ASSERT(prefWidthsDirty()); - int paddingAndBorders = paddingLeft() + paddingRight() + borderLeft() + borderRight(); - int width = calcReplacedWidth(false) + paddingAndBorders; + int borderAndPadding = borderAndPaddingWidth(); + int width = calcReplacedWidth(false) + borderAndPadding; if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) - width = min(width, style()->maxWidth().value() + (style()->boxSizing() == CONTENT_BOX ? paddingAndBorders : 0)); + width = min(width, style()->maxWidth().value() + (style()->boxSizing() == CONTENT_BOX ? borderAndPadding : 0)); if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent())) { m_minPrefWidth = 0; diff --git a/WebCore/rendering/RenderSVGText.cpp b/WebCore/rendering/RenderSVGText.cpp index c0c4650..966196b 100644 --- a/WebCore/rendering/RenderSVGText.cpp +++ b/WebCore/rendering/RenderSVGText.cpp @@ -160,7 +160,10 @@ void RenderSVGText::absoluteQuads(Vector<FloatQuad>& quads) } void RenderSVGText::paint(PaintInfo& paintInfo, int, int) -{ +{ + if (paintInfo.context->paintingDisabled()) + return; + PaintInfo pi(paintInfo); pi.context->save(); applyTransformToPaintInfo(pi, localToParentTransform()); diff --git a/WebCore/rendering/RenderSVGText.h b/WebCore/rendering/RenderSVGText.h index fe53086..66f7eb3 100644 --- a/WebCore/rendering/RenderSVGText.h +++ b/WebCore/rendering/RenderSVGText.h @@ -42,8 +42,6 @@ public: private: virtual const char* renderName() const { return "RenderSVGText"; } - virtual const SVGRenderBase* toSVGRenderBase() const { return this; } - virtual bool isSVGText() const { return true; } virtual const AffineTransform& localToParentTransform() const { return m_localTransform; } diff --git a/WebCore/rendering/RenderSlider.cpp b/WebCore/rendering/RenderSlider.cpp index 37b5e19..ed5fe76 100644 --- a/WebCore/rendering/RenderSlider.cpp +++ b/WebCore/rendering/RenderSlider.cpp @@ -30,6 +30,7 @@ #include "HTMLInputElement.h" #include "HTMLDivElement.h" #include "HTMLNames.h" +#include "HTMLParser.h" #include "MediaControlElements.h" #include "MouseEvent.h" #include "RenderLayer.h" @@ -186,7 +187,7 @@ void RenderSlider::calcPrefWidths() m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value())); } - int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight(); + int toAdd = borderAndPaddingWidth(); m_minPrefWidth += toAdd; m_maxPrefWidth += toAdd; @@ -260,8 +261,7 @@ void RenderSlider::layout() RenderBox* thumb = m_thumb ? toRenderBox(m_thumb->renderer()) : 0; - IntSize baseSize(borderLeft() + paddingLeft() + paddingRight() + borderRight(), - borderTop() + paddingTop() + paddingBottom() + borderBottom()); + IntSize baseSize(borderAndPaddingWidth(), borderAndPaddingHeight()); if (thumb) { // Allow the theme to set the size of the thumb. @@ -314,7 +314,7 @@ void RenderSlider::updateFromElement() m_thumb->setRenderer(m_thumb->createRenderer(renderArena(), thumbStyle.get())); m_thumb->renderer()->setStyle(thumbStyle.release()); m_thumb->setAttached(); - m_thumb->setInDocument(true); + m_thumb->setInDocument(); addChild(m_thumb->renderer()); } setNeedsLayout(true); @@ -361,7 +361,7 @@ void RenderSlider::setValueForPosition(int position) if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart) fraction = 1 - fraction; double value = range.clampValue(range.valueFromProportion(fraction)); - element->setValueFromRenderer(HTMLInputElement::serializeForNumberType(value)); + element->setValueFromRenderer(serializeForNumberType(value)); // Also update the position if appropriate. if (position != currentPosition()) { diff --git a/WebCore/rendering/RenderTableCell.cpp b/WebCore/rendering/RenderTableCell.cpp index 4506e77..5779422 100644 --- a/WebCore/rendering/RenderTableCell.cpp +++ b/WebCore/rendering/RenderTableCell.cpp @@ -120,7 +120,7 @@ Length RenderTableCell::styleOrColWidth() const // Percentages don't need to be handled since they're always treated this way (even when specified on the cells). // See Bugzilla bug 8126 for details. if (colWidthSum.isFixed() && colWidthSum.value() > 0) - colWidthSum = Length(max(0, colWidthSum.value() - borderLeft() - borderRight() - paddingLeft() - paddingRight()), Fixed); + colWidthSum = Length(max(0, colWidthSum.value() - borderAndPaddingWidth()), Fixed); return colWidthSum; } diff --git a/WebCore/rendering/RenderText.cpp b/WebCore/rendering/RenderText.cpp index 90ad6d8..bede6a6 100644 --- a/WebCore/rendering/RenderText.cpp +++ b/WebCore/rendering/RenderText.cpp @@ -455,23 +455,40 @@ IntRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, int* e *extraWidthToEndOfLine = (box->root()->width() + rootLeft) - (left + 1); RenderBlock* cb = containingBlock(); + RenderStyle* cbStyle = cb->style(); + int leftEdge; + int rightEdge; if (style()->autoWrap()) { - int availableWidth = cb->lineWidth(top, false); - if (box->direction() == LTR) - left = min(left, rootLeft + availableWidth - caretWidthRightOfOffset); - else - left = max(left, cb->x()); + leftEdge = cb->x(); + rightEdge = cb->frameRect().right(); } else { - // If there is no wrapping, the caret can leave its containing block, but not its root line box. - if (cb->style()->direction() == LTR) { - int rightEdge = max(cb->width(), rootRight); - left = min(left, rightEdge - caretWidthRightOfOffset); - left = max(left, rootLeft); - } else { - int leftEdge = min(cb->x(), rootLeft); - left = max(left, leftEdge); - left = min(left, rootRight - caretWidth); - } + leftEdge = min(cb->x(), rootLeft); + rightEdge = max(cb->frameRect().right(), rootRight); + } + + bool rightAligned = false; + switch (cbStyle->textAlign()) { + case TAAUTO: + case JUSTIFY: + rightAligned = cbStyle->direction() == RTL; + break; + case RIGHT: + case WEBKIT_RIGHT: + rightAligned = true; + break; + case LEFT: + case WEBKIT_LEFT: + case CENTER: + case WEBKIT_CENTER: + break; + } + + if (rightAligned) { + left = max(left, leftEdge); + left = min(left, rootRight - caretWidth); + } else { + left = min(left, rightEdge - caretWidthRightOfOffset); + left = max(left, rootLeft); } return IntRect(left, top, caretWidth, height); diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp index 5e19362..1e80ff0 100644 --- a/WebCore/rendering/RenderTextControl.cpp +++ b/WebCore/rendering/RenderTextControl.cpp @@ -151,13 +151,12 @@ void RenderTextControl::createSubtreeIfNeeded(TextControlInnerElement* innerBloc int RenderTextControl::textBlockHeight() const { - return height() - paddingTop() - paddingBottom() - borderTop() - borderBottom(); + return height() - borderAndPaddingHeight(); } int RenderTextControl::textBlockWidth() const { - return width() - paddingLeft() - paddingRight() - borderLeft() - borderRight() - - m_innerText->renderBox()->paddingLeft() - m_innerText->renderBox()->paddingRight(); + return width() - borderAndPaddingWidth() - m_innerText->renderBox()->paddingLeft() - m_innerText->renderBox()->paddingRight(); } void RenderTextControl::updateFromElement() @@ -410,7 +409,7 @@ void RenderTextControl::calcHeight() m_innerText->renderBox()->marginTop() + m_innerText->renderBox()->marginBottom()); adjustControlHeightBasedOnLineHeight(m_innerText->renderer()->lineHeight(true, true)); - setHeight(height() + paddingTop() + paddingBottom() + borderTop() + borderBottom()); + setHeight(height() + borderAndPaddingHeight()); // We are able to have a horizontal scrollbar if the overflow style is scroll, or if its auto and there's no word wrap. if (style()->overflowX() == OSCROLL || (style()->overflowX() == OAUTO && m_innerText->renderer()->style()->wordWrap() == NormalWordWrap)) @@ -434,13 +433,6 @@ void RenderTextControl::forwardEvent(Event* event) m_innerText->defaultEventHandler(event); } -IntRect RenderTextControl::controlClipRect(int tx, int ty) const -{ - IntRect clipRect = contentBoxRect(); - clipRect.move(tx, ty); - return clipRect; -} - static const char* fontFamiliesWithInvalidCharWidth[] = { "American Typewriter", "Arial Hebrew", @@ -541,7 +533,7 @@ void RenderTextControl::calcPrefWidths() m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value())); } - int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight(); + int toAdd = borderAndPaddingWidth(); m_minPrefWidth += toAdd; m_maxPrefWidth += toAdd; diff --git a/WebCore/rendering/RenderTextControl.h b/WebCore/rendering/RenderTextControl.h index 2fc8edc..b76d1f2 100644 --- a/WebCore/rendering/RenderTextControl.h +++ b/WebCore/rendering/RenderTextControl.h @@ -95,8 +95,6 @@ protected: private: virtual const char* renderName() const { return "RenderTextControl"; } virtual bool isTextControl() const { return true; } - virtual bool hasControlClip() const { return false; } - virtual IntRect controlClipRect(int tx, int ty) const; virtual void calcPrefWidths(); virtual void removeLeftoverAnonymousBlock(RenderBlock*) { } virtual bool canHaveChildren() const { return false; } diff --git a/WebCore/rendering/RenderTextControlSingleLine.cpp b/WebCore/rendering/RenderTextControlSingleLine.cpp index 4edd203..37d44c4 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.cpp +++ b/WebCore/rendering/RenderTextControlSingleLine.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2010 Apple Inc. All rights reserved. * (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * * This library is free software; you can redistribute it and/or @@ -66,6 +66,9 @@ RenderTextControlSingleLine::~RenderTextControlSingleLine() if (m_innerBlock) m_innerBlock->detach(); + + if (m_outerSpinButton) + m_outerSpinButton->detach(); } RenderStyle* RenderTextControlSingleLine::textBaseStyle() const @@ -185,12 +188,27 @@ void RenderTextControlSingleLine::paint(PaintInfo& paintInfo, int tx, int ty) if (paintInfo.phase == PaintPhaseBlockBackground && m_shouldDrawCapsLockIndicator) { IntRect contentsRect = contentBoxRect(); + // Center vertically like the text. + contentsRect.setY((height() - contentsRect.height()) / 2); + // Convert the rect into the coords used for painting the content contentsRect.move(tx + x(), ty + y()); theme()->paintCapsLockIndicator(this, paintInfo, contentsRect); } } +void RenderTextControlSingleLine::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty) +{ + paintBoxDecorationsWithSize(paintInfo, tx, ty, width() - decorationWidthRight(), height()); +} + +void RenderTextControlSingleLine::addFocusRingRects(Vector<IntRect>& rects, int tx, int ty) +{ + int w = width() - decorationWidthRight(); + if (w && height()) + rects.append(IntRect(tx, ty, w, height())); +} + void RenderTextControlSingleLine::layout() { int oldHeight = height(); @@ -234,7 +252,7 @@ void RenderTextControlSingleLine::layout() innerTextRenderer->style()->setWidth(Length(desiredWidth, Fixed)); if (m_innerBlock) { - int innerBlockWidth = width() - paddingLeft() - paddingRight() - borderLeft() - borderRight(); + int innerBlockWidth = width() - borderAndPaddingWidth(); if (innerBlockWidth != innerBlockRenderer->width()) relayoutChildren = true; innerBlockRenderer->style()->setWidth(Length(innerBlockWidth, Fixed)); @@ -246,7 +264,18 @@ void RenderTextControlSingleLine::layout() RenderBox* childBlock = innerBlockRenderer ? innerBlockRenderer : innerTextRenderer; currentHeight = childBlock->height(); if (currentHeight < height()) - childBlock->setLocation(childBlock->x(), (height() - currentHeight) / 2); + childBlock->setY((height() - currentHeight) / 2); + + // Center the spin button vertically, and move it to the right by + // padding + border of the text fields. + if (RenderBox* spinBox = m_outerSpinButton ? m_outerSpinButton->renderBox() : 0) { + int diff = height() - spinBox->height(); + // If the diff is odd, the top area over the spin button takes the + // remaining one pixel. It's good for Mac NSStepper because it has + // shadow at the bottom. + int y = (diff / 2) + (diff % 2); + spinBox->setLocation(spinBox->x() + paddingRight() + borderRight(), y); + } } bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction hitTestAction) @@ -266,6 +295,9 @@ bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, Hit if (result.innerNode()->isDescendantOf(innerTextElement()) || result.innerNode() == node()) hitInnerTextElement(result, xPos, yPos, tx, ty); + // If we found a spin button, we're done. + if (m_outerSpinButton && result.innerNode() == m_outerSpinButton) + return true; // If we're not a search field, or we already found the results or cancel buttons, we're done. if (!m_innerBlock || result.innerNode() == m_resultsButton || result.innerNode() == m_cancelButton) return true; @@ -316,10 +348,13 @@ void RenderTextControlSingleLine::forwardEvent(Event* event) } FloatPoint localPoint = innerTextRenderer->absoluteToLocal(static_cast<MouseEvent*>(event)->absoluteLocation(), false, true); + int textRight = innerTextRenderer->borderBoxRect().right(); if (m_resultsButton && localPoint.x() < innerTextRenderer->borderBoxRect().x()) m_resultsButton->defaultEventHandler(event); - else if (m_cancelButton && localPoint.x() > innerTextRenderer->borderBoxRect().right()) + else if (m_cancelButton && localPoint.x() > textRight) m_cancelButton->defaultEventHandler(event); + else if (m_outerSpinButton && localPoint.x() > textRight) + m_outerSpinButton->defaultEventHandler(event); else RenderTextControl::forwardEvent(event); } @@ -342,6 +377,9 @@ void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const Ren if (RenderObject* cancelRenderer = m_cancelButton ? m_cancelButton->renderer() : 0) cancelRenderer->setStyle(createCancelButtonStyle(style())); + if (RenderObject* spinRenderer = m_outerSpinButton ? m_outerSpinButton->renderer() : 0) + spinRenderer->setStyle(createOuterSpinButtonStyle()); + setHasOverflowClip(false); } @@ -369,6 +407,16 @@ void RenderTextControlSingleLine::capsLockStateMayHaveChanged() } } +IntRect RenderTextControlSingleLine::controlClipRect(int tx, int ty) const +{ + // This should only get called for search inputs. + ASSERT(hasControlClip()); + + IntRect clipRect = IntRect(m_innerBlock->renderBox()->frameRect()); + clipRect.move(tx, ty); + return clipRect; +} + int RenderTextControlSingleLine::textBlockWidth() const { int width = RenderTextControl::textBlockWidth(); @@ -383,6 +431,18 @@ int RenderTextControlSingleLine::textBlockWidth() const width -= cancelRenderer->width() + cancelRenderer->marginLeft() + cancelRenderer->marginRight(); } + return width - decorationWidthRight(); +} + +int RenderTextControlSingleLine::decorationWidthRight() const +{ + int width = 0; + if (RenderBox* spinRenderer = m_outerSpinButton ? m_outerSpinButton->renderBox() : 0) { + spinRenderer->calcWidth(); + width += spinRenderer->width() + spinRenderer->marginLeft() + spinRenderer->marginRight(); + } + if (width > 0) + width += paddingRight() + borderRight(); return width; } @@ -432,6 +492,18 @@ int RenderTextControlSingleLine::preferredContentWidth(float charWidth) const return result; } +int RenderTextControlSingleLine::preferredDecorationWidthRight() const +{ + int width = 0; + if (RenderBox* spinRenderer = m_outerSpinButton ? m_outerSpinButton->renderBox() : 0) { + spinRenderer->calcWidth(); + width += spinRenderer->minPrefWidth() + spinRenderer->marginLeft() + spinRenderer->marginRight(); + } + if (width > 0) + width += paddingRight() + borderRight(); + return width; +} + void RenderTextControlSingleLine::adjustControlHeightBasedOnLineHeight(int lineHeight) { if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) { @@ -459,6 +531,10 @@ void RenderTextControlSingleLine::createSubtreeIfNeeded() { if (!inputElement()->isSearchField()) { RenderTextControl::createSubtreeIfNeeded(m_innerBlock.get()); + if (inputElement()->hasSpinButton() && !m_outerSpinButton) { + m_outerSpinButton = new SpinButtonElement(document(), node()); + m_outerSpinButton->attachInnerElement(node(), createOuterSpinButtonStyle(), renderArena()); + } return; } @@ -535,7 +611,7 @@ PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const if (textBlockStyle->font().lineSpacing() > lineHeight(true, true)) textBlockStyle->setLineHeight(Length(-100.0f, Percent)); - textBlockStyle->setDisplay(m_innerBlock ? INLINE_BLOCK : BLOCK); + textBlockStyle->setDisplay(m_innerBlock || inputElement()->hasSpinButton() ? INLINE_BLOCK : BLOCK); // We're adding one extra pixel of padding to match WinIE. textBlockStyle->setPaddingLeft(Length(1, Fixed)); @@ -607,6 +683,16 @@ PassRefPtr<RenderStyle> RenderTextControlSingleLine::createCancelButtonStyle(con return cancelBlockStyle.release(); } +PassRefPtr<RenderStyle> RenderTextControlSingleLine::createOuterSpinButtonStyle() const +{ + ASSERT(node()->isHTMLElement()); + RefPtr<RenderStyle> buttonStyle = getCachedPseudoStyle(OUTER_SPIN_BUTTON); + if (!buttonStyle) + buttonStyle = RenderStyle::create(); + buttonStyle->inheritFrom(style()); + return buttonStyle.release(); +} + void RenderTextControlSingleLine::updateCancelButtonVisibility() const { if (!m_cancelButton->renderer()) diff --git a/WebCore/rendering/RenderTextControlSingleLine.h b/WebCore/rendering/RenderTextControlSingleLine.h index e1bcc84..b093954 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.h +++ b/WebCore/rendering/RenderTextControlSingleLine.h @@ -32,6 +32,7 @@ class InputElement; class SearchFieldCancelButtonElement; class SearchFieldResultsButtonElement; class SearchPopupMenu; +class SpinButtonElement; class TextControlInnerElement; class RenderTextControlSingleLine : public RenderTextControl, private PopupMenuClient { @@ -53,12 +54,19 @@ public: void capsLockStateMayHaveChanged(); + // Decoration width outside of the text field. + int decorationWidthRight() const; + private: + int preferredDecorationWidthRight() const; virtual bool hasControlClip() const { return m_cancelButton; } + virtual IntRect controlClipRect(int tx, int ty) const; virtual bool isTextField() const { return true; } virtual void subtreeHasChanged(); virtual void paint(PaintInfo&, int tx, int ty); + virtual void paintBoxDecorations(PaintInfo&, int tx, int ty); + virtual void addFocusRingRects(Vector<IntRect>&, int tx, int ty); virtual void layout(); virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); @@ -89,6 +97,7 @@ private: PassRefPtr<RenderStyle> createInnerBlockStyle(const RenderStyle* startStyle) const; PassRefPtr<RenderStyle> createResultsButtonStyle(const RenderStyle* startStyle) const; PassRefPtr<RenderStyle> createCancelButtonStyle(const RenderStyle* startStyle) const; + PassRefPtr<RenderStyle> createOuterSpinButtonStyle() const; void updateCancelButtonVisibility() const; EVisibility visibilityForCancelButton() const; @@ -130,6 +139,7 @@ private: RefPtr<TextControlInnerElement> m_innerBlock; RefPtr<SearchFieldResultsButtonElement> m_resultsButton; RefPtr<SearchFieldCancelButtonElement> m_cancelButton; + RefPtr<TextControlInnerElement> m_outerSpinButton; Timer<RenderTextControlSingleLine> m_searchEventTimer; RefPtr<SearchPopupMenu> m_searchPopup; diff --git a/WebCore/rendering/RenderTheme.cpp b/WebCore/rendering/RenderTheme.cpp index b3b7a1e..76af001 100644 --- a/WebCore/rendering/RenderTheme.cpp +++ b/WebCore/rendering/RenderTheme.cpp @@ -36,6 +36,7 @@ #include "RenderView.h" #include "SelectionController.h" #include "Settings.h" +#include "TextControlInnerElements.h" // The methods in this file are shared by all themes on every platform. @@ -617,6 +618,7 @@ bool RenderTheme::isControlStyled(const RenderStyle* style, const BorderData& bo case ButtonPart: case ListboxPart: case MenulistPart: + case ProgressBarPart: // FIXME: Uncomment this when making search fields style-able. // case SearchFieldPart: case TextFieldPart: @@ -660,10 +662,16 @@ bool RenderTheme::stateChanged(RenderObject* o, ControlState state) const ControlStates RenderTheme::controlStatesForRenderer(const RenderObject* o) const { ControlStates result = 0; - if (isHovered(o)) + if (isHovered(o)) { result |= HoverState; - if (isPressed(o)) + if (isSpinUpButtonPartHovered(o)) + result |= SpinUpState; + } + if (isPressed(o)) { result |= PressedState; + if (isSpinUpButtonPartPressed(o)) + result |= SpinUpState; + } if (isFocused(o) && o->style()->outlineStyleIsAuto()) result |= FocusState; if (isEnabled(o)) @@ -747,6 +755,16 @@ bool RenderTheme::isPressed(const RenderObject* o) const return o->node()->active(); } +bool RenderTheme::isSpinUpButtonPartPressed(const RenderObject* o) const +{ + Node* node = o->node(); + if (!node || !node->active() || !node->isElementNode() + || !static_cast<Element*>(node)->isSpinButtonElement()) + return false; + SpinButtonElement* element = static_cast<SpinButtonElement*>(node); + return element->onUpButton(); +} + bool RenderTheme::isReadOnlyControl(const RenderObject* o) const { Node* node = o->node(); @@ -762,6 +780,16 @@ bool RenderTheme::isHovered(const RenderObject* o) const return o->node()->hovered(); } +bool RenderTheme::isSpinUpButtonPartHovered(const RenderObject* o) const +{ + Node* node = o->node(); + if (!node || !node->active() || !node->isElementNode() + || !static_cast<Element*>(node)->isSpinButtonElement()) + return false; + SpinButtonElement* element = static_cast<SpinButtonElement*>(node); + return element->onUpButton(); +} + bool RenderTheme::isDefault(const RenderObject* o) const { // A button should only have the default appearance if the page is active diff --git a/WebCore/rendering/RenderTheme.h b/WebCore/rendering/RenderTheme.h index 1526138..6edc878 100644 --- a/WebCore/rendering/RenderTheme.h +++ b/WebCore/rendering/RenderTheme.h @@ -292,7 +292,9 @@ public: bool isEnabled(const RenderObject*) const; bool isFocused(const RenderObject*) const; bool isPressed(const RenderObject*) const; + bool isSpinUpButtonPartPressed(const RenderObject*) const; bool isHovered(const RenderObject*) const; + bool isSpinUpButtonPartHovered(const RenderObject*) const; bool isReadOnlyControl(const RenderObject*) const; bool isDefault(const RenderObject*) const; diff --git a/WebCore/rendering/RenderThemeChromiumMac.h b/WebCore/rendering/RenderThemeChromiumMac.h index 8101038..aaaade0 100644 --- a/WebCore/rendering/RenderThemeChromiumMac.h +++ b/WebCore/rendering/RenderThemeChromiumMac.h @@ -24,173 +24,32 @@ #ifndef RenderThemeChromiumMac_h #define RenderThemeChromiumMac_h -#import "RenderTheme.h" -#import <wtf/HashMap.h> -#import <wtf/RetainPtr.h> - -#ifdef __OBJC__ -@class WebCoreRenderThemeNotificationObserver; -#else -class WebCoreRenderThemeNotificationObserver; -#endif - -// This file (and its associated .mm file) is a clone of RenderThemeMac.h. See -// the .mm file for details. +#import "RenderThemeMac.h" namespace WebCore { -class RenderStyle; - -class RenderThemeChromiumMac : public RenderTheme { +class RenderThemeChromiumMac : public RenderThemeMac { public: static PassRefPtr<RenderTheme> create(); - - // A method asking if the control changes its tint when the window has focus or not. - virtual bool controlSupportsTints(const RenderObject*) const; - - // A general method asking if any control tinting is supported at all. - virtual bool supportsControlTints() const { return true; } - - virtual void adjustRepaintRect(const RenderObject*, IntRect&); - - virtual bool isControlStyled(const RenderStyle*, const BorderData&, - const FillLayer&, const Color& backgroundColor) const; - - virtual Color platformActiveSelectionBackgroundColor() const; - virtual Color platformInactiveSelectionBackgroundColor() const; - virtual Color platformActiveListBoxSelectionBackgroundColor() const; - virtual Color platformActiveListBoxSelectionForegroundColor() const; - virtual Color platformInactiveListBoxSelectionBackgroundColor() const; - virtual Color platformInactiveListBoxSelectionForegroundColor() const; - virtual Color platformFocusRingColor() const; - - virtual ScrollbarControlSize scrollbarControlSizeForPart(ControlPart) { return SmallScrollbar; } - - virtual void platformColorsDidChange(); - - // System fonts. - virtual void systemFont(int cssValueId, FontDescription&) const; - - virtual int minimumMenuListSize(RenderStyle*) const; - - virtual void adjustSliderThumbSize(RenderObject*) const; - - virtual int popupInternalPaddingLeft(RenderStyle*) const; - virtual int popupInternalPaddingRight(RenderStyle*) const; - virtual int popupInternalPaddingTop(RenderStyle*) const; - virtual int popupInternalPaddingBottom(RenderStyle*) const; - - virtual bool paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - - virtual Color systemColor(int cssValueId) const; - protected: - virtual bool supportsSelectionForegroundColors() const { return false; } - - virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - - virtual bool paintTextArea(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - - virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - - virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - - virtual bool paintSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - - virtual bool paintSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - - virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - - virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - virtual bool paintSearchFieldCancelButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - - virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - virtual bool paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - - virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - - virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; - virtual bool paintSearchFieldResultsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - #if ENABLE(VIDEO) - virtual bool shouldRenderMediaControlPart(ControlPart, Element*); + virtual void adjustMediaSliderThumbSize(RenderObject*) const; virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual bool paintMediaVolumeSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - virtual bool paintMediaVolumeSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaControlsBackground(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - - // Media controls + virtual bool shouldRenderMediaControlPart(ControlPart, Element*); virtual String extraMediaControlsStyleSheet(); -#endif - -private: - RenderThemeChromiumMac(); - virtual ~RenderThemeChromiumMac(); - - IntRect inflateRect(const IntRect&, const IntSize&, const int* margins, float zoomLevel = 1.0f) const; - - FloatRect convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const; - - // Get the control size based off the font. Used by some of the controls (like buttons). - NSControlSize controlSizeForFont(RenderStyle*) const; - NSControlSize controlSizeForSystemFont(RenderStyle*) const; - void setControlSize(NSCell*, const IntSize* sizes, const IntSize& minSize, float zoomLevel = 1.0f); - void setSizeFromFont(RenderStyle*, const IntSize* sizes) const; - IntSize sizeForFont(RenderStyle*, const IntSize* sizes) const; - IntSize sizeForSystemFont(RenderStyle*, const IntSize* sizes) const; - void setFontFromControlSize(CSSStyleSelector*, RenderStyle*, NSControlSize) const; - void updateActiveState(NSCell*, const RenderObject*); - void updateCheckedState(NSCell*, const RenderObject*); - void updateEnabledState(NSCell*, const RenderObject*); - void updateFocusedState(NSCell*, const RenderObject*); - void updatePressedState(NSCell*, const RenderObject*); - - // Helpers for adjusting appearance and for painting - - void setPopupButtonCellState(const RenderObject*, const IntRect&); - const IntSize* popupButtonSizes() const; - const int* popupButtonMargins() const; - const int* popupButtonPadding(NSControlSize) const; - void paintMenuListButtonGradients(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - const IntSize* menuListSizes() const; + virtual bool paintMediaVolumeSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintMediaVolumeSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - const IntSize* searchFieldSizes() const; - const IntSize* cancelButtonSizes() const; - const IntSize* resultsButtonSizes() const; - void setSearchCellState(RenderObject*, const IntRect&); - void setSearchFieldSize(RenderStyle*) const; - - NSPopUpButtonCell* popupButton() const; - NSSearchFieldCell* search() const; - NSMenu* searchMenuTemplate() const; - NSSliderCell* sliderThumbHorizontal() const; - NSSliderCell* sliderThumbVertical() const; +#endif + virtual bool usesTestModeFocusRingColor() const; + virtual NSView* documentViewFor(RenderObject*) const; private: - mutable RetainPtr<NSPopUpButtonCell> m_popupButton; - mutable RetainPtr<NSSearchFieldCell> m_search; - mutable RetainPtr<NSMenu> m_searchMenuTemplate; - mutable RetainPtr<NSSliderCell> m_sliderThumbHorizontal; - mutable RetainPtr<NSSliderCell> m_sliderThumbVertical; - - bool m_isSliderThumbHorizontalPressed; - bool m_isSliderThumbVerticalPressed; - - mutable HashMap<int, RGBA32> m_systemColorCache; - - RetainPtr<WebCoreRenderThemeNotificationObserver> m_notificationObserver; + virtual void updateActiveState(NSCell*, const RenderObject*); }; } // namespace WebCore diff --git a/WebCore/rendering/RenderThemeChromiumMac.mm b/WebCore/rendering/RenderThemeChromiumMac.mm index 03aab1c..47a872d 100644 --- a/WebCore/rendering/RenderThemeChromiumMac.mm +++ b/WebCore/rendering/RenderThemeChromiumMac.mm @@ -20,29 +20,8 @@ #import "config.h" #import "RenderThemeChromiumMac.h" - -#import "BitmapImage.h" #import "ChromiumBridge.h" -#import "ColorMac.h" -#import "CSSStyleSelector.h" -#import "CSSValueKeywords.h" -#import "Document.h" -#import "Element.h" -#import "FrameView.h" -#import "GraphicsContext.h" -#import "HTMLInputElement.h" -#import "HTMLMediaElement.h" -#import "HTMLNames.h" -#import "Image.h" -#import "LocalCurrentGraphicsContext.h" -#import "MediaControlElements.h" -#import "RenderMedia.h" #import "RenderMediaControlsChromium.h" -#import "RenderSlider.h" -#import "RenderView.h" -#import "SharedBuffer.h" -#import "TimeRanges.h" -#import "WebCoreSystemInterface.h" #import "UserAgentStyleSheets.h" #import <Carbon/Carbon.h> #import <Cocoa/Cocoa.h> @@ -50,64 +29,6 @@ #import <wtf/StdLibExtras.h> #import <math.h> -#ifdef BUILDING_ON_TIGER -typedef int NSInteger; -typedef unsigned NSUInteger; -#endif - -using std::min; - -// This file (and its associated .h file) is a clone of RenderThemeMac.mm. -// Because the original file is designed to run in-process inside a Cocoa view, -// we must maintain a fork. Please maintain this file by performing parallel -// changes to it. -// -// The only changes from RenderThemeMac should be: -// - The classname change from RenderThemeMac to RenderThemeChromiumMac. -// - The introduction of RTCMFlippedView and FlippedView() and its use as the -// parent view for cell rendering. -// - In platformFocusRingColor(), the use of ChromiumBridge to determine if -// we're in layout test mode. -// - updateActiveState() and its use to update the cells' visual appearance. -// - All the paintMedia*() functions and extraMediaControlsStyleSheet() -// are forked from RenderThemeChromiumSkia instead of RenderThemeMac. -// -// For all other differences, if it was introduced in this file, then the -// maintainer forgot to include it in the list; otherwise it is an update that -// should have been applied to this file but was not. - -// The methods in this file are specific to the Mac OS X platform. - -// FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeSafari. - -@interface WebCoreRenderThemeNotificationObserver : NSObject -{ - WebCore::RenderTheme *_theme; -} - -- (id)initWithTheme:(WebCore::RenderTheme *)theme; -- (void)systemColorsDidChange:(NSNotification *)notification; - -@end - -@implementation WebCoreRenderThemeNotificationObserver - -- (id)initWithTheme:(WebCore::RenderTheme *)theme -{ - [super init]; - _theme = theme; - - return self; -} - -- (void)systemColorsDidChange:(NSNotification *)unusedNotification -{ - ASSERT_UNUSED(unusedNotification, [[unusedNotification name] isEqualToString:NSSystemColorsDidChangeNotification]); - _theme->platformColorsDidChange(); -} - -@end - @interface RTCMFlippedView : NSView {} @@ -130,26 +51,6 @@ using std::min; namespace WebCore { -using namespace HTMLNames; - -enum { - topMargin, - rightMargin, - bottomMargin, - leftMargin -}; - -enum { - topPadding, - rightPadding, - bottomPadding, - leftPadding -}; - -// In Snow Leopard, many cells only check to see if the view they're passed is -// flipped, and if a nil view is passed, neglect to check if the current -// graphics context is flipped. Thus we pass a sham view to them, one whose -// flipped state just reflects the state of the context. NSView* FlippedView() { static NSView* view = [[RTCMFlippedView alloc] init]; @@ -167,422 +68,14 @@ PassRefPtr<RenderTheme> RenderThemeChromiumMac::create() return adoptRef(new RenderThemeChromiumMac); } -RenderThemeChromiumMac::RenderThemeChromiumMac() - : m_isSliderThumbHorizontalPressed(false) - , m_isSliderThumbVerticalPressed(false) - , m_notificationObserver(AdoptNS, [[WebCoreRenderThemeNotificationObserver alloc] initWithTheme:this]) +bool RenderThemeChromiumMac::usesTestModeFocusRingColor() const { - [[NSNotificationCenter defaultCenter] addObserver:m_notificationObserver.get() - selector:@selector(systemColorsDidChange:) - name:NSSystemColorsDidChangeNotification - object:nil]; + return ChromiumBridge::layoutTestMode(); } -RenderThemeChromiumMac::~RenderThemeChromiumMac() +NSView* RenderThemeChromiumMac::documentViewFor(RenderObject*) const { - [[NSNotificationCenter defaultCenter] removeObserver:m_notificationObserver.get()]; -} - -Color RenderThemeChromiumMac::platformActiveSelectionBackgroundColor() const -{ - NSColor* color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace]; - return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent])); -} - -Color RenderThemeChromiumMac::platformInactiveSelectionBackgroundColor() const -{ - NSColor* color = [[NSColor secondarySelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace]; - return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent])); -} - -Color RenderThemeChromiumMac::platformActiveListBoxSelectionBackgroundColor() const -{ - NSColor* color = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace]; - return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent])); -} - -Color RenderThemeChromiumMac::platformActiveListBoxSelectionForegroundColor() const -{ - return Color::white; -} - -Color RenderThemeChromiumMac::platformInactiveListBoxSelectionForegroundColor() const -{ - return Color::black; -} - -Color RenderThemeChromiumMac::platformFocusRingColor() const -{ - if (ChromiumBridge::layoutTestMode()) - return oldAquaFocusRingColor(); - - return systemColor(CSSValueWebkitFocusRingColor); -} - -Color RenderThemeChromiumMac::platformInactiveListBoxSelectionBackgroundColor() const -{ - return platformInactiveSelectionBackgroundColor(); -} - -static FontWeight toFontWeight(NSInteger appKitFontWeight) -{ - ASSERT(appKitFontWeight > 0 && appKitFontWeight < 15); - if (appKitFontWeight > 14) - appKitFontWeight = 14; - else if (appKitFontWeight < 1) - appKitFontWeight = 1; - - static FontWeight fontWeights[] = { - FontWeight100, - FontWeight100, - FontWeight200, - FontWeight300, - FontWeight400, - FontWeight500, - FontWeight600, - FontWeight600, - FontWeight700, - FontWeight800, - FontWeight800, - FontWeight900, - FontWeight900, - FontWeight900 - }; - return fontWeights[appKitFontWeight - 1]; -} - -void RenderThemeChromiumMac::systemFont(int cssValueId, FontDescription& fontDescription) const -{ - DEFINE_STATIC_LOCAL(FontDescription, systemFont, ()); - DEFINE_STATIC_LOCAL(FontDescription, smallSystemFont, ()); - DEFINE_STATIC_LOCAL(FontDescription, menuFont, ()); - DEFINE_STATIC_LOCAL(FontDescription, labelFont, ()); - DEFINE_STATIC_LOCAL(FontDescription, miniControlFont, ()); - DEFINE_STATIC_LOCAL(FontDescription, smallControlFont, ()); - DEFINE_STATIC_LOCAL(FontDescription, controlFont, ()); - - FontDescription* cachedDesc; - NSFont* font = nil; - switch (cssValueId) { - case CSSValueSmallCaption: - cachedDesc = &smallSystemFont; - if (!smallSystemFont.isAbsoluteSize()) - font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]; - break; - case CSSValueMenu: - cachedDesc = &menuFont; - if (!menuFont.isAbsoluteSize()) - font = [NSFont menuFontOfSize:[NSFont systemFontSize]]; - break; - case CSSValueStatusBar: - cachedDesc = &labelFont; - if (!labelFont.isAbsoluteSize()) - font = [NSFont labelFontOfSize:[NSFont labelFontSize]]; - break; - case CSSValueWebkitMiniControl: - cachedDesc = &miniControlFont; - if (!miniControlFont.isAbsoluteSize()) - font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]]; - break; - case CSSValueWebkitSmallControl: - cachedDesc = &smallControlFont; - if (!smallControlFont.isAbsoluteSize()) - font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]; - break; - case CSSValueWebkitControl: - cachedDesc = &controlFont; - if (!controlFont.isAbsoluteSize()) - font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]; - break; - default: - cachedDesc = &systemFont; - if (!systemFont.isAbsoluteSize()) - font = [NSFont systemFontOfSize:[NSFont systemFontSize]]; - } - - if (font) { - NSFontManager *fontManager = [NSFontManager sharedFontManager]; - cachedDesc->setIsAbsoluteSize(true); - cachedDesc->setGenericFamily(FontDescription::NoFamily); - cachedDesc->firstFamily().setFamily([font familyName]); - cachedDesc->setSpecifiedSize([font pointSize]); - cachedDesc->setWeight(toFontWeight([fontManager weightOfFont:font])); - cachedDesc->setItalic([fontManager traitsOfFont:font] & NSItalicFontMask); - } - fontDescription = *cachedDesc; -} - -static RGBA32 convertNSColorToColor(NSColor *color) -{ - NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace]; - if (colorInColorSpace) { - static const double scaleFactor = nextafter(256.0, 0.0); - return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]), - static_cast<int>(scaleFactor * [colorInColorSpace greenComponent]), - static_cast<int>(scaleFactor * [colorInColorSpace blueComponent])); - } - - // This conversion above can fail if the NSColor in question is an NSPatternColor - // (as many system colors are). These colors are actually a repeating pattern - // not just a solid color. To work around this we simply draw a 1x1 image of - // the color and use that pixel's color. It might be better to use an average of - // the colors in the pattern instead. - NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil - pixelsWide:1 - pixelsHigh:1 - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bytesPerRow:4 - bitsPerPixel:32]; - - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]]; - NSEraseRect(NSMakeRect(0, 0, 1, 1)); - [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)]; - [NSGraphicsContext restoreGraphicsState]; - - NSUInteger pixel[4]; - [offscreenRep getPixel:pixel atX:0 y:0]; - - [offscreenRep release]; - - return makeRGB(pixel[0], pixel[1], pixel[2]); -} - -static RGBA32 menuBackgroundColor() -{ - NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil - pixelsWide:1 - pixelsHigh:1 - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bytesPerRow:4 - bitsPerPixel:32]; - - CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep] graphicsPort]); - CGRect rect = CGRectMake(0, 0, 1, 1); - HIThemeMenuDrawInfo drawInfo; - drawInfo.version = 0; - drawInfo.menuType = kThemeMenuTypePopUp; - HIThemeDrawMenuBackground(&rect, &drawInfo, context, kHIThemeOrientationInverted); - - NSUInteger pixel[4]; - [offscreenRep getPixel:pixel atX:0 y:0]; - - [offscreenRep release]; - - return makeRGB(pixel[0], pixel[1], pixel[2]); -} - -void RenderThemeChromiumMac::platformColorsDidChange() -{ - m_systemColorCache.clear(); - RenderTheme::platformColorsDidChange(); -} - -Color RenderThemeChromiumMac::systemColor(int cssValueId) const -{ - if (m_systemColorCache.contains(cssValueId)) - return m_systemColorCache.get(cssValueId); - - Color color; - switch (cssValueId) { - case CSSValueActiveborder: - color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]); - break; - case CSSValueActivecaption: - color = convertNSColorToColor([NSColor windowFrameTextColor]); - break; - case CSSValueAppworkspace: - color = convertNSColorToColor([NSColor headerColor]); - break; - case CSSValueBackground: - // Use theme independent default - break; - case CSSValueButtonface: - // We use this value instead of NSColor's controlColor to avoid website incompatibilities. - // We may want to change this to use the NSColor in future. - color = 0xFFC0C0C0; - break; - case CSSValueButtonhighlight: - color = convertNSColorToColor([NSColor controlHighlightColor]); - break; - case CSSValueButtonshadow: - color = convertNSColorToColor([NSColor controlShadowColor]); - break; - case CSSValueButtontext: - color = convertNSColorToColor([NSColor controlTextColor]); - break; - case CSSValueCaptiontext: - color = convertNSColorToColor([NSColor textColor]); - break; - case CSSValueGraytext: - color = convertNSColorToColor([NSColor disabledControlTextColor]); - break; - case CSSValueHighlight: - color = convertNSColorToColor([NSColor selectedTextBackgroundColor]); - break; - case CSSValueHighlighttext: - color = convertNSColorToColor([NSColor selectedTextColor]); - break; - case CSSValueInactiveborder: - color = convertNSColorToColor([NSColor controlBackgroundColor]); - break; - case CSSValueInactivecaption: - color = convertNSColorToColor([NSColor controlBackgroundColor]); - break; - case CSSValueInactivecaptiontext: - color = convertNSColorToColor([NSColor textColor]); - break; - case CSSValueInfobackground: - // There is no corresponding NSColor for this so we use a hard coded value. - color = 0xFFFBFCC5; - break; - case CSSValueInfotext: - color = convertNSColorToColor([NSColor textColor]); - break; - case CSSValueMenu: - color = menuBackgroundColor(); - break; - case CSSValueMenutext: - color = convertNSColorToColor([NSColor selectedMenuItemTextColor]); - break; - case CSSValueScrollbar: - color = convertNSColorToColor([NSColor scrollBarColor]); - break; - case CSSValueText: - color = convertNSColorToColor([NSColor textColor]); - break; - case CSSValueThreeddarkshadow: - color = convertNSColorToColor([NSColor controlDarkShadowColor]); - break; - case CSSValueThreedshadow: - color = convertNSColorToColor([NSColor shadowColor]); - break; - case CSSValueThreedface: - // We use this value instead of NSColor's controlColor to avoid website incompatibilities. - // We may want to change this to use the NSColor in future. - color = 0xFFC0C0C0; - break; - case CSSValueThreedhighlight: - color = convertNSColorToColor([NSColor highlightColor]); - break; - case CSSValueThreedlightshadow: - color = convertNSColorToColor([NSColor controlLightHighlightColor]); - break; - case CSSValueWebkitFocusRingColor: - color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]); - break; - case CSSValueWindow: - color = convertNSColorToColor([NSColor windowBackgroundColor]); - break; - case CSSValueWindowframe: - color = convertNSColorToColor([NSColor windowFrameColor]); - break; - case CSSValueWindowtext: - color = convertNSColorToColor([NSColor windowFrameTextColor]); - break; - } - - if (!color.isValid()) - color = RenderTheme::systemColor(cssValueId); - - if (color.isValid()) - m_systemColorCache.set(cssValueId, color.rgb()); - - return color; -} - -bool RenderThemeChromiumMac::isControlStyled(const RenderStyle* style, const BorderData& border, - const FillLayer& background, const Color& backgroundColor) const -{ - if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart) - return style->border() != border; - - // FIXME: This is horrible, but there is not much else that can be done. Menu lists cannot draw properly when - // scaled. They can't really draw properly when transformed either. We can't detect the transform case at style - // adjustment time so that will just have to stay broken. We can however detect that we're zooming. If zooming - // is in effect we treat it like the control is styled. - if (style->appearance() == MenulistPart && style->effectiveZoom() != 1.0f) - return true; - - return RenderTheme::isControlStyled(style, border, background, backgroundColor); -} - -void RenderThemeChromiumMac::adjustRepaintRect(const RenderObject* o, IntRect& r) -{ - ControlPart part = o->style()->appearance(); - -#if USE(NEW_THEME) - switch (part) { - case CheckboxPart: - case RadioPart: - case PushButtonPart: - case SquareButtonPart: - case ListButtonPart: - case DefaultButtonPart: - case ButtonPart: - return RenderTheme::adjustRepaintRect(o, r); - default: - break; - } -#endif - - float zoomLevel = o->style()->effectiveZoom(); - - if (part == MenulistPart) { - setPopupButtonCellState(o, r); - IntSize size = popupButtonSizes()[[popupButton() controlSize]]; - size.setHeight(size.height() * zoomLevel); - size.setWidth(r.width()); - r = inflateRect(r, size, popupButtonMargins(), zoomLevel); - } -} - -IntRect RenderThemeChromiumMac::inflateRect(const IntRect& r, const IntSize& size, const int* margins, float zoomLevel) const -{ - // Only do the inflation if the available width/height are too small. Otherwise try to - // fit the glow/check space into the available box's width/height. - int widthDelta = r.width() - (size.width() + margins[leftMargin] * zoomLevel + margins[rightMargin] * zoomLevel); - int heightDelta = r.height() - (size.height() + margins[topMargin] * zoomLevel + margins[bottomMargin] * zoomLevel); - IntRect result(r); - if (widthDelta < 0) { - result.setX(result.x() - margins[leftMargin] * zoomLevel); - result.setWidth(result.width() - widthDelta); - } - if (heightDelta < 0) { - result.setY(result.y() - margins[topMargin] * zoomLevel); - result.setHeight(result.height() - heightDelta); - } - return result; -} - -FloatRect RenderThemeChromiumMac::convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const -{ - FloatRect partRect(inputRect); - - // Compute an offset between the part renderer and the input renderer - FloatSize offsetFromInputRenderer; - const RenderObject* renderer = partRenderer; - while (renderer && renderer != inputRenderer) { - RenderObject* containingRenderer = renderer->container(); - offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer, IntPoint()); - renderer = containingRenderer; - } - // If the input renderer was not a container, something went wrong - ASSERT(renderer == inputRenderer); - // Move the rect into partRenderer's coords - partRect.move(offsetFromInputRenderer); - // Account for the local drawing offset (tx, ty) - partRect.move(r.x(), r.y()); - - return partRect; + return FlippedView(); } // Updates the control tint (a.k.a. active state) of |cell| (from |o|). @@ -604,917 +97,13 @@ void RenderThemeChromiumMac::updateActiveState(NSCell* cell, const RenderObject* [cell setControlTint:tint]; } -void RenderThemeChromiumMac::updateCheckedState(NSCell* cell, const RenderObject* o) -{ - bool oldIndeterminate = [cell state] == NSMixedState; - bool indeterminate = isIndeterminate(o); - bool checked = isChecked(o); - - if (oldIndeterminate != indeterminate) { - [cell setState:indeterminate ? NSMixedState : (checked ? NSOnState : NSOffState)]; - return; - } - - bool oldChecked = [cell state] == NSOnState; - if (checked != oldChecked) - [cell setState:checked ? NSOnState : NSOffState]; -} - -void RenderThemeChromiumMac::updateEnabledState(NSCell* cell, const RenderObject* o) -{ - bool oldEnabled = [cell isEnabled]; - bool enabled = isEnabled(o); - if (enabled != oldEnabled) - [cell setEnabled:enabled]; -} - -void RenderThemeChromiumMac::updateFocusedState(NSCell* cell, const RenderObject* o) -{ - bool oldFocused = [cell showsFirstResponder]; - bool focused = isFocused(o) && o->style()->outlineStyleIsAuto(); - if (focused != oldFocused) - [cell setShowsFirstResponder:focused]; -} - -void RenderThemeChromiumMac::updatePressedState(NSCell* cell, const RenderObject* o) -{ - bool oldPressed = [cell isHighlighted]; - bool pressed = (o->node() && o->node()->active()); - if (pressed != oldPressed) - [cell setHighlighted:pressed]; -} - -bool RenderThemeChromiumMac::controlSupportsTints(const RenderObject* o) const -{ - // An alternate way to implement this would be to get the appropriate cell object - // and call the private _needRedrawOnWindowChangedKeyState method. An advantage of - // that would be that we would match AppKit behavior more closely, but a disadvantage - // would be that we would rely on an AppKit SPI method. - - if (!isEnabled(o)) - return false; - - // Checkboxes only have tint when checked. - if (o->style()->appearance() == CheckboxPart) - return isChecked(o); - - // For now assume other controls have tint if enabled. - return true; -} - -NSControlSize RenderThemeChromiumMac::controlSizeForFont(RenderStyle* style) const -{ - int fontSize = style->fontSize(); - if (fontSize >= 16) - return NSRegularControlSize; - if (fontSize >= 11) - return NSSmallControlSize; - return NSMiniControlSize; -} - -void RenderThemeChromiumMac::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize, float zoomLevel) -{ - NSControlSize size; - if (minSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomLevel) && - minSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomLevel)) - size = NSRegularControlSize; - else if (minSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomLevel) && - minSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomLevel)) - size = NSSmallControlSize; - else - size = NSMiniControlSize; - if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same. - [cell setControlSize:size]; -} - -IntSize RenderThemeChromiumMac::sizeForFont(RenderStyle* style, const IntSize* sizes) const -{ - if (style->effectiveZoom() != 1.0f) { - IntSize result = sizes[controlSizeForFont(style)]; - return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom()); - } - return sizes[controlSizeForFont(style)]; -} - -IntSize RenderThemeChromiumMac::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const -{ - if (style->effectiveZoom() != 1.0f) { - IntSize result = sizes[controlSizeForSystemFont(style)]; - return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom()); - } - return sizes[controlSizeForSystemFont(style)]; -} - -void RenderThemeChromiumMac::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const -{ - // FIXME: Check is flawed, since it doesn't take min-width/max-width into account. - IntSize size = sizeForFont(style, sizes); - if (style->width().isIntrinsicOrAuto() && size.width() > 0) - style->setWidth(Length(size.width(), Fixed)); - if (style->height().isAuto() && size.height() > 0) - style->setHeight(Length(size.height(), Fixed)); -} - -void RenderThemeChromiumMac::setFontFromControlSize(CSSStyleSelector*, RenderStyle* style, NSControlSize controlSize) const -{ - FontDescription fontDescription; - fontDescription.setIsAbsoluteSize(true); - fontDescription.setGenericFamily(FontDescription::SerifFamily); - - NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:controlSize]]; - fontDescription.firstFamily().setFamily([font familyName]); - fontDescription.setComputedSize([font pointSize] * style->effectiveZoom()); - fontDescription.setSpecifiedSize([font pointSize] * style->effectiveZoom()); - - // Reset line height - style->setLineHeight(RenderStyle::initialLineHeight()); - - if (style->setFontDescription(fontDescription)) - style->font().update(0); -} - -NSControlSize RenderThemeChromiumMac::controlSizeForSystemFont(RenderStyle* style) const -{ - int fontSize = style->fontSize(); - if (fontSize >= [NSFont systemFontSizeForControlSize:NSRegularControlSize]) - return NSRegularControlSize; - if (fontSize >= [NSFont systemFontSizeForControlSize:NSSmallControlSize]) - return NSSmallControlSize; - return NSMiniControlSize; -} - -bool RenderThemeChromiumMac::paintTextField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) -{ - LocalCurrentGraphicsContext localContext(paintInfo.context); - wkDrawBezeledTextFieldCell(r, isEnabled(o) && !isReadOnlyControl(o)); - return false; -} - -void RenderThemeChromiumMac::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const -{ -} - -bool RenderThemeChromiumMac::paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo& paintInfo, const IntRect& r) -{ - if (paintInfo.context->paintingDisabled()) - return true; - - LocalCurrentGraphicsContext localContext(paintInfo.context); - wkDrawCapsLockIndicator(paintInfo.context->platformContext(), r); - - return false; -} - -bool RenderThemeChromiumMac::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) -{ - LocalCurrentGraphicsContext localContext(paintInfo.context); - wkDrawBezeledTextArea(r, isEnabled(o) && !isReadOnlyControl(o)); - return false; -} - -void RenderThemeChromiumMac::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const -{ -} - -const int* RenderThemeChromiumMac::popupButtonMargins() const -{ - static const int margins[3][4] = - { - { 0, 3, 1, 3 }, - { 0, 3, 2, 3 }, - { 0, 1, 0, 1 } - }; - return margins[[popupButton() controlSize]]; -} - -const IntSize* RenderThemeChromiumMac::popupButtonSizes() const -{ - static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) }; - return sizes; -} - -const int* RenderThemeChromiumMac::popupButtonPadding(NSControlSize size) const -{ - static const int padding[3][4] = - { - { 2, 26, 3, 8 }, - { 2, 23, 3, 8 }, - { 2, 22, 3, 10 } - }; - return padding[size]; -} - -bool RenderThemeChromiumMac::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) -{ - setPopupButtonCellState(o, r); - - NSPopUpButtonCell* popupButton = this->popupButton(); - - float zoomLevel = o->style()->effectiveZoom(); - IntSize size = popupButtonSizes()[[popupButton controlSize]]; - size.setHeight(size.height() * zoomLevel); - size.setWidth(r.width()); - - // Now inflate it to account for the shadow. - IntRect inflatedRect = r; - if (r.width() >= minimumMenuListSize(o->style())) - inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(), zoomLevel); - - paintInfo.context->save(); - -#ifndef BUILDING_ON_TIGER - // On Leopard, the cell will draw outside of the given rect, so we have to clip to the rect - paintInfo.context->clip(inflatedRect); -#endif - - if (zoomLevel != 1.0f) { - inflatedRect.setWidth(inflatedRect.width() / zoomLevel); - inflatedRect.setHeight(inflatedRect.height() / zoomLevel); - paintInfo.context->translate(inflatedRect.x(), inflatedRect.y()); - paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel)); - paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y()); - } - - [popupButton drawWithFrame:inflatedRect inView:FlippedView()]; - [popupButton setControlView:nil]; - - paintInfo.context->restore(); - - return false; -} - -const float baseFontSize = 11.0f; -const float baseArrowHeight = 4.0f; -const float baseArrowWidth = 5.0f; -const float baseSpaceBetweenArrows = 2.0f; -const int arrowPaddingLeft = 6; -const int arrowPaddingRight = 6; -const int paddingBeforeSeparator = 4; -const int baseBorderRadius = 5; -const int styledPopupPaddingLeft = 8; -const int styledPopupPaddingTop = 1; -const int styledPopupPaddingBottom = 2; - -static void TopGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData) -{ - static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f }; - static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f }; - float a = inData[0]; - int i = 0; - for (i = 0; i < 4; i++) - outData[i] = (1.0f - a) * dark[i] + a * light[i]; -} - -static void BottomGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData) -{ - static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f }; - static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f }; - float a = inData[0]; - int i = 0; - for (i = 0; i < 4; i++) - outData[i] = (1.0f - a) * dark[i] + a * light[i]; -} - -static void MainGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData) -{ - static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f }; - static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - float a = inData[0]; - int i = 0; - for (i = 0; i < 4; i++) - outData[i] = (1.0f - a) * dark[i] + a * light[i]; -} - -static void TrackGradientInterpolate(void*, const CGFloat* inData, CGFloat* outData) -{ - static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f }; - static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f }; - float a = inData[0]; - int i = 0; - for (i = 0; i < 4; i++) - outData[i] = (1.0f - a) * dark[i] + a * light[i]; -} - -void RenderThemeChromiumMac::paintMenuListButtonGradients(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) -{ - if (r.isEmpty()) - return; - - CGContextRef context = paintInfo.context->platformContext(); - - paintInfo.context->save(); - - IntSize topLeftRadius; - IntSize topRightRadius; - IntSize bottomLeftRadius; - IntSize bottomRightRadius; - - o->style()->getBorderRadiiForRect(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); - - int radius = topLeftRadius.width(); - - RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB()); - - FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f); - struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL }; - RetainPtr<CGFunctionRef> topFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks)); - RetainPtr<CGShadingRef> topShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.bottom()), topFunction.get(), false, false)); - - FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f); - struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL }; - RetainPtr<CGFunctionRef> bottomFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks)); - RetainPtr<CGShadingRef> bottomShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(bottomGradient.x(), bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.bottom()), bottomFunction.get(), false, false)); - - struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL }; - RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks)); - RetainPtr<CGShadingRef> mainShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(), r.y()), CGPointMake(r.x(), r.bottom()), mainFunction.get(), false, false)); - - RetainPtr<CGShadingRef> leftShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(), r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false)); - - RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.right(), r.y()), CGPointMake(r.right() - radius, r.y()), mainFunction.get(), false, false)); - paintInfo.context->save(); - CGContextClipToRect(context, r); - paintInfo.context->addRoundedRectClip(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); - CGContextDrawShading(context, mainShading.get()); - paintInfo.context->restore(); - - paintInfo.context->save(); - CGContextClipToRect(context, topGradient); - paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient), topLeftRadius, topRightRadius, IntSize(), IntSize()); - CGContextDrawShading(context, topShading.get()); - paintInfo.context->restore(); - - if (!bottomGradient.isEmpty()) { - paintInfo.context->save(); - CGContextClipToRect(context, bottomGradient); - paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient), IntSize(), IntSize(), bottomLeftRadius, bottomRightRadius); - CGContextDrawShading(context, bottomShading.get()); - paintInfo.context->restore(); - } - - paintInfo.context->save(); - CGContextClipToRect(context, r); - paintInfo.context->addRoundedRectClip(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius); - CGContextDrawShading(context, leftShading.get()); - CGContextDrawShading(context, rightShading.get()); - paintInfo.context->restore(); - - paintInfo.context->restore(); -} - -bool RenderThemeChromiumMac::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) -{ - IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(), - r.y() + o->style()->borderTopWidth(), - r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(), - r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth()); - // Draw the gradients to give the styled popup menu a button appearance - paintMenuListButtonGradients(o, paintInfo, bounds); - - // Since we actually know the size of the control here, we restrict the font scale to make sure the arrows will fit vertically in the bounds - float fontScale = min(o->style()->fontSize() / baseFontSize, bounds.height() / (baseArrowHeight * 2 + baseSpaceBetweenArrows)); - float centerY = bounds.y() + bounds.height() / 2.0f; - float arrowHeight = baseArrowHeight * fontScale; - float arrowWidth = baseArrowWidth * fontScale; - float leftEdge = bounds.right() - arrowPaddingRight * o->style()->effectiveZoom() - arrowWidth; - float spaceBetweenArrows = baseSpaceBetweenArrows * fontScale; - - if (bounds.width() < arrowWidth + arrowPaddingLeft * o->style()->effectiveZoom()) - return false; - - paintInfo.context->save(); - - paintInfo.context->setFillColor(o->style()->color(), o->style()->colorSpace()); - paintInfo.context->setStrokeStyle(NoStroke); - - FloatPoint arrow1[3]; - arrow1[0] = FloatPoint(leftEdge, centerY - spaceBetweenArrows / 2.0f); - arrow1[1] = FloatPoint(leftEdge + arrowWidth, centerY - spaceBetweenArrows / 2.0f); - arrow1[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY - spaceBetweenArrows / 2.0f - arrowHeight); - - // Draw the top arrow - paintInfo.context->drawConvexPolygon(3, arrow1, true); - - FloatPoint arrow2[3]; - arrow2[0] = FloatPoint(leftEdge, centerY + spaceBetweenArrows / 2.0f); - arrow2[1] = FloatPoint(leftEdge + arrowWidth, centerY + spaceBetweenArrows / 2.0f); - arrow2[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + spaceBetweenArrows / 2.0f + arrowHeight); - - // Draw the bottom arrow - paintInfo.context->drawConvexPolygon(3, arrow2, true); - - Color leftSeparatorColor(0, 0, 0, 40); - Color rightSeparatorColor(255, 255, 255, 40); - - // FIXME: Should the separator thickness and space be scaled up by fontScale? - int separatorSpace = 2; // Deliberately ignores zoom since it looks nicer if it stays thin. - int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft * o->style()->effectiveZoom()); // FIXME: Round? - - // Draw the separator to the left of the arrows - paintInfo.context->setStrokeThickness(1.0f); // Deliberately ignores zoom since it looks nicer if it stays thin. - paintInfo.context->setStrokeStyle(SolidStroke); - paintInfo.context->setStrokeColor(leftSeparatorColor, DeviceColorSpace); - paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()), - IntPoint(leftEdgeOfSeparator, bounds.bottom())); - - paintInfo.context->setStrokeColor(rightSeparatorColor, DeviceColorSpace); - paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()), - IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.bottom())); - - paintInfo.context->restore(); - return false; -} - -static const IntSize* menuListButtonSizes() -{ - static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) }; - return sizes; -} - -void RenderThemeChromiumMac::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const -{ - NSControlSize controlSize = controlSizeForFont(style); - - style->resetBorder(); - style->resetPadding(); - - // Height is locked to auto. - style->setHeight(Length(Auto)); - - // White-space is locked to pre - style->setWhiteSpace(PRE); - - // Set the foreground color to black or gray when we have the aqua look. - // Cast to RGB32 is to work around a compiler bug. - style->setColor(e && e->isEnabledFormControl() ? static_cast<RGBA32>(Color::black) : Color::darkGray); - - // Set the button's vertical size. - setSizeFromFont(style, menuListButtonSizes()); - - // Our font is locked to the appropriate system font size for the control. To clarify, we first use the CSS-specified font to figure out - // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate - // system font for the control size instead. - setFontFromControlSize(selector, style, controlSize); - - style->setBoxShadow(0); -} - -int RenderThemeChromiumMac::popupInternalPaddingLeft(RenderStyle* style) const -{ - if (style->appearance() == MenulistPart) - return popupButtonPadding(controlSizeForFont(style))[leftPadding] * style->effectiveZoom(); - if (style->appearance() == MenulistButtonPart) - return styledPopupPaddingLeft * style->effectiveZoom(); - return 0; -} - -int RenderThemeChromiumMac::popupInternalPaddingRight(RenderStyle* style) const -{ - if (style->appearance() == MenulistPart) - return popupButtonPadding(controlSizeForFont(style))[rightPadding] * style->effectiveZoom(); - if (style->appearance() == MenulistButtonPart) { - float fontScale = style->fontSize() / baseFontSize; - float arrowWidth = baseArrowWidth * fontScale; - return static_cast<int>(ceilf(arrowWidth + (arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator) * style->effectiveZoom())); - } - return 0; -} - -int RenderThemeChromiumMac::popupInternalPaddingTop(RenderStyle* style) const -{ - if (style->appearance() == MenulistPart) - return popupButtonPadding(controlSizeForFont(style))[topPadding] * style->effectiveZoom(); - if (style->appearance() == MenulistButtonPart) - return styledPopupPaddingTop * style->effectiveZoom(); - return 0; -} - -int RenderThemeChromiumMac::popupInternalPaddingBottom(RenderStyle* style) const -{ - if (style->appearance() == MenulistPart) - return popupButtonPadding(controlSizeForFont(style))[bottomPadding] * style->effectiveZoom(); - if (style->appearance() == MenulistButtonPart) - return styledPopupPaddingBottom * style->effectiveZoom(); - return 0; -} - -void RenderThemeChromiumMac::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const -{ - float fontScale = style->fontSize() / baseFontSize; - - style->resetPadding(); - style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up? - - const int minHeight = 15; - style->setMinHeight(Length(minHeight, Fixed)); - - style->setLineHeight(RenderStyle::initialLineHeight()); -} - -void RenderThemeChromiumMac::setPopupButtonCellState(const RenderObject* o, const IntRect& r) -{ - NSPopUpButtonCell* popupButton = this->popupButton(); - - // Set the control size based off the rectangle we're painting into. - setControlSize(popupButton, popupButtonSizes(), r.size(), o->style()->effectiveZoom()); - - // Update the various states we respond to. - updateActiveState(popupButton, o); - updateCheckedState(popupButton, o); - updateEnabledState(popupButton, o); - updatePressedState(popupButton, o); - updateFocusedState(popupButton, o); -} - -const IntSize* RenderThemeChromiumMac::menuListSizes() const -{ - static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) }; - return sizes; -} - -int RenderThemeChromiumMac::minimumMenuListSize(RenderStyle* style) const -{ - return sizeForSystemFont(style, menuListSizes()).width(); -} - -const int trackWidth = 5; -const int trackRadius = 2; - -void RenderThemeChromiumMac::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* style, Element*) const -{ - style->setBoxShadow(0); -} - -bool RenderThemeChromiumMac::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) -{ - IntRect bounds = r; - float zoomLevel = o->style()->effectiveZoom(); - float zoomedTrackWidth = trackWidth * zoomLevel; - - if (o->style()->appearance() == SliderHorizontalPart || o->style()->appearance() == MediaSliderPart) { - bounds.setHeight(zoomedTrackWidth); - bounds.setY(r.y() + r.height() / 2 - zoomedTrackWidth / 2); - } else if (o->style()->appearance() == SliderVerticalPart) { - bounds.setWidth(zoomedTrackWidth); - bounds.setX(r.x() + r.width() / 2 - zoomedTrackWidth / 2); - } - - LocalCurrentGraphicsContext localContext(paintInfo.context); - CGContextRef context = paintInfo.context->platformContext(); - RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB()); - - paintInfo.context->save(); - CGContextClipToRect(context, bounds); - - struct CGFunctionCallbacks mainCallbacks = { 0, TrackGradientInterpolate, NULL }; - RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks)); - RetainPtr<CGShadingRef> mainShading; - if (o->style()->appearance() == SliderVerticalPart) - mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(), bounds.bottom()), CGPointMake(bounds.right(), bounds.bottom()), mainFunction.get(), false, false)); - else - mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(), bounds.y()), CGPointMake(bounds.x(), bounds.bottom()), mainFunction.get(), false, false)); - - IntSize radius(trackRadius, trackRadius); - paintInfo.context->addRoundedRectClip(bounds, - radius, radius, - radius, radius); - CGContextDrawShading(context, mainShading.get()); - paintInfo.context->restore(); - - return false; -} - -void RenderThemeChromiumMac::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle* style, Element*) const -{ - style->setBoxShadow(0); -} - -const float verticalSliderHeightPadding = 0.1f; - -bool RenderThemeChromiumMac::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) -{ - ASSERT(o->parent()->isSlider()); - - NSSliderCell* sliderThumbCell = o->style()->appearance() == SliderThumbVerticalPart - ? sliderThumbVertical() - : sliderThumbHorizontal(); - - LocalCurrentGraphicsContext localContext(paintInfo.context); - - // Update the various states we respond to. - updateActiveState(sliderThumbCell, o->parent()); - updateEnabledState(sliderThumbCell, o->parent()); - updateFocusedState(sliderThumbCell, o->parent()); - - // Update the pressed state using the NSCell tracking methods, since that's how NSSliderCell keeps track of it. - bool oldPressed; - if (o->style()->appearance() == SliderThumbVerticalPart) - oldPressed = m_isSliderThumbVerticalPressed; - else - oldPressed = m_isSliderThumbHorizontalPressed; - - bool pressed = toRenderSlider(o->parent())->inDragMode(); - - if (o->style()->appearance() == SliderThumbVerticalPart) - m_isSliderThumbVerticalPressed = pressed; - else - m_isSliderThumbHorizontalPressed = pressed; - - if (pressed != oldPressed) { - if (pressed) - [sliderThumbCell startTrackingAt:NSPoint() inView:nil]; - else - [sliderThumbCell stopTracking:NSPoint() at:NSPoint() inView:nil mouseIsUp:YES]; - } - - FloatRect bounds = r; - // Make the height of the vertical slider slightly larger so NSSliderCell will draw a vertical slider. - if (o->style()->appearance() == SliderThumbVerticalPart) - bounds.setHeight(bounds.height() + verticalSliderHeightPadding * o->style()->effectiveZoom()); - - paintInfo.context->save(); - float zoomLevel = o->style()->effectiveZoom(); - - FloatRect unzoomedRect = bounds; - if (zoomLevel != 1.0f) { - unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); - unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); - paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); - paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel)); - paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); - } - - [sliderThumbCell drawWithFrame:unzoomedRect inView:FlippedView()]; - [sliderThumbCell setControlView:nil]; - - paintInfo.context->restore(); - - return false; -} - -bool RenderThemeChromiumMac::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) -{ - NSSearchFieldCell* search = this->search(); - LocalCurrentGraphicsContext localContext(paintInfo.context); - - setSearchCellState(o, r); - - paintInfo.context->save(); - - float zoomLevel = o->style()->effectiveZoom(); - - IntRect unzoomedRect = r; - - if (zoomLevel != 1.0f) { - unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); - unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); - paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); - paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel)); - paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); - } - - // Set the search button to nil before drawing. Then reset it so we can draw it later. - [search setSearchButtonCell:nil]; - - [search drawWithFrame:NSRect(unzoomedRect) inView:FlippedView()]; -#ifdef BUILDING_ON_TIGER - if ([search showsFirstResponder]) - wkDrawTextFieldCellFocusRing(search, NSRect(unzoomedRect)); -#endif - - [search setControlView:nil]; - [search resetSearchButtonCell]; - - paintInfo.context->restore(); - - return false; -} - -void RenderThemeChromiumMac::setSearchCellState(RenderObject* o, const IntRect&) -{ - NSSearchFieldCell* search = this->search(); - - [search setControlSize:controlSizeForFont(o->style())]; - - // Update the various states we respond to. - updateActiveState(search, o); - updateEnabledState(search, o); - updateFocusedState(search, o); -} - -const IntSize* RenderThemeChromiumMac::searchFieldSizes() const -{ - static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 17) }; - return sizes; -} - -void RenderThemeChromiumMac::setSearchFieldSize(RenderStyle* style) const -{ - // If the width and height are both specified, then we have nothing to do. - if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) - return; - - // Use the font size to determine the intrinsic width of the control. - setSizeFromFont(style, searchFieldSizes()); -} - -void RenderThemeChromiumMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element*) const -{ - // Override border. - style->resetBorder(); - const short borderWidth = 2 * style->effectiveZoom(); - style->setBorderLeftWidth(borderWidth); - style->setBorderLeftStyle(INSET); - style->setBorderRightWidth(borderWidth); - style->setBorderRightStyle(INSET); - style->setBorderBottomWidth(borderWidth); - style->setBorderBottomStyle(INSET); - style->setBorderTopWidth(borderWidth); - style->setBorderTopStyle(INSET); - - // Override height. - style->setHeight(Length(Auto)); - setSearchFieldSize(style); - - // Override padding size to match AppKit text positioning. - const int padding = 1 * style->effectiveZoom(); - style->setPaddingLeft(Length(padding, Fixed)); - style->setPaddingRight(Length(padding, Fixed)); - style->setPaddingTop(Length(padding, Fixed)); - style->setPaddingBottom(Length(padding, Fixed)); - - NSControlSize controlSize = controlSizeForFont(style); - setFontFromControlSize(selector, style, controlSize); - - style->setBoxShadow(0); -} - -bool RenderThemeChromiumMac::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) -{ - Node* input = o->node()->shadowAncestorNode(); - if (!input->renderer()->isBox()) - return false; - - setSearchCellState(input->renderer(), r); - - NSSearchFieldCell* search = this->search(); - - updateActiveState([search cancelButtonCell], o); - updatePressedState([search cancelButtonCell], o); - - paintInfo.context->save(); - - float zoomLevel = o->style()->effectiveZoom(); - - FloatRect localBounds = [search cancelButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())]; - localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r); - - FloatRect unzoomedRect(localBounds); - if (zoomLevel != 1.0f) { - unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); - unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); - paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); - paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel)); - paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); - } - - [[search cancelButtonCell] drawWithFrame:unzoomedRect inView:FlippedView()]; - [[search cancelButtonCell] setControlView:nil]; - - paintInfo.context->restore(); - return false; -} - -const IntSize* RenderThemeChromiumMac::cancelButtonSizes() const -{ - static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) }; - return sizes; -} - -void RenderThemeChromiumMac::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const -{ - IntSize size = sizeForSystemFont(style, cancelButtonSizes()); - style->setWidth(Length(size.width(), Fixed)); - style->setHeight(Length(size.height(), Fixed)); - style->setBoxShadow(0); -} - -const IntSize* RenderThemeChromiumMac::resultsButtonSizes() const -{ - static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) }; - return sizes; -} - -const int emptyResultsOffset = 9; -void RenderThemeChromiumMac::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const -{ - IntSize size = sizeForSystemFont(style, resultsButtonSizes()); - style->setWidth(Length(size.width() - emptyResultsOffset, Fixed)); - style->setHeight(Length(size.height(), Fixed)); - style->setBoxShadow(0); -} - -bool RenderThemeChromiumMac::paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) -{ - return false; -} - -void RenderThemeChromiumMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const -{ - IntSize size = sizeForSystemFont(style, resultsButtonSizes()); - style->setWidth(Length(size.width(), Fixed)); - style->setHeight(Length(size.height(), Fixed)); - style->setBoxShadow(0); -} - -bool RenderThemeChromiumMac::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) -{ - Node* input = o->node()->shadowAncestorNode(); - if (!input->renderer()->isBox()) - return false; - - setSearchCellState(input->renderer(), r); - - NSSearchFieldCell* search = this->search(); - - updateActiveState([search searchButtonCell], o); - - if ([search searchMenuTemplate] != nil) - [search setSearchMenuTemplate:nil]; - - FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())]; - localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r); - - [[search searchButtonCell] drawWithFrame:localBounds inView:FlippedView()]; - [[search searchButtonCell] setControlView:nil]; - return false; -} - -const int resultsArrowWidth = 5; -void RenderThemeChromiumMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const -{ - IntSize size = sizeForSystemFont(style, resultsButtonSizes()); - style->setWidth(Length(size.width() + resultsArrowWidth, Fixed)); - style->setHeight(Length(size.height(), Fixed)); - style->setBoxShadow(0); -} - -bool RenderThemeChromiumMac::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) -{ - Node* input = o->node()->shadowAncestorNode(); - if (!input->renderer()->isBox()) - return false; - - setSearchCellState(input->renderer(), r); - - NSSearchFieldCell* search = this->search(); - - updateActiveState([search searchButtonCell], o); - - if (![search searchMenuTemplate]) - [search setSearchMenuTemplate:searchMenuTemplate()]; - - paintInfo.context->save(); - - float zoomLevel = o->style()->effectiveZoom(); - - FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())]; - localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r); - - IntRect unzoomedRect(localBounds); - if (zoomLevel != 1.0f) { - unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); - unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); - paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); - paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel)); - paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); - } - - [[search searchButtonCell] drawWithFrame:unzoomedRect inView:FlippedView()]; - [[search searchButtonCell] setControlView:nil]; - - paintInfo.context->restore(); - - return false; -} - -const int sliderThumbWidth = 15; -const int sliderThumbHeight = 15; +#if ENABLE(VIDEO) -void RenderThemeChromiumMac::adjustSliderThumbSize(RenderObject* o) const +void RenderThemeChromiumMac::adjustMediaSliderThumbSize(RenderObject* o) const { - float zoomLevel = o->style()->effectiveZoom(); - if (o->style()->appearance() == SliderThumbHorizontalPart || o->style()->appearance() == SliderThumbVerticalPart) { - o->style()->setWidth(Length(static_cast<int>(sliderThumbWidth * zoomLevel), Fixed)); - o->style()->setHeight(Length(static_cast<int>(sliderThumbHeight * zoomLevel), Fixed)); - } - -#if ENABLE(VIDEO) RenderMediaControlsChromium::adjustMediaSliderThumbSize(o); -#endif } -#if ENABLE(VIDEO) bool RenderThemeChromiumMac::shouldRenderMediaControlPart(ControlPart part, Element* e) { return RenderMediaControlsChromium::shouldRenderMediaControlPart(part, e); @@ -1535,21 +124,6 @@ bool RenderThemeChromiumMac::paintMediaSliderTrack(RenderObject* object, const R return RenderMediaControlsChromium::paintMediaControlsPart(MediaSlider, object, paintInfo, rect); } -bool RenderThemeChromiumMac::paintMediaVolumeSliderTrack(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) -{ - return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSlider, object, paintInfo, rect); -} - -bool RenderThemeChromiumMac::paintMediaSliderThumb(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) -{ - return RenderMediaControlsChromium::paintMediaControlsPart(MediaSliderThumb, object, paintInfo, rect); -} - -bool RenderThemeChromiumMac::paintMediaVolumeSliderThumb(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) -{ - return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSliderThumb, object, paintInfo, rect); -} - bool RenderThemeChromiumMac::paintMediaControlsBackground(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { return RenderMediaControlsChromium::paintMediaControlsPart(MediaTimelineContainer, object, paintInfo, rect); @@ -1560,64 +134,16 @@ String RenderThemeChromiumMac::extraMediaControlsStyleSheet() return String(mediaControlsChromiumUserAgentStyleSheet, sizeof(mediaControlsChromiumUserAgentStyleSheet)); } -#endif - -NSPopUpButtonCell* RenderThemeChromiumMac::popupButton() const -{ - if (!m_popupButton) { - m_popupButton.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]); - [m_popupButton.get() setUsesItemFromMenu:NO]; - [m_popupButton.get() setFocusRingType:NSFocusRingTypeExterior]; - } - - return m_popupButton.get(); -} - -NSSearchFieldCell* RenderThemeChromiumMac::search() const -{ - if (!m_search) { - m_search.adoptNS([[NSSearchFieldCell alloc] initTextCell:@""]); - [m_search.get() setBezelStyle:NSTextFieldRoundedBezel]; - [m_search.get() setBezeled:YES]; - [m_search.get() setEditable:YES]; - [m_search.get() setFocusRingType:NSFocusRingTypeExterior]; - } - - return m_search.get(); -} - -NSMenu* RenderThemeChromiumMac::searchMenuTemplate() const +bool RenderThemeChromiumMac::paintMediaVolumeSliderTrack(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { - if (!m_searchMenuTemplate) - m_searchMenuTemplate.adoptNS([[NSMenu alloc] initWithTitle:@""]); - - return m_searchMenuTemplate.get(); + return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSlider, object, paintInfo, rect); } -NSSliderCell* RenderThemeChromiumMac::sliderThumbHorizontal() const +bool RenderThemeChromiumMac::paintMediaVolumeSliderThumb(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { - if (!m_sliderThumbHorizontal) { - m_sliderThumbHorizontal.adoptNS([[NSSliderCell alloc] init]); - [m_sliderThumbHorizontal.get() setTitle:nil]; - [m_sliderThumbHorizontal.get() setSliderType:NSLinearSlider]; - [m_sliderThumbHorizontal.get() setControlSize:NSSmallControlSize]; - [m_sliderThumbHorizontal.get() setFocusRingType:NSFocusRingTypeExterior]; - } - - return m_sliderThumbHorizontal.get(); + return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSliderThumb, object, paintInfo, rect); } -NSSliderCell* RenderThemeChromiumMac::sliderThumbVertical() const -{ - if (!m_sliderThumbVertical) { - m_sliderThumbVertical.adoptNS([[NSSliderCell alloc] init]); - [m_sliderThumbVertical.get() setTitle:nil]; - [m_sliderThumbVertical.get() setSliderType:NSLinearSlider]; - [m_sliderThumbVertical.get() setControlSize:NSSmallControlSize]; - [m_sliderThumbVertical.get() setFocusRingType:NSFocusRingTypeExterior]; - } - - return m_sliderThumbVertical.get(); -} +#endif } // namespace WebCore diff --git a/WebCore/rendering/RenderThemeMac.h b/WebCore/rendering/RenderThemeMac.h index cba927f..cb604b9 100644 --- a/WebCore/rendering/RenderThemeMac.h +++ b/WebCore/rendering/RenderThemeMac.h @@ -88,8 +88,14 @@ public: #endif virtual Color systemColor(int cssValueId) const; - + // Controls color values returned from platformFocusRingColor(). systemColor() will be used when false. + virtual bool usesTestModeFocusRingColor() const; + // A view associated to the contained document. Subclasses may not have such a view and return a fake. + virtual NSView* documentViewFor(RenderObject*) const; protected: + RenderThemeMac(); + virtual ~RenderThemeMac(); + virtual bool supportsSelectionForegroundColors() const { return false; } virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); @@ -149,11 +155,10 @@ protected: virtual String extraMediaControlsStyleSheet(); virtual bool shouldRenderMediaControlPart(ControlPart, Element*); + virtual void adjustMediaSliderThumbSize(RenderObject*) const; #endif private: - RenderThemeMac(); - virtual ~RenderThemeMac(); IntRect inflateRect(const IntRect&, const IntSize&, const int* margins, float zoomLevel = 1.0f) const; @@ -172,6 +177,8 @@ private: void updateEnabledState(NSCell*, const RenderObject*); void updateFocusedState(NSCell*, const RenderObject*); void updatePressedState(NSCell*, const RenderObject*); + // An optional hook for subclasses to update the control tint of NSCell. + virtual void updateActiveState(NSCell*, const RenderObject*) {} // Helpers for adjusting appearance and for painting diff --git a/WebCore/rendering/RenderThemeMac.mm b/WebCore/rendering/RenderThemeMac.mm index c0d8020..d1a3965 100644 --- a/WebCore/rendering/RenderThemeMac.mm +++ b/WebCore/rendering/RenderThemeMac.mm @@ -115,11 +115,13 @@ enum { leftPadding }; +#if PLATFORM(MAC) PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page*) { static RenderTheme* rt = RenderThemeMac::create().releaseRef(); return rt; } +#endif PassRefPtr<RenderTheme> RenderThemeMac::create() { @@ -458,6 +460,21 @@ Color RenderThemeMac::systemColor(int cssValueId) const return color; } +bool RenderThemeMac::usesTestModeFocusRingColor() const +{ + return WebCore::usesTestModeFocusRingColor(); +} + +NSView* RenderThemeMac::documentViewFor(RenderObject* o) const +{ +#if PLATFORM(MAC) + return ThemeMac::ensuredView(o->view()->frameView()); +#else + ASSERT_NOT_REACHED(); + return 0; +#endif +} + bool RenderThemeMac::isControlStyled(const RenderStyle* style, const BorderData& border, const FillLayer& background, const Color& backgroundColor) const { @@ -487,6 +504,7 @@ void RenderThemeMac::adjustRepaintRect(const RenderObject* o, IntRect& r) case ListButtonPart: case DefaultButtonPart: case ButtonPart: + case OuterSpinButtonPart: return RenderTheme::adjustRepaintRect(o, r); default: break; @@ -776,7 +794,7 @@ bool RenderThemeMac::paintMenuList(RenderObject* o, const RenderObject::PaintInf paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y()); } - [popupButton drawWithFrame:inflatedRect inView:ThemeMac::ensuredView(o->view()->frameView())]; + [popupButton drawWithFrame:inflatedRect inView:documentViewFor(o)]; [popupButton setControlView:nil]; paintInfo.context->restore(); @@ -1111,6 +1129,7 @@ void RenderThemeMac::setPopupButtonCellState(const RenderObject* o, const IntRec setControlSize(popupButton, popupButtonSizes(), r.size(), o->style()->effectiveZoom()); // Update the various states we respond to. + updateActiveState(popupButton, o); updateCheckedState(popupButton, o); updateEnabledState(popupButton, o); updatePressedState(popupButton, o); @@ -1193,6 +1212,7 @@ bool RenderThemeMac::paintSliderThumb(RenderObject* o, const RenderObject::Paint LocalCurrentGraphicsContext localContext(paintInfo.context); // Update the various states we respond to. + updateActiveState(sliderThumbCell, o->parent()); updateEnabledState(sliderThumbCell, o->parent()); updateFocusedState(sliderThumbCell, o->parent()); @@ -1234,7 +1254,7 @@ bool RenderThemeMac::paintSliderThumb(RenderObject* o, const RenderObject::Paint paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); } - [sliderThumbCell drawWithFrame:unzoomedRect inView:ThemeMac::ensuredView(o->view()->frameView())]; + [sliderThumbCell drawWithFrame:unzoomedRect inView:documentViewFor(o)]; [sliderThumbCell setControlView:nil]; paintInfo.context->restore(); @@ -1266,7 +1286,7 @@ bool RenderThemeMac::paintSearchField(RenderObject* o, const RenderObject::Paint // Set the search button to nil before drawing. Then reset it so we can draw it later. [search setSearchButtonCell:nil]; - [search drawWithFrame:NSRect(unzoomedRect) inView:ThemeMac::ensuredView(o->view()->frameView())]; + [search drawWithFrame:NSRect(unzoomedRect) inView:documentViewFor(o)]; #ifdef BUILDING_ON_TIGER if ([search showsFirstResponder]) wkDrawTextFieldCellFocusRing(search, NSRect(unzoomedRect)); @@ -1287,6 +1307,7 @@ void RenderThemeMac::setSearchCellState(RenderObject* o, const IntRect&) [search setControlSize:controlSizeForFont(o->style())]; // Update the various states we respond to. + updateActiveState(search, o); updateEnabledState(search, o); updateFocusedState(search, o); } @@ -1348,6 +1369,7 @@ bool RenderThemeMac::paintSearchFieldCancelButton(RenderObject* o, const RenderO NSSearchFieldCell* search = this->search(); + updateActiveState([search cancelButtonCell], o); updatePressedState([search cancelButtonCell], o); paintInfo.context->save(); @@ -1366,7 +1388,7 @@ bool RenderThemeMac::paintSearchFieldCancelButton(RenderObject* o, const RenderO paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); } - [[search cancelButtonCell] drawWithFrame:unzoomedRect inView:ThemeMac::ensuredView(o->view()->frameView())]; + [[search cancelButtonCell] drawWithFrame:unzoomedRect inView:documentViewFor(o)]; [[search cancelButtonCell] setControlView:nil]; paintInfo.context->restore(); @@ -1428,10 +1450,12 @@ bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const Re if ([search searchMenuTemplate] != nil) [search setSearchMenuTemplate:nil]; + updateActiveState([search searchButtonCell], o); + FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())]; localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r); - [[search searchButtonCell] drawWithFrame:localBounds inView:ThemeMac::ensuredView(o->view()->frameView())]; + [[search searchButtonCell] drawWithFrame:localBounds inView:documentViewFor(o)]; [[search searchButtonCell] setControlView:nil]; return false; } @@ -1455,6 +1479,8 @@ bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const Render NSSearchFieldCell* search = this->search(); + updateActiveState([search searchButtonCell], o); + if (![search searchMenuTemplate]) [search setSearchMenuTemplate:searchMenuTemplate()]; @@ -1474,7 +1500,7 @@ bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const Render paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); } - [[search searchButtonCell] drawWithFrame:unzoomedRect inView:ThemeMac::ensuredView(o->view()->frameView())]; + [[search searchButtonCell] drawWithFrame:unzoomedRect inView:documentViewFor(o)]; [[search searchButtonCell] setControlView:nil]; paintInfo.context->restore(); @@ -1527,7 +1553,15 @@ void RenderThemeMac::adjustSliderThumbSize(RenderObject* o) const } #if ENABLE(VIDEO) - else if (o->style()->appearance() == MediaSliderThumbPart) { + adjustMediaSliderThumbSize(o); +#endif +} + +#if ENABLE(VIDEO) + +void RenderThemeMac::adjustMediaSliderThumbSize(RenderObject* o) const +{ + if (o->style()->appearance() == MediaSliderThumbPart) { int width = mediaSliderThumbWidth; int height = mediaSliderThumbHeight; @@ -1539,15 +1573,12 @@ void RenderThemeMac::adjustSliderThumbSize(RenderObject* o) const height = size.height; } + float zoomLevel = o->style()->effectiveZoom(); o->style()->setWidth(Length(static_cast<int>(width * zoomLevel), Fixed)); o->style()->setHeight(Length(static_cast<int>(height * zoomLevel), Fixed)); } -#endif } - -#if ENABLE(VIDEO) - enum WKMediaControllerThemeState { MediaUIPartDisabledFlag = 1 << 0, MediaUIPartPressedFlag = 1 << 1, @@ -1759,10 +1790,15 @@ bool RenderThemeMac::paintMediaTimeRemaining(RenderObject* o, const RenderObject String RenderThemeMac::extraMediaControlsStyleSheet() { +#if PLATFORM(MAC) if (mediaControllerTheme() == MediaControllerThemeQuickTime) return String(mediaControlsQuickTimeUserAgentStyleSheet, sizeof(mediaControlsQuickTimeUserAgentStyleSheet)); else return String(); +#else + ASSERT_NOT_REACHED(); + return String(); +#endif } bool RenderThemeMac::shouldRenderMediaControlPart(ControlPart part, Element* element) diff --git a/WebCore/rendering/RenderTreeAsText.cpp b/WebCore/rendering/RenderTreeAsText.cpp index 75c35ba..311854e 100644 --- a/WebCore/rendering/RenderTreeAsText.cpp +++ b/WebCore/rendering/RenderTreeAsText.cpp @@ -34,6 +34,7 @@ #include "HTMLElement.h" #include "HTMLNames.h" #include "InlineTextBox.h" +#include "PrintContext.h" #include "RenderBR.h" #include "RenderFileUploadControl.h" #include "RenderInline.h" @@ -51,6 +52,7 @@ #if ENABLE(SVG) #include "RenderPath.h" #include "RenderSVGContainer.h" +#include "RenderSVGGradientStop.h" #include "RenderSVGImage.h" #include "RenderSVGInlineText.h" #include "RenderSVGRoot.h" @@ -396,8 +398,12 @@ void write(TextStream& ts, const RenderObject& o, int indent, RenderAsTextBehavi write(ts, *toRenderPath(&o), indent); return; } - if (o.isSVGResource()) { - writeSVGResource(ts, o, indent); + if (o.isSVGGradientStop()) { + writeSVGGradientStop(ts, *toRenderSVGGradientStop(&o), indent); + return; + } + if (o.isSVGResourceContainer()) { + writeSVGResourceContainer(ts, o, indent); return; } if (o.isSVGContainer()) { @@ -612,6 +618,13 @@ static void writeSelection(TextStream& ts, const RenderObject* o) String externalRepresentation(Frame* frame, RenderAsTextBehavior behavior) { + PrintContext printContext(frame); + if (behavior & RenderAsTextPrintingMode) { + if (!frame->contentRenderer()) + return String(); + printContext.begin(frame->contentRenderer()->width()); + } + frame->document()->updateLayout(); RenderObject* o = frame->contentRenderer(); @@ -619,9 +632,6 @@ String externalRepresentation(Frame* frame, RenderAsTextBehavior behavior) return String(); TextStream ts; -#if ENABLE(SVG) - writeRenderResources(ts, o->document()); -#endif if (o->hasLayer()) { RenderLayer* l = toRenderBox(o)->layer(); writeLayers(ts, l, l, IntRect(l->x(), l->y(), l->width(), l->height()), 0, behavior); diff --git a/WebCore/rendering/RenderTreeAsText.h b/WebCore/rendering/RenderTreeAsText.h index 4da0bab..1427342 100644 --- a/WebCore/rendering/RenderTreeAsText.h +++ b/WebCore/rendering/RenderTreeAsText.h @@ -39,10 +39,12 @@ enum RenderAsTextBehaviorFlags { RenderAsTextShowAllLayers = 1 << 0, // Dump all layers, not just those that would paint. RenderAsTextShowLayerNesting = 1 << 1, // Annotate the layer lists. RenderAsTextShowCompositedLayers = 1 << 2, // Show which layers are composited. - RenderAsTextShowAddresses = 1 << 3 // Show layer and renderer addresses. + RenderAsTextShowAddresses = 1 << 3, // Show layer and renderer addresses. + RenderAsTextPrintingMode = 1 << 4 // Dump the tree in printing mode. }; typedef unsigned RenderAsTextBehavior; +// You don't need pageWidthInPixels if you don't specify RenderAsTextInPrintingMode. String externalRepresentation(Frame*, RenderAsTextBehavior = RenderAsTextBehaviorNormal); void write(TextStream&, const RenderObject&, int indent = 0, RenderAsTextBehavior = RenderAsTextBehaviorNormal); diff --git a/WebCore/rendering/RenderVideo.cpp b/WebCore/rendering/RenderVideo.cpp index ad25c22..610fb5f 100644 --- a/WebCore/rendering/RenderVideo.cpp +++ b/WebCore/rendering/RenderVideo.cpp @@ -50,7 +50,7 @@ using namespace HTMLNames; RenderVideo::RenderVideo(HTMLVideoElement* video) : RenderMedia(video) { - if (video->player()) + if (video->player() && video->readyState() >= HTMLVideoElement::HAVE_METADATA) setIntrinsicSize(video->player()->naturalSize()); else { // When the natural size of the video is unavailable, we use the provided @@ -101,7 +101,11 @@ void RenderVideo::videoSizeChanged() if (!player()) return; IntSize size = player()->naturalSize(); - if (!size.isEmpty() && size != intrinsicSize()) { + if (size.isEmpty()) { + if (node()->ownerDocument() && node()->ownerDocument()->isMediaDocument()) + return; + } + if (size != intrinsicSize()) { setIntrinsicSize(size); setPrefWidthsDirty(true); setNeedsLayout(true); diff --git a/WebCore/rendering/RenderView.cpp b/WebCore/rendering/RenderView.cpp index a95ffdd..449e293 100644 --- a/WebCore/rendering/RenderView.cpp +++ b/WebCore/rendering/RenderView.cpp @@ -747,16 +747,6 @@ bool RenderView::usesCompositing() const return m_compositor && m_compositor->inCompositingMode(); } -void RenderView::compositingStateChanged(bool) -{ - Element* elt = document()->ownerElement(); - if (!elt) - return; - - // Trigger a recalcStyle in the parent document, to update compositing in that document. - elt->setNeedsStyleRecalc(SyntheticStyleChange); -} - RenderLayerCompositor* RenderView::compositor() { if (!m_compositor) diff --git a/WebCore/rendering/RenderView.h b/WebCore/rendering/RenderView.h index 0751866..05c3876 100644 --- a/WebCore/rendering/RenderView.h +++ b/WebCore/rendering/RenderView.h @@ -166,7 +166,6 @@ public: #if USE(ACCELERATED_COMPOSITING) RenderLayerCompositor* compositor(); bool usesCompositing() const; - void compositingStateChanged(bool nowComposited); #endif protected: diff --git a/WebCore/rendering/RenderWidget.cpp b/WebCore/rendering/RenderWidget.cpp index 485baa3..15c75f1 100644 --- a/WebCore/rendering/RenderWidget.cpp +++ b/WebCore/rendering/RenderWidget.cpp @@ -320,8 +320,8 @@ void RenderWidget::updateWidgetPosition() FloatPoint absPos = localToAbsolute(); absPos.move(borderLeft() + paddingLeft(), borderTop() + paddingTop()); - int w = width() - borderLeft() - borderRight() - paddingLeft() - paddingRight(); - int h = height() - borderTop() - borderBottom() - paddingTop() - paddingBottom(); + int w = width() - borderAndPaddingWidth(); + int h = height() - borderAndPaddingHeight(); bool boundsChanged = setWidgetGeometry(IntRect(absPos.x(), absPos.y(), w, h)); diff --git a/WebCore/rendering/SVGCharacterData.cpp b/WebCore/rendering/SVGCharacterData.cpp new file mode 100644 index 0000000..394a303 --- /dev/null +++ b/WebCore/rendering/SVGCharacterData.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) Research In Motion Limited 2010. 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 "SVGCharacterData.h" + +#if ENABLE(SVG) +#include "AffineTransform.h" + +namespace WebCore { + +bool SVGChar::isHidden() const +{ + return pathData && pathData->hidden; +} + +AffineTransform SVGChar::characterTransform() const +{ + AffineTransform ctm; + + // Rotate character around angle, and possibly scale. + ctm.translate(x, y); + ctm.rotate(angle); + + if (pathData) { + ctm.scaleNonUniform(pathData->xScale, pathData->yScale); + ctm.translate(pathData->xShift, pathData->yShift); + ctm.rotate(pathData->orientationAngle); + } + + ctm.translate(orientationShiftX - x, orientationShiftY - y); + return ctm; +} + +} // namespace WebCore + +#endif // ENABLE(SVG) diff --git a/WebCore/rendering/SVGCharacterData.h b/WebCore/rendering/SVGCharacterData.h new file mode 100644 index 0000000..68682c9 --- /dev/null +++ b/WebCore/rendering/SVGCharacterData.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) Research In Motion Limited 2010. 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 SVGCharacterData_h +#define SVGCharacterData_h + +#if ENABLE(SVG) +#include <wtf/HashMap.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +namespace WebCore { + +class AffineTransform; +class RenderObject; + +// Holds extra data, when the character is laid out on a path +struct SVGCharOnPath : RefCounted<SVGCharOnPath> { + static PassRefPtr<SVGCharOnPath> create() { return adoptRef(new SVGCharOnPath); } + + float xScale; + float yScale; + + float xShift; + float yShift; + + float orientationAngle; + + bool hidden : 1; + +private: + SVGCharOnPath() + : xScale(1.0f) + , yScale(1.0f) + , xShift(0.0f) + , yShift(0.0f) + , orientationAngle(0.0f) + , hidden(false) + { + } +}; + +struct SVGChar { + SVGChar() + : x(0.0f) + , y(0.0f) + , angle(0.0f) + , orientationShiftX(0.0f) + , orientationShiftY(0.0f) + , drawnSeperated(false) + , newTextChunk(false) + { + } + + float x; + float y; + float angle; + + float orientationShiftX; + float orientationShiftY; + + RefPtr<SVGCharOnPath> pathData; + + // Determines wheter this char needs to be drawn seperated + bool drawnSeperated : 1; + + // Determines wheter this char starts a new chunk + bool newTextChunk : 1; + + // Helper methods + bool isHidden() const; + AffineTransform characterTransform() const; +}; + +struct SVGTextDecorationInfo { + // ETextDecoration is meant to be used here + HashMap<int, RenderObject*> fillServerMap; + HashMap<int, RenderObject*> strokeServerMap; +}; + +} // namespace WebCore + +#endif // ENABLE(SVG) +#endif // SVGCharacterData_h diff --git a/WebCore/rendering/SVGCharacterLayoutInfo.cpp b/WebCore/rendering/SVGCharacterLayoutInfo.cpp index 7e85672..04f0067 100644 --- a/WebCore/rendering/SVGCharacterLayoutInfo.cpp +++ b/WebCore/rendering/SVGCharacterLayoutInfo.cpp @@ -1,6 +1,4 @@ /* - * This file is part of the WebKit project. - * * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> * * This library is free software; you can redistribute it and/or @@ -21,16 +19,16 @@ */ #include "config.h" - -#if ENABLE(SVG) #include "SVGCharacterLayoutInfo.h" +#if ENABLE(SVG) #include "InlineFlowBox.h" #include "InlineTextBox.h" +#include "RenderSVGTextPath.h" +#include "SVGCharacterData.h" #include "SVGLengthList.h" #include "SVGNumberList.h" #include "SVGTextPositioningElement.h" -#include "RenderSVGTextPath.h" #include <float.h> @@ -161,6 +159,19 @@ float SVGCharacterLayoutInfo::baselineShiftValueNext() const return baselineShiftStack.last(); } + +bool SVGCharacterLayoutInfo::isInitialLayout() const +{ + return xStack.isEmpty() + && yStack.isEmpty() + && dxStack.isEmpty() + && dyStack.isEmpty() + && angleStack.isEmpty() + && baselineShiftStack.isEmpty() + && curx == 0.0f + && cury == 0.0f; +} + void SVGCharacterLayoutInfo::processedSingleCharacter() { xStackWalk(); @@ -249,7 +260,6 @@ bool SVGCharacterLayoutInfo::nextPathLayoutPointAndAngle(float glyphAdvance, flo angle = layoutPath.normalAngleAtLength(offset, ok); ASSERT(ok); - // fprintf(stderr, "t: %f, x: %f, y: %f, angle: %f, glyphAdvance: %f\n", currentOffset, x, y, angle, glyphAdvance); return true; } @@ -269,10 +279,7 @@ void SVGCharacterLayoutInfo::setInPathLayout(bool value) void SVGCharacterLayoutInfo::addLayoutInformation(InlineFlowBox* flowBox, float textAnchorStartOffset) { - bool isInitialLayout = xStack.isEmpty() && yStack.isEmpty() && - dxStack.isEmpty() && dyStack.isEmpty() && - angleStack.isEmpty() && baselineShiftStack.isEmpty() && - curx == 0.0f && cury == 0.0f; + bool wasInitialLayout = isInitialLayout(); RenderSVGTextPath* textPath = toRenderSVGTextPath(flowBox->renderer()); Path path = textPath->layoutPath(); @@ -296,7 +303,7 @@ void SVGCharacterLayoutInfo::addLayoutInformation(InlineFlowBox* flowBox, float // Only baseline-shift is handled through the normal layout system addStackContent(BaselineShiftStack, baselineShift); - if (isInitialLayout) { + if (wasInitialLayout) { xStackChanged = false; yStackChanged = false; dxStackChanged = false; @@ -308,11 +315,7 @@ void SVGCharacterLayoutInfo::addLayoutInformation(InlineFlowBox* flowBox, float void SVGCharacterLayoutInfo::addLayoutInformation(SVGTextPositioningElement* element) { - bool isInitialLayout = xStack.isEmpty() && yStack.isEmpty() && - dxStack.isEmpty() && dyStack.isEmpty() && - angleStack.isEmpty() && baselineShiftStack.isEmpty() && - curx == 0.0f && cury == 0.0f; - + bool wasInitialLayout = isInitialLayout(); float baselineShift = calculateBaselineShift(element->renderer()); addStackContent(XStack, element->x(), element); @@ -322,7 +325,7 @@ void SVGCharacterLayoutInfo::addLayoutInformation(SVGTextPositioningElement* ele addStackContent(AngleStack, element->rotate()); addStackContent(BaselineShiftStack, baselineShift); - if (isInitialLayout) { + if (wasInitialLayout) { xStackChanged = false; yStackChanged = false; dxStackChanged = false; @@ -344,7 +347,7 @@ void SVGCharacterLayoutInfo::addStackContent(StackType type, SVGNumberList* list ExceptionCode ec = 0; for (unsigned i = 0; i < length; ++i) { float value = list->getItem(i, ec); - ASSERT(ec == 0); + ASSERT(!ec); newLayoutInfo.append(value); } @@ -363,7 +366,7 @@ void SVGCharacterLayoutInfo::addStackContent(StackType type, SVGLengthList* list ExceptionCode ec = 0; for (unsigned i = 0; i < length; ++i) { float value = list->getItem(i, ec).value(context); - ASSERT(ec == 0); + ASSERT(!ec); newLayoutInfo.append(value); } @@ -507,29 +510,6 @@ void SVGCharacterLayoutInfo::baselineShiftStackWalk() } } -bool SVGChar::isHidden() const -{ - return pathData && pathData->hidden; -} - -AffineTransform SVGChar::characterTransform() const -{ - AffineTransform ctm; - - // Rotate character around angle, and possibly scale. - ctm.translate(x, y); - ctm.rotate(angle); - - if (pathData) { - ctm.scaleNonUniform(pathData->xScale, pathData->yScale); - ctm.translate(pathData->xShift, pathData->yShift); - ctm.rotate(pathData->orientationAngle); - } - - ctm.translate(orientationShiftX - x, orientationShiftY - y); - return ctm; -} - } // namespace WebCore #endif // ENABLE(SVG) diff --git a/WebCore/rendering/SVGCharacterLayoutInfo.h b/WebCore/rendering/SVGCharacterLayoutInfo.h index f0d1fa4..16fd740 100644 --- a/WebCore/rendering/SVGCharacterLayoutInfo.h +++ b/WebCore/rendering/SVGCharacterLayoutInfo.h @@ -1,6 +1,4 @@ /* - * This file is part of the WebKit project. - * * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> * * This library is free software; you can redistribute it and/or @@ -24,21 +22,14 @@ #define SVGCharacterLayoutInfo_h #if ENABLE(SVG) -#include "AffineTransform.h" -#include "SVGRenderStyle.h" -#include "SVGTextContentElement.h" - +#include "Path.h" #include <wtf/Assertions.h> -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/RefCounted.h> #include <wtf/Vector.h> namespace WebCore { -class InlineBox; class InlineFlowBox; -class SVGInlineTextBox; +class SVGElement; class SVGLengthList; class SVGNumberList; class SVGTextPositioningElement; @@ -151,6 +142,8 @@ private: void angleStackWalk(); void baselineShiftStackWalk(); + bool isInitialLayout() const; + private: bool xStackChanged : 1; bool yStackChanged : 1; @@ -174,211 +167,6 @@ private: Vector<float> baselineShiftStack; }; -// Holds extra data, when the character is laid out on a path -struct SVGCharOnPath : RefCounted<SVGCharOnPath> { - static PassRefPtr<SVGCharOnPath> create() { return adoptRef(new SVGCharOnPath); } - - float xScale; - float yScale; - - float xShift; - float yShift; - - float orientationAngle; - - bool hidden : 1; - -private: - SVGCharOnPath() - : xScale(1.0f) - , yScale(1.0f) - , xShift(0.0f) - , yShift(0.0f) - , orientationAngle(0.0f) - , hidden(false) - { - } -}; - -struct SVGChar { - SVGChar() - : x(0.0f) - , y(0.0f) - , angle(0.0f) - , orientationShiftX(0.0f) - , orientationShiftY(0.0f) - , pathData() - , drawnSeperated(false) - , newTextChunk(false) - { - } - - ~SVGChar() - { - } - - float x; - float y; - float angle; - - float orientationShiftX; - float orientationShiftY; - - RefPtr<SVGCharOnPath> pathData; - - // Determines wheter this char needs to be drawn seperated - bool drawnSeperated : 1; - - // Determines wheter this char starts a new chunk - bool newTextChunk : 1; - - // Helper methods - bool isHidden() const; - AffineTransform characterTransform() const; -}; - -struct SVGInlineBoxCharacterRange { - SVGInlineBoxCharacterRange() - : startOffset(INT_MIN) - , endOffset(INT_MIN) - , box(0) - { - } - - bool isOpen() const { return (startOffset == endOffset) && (endOffset == INT_MIN); } - bool isClosed() const { return startOffset != INT_MIN && endOffset != INT_MIN; } - - int startOffset; - int endOffset; - - InlineBox* box; -}; - -// Convenience typedef -typedef SVGTextContentElement::SVGLengthAdjustType ELengthAdjust; - -struct SVGTextChunk { - SVGTextChunk() - : anchor(TA_START) - , textLength(0.0f) - , lengthAdjust(SVGTextContentElement::LENGTHADJUST_SPACING) - , ctm() - , isVerticalText(false) - , isTextPath(false) - , start(0) - , end(0) - { } - - // text-anchor support - ETextAnchor anchor; - - // textLength & lengthAdjust support - float textLength; - ELengthAdjust lengthAdjust; - AffineTransform ctm; - - // status flags - bool isVerticalText : 1; - bool isTextPath : 1; - - // main chunk data - Vector<SVGChar>::iterator start; - Vector<SVGChar>::iterator end; - - Vector<SVGInlineBoxCharacterRange> boxes; -}; - -struct SVGTextChunkWalkerBase { - virtual ~SVGTextChunkWalkerBase() { } - - virtual void operator()(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm, - const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end) = 0; - - // Followings methods are only used for painting text chunks - virtual void start(InlineBox*) = 0; - virtual void end(InlineBox*) = 0; -}; - -template<typename CallbackClass> -struct SVGTextChunkWalker : public SVGTextChunkWalkerBase { -public: - typedef void (CallbackClass::*SVGTextChunkWalkerCallback)(SVGInlineTextBox* textBox, - int startOffset, - const AffineTransform& chunkCtm, - const Vector<SVGChar>::iterator& start, - const Vector<SVGChar>::iterator& end); - - // These callbacks are only used for painting! - typedef void (CallbackClass::*SVGTextChunkStartCallback)(InlineBox* box); - typedef void (CallbackClass::*SVGTextChunkEndCallback)(InlineBox* box); - - SVGTextChunkWalker(CallbackClass* object, - SVGTextChunkWalkerCallback walker, - SVGTextChunkStartCallback start = 0, - SVGTextChunkEndCallback end = 0) - : m_object(object) - , m_walkerCallback(walker) - , m_startCallback(start) - , m_endCallback(end) - { - ASSERT(object); - ASSERT(walker); - } - - virtual void operator()(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm, - const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end) - { - (*m_object.*m_walkerCallback)(textBox, startOffset, chunkCtm, start, end); - } - - // Followings methods are only used for painting text chunks - virtual void start(InlineBox* box) - { - if (m_startCallback) - (*m_object.*m_startCallback)(box); - else - ASSERT_NOT_REACHED(); - } - - virtual void end(InlineBox* box) - { - if (m_endCallback) - (*m_object.*m_endCallback)(box); - else - ASSERT_NOT_REACHED(); - } - -private: - CallbackClass* m_object; - SVGTextChunkWalkerCallback m_walkerCallback; - SVGTextChunkStartCallback m_startCallback; - SVGTextChunkEndCallback m_endCallback; -}; - -struct SVGTextChunkLayoutInfo { - SVGTextChunkLayoutInfo(Vector<SVGTextChunk>& textChunks) - : assignChunkProperties(true) - , handlingTextPath(false) - , svgTextChunks(textChunks) - , it(0) - { - } - - bool assignChunkProperties : 1; - bool handlingTextPath : 1; - - Vector<SVGTextChunk>& svgTextChunks; - Vector<SVGChar>::iterator it; - - SVGTextChunk chunk; -}; - -struct SVGTextDecorationInfo { - // ETextDecoration is meant to be used here - HashMap<int, RenderObject*> fillServerMap; - HashMap<int, RenderObject*> strokeServerMap; -}; - } // namespace WebCore #endif // ENABLE(SVG) diff --git a/WebCore/rendering/SVGInlineTextBox.cpp b/WebCore/rendering/SVGInlineTextBox.cpp index bda512f..8b35507 100644 --- a/WebCore/rendering/SVGInlineTextBox.cpp +++ b/WebCore/rendering/SVGInlineTextBox.cpp @@ -30,7 +30,7 @@ #include "GraphicsContext.h" #include "InlineFlowBox.h" #include "Range.h" -#include "SVGPaintServer.h" +#include "RenderSVGResource.h" #include "SVGRootInlineBox.h" #include "Text.h" @@ -418,10 +418,9 @@ void SVGInlineTextBox::paintCharacters(RenderObject::PaintInfo& paintInfo, int t TextRun run = svgTextRunForInlineTextBox(chars, length, styleToUse, this, svgChar.x); #if ENABLE(SVG_FONTS) - // SVG Fonts need access to the paint server used to draw the current text chunk. - // They need to be able to call renderPath() on a SVGPaintServer object. - ASSERT(textPaintInfo.activePaintServer); - run.setActivePaintServer(textPaintInfo.activePaintServer); + // SVG Fonts need access to the painting resource used to draw the current text chunk. + ASSERT(textPaintInfo.activePaintingResource); + run.setActivePaintingResource(textPaintInfo.activePaintingResource); #endif int selectionStart = 0; @@ -569,18 +568,20 @@ void SVGInlineTextBox::paintDecoration(ETextDecoration decoration, GraphicsConte if (isFilled) { if (RenderObject* fillObject = info.fillServerMap.get(decoration)) { - if (SVGPaintServer* fillPaintServer = SVGPaintServer::fillPaintServer(fillObject->style(), fillObject)) { + if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(fillObject, fillObject->style())) { context->addPath(pathForDecoration(decoration, fillObject, tx, ty, width)); - fillPaintServer->draw(context, fillObject, ApplyToFillTargetType); + if (fillPaintingResource->applyResource(fillObject, fillObject->style(), context, ApplyToFillMode)) + fillPaintingResource->postApplyResource(fillObject, context, ApplyToFillMode); } } } if (isStroked) { if (RenderObject* strokeObject = info.strokeServerMap.get(decoration)) { - if (SVGPaintServer* strokePaintServer = SVGPaintServer::strokePaintServer(strokeObject->style(), strokeObject)) { + if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(strokeObject, strokeObject->style())) { context->addPath(pathForDecoration(decoration, strokeObject, tx, ty, width)); - strokePaintServer->draw(context, strokeObject, ApplyToStrokeTargetType); + if (strokePaintingResource->applyResource(strokeObject, strokeObject->style(), context, ApplyToStrokeMode)) + strokePaintingResource->postApplyResource(strokeObject, context, ApplyToStrokeMode); } } } diff --git a/WebCore/rendering/SVGInlineTextBox.h b/WebCore/rendering/SVGInlineTextBox.h index 596fdf3..c586ddd 100644 --- a/WebCore/rendering/SVGInlineTextBox.h +++ b/WebCore/rendering/SVGInlineTextBox.h @@ -24,6 +24,7 @@ #if ENABLE(SVG) #include "InlineTextBox.h" +#include "RenderSVGResource.h" namespace WebCore { @@ -42,9 +43,13 @@ namespace WebCore { }; struct SVGTextPaintInfo { - SVGTextPaintInfo() : activePaintServer(0), subphase(SVGTextPaintSubphaseBackground) {} + SVGTextPaintInfo() + : activePaintingResource(0) + , subphase(SVGTextPaintSubphaseBackground) + { + } - SVGPaintServer* activePaintServer; + RenderSVGResource* activePaintingResource; SVGTextPaintSubphase subphase; }; diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp index dd67746..2600512 100644 --- a/WebCore/rendering/SVGRenderSupport.cpp +++ b/WebCore/rendering/SVGRenderSupport.cpp @@ -31,6 +31,7 @@ #include "AffineTransform.h" #include "Document.h" #include "ImageBuffer.h" +#include "NodeRenderStyle.h" #include "RenderObject.h" #include "RenderSVGContainer.h" #include "RenderSVGResource.h" @@ -92,7 +93,7 @@ bool SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject ASSERT(svgElement && svgElement->document() && svgElement->isStyled()); SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); - const RenderStyle* style = object->style(); + RenderStyle* style = object->style(); ASSERT(style); const SVGRenderStyle* svgStyle = style->svgStyle(); @@ -132,19 +133,19 @@ bool SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject #endif if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(document, maskerId)) { - if (!masker->applyResource(object, paintInfo.context)) + if (!masker->applyResource(object, style, paintInfo.context, ApplyToDefaultMode)) return false; } else if (!maskerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement); if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(document, clipperId)) - clipper->applyResource(object, paintInfo.context); + clipper->applyResource(object, style, paintInfo.context, ApplyToDefaultMode); else if (!clipperId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement); #if ENABLE(FILTERS) if (filter) { - if (!filter->applyResource(object, paintInfo.context)) + if (!filter->applyResource(object, style, paintInfo.context, ApplyToDefaultMode)) return false; } else if (!filterId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement); @@ -167,7 +168,7 @@ void SVGRenderBase::finishRenderSVGContent(RenderObject* object, RenderObject::P #if ENABLE(FILTERS) if (filter) { - filter->postApplyResource(object, paintInfo.context); + filter->postApplyResource(object, paintInfo.context, ApplyToDefaultMode); paintInfo.context = savedContext; } #endif @@ -306,23 +307,57 @@ FloatRect SVGRenderBase::maskerBoundingBoxForRenderer(const RenderObject* object return FloatRect(); } +static inline void invalidatePaintingResource(SVGPaint* paint, RenderObject* object) +{ + ASSERT(paint); + + SVGPaint::SVGPaintType paintType = paint->paintType(); + if (paintType != SVGPaint::SVG_PAINTTYPE_URI && paintType != SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR) + return; + + AtomicString id(SVGURIReference::getTarget(paint->uri())); + if (RenderSVGResourceContainer* paintingResource = getRenderSVGResourceContainerById(object->document(), id)) + paintingResource->invalidateClient(object); +} + void deregisterFromResources(RenderObject* object) { - // We only have the renderer for masker and clipper at the moment. - if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object->document(), object->style()->svgStyle()->maskerResource())) + ASSERT(object); + ASSERT(object->style()); + + Document* document = object->document(); + ASSERT(document); + + const SVGRenderStyle* svgStyle = object->style()->svgStyle(); + ASSERT(svgStyle); + + // Masker + if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(document, svgStyle->maskerResource())) masker->invalidateClient(object); - if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(object->document(), object->style()->svgStyle()->clipperResource())) + + // Clipper + if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(document, svgStyle->clipperResource())) clipper->invalidateClient(object); + + // Filter #if ENABLE(FILTERS) - if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(object->document(), object->style()->svgStyle()->filterResource())) + if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(document, svgStyle->filterResource())) filter->invalidateClient(object); #endif - if (RenderSVGResourceMarker* startMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(object->document(), object->style()->svgStyle()->markerStartResource())) + + // Markers + if (RenderSVGResourceMarker* startMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(document, svgStyle->markerStartResource())) startMarker->invalidateClient(object); - if (RenderSVGResourceMarker* midMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(object->document(), object->style()->svgStyle()->markerMidResource())) + if (RenderSVGResourceMarker* midMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(document, svgStyle->markerMidResource())) midMarker->invalidateClient(object); - if (RenderSVGResourceMarker* endMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(object->document(), object->style()->svgStyle()->markerEndResource())) + if (RenderSVGResourceMarker* endMarker = getRenderSVGResourceById<RenderSVGResourceMarker>(document, svgStyle->markerEndResource())) endMarker->invalidateClient(object); + + // Gradients/Patterns + if (svgStyle->hasFill()) + invalidatePaintingResource(svgStyle->fillPaint(), object); + if (svgStyle->hasStroke()) + invalidatePaintingResource(svgStyle->strokePaint(), object); } void applyTransformToPaintInfo(RenderObject::PaintInfo& paintInfo, const AffineTransform& localToAncestorTransform) @@ -334,6 +369,42 @@ void applyTransformToPaintInfo(RenderObject::PaintInfo& paintInfo, const AffineT paintInfo.rect = localToAncestorTransform.inverse().mapRect(paintInfo.rect); } +DashArray dashArrayFromRenderingStyle(const RenderStyle* style, RenderStyle* rootStyle) +{ + DashArray array; + + CSSValueList* dashes = style->svgStyle()->strokeDashArray(); + if (dashes) { + CSSPrimitiveValue* dash = 0; + unsigned long len = dashes->length(); + for (unsigned long i = 0; i < len; i++) { + dash = static_cast<CSSPrimitiveValue*>(dashes->itemWithoutBoundsCheck(i)); + if (!dash) + continue; + + array.append((float) dash->computeLengthFloat(const_cast<RenderStyle*>(style), rootStyle)); + } + } + + return array; +} + +void applyStrokeStyleToContext(GraphicsContext* context, const RenderStyle* style, const RenderObject* object) +{ + context->setStrokeThickness(SVGRenderStyle::cssPrimitiveToLength(object, style->svgStyle()->strokeWidth(), 1.0f)); + context->setLineCap(style->svgStyle()->capStyle()); + context->setLineJoin(style->svgStyle()->joinStyle()); + if (style->svgStyle()->joinStyle() == MiterJoin) + context->setMiterLimit(style->svgStyle()->strokeMiterLimit()); + + const DashArray& dashes = dashArrayFromRenderingStyle(object->style(), object->document()->documentElement()->renderStyle()); + float dashOffset = SVGRenderStyle::cssPrimitiveToLength(object, style->svgStyle()->strokeDashOffset(), 0.0f); + if (dashes.isEmpty()) + context->setStrokeStyle(SolidStroke); + else + context->setLineDash(dashes, dashOffset); +} + const RenderObject* findTextRootObject(const RenderObject* start) { while (start && !start->isSVGText()) diff --git a/WebCore/rendering/SVGRenderSupport.h b/WebCore/rendering/SVGRenderSupport.h index 4b59b71..b8a014a 100644 --- a/WebCore/rendering/SVGRenderSupport.h +++ b/WebCore/rendering/SVGRenderSupport.h @@ -25,6 +25,7 @@ #define SVGRenderBase_h #if ENABLE(SVG) +#include "DashArray.h" #include "RenderObject.h" #include "SVGElement.h" #include "SVGStyledElement.h" @@ -42,8 +43,6 @@ class SVGRenderBase { public: virtual ~SVGRenderBase(); - virtual const SVGRenderBase* toSVGRenderBase() const { return this; } - // FIXME: These are only public for SVGRootInlineBox. // It's unclear if these should be exposed or not. SVGRootInlineBox may // pass the wrong RenderObject* and boundingBox to these functions. @@ -56,8 +55,8 @@ public: // Helper function determining wheter overflow is hidden static bool isOverflowHidden(const RenderObject*); + // strokeBoundingBox() includes the marker boundaries for a RenderPath object virtual FloatRect strokeBoundingBox() const { return FloatRect(); } - virtual FloatRect markerBoundingBox() const { return FloatRect(); } // returns the bounding box of filter, clipper, marker and masker (or the empty rect if no filter) in local coordinates FloatRect filterBoundingBoxForRenderer(const RenderObject*) const; @@ -85,7 +84,11 @@ void renderSubtreeToImage(ImageBuffer*, RenderObject*); void deregisterFromResources(RenderObject*); void clampImageBufferSizeToViewport(FrameView*, IntSize& imageBufferSize); +void applyStrokeStyleToContext(GraphicsContext*, const RenderStyle*, const RenderObject*); +DashArray dashArrayFromRenderingStyle(const RenderStyle* style, RenderStyle* rootStyle); + const RenderObject* findTextRootObject(const RenderObject* start); + } // namespace WebCore #endif // ENABLE(SVG) diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp index 0f1f15d..f6fbae2 100644 --- a/WebCore/rendering/SVGRenderTreeAsText.cpp +++ b/WebCore/rendering/SVGRenderTreeAsText.cpp @@ -34,26 +34,37 @@ #include "GraphicsTypes.h" #include "HTMLNames.h" #include "InlineTextBox.h" +#include "LinearGradientAttributes.h" #include "NodeRenderStyle.h" #include "Path.h" +#include "PatternAttributes.h" +#include "RadialGradientAttributes.h" #include "RenderImage.h" #include "RenderPath.h" #include "RenderSVGContainer.h" +#include "RenderSVGGradientStop.h" #include "RenderSVGInlineText.h" #include "RenderSVGResourceClipper.h" #include "RenderSVGResourceFilter.h" +#include "RenderSVGResourceGradient.h" +#include "RenderSVGResourceLinearGradient.h" #include "RenderSVGResourceMarker.h" #include "RenderSVGResourceMasker.h" +#include "RenderSVGResourcePattern.h" +#include "RenderSVGResourceRadialGradient.h" +#include "RenderSVGResourceSolidColor.h" #include "RenderSVGRoot.h" #include "RenderSVGText.h" #include "RenderTreeAsText.h" #include "SVGCharacterLayoutInfo.h" #include "SVGInlineTextBox.h" -#include "SVGPaintServerGradient.h" -#include "SVGPaintServerPattern.h" -#include "SVGPaintServerSolid.h" +#include "SVGLinearGradientElement.h" +#include "SVGPatternElement.h" +#include "SVGRadialGradientElement.h" #include "SVGRootInlineBox.h" +#include "SVGStopElement.h" #include "SVGStyledElement.h" + #include <math.h> namespace WebCore { @@ -307,6 +318,47 @@ static TextStream& operator<<(TextStream& ts, LineJoin style) return ts; } +// FIXME: Maybe this should be in Gradient.cpp +static TextStream& operator<<(TextStream& ts, GradientSpreadMethod mode) +{ + switch (mode) { + case SpreadMethodPad: + ts << "PAD"; + break; + case SpreadMethodRepeat: + ts << "REPEAT"; + break; + case SpreadMethodReflect: + ts << "REFLECT"; + break; + } + + return ts; +} + +static void writeSVGPaintingResource(TextStream& ts, RenderSVGResource* resource) +{ + if (resource->resourceType() == SolidColorResourceType) { + ts << "[type=SOLID] [color=" << static_cast<RenderSVGResourceSolidColor*>(resource)->color() << "]"; + return; + } + + // All other resources derive from RenderSVGResourceContainer + RenderSVGResourceContainer* container = static_cast<RenderSVGResourceContainer*>(resource); + Node* node = container->node(); + ASSERT(node); + ASSERT(node->isSVGElement()); + + if (resource->resourceType() == PatternResourceType) + ts << "[type=PATTERN]"; + else if (resource->resourceType() == LinearGradientResourceType) + ts << "[type=LINEAR-GRADIENT]"; + else if (resource->resourceType() == RadialGradientResourceType) + ts << "[type=RADIAL-GRADIENT]"; + + ts << " [id=\"" << static_cast<SVGElement*>(node)->getIDAttribute() << "\"]"; +} + static void writeStyle(TextStream& ts, const RenderObject& object) { const RenderStyle* style = object.style(); @@ -318,12 +370,11 @@ static void writeStyle(TextStream& ts, const RenderObject& object) writeIfNotDefault(ts, "opacity", style->opacity(), RenderStyle::initialOpacity()); if (object.isRenderPath()) { const RenderPath& path = static_cast<const RenderPath&>(object); - SVGPaintServer* strokePaintServer = SVGPaintServer::strokePaintServer(style, &path); - if (strokePaintServer) { + + if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(&path, path.style())) { TextStreamSeparator s(" "); - ts << " [stroke={"; - if (strokePaintServer) - ts << s << *strokePaintServer; + ts << " [stroke={" << s; + writeSVGPaintingResource(ts, strokePaintingResource); double dashOffset = SVGRenderStyle::cssPrimitiveToLength(&path, svgStyle->strokeDashOffset(), 0.0f); const DashArray& dashArray = dashArrayFromRenderingStyle(style, object.document()->documentElement()->renderStyle()); @@ -340,12 +391,11 @@ static void writeStyle(TextStream& ts, const RenderObject& object) ts << "}]"; } - SVGPaintServer* fillPaintServer = SVGPaintServer::fillPaintServer(style, &path); - if (fillPaintServer) { + + if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(&path, path.style())) { TextStreamSeparator s(" "); - ts << " [fill={"; - if (fillPaintServer) - ts << s << *fillPaintServer; + ts << " [fill={" << s; + writeSVGPaintingResource(ts, fillPaintingResource); writeIfNotDefault(ts, "opacity", svgStyle->fillOpacity(), 1.0f); writeIfNotDefault(ts, "fill rule", svgStyle->fillRule(), RULE_NONZERO); @@ -515,7 +565,23 @@ static void writeChildren(TextStream& ts, const RenderObject& object, int indent write(ts, *child, indent + 1); } -void writeSVGResource(TextStream& ts, const RenderObject& object, int indent) +static inline String boundingBoxModeString(bool boundingBoxMode) +{ + return boundingBoxMode ? "objectBoundingBox" : "userSpaceOnUse"; +} + +static inline void writeCommonGradientProperties(TextStream& ts, GradientSpreadMethod spreadMethod, const AffineTransform& gradientTransform, bool boundingBoxMode) +{ + writeNameValuePair(ts, "gradientUnits", boundingBoxModeString(boundingBoxMode)); + + if (spreadMethod != SpreadMethodPad) + ts << " [spreadMethod=" << spreadMethod << "]"; + + if (!gradientTransform.isIdentity()) + ts << " [gradientTransform=" << gradientTransform << "]"; +} + +void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int indent) { writeStandardPrefix(ts, object, indent); @@ -523,16 +589,16 @@ void writeSVGResource(TextStream& ts, const RenderObject& object, int indent) const AtomicString& id = element->getIDAttribute(); writeNameAndQuotedValue(ts, "id", id); - RenderSVGResource* resource = const_cast<RenderObject&>(object).toRenderSVGResource(); + RenderSVGResourceContainer* resource = const_cast<RenderObject&>(object).toRenderSVGResourceContainer(); + ASSERT(resource); + if (resource->resourceType() == MaskerResourceType) { RenderSVGResourceMasker* masker = static_cast<RenderSVGResourceMasker*>(resource); - ASSERT(masker); writeNameValuePair(ts, "maskUnits", masker->maskUnits()); writeNameValuePair(ts, "maskContentUnits", masker->maskContentUnits()); #if ENABLE(FILTERS) } else if (resource->resourceType() == FilterResourceType) { RenderSVGResourceFilter* filter = static_cast<RenderSVGResourceFilter*>(resource); - ASSERT(filter); writeNameValuePair(ts, "filterUnits", filter->filterUnits()); writeNameValuePair(ts, "primitiveUnits", filter->primitiveUnits()); if (OwnPtr<SVGFilterBuilder> builder = filter->buildPrimitives()) { @@ -558,11 +624,9 @@ void writeSVGResource(TextStream& ts, const RenderObject& object, int indent) #endif } else if (resource->resourceType() == ClipperResourceType) { RenderSVGResourceClipper* clipper = static_cast<RenderSVGResourceClipper*>(resource); - ASSERT(clipper); writeNameValuePair(ts, "clipPathUnits", clipper->clipPathUnits()); } else if (resource->resourceType() == MarkerResourceType) { RenderSVGResourceMarker* marker = static_cast<RenderSVGResourceMarker*>(resource); - ASSERT(marker); writeNameValuePair(ts, "markerUnits", marker->markerUnits()); ts << " [ref at " << marker->referencePoint() << "]"; ts << " [angle="; @@ -570,6 +634,49 @@ void writeSVGResource(TextStream& ts, const RenderObject& object, int indent) ts << "auto" << "]"; else ts << marker->angle() << "]"; + } else if (resource->resourceType() == PatternResourceType) { + RenderSVGResourcePattern* pattern = static_cast<RenderSVGResourcePattern*>(resource); + + // Dump final results that are used for rendering. No use in asking SVGPatternElement for its patternUnits(), as it may + // link to other patterns using xlink:href, we need to build the full inheritance chain, aka. collectPatternProperties() + PatternAttributes attributes = static_cast<SVGPatternElement*>(pattern->node())->collectPatternProperties(); + writeNameValuePair(ts, "patternUnits", boundingBoxModeString(attributes.boundingBoxMode())); + writeNameValuePair(ts, "patternContentUnits", boundingBoxModeString(attributes.boundingBoxModeContent())); + + AffineTransform transform = attributes.patternTransform(); + if (!transform.isIdentity()) + ts << " [patternTransform=" << transform << "]"; + } else if (resource->resourceType() == LinearGradientResourceType) { + RenderSVGResourceLinearGradient* gradient = static_cast<RenderSVGResourceLinearGradient*>(resource); + + // Dump final results that are used for rendering. No use in asking SVGGradientElement for its gradientUnits(), as it may + // link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties() + SVGLinearGradientElement* linearGradientElement = static_cast<SVGLinearGradientElement*>(gradient->node()); + + LinearGradientAttributes attributes = linearGradientElement->collectGradientProperties(); + writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.boundingBoxMode()); + + FloatPoint startPoint; + FloatPoint endPoint; + linearGradientElement->calculateStartEndPoints(attributes, startPoint, endPoint); + + ts << " [start=" << startPoint << "] [end=" << endPoint << "]"; + } else if (resource->resourceType() == RadialGradientResourceType) { + RenderSVGResourceRadialGradient* gradient = static_cast<RenderSVGResourceRadialGradient*>(resource); + + // Dump final results that are used for rendering. No use in asking SVGGradientElement for its gradientUnits(), as it may + // link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties() + SVGRadialGradientElement* radialGradientElement = static_cast<SVGRadialGradientElement*>(gradient->node()); + + RadialGradientAttributes attributes = radialGradientElement->collectGradientProperties(); + writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.boundingBoxMode()); + + FloatPoint focalPoint; + FloatPoint centerPoint; + float radius; + radialGradientElement->calculateFocalCenterPointsAndRadius(attributes, focalPoint, centerPoint, radius); + + ts << " [center=" << centerPoint << "] [focal=" << focalPoint << "] [radius=" << radius << "]"; } ts << "\n"; @@ -626,6 +733,20 @@ void write(TextStream& ts, const RenderPath& path, int indent) writeResources(ts, path, indent); } +void writeSVGGradientStop(TextStream& ts, const RenderSVGGradientStop& stop, int indent) +{ + writeStandardPrefix(ts, stop, indent); + + SVGStopElement* stopElement = static_cast<SVGStopElement*>(stop.node()); + ASSERT(stopElement); + + RenderStyle* style = stop.style(); + if (!style) + return; + + ts << " [offset=" << stopElement->offset() << "] [color=" << stopElement->stopColorIncludingOpacity() << "]\n"; +} + void writeResources(TextStream& ts, const RenderObject& object, int indent) { const RenderStyle* style = object.style(); @@ -665,31 +786,6 @@ void writeResources(TextStream& ts, const RenderObject& object, int indent) #endif } -void writeRenderResources(TextStream& ts, Node* parent) -{ - ASSERT(parent); - Node* node = parent; - do { - if (!node->isSVGElement()) - continue; - SVGElement* svgElement = static_cast<SVGElement*>(node); - if (!svgElement->isStyled()) - continue; - - SVGStyledElement* styled = static_cast<SVGStyledElement*>(svgElement); - RefPtr<SVGResource> resource(styled->canvasResource(node->renderer())); - if (!resource) - continue; - - String elementId = svgElement->getAttribute(svgElement->idAttributeName()); - // FIXME: These names are lies! - if (resource->isPaintServer()) { - RefPtr<SVGPaintServer> paintServer = WTF::static_pointer_cast<SVGPaintServer>(resource); - ts << "KRenderingPaintServer {id=\"" << elementId << "\" " << *paintServer << "}" << "\n"; - } - } while ((node = node->traverseNextNode(parent))); -} - } // namespace WebCore #endif // ENABLE(SVG) diff --git a/WebCore/rendering/SVGRenderTreeAsText.h b/WebCore/rendering/SVGRenderTreeAsText.h index 905652b..0fda958 100644 --- a/WebCore/rendering/SVGRenderTreeAsText.h +++ b/WebCore/rendering/SVGRenderTreeAsText.h @@ -43,6 +43,7 @@ namespace WebCore { class RenderImage; class RenderObject; class RenderPath; + class RenderSVGGradientStop; class RenderSVGRoot; class RenderText; class AffineTransform; @@ -51,15 +52,14 @@ namespace WebCore { // functions used by the main RenderTreeAsText code void write(TextStream&, const RenderPath&, int indent); void write(TextStream&, const RenderSVGRoot&, int indent); -void writeSVGResource(TextStream&, const RenderObject&, int indent); +void writeSVGGradientStop(TextStream&, const RenderSVGGradientStop&, int indent); +void writeSVGResourceContainer(TextStream&, const RenderObject&, int indent); void writeSVGContainer(TextStream&, const RenderObject&, int indent); void writeSVGImage(TextStream&, const RenderImage&, int indent); void writeSVGInlineText(TextStream&, const RenderText&, int indent); void writeSVGText(TextStream&, const RenderBlock&, int indent); void writeResources(TextStream&, const RenderObject&, int indent); -void writeRenderResources(TextStream&, Node* parent); - // helper operators defined used in various classes to dump the render tree. TextStream& operator<<(TextStream&, const AffineTransform&); TextStream& operator<<(TextStream&, const IntRect&); diff --git a/WebCore/rendering/SVGRootInlineBox.cpp b/WebCore/rendering/SVGRootInlineBox.cpp index 89b4375..6c99b1a 100644 --- a/WebCore/rendering/SVGRootInlineBox.cpp +++ b/WebCore/rendering/SVGRootInlineBox.cpp @@ -4,6 +4,7 @@ * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz> * (C) 2006 Apple Computer Inc. * (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) Research In Motion Limited 2010. 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 @@ -32,12 +33,12 @@ #include "Frame.h" #include "GraphicsContext.h" #include "RenderBlock.h" +#include "RenderSVGResource.h" #include "RenderSVGResourceFilter.h" #include "RenderSVGRoot.h" #include "SVGInlineFlowBox.h" #include "SVGInlineTextBox.h" #include "SVGFontElement.h" -#include "SVGPaintServer.h" #include "SVGRenderStyleDefs.h" #include "SVGRenderSupport.h" #include "SVGTextPositioningElement.h" @@ -319,7 +320,7 @@ FloatPoint topLeftPositionOfCharacterRange(Vector<SVGChar>::iterator it, Vector< } // Helper function -static float calculateKerning(RenderObject* item) +static float calculateCSSKerning(RenderObject* item) { const Font& font = item->style()->font(); const SVGRenderStyle* svgStyle = item->style()->svgStyle(); @@ -335,6 +336,40 @@ static float calculateKerning(RenderObject* item) return kerning; } +static bool applySVGKerning(SVGCharacterLayoutInfo& info, RenderObject* item, LastGlyphInfo& lastGlyph, const String& unicodeString, const String& glyphName) +{ +#if ENABLE(SVG_FONTS) + float kerning = 0.0f; + const RenderStyle* style = item->style(); + SVGFontElement* svgFont = 0; + if (style->font().isSVGFont()) + svgFont = style->font().svgFont(); + + if (lastGlyph.isValid && style->font().isSVGFont()) + kerning = svgFont->getHorizontalKerningPairForStringsAndGlyphs(lastGlyph.unicode, lastGlyph.glyphName, unicodeString, glyphName); + + if (style->font().isSVGFont()) { + lastGlyph.unicode = unicodeString; + lastGlyph.glyphName = glyphName; + lastGlyph.isValid = true; + kerning *= style->font().size() / style->font().primaryFont()->unitsPerEm(); + } else + lastGlyph.isValid = false; + + if (kerning != 0.0f) { + info.curx -= kerning; + return true; + } +#else + UNUSED_PARAM(info); + UNUSED_PARAM(item); + UNUSED_PARAM(lastGlyph); + UNUSED_PARAM(unicodeString); + UNUSED_PARAM(glyphName); +#endif + return false; +} + // Helper class for paint() struct SVGRootInlineBoxPaintWalker { SVGRootInlineBoxPaintWalker(SVGRootInlineBox* rootBox, RenderSVGResourceFilter* rootFilter, RenderObject::PaintInfo paintInfo, int tx, int ty) @@ -345,10 +380,10 @@ struct SVGRootInlineBoxPaintWalker { , m_boundingBox(tx + rootBox->x(), ty + rootBox->y(), rootBox->width(), rootBox->height()) , m_filter(0) , m_rootFilter(rootFilter) - , m_fillPaintServer(0) - , m_strokePaintServer(0) - , m_fillPaintServerObject(0) - , m_strokePaintServerObject(0) + , m_fillPaintingResource(0) + , m_strokePaintingResource(0) + , m_fillPaintingResourceObject(0) + , m_strokePaintingResourceObject(0) , m_tx(tx) , m_ty(ty) { @@ -357,10 +392,10 @@ struct SVGRootInlineBoxPaintWalker { ~SVGRootInlineBoxPaintWalker() { ASSERT(!m_filter); - ASSERT(!m_fillPaintServer); - ASSERT(!m_fillPaintServerObject); - ASSERT(!m_strokePaintServer); - ASSERT(!m_strokePaintServerObject); + ASSERT(!m_fillPaintingResource); + ASSERT(!m_fillPaintingResourceObject); + ASSERT(!m_strokePaintingResource); + ASSERT(!m_strokePaintingResourceObject); ASSERT(!m_chunkStarted); } @@ -373,24 +408,22 @@ struct SVGRootInlineBoxPaintWalker { void teardownFillPaintServer() { - if (!m_fillPaintServer) + if (!m_fillPaintingResource) return; - m_fillPaintServer->teardown(m_paintInfo.context, m_fillPaintServerObject, ApplyToFillTargetType, true); - - m_fillPaintServer = 0; - m_fillPaintServerObject = 0; + m_fillPaintingResource->postApplyResource(m_fillPaintingResourceObject, m_paintInfo.context, ApplyToFillMode | ApplyToTextMode); + m_fillPaintingResource = 0; + m_fillPaintingResourceObject = 0; } void teardownStrokePaintServer() { - if (!m_strokePaintServer) + if (!m_strokePaintingResource) return; - m_strokePaintServer->teardown(m_paintInfo.context, m_strokePaintServerObject, ApplyToStrokeTargetType, true); - - m_strokePaintServer = 0; - m_strokePaintServerObject = 0; + m_strokePaintingResource->postApplyResource(m_strokePaintingResourceObject, m_paintInfo.context, ApplyToStrokeMode | ApplyToTextMode); + m_strokePaintingResource = 0; + m_strokePaintingResourceObject = 0; } void chunkStartCallback(InlineBox* box) @@ -437,7 +470,7 @@ struct SVGRootInlineBoxPaintWalker { m_paintInfo.rect = m_savedInfo.rect; } - bool setupBackground(SVGInlineTextBox* /*box*/) + bool setupBackground(SVGInlineTextBox*) { m_textPaintInfo.subphase = SVGTextPaintSubphaseBackground; return true; @@ -451,14 +484,14 @@ struct SVGRootInlineBoxPaintWalker { RenderObject* object = flowBox->renderer(); ASSERT(object); - ASSERT(!m_strokePaintServer); + ASSERT(!m_strokePaintingResource); teardownFillPaintServer(); m_textPaintInfo.subphase = SVGTextPaintSubphaseGlyphFill; - m_fillPaintServer = SVGPaintServer::fillPaintServer(object->style(), object); - if (m_fillPaintServer) { - m_fillPaintServer->setup(m_paintInfo.context, object, ApplyToFillTargetType, true); - m_fillPaintServerObject = object; + m_fillPaintingResource = RenderSVGResource::fillPaintingResource(object, object->style()); + if (m_fillPaintingResource) { + m_fillPaintingResource->applyResource(object, object->style(), m_paintInfo.context, ApplyToFillMode | ApplyToTextMode); + m_fillPaintingResourceObject = object; return true; } @@ -476,17 +509,17 @@ struct SVGRootInlineBoxPaintWalker { if (!style) style = object->style(); - ASSERT(!m_strokePaintServer); + ASSERT(!m_strokePaintingResource); teardownFillPaintServer(); if (!mayHaveSelection(box)) return false; m_textPaintInfo.subphase = SVGTextPaintSubphaseGlyphFillSelection; - m_fillPaintServer = SVGPaintServer::fillPaintServer(style, object); - if (m_fillPaintServer) { - m_fillPaintServer->setup(m_paintInfo.context, object, style, ApplyToFillTargetType, true); - m_fillPaintServerObject = object; + m_fillPaintingResource = RenderSVGResource::fillPaintingResource(object, style); + if (m_fillPaintingResource) { + m_fillPaintingResource->applyResource(object, style, m_paintInfo.context, ApplyToFillMode | ApplyToTextMode); + m_fillPaintingResourceObject = object; return true; } @@ -506,11 +539,10 @@ struct SVGRootInlineBoxPaintWalker { teardownStrokePaintServer(); m_textPaintInfo.subphase = SVGTextPaintSubphaseGlyphStroke; - m_strokePaintServer = SVGPaintServer::strokePaintServer(object->style(), object); - - if (m_strokePaintServer) { - m_strokePaintServer->setup(m_paintInfo.context, object, ApplyToStrokeTargetType, true); - m_strokePaintServerObject = object; + m_strokePaintingResource = RenderSVGResource::strokePaintingResource(object, object->style()); + if (m_strokePaintingResource) { + m_strokePaintingResource->applyResource(object, object->style(), m_paintInfo.context, ApplyToStrokeMode | ApplyToTextMode); + m_strokePaintingResourceObject = object; return true; } @@ -536,17 +568,17 @@ struct SVGRootInlineBoxPaintWalker { return false; m_textPaintInfo.subphase = SVGTextPaintSubphaseGlyphStrokeSelection; - m_strokePaintServer = SVGPaintServer::strokePaintServer(style, object); - if (m_strokePaintServer) { - m_strokePaintServer->setup(m_paintInfo.context, object, style, ApplyToStrokeTargetType, true); - m_strokePaintServerObject = object; + m_strokePaintingResource = RenderSVGResource::strokePaintingResource(object, style); + if (m_strokePaintingResource) { + m_strokePaintingResource->applyResource(object, style, m_paintInfo.context, ApplyToStrokeMode | ApplyToTextMode); + m_strokePaintingResourceObject = object; return true; } return false; } - bool setupForeground(SVGInlineTextBox* /*box*/) + bool setupForeground(SVGInlineTextBox*) { teardownFillPaintServer(); teardownStrokePaintServer(); @@ -556,17 +588,17 @@ struct SVGRootInlineBoxPaintWalker { return true; } - SVGPaintServer* activePaintServer() const + RenderSVGResource* activePaintingResource() const { switch (m_textPaintInfo.subphase) { case SVGTextPaintSubphaseGlyphFill: case SVGTextPaintSubphaseGlyphFillSelection: - ASSERT(m_fillPaintServer); - return m_fillPaintServer; + ASSERT(m_fillPaintingResource); + return m_fillPaintingResource; case SVGTextPaintSubphaseGlyphStroke: case SVGTextPaintSubphaseGlyphStrokeSelection: - ASSERT(m_strokePaintServer); - return m_strokePaintServer; + ASSERT(m_strokePaintingResource); + return m_strokePaintingResource; case SVGTextPaintSubphaseBackground: case SVGTextPaintSubphaseForeground: default: @@ -646,7 +678,7 @@ struct SVGRootInlineBoxPaintWalker { textBox->paintDecoration(OVERLINE, m_paintInfo.context, decorationOrigin.x(), decorationOrigin.y(), textWidth, *it, info); // Paint text - m_textPaintInfo.activePaintServer = activePaintServer(); + m_textPaintInfo.activePaintingResource = activePaintingResource(); textBox->paintCharacters(m_paintInfo, m_tx, m_ty, *it, stringStart, stringLength, m_textPaintInfo); // Paint decorations, that have to be drawn afterwards @@ -672,11 +704,11 @@ private: RenderSVGResourceFilter* m_filter; RenderSVGResourceFilter* m_rootFilter; - SVGPaintServer* m_fillPaintServer; - SVGPaintServer* m_strokePaintServer; + RenderSVGResource* m_fillPaintingResource; + RenderSVGResource* m_strokePaintingResource; - RenderObject* m_fillPaintServerObject; - RenderObject* m_strokePaintServerObject; + RenderObject* m_fillPaintingResourceObject; + RenderObject* m_strokePaintingResourceObject; int m_tx; int m_ty; @@ -1296,7 +1328,7 @@ void SVGRootInlineBox::buildLayoutInformationForTextBox(SVGCharacterLayoutInfo& } // Take letter & word spacing and kerning into account - float spacing = font.letterSpacing() + calculateKerning(textBox->renderer()->node()->renderer()); + float spacing = font.letterSpacing() + calculateCSSKerning(textBox->renderer()->node()->renderer()); const UChar* currentCharacter = text->characters() + (textBox->direction() == RTL ? textBox->end() - i : textBox->start() + i); const UChar* lastCharacter = 0; @@ -1309,7 +1341,9 @@ void SVGRootInlineBox::buildLayoutInformationForTextBox(SVGCharacterLayoutInfo& lastCharacter = text->characters() + textBox->start() + i - 1; } - if (info.nextDrawnSeperated || spacing != 0.0f) { + // FIXME: SVG Kerning doesn't get applied on texts on path. + bool appliedSVGKerning = applySVGKerning(info, textBox->renderer()->node()->renderer(), lastGlyph, unicodeStr, glyphName); + if (info.nextDrawnSeperated || spacing != 0.0f || appliedSVGKerning) { info.nextDrawnSeperated = false; svgChar.drawnSeperated = true; } @@ -1414,35 +1448,12 @@ void SVGRootInlineBox::buildLayoutInformationForTextBox(SVGCharacterLayoutInfo& } } - float kerning = 0.0f; -#if ENABLE(SVG_FONTS) - SVGFontElement* svgFont = 0; - if (style->font().isSVGFont()) - svgFont = style->font().svgFont(); - - if (lastGlyph.isValid && style->font().isSVGFont()) { - SVGHorizontalKerningPair kerningPair; - if (svgFont->getHorizontalKerningPairForStringsAndGlyphs(lastGlyph.unicode, lastGlyph.glyphName, unicodeStr, glyphName, kerningPair)) - kerning = narrowPrecisionToFloat(kerningPair.kerning); - } - - if (style->font().isSVGFont()) { - lastGlyph.unicode = unicodeStr; - lastGlyph.glyphName = glyphName; - lastGlyph.isValid = true; - kerning *= style->font().size() / style->font().primaryFont()->unitsPerEm(); - } else - lastGlyph.isValid = false; -#endif - - svgChar.x -= kerning; - // Advance to new position if (isVerticalText) { svgChar.drawnSeperated = true; info.cury += glyphAdvance + spacing; } else - info.curx += glyphAdvance + spacing - kerning; + info.curx += glyphAdvance + spacing; // Advance to next character group for (int k = 0; k < charsConsumed; ++k) { diff --git a/WebCore/rendering/SVGRootInlineBox.h b/WebCore/rendering/SVGRootInlineBox.h index 7b1dcc4..73c88a1 100644 --- a/WebCore/rendering/SVGRootInlineBox.h +++ b/WebCore/rendering/SVGRootInlineBox.h @@ -27,7 +27,9 @@ #if ENABLE(SVG) #include "RootInlineBox.h" +#include "SVGCharacterData.h" #include "SVGCharacterLayoutInfo.h" +#include "SVGTextChunkLayoutInfo.h" #include "SVGRenderSupport.h" namespace WebCore { @@ -51,7 +53,6 @@ public: , m_height(0) { } - virtual const SVGRenderBase* toSVGRenderBase() const { return this; } virtual bool isSVGRootInlineBox() { return true; } diff --git a/WebCore/rendering/SVGShadowTreeElements.cpp b/WebCore/rendering/SVGShadowTreeElements.cpp index d9ce640..f26f87e 100644 --- a/WebCore/rendering/SVGShadowTreeElements.cpp +++ b/WebCore/rendering/SVGShadowTreeElements.cpp @@ -49,7 +49,7 @@ SVGShadowTreeRootElement::SVGShadowTreeRootElement(Document* document, Node* sha : SVGShadowTreeContainerElement(document) , m_shadowParent(shadowParent) { - setInDocument(true); + setInDocument(); } SVGShadowTreeRootElement::~SVGShadowTreeRootElement() diff --git a/WebCore/rendering/SVGTextChunkLayoutInfo.h b/WebCore/rendering/SVGTextChunkLayoutInfo.h new file mode 100644 index 0000000..524c983 --- /dev/null +++ b/WebCore/rendering/SVGTextChunkLayoutInfo.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) Research In Motion Limited 2010. 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 SVGTextChunkLayoutInfo_h +#define SVGTextChunkLayoutInfo_h + +#if ENABLE(SVG) +#include "AffineTransform.h" +#include "SVGTextContentElement.h" + +#include <wtf/Assertions.h> +#include <wtf/Vector.h> + +namespace WebCore { + +class InlineBox; +class SVGInlineTextBox; + +struct SVGInlineBoxCharacterRange { + SVGInlineBoxCharacterRange() + : startOffset(INT_MIN) + , endOffset(INT_MIN) + , box(0) + { + } + + bool isOpen() const { return (startOffset == endOffset) && (endOffset == INT_MIN); } + bool isClosed() const { return startOffset != INT_MIN && endOffset != INT_MIN; } + + int startOffset; + int endOffset; + + InlineBox* box; +}; + +struct SVGChar; + +// Convenience typedef +typedef SVGTextContentElement::SVGLengthAdjustType ELengthAdjust; + +struct SVGTextChunk { + SVGTextChunk() + : anchor(TA_START) + , textLength(0.0f) + , lengthAdjust(SVGTextContentElement::LENGTHADJUST_SPACING) + , ctm() + , isVerticalText(false) + , isTextPath(false) + , start(0) + , end(0) + { } + + // text-anchor support + ETextAnchor anchor; + + // textLength & lengthAdjust support + float textLength; + ELengthAdjust lengthAdjust; + AffineTransform ctm; + + // status flags + bool isVerticalText : 1; + bool isTextPath : 1; + + // main chunk data + Vector<SVGChar>::iterator start; + Vector<SVGChar>::iterator end; + + Vector<SVGInlineBoxCharacterRange> boxes; +}; + +struct SVGTextChunkWalkerBase { + virtual ~SVGTextChunkWalkerBase() { } + + virtual void operator()(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm, + const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end) = 0; + + // Followings methods are only used for painting text chunks + virtual void start(InlineBox*) = 0; + virtual void end(InlineBox*) = 0; +}; + +template<typename CallbackClass> +struct SVGTextChunkWalker : public SVGTextChunkWalkerBase { +public: + typedef void (CallbackClass::*SVGTextChunkWalkerCallback)(SVGInlineTextBox* textBox, + int startOffset, + const AffineTransform& chunkCtm, + const Vector<SVGChar>::iterator& start, + const Vector<SVGChar>::iterator& end); + + // These callbacks are only used for painting! + typedef void (CallbackClass::*SVGTextChunkStartCallback)(InlineBox* box); + typedef void (CallbackClass::*SVGTextChunkEndCallback)(InlineBox* box); + + SVGTextChunkWalker(CallbackClass* object, + SVGTextChunkWalkerCallback walker, + SVGTextChunkStartCallback start = 0, + SVGTextChunkEndCallback end = 0) + : m_object(object) + , m_walkerCallback(walker) + , m_startCallback(start) + , m_endCallback(end) + { + ASSERT(object); + ASSERT(walker); + } + + virtual void operator()(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm, + const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end) + { + (*m_object.*m_walkerCallback)(textBox, startOffset, chunkCtm, start, end); + } + + // Followings methods are only used for painting text chunks + virtual void start(InlineBox* box) + { + if (m_startCallback) + (*m_object.*m_startCallback)(box); + else + ASSERT_NOT_REACHED(); + } + + virtual void end(InlineBox* box) + { + if (m_endCallback) + (*m_object.*m_endCallback)(box); + else + ASSERT_NOT_REACHED(); + } + +private: + CallbackClass* m_object; + SVGTextChunkWalkerCallback m_walkerCallback; + SVGTextChunkStartCallback m_startCallback; + SVGTextChunkEndCallback m_endCallback; +}; + +struct SVGTextChunkLayoutInfo { + SVGTextChunkLayoutInfo(Vector<SVGTextChunk>& textChunks) + : assignChunkProperties(true) + , handlingTextPath(false) + , svgTextChunks(textChunks) + , it(0) + { + } + + bool assignChunkProperties : 1; + bool handlingTextPath : 1; + + Vector<SVGTextChunk>& svgTextChunks; + Vector<SVGChar>::iterator it; + + SVGTextChunk chunk; +}; + +} // namespace WebCore + +#endif // ENABLE(SVG) +#endif // SVGTextChunkLayoutInfo_h diff --git a/WebCore/rendering/TextControlInnerElements.cpp b/WebCore/rendering/TextControlInnerElements.cpp index 4cd55c5..84f7c0f 100644 --- a/WebCore/rendering/TextControlInnerElements.cpp +++ b/WebCore/rendering/TextControlInnerElements.cpp @@ -96,7 +96,7 @@ void TextControlInnerElement::attachInnerElement(Node* parent, PassRefPtr<Render // Set these explicitly since this normally happens during an attach() setAttached(); - setInDocument(true); + setInDocument(); // For elements without a shadow parent, add the node to the DOM normally. if (!m_shadowParent) @@ -116,16 +116,9 @@ void TextControlInnerTextElement::defaultEventHandler(Event* evt) { // FIXME: In the future, we should add a way to have default event listeners. Then we would add one to the text field's inner div, and we wouldn't need this subclass. Node* shadowAncestor = shadowAncestorNode(); - if (shadowAncestor && shadowAncestor->renderer()) { - ASSERT(shadowAncestor->renderer()->isTextControl()); - if (evt->isBeforeTextInsertedEvent()) { - if (shadowAncestor->renderer()->isTextField()) - static_cast<HTMLInputElement*>(shadowAncestor)->defaultEventHandler(evt); - else - static_cast<HTMLTextAreaElement*>(shadowAncestor)->defaultEventHandler(evt); - } - if (evt->type() == eventNames().webkitEditableContentChangedEvent) - toRenderTextControl(shadowAncestor->renderer())->subtreeHasChanged(); + if (shadowAncestor) { + if (evt->isBeforeTextInsertedEvent() || evt->type() == eventNames().webkitEditableContentChangedEvent) + shadowAncestor->defaultEventHandler(evt); } if (!evt->defaultHandled()) HTMLDivElement::defaultEventHandler(evt); @@ -211,4 +204,62 @@ void SearchFieldCancelButtonElement::defaultEventHandler(Event* evt) HTMLDivElement::defaultEventHandler(evt); } +SpinButtonElement::SpinButtonElement(Document* doc, Node* shadowParent) + : TextControlInnerElement(doc, shadowParent) + , m_capturing(false) + , m_onUpButton(false) +{ +} + +void SpinButtonElement::defaultEventHandler(Event* evt) +{ + if (!evt->isMouseEvent()) { + if (!evt->defaultHandled()) + HTMLDivElement::defaultEventHandler(evt); + return; + } + const MouseEvent* mevt = static_cast<MouseEvent*>(evt); + if (mevt->button() != LeftButton) { + if (!evt->defaultHandled()) + HTMLDivElement::defaultEventHandler(evt); + return; + } + + HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowAncestorNode()); + IntPoint local = roundedIntPoint(renderBox()->absoluteToLocal(mevt->absoluteLocation(), false, true)); + if (evt->type() == eventNames().clickEvent) { + if (renderBox()->borderBoxRect().contains(local)) { + input->focus(); + input->select(); + if (local.y() < renderBox()->y() + renderBox()->height() / 2) + input->stepUpFromRenderer(1); + else + input->stepUpFromRenderer(-1); + evt->setDefaultHandled(); + } + } else if (evt->type() == eventNames().mousemoveEvent) { + if (renderBox()->borderBoxRect().contains(local)) { + if (!m_capturing) { + if (Frame* frame = document()->frame()) { + frame->eventHandler()->setCapturingMouseEventsNode(input); + m_capturing = true; + } + } + bool oldOnUpButton = m_onUpButton; + m_onUpButton = local.y() < renderBox()->y() + renderBox()->height() / 2; + if (m_onUpButton != oldOnUpButton) + renderer()->repaint(); + } else { + if (m_capturing) { + if (Frame* frame = document()->frame()) { + frame->eventHandler()->setCapturingMouseEventsNode(0); + m_capturing = false; + } + } + } + } + if (!evt->defaultHandled()) + HTMLDivElement::defaultEventHandler(evt); +} + } diff --git a/WebCore/rendering/TextControlInnerElements.h b/WebCore/rendering/TextControlInnerElements.h index f72ddf2..f59ac96 100644 --- a/WebCore/rendering/TextControlInnerElements.h +++ b/WebCore/rendering/TextControlInnerElements.h @@ -68,6 +68,21 @@ private: bool m_capturing; }; +class SpinButtonElement : public TextControlInnerElement { +public: + SpinButtonElement(Document*, Node*); + virtual bool isSpinButtonElement() const { return true; } + virtual bool isEnabledFormControl() { return static_cast<Element*>(shadowAncestorNode())->isEnabledFormControl(); } + virtual void defaultEventHandler(Event*); + + bool onUpButton() const { return m_onUpButton; } + static const AtomicString& spinButtonNodeName(); + +private: + bool m_capturing; + bool m_onUpButton; +}; + } //namespace #endif diff --git a/WebCore/rendering/style/RenderStyle.cpp b/WebCore/rendering/style/RenderStyle.cpp index f1cf0bc..f3b3f0c 100644 --- a/WebCore/rendering/style/RenderStyle.cpp +++ b/WebCore/rendering/style/RenderStyle.cpp @@ -58,7 +58,7 @@ PassRefPtr<RenderStyle> RenderStyle::clone(const RenderStyle* other) return adoptRef(new RenderStyle(*other)); } -RenderStyle::RenderStyle() +ALWAYS_INLINE RenderStyle::RenderStyle() : m_affectedByAttributeSelectors(false) , m_unique(false) , m_affectedByEmpty(false) @@ -85,7 +85,7 @@ RenderStyle::RenderStyle() setBitDefaults(); // Would it be faster to copy this from the default style? } -RenderStyle::RenderStyle(bool) +ALWAYS_INLINE RenderStyle::RenderStyle(bool) : m_affectedByAttributeSelectors(false) , m_unique(false) , m_affectedByEmpty(false) @@ -118,7 +118,7 @@ RenderStyle::RenderStyle(bool) #endif } -RenderStyle::RenderStyle(const RenderStyle& o) +ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o) : RefCounted<RenderStyle>() , m_affectedByAttributeSelectors(false) , m_unique(false) diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h index fe42339..815fb30 100644 --- a/WebCore/rendering/style/RenderStyle.h +++ b/WebCore/rendering/style/RenderStyle.h @@ -302,7 +302,7 @@ protected: noninherited_flags._isLink = false; } -protected: +private: RenderStyle(); // used to create the default style. RenderStyle(bool); diff --git a/WebCore/rendering/style/RenderStyleConstants.h b/WebCore/rendering/style/RenderStyleConstants.h index b899d57..b6dce18 100644 --- a/WebCore/rendering/style/RenderStyleConstants.h +++ b/WebCore/rendering/style/RenderStyleConstants.h @@ -74,7 +74,7 @@ enum PseudoId { MEDIA_CONTROLS_SEEK_BACK_BUTTON, MEDIA_CONTROLS_SEEK_FORWARD_BUTTON, MEDIA_CONTROLS_FULLSCREEN_BUTTON, MEDIA_CONTROLS_REWIND_BUTTON, MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON, MEDIA_CONTROLS_TOGGLE_CLOSED_CAPTIONS_BUTTON, MEDIA_CONTROLS_STATUS_DISPLAY, SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER, - INPUT_LIST_BUTTON, INNER_SPIN_BUTTON, OUTER_SPIN_BUTTON, VISITED_LINK, + INPUT_LIST_BUTTON, INNER_SPIN_BUTTON, OUTER_SPIN_BUTTON, VISITED_LINK, PROGRESS_BAR_VALUE, AFTER_LAST_INTERNAL_PSEUDOID, FIRST_PUBLIC_PSEUDOID = FIRST_LINE, diff --git a/WebCore/rendering/style/SVGRenderStyle.h b/WebCore/rendering/style/SVGRenderStyle.h index c6d5022..3d6a7da 100644 --- a/WebCore/rendering/style/SVGRenderStyle.h +++ b/WebCore/rendering/style/SVGRenderStyle.h @@ -108,8 +108,9 @@ public: SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL(String, inheritedResources, markerEnd, MarkerEndResource, markerEndResource, String()) // convenience - bool hasStroke() const { return (strokePaint()->paintType() != SVGPaint::SVG_PAINTTYPE_NONE); } - bool hasFill() const { return (fillPaint()->paintType() != SVGPaint::SVG_PAINTTYPE_NONE); } + bool hasMarkers() const { return !markerStartResource().isEmpty() || !markerMidResource().isEmpty() || !markerEndResource().isEmpty(); } + bool hasStroke() const { return strokePaint()->paintType() != SVGPaint::SVG_PAINTTYPE_NONE; } + bool hasFill() const { return fillPaint()->paintType() != SVGPaint::SVG_PAINTTYPE_NONE; } static float cssPrimitiveToLength(const RenderObject*, CSSValue*, float defaultValue = 0.0f); diff --git a/WebCore/rendering/style/StyleRareInheritedData.h b/WebCore/rendering/style/StyleRareInheritedData.h index 1aa7b05..8f128fd 100644 --- a/WebCore/rendering/style/StyleRareInheritedData.h +++ b/WebCore/rendering/style/StyleRareInheritedData.h @@ -32,7 +32,7 @@ namespace WebCore { -struct ShadowData; +class ShadowData; // This struct is for rarely used inherited CSS3, CSS2, and WebKit-specific properties. // By grouping them together, we save space, and only allocate this object when someone diff --git a/WebCore/rendering/style/StyleRareNonInheritedData.h b/WebCore/rendering/style/StyleRareNonInheritedData.h index 452b273..21bbe94 100644 --- a/WebCore/rendering/style/StyleRareNonInheritedData.h +++ b/WebCore/rendering/style/StyleRareNonInheritedData.h @@ -40,13 +40,14 @@ namespace WebCore { class AnimationList; class CSSStyleSelector; +class ShadowData; class StyleFlexibleBoxData; class StyleMarqueeData; class StyleMultiColData; class StyleReflection; class StyleTransformData; + struct ContentData; -struct ShadowData; #if ENABLE(DASHBOARD_SUPPORT) class StyleDashboardRegion; diff --git a/WebCore/storage/Database.cpp b/WebCore/storage/Database.cpp index cb61d48..0644df5 100644 --- a/WebCore/storage/Database.cpp +++ b/WebCore/storage/Database.cpp @@ -543,6 +543,8 @@ bool Database::performOpenAndVerify(ExceptionCode& e) e = INVALID_STATE_ERR; return false; } + if (!m_sqliteDatabase.turnOnIncrementalAutoVacuum()) + LOG_ERROR("Unable to turn on incremental auto-vacuum for database %s", m_filename.ascii().data()); ASSERT(m_databaseAuthorizer); m_sqliteDatabase.setAuthorizer(m_databaseAuthorizer); @@ -808,6 +810,14 @@ String Database::fileName() const return m_filename.threadsafeCopy(); } +void Database::incrementalVacuumIfNeeded() +{ + int64_t freeSpaceSize = m_sqliteDatabase.freeSpaceSize(); + int64_t totalSize = m_sqliteDatabase.totalSize(); + if (totalSize <= 10 * freeSpaceSize) + m_sqliteDatabase.runIncrementalVacuumCommand(); +} + #endif // ENABLE(DATABASE) } // namespace WebCore diff --git a/WebCore/storage/Database.h b/WebCore/storage/Database.h index f7b88a2..890d98c 100644 --- a/WebCore/storage/Database.h +++ b/WebCore/storage/Database.h @@ -73,7 +73,7 @@ public: ~Database(); -// Direct support for the DOM API + // Direct support for the DOM API static PassRefPtr<Database> openDatabase(ScriptExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback, @@ -85,7 +85,7 @@ public: void transaction(PassRefPtr<SQLTransactionCallback> callback, PassRefPtr<SQLTransactionErrorCallback> errorCallback, PassRefPtr<VoidCallback> successCallback, bool readOnly); -// Internal engine support + // Internal engine support static const String& databaseInfoTableName(); void disableAuthorizer(); @@ -121,7 +121,7 @@ public: unsigned long long databaseSize() const; unsigned long long maximumSize() const; -// Called from DatabaseThread, must be prepared to work on the background thread + // Called from DatabaseThread, must be prepared to work on the background thread void resetAuthorizer(); void performPolicyChecks(); @@ -133,6 +133,8 @@ public: SQLTransactionClient* transactionClient() const; SQLTransactionCoordinator* transactionCoordinator() const; + void incrementalVacuumIfNeeded(); + private: Database(ScriptExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, diff --git a/WebCore/storage/DatabaseCallback.h b/WebCore/storage/DatabaseCallback.h index 2115a21..f87732f 100644 --- a/WebCore/storage/DatabaseCallback.h +++ b/WebCore/storage/DatabaseCallback.h @@ -43,7 +43,7 @@ class ScriptExecutionContext; class DatabaseCallback : public ThreadSafeShared<DatabaseCallback> { public: virtual ~DatabaseCallback() { } - virtual void handleEvent(ScriptExecutionContext*, Database*) = 0; + virtual bool handleEvent(ScriptExecutionContext*, Database*) = 0; }; } diff --git a/WebCore/bindings/js/JSCustomSQLTransactionCallback.h b/WebCore/storage/DatabaseCallback.idl index bf2ae68..7d060fe 100644 --- a/WebCore/bindings/js/JSCustomSQLTransactionCallback.h +++ b/WebCore/storage/DatabaseCallback.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,41 +26,11 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSCustomSQLTransactionCallback_h -#define JSCustomSQLTransactionCallback_h - -#if ENABLE(DATABASE) - -#include "JSDOMGlobalObject.h" -#include "SQLTransactionCallback.h" -#include <wtf/Forward.h> - -namespace WebCore { - -class Frame; -class JSCallbackData; -class JSDOMGlobalObject; - -class JSCustomSQLTransactionCallback : public SQLTransactionCallback { -public: - static PassRefPtr<JSCustomSQLTransactionCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject) - { - return adoptRef(new JSCustomSQLTransactionCallback(callback, globalObject)); - } - - virtual ~JSCustomSQLTransactionCallback(); - - virtual void handleEvent(ScriptExecutionContext*, SQLTransaction*, bool& raisedException); - -private: - JSCustomSQLTransactionCallback(JSC::JSObject* callback, JSDOMGlobalObject*); - - JSCallbackData* m_data; - RefPtr<DOMWrapperWorld> m_isolatedWorld; -}; - +module storage { + interface [ + Conditional=DATABASE, + Callback + ] DatabaseCallback { + boolean handleEvent(in Database database); + }; } - -#endif // ENABLE(DATABASE) - -#endif // JSCustomSQLTransactionCallback_h diff --git a/WebCore/storage/DatabaseSync.cpp b/WebCore/storage/DatabaseSync.cpp new file mode 100644 index 0000000..3c36803 --- /dev/null +++ b/WebCore/storage/DatabaseSync.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2010 Google 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. + */ + +#include "config.h" +#include "DatabaseSync.h" + +#if ENABLE(DATABASE) +#include "DatabaseCallback.h" +#include "ExceptionCode.h" +#include "SQLTransactionSyncCallback.h" +#include "ScriptExecutionContext.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> +#include <wtf/StdLibExtras.h> + +namespace WebCore { + +const String& DatabaseSync::databaseInfoTableName() +{ + DEFINE_STATIC_LOCAL(String, name, ("__WebKitDatabaseInfoTable__")); + return name; +} + +static bool isSyncDatabaseAvailable = true; + +void DatabaseSync::setIsAvailable(bool available) +{ + isSyncDatabaseAvailable = available; +} + +bool DatabaseSync::isAvailable() +{ + return isSyncDatabaseAvailable; +} + +PassRefPtr<DatabaseSync> DatabaseSync::openDatabaseSync(ScriptExecutionContext*, const String&, const String&, const String&, + unsigned long, PassRefPtr<DatabaseCallback>, ExceptionCode& ec) +{ + // FIXME: uncomment the assert once we use the ScriptExecutionContext* parameter + //ASSERT(context->isContextThread()); + + ec = SECURITY_ERR; + return 0; +} + +DatabaseSync::DatabaseSync(ScriptExecutionContext* context, const String& name, const String& expectedVersion, + const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback) + : m_scriptExecutionContext(context) + , m_name(name.crossThreadString()) + , m_expectedVersion(expectedVersion.crossThreadString()) + , m_displayName(displayName.crossThreadString()) + , m_estimatedSize(estimatedSize) + , m_creationCallback(creationCallback) +{ + ASSERT(context->isContextThread()); +} + +DatabaseSync::~DatabaseSync() +{ + ASSERT(m_scriptExecutionContext->isContextThread()); +} + +String DatabaseSync::version() const +{ + ASSERT(m_scriptExecutionContext->isContextThread()); + return String(); +} + +void DatabaseSync::changeVersion(const String&, const String&, PassRefPtr<SQLTransactionSyncCallback>) +{ + ASSERT(m_scriptExecutionContext->isContextThread()); +} + +void DatabaseSync::transaction(PassRefPtr<SQLTransactionSyncCallback>, bool) +{ + ASSERT(m_scriptExecutionContext->isContextThread()); +} + +ScriptExecutionContext* DatabaseSync::scriptExecutionContext() const +{ + ASSERT(m_scriptExecutionContext->isContextThread()); + return m_scriptExecutionContext.get(); +} + +#endif // ENABLE(DATABASE) + +} // namespace WebCore diff --git a/WebCore/storage/DatabaseSync.h b/WebCore/storage/DatabaseSync.h new file mode 100644 index 0000000..c398607 --- /dev/null +++ b/WebCore/storage/DatabaseSync.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2010 Google 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 DatabaseSync_h +#define DatabaseSync_h + +#if ENABLE(DATABASE) +#include "PlatformString.h" +#include <wtf/Forward.h> + +namespace WebCore { + +class DatabaseCallback; +class SQLTransactionSyncCallback; +class ScriptExecutionContext; + +typedef int ExceptionCode; + +// Instances of this class should be created and used only on the worker's context thread. +class DatabaseSync : public RefCounted<DatabaseSync> { +public: + static void setIsAvailable(bool); + static bool isAvailable(); + + ~DatabaseSync(); + + // Direct support for the DOM API + static PassRefPtr<DatabaseSync> openDatabaseSync(ScriptExecutionContext*, const String& name, const String& expectedVersion, + const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback>, ExceptionCode&); + String version() const; + void changeVersion(const String& oldVersion, const String& newVersion, PassRefPtr<SQLTransactionSyncCallback>); + void transaction(PassRefPtr<SQLTransactionSyncCallback>, bool readOnly); + + // Internal engine support + ScriptExecutionContext* scriptExecutionContext() const; + + static const String& databaseInfoTableName(); + +private: + DatabaseSync(ScriptExecutionContext*, const String& name, const String& expectedVersion, + const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback>); + + RefPtr<ScriptExecutionContext> m_scriptExecutionContext; + String m_name; + String m_expectedVersion; + String m_displayName; + unsigned long m_estimatedSize; + RefPtr<DatabaseCallback> m_creationCallback; + +#ifndef NDEBUG + String databaseDebugName() const { return String(); } +#endif +}; + +} // namespace WebCore + +#endif // ENABLE(DATABASE) + +#endif // DatabaseSync_h diff --git a/WebCore/storage/SQLStatement.cpp b/WebCore/storage/SQLStatement.cpp index 64f2634..2e1aea2 100644 --- a/WebCore/storage/SQLStatement.cpp +++ b/WebCore/storage/SQLStatement.cpp @@ -174,7 +174,7 @@ bool SQLStatement::performCallback(SQLTransaction* transaction) ASSERT(m_statementErrorCallback); callbackError = m_statementErrorCallback->handleEvent(transaction->database()->scriptExecutionContext(), transaction, m_error.get()); } else if (m_statementCallback) - m_statementCallback->handleEvent(transaction->database()->scriptExecutionContext(), transaction, m_resultSet.get(), callbackError); + callbackError = !m_statementCallback->handleEvent(transaction->database()->scriptExecutionContext(), transaction, m_resultSet.get()); // Now release our callbacks, to break reference cycles. m_statementCallback = 0; diff --git a/WebCore/storage/SQLStatementCallback.h b/WebCore/storage/SQLStatementCallback.h index ccb8fa7..68e7cb8 100644 --- a/WebCore/storage/SQLStatementCallback.h +++ b/WebCore/storage/SQLStatementCallback.h @@ -41,7 +41,7 @@ class SQLResultSet; class SQLStatementCallback : public ThreadSafeShared<SQLStatementCallback> { public: virtual ~SQLStatementCallback() { } - virtual void handleEvent(ScriptExecutionContext*, SQLTransaction*, SQLResultSet*, bool& raisedException) = 0; + virtual bool handleEvent(ScriptExecutionContext*, SQLTransaction*, SQLResultSet*) = 0; }; } diff --git a/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.h b/WebCore/storage/SQLStatementCallback.idl index bb92393..cc25711 100644 --- a/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.h +++ b/WebCore/storage/SQLStatementCallback.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,39 +26,11 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSCustomSQLTransactionErrorCallback_h -#define JSCustomSQLTransactionErrorCallback_h - -#if ENABLE(DATABASE) - -#include "JSCallbackData.h" -#include "SQLTransactionErrorCallback.h" -#include <wtf/Forward.h> - -namespace WebCore { - -class JSCallbackData; -class SQLError; - -class JSCustomSQLTransactionErrorCallback : public SQLTransactionErrorCallback { -public: - static PassRefPtr<JSCustomSQLTransactionErrorCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject) - { - return adoptRef(new JSCustomSQLTransactionErrorCallback(callback, globalObject)); - } - - virtual ~JSCustomSQLTransactionErrorCallback(); - - virtual void handleEvent(ScriptExecutionContext*, SQLError*); - -private: - JSCustomSQLTransactionErrorCallback(JSC::JSObject* callback, JSDOMGlobalObject* globalObject); - - JSCallbackData* m_data; - RefPtr<DOMWrapperWorld> m_isolatedWorld; -}; - +module storage { + interface [ + Conditional=DATABASE, + Callback + ] SQLStatementCallback { + boolean handleEvent(in SQLTransaction transaction, in SQLResultSet resultSet); + }; } -#endif // ENABLE(DATABASE) - -#endif // JSCustomSQLTransactionErrorCallback_h diff --git a/WebCore/storage/SQLStatementErrorCallback.idl b/WebCore/storage/SQLStatementErrorCallback.idl new file mode 100644 index 0000000..315500d --- /dev/null +++ b/WebCore/storage/SQLStatementErrorCallback.idl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2010 Google 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. + */ + +module storage { + interface [ + Conditional=DATABASE, + Callback + ] SQLStatementErrorCallback { + [Custom] boolean handleEvent(in SQLTransaction transaction, in SQLError error); + }; +} diff --git a/WebCore/storage/SQLTransaction.cpp b/WebCore/storage/SQLTransaction.cpp index ea7deee..aebc293 100644 --- a/WebCore/storage/SQLTransaction.cpp +++ b/WebCore/storage/SQLTransaction.cpp @@ -290,7 +290,7 @@ void SQLTransaction::deliverTransactionCallback() if (m_callback) { m_executeSqlAllowed = true; - m_callback->handleEvent(m_database->scriptExecutionContext(), this, shouldDeliverErrorCallback); + shouldDeliverErrorCallback = !m_callback->handleEvent(m_database->scriptExecutionContext(), this); m_executeSqlAllowed = false; } else shouldDeliverErrorCallback = true; @@ -466,6 +466,9 @@ void SQLTransaction::postflightAndCommit() return; } + // The commit was successful, so vacuum the database if needed + m_database->incrementalVacuumIfNeeded(); + // The commit was successful, notify the delegates if the transaction modified this database if (m_modifiedDatabase) m_database->transactionClient()->didCommitTransaction(this); diff --git a/WebCore/storage/SQLTransactionCallback.h b/WebCore/storage/SQLTransactionCallback.h index 34b7613..048410f 100644 --- a/WebCore/storage/SQLTransactionCallback.h +++ b/WebCore/storage/SQLTransactionCallback.h @@ -37,12 +37,11 @@ namespace WebCore { class ScriptExecutionContext; class SQLTransaction; -class SQLError; class SQLTransactionCallback : public ThreadSafeShared<SQLTransactionCallback> { public: virtual ~SQLTransactionCallback() { } - virtual void handleEvent(ScriptExecutionContext*, SQLTransaction*, bool& raisedException) = 0; + virtual bool handleEvent(ScriptExecutionContext*, SQLTransaction*) = 0; }; } diff --git a/WebCore/storage/SQLTransactionCallback.idl b/WebCore/storage/SQLTransactionCallback.idl new file mode 100644 index 0000000..d1bc77c --- /dev/null +++ b/WebCore/storage/SQLTransactionCallback.idl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2010 Google 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. + */ + +module storage { + interface [ + Conditional=DATABASE, + Callback + ] SQLTransactionCallback { + boolean handleEvent(in SQLTransaction transaction); + }; +} diff --git a/WebCore/storage/SQLTransactionErrorCallback.h b/WebCore/storage/SQLTransactionErrorCallback.h index 6c0d13a..2fe2cb3 100644 --- a/WebCore/storage/SQLTransactionErrorCallback.h +++ b/WebCore/storage/SQLTransactionErrorCallback.h @@ -41,7 +41,7 @@ class SQLError; class SQLTransactionErrorCallback : public ThreadSafeShared<SQLTransactionErrorCallback> { public: virtual ~SQLTransactionErrorCallback() { } - virtual void handleEvent(ScriptExecutionContext*, SQLError*) = 0; + virtual bool handleEvent(ScriptExecutionContext*, SQLError*) = 0; }; } diff --git a/WebCore/storage/SQLTransactionErrorCallback.idl b/WebCore/storage/SQLTransactionErrorCallback.idl new file mode 100644 index 0000000..779ba69 --- /dev/null +++ b/WebCore/storage/SQLTransactionErrorCallback.idl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2010 Google 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. + */ + +module storage { + interface [ + Conditional=DATABASE, + Callback + ] SQLTransactionErrorCallback { + boolean handleEvent(in SQLError error); + }; +} diff --git a/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp b/WebCore/storage/SQLTransactionSync.cpp index 09ff340..5e7c879 100644 --- a/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp +++ b/WebCore/storage/SQLTransactionSync.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,53 +27,47 @@ */ #include "config.h" -#include "JSCustomSQLTransactionErrorCallback.h" +#include "SQLTransactionSync.h" #if ENABLE(DATABASE) -#include "Frame.h" -#include "JSCallbackData.h" -#include "JSSQLError.h" +#include "DatabaseSync.h" +#include "ExceptionCode.h" +#include "PlatformString.h" +#include "SQLResultSet.h" +#include "SQLTransactionSyncCallback.h" +#include "SQLValue.h" #include "ScriptExecutionContext.h" -#include <runtime/JSLock.h> -#include <wtf/MainThread.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> namespace WebCore { -using namespace JSC; - -JSCustomSQLTransactionErrorCallback::JSCustomSQLTransactionErrorCallback(JSObject* callback, JSDOMGlobalObject* globalObject) - : m_data(new JSCallbackData(callback, globalObject)) - , m_isolatedWorld(globalObject->world()) +PassRefPtr<SQLTransactionSync> SQLTransactionSync::create(DatabaseSync* db, PassRefPtr<SQLTransactionSyncCallback> callback, bool readOnly) { + return adoptRef(new SQLTransactionSync(db, callback, readOnly)); } -JSCustomSQLTransactionErrorCallback::~JSCustomSQLTransactionErrorCallback() +SQLTransactionSync::SQLTransactionSync(DatabaseSync* db, PassRefPtr<SQLTransactionSyncCallback> callback, bool readOnly) + : m_database(db) + , m_callback(callback) + , m_readOnly(readOnly) { - callOnMainThread(JSCallbackData::deleteData, m_data); -#ifndef NDEBUG - m_data = 0; -#endif + ASSERT(m_database->scriptExecutionContext()->isContextThread()); + ASSERT(callback); } -void JSCustomSQLTransactionErrorCallback::handleEvent(ScriptExecutionContext* context, SQLError* error) +SQLTransactionSync::~SQLTransactionSync() { - ASSERT(m_data); - ASSERT(context); - - RefPtr<JSCustomSQLTransactionErrorCallback> protect(this); - - JSC::JSLock lock(SilenceAssertionsOnly); - JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get()); - if (!globalObject) - return; - - ExecState* exec = globalObject->globalExec(); - MarkedArgumentBuffer args; - args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), error)); - m_data->invokeCallback(args); + ASSERT(m_database->scriptExecutionContext()->isContextThread()); } +PassRefPtr<SQLResultSet> SQLTransactionSync::executeSQL(const String&, const Vector<SQLValue>&, ExceptionCode&) +{ + ASSERT(m_database->scriptExecutionContext()->isContextThread()); + return 0; } +} // namespace WebCore + #endif // ENABLE(DATABASE) diff --git a/WebCore/storage/SQLTransactionSync.h b/WebCore/storage/SQLTransactionSync.h new file mode 100644 index 0000000..7c03927 --- /dev/null +++ b/WebCore/storage/SQLTransactionSync.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 Google 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 SQLTransactionSync_h +#define SQLTransactionSync_h + +#if ENABLE(DATABASE) + +#include <wtf/Forward.h> +#include <wtf/RefCounted.h> +#include <wtf/Vector.h> + +namespace WebCore { + +typedef int ExceptionCode; + +class DatabaseSync; +class SQLResultSet; +class SQLTransactionSyncCallback; +class SQLValue; +class String; + +// Instances of this class should be created and used only on the worker's context thread. +class SQLTransactionSync : public RefCounted<SQLTransactionSync> { +public: + static PassRefPtr<SQLTransactionSync> create(DatabaseSync*, PassRefPtr<SQLTransactionSyncCallback>, bool readOnly = false); + + ~SQLTransactionSync(); + + PassRefPtr<SQLResultSet> executeSQL(const String& sqlStatement, const Vector<SQLValue>& arguments, ExceptionCode&); + + DatabaseSync* database() { return m_database.get(); } + bool isReadOnly() const { return m_readOnly; } + +private: + SQLTransactionSync(DatabaseSync*, PassRefPtr<SQLTransactionSyncCallback>, bool readOnly); + + RefPtr<DatabaseSync> m_database; + RefPtr<SQLTransactionSyncCallback> m_callback; + bool m_readOnly; +}; + +} // namespace WebCore + +#endif + +#endif // SQLTransactionSync_h diff --git a/WebCore/bindings/js/JSCustomSQLStatementCallback.h b/WebCore/storage/SQLTransactionSyncCallback.h index cb7b34d..d32bbfa 100644 --- a/WebCore/bindings/js/JSCustomSQLStatementCallback.h +++ b/WebCore/storage/SQLTransactionSyncCallback.h @@ -1,10 +1,10 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google 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: - * + *Transaction * 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 @@ -26,39 +26,27 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSCustomSQLStatementCallback_h -#define JSCustomSQLStatementCallback_h +#ifndef SQLTransactionSyncCallback_h +#define SQLTransactionSyncCallback_h #if ENABLE(DATABASE) -#include "JSCallbackData.h" -#include "SQLStatementCallback.h" -#include <wtf/Forward.h> +#include <wtf/Threading.h> namespace WebCore { -class SQLResultSet; +class ScriptExecutionContext; +class SQLTransactionSync; -class JSCustomSQLStatementCallback : public SQLStatementCallback { +// Instances of this class should be created and used only on the worker's context thread. +class SQLTransactionSyncCallback : public RefCounted<SQLTransactionSyncCallback> { public: - static PassRefPtr<JSCustomSQLStatementCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject) - { - return adoptRef(new JSCustomSQLStatementCallback(callback, globalObject)); - } - - virtual ~JSCustomSQLStatementCallback(); - - virtual void handleEvent(ScriptExecutionContext*, SQLTransaction*, SQLResultSet*, bool& raisedException); - -private: - JSCustomSQLStatementCallback(JSC::JSObject* callback, JSDOMGlobalObject*); - - JSCallbackData* m_data; - RefPtr<DOMWrapperWorld> m_isolatedWorld; + virtual ~SQLTransactionSyncCallback() { } + virtual void handleEvent(ScriptExecutionContext*, SQLTransactionSync*, bool& raisedException) = 0; }; } -#endif // ENABLE(DATABASE) +#endif -#endif // JSCustomSQLStatementCallback_h +#endif // SQLTransactionSyncCallback_h diff --git a/WebCore/storage/StorageEvent.cpp b/WebCore/storage/StorageEvent.cpp index f2b1339..a08cde2 100644 --- a/WebCore/storage/StorageEvent.cpp +++ b/WebCore/storage/StorageEvent.cpp @@ -45,22 +45,22 @@ StorageEvent::~StorageEvent() { } -PassRefPtr<StorageEvent> StorageEvent::create(const AtomicString& type, const String& key, const String& oldValue, const String& newValue, const String& uri, Storage* storageArea) +PassRefPtr<StorageEvent> StorageEvent::create(const AtomicString& type, const String& key, const String& oldValue, const String& newValue, const String& url, Storage* storageArea) { - return adoptRef(new StorageEvent(type, key, oldValue, newValue, uri, storageArea)); + return adoptRef(new StorageEvent(type, key, oldValue, newValue, url, storageArea)); } -StorageEvent::StorageEvent(const AtomicString& type, const String& key, const String& oldValue, const String& newValue, const String& uri, Storage* storageArea) +StorageEvent::StorageEvent(const AtomicString& type, const String& key, const String& oldValue, const String& newValue, const String& url, Storage* storageArea) : Event(type, false, false) , m_key(key) , m_oldValue(oldValue) , m_newValue(newValue) - , m_uri(uri) + , m_url(url) , m_storageArea(storageArea) { } -void StorageEvent::initStorageEvent(const AtomicString& type, bool canBubble, bool cancelable, const String& key, const String& oldValue, const String& newValue, const String& uri, Storage* storageArea) +void StorageEvent::initStorageEvent(const AtomicString& type, bool canBubble, bool cancelable, const String& key, const String& oldValue, const String& newValue, const String& url, Storage* storageArea) { if (dispatched()) return; @@ -70,7 +70,7 @@ void StorageEvent::initStorageEvent(const AtomicString& type, bool canBubble, bo m_key = key; m_oldValue = oldValue; m_newValue = newValue; - m_uri = uri; + m_url = url; m_storageArea = storageArea; } diff --git a/WebCore/storage/StorageEvent.h b/WebCore/storage/StorageEvent.h index 918515a..8e558a8 100644 --- a/WebCore/storage/StorageEvent.h +++ b/WebCore/storage/StorageEvent.h @@ -38,30 +38,30 @@ namespace WebCore { class StorageEvent : public Event { public: static PassRefPtr<StorageEvent> create(); - static PassRefPtr<StorageEvent> create(const AtomicString& type, const String& key, const String& oldValue, const String& newValue, const String& uri, Storage* storageArea); + static PassRefPtr<StorageEvent> create(const AtomicString& type, const String& key, const String& oldValue, const String& newValue, const String& url, Storage* storageArea); virtual ~StorageEvent(); const String& key() const { return m_key; } const String& oldValue() const { return m_oldValue; } const String& newValue() const { return m_newValue; } - const String& uri() const { return m_uri; } + const String& url() const { return m_url; } Storage* storageArea() const { return m_storageArea.get(); } - void initStorageEvent(const AtomicString& type, bool canBubble, bool cancelable, const String& key, const String& oldValue, const String& newValue, const String& uri, Storage* storageArea); + void initStorageEvent(const AtomicString& type, bool canBubble, bool cancelable, const String& key, const String& oldValue, const String& newValue, const String& url, Storage* storageArea); // Needed once we support init<blank>EventNS - // void initStorageEventNS(in DOMString namespaceURI, in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString keyArg, in DOMString oldValueArg, in DOMString newValueArg, in DOMString uriArg, Storage storageAreaArg); + // void initStorageEventNS(in DOMString namespaceURI, in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString keyArg, in DOMString oldValueArg, in DOMString newValueArg, in DOMString urlArg, Storage storageAreaArg); virtual bool isStorageEvent() const { return true; } private: StorageEvent(); - StorageEvent(const AtomicString& type, const String& key, const String& oldValue, const String& newValue, const String& uri, Storage* storageArea); + StorageEvent(const AtomicString& type, const String& key, const String& oldValue, const String& newValue, const String& url, Storage* storageArea); String m_key; String m_oldValue; String m_newValue; - String m_uri; + String m_url; RefPtr<Storage> m_storageArea; }; diff --git a/WebCore/storage/StorageEvent.idl b/WebCore/storage/StorageEvent.idl index 3e77eda..3464caa 100644 --- a/WebCore/storage/StorageEvent.idl +++ b/WebCore/storage/StorageEvent.idl @@ -31,12 +31,12 @@ module storage { readonly attribute [ConvertNullStringTo=Null] DOMString key; readonly attribute [ConvertNullStringTo=Null] DOMString oldValue; readonly attribute [ConvertNullStringTo=Null] DOMString newValue; - readonly attribute DOMString uri; + readonly attribute DOMString url; readonly attribute Storage storageArea; - void initStorageEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString keyArg, in [ConvertNullToNullString] DOMString oldValueArg, in [ConvertNullToNullString] DOMString newValueArg, in DOMString uriArg, in Storage storageAreaArg); + void initStorageEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString keyArg, in [ConvertNullToNullString] DOMString oldValueArg, in [ConvertNullToNullString] DOMString newValueArg, in DOMString urlArg, in Storage storageAreaArg); // Needed once we support init<blank>EventNS - // void initStorageEventNS(in DOMString namespaceURI, in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString keyArg, in DOMString oldValueArg, in DOMString newValueArg, in DOMString uriArg, in Storage storageAreaArg); + // void initStorageEventNS(in DOMString namespaceURI, in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString keyArg, in DOMString oldValueArg, in DOMString newValueArg, in DOMString urlArg, in Storage storageAreaArg); }; } diff --git a/WebCore/storage/StorageEventDispatcher.cpp b/WebCore/storage/StorageEventDispatcher.cpp index 2118a83..5833c59 100644 --- a/WebCore/storage/StorageEventDispatcher.cpp +++ b/WebCore/storage/StorageEventDispatcher.cpp @@ -54,8 +54,12 @@ void StorageEventDispatcher::dispatch(const String& key, const String& oldValue, frames.append(frame); } - for (unsigned i = 0; i < frames.size(); ++i) - frames[i]->document()->enqueueEvent(StorageEvent::create(eventNames().storageEvent, key, oldValue, newValue, sourceFrame->document()->url(), frames[i]->domWindow()->sessionStorage())); + for (unsigned i = 0; i < frames.size(); ++i) { + ExceptionCode ec = 0; + Storage* storage = frames[i]->domWindow()->sessionStorage(ec); + if (!ec) + frames[i]->document()->enqueueEvent(StorageEvent::create(eventNames().storageEvent, key, oldValue, newValue, sourceFrame->document()->url(), storage)); + } } else { // Send events to every page. const HashSet<Page*>& pages = page->group().pages(); diff --git a/WebCore/svg/GradientAttributes.h b/WebCore/svg/GradientAttributes.h index ba513b8..473c1b9 100644 --- a/WebCore/svg/GradientAttributes.h +++ b/WebCore/svg/GradientAttributes.h @@ -21,51 +21,72 @@ #define GradientAttributes_h #if ENABLE(SVG) +#include "Color.h" +#include "Gradient.h" +#include "SVGLength.h" namespace WebCore { - struct GradientAttributes { - GradientAttributes() - : m_spreadMethod(SpreadMethodPad) - , m_boundingBoxMode(true) - , m_spreadMethodSet(false) - , m_boundingBoxModeSet(false) - , m_gradientTransformSet(false) - , m_stopsSet(false) - { - } - - GradientSpreadMethod spreadMethod() const { return m_spreadMethod; } - bool boundingBoxMode() const { return m_boundingBoxMode; } - AffineTransform gradientTransform() const { return m_gradientTransform; } - const Vector<SVGGradientStop>& stops() const { return m_stops; } - - void setSpreadMethod(GradientSpreadMethod value) { m_spreadMethod = value; m_spreadMethodSet = true; } - void setBoundingBoxMode(bool value) { m_boundingBoxMode = value; m_boundingBoxModeSet = true; } - void setGradientTransform(const AffineTransform& value) { m_gradientTransform = value; m_gradientTransformSet = true; } - void setStops(const Vector<SVGGradientStop>& value) { m_stops = value; m_stopsSet = true; } - - bool hasSpreadMethod() const { return m_spreadMethodSet; } - bool hasBoundingBoxMode() const { return m_boundingBoxModeSet; } - bool hasGradientTransform() const { return m_gradientTransformSet; } - bool hasStops() const { return m_stopsSet; } - - private: - // Properties - GradientSpreadMethod m_spreadMethod; - bool m_boundingBoxMode; - AffineTransform m_gradientTransform; - Vector<SVGGradientStop> m_stops; - - // Property states - bool m_spreadMethodSet : 1; - bool m_boundingBoxModeSet : 1; - bool m_gradientTransformSet : 1; - bool m_stopsSet : 1; - }; + +struct GradientAttributes { + GradientAttributes() + : m_spreadMethod(SpreadMethodPad) + , m_boundingBoxMode(true) + , m_spreadMethodSet(false) + , m_boundingBoxModeSet(false) + , m_gradientTransformSet(false) + , m_stopsSet(false) + { + } + + GradientSpreadMethod spreadMethod() const { return m_spreadMethod; } + bool boundingBoxMode() const { return m_boundingBoxMode; } + AffineTransform gradientTransform() const { return m_gradientTransform; } + const Vector<Gradient::ColorStop>& stops() const { return m_stops; } + + void setSpreadMethod(GradientSpreadMethod value) + { + m_spreadMethod = value; + m_spreadMethodSet = true; + } + + void setBoundingBoxMode(bool value) + { + m_boundingBoxMode = value; + m_boundingBoxModeSet = true; + } + + void setGradientTransform(const AffineTransform& value) + { + m_gradientTransform = value; + m_gradientTransformSet = true; + } + + void setStops(const Vector<Gradient::ColorStop>& value) + { + m_stops = value; + m_stopsSet = true; + } + + bool hasSpreadMethod() const { return m_spreadMethodSet; } + bool hasBoundingBoxMode() const { return m_boundingBoxModeSet; } + bool hasGradientTransform() const { return m_gradientTransformSet; } + bool hasStops() const { return m_stopsSet; } + +private: + // Properties + GradientSpreadMethod m_spreadMethod; + bool m_boundingBoxMode; + AffineTransform m_gradientTransform; + Vector<Gradient::ColorStop> m_stops; + + // Property states + bool m_spreadMethodSet : 1; + bool m_boundingBoxModeSet : 1; + bool m_gradientTransformSet : 1; + bool m_stopsSet : 1; +}; } // namespace WebCore #endif // ENABLE(SVG) #endif - -// vim:ts=4:noet diff --git a/WebCore/svg/LinearGradientAttributes.h b/WebCore/svg/LinearGradientAttributes.h index b71dc22..af16b8a 100644 --- a/WebCore/svg/LinearGradientAttributes.h +++ b/WebCore/svg/LinearGradientAttributes.h @@ -20,9 +20,8 @@ #ifndef LinearGradientAttributes_h #define LinearGradientAttributes_h -#include "GradientAttributes.h" - #if ENABLE(SVG) +#include "GradientAttributes.h" namespace WebCore { struct LinearGradientAttributes : GradientAttributes { diff --git a/WebCore/svg/PatternAttributes.h b/WebCore/svg/PatternAttributes.h index 2d25763..feaabd9 100644 --- a/WebCore/svg/PatternAttributes.h +++ b/WebCore/svg/PatternAttributes.h @@ -21,80 +21,121 @@ #define PatternAttributes_h #if ENABLE(SVG) +#include "SVGLength.h" namespace WebCore { - struct PatternAttributes { - PatternAttributes() - : m_x() - , m_y() - , m_width() - , m_height() - , m_boundingBoxMode(true) - , m_boundingBoxModeContent(false) - , m_patternContentElement(0) - , m_xSet(false) - , m_ySet(false) - , m_widthSet(false) - , m_heightSet(false) - , m_boundingBoxModeSet(false) - , m_boundingBoxModeContentSet(false) - , m_patternTransformSet(false) - , m_patternContentElementSet(false) - { - } - - SVGLength x() const { return m_x; } - SVGLength y() const { return m_y; } - SVGLength width() const { return m_width; } - SVGLength height() const { return m_height; } - bool boundingBoxMode() const { return m_boundingBoxMode; } - bool boundingBoxModeContent() const { return m_boundingBoxModeContent; } - AffineTransform patternTransform() const { return m_patternTransform; } - const SVGPatternElement* patternContentElement() const { return m_patternContentElement; } - - void setX(const SVGLength& value) { m_x = value; m_xSet = true; } - void setY(const SVGLength& value) { m_y = value; m_ySet = true; } - void setWidth(const SVGLength& value) { m_width = value; m_widthSet = true; } - void setHeight(const SVGLength& value) { m_height = value; m_heightSet = true; } - void setBoundingBoxMode(bool value) { m_boundingBoxMode = value; m_boundingBoxModeSet = true; } - void setBoundingBoxModeContent(bool value) { m_boundingBoxModeContent = value; m_boundingBoxModeContentSet = true; } - void setPatternTransform(const AffineTransform& value) { m_patternTransform = value; m_patternTransformSet = true; } - void setPatternContentElement(const SVGPatternElement* value) { m_patternContentElement = value; m_patternContentElementSet = true; } - - bool hasX() const { return m_xSet; } - bool hasY() const { return m_ySet; } - bool hasWidth() const { return m_widthSet; } - bool hasHeight() const { return m_heightSet; } - bool hasBoundingBoxMode() const { return m_boundingBoxModeSet; } - bool hasBoundingBoxModeContent() const { return m_boundingBoxModeContentSet; } - bool hasPatternTransform() const { return m_patternTransformSet; } - bool hasPatternContentElement() const { return m_patternContentElementSet; } - - private: - // Properties - SVGLength m_x; - SVGLength m_y; - SVGLength m_width; - SVGLength m_height; - bool m_boundingBoxMode; - bool m_boundingBoxModeContent; - AffineTransform m_patternTransform; - const SVGPatternElement* m_patternContentElement; - - // Property states - bool m_xSet : 1; - bool m_ySet : 1; - bool m_widthSet : 1; - bool m_heightSet : 1; - bool m_boundingBoxModeSet : 1; - bool m_boundingBoxModeContentSet : 1; - bool m_patternTransformSet : 1; - bool m_patternContentElementSet : 1; - }; + +class SVGPatternElement; + +struct PatternAttributes { + PatternAttributes() + : m_x() + , m_y() + , m_width() + , m_height() + , m_boundingBoxMode(true) + , m_boundingBoxModeContent(false) + , m_patternContentElement(0) + , m_xSet(false) + , m_ySet(false) + , m_widthSet(false) + , m_heightSet(false) + , m_boundingBoxModeSet(false) + , m_boundingBoxModeContentSet(false) + , m_patternTransformSet(false) + , m_patternContentElementSet(false) + { + } + + SVGLength x() const { return m_x; } + SVGLength y() const { return m_y; } + SVGLength width() const { return m_width; } + SVGLength height() const { return m_height; } + bool boundingBoxMode() const { return m_boundingBoxMode; } + bool boundingBoxModeContent() const { return m_boundingBoxModeContent; } + AffineTransform patternTransform() const { return m_patternTransform; } + const SVGPatternElement* patternContentElement() const { return m_patternContentElement; } + + void setX(const SVGLength& value) + { + m_x = value; + m_xSet = true; + } + + void setY(const SVGLength& value) + { + m_y = value; + m_ySet = true; + } + + void setWidth(const SVGLength& value) + { + m_width = value; + m_widthSet = true; + } + + void setHeight(const SVGLength& value) + { + m_height = value; + m_heightSet = true; + } + + void setBoundingBoxMode(bool value) + { + m_boundingBoxMode = value; + m_boundingBoxModeSet = true; + } + + void setBoundingBoxModeContent(bool value) + { + m_boundingBoxModeContent = value; + m_boundingBoxModeContentSet = true; + } + + void setPatternTransform(const AffineTransform& value) + { + m_patternTransform = value; + m_patternTransformSet = true; + } + + void setPatternContentElement(const SVGPatternElement* value) + { + m_patternContentElement = value; + m_patternContentElementSet = true; + } + + bool hasX() const { return m_xSet; } + bool hasY() const { return m_ySet; } + bool hasWidth() const { return m_widthSet; } + bool hasHeight() const { return m_heightSet; } + bool hasBoundingBoxMode() const { return m_boundingBoxModeSet; } + bool hasBoundingBoxModeContent() const { return m_boundingBoxModeContentSet; } + bool hasPatternTransform() const { return m_patternTransformSet; } + bool hasPatternContentElement() const { return m_patternContentElementSet; } + +private: + // Properties + SVGLength m_x; + SVGLength m_y; + SVGLength m_width; + SVGLength m_height; + bool m_boundingBoxMode; + bool m_boundingBoxModeContent; + AffineTransform m_patternTransform; + const SVGPatternElement* m_patternContentElement; + + // Property states + bool m_xSet : 1; + bool m_ySet : 1; + bool m_widthSet : 1; + bool m_heightSet : 1; + bool m_boundingBoxModeSet : 1; + bool m_boundingBoxModeContentSet : 1; + bool m_patternTransformSet : 1; + bool m_patternContentElementSet : 1; +}; } // namespace WebCore #endif // ENABLE(SVG) #endif - -// vim:ts=4:noet diff --git a/WebCore/svg/RadialGradientAttributes.h b/WebCore/svg/RadialGradientAttributes.h index 76a78ec..b461854 100644 --- a/WebCore/svg/RadialGradientAttributes.h +++ b/WebCore/svg/RadialGradientAttributes.h @@ -20,9 +20,8 @@ #ifndef RadialGradientAttributes_h #define RadialGradientAttributes_h -#include "GradientAttributes.h" - #if ENABLE(SVG) +#include "GradientAttributes.h" namespace WebCore { struct RadialGradientAttributes : GradientAttributes { diff --git a/WebCore/svg/SVGAElement.cpp b/WebCore/svg/SVGAElement.cpp index b344a4e..4a1f18a 100644 --- a/WebCore/svg/SVGAElement.cpp +++ b/WebCore/svg/SVGAElement.cpp @@ -60,7 +60,13 @@ SVGAElement::~SVGAElement() String SVGAElement::title() const { - return getAttribute(XLinkNames::titleAttr); + // If the xlink:title is set (non-empty string), use it. + const AtomicString& title = getAttribute(XLinkNames::titleAttr); + if (!title.isEmpty()) + return title; + + // Otherwise, use the title of this element. + return SVGStyledElement::title(); } void SVGAElement::parseMappedAttribute(MappedAttribute* attr) diff --git a/WebCore/svg/SVGAnimateElement.cpp b/WebCore/svg/SVGAnimateElement.cpp index d431583..ff3317b 100644 --- a/WebCore/svg/SVGAnimateElement.cpp +++ b/WebCore/svg/SVGAnimateElement.cpp @@ -178,7 +178,7 @@ bool SVGAnimateElement::calculateFromAndToValues(const String& fromString, const if (m_propertyType == ColorProperty) { m_fromColor = SVGColor::colorFromRGBColorString(fromString); m_toColor = SVGColor::colorFromRGBColorString(toString); - if (m_fromColor.isValid() && m_toColor.isValid() || m_toColor.isValid() && animationMode() == ToAnimation) + if ((m_fromColor.isValid() && m_toColor.isValid()) || (m_toColor.isValid() && animationMode() == ToAnimation)) return true; } else if (m_propertyType == NumberProperty) { m_numberUnit = String(); diff --git a/WebCore/svg/SVGAnimatedProperty.h b/WebCore/svg/SVGAnimatedProperty.h index 0e3ceda..b963265 100644 --- a/WebCore/svg/SVGAnimatedProperty.h +++ b/WebCore/svg/SVGAnimatedProperty.h @@ -48,13 +48,13 @@ public: virtual void setBaseVal(PassType type) { m_creator.setBaseValue(type); - m_contextElement->setSynchronizedSVGAttributes(false); + m_contextElement->invalidateSVGAttributes(); } virtual void setAnimVal(PassType type) { m_creator.setValue(type); - m_contextElement->setSynchronizedSVGAttributes(false); + m_contextElement->invalidateSVGAttributes(); } virtual ReturnType baseVal() const { return m_creator.baseValue(); } @@ -181,14 +181,14 @@ public: \ { \ m_##LowerProperty.setValue(type); \ SVGElement* contextElement = GetOwnerElementForType<OwnerType, IsDerivedFromSVGElement<OwnerType>::value>::ownerElement(this); \ - contextElement->setSynchronizedSVGAttributes(false); \ + contextElement->invalidateSVGAttributes(); \ } \ \ void set##UpperProperty##BaseValue(SVGAnimatedPropertyTraits<AnimatedType>::PassType type) \ { \ m_##LowerProperty.setBaseValue(type); \ SVGElement* contextElement = GetOwnerElementForType<OwnerType, IsDerivedFromSVGElement<OwnerType>::value>::ownerElement(this); \ - contextElement->setSynchronizedSVGAttributes(false); \ + contextElement->invalidateSVGAttributes(); \ } \ \ void synchronize##UpperProperty() \ diff --git a/WebCore/svg/SVGClipPathElement.cpp b/WebCore/svg/SVGClipPathElement.cpp index 694e0bc..dd880f5 100644 --- a/WebCore/svg/SVGClipPathElement.cpp +++ b/WebCore/svg/SVGClipPathElement.cpp @@ -74,7 +74,7 @@ void SVGClipPathElement::svgAttributeChanged(const QualifiedName& attrName) SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName) || SVGStyledTransformableElement::isKnownAttribute(attrName)) - invalidateCanvasResources(); + invalidateResourceClients(); } void SVGClipPathElement::synchronizeProperty(const QualifiedName& attrName) @@ -96,7 +96,9 @@ void SVGClipPathElement::synchronizeProperty(const QualifiedName& attrName) void SVGClipPathElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { SVGStyledTransformableElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); - invalidateCanvasResources(); + + if (!changedByParser) + invalidateResourceClients(); } RenderObject* SVGClipPathElement::createRenderer(RenderArena* arena, RenderStyle*) diff --git a/WebCore/svg/SVGClipPathElement.h b/WebCore/svg/SVGClipPathElement.h index dbf5380..40e34f0 100644 --- a/WebCore/svg/SVGClipPathElement.h +++ b/WebCore/svg/SVGClipPathElement.h @@ -29,6 +29,7 @@ #include "SVGTests.h" namespace WebCore { + class SVGClipPathElement : public SVGStyledTransformableElement, public SVGTests, public SVGLangSpace, diff --git a/WebCore/svg/SVGDocumentExtensions.cpp b/WebCore/svg/SVGDocumentExtensions.cpp index ef2e40c..0db682f 100644 --- a/WebCore/svg/SVGDocumentExtensions.cpp +++ b/WebCore/svg/SVGDocumentExtensions.cpp @@ -62,7 +62,7 @@ void SVGDocumentExtensions::removeTimeContainer(SVGSVGElement* element) m_timeContainers.remove(element); } -void SVGDocumentExtensions::addResource(const String& id, RenderSVGResource* resource) +void SVGDocumentExtensions::addResource(const AtomicString& id, RenderSVGResourceContainer* resource) { ASSERT(resource); @@ -73,16 +73,15 @@ void SVGDocumentExtensions::addResource(const String& id, RenderSVGResource* res m_resources.set(id, resource); } -void SVGDocumentExtensions::removeResource(const String& id) +void SVGDocumentExtensions::removeResource(const AtomicString& id) { - if (id.isEmpty()) + if (id.isEmpty() || !m_resources.contains(id)) return; - ASSERT(m_resources.contains(id)); m_resources.remove(id); } -RenderSVGResource* SVGDocumentExtensions::resourceById(const String& id) const +RenderSVGResourceContainer* SVGDocumentExtensions::resourceById(const AtomicString& id) const { if (id.isEmpty()) return 0; @@ -148,7 +147,7 @@ void SVGDocumentExtensions::addPendingResource(const AtomicString& id, SVGStyled if (m_pendingResources.contains(id)) m_pendingResources.get(id)->add(obj); else { - HashSet<SVGStyledElement*>* set = new HashSet<SVGStyledElement*>(); + HashSet<SVGStyledElement*>* set = new HashSet<SVGStyledElement*>; set->add(obj); m_pendingResources.add(id, set); diff --git a/WebCore/svg/SVGDocumentExtensions.h b/WebCore/svg/SVGDocumentExtensions.h index f5de647..d31536c 100644 --- a/WebCore/svg/SVGDocumentExtensions.h +++ b/WebCore/svg/SVGDocumentExtensions.h @@ -24,18 +24,16 @@ #define SVGDocumentExtensions_h #if ENABLE(SVG) - -#include <wtf/PassOwnPtr.h> -#include <wtf/HashSet.h> -#include <wtf/HashMap.h> - -#include "StringHash.h" +#include "AtomicStringHash.h" #include "StringImpl.h" +#include <wtf/HashMap.h> +#include <wtf/HashSet.h> +#include <wtf/PassOwnPtr.h> namespace WebCore { class Document; -class RenderSVGResource; +class RenderSVGResourceContainer; class String; class SVGStyledElement; class SVGSMILElement; @@ -49,9 +47,9 @@ public: void addTimeContainer(SVGSVGElement*); void removeTimeContainer(SVGSVGElement*); - void addResource(const String& id, RenderSVGResource*); - void removeResource(const String& id); - RenderSVGResource* resourceById(const String& id) const; + void addResource(const AtomicString& id, RenderSVGResourceContainer*); + void removeResource(const AtomicString& id); + RenderSVGResourceContainer* resourceById(const AtomicString& id) const; void startAnimations(); void pauseAnimations(); @@ -64,8 +62,8 @@ public: private: Document* m_doc; // weak reference HashSet<SVGSVGElement*> m_timeContainers; // For SVG 1.2 support this will need to be made more general. - HashMap<String, RenderSVGResource*> m_resources; - HashMap<String, HashSet<SVGStyledElement*>*> m_pendingResources; + HashMap<AtomicString, RenderSVGResourceContainer*> m_resources; + HashMap<AtomicString, HashSet<SVGStyledElement*>*> m_pendingResources; SVGDocumentExtensions(const SVGDocumentExtensions&); SVGDocumentExtensions& operator=(const SVGDocumentExtensions&); diff --git a/WebCore/svg/SVGElement.cpp b/WebCore/svg/SVGElement.cpp index 41bbba4..ab146bb 100644 --- a/WebCore/svg/SVGElement.cpp +++ b/WebCore/svg/SVGElement.cpp @@ -41,7 +41,6 @@ #include "SVGElementInstance.h" #include "SVGElementRareData.h" #include "SVGNames.h" -#include "SVGResource.h" #include "SVGSVGElement.h" #include "SVGURIReference.h" #include "SVGUseElement.h" @@ -53,7 +52,7 @@ namespace WebCore { using namespace HTMLNames; SVGElement::SVGElement(const QualifiedName& tagName, Document* document) - : StyledElement(tagName, document, CreateElementZeroRefCount) + : StyledElement(tagName, document, CreateSVGElementZeroRefCount) { } @@ -96,7 +95,7 @@ SVGElementRareData* SVGElement::ensureRareSVGData() ASSERT(!SVGElementRareData::rareDataMap().contains(this)); SVGElementRareData* data = new SVGElementRareData; SVGElementRareData::rareDataMap().set(this, data); - m_hasRareSVGData = true; + setHasRareSVGData(); return data; } @@ -281,7 +280,7 @@ void SVGElement::insertedIntoDocument() StyledElement::insertedIntoDocument(); SVGDocumentExtensions* extensions = document()->accessSVGExtensions(); - String resourceId = SVGURIReference::getTarget(getAttribute(idAttributeName())); + String resourceId = getAttribute(idAttributeName()); if (extensions->isPendingResource(resourceId)) { OwnPtr<HashSet<SVGStyledElement*> > clients(extensions->removePendingResource(resourceId)); if (clients->isEmpty()) @@ -292,8 +291,6 @@ void SVGElement::insertedIntoDocument() for (; it != end; ++it) (*it)->buildPendingResource(); - - SVGResource::invalidateClients(*clients); } } @@ -309,18 +306,16 @@ void SVGElement::attributeChanged(Attribute* attr, bool preserveDecls) void SVGElement::updateAnimatedSVGAttribute(const QualifiedName& name) const { - ASSERT(!m_areSVGAttributesValid); - - if (m_synchronizingSVGAttributes) + if (isSynchronizingSVGAttributes() || areSVGAttributesValid()) return; - m_synchronizingSVGAttributes = true; + setIsSynchronizingSVGAttributes(); const_cast<SVGElement*>(this)->synchronizeProperty(name); if (name == anyQName()) - m_areSVGAttributesValid = true; + setAreSVGAttributesValid(); - m_synchronizingSVGAttributes = false; + clearIsSynchronizingSVGAttributes(); } ContainerNode* SVGElement::eventParentNode() diff --git a/WebCore/svg/SVGElement.h b/WebCore/svg/SVGElement.h index 88d7412..9467250 100644 --- a/WebCore/svg/SVGElement.h +++ b/WebCore/svg/SVGElement.h @@ -72,20 +72,21 @@ namespace WebCore { virtual AffineTransform* supplementalTransform() { return 0; } - void setSynchronizedSVGAttributes(bool value) { m_areSVGAttributesValid = value; } + void invalidateSVGAttributes() { clearAreSVGAttributesValid(); } const HashSet<SVGElementInstance*>& instancesForElement() const; void setCursorElement(SVGCursorElement*); void setCursorImageValue(CSSCursorImageValue*); + virtual void updateAnimatedSVGAttribute(const QualifiedName&) const; + protected: SVGElement(const QualifiedName&, Document*); virtual void finishParsingChildren(); virtual void insertedIntoDocument(); virtual void attributeChanged(Attribute*, bool preserveDecls = false); - virtual void updateAnimatedSVGAttribute(const QualifiedName&) const; SVGElementRareData* rareSVGData() const; SVGElementRareData* ensureRareSVGData(); @@ -93,7 +94,6 @@ namespace WebCore { private: friend class SVGElementInstance; - virtual bool isSVGElement() const { return true; } virtual bool isSupported(StringImpl* feature, StringImpl* version) const; virtual ContainerNode* eventParentNode(); diff --git a/WebCore/svg/SVGElementInstance.idl b/WebCore/svg/SVGElementInstance.idl index d23fea2..3fcadb9 100644 --- a/WebCore/svg/SVGElementInstance.idl +++ b/WebCore/svg/SVGElementInstance.idl @@ -90,12 +90,12 @@ module svg { attribute [DontEnum] EventListener onsubmit; attribute [DontEnum] EventListener onunload; - [JSCCustom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [JSCCustom] void removeEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); + void addEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); + void removeEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); boolean dispatchEvent(in Event event) raises(EventException); #endif /* defined(LANGUAGE_OBJECTIVE_C) */ diff --git a/WebCore/svg/SVGFont.cpp b/WebCore/svg/SVGFont.cpp index dacbac2..049d35e 100644 --- a/WebCore/svg/SVGFont.cpp +++ b/WebCore/svg/SVGFont.cpp @@ -27,6 +27,7 @@ #include "CSSFontSelector.h" #include "GraphicsContext.h" #include "RenderObject.h" +#include "RenderSVGResourceSolidColor.h" #include "SimpleFontData.h" #include "SVGAltGlyphElement.h" #include "SVGFontData.h" @@ -35,8 +36,6 @@ #include "SVGFontElement.h" #include "SVGFontFaceElement.h" #include "SVGMissingGlyphElement.h" -#include "SVGPaintServer.h" -#include "SVGPaintServerSolid.h" #include "XMLNames.h" using namespace WTF::Unicode; @@ -471,20 +470,20 @@ void Font::drawTextUsingSVGFont(GraphicsContext* context, const TextRun& run, FloatPoint currentPoint = point; float scale = convertEmUnitToPixel(size(), fontFaceElement->unitsPerEm(), 1.0f); - SVGPaintServer* activePaintServer = run.activePaintServer(); + RenderSVGResource* activePaintingResource = run.activePaintingResource(); // If renderObject is not set, we're dealing for HTML text rendered using SVG Fonts. if (!run.referencingRenderObject()) { - ASSERT(!activePaintServer); + ASSERT(!activePaintingResource); // TODO: We're only supporting simple filled HTML text so far. - SVGPaintServerSolid* solidPaintServer = SVGPaintServer::sharedSolidPaintServer(); - solidPaintServer->setColor(context->fillColor()); + RenderSVGResourceSolidColor* solidPaintingResource = RenderSVGResource::sharedSolidPaintingResource(); + solidPaintingResource->setColor(context->fillColor()); - activePaintServer = solidPaintServer; + activePaintingResource = solidPaintingResource; } - ASSERT(activePaintServer); + ASSERT(activePaintingResource); int charsConsumed; String glyphName; @@ -513,7 +512,7 @@ void Font::drawTextUsingSVGFont(GraphicsContext* context, const TextRun& run, SVGTextRunWalker<SVGTextRunWalkerDrawTextData> runWalker(fontData, fontElement, data, drawTextUsingSVGFontCallback, drawTextMissingGlyphCallback); runWalker.walk(run, isVerticalText, language, from, to); - SVGPaintTargetType targetType = context->textDrawingMode() == cTextStroke ? ApplyToStrokeTargetType : ApplyToFillTargetType; + RenderSVGResourceMode resourceMode = context->textDrawingMode() == cTextStroke ? ApplyToStrokeMode : ApplyToFillMode; unsigned numGlyphs = data.glyphIdentifiers.size(); unsigned fallbackCharacterIndex = 0; @@ -538,10 +537,10 @@ void Font::drawTextUsingSVGFont(GraphicsContext* context, const TextRun& run, context->beginPath(); context->addPath(glyphPath); - if (activePaintServer->setup(context, run.referencingRenderObject(), targetType)) { - activePaintServer->renderPath(context, run.referencingRenderObject(), targetType); - activePaintServer->teardown(context, run.referencingRenderObject(), targetType); - } + + RenderStyle* style = run.referencingRenderObject() ? run.referencingRenderObject()->style() : 0; + if (activePaintingResource->applyResource(run.referencingRenderObject(), style, context, resourceMode)) + activePaintingResource->postApplyResource(run.referencingRenderObject(), context, resourceMode); context->restore(); } diff --git a/WebCore/svg/SVGFontElement.cpp b/WebCore/svg/SVGFontElement.cpp index 91d222c..a573350 100644 --- a/WebCore/svg/SVGFontElement.cpp +++ b/WebCore/svg/SVGFontElement.cpp @@ -95,149 +95,64 @@ void SVGFontElement::ensureGlyphCache() const m_isGlyphCacheValid = true; } - -// Returns the number of characters consumed or 0 if no range was found. -static unsigned parseUnicodeRange(const UChar* characters, unsigned length, pair<unsigned, unsigned>& range) + +static bool stringMatchesUnicodeRange(const String& unicodeString, const UnicodeRanges& ranges, const HashSet<String>& unicodeValues) { - if (length < 2) - return 0; - if (characters[0] != 'U') - return 0; - if (characters[1] != '+') - return 0; - - // Parse the starting hex number (or its prefix). - unsigned start = 0; - unsigned startLength = 0; - for (unsigned i = 2; i < length; ++i) { - if (!isASCIIHexDigit(characters[i])) - break; - if (++startLength > 6) - return 0; - start = (start << 4) | toASCIIHexValue(characters[i]); - } - - // Handle the case of ranges separated by "-" sign. - if (2 + startLength < length && characters[2 + startLength] == '-') { - if (!startLength) - return 0; - - // Parse the ending hex number (or its prefix). - unsigned end = 0; - unsigned endLength = 0; - for (unsigned i = 2 + startLength + 1; i < length; ++i) { - if (!isASCIIHexDigit(characters[i])) - break; - if (++endLength > 6) - return 0; - end = (end << 4) | toASCIIHexValue(characters[i]); + if (unicodeString.isEmpty()) + return false; + + if (!ranges.isEmpty()) { + UChar firstChar = unicodeString[0]; + const UnicodeRanges::const_iterator end = ranges.end(); + for (UnicodeRanges::const_iterator it = ranges.begin(); it != end; ++it) { + if (firstChar >= it->first && firstChar <= it->second) + return true; } - - if (!endLength) - return 0; - - range.first = start; - range.second = end; - return 2 + startLength + 1 + endLength; } + + if (!unicodeValues.isEmpty()) + return unicodeValues.contains(unicodeString); - // Handle the case of a number with some optional trailing question marks. - unsigned end = start; - for (unsigned i = 2 + startLength; i < length; ++i) { - if (characters[i] != '?') - break; - if (++startLength > 6) - return 0; - start <<= 4; - end = (end << 4) | 0xF; - } - - if (!startLength) - return 0; - - range.first = start; - range.second = end; - return 2 + startLength; -} - -static bool parseUnicodeRangeList(const UChar* characters, unsigned length, Vector<pair<unsigned, unsigned> >& ranges) -{ - ranges.clear(); - if (!length) - return true; - - const UChar* remainingCharacters = characters; - unsigned remainingLength = length; - - while (1) { - pair<unsigned, unsigned> range; - unsigned charactersConsumed = parseUnicodeRange(remainingCharacters, remainingLength, range); - if (charactersConsumed) { - ranges.append(range); - remainingCharacters += charactersConsumed; - remainingLength -= charactersConsumed; - } else { - if (!remainingLength) - return false; - UChar character = remainingCharacters[0]; - if (character == ',') - return false; - ranges.append(make_pair(character, character)); - ++remainingCharacters; - --remainingLength; - } - if (!remainingLength) - return true; - if (remainingCharacters[0] != ',') - return false; - ++remainingCharacters; - --remainingLength; - } + return false; } -static bool stringMatchesUnicodeRange(const String& unicodeString, const String& unicodeRangeSpec) +static bool stringMatchesGlyphName(const String& glyphName, const HashSet<String>& glyphValues) { - Vector<pair<unsigned, unsigned> > ranges; - if (!parseUnicodeRangeList(unicodeRangeSpec.characters(), unicodeRangeSpec.length(), ranges)) - return false; - - if (unicodeString.length() != ranges.size()) + if (glyphName.isEmpty()) return false; + + if (!glyphValues.isEmpty()) + return glyphValues.contains(glyphName); - for (size_t i = 0; i < unicodeString.length(); ++i) { - UChar c = unicodeString[i]; - if (c < ranges[i].first || c > ranges[i].second) - return false; - } - - return true; + return false; } static bool matches(const String& u1, const String& g1, const String& u2, const String& g2, const SVGHorizontalKerningPair& kerningPair) { - if (kerningPair.unicode1.length() && !stringMatchesUnicodeRange(u1, kerningPair.unicode1)) + if (!stringMatchesUnicodeRange(u1, kerningPair.unicodeRange1, kerningPair.unicodeName1) + && !stringMatchesGlyphName(g1, kerningPair.glyphName1)) return false; - if (kerningPair.glyphName1.length() && kerningPair.glyphName1 != g1) - return false; - - if (kerningPair.unicode2.length() && !stringMatchesUnicodeRange(u2, kerningPair.unicode2)) - return false; - if (kerningPair.glyphName2.length() && kerningPair.glyphName2 != g2) + + if (!stringMatchesUnicodeRange(u2, kerningPair.unicodeRange2, kerningPair.unicodeName2) + && !stringMatchesGlyphName(g2, kerningPair.glyphName2)) return false; - + return true; } -bool SVGFontElement::getHorizontalKerningPairForStringsAndGlyphs(const String& u1, const String& g1, const String& u2, const String& g2, SVGHorizontalKerningPair& kerningPair) const +float SVGFontElement::getHorizontalKerningPairForStringsAndGlyphs(const String& u1, const String& g1, const String& u2, const String& g2) const { - for (size_t i = 0; i < m_kerningPairs.size(); ++i) { - if (matches(u1, g1, u2, g2, m_kerningPairs[i])) { - kerningPair = m_kerningPairs[i]; - return true; - } + if (m_kerningPairs.isEmpty()) + return 0.0f; + + KerningPairVector::const_iterator it = m_kerningPairs.end() - 1; + const KerningPairVector::const_iterator begin = m_kerningPairs.begin() - 1; + for (; it != begin; --it) { + if (matches(u1, g1, u2, g2, *it)) + return it->kerning; } - - return false; + + return 0.0f; } void SVGFontElement::getGlyphIdentifiersForString(const String& string, Vector<SVGGlyphIdentifier>& glyphs) const diff --git a/WebCore/svg/SVGFontElement.h b/WebCore/svg/SVGFontElement.h index 90641a8..31d83c4 100644 --- a/WebCore/svg/SVGFontElement.h +++ b/WebCore/svg/SVGFontElement.h @@ -44,7 +44,7 @@ namespace WebCore { void getGlyphIdentifiersForString(const String&, Vector<SVGGlyphIdentifier>&) const; - bool getHorizontalKerningPairForStringsAndGlyphs(const String& u1, const String& g1, const String& u2, const String& g2, SVGHorizontalKerningPair& kerningPair) const; + float getHorizontalKerningPairForStringsAndGlyphs(const String& u1, const String& g1, const String& u2, const String& g2) const; SVGMissingGlyphElement* firstMissingGlyphElement() const; diff --git a/WebCore/svg/SVGGElement.cpp b/WebCore/svg/SVGGElement.cpp index 6e39bf5..d429400 100644 --- a/WebCore/svg/SVGGElement.cpp +++ b/WebCore/svg/SVGGElement.cpp @@ -23,6 +23,7 @@ #if ENABLE(SVG) #include "SVGGElement.h" +#include "RenderSVGHiddenContainer.h" #include "RenderSVGTransformableContainer.h" namespace WebCore { @@ -79,16 +80,15 @@ void SVGGElement::synchronizeProperty(const QualifiedName& attrName) synchronizeExternalResourcesRequired(); } -void SVGGElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) +RenderObject* SVGGElement::createRenderer(RenderArena* arena, RenderStyle* style) { - SVGStyledTransformableElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); + // SVG 1.1 testsuite explicitely uses constructs like <g display="none"><linearGradient> + // We still have to create renderers for the <g> & <linearGradient> element, though the + // subtree may be hidden - we only want the resource renderers to exist so they can be + // referenced from somewhere else. + if (style->display() == NONE) + return new (arena) RenderSVGHiddenContainer(this); - if (renderer()) - renderer()->setNeedsLayout(true); -} - -RenderObject* SVGGElement::createRenderer(RenderArena* arena, RenderStyle*) -{ return new (arena) RenderSVGTransformableContainer(this); } diff --git a/WebCore/svg/SVGGElement.h b/WebCore/svg/SVGGElement.h index 3e0dd8e..b90eddb 100644 --- a/WebCore/svg/SVGGElement.h +++ b/WebCore/svg/SVGGElement.h @@ -43,8 +43,8 @@ namespace WebCore { virtual void parseMappedAttribute(MappedAttribute*); virtual void svgAttributeChanged(const QualifiedName&); virtual void synchronizeProperty(const QualifiedName&); - virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); + virtual bool rendererIsNeeded(RenderStyle*) { return true; } virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); private: diff --git a/WebCore/svg/SVGGradientElement.cpp b/WebCore/svg/SVGGradientElement.cpp index f573265..b4bdb16 100644 --- a/WebCore/svg/SVGGradientElement.cpp +++ b/WebCore/svg/SVGGradientElement.cpp @@ -1,6 +1,7 @@ /* Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org> 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> + Copyright (C) Research In Motion Limited 2010. 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 @@ -27,9 +28,9 @@ #include "MappedAttribute.h" #include "RenderPath.h" #include "RenderSVGHiddenContainer.h" +#include "RenderSVGResourceLinearGradient.h" +#include "RenderSVGResourceRadialGradient.h" #include "SVGNames.h" -#include "SVGPaintServerLinearGradient.h" -#include "SVGPaintServerRadialGradient.h" #include "SVGStopElement.h" #include "SVGTransformList.h" #include "SVGTransformable.h" @@ -84,16 +85,13 @@ void SVGGradientElement::svgAttributeChanged(const QualifiedName& attrName) { SVGStyledElement::svgAttributeChanged(attrName); - if (!m_resource) - return; - - if (attrName == SVGNames::gradientUnitsAttr || - attrName == SVGNames::gradientTransformAttr || - attrName == SVGNames::spreadMethodAttr || - SVGURIReference::isKnownAttribute(attrName) || - SVGExternalResourcesRequired::isKnownAttribute(attrName) || - SVGStyledElement::isKnownAttribute(attrName)) - m_resource->invalidate(); + if (attrName == SVGNames::gradientUnitsAttr + || attrName == SVGNames::gradientTransformAttr + || attrName == SVGNames::spreadMethodAttr + || SVGURIReference::isKnownAttribute(attrName) + || SVGExternalResourcesRequired::isKnownAttribute(attrName) + || SVGStyledElement::isKnownAttribute(attrName)) + invalidateResourceClients(); } void SVGGradientElement::synchronizeProperty(const QualifiedName& attrName) @@ -125,61 +123,34 @@ void SVGGradientElement::childrenChanged(bool changedByParser, Node* beforeChang { SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); - if (m_resource) - m_resource->invalidate(); + if (!changedByParser) + invalidateResourceClients(); } -RenderObject* SVGGradientElement::createRenderer(RenderArena* arena, RenderStyle*) +Vector<Gradient::ColorStop> SVGGradientElement::buildStops() { - return new (arena) RenderSVGHiddenContainer(this); -} - -SVGResource* SVGGradientElement::canvasResource(const RenderObject*) -{ - if (!m_resource) { - if (gradientType() == LinearGradientPaintServer) - m_resource = SVGPaintServerLinearGradient::create(this); - else - m_resource = SVGPaintServerRadialGradient::create(this); - } - - return m_resource.get(); -} - -Vector<SVGGradientStop> SVGGradientElement::buildStops() const -{ - Vector<SVGGradientStop> stops; - RefPtr<RenderStyle> gradientStyle; + Vector<Gradient::ColorStop> stops; + float previousOffset = 0.0f; for (Node* n = firstChild(); n; n = n->nextSibling()) { SVGElement* element = n->isSVGElement() ? static_cast<SVGElement*>(n) : 0; + if (!element || !element->isGradientStop()) + continue; - if (element && element->isGradientStop()) { - SVGStopElement* stop = static_cast<SVGStopElement*>(element); - float stopOffset = stop->offset(); + SVGStopElement* stop = static_cast<SVGStopElement*>(element); + Color color = stop->stopColorIncludingOpacity(); - Color color; - float opacity; + // Figure out right monotonic offset + float offset = stop->offset(); + offset = std::min(std::max(previousOffset, offset), 1.0f); + previousOffset = offset; - if (stop->renderer()) { - RenderStyle* stopStyle = stop->renderer()->style(); - color = stopStyle->svgStyle()->stopColor(); - opacity = stopStyle->svgStyle()->stopOpacity(); - } else { - // If there is no renderer for this stop element, then a parent element - // set display="none" - ie. <g display="none"><linearGradient><stop>.. - // Unfortunately we have to manually rebuild the stop style. See pservers-grad-19-b.svg - if (!gradientStyle) - gradientStyle = const_cast<SVGGradientElement*>(this)->styleForRenderer(); + // Extract individual channel values + // FIXME: Why doesn't ColorStop take a Color and an offset?? + float r, g, b, a; + color.getRGBA(r, g, b, a); - RefPtr<RenderStyle> stopStyle = stop->resolveStyle(gradientStyle.get()); - - color = stopStyle->svgStyle()->stopColor(); - opacity = stopStyle->svgStyle()->stopOpacity(); - } - - stops.append(makeGradientStop(stopOffset, makeRGBA(color.red(), color.green(), color.blue(), int(opacity * 255.)))); - } + stops.append(Gradient::ColorStop(offset, r, g, b, a)); } return stops; diff --git a/WebCore/svg/SVGGradientElement.h b/WebCore/svg/SVGGradientElement.h index 122e1d9..4447ec4 100644 --- a/WebCore/svg/SVGGradientElement.h +++ b/WebCore/svg/SVGGradientElement.h @@ -22,8 +22,7 @@ #define SVGGradientElement_h #if ENABLE(SVG) -#include "RenderObject.h" -#include "SVGPaintServerGradient.h" +#include "Gradient.h" #include "SVGExternalResourcesRequired.h" #include "SVGStyledElement.h" #include "SVGTransformList.h" @@ -43,20 +42,8 @@ namespace WebCore { virtual void synchronizeProperty(const QualifiedName&); virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); - virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); - virtual SVGResource* canvasResource(const RenderObject*); - - protected: - friend class SVGPaintServerGradient; - friend class SVGLinearGradientElement; - friend class SVGRadialGradientElement; - - virtual void buildGradient() const = 0; - virtual SVGPaintServerType gradientType() const = 0; - - Vector<SVGGradientStop> buildStops() const; - mutable RefPtr<SVGPaintServerGradient> m_resource; + Vector<Gradient::ColorStop> buildStops(); protected: DECLARE_ANIMATED_PROPERTY(SVGGradientElement, SVGNames::spreadMethodAttr, int, SpreadMethod, spreadMethod) diff --git a/WebCore/svg/SVGHKernElement.cpp b/WebCore/svg/SVGHKernElement.cpp index 0ee3e76..1b8746b 100644 --- a/WebCore/svg/SVGHKernElement.cpp +++ b/WebCore/svg/SVGHKernElement.cpp @@ -28,7 +28,6 @@ #include "SVGFontFaceElement.h" #include "SVGFontData.h" #include "SVGNames.h" -#include "SVGParserUtilities.h" #include "SimpleFontData.h" #include "XMLNames.h" @@ -67,11 +66,12 @@ SVGHorizontalKerningPair SVGHKernElement::buildHorizontalKerningPair() const { SVGHorizontalKerningPair kerningPair; - kerningPair.unicode1 = getAttribute(u1Attr); - kerningPair.glyphName1 = getAttribute(g1Attr); - kerningPair.unicode2 = getAttribute(u2Attr); - kerningPair.glyphName2 = getAttribute(g2Attr); - kerningPair.kerning = getAttribute(kAttr).string().toDouble(); + // FIXME: KerningPairs shouldn't be created on parsing errors. + parseGlyphName(getAttribute(g1Attr), kerningPair.glyphName1); + parseGlyphName(getAttribute(g2Attr), kerningPair.glyphName2); + parseKerningUnicodeString(getAttribute(u1Attr), kerningPair.unicodeRange1, kerningPair.unicodeName1); + parseKerningUnicodeString(getAttribute(u2Attr), kerningPair.unicodeRange2, kerningPair.unicodeName2); + kerningPair.kerning = getAttribute(kAttr).string().toFloat(); return kerningPair; } diff --git a/WebCore/svg/SVGHKernElement.h b/WebCore/svg/SVGHKernElement.h index 32772bd..3d13119 100644 --- a/WebCore/svg/SVGHKernElement.h +++ b/WebCore/svg/SVGHKernElement.h @@ -23,10 +23,10 @@ #define SVGHKernElement_h #if ENABLE(SVG_FONTS) +#include "SVGParserUtilities.h" #include "SVGStyledElement.h" #include <limits> -#include "Path.h" namespace WebCore { @@ -35,11 +35,13 @@ namespace WebCore { // Describe an SVG <hkern> element struct SVGHorizontalKerningPair { - String unicode1; - String glyphName1; - String unicode2; - String glyphName2; - double kerning; + UnicodeRanges unicodeRange1; + HashSet<String> unicodeName1; + HashSet<String> glyphName1; + UnicodeRanges unicodeRange2; + HashSet<String> unicodeName2; + HashSet<String> glyphName2; + float kerning; SVGHorizontalKerningPair() : kerning(0) diff --git a/WebCore/svg/SVGLinearGradientElement.cpp b/WebCore/svg/SVGLinearGradientElement.cpp index 665a1da..87021b1 100644 --- a/WebCore/svg/SVGLinearGradientElement.cpp +++ b/WebCore/svg/SVGLinearGradientElement.cpp @@ -3,6 +3,7 @@ 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> 2008 Eric Seidel <eric@webkit.org> 2008 Dirk Schulze <krit@webkit.org> + Copyright (C) Research In Motion Limited 2010. 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 @@ -29,9 +30,9 @@ #include "FloatPoint.h" #include "LinearGradientAttributes.h" #include "MappedAttribute.h" +#include "RenderSVGResourceLinearGradient.h" #include "SVGLength.h" #include "SVGNames.h" -#include "SVGPaintServerLinearGradient.h" #include "SVGTransform.h" #include "SVGTransformList.h" #include "SVGUnitTypes.h" @@ -70,12 +71,11 @@ void SVGLinearGradientElement::svgAttributeChanged(const QualifiedName& attrName { SVGGradientElement::svgAttributeChanged(attrName); - if (!m_resource) - return; - - if (attrName == SVGNames::x1Attr || attrName == SVGNames::y1Attr || - attrName == SVGNames::x2Attr || attrName == SVGNames::y2Attr) - m_resource->invalidate(); + if (attrName == SVGNames::x1Attr + || attrName == SVGNames::y1Attr + || attrName == SVGNames::x2Attr + || attrName == SVGNames::y2Attr) + invalidateResourceClients(); } void SVGLinearGradientElement::synchronizeProperty(const QualifiedName& attrName) @@ -100,56 +100,18 @@ void SVGLinearGradientElement::synchronizeProperty(const QualifiedName& attrName synchronizeY2(); } -void SVGLinearGradientElement::buildGradient() const +RenderObject* SVGLinearGradientElement::createRenderer(RenderArena* arena, RenderStyle*) { - LinearGradientAttributes attributes = collectGradientProperties(); - - RefPtr<SVGPaintServerLinearGradient> linearGradient = WTF::static_pointer_cast<SVGPaintServerLinearGradient>(m_resource); - - FloatPoint startPoint; - FloatPoint endPoint; - if (attributes.boundingBoxMode()) { - startPoint = FloatPoint(attributes.x1().valueAsPercentage(), attributes.y1().valueAsPercentage()); - endPoint = FloatPoint(attributes.x2().valueAsPercentage(), attributes.y2().valueAsPercentage()); - } else { - startPoint = FloatPoint(attributes.x1().value(this), attributes.y1().value(this)); - endPoint = FloatPoint(attributes.x2().value(this), attributes.y2().value(this)); - } - - RefPtr<Gradient> gradient = Gradient::create(startPoint, endPoint); - gradient->setSpreadMethod(attributes.spreadMethod()); - - Vector<SVGGradientStop> m_stops = attributes.stops(); - float previousOffset = 0.0f; - for (unsigned i = 0; i < m_stops.size(); ++i) { - float offset = std::min(std::max(previousOffset, m_stops[i].first), 1.0f); - previousOffset = offset; - gradient->addColorStop(offset, m_stops[i].second); - } - - linearGradient->setGradient(gradient); - - if (attributes.stops().isEmpty()) - return; - - // This code should go away. PaintServers should go away too. - // Only this code should care about bounding boxes - linearGradient->setBoundingBoxMode(attributes.boundingBoxMode()); - linearGradient->setGradientStops(attributes.stops()); - - // These should possibly be supported on Gradient - linearGradient->setGradientTransform(attributes.gradientTransform()); - linearGradient->setGradientStart(startPoint); - linearGradient->setGradientEnd(endPoint); + return new (arena) RenderSVGResourceLinearGradient(this); } -LinearGradientAttributes SVGLinearGradientElement::collectGradientProperties() const +LinearGradientAttributes SVGLinearGradientElement::collectGradientProperties() { LinearGradientAttributes attributes; - HashSet<const SVGGradientElement*> processedGradients; + HashSet<SVGGradientElement*> processedGradients; bool isLinear = true; - const SVGGradientElement* current = this; + SVGGradientElement* current = this; while (current) { if (!attributes.hasSpreadMethod() && current->hasAttribute(SVGNames::spreadMethodAttr)) @@ -162,13 +124,13 @@ LinearGradientAttributes SVGLinearGradientElement::collectGradientProperties() c attributes.setGradientTransform(current->gradientTransform()->consolidate().matrix()); if (!attributes.hasStops()) { - const Vector<SVGGradientStop>& stops(current->buildStops()); + const Vector<Gradient::ColorStop>& stops(current->buildStops()); if (!stops.isEmpty()) attributes.setStops(stops); } if (isLinear) { - const SVGLinearGradientElement* linear = static_cast<const SVGLinearGradientElement*>(current); + SVGLinearGradientElement* linear = static_cast<SVGLinearGradientElement*>(current); if (!attributes.hasX1() && current->hasAttribute(SVGNames::x1Attr)) attributes.setX1(linear->x1()); @@ -188,13 +150,13 @@ LinearGradientAttributes SVGLinearGradientElement::collectGradientProperties() c // Respect xlink:href, take attributes from referenced element Node* refNode = ownerDocument()->getElementById(SVGURIReference::getTarget(current->href())); if (refNode && (refNode->hasTagName(SVGNames::linearGradientTag) || refNode->hasTagName(SVGNames::radialGradientTag))) { - current = static_cast<const SVGGradientElement*>(const_cast<const Node*>(refNode)); + current = static_cast<SVGGradientElement*>(refNode); // Cycle detection if (processedGradients.contains(current)) return LinearGradientAttributes(); - isLinear = current->gradientType() == LinearGradientPaintServer; + isLinear = current->hasTagName(SVGNames::linearGradientTag); } else current = 0; } @@ -202,6 +164,18 @@ LinearGradientAttributes SVGLinearGradientElement::collectGradientProperties() c return attributes; } +void SVGLinearGradientElement::calculateStartEndPoints(const LinearGradientAttributes& attributes, FloatPoint& startPoint, FloatPoint& endPoint) +{ + // Determine gradient start/end points + if (attributes.boundingBoxMode()) { + startPoint = FloatPoint(attributes.x1().valueAsPercentage(), attributes.y1().valueAsPercentage()); + endPoint = FloatPoint(attributes.x2().valueAsPercentage(), attributes.y2().valueAsPercentage()); + } else { + startPoint = FloatPoint(attributes.x1().value(this), attributes.y1().value(this)); + endPoint = FloatPoint(attributes.x2().value(this), attributes.y2().value(this)); + } +} + } #endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGLinearGradientElement.h b/WebCore/svg/SVGLinearGradientElement.h index 0308c0e..f92fe80 100644 --- a/WebCore/svg/SVGLinearGradientElement.h +++ b/WebCore/svg/SVGLinearGradientElement.h @@ -38,11 +38,10 @@ namespace WebCore { virtual void svgAttributeChanged(const QualifiedName&); virtual void synchronizeProperty(const QualifiedName&); - protected: - virtual void buildGradient() const; - virtual SVGPaintServerType gradientType() const { return LinearGradientPaintServer; } + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); - LinearGradientAttributes collectGradientProperties() const; + LinearGradientAttributes collectGradientProperties(); + void calculateStartEndPoints(const LinearGradientAttributes&, FloatPoint& startPoint, FloatPoint& endPoint); private: DECLARE_ANIMATED_PROPERTY(SVGLinearGradientElement, SVGNames::x1Attr, SVGLength, X1, x1) diff --git a/WebCore/svg/SVGMarkerElement.cpp b/WebCore/svg/SVGMarkerElement.cpp index ba9728f..79a445c 100644 --- a/WebCore/svg/SVGMarkerElement.cpp +++ b/WebCore/svg/SVGMarkerElement.cpp @@ -111,7 +111,7 @@ void SVGMarkerElement::svgAttributeChanged(const QualifiedName& attrName) SVGExternalResourcesRequired::isKnownAttribute(attrName) || SVGFitToViewBox::isKnownAttribute(attrName) || SVGStyledElement::isKnownAttribute(attrName)) - invalidateCanvasResources(); + invalidateResourceClients(); } void SVGMarkerElement::synchronizeProperty(const QualifiedName& attrName) @@ -157,7 +157,8 @@ void SVGMarkerElement::childrenChanged(bool changedByParser, Node* beforeChange, { SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); - invalidateCanvasResources(); + if (!changedByParser) + invalidateResourceClients(); } void SVGMarkerElement::setOrientToAuto() @@ -165,7 +166,7 @@ void SVGMarkerElement::setOrientToAuto() setOrientTypeBaseValue(SVG_MARKER_ORIENT_AUTO); setOrientAngleBaseValue(SVGAngle()); - invalidateCanvasResources(); + invalidateResourceClients(); } void SVGMarkerElement::setOrientToAngle(const SVGAngle& angle) @@ -173,7 +174,7 @@ void SVGMarkerElement::setOrientToAngle(const SVGAngle& angle) setOrientTypeBaseValue(SVG_MARKER_ORIENT_ANGLE); setOrientAngleBaseValue(angle); - invalidateCanvasResources(); + invalidateResourceClients(); } RenderObject* SVGMarkerElement::createRenderer(RenderArena* arena, RenderStyle*) diff --git a/WebCore/svg/SVGMaskElement.cpp b/WebCore/svg/SVGMaskElement.cpp index 67b0a98..6eb19fc 100644 --- a/WebCore/svg/SVGMaskElement.cpp +++ b/WebCore/svg/SVGMaskElement.cpp @@ -104,7 +104,7 @@ void SVGMaskElement::svgAttributeChanged(const QualifiedName& attrName) SVGLangSpace::isKnownAttribute(attrName) || SVGExternalResourcesRequired::isKnownAttribute(attrName) || SVGStyledElement::isKnownAttribute(attrName)) - invalidateCanvasResources(); + invalidateResourceClients(); } void SVGMaskElement::synchronizeProperty(const QualifiedName& attrName) @@ -138,7 +138,9 @@ void SVGMaskElement::synchronizeProperty(const QualifiedName& attrName) void SVGMaskElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) { SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); - invalidateCanvasResources(); + + if (!changedByParser) + invalidateResourceClients(); } FloatRect SVGMaskElement::maskBoundingBox(const FloatRect& objectBoundingBox) const diff --git a/WebCore/svg/SVGParserUtilities.cpp b/WebCore/svg/SVGParserUtilities.cpp index fc9ca5d..b24c3cc 100644 --- a/WebCore/svg/SVGParserUtilities.cpp +++ b/WebCore/svg/SVGParserUtilities.cpp @@ -44,6 +44,7 @@ #include "SVGPointList.h" #include "SVGPathElement.h" #include <math.h> +#include <wtf/ASCIICType.h> #include <wtf/MathExtras.h> namespace WebCore { @@ -840,6 +841,125 @@ bool pathSegListFromSVGData(SVGPathSegList* path, const String& d, bool process) return builder.build(path, d, process); } +void parseGlyphName(const String& input, HashSet<String>& values) +{ + values.clear(); + + const UChar* ptr = input.characters(); + const UChar* end = ptr + input.length(); + skipOptionalSpaces(ptr, end); + + while (ptr < end) { + // Leading and trailing white space, and white space before and after separators, will be ignored. + const UChar* inputStart = ptr; + while (ptr < end && *ptr != ',') + ++ptr; + + if (ptr == inputStart) + break; + + // walk backwards from the ; to ignore any whitespace + const UChar* inputEnd = ptr - 1; + while (inputStart < inputEnd && isWhitespace(*inputEnd)) + --inputEnd; + + values.add(String(inputStart, inputEnd - inputStart + 1)); + skipOptionalSpacesOrDelimiter(ptr, end, ','); + } +} + +static bool parseUnicodeRange(const UChar* characters, unsigned length, UnicodeRange& range) +{ + if (length < 2 || characters[0] != 'U' || characters[1] != '+') + return false; + + // Parse the starting hex number (or its prefix). + unsigned startRange = 0; + unsigned startLength = 0; + + const UChar* ptr = characters + 2; + const UChar* end = characters + length; + while (ptr < end) { + if (!isASCIIHexDigit(*ptr)) + break; + ++startLength; + if (startLength > 6) + return false; + startRange = (startRange << 4) | toASCIIHexValue(*ptr); + ++ptr; + } + + // Handle the case of ranges separated by "-" sign. + if (2 + startLength < length && *ptr == '-') { + if (!startLength) + return false; + + // Parse the ending hex number (or its prefix). + unsigned endRange = 0; + unsigned endLength = 0; + ++ptr; + while (ptr < end) { + if (!isASCIIHexDigit(*ptr)) + break; + ++endLength; + if (endLength > 6) + return false; + endRange = (endRange << 4) | toASCIIHexValue(*ptr); + ++ptr; + } + + if (!endLength) + return false; + + range.first = startRange; + range.second = endRange; + return true; + } + + // Handle the case of a number with some optional trailing question marks. + unsigned endRange = startRange; + while (ptr < end) { + if (*ptr != '?') + break; + ++startLength; + if (startLength > 6) + return false; + startRange <<= 4; + endRange = (endRange << 4) | 0xF; + ++ptr; + } + + if (!startLength) + return false; + + range.first = startRange; + range.second = endRange; + return true; +} + +void parseKerningUnicodeString(const String& input, UnicodeRanges& rangeList, HashSet<String>& stringList) +{ + const UChar* ptr = input.characters(); + const UChar* end = ptr + input.length(); + + while (ptr < end) { + const UChar* inputStart = ptr; + while (ptr < end && *ptr != ',') + ++ptr; + + if (ptr == inputStart) + break; + + // Try to parse unicode range first + UnicodeRange range; + if (parseUnicodeRange(inputStart, ptr - inputStart, range)) + rangeList.append(range); + else + stringList.add(String(inputStart, ptr - inputStart)); + ++ptr; + } +} + Vector<String> parseDelimitedString(const String& input, const char seperator) { Vector<String> values; diff --git a/WebCore/svg/SVGParserUtilities.h b/WebCore/svg/SVGParserUtilities.h index 8d3c9b2..3761688 100644 --- a/WebCore/svg/SVGParserUtilities.h +++ b/WebCore/svg/SVGParserUtilities.h @@ -23,6 +23,10 @@ #if ENABLE(SVG) #include "ParserUtilities.h" +#include <wtf/HashSet.h> + +typedef pair<unsigned, unsigned> UnicodeRange; +typedef Vector<UnicodeRange> UnicodeRanges; namespace WebCore { @@ -64,6 +68,8 @@ namespace WebCore { bool pathFromSVGData(Path& path, const String& d); bool pathSegListFromSVGData(SVGPathSegList* pathSegList, const String& d, bool process = false); Vector<String> parseDelimitedString(const String& input, const char seperator); + void parseKerningUnicodeString(const String& input, UnicodeRanges&, HashSet<String>& stringList); + void parseGlyphName(const String& input, HashSet<String>& values); } // namespace WebCore diff --git a/WebCore/svg/SVGPatternElement.cpp b/WebCore/svg/SVGPatternElement.cpp index 7659afa..3df6198 100644 --- a/WebCore/svg/SVGPatternElement.cpp +++ b/WebCore/svg/SVGPatternElement.cpp @@ -1,6 +1,7 @@ /* Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> + Copyright (C) Research In Motion Limited 2010. 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 @@ -31,9 +32,9 @@ #include "MappedAttribute.h" #include "PatternAttributes.h" #include "RenderSVGContainer.h" +#include "RenderSVGResourcePattern.h" #include "SVGLength.h" #include "SVGNames.h" -#include "SVGPaintServerPattern.h" #include "SVGRenderSupport.h" #include "SVGSVGElement.h" #include "SVGStyledTransformableElement.h" @@ -119,19 +120,20 @@ void SVGPatternElement::svgAttributeChanged(const QualifiedName& attrName) { SVGStyledElement::svgAttributeChanged(attrName); - if (!m_resource) - return; - - if (attrName == SVGNames::patternUnitsAttr || attrName == SVGNames::patternContentUnitsAttr || - attrName == SVGNames::patternTransformAttr || attrName == SVGNames::xAttr || attrName == SVGNames::yAttr || - attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr || - SVGURIReference::isKnownAttribute(attrName) || - SVGTests::isKnownAttribute(attrName) || - SVGLangSpace::isKnownAttribute(attrName) || - SVGExternalResourcesRequired::isKnownAttribute(attrName) || - SVGFitToViewBox::isKnownAttribute(attrName) || - SVGStyledElement::isKnownAttribute(attrName)) - m_resource->invalidate(); + if (attrName == SVGNames::patternUnitsAttr + || attrName == SVGNames::patternContentUnitsAttr + || attrName == SVGNames::patternTransformAttr + || attrName == SVGNames::xAttr + || attrName == SVGNames::yAttr + || attrName == SVGNames::widthAttr + || attrName == SVGNames::heightAttr + || SVGURIReference::isKnownAttribute(attrName) + || SVGTests::isKnownAttribute(attrName) + || SVGLangSpace::isKnownAttribute(attrName) + || SVGExternalResourcesRequired::isKnownAttribute(attrName) + || SVGFitToViewBox::isKnownAttribute(attrName) + || SVGStyledElement::isKnownAttribute(attrName)) + invalidateResourceClients(); } void SVGPatternElement::synchronizeProperty(const QualifiedName& attrName) @@ -180,126 +182,13 @@ void SVGPatternElement::childrenChanged(bool changedByParser, Node* beforeChange { SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); - if (!m_resource) - return; - - m_resource->invalidate(); -} - -void SVGPatternElement::buildPattern(const FloatRect& targetRect) const -{ - PatternAttributes attributes = collectPatternProperties(); - - // If we didn't find any pattern content, ignore the request. - if (!attributes.patternContentElement() || !renderer() || !renderer()->style()) - return; - - FloatRect patternBoundaries; - FloatRect patternContentBoundaries; - - // Determine specified pattern size - if (attributes.boundingBoxMode()) - patternBoundaries = FloatRect(attributes.x().valueAsPercentage() * targetRect.width(), - attributes.y().valueAsPercentage() * targetRect.height(), - attributes.width().valueAsPercentage() * targetRect.width(), - attributes.height().valueAsPercentage() * targetRect.height()); - else - patternBoundaries = FloatRect(attributes.x().value(this), - attributes.y().value(this), - attributes.width().value(this), - attributes.height().value(this)); - - IntSize patternSize(patternBoundaries.width(), patternBoundaries.height()); - clampImageBufferSizeToViewport(document()->view(), patternSize); - - if (patternSize.width() < static_cast<int>(patternBoundaries.width())) - patternBoundaries.setWidth(patternSize.width()); - - if (patternSize.height() < static_cast<int>(patternBoundaries.height())) - patternBoundaries.setHeight(patternSize.height()); - - // Eventually calculate the pattern content boundaries (only needed with overflow="visible"). - RenderStyle* style = renderer()->style(); - if (style->overflowX() == OVISIBLE && style->overflowY() == OVISIBLE) { - for (Node* n = attributes.patternContentElement()->firstChild(); n; n = n->nextSibling()) { - if (!n->isSVGElement() || !static_cast<SVGElement*>(n)->isStyledTransformable() || !n->renderer()) - continue; - patternContentBoundaries.unite(n->renderer()->repaintRectInLocalCoordinates()); - } - } - - AffineTransform viewBoxCTM = viewBoxToViewTransform(viewBox(), preserveAspectRatio(), patternBoundaries.width(), patternBoundaries.height()); - FloatRect patternBoundariesIncludingOverflow = patternBoundaries; - - // Apply objectBoundingBoxMode fixup for patternContentUnits, if viewBox is not set. - if (!patternContentBoundaries.isEmpty()) { - if (!viewBoxCTM.isIdentity()) - patternContentBoundaries = viewBoxCTM.mapRect(patternContentBoundaries); - else if (attributes.boundingBoxModeContent()) - patternContentBoundaries = FloatRect(patternContentBoundaries.x() * targetRect.width(), - patternContentBoundaries.y() * targetRect.height(), - patternContentBoundaries.width() * targetRect.width(), - patternContentBoundaries.height() * targetRect.height()); - - patternBoundariesIncludingOverflow.unite(patternContentBoundaries); - } - - IntSize imageSize(lroundf(patternBoundariesIncludingOverflow.width()), lroundf(patternBoundariesIncludingOverflow.height())); - clampImageBufferSizeToViewport(document()->view(), imageSize); - - OwnPtr<ImageBuffer> patternImage = ImageBuffer::create(imageSize); - - if (!patternImage) - return; - - GraphicsContext* context = patternImage->context(); - ASSERT(context); - - context->save(); - - // Move to pattern start origin - if (patternBoundariesIncludingOverflow.location() != patternBoundaries.location()) { - context->translate(patternBoundaries.x() - patternBoundariesIncludingOverflow.x(), - patternBoundaries.y() - patternBoundariesIncludingOverflow.y()); - - patternBoundaries.setLocation(patternBoundariesIncludingOverflow.location()); - } - - // Process viewBox or boundingBoxModeContent correction - if (!viewBoxCTM.isIdentity()) - context->concatCTM(viewBoxCTM); - else if (attributes.boundingBoxModeContent()) { - context->translate(targetRect.x(), targetRect.y()); - context->scale(FloatSize(targetRect.width(), targetRect.height())); - } - - // Render subtree into ImageBuffer - for (Node* n = attributes.patternContentElement()->firstChild(); n; n = n->nextSibling()) { - if (!n->isSVGElement() || !static_cast<SVGElement*>(n)->isStyled() || !n->renderer()) - continue; - renderSubtreeToImage(patternImage.get(), n->renderer()); - } - - context->restore(); - - m_resource->setPatternTransform(attributes.patternTransform()); - m_resource->setPatternBoundaries(patternBoundaries); - m_resource->setTile(patternImage.release()); + if (!changedByParser) + invalidateResourceClients(); } RenderObject* SVGPatternElement::createRenderer(RenderArena* arena, RenderStyle*) { - RenderSVGContainer* patternContainer = new (arena) RenderSVGContainer(this); - patternContainer->setDrawsContents(false); - return patternContainer; -} - -SVGResource* SVGPatternElement::canvasResource(const RenderObject*) -{ - if (!m_resource) - m_resource = SVGPaintServerPattern::create(this); - - return m_resource.get(); + return new (arena) RenderSVGResourcePattern(this); } PatternAttributes SVGPatternElement::collectPatternProperties() const diff --git a/WebCore/svg/SVGPatternElement.h b/WebCore/svg/SVGPatternElement.h index fffbbca..014d2b4 100644 --- a/WebCore/svg/SVGPatternElement.h +++ b/WebCore/svg/SVGPatternElement.h @@ -22,11 +22,9 @@ #define SVGPatternElement_h #if ENABLE(SVG) -#include "RenderObject.h" #include "SVGExternalResourcesRequired.h" #include "SVGFitToViewBox.h" #include "SVGLangSpace.h" -#include "SVGPaintServerPattern.h" #include "SVGStyledElement.h" #include "SVGTests.h" #include "SVGTransformList.h" @@ -56,7 +54,8 @@ namespace WebCore { virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); - virtual SVGResource* canvasResource(const RenderObject*); + + PatternAttributes collectPatternProperties() const; private: DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::xAttr, SVGLength, X, x) @@ -75,15 +74,7 @@ namespace WebCore { // SVGPatternElement DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::viewBoxAttr, FloatRect, ViewBox, viewBox) - DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::preserveAspectRatioAttr, SVGPreserveAspectRatio, PreserveAspectRatio, preserveAspectRatio) - - mutable RefPtr<SVGPaintServerPattern> m_resource; - - private: - friend class SVGPaintServerPattern; - void buildPattern(const FloatRect& targetRect) const; - - PatternAttributes collectPatternProperties() const; + DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::preserveAspectRatioAttr, SVGPreserveAspectRatio, PreserveAspectRatio, preserveAspectRatio) }; } // namespace WebCore diff --git a/WebCore/svg/SVGPolyElement.cpp b/WebCore/svg/SVGPolyElement.cpp index 371c679..73940dc 100644 --- a/WebCore/svg/SVGPolyElement.cpp +++ b/WebCore/svg/SVGPolyElement.cpp @@ -88,7 +88,7 @@ void SVGPolyElement::svgAttributeChanged(const QualifiedName& attrName) // The points property is not a regular SVGAnimatedProperty, still we use the same SVG<->XML DOM synchronization framework. if (attrName == SVGNames::pointsAttr) - setSynchronizedSVGAttributes(false); + invalidateSVGAttributes(); RenderPath* renderer = static_cast<RenderPath*>(this->renderer()); if (!renderer) diff --git a/WebCore/svg/SVGPolyElement.h b/WebCore/svg/SVGPolyElement.h index b881ca2..88947de 100644 --- a/WebCore/svg/SVGPolyElement.h +++ b/WebCore/svg/SVGPolyElement.h @@ -48,7 +48,6 @@ namespace WebCore { virtual void svgAttributeChanged(const QualifiedName&); virtual void synchronizeProperty(const QualifiedName&); - virtual bool rendererIsNeeded(RenderStyle* style) { return StyledElement::rendererIsNeeded(style); } virtual bool supportsMarkers() const { return true; } private: diff --git a/WebCore/svg/SVGRadialGradientElement.cpp b/WebCore/svg/SVGRadialGradientElement.cpp index b153c0f..29cc1cc 100644 --- a/WebCore/svg/SVGRadialGradientElement.cpp +++ b/WebCore/svg/SVGRadialGradientElement.cpp @@ -3,6 +3,7 @@ 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> 2008 Eric Seidel <eric@webkit.org> 2008 Dirk Schulze <krit@webkit.org> + Copyright (C) Research In Motion Limited 2010. 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 @@ -29,10 +30,9 @@ #include "FloatPoint.h" #include "MappedAttribute.h" #include "RadialGradientAttributes.h" -#include "RenderObject.h" +#include "RenderSVGResourceRadialGradient.h" #include "SVGLength.h" #include "SVGNames.h" -#include "SVGPaintServerRadialGradient.h" #include "SVGStopElement.h" #include "SVGTransform.h" #include "SVGTransformList.h" @@ -77,13 +77,12 @@ void SVGRadialGradientElement::svgAttributeChanged(const QualifiedName& attrName { SVGGradientElement::svgAttributeChanged(attrName); - if (!m_resource) - return; - - if (attrName == SVGNames::cxAttr || attrName == SVGNames::cyAttr || - attrName == SVGNames::fxAttr || attrName == SVGNames::fyAttr || - attrName == SVGNames::rAttr) - m_resource->invalidate(); + if (attrName == SVGNames::cxAttr + || attrName == SVGNames::cyAttr + || attrName == SVGNames::fxAttr + || attrName == SVGNames::fyAttr + || attrName == SVGNames::rAttr) + invalidateResourceClients(); } void SVGRadialGradientElement::synchronizeProperty(const QualifiedName& attrName) @@ -111,77 +110,18 @@ void SVGRadialGradientElement::synchronizeProperty(const QualifiedName& attrName synchronizeR(); } -void SVGRadialGradientElement::buildGradient() const +RenderObject* SVGRadialGradientElement::createRenderer(RenderArena* arena, RenderStyle*) { - RadialGradientAttributes attributes = collectGradientProperties(); - - RefPtr<SVGPaintServerRadialGradient> radialGradient = WTF::static_pointer_cast<SVGPaintServerRadialGradient>(m_resource); - - FloatPoint focalPoint; - FloatPoint centerPoint; - float radius; - if (attributes.boundingBoxMode()) { - focalPoint = FloatPoint(attributes.fx().valueAsPercentage(), attributes.fy().valueAsPercentage()); - centerPoint = FloatPoint(attributes.cx().valueAsPercentage(), attributes.cy().valueAsPercentage()); - radius = attributes.r().valueAsPercentage(); - } else { - focalPoint = FloatPoint(attributes.fx().value(this), attributes.fy().value(this)); - centerPoint = FloatPoint(attributes.cx().value(this), attributes.cy().value(this)); - radius = attributes.r().value(this); - } - - FloatPoint adjustedFocalPoint = focalPoint; - float dfx = focalPoint.x() - centerPoint.x(); - float dfy = focalPoint.y() - centerPoint.y(); - float rMax = 0.99f * radius; - - // Spec: If (fx, fy) lies outside the circle defined by (cx, cy) and - // r, set (fx, fy) to the point of intersection of the line through - // (fx, fy) and the circle. - // We scale the radius by 0.99 to match the behavior of FireFox. - if (sqrt(dfx * dfx + dfy * dfy) > rMax) { - float angle = atan2f(dfy, dfx); - - dfx = cosf(angle) * rMax; - dfy = sinf(angle) * rMax; - adjustedFocalPoint = FloatPoint(dfx + centerPoint.x(), dfy + centerPoint.y()); - } - - RefPtr<Gradient> gradient = Gradient::create( - adjustedFocalPoint, - 0.f, // SVG does not support a "focus radius" - centerPoint, - radius); - gradient->setSpreadMethod(attributes.spreadMethod()); - - Vector<SVGGradientStop> stops = attributes.stops(); - float previousOffset = 0.0f; - for (unsigned i = 0; i < stops.size(); ++i) { - float offset = std::min(std::max(previousOffset, stops[i].first), 1.0f); - previousOffset = offset; - gradient->addColorStop(offset, stops[i].second); - } - - radialGradient->setGradient(gradient); - - if (attributes.stops().isEmpty()) - return; - - radialGradient->setBoundingBoxMode(attributes.boundingBoxMode()); - radialGradient->setGradientTransform(attributes.gradientTransform()); - radialGradient->setGradientCenter(centerPoint); - radialGradient->setGradientFocal(focalPoint); - radialGradient->setGradientRadius(radius); - radialGradient->setGradientStops(attributes.stops()); + return new (arena) RenderSVGResourceRadialGradient(this); } -RadialGradientAttributes SVGRadialGradientElement::collectGradientProperties() const +RadialGradientAttributes SVGRadialGradientElement::collectGradientProperties() { RadialGradientAttributes attributes; - HashSet<const SVGGradientElement*> processedGradients; + HashSet<SVGGradientElement*> processedGradients; bool isRadial = true; - const SVGGradientElement* current = this; + SVGGradientElement* current = this; while (current) { if (!attributes.hasSpreadMethod() && current->hasAttribute(SVGNames::spreadMethodAttr)) @@ -194,13 +134,13 @@ RadialGradientAttributes SVGRadialGradientElement::collectGradientProperties() c attributes.setGradientTransform(current->gradientTransform()->consolidate().matrix()); if (!attributes.hasStops()) { - const Vector<SVGGradientStop>& stops(current->buildStops()); + const Vector<Gradient::ColorStop>& stops(current->buildStops()); if (!stops.isEmpty()) attributes.setStops(stops); } if (isRadial) { - const SVGRadialGradientElement* radial = static_cast<const SVGRadialGradientElement*>(current); + SVGRadialGradientElement* radial = static_cast<SVGRadialGradientElement*>(current); if (!attributes.hasCx() && current->hasAttribute(SVGNames::cxAttr)) attributes.setCx(radial->cx()); @@ -223,13 +163,13 @@ RadialGradientAttributes SVGRadialGradientElement::collectGradientProperties() c // Respect xlink:href, take attributes from referenced element Node* refNode = ownerDocument()->getElementById(SVGURIReference::getTarget(current->href())); if (refNode && (refNode->hasTagName(SVGNames::radialGradientTag) || refNode->hasTagName(SVGNames::linearGradientTag))) { - current = static_cast<const SVGGradientElement*>(const_cast<const Node*>(refNode)); + current = static_cast<SVGGradientElement*>(refNode); // Cycle detection if (processedGradients.contains(current)) return RadialGradientAttributes(); - isRadial = current->gradientType() == RadialGradientPaintServer; + isRadial = current->hasTagName(SVGNames::radialGradientTag); } else current = 0; } @@ -243,6 +183,37 @@ RadialGradientAttributes SVGRadialGradientElement::collectGradientProperties() c return attributes; } + +void SVGRadialGradientElement::calculateFocalCenterPointsAndRadius(const RadialGradientAttributes& attributes, FloatPoint& focalPoint, FloatPoint& centerPoint, float& radius) +{ + // Determine gradient focal/center points and radius + if (attributes.boundingBoxMode()) { + focalPoint = FloatPoint(attributes.fx().valueAsPercentage(), attributes.fy().valueAsPercentage()); + centerPoint = FloatPoint(attributes.cx().valueAsPercentage(), attributes.cy().valueAsPercentage()); + radius = attributes.r().valueAsPercentage(); + } else { + focalPoint = FloatPoint(attributes.fx().value(this), attributes.fy().value(this)); + centerPoint = FloatPoint(attributes.cx().value(this), attributes.cy().value(this)); + radius = attributes.r().value(this); + } + + // Eventually adjust focal points, as described below + float deltaX = focalPoint.x() - centerPoint.x(); + float deltaY = focalPoint.y() - centerPoint.y(); + float radiusMax = 0.99f * radius; + + // Spec: If (fx, fy) lies outside the circle defined by (cx, cy) and r, set + // (fx, fy) to the point of intersection of the line through (fx, fy) and the circle. + // We scale the radius by 0.99 to match the behavior of FireFox. + if (sqrt(deltaX * deltaX + deltaY * deltaY) > radiusMax) { + float angle = atan2f(deltaY, deltaX); + + deltaX = cosf(angle) * radiusMax; + deltaY = sinf(angle) * radiusMax; + focalPoint = FloatPoint(deltaX + centerPoint.x(), deltaY + centerPoint.y()); + } +} + } #endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGRadialGradientElement.h b/WebCore/svg/SVGRadialGradientElement.h index 180948f..25219db 100644 --- a/WebCore/svg/SVGRadialGradientElement.h +++ b/WebCore/svg/SVGRadialGradientElement.h @@ -38,11 +38,10 @@ namespace WebCore { virtual void svgAttributeChanged(const QualifiedName&); virtual void synchronizeProperty(const QualifiedName&); - protected: - virtual void buildGradient() const; - virtual SVGPaintServerType gradientType() const { return RadialGradientPaintServer; } + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); - RadialGradientAttributes collectGradientProperties() const; + RadialGradientAttributes collectGradientProperties(); + void calculateFocalCenterPointsAndRadius(const RadialGradientAttributes&, FloatPoint& focalPoint, FloatPoint& centerPoint, float& radius); private: DECLARE_ANIMATED_PROPERTY(SVGRadialGradientElement, SVGNames::cxAttr, SVGLength, Cx, cx) diff --git a/WebCore/svg/SVGStopElement.cpp b/WebCore/svg/SVGStopElement.cpp index 3c97827..3ac2d5b 100644 --- a/WebCore/svg/SVGStopElement.cpp +++ b/WebCore/svg/SVGStopElement.cpp @@ -49,8 +49,6 @@ void SVGStopElement::parseMappedAttribute(MappedAttribute* attr) setOffsetBaseValue(value.left(value.length() - 1).toFloat() / 100.0f); else setOffsetBaseValue(value.toFloat()); - - setNeedsStyleRecalc(); } else SVGStyledElement::parseMappedAttribute(attr); } @@ -68,6 +66,15 @@ RenderObject* SVGStopElement::createRenderer(RenderArena* arena, RenderStyle*) return new (arena) RenderSVGGradientStop(this); } +Color SVGStopElement::stopColorIncludingOpacity() const +{ + ASSERT(renderer()); + ASSERT(renderer()->style()); + + const SVGRenderStyle* svgStyle = renderer()->style()->svgStyle(); + return colorWithOverrideAlpha(svgStyle->stopColor().rgb(), svgStyle->stopOpacity()); +} + } #endif // ENABLE(SVG) diff --git a/WebCore/svg/SVGStopElement.h b/WebCore/svg/SVGStopElement.h index 23c09bb..222dd4d 100644 --- a/WebCore/svg/SVGStopElement.h +++ b/WebCore/svg/SVGStopElement.h @@ -32,13 +32,14 @@ namespace WebCore { SVGStopElement(const QualifiedName&, Document*); virtual ~SVGStopElement(); + virtual void parseMappedAttribute(MappedAttribute*); virtual void synchronizeProperty(const QualifiedName&); + Color stopColorIncludingOpacity() const; + private: virtual bool isGradientStop() const { return true; } - virtual void parseMappedAttribute(MappedAttribute*); - virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); DECLARE_ANIMATED_PROPERTY(SVGStopElement, SVGNames::offsetAttr, float, Offset, offset) diff --git a/WebCore/svg/SVGStyledElement.cpp b/WebCore/svg/SVGStyledElement.cpp index 22c2008..9a3f950 100644 --- a/WebCore/svg/SVGStyledElement.cpp +++ b/WebCore/svg/SVGStyledElement.cpp @@ -41,8 +41,8 @@ #include "SVGNames.h" #include "SVGRenderStyle.h" #include "SVGRenderSupport.h" -#include "SVGResource.h" #include "SVGSVGElement.h" +#include "SVGUseElement.h" #include <wtf/Assertions.h> namespace WebCore { @@ -63,7 +63,50 @@ SVGStyledElement::SVGStyledElement(const QualifiedName& tagName, Document* doc) SVGStyledElement::~SVGStyledElement() { - SVGResource::removeClient(this); +} + +String SVGStyledElement::title() const +{ + // According to spec, we should not return titles when hovering over <svg> elements (those + // <title> elements are the title of the document, not a tooltip) so we instantly return. + if (hasTagName(SVGNames::svgTag)) + return String(); + + // Walk up the tree, to find out whether we're inside a <use> shadow tree, to find the right title. + Node* parent = const_cast<SVGStyledElement*>(this); + while (parent) { + if (!parent->isShadowNode()) { + parent = parent->parentNode(); + continue; + } + + // Get the <use> element. + Node* shadowParent = parent->shadowParentNode(); + if (shadowParent && shadowParent->isSVGElement() && shadowParent->hasTagName(SVGNames::useTag)) { + SVGUseElement* useElement = static_cast<SVGUseElement*>(shadowParent); + // If the <use> title is not empty we found the title to use. + String useTitle(useElement->title()); + if (useTitle.isEmpty()) + break; + return useTitle; + } + parent = parent->parentNode(); + } + + // If we aren't an instance in a <use> or the <use> title was not found, then find the first + // <title> child of this element. + Element* titleElement = firstElementChild(); + for (; titleElement; titleElement = titleElement->nextElementSibling()) { + if (titleElement->hasTagName(SVGNames::titleTag) && titleElement->isSVGElement()) + break; + } + + // If a title child was found, return the text contents. + if (titleElement) + return titleElement->innerText(); + + // Otherwise return a null/empty string. + return String(); } bool SVGStyledElement::rendererIsNeeded(RenderStyle* style) @@ -200,19 +243,21 @@ void SVGStyledElement::svgAttributeChanged(const QualifiedName& attrName) if (attrName.matches(HTMLNames::classAttr)) classAttributeChanged(className()); + RenderObject* object = renderer(); + if (attrName == idAttributeName()) { // Notify resources about id changes, this is important as we cache resources by id in SVGDocumentExtensions - if (renderer() && renderer()->isSVGResource()) { - RenderSVGResource* resource = renderer()->toRenderSVGResource(); - resource->idChanged(); - } + if (object && object->isSVGResourceContainer()) + object->toRenderSVGResourceContainer()->idChanged(); } - // If we're the child of a resource element, be sure to invalidate it. - invalidateResourcesInAncestorChain(); + if (!document()->parsing() && object) { + // If we're the child of a resource element, tell the resource (and eventually its resources) that we've changed. + invalidateResourcesInAncestorChain(); - // If the element is using resources, invalidate them. - invalidateResources(); + // If we're referencing resources, tell them we've changed. + deregisterFromResources(object); + } // Invalidate all SVGElementInstances associated with us SVGElementInstance::invalidateAllInstancesOfElement(this); @@ -226,20 +271,6 @@ void SVGStyledElement::synchronizeProperty(const QualifiedName& attrName) synchronizeClassName(); } -void SVGStyledElement::invalidateResources() -{ - RenderObject* object = renderer(); - if (!object) - return; - - Document* document = this->document(); - - if (document->parsing()) - return; - - deregisterFromResources(object); -} - void SVGStyledElement::invalidateResourcesInAncestorChain() const { Node* node = parentNode(); @@ -248,25 +279,25 @@ void SVGStyledElement::invalidateResourcesInAncestorChain() const break; SVGElement* element = static_cast<SVGElement*>(node); - if (SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(element->isStyled() ? element : 0)) - styledElement->invalidateCanvasResources(); + if (SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(element->isStyled() ? element : 0)) { + styledElement->invalidateResourceClients(); + + // If we found the first resource in the ancestor chain, immediately stop. + break; + } node = node->parentNode(); } } -void SVGStyledElement::invalidateCanvasResources() +void SVGStyledElement::invalidateResourceClients() { RenderObject* object = renderer(); if (!object) return; - if (object->isSVGResource()) - object->toRenderSVGResource()->invalidateClients(); - - // The following lines will be removed soon, once all resources are handled by renderers. - if (SVGResource* resource = canvasResource(object)) - resource->invalidate(); + if (object->isSVGResourceContainer()) + object->toRenderSVGResourceContainer()->invalidateClients(); } void SVGStyledElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) @@ -274,7 +305,8 @@ void SVGStyledElement::childrenChanged(bool changedByParser, Node* beforeChange, SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); // Invalidate all SVGElementInstances associated with us - SVGElementInstance::invalidateAllInstancesOfElement(this); + if (!changedByParser) + SVGElementInstance::invalidateAllInstancesOfElement(this); } PassRefPtr<RenderStyle> SVGStyledElement::resolveStyle(RenderStyle* parentStyle) @@ -309,12 +341,6 @@ PassRefPtr<CSSValue> SVGStyledElement::getPresentationAttribute(const String& na return cssSVGAttr->style()->getPropertyCSSValue(name); } -void SVGStyledElement::detach() -{ - SVGResource::removeClient(this); - SVGElement::detach(); -} - bool SVGStyledElement::instanceUpdatesBlocked() const { return hasRareSVGData() && rareSVGData()->instanceUpdatesBlocked(); diff --git a/WebCore/svg/SVGStyledElement.h b/WebCore/svg/SVGStyledElement.h index ea19aa5..69d7e96 100644 --- a/WebCore/svg/SVGStyledElement.h +++ b/WebCore/svg/SVGStyledElement.h @@ -29,8 +29,6 @@ namespace WebCore { - class SVGResource; - void mapAttributeToCSSProperty(HashMap<AtomicStringImpl*, int>* propertyNameToIdMap, const QualifiedName& attrName); class SVGStyledElement : public SVGElement, @@ -39,6 +37,8 @@ namespace WebCore { SVGStyledElement(const QualifiedName&, Document*); virtual ~SVGStyledElement(); + virtual String title() const; + virtual bool hasRelativeValues() const { return false; } virtual bool isStyled() const { return true; } virtual bool supportsMarkers() const { return false; } @@ -49,7 +49,6 @@ namespace WebCore { bool isKnownAttribute(const QualifiedName&); virtual bool rendererIsNeeded(RenderStyle*); - virtual SVGResource* canvasResource(const RenderObject*) { return 0; } virtual bool mapToEntry(const QualifiedName&, MappedAttributeEntry&) const; virtual void parseMappedAttribute(MappedAttribute*); @@ -61,10 +60,8 @@ namespace WebCore { // Centralized place to force a manual style resolution. Hacky but needed for now. PassRefPtr<RenderStyle> resolveStyle(RenderStyle* parentStyle); + void invalidateResourceClients(); void invalidateResourcesInAncestorChain() const; - void invalidateResources(); - - virtual void detach(); bool instanceUpdatesBlocked() const; void setInstanceUpdatesBlocked(bool); @@ -74,8 +71,6 @@ namespace WebCore { protected: static int cssPropertyIdForSVGAttributeName(const QualifiedName&); - void invalidateCanvasResources(); - private: DECLARE_ANIMATED_PROPERTY(SVGStyledElement, HTMLNames::classAttr, String, ClassName, className) }; diff --git a/WebCore/svg/SVGTextContentElement.cpp b/WebCore/svg/SVGTextContentElement.cpp index b28536b..3f1ec49 100644 --- a/WebCore/svg/SVGTextContentElement.cpp +++ b/WebCore/svg/SVGTextContentElement.cpp @@ -32,7 +32,7 @@ #include "MappedAttribute.h" #include "Position.h" #include "RenderSVGText.h" -#include "SVGCharacterLayoutInfo.h" +#include "SVGCharacterData.h" #include "SVGInlineTextBox.h" #include "SVGLength.h" #include "SVGNames.h" diff --git a/WebCore/svg/SVGTextPathElement.h b/WebCore/svg/SVGTextPathElement.h index ff09ed2..0862335 100644 --- a/WebCore/svg/SVGTextPathElement.h +++ b/WebCore/svg/SVGTextPathElement.h @@ -58,7 +58,6 @@ namespace WebCore { virtual void parseMappedAttribute(MappedAttribute*); virtual void synchronizeProperty(const QualifiedName&); - virtual bool rendererIsNeeded(RenderStyle* style) { return StyledElement::rendererIsNeeded(style); } virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); bool childShouldCreateRenderer(Node*) const; diff --git a/WebCore/svg/SVGURIReference.cpp b/WebCore/svg/SVGURIReference.cpp index 5fe71ab..5dbdfb8 100644 --- a/WebCore/svg/SVGURIReference.cpp +++ b/WebCore/svg/SVGURIReference.cpp @@ -60,8 +60,8 @@ String SVGURIReference::getTarget(const String& url) } else if (url.find('#') > -1) { // format is #target unsigned int start = url.find('#') + 1; return url.substring(start, url.length() - start); - } else // Normal Reference, ie. style="color-profile:changeColor" - return url; + } else // The url doesn't have any target. + return String(); } } diff --git a/WebCore/svg/graphics/SVGImage.cpp b/WebCore/svg/graphics/SVGImage.cpp index 11d3f60..97ef710 100644 --- a/WebCore/svg/graphics/SVGImage.cpp +++ b/WebCore/svg/graphics/SVGImage.cpp @@ -186,13 +186,22 @@ void SVGImage::draw(GraphicsContext* context, const FloatRect& dstRect, const Fl context->clip(enclosingIntRect(dstRect)); if (compositeOp != CompositeSourceOver) context->beginTransparencyLayer(1); - context->translate(dstRect.location().x(), dstRect.location().y()); - context->scale(FloatSize(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height())); + + FloatSize scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height()); + + // We can only draw the entire frame, clipped to the rect we want. So compute where the top left + // of the image would be if we were drawing without clipping, and translate accordingly. + FloatSize topLeftOffset(srcRect.location().x() * scale.width(), srcRect.location().y() * scale.height()); + FloatPoint destOffset = dstRect.location() - topLeftOffset; + + context->translate(destOffset.x(), destOffset.y()); + context->scale(scale); view->resize(size()); if (view->needsLayout()) view->layout(); + view->paint(context, IntRect(0, 0, view->width(), view->height())); if (compositeOp != CompositeSourceOver) diff --git a/WebCore/svg/graphics/SVGPaintServer.h b/WebCore/svg/graphics/SVGPaintServer.h deleted file mode 100644 index d9d2218..0000000 --- a/WebCore/svg/graphics/SVGPaintServer.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.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 SVGPaintServer_h -#define SVGPaintServer_h - -#if ENABLE(SVG) - -#include "DashArray.h" -#include "RenderObject.h" -#include "SVGResource.h" - -#if PLATFORM(CG) -#include <ApplicationServices/ApplicationServices.h> -#endif - -namespace WebCore { - - enum SVGPaintServerType { - // Painting mode - SolidPaintServer = 0, - PatternPaintServer = 1, - LinearGradientPaintServer = 2, - RadialGradientPaintServer = 3 - }; - - enum SVGPaintTargetType { - // Target mode - ApplyToFillTargetType = 1, - ApplyToStrokeTargetType = 2 - }; - - class GraphicsContext; - class RenderObject; - class RenderStyle; - class SVGPaintServerSolid; - - class SVGPaintServer : public SVGResource { - public: - virtual ~SVGPaintServer(); - - virtual SVGResourceType resourceType() const { return PaintServerResourceType; } - - virtual SVGPaintServerType type() const = 0; - virtual TextStream& externalRepresentation(TextStream&) const = 0; - - // To be implemented in platform specific code. - virtual void draw(GraphicsContext*&, const RenderObject*, SVGPaintTargetType) const; - virtual void teardown(GraphicsContext*&, const RenderObject*, SVGPaintTargetType, bool isPaintingText = false) const; - virtual void renderPath(GraphicsContext*&, const RenderObject*, SVGPaintTargetType) const; - - virtual bool setup(GraphicsContext*&, const RenderObject*, const RenderStyle*, SVGPaintTargetType, bool isPaintingText = false) const = 0; - - bool setup(GraphicsContext*&, const RenderObject*, SVGPaintTargetType, bool isPaintingText = false) const; - - static SVGPaintServer* strokePaintServer(const RenderStyle*, const RenderObject*); - static SVGPaintServer* fillPaintServer(const RenderStyle*, const RenderObject*); - static SVGPaintServerSolid* sharedSolidPaintServer(); - - protected: - SVGPaintServer(); - }; - - TextStream& operator<<(TextStream&, const SVGPaintServer&); - - SVGPaintServer* getPaintServerById(Document*, const AtomicString&, const RenderObject*); - - void applyStrokeStyleToContext(GraphicsContext*, const RenderStyle*, const RenderObject*); - DashArray dashArrayFromRenderingStyle(const RenderStyle* style, RenderStyle* rootStyle); -} // namespace WebCore - -#endif - -#endif // SVGPaintServer_h diff --git a/WebCore/svg/graphics/SVGPaintServerGradient.cpp b/WebCore/svg/graphics/SVGPaintServerGradient.cpp deleted file mode 100644 index 6e6ebfc..0000000 --- a/WebCore/svg/graphics/SVGPaintServerGradient.cpp +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> - * 2008 Eric Seidel <eric@webkit.org> - * 2008 Dirk Schulze <krit@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" - -#if ENABLE(SVG) -#include "SVGPaintServerGradient.h" - -#include "FloatConversion.h" -#include "GraphicsContext.h" -#include "ImageBuffer.h" -#include "RenderObject.h" -#include "RenderView.h" -#include "SVGGradientElement.h" -#include "SVGPaintServerLinearGradient.h" -#include "SVGPaintServerRadialGradient.h" -#include "SVGRenderSupport.h" -#include "SVGRenderTreeAsText.h" - -using namespace std; - -namespace WebCore { - -static TextStream& operator<<(TextStream& ts, GradientSpreadMethod m) -{ - switch (m) { - case SpreadMethodPad: - ts << "PAD"; break; - case SpreadMethodRepeat: - ts << "REPEAT"; break; - case SpreadMethodReflect: - ts << "REFLECT"; break; - } - - return ts; -} - -static TextStream& operator<<(TextStream& ts, const Vector<SVGGradientStop>& l) -{ - ts << "["; - for (Vector<SVGGradientStop>::const_iterator it = l.begin(); it != l.end(); ++it) { - ts << "(" << it->first << "," << it->second << ")"; - if (it + 1 != l.end()) - ts << ", "; - } - ts << "]"; - return ts; -} - -SVGPaintServerGradient::SVGPaintServerGradient(const SVGGradientElement* owner) - : m_boundingBoxMode(true) - , m_ownerElement(owner) -#if PLATFORM(CG) - , m_savedContext(0) - , m_imageBuffer(0) -#endif -{ - ASSERT(owner); -} - -SVGPaintServerGradient::~SVGPaintServerGradient() -{ -} - -Gradient* SVGPaintServerGradient::gradient() const -{ - return m_gradient.get(); -} - -void SVGPaintServerGradient::setGradient(PassRefPtr<Gradient> gradient) -{ - m_gradient = gradient; -} - -bool SVGPaintServerGradient::boundingBoxMode() const -{ - return m_boundingBoxMode; -} - -void SVGPaintServerGradient::setBoundingBoxMode(bool mode) -{ - m_boundingBoxMode = mode; -} - -AffineTransform SVGPaintServerGradient::gradientTransform() const -{ - return m_gradientTransform; -} - -void SVGPaintServerGradient::setGradientTransform(const AffineTransform& transform) -{ - m_gradientTransform = transform; -} - -#if PLATFORM(CG) -static inline AffineTransform absoluteTransformForRenderer(const RenderObject* object) -{ - AffineTransform absoluteTransform; - - const RenderObject* currentObject = object; - while (currentObject) { - absoluteTransform = currentObject->localToParentTransform() * absoluteTransform; - currentObject = currentObject->parent(); - } - - return absoluteTransform; -} - -static inline bool createMaskAndSwapContextForTextGradient( - GraphicsContext*& context, GraphicsContext*& savedContext, - OwnPtr<ImageBuffer>& imageBuffer, const RenderObject* object) -{ - const RenderObject* textRootBlock = findTextRootObject(object); - - AffineTransform transform = absoluteTransformForRenderer(textRootBlock); - FloatRect maskAbsoluteBoundingBox = transform.mapRect(textRootBlock->repaintRectInLocalCoordinates()); - - IntRect maskImageRect = enclosingIntRect(maskAbsoluteBoundingBox); - if (maskImageRect.isEmpty()) - return false; - - // Allocate an image buffer as big as the absolute unclipped size of the object - OwnPtr<ImageBuffer> maskImage = ImageBuffer::create(maskImageRect.size()); - if (!maskImage) - return false; - - GraphicsContext* maskImageContext = maskImage->context(); - - // Transform the mask image coordinate system to absolute screen coordinates - maskImageContext->translate(-maskAbsoluteBoundingBox.x(), -maskAbsoluteBoundingBox.y()); - maskImageContext->concatCTM(transform); - - imageBuffer.set(maskImage.release()); - savedContext = context; - context = maskImageContext; - - return true; -} - -static inline AffineTransform clipToTextMask(GraphicsContext* context, - OwnPtr<ImageBuffer>& imageBuffer, const RenderObject* object, - const SVGPaintServerGradient* gradientServer) -{ - const RenderObject* textRootBlock = findTextRootObject(object); - context->clipToImageBuffer(textRootBlock->repaintRectInLocalCoordinates(), imageBuffer.get()); - - AffineTransform matrix; - if (gradientServer->boundingBoxMode()) { - FloatRect maskBoundingBox = textRootBlock->objectBoundingBox(); - matrix.translate(maskBoundingBox.x(), maskBoundingBox.y()); - matrix.scaleNonUniform(maskBoundingBox.width(), maskBoundingBox.height()); - } - matrix.multiply(gradientServer->gradientTransform()); - return matrix; -} -#endif - -bool SVGPaintServerGradient::setup(GraphicsContext*& context, const RenderObject* object, const RenderStyle*style, SVGPaintTargetType type, bool isPaintingText) const -{ - m_ownerElement->buildGradient(); - - const SVGRenderStyle* svgStyle = style->svgStyle(); - bool isFilled = (type & ApplyToFillTargetType) && svgStyle->hasFill(); - bool isStroked = (type & ApplyToStrokeTargetType) && svgStyle->hasStroke(); - - ASSERT((isFilled && !isStroked) || (!isFilled && isStroked)); - - context->save(); - - if (isPaintingText) { -#if PLATFORM(CG) - if (!createMaskAndSwapContextForTextGradient(context, m_savedContext, m_imageBuffer, object)) { - context->restore(); - return false; - } -#endif - context->setTextDrawingMode(isFilled ? cTextFill : cTextStroke); - } - - if (isFilled) { - context->setAlpha(svgStyle->fillOpacity()); - context->setFillGradient(m_gradient); - context->setFillRule(svgStyle->fillRule()); - } - if (isStroked) { - context->setAlpha(svgStyle->strokeOpacity()); - context->setStrokeGradient(m_gradient); - applyStrokeStyleToContext(context, style, object); - } - - AffineTransform matrix; - // CG platforms will handle the gradient space transform for text in - // teardown, so we don't apply it here. For non-CG platforms, we - // want the text bounding box applied to the gradient space transform now, - // so the gradient shader can use it. -#if PLATFORM(CG) - if (boundingBoxMode() && !isPaintingText) { -#else - if (boundingBoxMode()) { -#endif - FloatRect bbox = object->objectBoundingBox(); - matrix.translate(bbox.x(), bbox.y()); - matrix.scaleNonUniform(bbox.width(), bbox.height()); - } - matrix.multiply(gradientTransform()); - m_gradient->setGradientSpaceTransform(matrix); - - return true; -} - -void SVGPaintServerGradient::teardown(GraphicsContext*& context, const RenderObject* object, SVGPaintTargetType, bool isPaintingText) const -{ -#if PLATFORM(CG) - // renderPath() is not used when painting text, so we paint the gradient during teardown() - if (isPaintingText && m_savedContext) { - // Restore on-screen drawing context - context = m_savedContext; - m_savedContext = 0; - - AffineTransform matrix = clipToTextMask(context, m_imageBuffer, object, this); - m_gradient->setGradientSpaceTransform(matrix); - context->setFillGradient(m_gradient); - - const RenderObject* textRootBlock = findTextRootObject(object); - context->fillRect(textRootBlock->repaintRectInLocalCoordinates()); - - m_imageBuffer.clear(); - } -#endif - context->restore(); -} - -TextStream& SVGPaintServerGradient::externalRepresentation(TextStream& ts) const -{ - // Gradients/patterns aren't setup, until they are used for painting. Work around that fact. - m_ownerElement->buildGradient(); - - // abstract, don't stream type - ts << "[stops=" << gradientStops() << "]"; - if (m_gradient->spreadMethod() != SpreadMethodPad) - ts << "[method=" << m_gradient->spreadMethod() << "]"; - if (!boundingBoxMode()) - ts << " [bounding box mode=" << boundingBoxMode() << "]"; - if (!gradientTransform().isIdentity()) - ts << " [transform=" << gradientTransform() << "]"; - - return ts; -} - -} // namespace WebCore - -#endif diff --git a/WebCore/svg/graphics/SVGPaintServerGradient.h b/WebCore/svg/graphics/SVGPaintServerGradient.h deleted file mode 100644 index 953b0d9..0000000 --- a/WebCore/svg/graphics/SVGPaintServerGradient.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> - * 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. - */ - -#ifndef SVGPaintServerGradient_h -#define SVGPaintServerGradient_h - -#if ENABLE(SVG) - -#include "AffineTransform.h" -#include "Color.h" -#include "Gradient.h" -#include "GraphicsContext.h" -#include "SVGPaintServer.h" - -#include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - - class ImageBuffer; - class SVGGradientElement; - - typedef std::pair<float, Color> SVGGradientStop; - - class SVGPaintServerGradient : public SVGPaintServer { - public: - virtual ~SVGPaintServerGradient(); - - void setGradient(PassRefPtr<Gradient>); - Gradient* gradient() const; - - // Gradient start and end points are percentages when used in boundingBox mode. - // For instance start point with value (0,0) is top-left and end point with - // value (100, 100) is bottom-right. BoundingBox mode is enabled by default. - bool boundingBoxMode() const; - void setBoundingBoxMode(bool mode = true); - - AffineTransform gradientTransform() const; - void setGradientTransform(const AffineTransform&); - - void setGradientStops(const Vector<SVGGradientStop>& stops) { m_stops = stops; } - const Vector<SVGGradientStop>& gradientStops() const { return m_stops; } - - virtual TextStream& externalRepresentation(TextStream&) const; - - virtual bool setup(GraphicsContext*&, const RenderObject*, const RenderStyle*, SVGPaintTargetType, bool isPaintingText) const; - virtual void teardown(GraphicsContext*&, const RenderObject*, SVGPaintTargetType, bool isPaintingText) const; - - protected: - SVGPaintServerGradient(const SVGGradientElement* owner); - - private: - Vector<SVGGradientStop> m_stops; - RefPtr<Gradient> m_gradient; - bool m_boundingBoxMode; - AffineTransform m_gradientTransform; - const SVGGradientElement* m_ownerElement; - -#if PLATFORM(CG) - public: - mutable GraphicsContext* m_savedContext; - mutable OwnPtr<ImageBuffer> m_imageBuffer; -#endif - }; - - inline SVGGradientStop makeGradientStop(float offset, const Color& color) - { - return std::make_pair(offset, color); - } - -} // namespace WebCore - -#endif - -#endif // SVGPaintServerGradient_h diff --git a/WebCore/svg/graphics/SVGPaintServerLinearGradient.h b/WebCore/svg/graphics/SVGPaintServerLinearGradient.h deleted file mode 100644 index f0568c7..0000000 --- a/WebCore/svg/graphics/SVGPaintServerLinearGradient.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.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 SVGPaintServerLinearGradient_h -#define SVGPaintServerLinearGradient_h - -#if ENABLE(SVG) - -#include "FloatPoint.h" -#include "SVGPaintServerGradient.h" - -namespace WebCore { - - class SVGPaintServerLinearGradient : public SVGPaintServerGradient { - public: - static PassRefPtr<SVGPaintServerLinearGradient> create(const SVGGradientElement* owner) { return adoptRef(new SVGPaintServerLinearGradient(owner)); } - virtual ~SVGPaintServerLinearGradient(); - - virtual SVGPaintServerType type() const { return LinearGradientPaintServer; } - - FloatPoint gradientStart() const; - void setGradientStart(const FloatPoint&); - - FloatPoint gradientEnd() const; - void setGradientEnd(const FloatPoint&); - - virtual TextStream& externalRepresentation(TextStream&) const; - - private: - SVGPaintServerLinearGradient(const SVGGradientElement* owner); - - FloatPoint m_start; - FloatPoint m_end; - }; - -} // namespace WebCore - -#endif - -#endif // SVGPaintServerLinearGradient_h diff --git a/WebCore/svg/graphics/SVGPaintServerPattern.cpp b/WebCore/svg/graphics/SVGPaintServerPattern.cpp deleted file mode 100644 index 7fc75fb..0000000 --- a/WebCore/svg/graphics/SVGPaintServerPattern.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> - * 2008 Dirk Schulze <krit@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" - -#if ENABLE(SVG) -#include "SVGPaintServerPattern.h" - -#include "AffineTransform.h" -#include "GraphicsContext.h" -#include "Image.h" -#include "ImageBuffer.h" -#include "Pattern.h" -#include "RenderObject.h" -#include "SVGPatternElement.h" -#include "SVGRenderTreeAsText.h" - -using namespace std; - -namespace WebCore { - -SVGPaintServerPattern::SVGPaintServerPattern(const SVGPatternElement* owner) - : m_ownerElement(owner) - , m_pattern(0) -{ - ASSERT(owner); -} - -SVGPaintServerPattern::~SVGPaintServerPattern() -{ -} - -FloatRect SVGPaintServerPattern::patternBoundaries() const -{ - return m_patternBoundaries; -} - -void SVGPaintServerPattern::setPatternBoundaries(const FloatRect& rect) -{ - m_patternBoundaries = rect; -} - -ImageBuffer* SVGPaintServerPattern::tile() const -{ - return m_tile.get(); -} - -void SVGPaintServerPattern::setTile(PassOwnPtr<ImageBuffer> tile) -{ - m_tile = tile; -} - -AffineTransform SVGPaintServerPattern::patternTransform() const -{ - return m_patternTransform; -} - -void SVGPaintServerPattern::setPatternTransform(const AffineTransform& transform) -{ - m_patternTransform = transform; -} - -TextStream& SVGPaintServerPattern::externalRepresentation(TextStream& ts) const -{ - // Gradients/patterns aren't setup, until they are used for painting. Work around that fact. - m_ownerElement->buildPattern(FloatRect(0.0f, 0.0f, 1.0f, 1.0f)); - - ts << "[type=PATTERN]" - << " [bbox=" << patternBoundaries() << "]"; - if (!patternTransform().isIdentity()) - ts << " [pattern transform=" << patternTransform() << "]"; - return ts; -} - -bool SVGPaintServerPattern::setup(GraphicsContext*& context, const RenderObject* object, const RenderStyle* style, SVGPaintTargetType type, bool isPaintingText) const -{ - FloatRect targetRect = object->objectBoundingBox(); - - const SVGRenderStyle* svgStyle = style->svgStyle(); - bool isFilled = (type & ApplyToFillTargetType) && svgStyle->hasFill(); - bool isStroked = (type & ApplyToStrokeTargetType) && svgStyle->hasStroke(); - - ASSERT((isFilled && !isStroked) || (!isFilled && isStroked)); - - m_ownerElement->buildPattern(targetRect); - if (!tile()) - return false; - - context->save(); - - ASSERT(!m_pattern); - - IntRect tileRect = tile()->image()->rect(); - if (tileRect.width() > patternBoundaries().width() || tileRect.height() > patternBoundaries().height()) { - // Draw the first cell of the pattern manually to support overflow="visible" on all platforms. - int tileWidth = static_cast<int>(patternBoundaries().width() + 0.5f); - int tileHeight = static_cast<int>(patternBoundaries().height() + 0.5f); - OwnPtr<ImageBuffer> tileImage = ImageBuffer::create(IntSize(tileWidth, tileHeight)); - - GraphicsContext* tileImageContext = tileImage->context(); - - int numY = static_cast<int>(ceilf(tileRect.height() / tileHeight)) + 1; - int numX = static_cast<int>(ceilf(tileRect.width() / tileWidth)) + 1; - - tileImageContext->save(); - tileImageContext->translate(-patternBoundaries().width() * numX, -patternBoundaries().height() * numY); - for (int i = numY; i > 0; i--) { - tileImageContext->translate(0, patternBoundaries().height()); - for (int j = numX; j > 0; j--) { - tileImageContext->translate(patternBoundaries().width(), 0); - tileImageContext->drawImage(tile()->image(), style->colorSpace(), tileRect, tileRect); - } - tileImageContext->translate(-patternBoundaries().width() * numX, 0); - } - tileImageContext->restore(); - - m_pattern = Pattern::create(tileImage->image(), true, true); - } - else - m_pattern = Pattern::create(tile()->image(), true, true); - - if (isFilled) { - context->setAlpha(svgStyle->fillOpacity()); - context->setFillPattern(m_pattern); - context->setFillRule(svgStyle->fillRule()); - } - if (isStroked) { - context->setAlpha(svgStyle->strokeOpacity()); - context->setStrokePattern(m_pattern); - applyStrokeStyleToContext(context, style, object); - } - - AffineTransform matrix; - matrix.translate(patternBoundaries().x(), patternBoundaries().y()); - matrix.multiply(patternTransform()); - m_pattern->setPatternSpaceTransform(matrix); - - if (isPaintingText) { - context->setTextDrawingMode(isFilled ? cTextFill : cTextStroke); -#if PLATFORM(CG) - if (isFilled) - context->applyFillPattern(); - else - context->applyStrokePattern(); -#endif - } - - return true; -} - -void SVGPaintServerPattern::teardown(GraphicsContext*& context, const RenderObject*, SVGPaintTargetType, bool) const -{ - m_pattern = 0; - - context->restore(); -} - -} // namespace WebCore - -#endif diff --git a/WebCore/svg/graphics/SVGPaintServerPattern.h b/WebCore/svg/graphics/SVGPaintServerPattern.h deleted file mode 100644 index 3d3da49..0000000 --- a/WebCore/svg/graphics/SVGPaintServerPattern.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.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 SVGPaintServerPattern_h -#define SVGPaintServerPattern_h - -#if ENABLE(SVG) - -#include "AffineTransform.h" -#include "FloatRect.h" -#include "Pattern.h" -#include "SVGPaintServer.h" - -#include <memory> - -#include <wtf/OwnPtr.h> -#include <wtf/PassOwnPtr.h> - -namespace WebCore { - - class GraphicsContext; - class ImageBuffer; - class SVGPatternElement; - - class SVGPaintServerPattern : public SVGPaintServer { - public: - static PassRefPtr<SVGPaintServerPattern> create(const SVGPatternElement* owner) { return adoptRef(new SVGPaintServerPattern(owner)); } - - virtual ~SVGPaintServerPattern(); - - virtual SVGPaintServerType type() const { return PatternPaintServer; } - - // Pattern boundaries - void setPatternBoundaries(const FloatRect&); - FloatRect patternBoundaries() const; - - ImageBuffer* tile() const; - void setTile(PassOwnPtr<ImageBuffer>); - - AffineTransform patternTransform() const; - void setPatternTransform(const AffineTransform&); - - virtual TextStream& externalRepresentation(TextStream&) const; - - virtual bool setup(GraphicsContext*&, const RenderObject*, const RenderStyle*, SVGPaintTargetType, bool isPaintingText) const; - virtual void teardown(GraphicsContext*&, const RenderObject*, SVGPaintTargetType, bool isPaintingText) const; - - private: - SVGPaintServerPattern(const SVGPatternElement*); - - OwnPtr<ImageBuffer> m_tile; - const SVGPatternElement* m_ownerElement; - AffineTransform m_patternTransform; - FloatRect m_patternBoundaries; - - mutable RefPtr<Pattern> m_pattern; - }; - -} // namespace WebCore - -#endif - -#endif // SVGPaintServerPattern_h diff --git a/WebCore/svg/graphics/SVGPaintServerRadialGradient.cpp b/WebCore/svg/graphics/SVGPaintServerRadialGradient.cpp deleted file mode 100644 index a795ab5..0000000 --- a/WebCore/svg/graphics/SVGPaintServerRadialGradient.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.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" - -#if ENABLE(SVG) -#include "SVGPaintServerRadialGradient.h" -#include "SVGRenderTreeAsText.h" - -namespace WebCore { - -SVGPaintServerRadialGradient::SVGPaintServerRadialGradient(const SVGGradientElement* owner) - : SVGPaintServerGradient(owner) - , m_radius(0.0f) -{ -} - -SVGPaintServerRadialGradient::~SVGPaintServerRadialGradient() -{ -} - - -FloatPoint SVGPaintServerRadialGradient::gradientCenter() const -{ - return m_center; -} - -void SVGPaintServerRadialGradient::setGradientCenter(const FloatPoint& center) -{ - m_center = center; -} - -FloatPoint SVGPaintServerRadialGradient::gradientFocal() const -{ - return m_focal; -} - -void SVGPaintServerRadialGradient::setGradientFocal(const FloatPoint& focal) -{ - m_focal = focal; -} - -float SVGPaintServerRadialGradient::gradientRadius() const -{ - return m_radius; -} - -void SVGPaintServerRadialGradient::setGradientRadius(float radius) -{ - m_radius = radius; -} - -TextStream& SVGPaintServerRadialGradient::externalRepresentation(TextStream& ts) const -{ - ts << "[type=RADIAL-GRADIENT] "; - SVGPaintServerGradient::externalRepresentation(ts); - ts << " [center=" << gradientCenter() << "]" - << " [focal=" << gradientFocal() << "]" - << " [radius=" << gradientRadius() << "]"; - return ts; -} - -} // namespace WebCore - -#endif diff --git a/WebCore/svg/graphics/SVGPaintServerRadialGradient.h b/WebCore/svg/graphics/SVGPaintServerRadialGradient.h deleted file mode 100644 index 749ba08..0000000 --- a/WebCore/svg/graphics/SVGPaintServerRadialGradient.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.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 SVGPaintServerRadialGradient_h -#define SVGPaintServerRadialGradient_h - -#if ENABLE(SVG) - -#include "FloatPoint.h" -#include "SVGPaintServerGradient.h" - -namespace WebCore { - - class SVGPaintServerRadialGradient : public SVGPaintServerGradient { - public: - static PassRefPtr<SVGPaintServerRadialGradient> create(const SVGGradientElement* owner) { return adoptRef(new SVGPaintServerRadialGradient(owner)); } - virtual ~SVGPaintServerRadialGradient(); - - virtual SVGPaintServerType type() const { return RadialGradientPaintServer; } - - FloatPoint gradientCenter() const; - void setGradientCenter(const FloatPoint&); - - FloatPoint gradientFocal() const; - void setGradientFocal(const FloatPoint&); - - float gradientRadius() const; - void setGradientRadius(float); - - virtual TextStream& externalRepresentation(TextStream&) const; - - private: - SVGPaintServerRadialGradient(const SVGGradientElement* owner); - - float m_radius; - FloatPoint m_center; - FloatPoint m_focal; - }; - -} // namespace WebCore - -#endif - -#endif // SVGPaintServerRadialGradient_h diff --git a/WebCore/svg/graphics/SVGPaintServerSolid.cpp b/WebCore/svg/graphics/SVGPaintServerSolid.cpp deleted file mode 100644 index 8921bb0..0000000 --- a/WebCore/svg/graphics/SVGPaintServerSolid.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> - * Copyright (C) 2008 Dirk Schulze <krit@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" - -#if ENABLE(SVG) -#include "SVGPaintServerSolid.h" - -#include "GraphicsContext.h" -#include "RenderPath.h" -#include "SVGRenderTreeAsText.h" - -namespace WebCore { - -SVGPaintServerSolid::SVGPaintServerSolid() -{ -} - -SVGPaintServerSolid::~SVGPaintServerSolid() -{ -} - -Color SVGPaintServerSolid::color() const -{ - return m_color; -} - -void SVGPaintServerSolid::setColor(const Color& color) -{ - m_color = color; -} - -TextStream& SVGPaintServerSolid::externalRepresentation(TextStream& ts) const -{ - ts << "[type=SOLID]" - << " [color="<< color() << "]"; - return ts; -} - -bool SVGPaintServerSolid::setup(GraphicsContext*& context, const RenderObject* object, const RenderStyle* style, SVGPaintTargetType type, bool isPaintingText) const -{ - const SVGRenderStyle* svgStyle = style ? style->svgStyle() : 0; - ColorSpace colorSpace = style ? style->colorSpace() : DeviceColorSpace; - - if ((type & ApplyToFillTargetType) && (!style || svgStyle->hasFill())) { - context->setAlpha(style ? svgStyle->fillOpacity() : 1); - context->setFillColor(color().rgb(), colorSpace); - context->setFillRule(style ? svgStyle->fillRule() : RULE_NONZERO); - - if (isPaintingText) - context->setTextDrawingMode(cTextFill); - } - - if ((type & ApplyToStrokeTargetType) && (!style || svgStyle->hasStroke())) { - context->setAlpha(style ? svgStyle->strokeOpacity() : 1); - context->setStrokeColor(color().rgb(), colorSpace); - - if (style) - applyStrokeStyleToContext(context, style, object); - - if (isPaintingText) - context->setTextDrawingMode(cTextStroke); - } - - return true; -} - -} // namespace WebCore - -#endif diff --git a/WebCore/svg/graphics/SVGPaintServerSolid.h b/WebCore/svg/graphics/SVGPaintServerSolid.h deleted file mode 100644 index 680b0fe..0000000 --- a/WebCore/svg/graphics/SVGPaintServerSolid.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.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 SVGPaintServerSolid_h -#define SVGPaintServerSolid_h - -#if ENABLE(SVG) - -#include "Color.h" -#include "SVGPaintServer.h" - -namespace WebCore { - - class SVGPaintServerSolid : public SVGPaintServer { - public: - static PassRefPtr<SVGPaintServerSolid> create() { return adoptRef(new SVGPaintServerSolid); } - virtual ~SVGPaintServerSolid(); - - virtual SVGPaintServerType type() const { return SolidPaintServer; } - - Color color() const; - void setColor(const Color&); - - virtual TextStream& externalRepresentation(TextStream&) const; - - virtual bool setup(GraphicsContext*&, const RenderObject*, const RenderStyle*, SVGPaintTargetType, bool isPaintingText) const; - - private: - SVGPaintServerSolid(); - - Color m_color; - }; - -} // namespace WebCore - -#endif - -#endif // SVGPaintServerSolid_h diff --git a/WebCore/svg/graphics/SVGResource.cpp b/WebCore/svg/graphics/SVGResource.cpp deleted file mode 100644 index d1dd0e7..0000000 --- a/WebCore/svg/graphics/SVGResource.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2006, 2008 Nikolas Zimmermann <zimmermann@kde.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" - -#if ENABLE(SVG) -#include "SVGResource.h" - -#include "RenderPath.h" -#include "SVGElement.h" -#include "SVGStyledElement.h" -#include <wtf/HashSet.h> -#include <wtf/StdLibExtras.h> - -namespace WebCore { - -typedef HashSet<SVGResource*> ResourceSet; - -static ResourceSet& resourceSet() -{ - DEFINE_STATIC_LOCAL(ResourceSet, set, ()); - return set; -} - -SVGResource::SVGResource() -{ - ASSERT(!resourceSet().contains(this)); - resourceSet().add(this); -} - -SVGResource::~SVGResource() -{ - ASSERT(resourceSet().contains(this)); - resourceSet().remove(this); -} - -void SVGResource::invalidate() -{ - HashSet<SVGStyledElement*>::const_iterator it = m_clients.begin(); - const HashSet<SVGStyledElement*>::const_iterator end = m_clients.end(); - - for (; it != end; ++it) { - SVGStyledElement* cur = *it; - - if (cur->renderer()) - cur->renderer()->setNeedsLayout(true); - - cur->invalidateResourcesInAncestorChain(); - } -} - -void SVGResource::invalidateClients(HashSet<SVGStyledElement*> clients) -{ - HashSet<SVGStyledElement*>::const_iterator it = clients.begin(); - const HashSet<SVGStyledElement*>::const_iterator end = clients.end(); - - for (; it != end; ++it) { - SVGStyledElement* cur = *it; - - if (cur->renderer()) - cur->renderer()->setNeedsLayout(true); - - cur->invalidateResourcesInAncestorChain(); - } -} - -void SVGResource::removeClient(SVGStyledElement* item) -{ - ResourceSet::iterator it = resourceSet().begin(); - ResourceSet::iterator end = resourceSet().end(); - - for (; it != end; ++it) { - SVGResource* resource = *it; - if (!resource->m_clients.contains(item)) - continue; - resource->m_clients.remove(item); - } -} - -void SVGResource::addClient(SVGStyledElement* item) -{ - if (m_clients.contains(item)) - return; - - m_clients.add(item); -} - -TextStream& SVGResource::externalRepresentation(TextStream& ts) const -{ - return ts; -} - -SVGResource* getResourceById(Document* document, const AtomicString& id, const RenderObject* object) -{ - if (id.isEmpty()) - return 0; - - Element* element = document->getElementById(id); - SVGElement* svgElement = 0; - if (element && element->isSVGElement()) - svgElement = static_cast<SVGElement*>(element); - - if (svgElement && svgElement->isStyled()) - return static_cast<SVGStyledElement*>(svgElement)->canvasResource(object); - - return 0; -} - -TextStream& operator<<(TextStream& ts, const SVGResource& r) -{ - return r.externalRepresentation(ts); -} - -} - -#endif diff --git a/WebCore/svg/graphics/SVGResource.h b/WebCore/svg/graphics/SVGResource.h deleted file mode 100644 index 319add7..0000000 --- a/WebCore/svg/graphics/SVGResource.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2006, 2008 Nikolas Zimmermann <zimmermann@kde.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 SVGResource_h -#define SVGResource_h - -#if ENABLE(SVG) -#include "PlatformString.h" -#include "RenderObject.h" -#include "StringHash.h" - -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/RefCounted.h> - -namespace WebCore { - -class AtomicString; -class Document; -class SVGStyledElement; -class TextStream; - -enum SVGResourceType { - // Painting mode - ImageResourceType, - PaintServerResourceType, - - // For resource tracking we need to know how many types of resource there are - _ResourceTypeCount -}; - -// The SVGResource file represent various graphics resources: -// - Pattern resource -// - Linear/Radial gradient resource -// -// SVG creates/uses these resources. - -class SVGResource : public RefCounted<SVGResource> { -public: - virtual ~SVGResource(); - - virtual void invalidate(); - - void addClient(SVGStyledElement*); - virtual SVGResourceType resourceType() const = 0; - - bool isPaintServer() const { return resourceType() == PaintServerResourceType; } - - virtual TextStream& externalRepresentation(TextStream&) const; - - static void invalidateClients(HashSet<SVGStyledElement*>); - static void removeClient(SVGStyledElement*); - -protected: - SVGResource(); - -private: - HashSet<SVGStyledElement*> m_clients; -}; - -SVGResource* getResourceById(Document*, const AtomicString&, const RenderObject*); - -TextStream& operator<<(TextStream&, const SVGResource&); - -} - -#endif -#endif diff --git a/WebCore/svg/graphics/SVGResourceListener.h b/WebCore/svg/graphics/SVGResourceListener.h deleted file mode 100644 index e69de29..0000000 --- a/WebCore/svg/graphics/SVGResourceListener.h +++ /dev/null diff --git a/WebCore/websockets/WebSocket.idl b/WebCore/websockets/WebSocket.idl index 1707478..cc4a07b 100644 --- a/WebCore/websockets/WebSocket.idl +++ b/WebCore/websockets/WebSocket.idl @@ -57,12 +57,12 @@ module websockets { void close(); // EventTarget interface - [JSCCustom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [JSCCustom] void removeEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); + void addEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); + void removeEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); boolean dispatchEvent(in Event evt) raises(EventException); }; diff --git a/WebCore/wml/WMLAnchorElement.cpp b/WebCore/wml/WMLAnchorElement.cpp index b9b3f53..ac9c8f2 100644 --- a/WebCore/wml/WMLAnchorElement.cpp +++ b/WebCore/wml/WMLAnchorElement.cpp @@ -34,10 +34,10 @@ WMLAnchorElement::WMLAnchorElement(const QualifiedName& tagName, Document* doc) : WMLAElement(tagName, doc) , m_task(0) { - // Calling setIsLink(true), and returning a non-null value on CSSStyleSelectors' linkAttribute + // Calling setIsLink(), and returning a non-null value on CSSStyleSelectors' linkAttribute // method, makes it possible to 'appear as link' (just like <a href="..">) without the need to // actually set the href value to an empty value in the DOM tree. - setIsLink(true); + setIsLink(); } WMLAnchorElement::~WMLAnchorElement() diff --git a/WebCore/wml/WMLElement.cpp b/WebCore/wml/WMLElement.cpp index 3004aba..89fd07a 100644 --- a/WebCore/wml/WMLElement.cpp +++ b/WebCore/wml/WMLElement.cpp @@ -39,7 +39,7 @@ namespace WebCore { using namespace WMLNames; WMLElement::WMLElement(const QualifiedName& tagName, Document* document) - : StyledElement(tagName, document, CreateElementZeroRefCount) + : StyledElement(tagName, document, CreateStyledElementZeroRefCount) { } diff --git a/WebCore/wml/WMLInputElement.h b/WebCore/wml/WMLInputElement.h index eea633b..bd4e175 100644 --- a/WebCore/wml/WMLInputElement.h +++ b/WebCore/wml/WMLInputElement.h @@ -88,6 +88,9 @@ public: bool isConformedToInputMask(const String&); bool isConformedToInputMask(UChar, unsigned, bool isUserInput = true); +#if ENABLE(WCSS) + virtual InputElementData data() const { return m_data; } +#endif private: friend class WMLCardElement; diff --git a/WebCore/workers/AbstractWorker.idl b/WebCore/workers/AbstractWorker.idl index 4361dfc..f05ec17 100644 --- a/WebCore/workers/AbstractWorker.idl +++ b/WebCore/workers/AbstractWorker.idl @@ -38,12 +38,12 @@ module threads { attribute EventListener onerror; - [JSCCustom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [JSCCustom] void removeEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); + void addEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); + void removeEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); boolean dispatchEvent(in Event evt) raises(EventException); }; diff --git a/WebCore/workers/DefaultSharedWorkerRepository.cpp b/WebCore/workers/DefaultSharedWorkerRepository.cpp index 85ff768..88aea2d 100644 --- a/WebCore/workers/DefaultSharedWorkerRepository.cpp +++ b/WebCore/workers/DefaultSharedWorkerRepository.cpp @@ -274,7 +274,7 @@ SharedWorkerScriptLoader::SharedWorkerScriptLoader(PassRefPtr<SharedWorker> work void SharedWorkerScriptLoader::load(const KURL& url) { // Mark this object as active for the duration of the load. - m_scriptLoader = new WorkerScriptLoader(); + m_scriptLoader = new WorkerScriptLoader(ResourceRequestBase::TargetIsSharedWorker); m_scriptLoader->loadAsynchronously(m_worker->scriptExecutionContext(), url, DenyCrossOriginRequests, this); // Stay alive (and keep the SharedWorker and JS wrapper alive) until the load finishes. diff --git a/WebCore/workers/Worker.cpp b/WebCore/workers/Worker.cpp index 642502a..53ca9ae 100644 --- a/WebCore/workers/Worker.cpp +++ b/WebCore/workers/Worker.cpp @@ -58,7 +58,7 @@ Worker::Worker(const String& url, ScriptExecutionContext* context, ExceptionCode if (ec) return; - m_scriptLoader = new WorkerScriptLoader(); + m_scriptLoader = new WorkerScriptLoader(ResourceRequestBase::TargetIsWorker); m_scriptLoader->loadAsynchronously(scriptExecutionContext(), scriptURL, DenyCrossOriginRequests, this); setPendingActivity(this); // The worker context does not exist while loading, so we must ensure that the worker object is not collected, as well as its event listeners. #if ENABLE(INSPECTOR) diff --git a/WebCore/workers/WorkerContext.cpp b/WebCore/workers/WorkerContext.cpp index c6ee606..30c6c9b 100644 --- a/WebCore/workers/WorkerContext.cpp +++ b/WebCore/workers/WorkerContext.cpp @@ -214,7 +214,7 @@ void WorkerContext::importScripts(const Vector<String>& urls, ExceptionCode& ec) Vector<KURL>::const_iterator end = completedURLs.end(); for (Vector<KURL>::const_iterator it = completedURLs.begin(); it != end; ++it) { - WorkerScriptLoader scriptLoader; + WorkerScriptLoader scriptLoader(ResourceRequestBase::TargetIsScript); scriptLoader.loadSynchronously(scriptExecutionContext(), *it, AllowCrossOriginRequests); // If the fetching attempt failed, throw a NETWORK_ERR exception and abort all these steps. @@ -288,6 +288,11 @@ bool WorkerContext::isContextThread() const return currentThread() == thread()->threadID(); } +bool WorkerContext::isJSExecutionTerminated() const +{ + return m_script->isExecutionForbidden(); +} + EventTargetData* WorkerContext::eventTargetData() { return &m_eventTargetData; diff --git a/WebCore/workers/WorkerContext.h b/WebCore/workers/WorkerContext.h index 7026e35..91300c3 100644 --- a/WebCore/workers/WorkerContext.h +++ b/WebCore/workers/WorkerContext.h @@ -111,6 +111,7 @@ namespace WebCore { virtual void databaseExceededQuota(const String&) { } #endif virtual bool isContextThread() const; + virtual bool isJSExecutionTerminated() const; // These methods are used for GC marking. See JSWorkerContext::markChildren(MarkStack&) in diff --git a/WebCore/workers/WorkerContext.idl b/WebCore/workers/WorkerContext.idl index abb8ea8..ccc2588 100644 --- a/WebCore/workers/WorkerContext.idl +++ b/WebCore/workers/WorkerContext.idl @@ -62,12 +62,12 @@ module threads { // EventTarget interface - [JSCCustom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [JSCCustom] void removeEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); + void addEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); + void removeEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); boolean dispatchEvent(in Event evt) raises(EventException); diff --git a/WebCore/workers/WorkerScriptLoader.cpp b/WebCore/workers/WorkerScriptLoader.cpp index fa7d3c4..78f3d48 100644 --- a/WebCore/workers/WorkerScriptLoader.cpp +++ b/WebCore/workers/WorkerScriptLoader.cpp @@ -43,10 +43,11 @@ namespace WebCore { -WorkerScriptLoader::WorkerScriptLoader() +WorkerScriptLoader::WorkerScriptLoader(ResourceRequestBase::TargetType targetType) : m_client(0) , m_failed(false) , m_identifier(0) + , m_targetType(targetType) { } @@ -90,7 +91,7 @@ PassOwnPtr<ResourceRequest> WorkerScriptLoader::createResourceRequest() { OwnPtr<ResourceRequest> request(new ResourceRequest(m_url)); request->setHTTPMethod("GET"); - + request->setTargetType(m_targetType); return request.release(); } diff --git a/WebCore/workers/WorkerScriptLoader.h b/WebCore/workers/WorkerScriptLoader.h index 47623f6..a1a9afc 100644 --- a/WebCore/workers/WorkerScriptLoader.h +++ b/WebCore/workers/WorkerScriptLoader.h @@ -31,6 +31,7 @@ #if ENABLE(WORKERS) #include "KURL.h" +#include "ResourceRequest.h" #include "ResourceResponse.h" #include "ScriptString.h" #include "TextResourceDecoder.h" @@ -44,7 +45,7 @@ namespace WebCore { class WorkerScriptLoader : public ThreadableLoaderClient { public: - WorkerScriptLoader(); + explicit WorkerScriptLoader(ResourceRequestBase::TargetType); void loadSynchronously(ScriptExecutionContext*, const KURL&, CrossOriginRequestPolicy); void loadAsynchronously(ScriptExecutionContext*, const KURL&, CrossOriginRequestPolicy, WorkerScriptLoaderClient*); @@ -75,6 +76,7 @@ namespace WebCore { KURL m_url; bool m_failed; unsigned long m_identifier; + ResourceRequestBase::TargetType m_targetType; }; } // namespace WebCore diff --git a/WebCore/workers/WorkerThread.cpp b/WebCore/workers/WorkerThread.cpp index 16c5b70..52466bf 100644 --- a/WebCore/workers/WorkerThread.cpp +++ b/WebCore/workers/WorkerThread.cpp @@ -36,6 +36,7 @@ #include "PlatformString.h" #include "ScriptSourceCode.h" #include "ScriptValue.h" +#include "ThreadGlobalData.h" #include <utility> #include <wtf/Noncopyable.h> @@ -141,7 +142,10 @@ void* WorkerThread::workerThread() // The below assignment will destroy the context, which will in turn notify messaging proxy. // We cannot let any objects survive past thread exit, because no other thread will run GC or otherwise destroy them. m_workerContext = 0; - + + // Clean up WebCore::ThreadGlobalData before WTF::WTFThreadData goes away! + threadGlobalData().destroy(); + // The thread object may be already destroyed from notification now, don't try to access "this". detachThread(threadID); diff --git a/WebCore/wscript b/WebCore/wscript index 752486c..85c9885 100644 --- a/WebCore/wscript +++ b/WebCore/wscript @@ -50,9 +50,20 @@ if build_port == "wx": webcore_dirs.append('plugins/mac') webcore_dirs.append('platform/wx/wxcode/mac/carbon') webcore_dirs.append('platform/mac') + webcore_dirs.append('platform/text/mac') webcore_sources['wx-mac'] = [ - 'platform/mac/WebCoreNSStringExtras.mm', 'platform/mac/PurgeableBufferMac.cpp', + 'platform/mac/WebCoreNSStringExtras.mm', + 'platform/mac/WebCoreSystemInterface.mm', + 'platform/graphics/cg/FloatSizeCG.cpp', + 'platform/graphics/mac/ComplexTextController.cpp', + 'platform/graphics/mac/ComplexTextControllerCoreText.cpp', + 'platform/graphics/mac/ComplexTextControllerATSUI.cpp', + 'platform/graphics/mac/GlyphPageTreeNodeMac.cpp', + 'platform/graphics/mac/SimpleFontDataATSUI.mm', + 'platform/graphics/mac/SimpleFontDataCoreText.cpp', + 'platform/graphics/wx/FontPlatformDataWxMac.mm', + 'platform/text/mac/ShapeArabic.c', 'platform/wx/wxcode/mac/carbon/fontprops.mm', 'plugins/wx/PluginDataWx.cpp', 'plugins/mac/PluginPackageMac.cpp', @@ -101,8 +112,12 @@ def configure(conf): def build(bld): import Options + + import TaskGen + if sys.platform.startswith('darwin'): TaskGen.task_gen.mappings['.mm'] = TaskGen.task_gen.mappings['.cxx'] + TaskGen.task_gen.mappings['.m'] = TaskGen.task_gen.mappings['.cxx'] wk_includes = ['.', '..', 'DerivedSources', wk_root, @@ -124,6 +139,7 @@ def build(bld): if sys.platform.startswith('darwin'): features.append('cf') + bld.install_files(os.path.join(output_dir, 'WebCore'), 'platform/mac/WebCoreSystemInterface.h') else: exclude_patterns.append('*CF.cpp') @@ -201,11 +217,13 @@ def build(bld): if building_on_win32: excludes.append('SharedTimerWx.cpp') - excludes.append('GlyphMapWx.cpp') excludes.append('RenderThemeWin.cpp') excludes.append('KeyEventWin.cpp') + if building_on_win32 or sys.platform.startswith('darwin'): + excludes.append('GlyphMapWx.cpp') excludes.append('AuthenticationCF.cpp') excludes.append('LoaderRunLoopCF.cpp') + excludes.append('ResourceErrorCF.cpp') webcore.find_sources_in_dirs(full_dirs, excludes = excludes, exts=['.c', '.cpp']) diff --git a/WebCore/xml/XMLHttpRequest.cpp b/WebCore/xml/XMLHttpRequest.cpp index c95351f..5cde24d 100644 --- a/WebCore/xml/XMLHttpRequest.cpp +++ b/WebCore/xml/XMLHttpRequest.cpp @@ -496,6 +496,10 @@ void XMLHttpRequest::send(DOMFormData* body, ExceptionCode& ec) if (m_method != "GET" && m_method != "HEAD" && m_url.protocolInHTTPFamily()) { m_requestEntityBody = FormData::createMultiPart(*body, document()); + // We need to ask the client to provide the generated file names if needed. When FormData fills the element + // for the file, it could set a flag to use the generated file name, i.e. a package file on Mac. + m_requestEntityBody->generateFiles(document()); + String contentType = getRequestHeader("Content-Type"); if (contentType.isEmpty()) { contentType = "multipart/form-data; boundary="; @@ -525,7 +529,7 @@ void XMLHttpRequest::createRequest(ExceptionCode& ec) // We also remember whether upload events should be allowed for this request in case the upload listeners are // added after the request is started. - m_uploadEventsAllowed = !isSimpleCrossOriginAccessRequest(m_method, m_requestHeaders); + m_uploadEventsAllowed = m_sameOriginRequest || !isSimpleCrossOriginAccessRequest(m_method, m_requestHeaders); ResourceRequest request(m_url); request.setHTTPMethod(m_method); diff --git a/WebCore/xml/XMLHttpRequest.idl b/WebCore/xml/XMLHttpRequest.idl index 5a86fe5..0ca2205 100644 --- a/WebCore/xml/XMLHttpRequest.idl +++ b/WebCore/xml/XMLHttpRequest.idl @@ -91,12 +91,12 @@ module xml { [Custom] void overrideMimeType(in DOMString override); // EventTarget interface - [JSCCustom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [JSCCustom] void removeEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); + void addEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); + void removeEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); boolean dispatchEvent(in Event evt) raises(EventException); }; diff --git a/WebCore/xml/XMLHttpRequestUpload.idl b/WebCore/xml/XMLHttpRequestUpload.idl index a712a37..5a18567 100644 --- a/WebCore/xml/XMLHttpRequestUpload.idl +++ b/WebCore/xml/XMLHttpRequestUpload.idl @@ -42,12 +42,12 @@ module xml { attribute EventListener onprogress; // EventTarget interface - [JSCCustom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [JSCCustom] void removeEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); + void addEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); + void removeEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); boolean dispatchEvent(in Event evt) raises(EventException); }; diff --git a/WebCore/xml/XSLTProcessorLibxslt.cpp b/WebCore/xml/XSLTProcessorLibxslt.cpp index a0ed450..9c3fafd 100644 --- a/WebCore/xml/XSLTProcessorLibxslt.cpp +++ b/WebCore/xml/XSLTProcessorLibxslt.cpp @@ -315,7 +315,7 @@ bool XSLTProcessor::transformToString(Node* sourceNode, String& mimeType, String if (shouldFreeSourceDoc) xmlFreeDoc(sourceDoc); - if (success = saveResultToString(resultDoc, sheet, resultString)) { + if ((success = saveResultToString(resultDoc, sheet, resultString))) { mimeType = resultMIMEType(resultDoc, sheet); resultEncoding = (char*)resultDoc->encoding; } diff --git a/WebKit/ChangeLog b/WebKit/ChangeLog index 3ba6146..978e85e 100644 --- a/WebKit/ChangeLog +++ b/WebKit/ChangeLog @@ -1,3 +1,119 @@ +2010-05-05 Dan Bernstein <mitz@apple.com> + + Reviewed by Simon Fraser. + + <rdar://problem/7932072> Iframes in composited layers don’t repaint correctly (affects Yahoo! Mail with Flash Player 10.1) + https://bugs.webkit.org/show_bug.cgi?id=38427 + + * WebKit.xcodeproj/project.pbxproj: Renamed WebClipView.m to WebClipView.mm and changed it to + Objective-C++. + +2010-05-03 Darin Adler <darin@apple.com> + + * English.lproj/Localizable.strings: Regenerated. + * StringsNotToBeLocalized.txt: Updated for recent changes. + +2010-05-03 Jens Alfke <snej@chromium.org> + + Reviewed by Darin Fisher. + + [chromium] Add "willSendSubmitEvent" hook to WebFrameClient and FrameLoaderClient + https://bugs.webkit.org/show_bug.cgi?id=38397 + + No tests (functionality is exposed only through native WebKit API.) + + * efl/WebCoreSupport/FrameLoaderClientEfl.h: + (WebCore::FrameLoaderClientEfl::dispatchWillSendSubmitEvent): + +2010-04-22 Leandro Pereira <leandro@profusion.mobi> + + Reviewed by Gustavo Noronha Silva. + + Implement findThemePath to locate the correct theme file instead of + relying on a hardcoded location. + http://webkit.org/b/37996 + + * efl/EWebLauncher/main.c: + (findThemePath): Fix to locate the correct theme files. + (main): Use findThemePath() instead of a hardcoded one. + +2010-04-22 Leandro Pereira <leandro@profusion.mobi> + + Reviewed by Gustavo Noronha Silva. + + Update efl/ewebkit.pc.in to match the variable substitution syntax + of CMake. + http://webkit.org/b/37999 + + * efl/ewebkit.pc.in: Updated. + +2010-04-22 Leandro Pereira <leandro@profusion.mobi> + + Reviewed by Gustavo Noronha Silva. + + Update EWebKit (EFL port) to match recent API changes. + http://webkit.org/b/37997 + + * efl/ewk/ewk_frame.cpp: + (ewk_frame_zoom_set): Change to use WebCore::ZoomMode. + (ewk_frame_zoom_text_only_set): Change to use WebCore::ZoomMode. + (_ewk_frame_handle_key_scrolling): s/WebCore::VK_/VK_/g + (ewk_frame_plugin_create): Disable temporarily PluginView-related + code until a proper plugin implementation is made. + * efl/ewk/ewk_view.cpp: Fix typo in _parent_sc declaration. + (ewk_view_selection_get): Fix a reference to WebCore::CString to + WTF::CString. + +2010-04-22 Leandro Pereira <leandro@profusion.mobi> + + Reviewed by Gustavo Noronha Silva. + + Update EFL port files to match recent API changes. + http://webkit.org/b/37876 + + * efl/WebCoreSupport/ChromeClientEfl.cpp: + (kit): Added. + (WebCore::ChromeClientEfl::ChromeClientEfl): Coding style fix. + (WebCore::ChromeClientEfl::runBeforeUnloadConfirmPanel): Coding + style fix. + (WebCore::ChromeClientEfl::mouseDidMoveOverElement): Coding style fix. + (WebCore::ChromeClientEfl::runOpenPanel): Implemented. + (WebCore::ChromeClientEfl::cancelGeolocationPermissionRequestForFrame): Stubbed. + (WebCore::ChromeClientEfl::cancelGeolocationPermissionForFrame): Stubbed. + (WebCore::ChromeClientEfl::invalidateContents): Stubbed. + (WebCore::ChromeClientEfl::invalidateWindow): Stubbed. + (WebCore::ChromeClientEfl::invalidateContentsAndWindow): Implemented. + (WebCore::ChromeClientEfl::invalidateContentsForSlowScroll): Implemented. + (WebCore::ChromeClientEfl::scroll): Updated. + (WebCore::ChromeClientEfl::iconForFiles): Stubbed. + (WebCore::ChromeClientEfl::chooseIconForFiles): Stubbed. + * efl/WebCoreSupport/ChromeClientEfl.h: Add new method prototypes. + * efl/WebCoreSupport/FrameLoaderClientEfl.cpp: + (WebCore::FrameLoaderClientEfl::committedLoad): Call setEncoding() + from FrameLoader::writer. + (WebCore::FrameLoaderClientEfl::finishedLoading): Ditto. + (WebCore::FrameLoaderClientEfl::dispatchDidFailLoading): Ditto. + (WebCore::FrameLoaderClientEfl::setMainDocumentError): Ditto. + +2010-04-21 Gustavo Sverzut Barbieri <barbieri@profusion.mobi> + + Reviewed by Nikolas Zimmermann. + + Add missing EFL WebKit/efl theme files. + http://webkit.org/b/37854 + + * efl/DefaultTheme/default.edc: Added. + * efl/DefaultTheme/widget/button/button.edc: Added. + * efl/DefaultTheme/widget/check/check.edc: Added. + * efl/DefaultTheme/widget/combo/combo.edc: Added. + * efl/DefaultTheme/widget/entry/entry.edc: Added. + * efl/DefaultTheme/widget/file/file.edc: Added. + * efl/DefaultTheme/widget/radio/radio.edc: Added. + * efl/DefaultTheme/widget/scrollbar/scrollbar.edc: Added. + * efl/DefaultTheme/widget/search/cancel/search_cancel.edc: Added. + * efl/DefaultTheme/widget/search/decoration/search_decoration.edc: Added. + * efl/DefaultTheme/widget/search/field/search_field.edc: Added. + 2010-04-21 Gustavo Sverzut Barbieri <barbieri@profusion.mobi> Reviewed by Adam Roben. diff --git a/WebKit/English.lproj/Localizable.strings b/WebKit/English.lproj/Localizable.strings Binary files differindex 8301e28..615dc9a 100644 --- a/WebKit/English.lproj/Localizable.strings +++ b/WebKit/English.lproj/Localizable.strings diff --git a/WebKit/StringsNotToBeLocalized.txt b/WebKit/StringsNotToBeLocalized.txt index 74c90ca..9fbaa7f 100644 --- a/WebKit/StringsNotToBeLocalized.txt +++ b/WebKit/StringsNotToBeLocalized.txt @@ -26,7 +26,6 @@ "%@, %@" "%@-%d" "%@/%s" -"%@/.tmp%d" "%@/Library/Preferences/%@" "%@:%u" "%@://%@" @@ -52,7 +51,6 @@ "-createPluginMIMETypesPreferences" "-khtml-text-decorations-in-effect" "." -"._" ".download" ".html" ".jpg" @@ -263,6 +261,7 @@ "NP_GetEntryPoints" "NP_Initialize" "NP_Shutdown" +"NSAlert" "NSAllowContinuousSpellChecking" "NSAllowsBaseWritingDirectionKeyBindings" "NSApplicationIcon" @@ -305,6 +304,7 @@ "Software\\Synaptics\\SynTPEnh\\UltraNavPS2" "Software\\Synaptics\\SynTPEnh\\UltraNavUSB" "StatusDisplay" +"TSUpdateCheck" "TimeRemainingDisplay" "Times" "ToggleBold" @@ -485,6 +485,7 @@ "WebURLProtectionSpace" "WebURLResponse" "WebURLsWithTitlesPboardType" +"WebUserContentURLPattern" "WebView" "WebViewDidBeginEditingNotification" "WebViewDidChangeNotification" @@ -498,6 +499,7 @@ "Windows 98" "Windows 98; Win 9x 4.90" "Windows NT %d.%d" +"WmvPlugin" "XSL" "XXXXXX-" "\"@?" @@ -689,7 +691,6 @@ "name: %@\npath: %@\nmimeTypes:\n%@\npluginDescription:%@" "nameFieldLabel" "net.hmdt-web.Shiira" -"nullplugin" "oleacc.dll" "opacity" "org.xlife.NewsFire" @@ -729,7 +730,6 @@ "text/x-vcalendar" "text/x-vcard" "text/x-vcf" -"tiff" "transform" "treatsFilePackagesAsDirectories" "txt" diff --git a/WebKit/WebKit.xcodeproj/project.pbxproj b/WebKit/WebKit.xcodeproj/project.pbxproj index e6bbab5..d80e3aa 100644 --- a/WebKit/WebKit.xcodeproj/project.pbxproj +++ b/WebKit/WebKit.xcodeproj/project.pbxproj @@ -269,7 +269,7 @@ 939810E30824BF01008DF038 /* WebImageRendererFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CE1F8A302A5C6F30ECA2ACD /* WebImageRendererFactory.m */; }; 939810E40824BF01008DF038 /* WebJavaScriptTextInputPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = 9345D4EB0365C5B2008635CE /* WebJavaScriptTextInputPanel.m */; }; 939810E80824BF01008DF038 /* WebViewFactory.mm in Sources */ = {isa = PBXBuildFile; fileRef = F5F7174D02885C5B018635CA /* WebViewFactory.mm */; }; - 939810EB0824BF01008DF038 /* WebClipView.m in Sources */ = {isa = PBXBuildFile; fileRef = 933D659A03413FF2008635CE /* WebClipView.m */; }; + 939810EB0824BF01008DF038 /* WebClipView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 933D659A03413FF2008635CE /* WebClipView.mm */; }; 939810ED0824BF01008DF038 /* WebDataSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 39446071020F50ED0ECA1767 /* WebDataSource.mm */; }; 939810EF0824BF01008DF038 /* WebDefaultContextMenuDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5152FADE033FC50400CA2ACD /* WebDefaultContextMenuDelegate.mm */; }; 939810F00824BF01008DF038 /* WebDefaultPolicyDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5152FAE0033FC50400CA2ACD /* WebDefaultPolicyDelegate.m */; }; @@ -576,7 +576,7 @@ 93185DB506679F42005D5E7E /* WebHTMLViewInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebHTMLViewInternal.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; 9325FBDC07D829AE00159862 /* IDNScriptWhiteList.txt */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = text; path = IDNScriptWhiteList.txt; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; 933D659903413FF2008635CE /* WebClipView.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebClipView.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; - 933D659A03413FF2008635CE /* WebClipView.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebClipView.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; + 933D659A03413FF2008635CE /* WebClipView.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; indentWidth = 4; path = WebClipView.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; 9345D17C0365BF35008635CE /* English */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = wrapper.nib; name = English; path = Panels/English.lproj/WebAuthenticationPanel.nib; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; 9345D4EA0365C5B2008635CE /* WebJavaScriptTextInputPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebJavaScriptTextInputPanel.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; 9345D4EB0365C5B2008635CE /* WebJavaScriptTextInputPanel.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebJavaScriptTextInputPanel.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; @@ -1101,7 +1101,7 @@ 8373435A0624EE0D00F3B289 /* WebArchive.h */, 8373435B0624EE0D00F3B289 /* WebArchive.mm */, 933D659903413FF2008635CE /* WebClipView.h */, - 933D659A03413FF2008635CE /* WebClipView.m */, + 933D659A03413FF2008635CE /* WebClipView.mm */, 39446070020F50ED0ECA1767 /* WebDataSource.h */, 39446071020F50ED0ECA1767 /* WebDataSource.mm */, 658A40950A14853B005E6987 /* WebDataSourceInternal.h */, @@ -1790,7 +1790,7 @@ 939810D30824BF01008DF038 /* WebBasePluginPackage.mm in Sources */, 5241ADF60B1BC48A004012BD /* WebCache.mm in Sources */, 14D825300AF955090004F057 /* WebChromeClient.mm in Sources */, - 939810EB0824BF01008DF038 /* WebClipView.m in Sources */, + 939810EB0824BF01008DF038 /* WebClipView.mm in Sources */, 065AD5A40B0C32C7005A2B1D /* WebContextMenuClient.mm in Sources */, 939810BF0824BF01008DF038 /* WebCoreStatistics.mm in Sources */, 511F3FD50CECC88F00852565 /* WebDatabaseManager.mm in Sources */, diff --git a/WebKit/chromium/ChangeLog b/WebKit/chromium/ChangeLog index ed43fff..68129b0 100644 --- a/WebKit/chromium/ChangeLog +++ b/WebKit/chromium/ChangeLog @@ -1,3 +1,730 @@ +2010-05-06 Kent Tamura <tkent@chromium.org> + + Reviewed by Dimitri Glazkov. + + [DRT/Chromium] Add support for resources on Mac + https://bugs.webkit.org/show_bug.cgi?id=38637 + + * DEPS: Check out tools/data_pack. + +2010-05-06 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Chromium Dev Tools: Large toolbar icons flash when dev + tools is opened in docked mode. + + https://bugs.webkit.org/show_bug.cgi?id=38631 + + * src/js/DevTools.js: + (devtools.domContentLoaded): + +2010-05-06 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + drop support for sessionStorage in sandbox iframes + https://bugs.webkit.org/show_bug.cgi?id=38151 + + Update client of sessionStorage to handle exceptions. + + * src/StorageAreaProxy.cpp: + (WebCore::StorageAreaProxy::storageEvent): + +2010-05-05 Darin Fisher <darin@chromium.org> + + Reviewed by Dimitri Glazkov. + + [chromium] clear out deprecated methods that are no longer used + https://bugs.webkit.org/show_bug.cgi?id=38610 + + * public/WebFormElement.h: + * public/WebInputElement.h: + * public/WebKitClient.h: + * public/WebView.h: + * public/WebViewClient.h: + (WebKit::WebViewClient::createPopupMenu): + * src/ChromeClientImpl.cpp: + (WebKit::ChromeClientImpl::popupOpened): + * src/WebFormElement.cpp: + * src/WebInputElement.cpp: + (WebKit::WebInputElement::setSelectionRange): + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::hideSuggestionsPopup): + * src/WebViewImpl.h: + +2010-05-05 Hans Wennborg <hans@chromium.org> + + Reviewed by Jeremy Orlow. + + [chromium] Add quota parameter to WebStorageNamespace::createSessionStorageNamespace + https://bugs.webkit.org/show_bug.cgi?id=38589 + + * public/WebStorageNamespace.h: + (WebKit::WebStorageNamespace::createSessionStorageNamespace): + * src/WebStorageNamespaceImpl.cpp: + (WebKit::WebStorageNamespace::createSessionStorageNamespace): + +2010-05-05 Stuart Morgan <stuartmorgan@chromium.org> + + Reviewed by Darin Fisher. + + Update the plugin container's setFocus implementation to pass the new + boolean argument to the next layer. + + https://bugs.webkit.org/show_bug.cgi?id=37961 + + * src/WebPluginContainerImpl.cpp: + (WebKit::WebPluginContainerImpl::setFocus): + * src/WebPluginContainerImpl.h: + +2010-05-04 Vangelis Kokkevis <vangelis@chromium.org> + + Reviewed by Darin Fisher. + + Provide an API for querying whether a WebWidget is using gpu accelerated compositing. + Also changed: isAcceleratedCompositing to: isAcceleratedCompositingActive. + https://bugs.webkit.org/show_bug.cgi?id=38220 + + * public/WebWidget.h: + * src/WebPopupMenuImpl.h: + (WebKit::WebPopupMenuImpl::isAcceleratedCompositingActive): + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::WebViewImpl): + (WebKit::WebViewImpl::paint): + (WebKit::WebViewImpl::isAcceleratedCompositingActive): + (WebKit::WebViewImpl::setRootGraphicsLayer): + (WebKit::WebViewImpl::setIsAcceleratedCompositingActive): + (WebKit::WebViewImpl::updateRootLayerContents): + * src/WebViewImpl.h: + +2010-04-29 John Gregg <johnnyg@google.com> + + Reviewed by Dmitry Titov. + + notifications should have dir and replaceId attributes + https://bugs.webkit.org/show_bug.cgi?id=38336 + + * public/WebNotification.h: + * src/WebNotification.cpp: + (WebKit::WebNotification::dir): + (WebKit::WebNotification::replaceId): + +2010-05-04 Jay Civelli <jcivelli@chromium.org> + + Reviewed by David Levin. + + [chromium] Make the select popup not close on right/middle clicks. + https://bugs.webkit.org/show_bug.cgi?id=38473 + + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::mouseDown): + +2010-05-03 Abhishek Arya <inferno@chromium.org> + + Reviewed by Adam Barth. + + Add support for controlling clipboard access from javascript. + Clipboard access from javascript is disabled by default. + https://bugs.webkit.org/show_bug.cgi?id=27751 + + * public/WebSettings.h: + * src/WebSettingsImpl.cpp: + (WebKit::WebSettingsImpl::setJavaScriptCanAccessClipboard): + * src/WebSettingsImpl.h: + +2010-05-03 Jens Alfke <snej@chromium.org> + + Reviewed by Darin Fisher. + + [chromium] Add "willSendSubmitEvent" hook to WebFrameClient and FrameLoaderClient + https://bugs.webkit.org/show_bug.cgi?id=38397 + + No tests (functionality is exposed only through native WebKit API.) + + * public/WebFrameClient.h: + (WebKit::WebFrameClient::willSendSubmitEvent): New empty method + * src/FrameLoaderClientImpl.cpp: + (WebKit::FrameLoaderClientImpl::dispatchWillSendSubmitEvent): Delegate to client + * src/FrameLoaderClientImpl.h: + +2010-05-02 Michael Nordman <michaeln@google.com> + + Reviewed by Dmitry Titov. + + Define two new ResourceRequestBase TargetTypes for worker and shared worker + main resources. Use the new target types where appropiate. Add logic to marshal + the target type specified by requests initiated on a background worker thread. + + https://bugs.webkit.org/show_bug.cgi?id=38295 + + * src/SharedWorkerRepository.cpp: use TargetIsSharedWorker + (WebCore::SharedWorkerScriptLoader::SharedWorkerScriptLoader): + +2010-05-02 Rafael Weinstein <rafaelw@chromium.org> + + Reviewed by Darin Fisher. + + Include WebWindowFeatures in call to WebViewClient::createView. + https://bugs.webkit.org/show_bug.cgi?id=38301 + + * public/WebViewClient.h: + (WebKit::WebViewClient::createView): + * public/WebWindowFeatures.h: + * src/ChromeClientImpl.cpp: + (WebKit::ChromeClientImpl::createWindow): + +2010-05-01 Evan Stade <estade@chromium.org> + + Reviewed by David Levin + + [chromium] Skia needs to fade DragImages + https://bugs.webkit.org/show_bug.cgi?id=38008 + + * tests/DragImageTest.cpp: + (DragImageTest.CreateDragImage): test that the drag image is a deep copy + +2010-04-30 Jian Li <jianli@chromium.org> + + Reviewed by Darin Fisher. + + [chromium] Add WebFileSystem interface and hook up with all FileSystem methods. + https://bugs.webkit.org/show_bug.cgi?id=38228 + + * WebKit.gyp: + * public/WebFileSystem.h: Added. + * public/WebKitClient.h: + (WebKit::WebKitClient::fileSystem): + * src/ChromiumBridge.cpp: + (WebCore::ChromiumBridge::fileExists): + (WebCore::ChromiumBridge::deleteFile): + (WebCore::ChromiumBridge::deleteEmptyDirectory): + (WebCore::ChromiumBridge::getFileSize): + (WebCore::ChromiumBridge::getFileModificationTime): + (WebCore::ChromiumBridge::directoryName): + (WebCore::ChromiumBridge::pathByAppendingComponent): + (WebCore::ChromiumBridge::makeAllDirectories): + (WebCore::ChromiumBridge::getAbsolutePath): + (WebCore::ChromiumBridge::isDirectory): + (WebCore::ChromiumBridge::filePathToURL): + (WebCore::ChromiumBridge::openFile): + (WebCore::ChromiumBridge::closeFile): + (WebCore::ChromiumBridge::seekFile): + (WebCore::ChromiumBridge::truncateFile): + (WebCore::ChromiumBridge::readFromFile): + (WebCore::ChromiumBridge::writeToFile): + +2010-04-29 Jeremy Orlow <jorlow@chromium.org> + + Reviewed by Darin Fisher. + + Change StorageEvent.uri to StorageEvent.url to match the spec + https://bugs.webkit.org/show_bug.cgi?id=38331 + + Get rid of a stale FIXME and combine 2 lines that needn't be split. + + * src/StorageEventDispatcherImpl.cpp: + (WebCore::StorageEventDispatcherImpl::dispatchStorageEvent): + +2010-04-29 Anton Muhin <antonm@chromium.org> + + Reviewed by Darin Fisher. + + [Chromium] Consider implementing addOriginAccessWhitelistEntry method + http://trac.webkit.org/changeset/57537 introduced a new method + to manage whitelisting of origins. + Expose this method in Chromium's bridge. + https://bugs.webkit.org/show_bug.cgi?id=37578 + + * public/WebSecurityPolicy.h: Start renaming (keep old function names) and add new removeOriginAccessWhitelistEntry method + * src/WebSecurityPolicy.cpp: Start renaming (keep old function names) and add new removeOriginAccessWhitelistEntry method + +2010-04-29 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r58498. + http://trac.webkit.org/changeset/58498 + https://bugs.webkit.org/show_bug.cgi?id=38332 + + "Broke a bunch of tests on Chromium canaries" (Requested by + dglazkov on #webkit). + + * public/WebViewClient.h: + (WebKit::WebViewClient::createView): + * public/WebWindowFeatures.h: + * src/ChromeClientImpl.cpp: + (WebKit::ChromeClientImpl::createWindow): + +2010-04-29 Adam Langley <agl@chromium.org> + + Unreviewed, DEPS roll. + + WebKit's r58517 needs OTS's r30 which was rolled into Chromium in + r45932. + + * DEPS: + Use Chromium r45932. + +2010-04-29 Rafael Weinstein <rafaelw@chromium.org> + + Reviewed by Darin Fisher. + + Include WindowFeatures in call to WebViewClient::createView. + + https://bugs.webkit.org/show_bug.cgi?id=38301 + + * public/WebViewClient.h: + (WebKit::WebViewClient::createView): + * public/WebWindowFeatures.h: + * src/ChromeClientImpl.cpp: + (WebKit::ChromeClientImpl::createWindow): + +2010-04-29 Garret Kelly <gdk@chromium.org> + + Reviewed by Darin Fisher. + + Expose the RuntimeFeature for touch events through the + WebRuntimeFeatures mechanism. + https://bugs.webkit.org/show_bug.cgi?id=37486 + + * public/WebRuntimeFeatures.h: + * src/WebRuntimeFeatures.cpp: + (WebKit::WebRuntimeFeatures::enableTouch): + (WebKit::WebRuntimeFeatures::isTouchEnabled): + +2010-04-29 Zhenyao Mo <zmo@google.com> + + Reviewed by Dimitri Glazkov. + + Remove the unnecessary texImage2D function with Image as input in GraphicsContext3D + https://bugs.webkit.org/show_bug.cgi?id=38235 + + * src/GraphicsContext3D.cpp: Remove tex*image implementation with Image input. + +2010-04-28 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Yury Semikhatsky. + + Web Inspector: Allow editing script resources when resource tracking is enabled. + + http://bugs.webkit.org/show_bug.cgi?id=38269 + + * src/js/DebuggerAgent.js: + * src/js/InspectorControllerImpl.js: + (.devtools.InspectorBackendImpl.prototype.setBreakpoint): + (.devtools.InspectorBackendImpl.prototype.editScriptSource): + +2010-04-28 Darin Fisher <darin@chromium.org> + + Reviewed by David Levin. + + [Chromium] callOnMainThread should equate to MessageLoop::PostTask + https://bugs.webkit.org/show_bug.cgi?id=38276 + + * public/WebKitClient.h: + (WebKit::WebKitClient::callOnMainThread): + * src/ChromiumThreading.cpp: + (WTF::ChromiumThreading::callOnMainThread): + +2010-04-27 John Abd-El-Malek <jam@chromium.org> + + Reviewed by Darin Fisher. + + Make WebThemeEngine::paint take a const ref of ExtraParams + https://bugs.webkit.org/show_bug.cgi?id=38242 + + * public/WebThemeEngine.h: + (WebKit::WebThemeEngine::paint): + +2010-04-28 Andrey Kosyakov <caseq@chromium.org> + + Reviewed by Pavel Feldman. + + Fixed passing breakpoints to V8. + https://bugs.webkit.org/show_bug.cgi?id=38266 + + * src/js/InspectorControllerImpl.js: + (.devtools.InspectorBackendImpl.prototype.setBreakpoint): + +2010-04-28 Yury Semikhatsky <yurys@chromium.org> + + Reviewed by Pavel Feldman. + + Support pause on exceptions in v8 implementation of ScriptDebugServer. + + https://bugs.webkit.org/show_bug.cgi?id=38205 + + * src/js/DebuggerScript.js: + (debuggerScriptConstructor.DebuggerScript.getScripts): + (debuggerScriptConstructor.DebuggerScript.pauseOnExceptionsState): + (debuggerScriptConstructor.DebuggerScript.setPauseOnExceptionsState): + (debuggerScriptConstructor.DebuggerScript._v8ToWebkitLineNumber): + (debuggerScriptConstructor): + +2010-04-27 Jens Alfke <snej@chromium.org> + + Reviewed by Eric Seidel. + + [chromium] Fix bug that prevents autosave of forms without action attribute + https://bugs.webkit.org/show_bug.cgi?id=38014 + Change is in the Chromium WebKit API so it can't be tested with a JS-based layout test. + It needs a native unit test, which would go in the Chromium repo, not WebKit. + + * src/WebPasswordFormData.cpp: + (WebKit::WebPasswordFormData::WebPasswordFormData): Set correct URL if action is NULL + +2010-04-27 Michael Nordman <michaeln@google.com> + + Reviewed by Dmitry Titov. + + [Chromium] Add two things to the webkit API to support appcaches in workers. + 1) WebURLRequest TargetTypes for worker and shared worker main resources. + 2) Factory method on class WebCommonWorkerClient to + createApplicationCacheHost() for the associated worker. + + https://bugs.webkit.org/show_bug.cgi?id=38147 + + * public/WebCommonWorkerClient.h: add the factory method + * public/WebURLRequest.h: add the TargetTypes + * src/WebWorkerBase.cpp: call the embedder's factory when needed + (WebKit::WebWorkerBase::didCreateDataSource) + (WebKit::WebWorkerBase::createApplicationCacheHost) + * src/WebWorkerBase.h: ditto + * src/WebWorkerClientImpl.h: add a stub impl of the factory method + (WebKit::WebWorkerClientImpl::createApplicationCacheHost): + +2010-04-27 Kent Tamura <tkent@chromium.org> + + Reviewed by Shinichiro Hamaji. + + [DRT/Chromium] Enable Windows project generation + https://bugs.webkit.org/show_bug.cgi?id=38103 + + - Avoid platform.system(), which causes a crash with python.exe in + depot_tools. Use sys.platform instead. + - Process DumpRenderTree.gyp on all platforms. + + * gyp_webkit: + +2010-04-27 Jay Civelli <jcivelli@chromium.org> + + Reviewed by Darin Fisher. + + Makes clicking a select element close its associated popup if + it is open. + https://bugs.webkit.org/show_bug.cgi?id=38105 + + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::mouseDown): + +2010-04-27 Jay Civelli <jcivelli@chromium.org> + + Reviewed by Darin Fisher. + + [chromium] Merged the WebView public method to close suggestion popups + into a single method to close all popups (select and suggestions). + That ensures select popups are closed when the browser window is moved + or resized. + https://bugs.webkit.org/show_bug.cgi?id=37837 + + * public/WebView.h: + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::hidePopups): + (WebKit::WebViewImpl::hideSuggestionsPopup): + * src/WebViewImpl.h: + +2010-04-27 John Abd-El-Malek <jam@chromium.org> + + Reviewed by Darin Adler. + + Remove unnecessary header now that Chrome is updated + https://bugs.webkit.org/show_bug.cgi?id=38211 + + * public/win/WebThemeEngine.h: Removed. + +2010-04-27 Jens Alfke <snej@chromium.org> + + Reviewed by Darin Fisher. + + [Chromium] Add some notifications and an accessor to WebKit API + https://bugs.webkit.org/show_bug.cgi?id=37625 + + * public/WebFrameClient.h: + (WebKit::WebFrameClient::didFirstLayout): + (WebKit::WebFrameClient::didFirstVisuallyNonEmptyLayout): + * public/WebNode.h: + * src/FrameLoaderClientImpl.cpp: + (WebKit::FrameLoaderClientImpl::dispatchDidFirstLayout): + (WebKit::FrameLoaderClientImpl::dispatchDidFirstVisuallyNonEmptyLayout): + * src/WebElement.cpp: + * src/WebNode.cpp: + (WebKit::WebNode::hasNonEmptyBoundingBox): + +2010-04-27 Darin Fisher <darin@chromium.org> + + Reviewed by Dimitri Glazkov. + + [Chromium] Remove deprecated form of didChangeLocationWithinPage + https://bugs.webkit.org/show_bug.cgi?id=38178 + + * public/WebFrameClient.h: + * src/FrameLoaderClientImpl.cpp: + (WebKit::FrameLoaderClientImpl::dispatchDidNavigateWithinPage): + +2010-04-27 Evan Martin <evan@chromium.org> + + Reviewed by David Levin. + + [chromium] bold bengali text not rendered properly on Linux + Roll forward Chrome DEPS so we get new Skia API. + + * DEPS: update Chrome to r45696. + +2010-04-27 Andrey Kosyakov <caseq@chromium.org> + + Reviewed by Pavel Feldman. + + Restore breakpoints associated with script's URL once + script is parsed. + https://bugs.webkit.org/show_bug.cgi?id=38132 + + * src/js/DebuggerAgent.js: + (devtools.DebuggerAgent.prototype.initUI): + (devtools.DebuggerAgent.prototype.addBreakpoint): + (devtools.DebuggerAgent.prototype.addScriptInfo_): + (devtools.DebuggerAgent.prototype.restoreBreakpoints_): + (devtools.BreakpointInfo): + (devtools.BreakpointInfo.prototype.enabled): + (devtools.BreakpointInfo.prototype.condition): + +2010-04-27 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Yury Semikhatsky. + + Chrome Dev Tools: Further beautify themes. + + https://bugs.webkit.org/show_bug.cgi?id=38187 + + * src/js/DevTools.js: + (WebInspector.setToolbarColors): + * src/js/devTools.css: + (body.platform-windows #toolbar, body.platform-windows.inactive #toolbar): + +2010-04-26 John Abd-El-Malek <jam@chromium.org> + + Reviewed by Darin Fisher. + + [chromium] Prepare to making WebThemeEngine cross-platform + https://bugs.webkit.org/show_bug.cgi?id=38077 + + * WebKit.gyp: + * public/WebThemeEngine.h: Added. + * public/win/WebThemeEngine.h: + +2010-04-26 Darin Fisher <darin@chromium.org> + + Reviewed by Adam Barth. + + [Chromium] Crash after calling window.print() on a window object that has been closed. + https://bugs.webkit.org/show_bug.cgi?id=38148 + + It is unfortunately not possible to write a layout test for this as the + crash occurs in an API that is only called by Chrome while showing a + print dialog. + + * src/WebViewImpl.cpp: + (WebKit::WebView::willEnterModalLoop): + (WebKit::WebView::didExitModalLoop): + +2010-04-25 Sam Weinig <sam@webkit.org> + + Reviewed by Maciej Stachowiak. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38097 + Disentangle initializing the main thread from initializing threading + + * src/WebKit.cpp: + (WebKit::initialize): Add call to initializeMainThread. + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::WebViewImpl): Ditto. + +2010-04-26 Roman Gershman <romange@google.com> + + Reviewed by Adam Barth. + + [Chromium] Font size in suggestions popup menu should be correlated with the font size of its text field. + + https://bugs.webkit.org/show_bug.cgi?id=37977 + + * src/SuggestionsPopupMenuClient.cpp: + (WebKit::SuggestionsPopupMenuClient::initialize): + +2010-04-26 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Yury Semikhatsky. + + Chromium Dev Tools: brush up images. + + https://bugs.webkit.org/show_bug.cgi?id=38124 + + * WebKit.gypi: + * src/js/DevTools.js: + (WebInspector.setToolbarColors): + * src/js/Images/segmentChromium.png: + * src/js/Images/segmentChromium2.png: Removed. + * src/js/Images/segmentHoverChromium2.png: Removed. + * src/js/Images/segmentSelectedChromium2.png: Removed. + * src/js/Images/statusbarBackgroundChromium.png: + * src/js/Images/statusbarBackgroundChromium2.png: Removed. + * src/js/Images/statusbarBottomBackgroundChromium.png: + * src/js/Images/statusbarButtonsChromium.png: + * src/js/Images/statusbarMenuButtonChromium.png: + * src/js/Images/statusbarMenuButtonChromium2.png: Removed. + * src/js/devTools.css: + (.section > .header): + (.console-group-messages .section > .header): + (#resources-filter): + (.crumbs .crumb): + (.crumbs .crumb.end): + (.crumbs .crumb.selected): + (.crumbs .crumb.selected:hover): + (.crumbs .crumb.selected.end, .crumbs .crumb.selected.end:hover): + (.crumbs .crumb:hover): + (.crumbs .crumb.dimmed:hover): + (.crumbs .crumb.end:hover): + (body.drawer-visible #main-status-bar): + (.status-bar): + (button.status-bar-item): + (select.status-bar-item:active): + (#drawer): + (select.status-bar-item): + +2010-04-23 Zhenyao Mo <zmo@google.com> + + Reviewed by Darin Fisher. + + Add isGLES2Compliant to GraphicsContext3D: make the method const. + https://bugs.webkit.org/show_bug.cgi?id=37872 + + * src/GraphicsContext3D.cpp: Make isGLES2Compliant() const. + (WebCore::GraphicsContext3DInternal::isGLES2Compliant): + (WebCore::GraphicsContext3D::isGLES2Compliant): + +2010-04-23 Rafael Weinstein <rafaelw@grafaelw.sfo.corp.google.com> + + Reviewed by Darin Fisher. + + This patch adds a WebWindowFeatures binding struct for the + chromium client in anticipation of a follow-on patch which will + pass it to WebViewClient::createWindow. + + https://bugs.webkit.org/show_bug.cgi?id=38013 + + * public/WebViewClient.h: + (WebKit::WebViewClient::createView): + * public/WebWindowFeatures.h: Added. + (WebKit::WebWindowFeatures::WebWindowFeatures): + * src/ChromeClientImpl.cpp: + (WebKit::ChromeClientImpl::createWindow): + +2010-04-22 Zhenyao Mo <zmo@google.com> + + Reviewed by Darin Fisher. + + Add isGLES2Compliant to GraphicsContext3D + https://bugs.webkit.org/show_bug.cgi?id=37872 + + * public/WebGraphicsContext3D.h: Add isGLES2Compliant(). + * src/GraphicsContext3D.cpp: Ditto. + * src/WebGraphicsContext3DDefaultImpl.cpp: Ditto. + (WebKit::WebGraphicsContext3DDefaultImpl::isGLES2Compliant): + * src/WebGraphicsContext3DDefaultImpl.h: Ditto. + +2010-04-22 Dave Moore <davemoore@chromium.org> + + Reviewed by Dimitri Glazkov. + + Added notification when the favicons for a page are changed + from a script. + The Document object will notify the frame loader, which will + notify the client. Implementations of FrameLoaderClient will + have to add one method; dispatchDidChangeIcons(). + + https://bugs.webkit.org/show_bug.cgi?id=33812 + + * public/WebFrameClient.h: + (WebKit::WebFrameClient::didChangeIcons): + * src/FrameLoaderClientImpl.cpp: + (WebKit::FrameLoaderClientImpl::dispatchDidChangeIcons): + * src/FrameLoaderClientImpl.h: + +2010-04-22 Zhenyao Mo <zmo@google.com> + + Reviewed by Dimitri Glazkov. + + Emulate GL_IMPLEMENTATION_COLOR_READ_FORMAT/TYPE for glGet + https://bugs.webkit.org/show_bug.cgi?id=37281 + + * src/WebGraphicsContext3DDefaultImpl.cpp: + (WebKit::WebGraphicsContext3DDefaultImpl::getIntegerv): Emulate two enums. + +2010-04-22 Adam Barth <abarth@webkit.org> + + Unreviewed, rolling out r58069. + http://trac.webkit.org/changeset/58069 + https://bugs.webkit.org/show_bug.cgi?id=27751 + + Broke compile on Windows. + + * public/WebSettings.h: + * src/WebSettingsImpl.cpp: + * src/WebSettingsImpl.h: + +2010-04-22 Tony Chang <tony@chromium.org> + + Reviewed by Shinichiro Hamaji. + + [chromium] roll chromium deps to pick up some windows build fixes + https://bugs.webkit.org/show_bug.cgi?id=37972 + + * DEPS: + +2010-04-22 Abhishek Arya <inferno@chromium.org> + + Reviewed by Adam Barth. + + Add support for controlling clipboard access from javascript. + Clipboard access from javascript is disabled by default. + https://bugs.webkit.org/show_bug.cgi?id=27751 + + * public/WebSettings.h: + * src/WebSettingsImpl.cpp: + (WebKit::WebSettingsImpl::setJavaScriptCanAccessClipboard): + * src/WebSettingsImpl.h: + +2010-04-21 Tony Chang <tony@chromium.org> + + Reviewed by Shinichiro Hamaji. + + [chromium] gyp_webkit should be executable + https://bugs.webkit.org/show_bug.cgi?id=37971 + + * gyp_webkit: Added property svn:executable. + +2010-04-21 Jay Civelli <jcivelli@chromium.org> + + Reviewed by Darin Fisher. + + [Chromium] Don't notify the WebView that a popup was + opened when the popup is handled externally, as the popup + is in that case transparent to the WebView. + The notification was causing an ASSERT on Mac (where + the popup is handled externally) as there would be no + notification that the popup was closed. + https://bugs.webkit.org/show_bug.cgi?id=37825 + + * src/ChromeClientImpl.cpp: + (WebKit::ChromeClientImpl::popupOpened): + 2010-04-21 Sheriff Bot <webkit.review.bot@gmail.com> Unreviewed, rolling out r58028. diff --git a/WebKit/chromium/DEPS b/WebKit/chromium/DEPS index c6d71ab..07401d7 100644 --- a/WebKit/chromium/DEPS +++ b/WebKit/chromium/DEPS @@ -32,7 +32,7 @@ vars = { 'chromium_svn': 'http://src.chromium.org/svn/trunk/src', - 'chromium_rev': '44453', + 'chromium_rev': '45932', 'pthreads-win32_rev': '26716', } @@ -44,6 +44,8 @@ deps = { # build tools 'build': Var('chromium_svn')+'/build@'+Var('chromium_rev'), + 'tools/data_pack': + Var('chromium_svn')+'/tools/data_pack@'+Var('chromium_rev'), 'tools/gyp': From('chromium_deps', 'src/tools/gyp'), @@ -173,6 +175,8 @@ deps_os = { Var('chromium_svn')+'/third_party/harfbuzz@'+Var('chromium_rev'), 'tools/xdisplaycheck': Var('chromium_svn')+'/tools/xdisplaycheck@'+Var('chromium_rev'), + 'tools/data_pack': + Var('chromium_svn')+'/tools/data_pack@'+Var('chromium_rev'), 'third_party/yasm/source/patched-yasm': From('chromium_deps', 'src/third_party/yasm/source/patched-yasm'), }, diff --git a/WebKit/chromium/WebKit.gyp b/WebKit/chromium/WebKit.gyp index 53581bc..b3a926e 100644 --- a/WebKit/chromium/WebKit.gyp +++ b/WebKit/chromium/WebKit.gyp @@ -121,6 +121,7 @@ 'public/WebFileChooserCompletion.h', 'public/WebFileChooserParams.h', 'public/WebFileInfo.h', + 'public/WebFileSystem.h', 'public/WebFindOptions.h', 'public/WebFrame.h', 'public/WebFrameClient.h', @@ -201,6 +202,7 @@ 'public/WebTextAffinity.h', 'public/WebTextCaseSensitivity.h', 'public/WebTextDirection.h', + 'public/WebThemeEngine.h', 'public/WebURL.h', 'public/WebURLError.h', 'public/WebURLLoader.h', diff --git a/WebKit/chromium/WebKit.gypi b/WebKit/chromium/WebKit.gypi index 37faa99..a9df3f5 100644 --- a/WebKit/chromium/WebKit.gypi +++ b/WebKit/chromium/WebKit.gypi @@ -48,19 +48,14 @@ ], 'devtools_image_files': [ 'src/js/Images/segmentChromium.png', - 'src/js/Images/segmentChromium2.png', 'src/js/Images/segmentHoverChromium.png', - 'src/js/Images/segmentHoverChromium2.png', 'src/js/Images/segmentHoverEndChromium.png', 'src/js/Images/segmentSelectedChromium.png', - 'src/js/Images/segmentSelectedChromium2.png', 'src/js/Images/segmentSelectedEndChromium.png', 'src/js/Images/statusbarBackgroundChromium.png', - 'src/js/Images/statusbarBackgroundChromium2.png', 'src/js/Images/statusbarBottomBackgroundChromium.png', 'src/js/Images/statusbarButtonsChromium.png', 'src/js/Images/statusbarMenuButtonChromium.png', - 'src/js/Images/statusbarMenuButtonChromium2.png', 'src/js/Images/statusbarMenuButtonSelectedChromium.png', ], }, diff --git a/WebKit/chromium/gyp_webkit b/WebKit/chromium/gyp_webkit index db1aa7a..812ed27 100644..100755 --- a/WebKit/chromium/gyp_webkit +++ b/WebKit/chromium/gyp_webkit @@ -1,4 +1,4 @@ -# +#!/usr/bin/env python # Copyright (C) 2009 Google Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,7 +32,6 @@ import glob import os -import platform import shlex import sys @@ -78,7 +77,7 @@ if __name__ == '__main__': args.extend(['-I' + i for i in additional_include_files(args)]) # On linux, we want gyp to output a makefile (default is scons). - if platform.system() == 'Linux': + if sys.platform == 'linux2': args.extend(['-fmake']) # Other command args: @@ -91,12 +90,9 @@ if __name__ == '__main__': # gyp hack: otherwise gyp assumes its in chromium's src/ dir. '--depth=./', - # gyp file to execute. - 'WebKit.gyp']) - - # Generate DRT build files on the platforms that support it. - if platform.system() in ('Darwin', 'Linux'): - args.append('../../WebKitTools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp') + # gyp files to execute. + 'WebKit.gyp', + '../../WebKitTools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp']) print 'Updating webkit projects from gyp files...' sys.stdout.flush() diff --git a/WebKit/chromium/public/WebCommonWorkerClient.h b/WebKit/chromium/public/WebCommonWorkerClient.h index f4df16d..13603cb 100644 --- a/WebKit/chromium/public/WebCommonWorkerClient.h +++ b/WebKit/chromium/public/WebCommonWorkerClient.h @@ -33,6 +33,8 @@ namespace WebKit { +class WebApplicationCacheHost; +class WebApplicationCacheHostClient; class WebNotificationPresenter; class WebString; class WebWorker; @@ -74,6 +76,9 @@ public: // they are created via the WebSharedWorkerRepository. virtual WebWorker* createWorker(WebWorkerClient* client) = 0; + // Called on the main webkit thread in the worker process during initialization. + virtual WebApplicationCacheHost* createApplicationCacheHost(WebApplicationCacheHostClient*) = 0; + protected: ~WebCommonWorkerClient() { } }; diff --git a/WebKit/chromium/public/WebFileSystem.h b/WebKit/chromium/public/WebFileSystem.h new file mode 100644 index 0000000..fc6e6dd --- /dev/null +++ b/WebKit/chromium/public/WebFileSystem.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2010 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 WebFileSystem_h +#define WebFileSystem_h + +#include "WebCommon.h" +#include "WebString.h" +#include "WebURL.h" + +namespace WebKit { + +class WebFileSystem { +public: +#ifdef WIN32 + typedef HANDLE FileHandle; +#else + typedef int FileHandle; +#endif + + virtual bool fileExists(const WebString& path) { return false; } + virtual bool deleteFile(const WebString& path) { return false; } + virtual bool deleteEmptyDirectory(const WebString& path) { return false; } + virtual bool getFileSize(const WebString& path, long long& result) { return false; } + virtual bool getFileModificationTime(const WebString& path, double& result) { return false; } + virtual WebString directoryName(const WebString& path) { return WebString(); } + virtual WebString pathByAppendingComponent(const WebString& path, const WebString& component) { return WebString(); } + virtual bool makeAllDirectories(const WebString& path) { return false; } + virtual WebString getAbsolutePath(const WebString& path) { return WebString(); } + virtual bool isDirectory(const WebString& path) { return false; } + virtual WebURL filePathToURL(const WebString& path) { return WebURL(); } + virtual FileHandle openFile(const WebString& path, int mode) { return FileHandle(); } + // Should set the FileHandle to a invalid value if the file is closed successfully. + virtual void closeFile(FileHandle&) { } + virtual long long seekFile(FileHandle, long long offset, int origin) { return 0; } + virtual bool truncateFile(FileHandle, long long offset) { return false; } + virtual int readFromFile(FileHandle, char* data, int length) { return 0; } + virtual int writeToFile(FileHandle, const char* data, int length) { return 0; } + +protected: + ~WebFileSystem() {} +}; + +} // namespace WebKit + +#endif diff --git a/WebKit/chromium/public/WebFormElement.h b/WebKit/chromium/public/WebFormElement.h index 8cb4e47..6a0b24e 100644 --- a/WebKit/chromium/public/WebFormElement.h +++ b/WebKit/chromium/public/WebFormElement.h @@ -66,8 +66,6 @@ namespace WebKit { WEBKIT_API void submit(); // FIXME: Deprecate and replace with WebVector<WebElement>. WEBKIT_API void getNamedElements(const WebString&, WebVector<WebNode>&); - // DEPRECATED: Replaced by getFormControlElements. - WEBKIT_API void getInputElements(WebVector<WebInputElement>&) const; WEBKIT_API void getFormControlElements(WebVector<WebFormControlElement>&) const; #if WEBKIT_IMPLEMENTATION diff --git a/WebKit/chromium/public/WebFrameClient.h b/WebKit/chromium/public/WebFrameClient.h index 315cf87..2b7ee0d 100644 --- a/WebKit/chromium/public/WebFrameClient.h +++ b/WebKit/chromium/public/WebFrameClient.h @@ -138,6 +138,10 @@ public: // Navigational notifications ------------------------------------------ + // A form submission has been requested, but the page's submit event handler + // hasn't yet had a chance to run (and possibly alter/interrupt the submit.) + virtual void willSendSubmitEvent(WebFrame*, const WebFormElement&) { } + // A form submission is about to occur. virtual void willSubmitForm(WebFrame*, const WebFormElement&) { } @@ -192,6 +196,9 @@ public: // The page title is available. virtual void didReceiveTitle(WebFrame*, const WebString& title) { } + // The icons for the page have changed. + virtual void didChangeIcons(WebFrame*) { } + // The frame's document finished loading. virtual void didFinishDocumentLoad(WebFrame*) { } @@ -211,8 +218,6 @@ public: // The navigation resulted in scrolling the page to a named anchor instead // of downloading a new document. - // FIXME: The isNewNavigation parameter is DEPRECATED. - virtual void didChangeLocationWithinPage(WebFrame*, bool isNewNavigation) { } virtual void didChangeLocationWithinPage(WebFrame*) { } // Called upon update to scroll position, document state, and other @@ -292,6 +297,12 @@ public: // Geometry notifications ---------------------------------------------- + // The frame's document finished the initial layout of a page. + virtual void didFirstLayout(WebFrame*) { } + + // The frame's document finished the initial non-empty layout of a page. + virtual void didFirstVisuallyNonEmptyLayout(WebFrame*) { } + // The size of the content area changed. virtual void didChangeContentsSize(WebFrame*, const WebSize&) { } diff --git a/WebKit/chromium/public/WebGraphicsContext3D.h b/WebKit/chromium/public/WebGraphicsContext3D.h index 3418ef9..dc4f534 100644 --- a/WebKit/chromium/public/WebGraphicsContext3D.h +++ b/WebKit/chromium/public/WebGraphicsContext3D.h @@ -99,6 +99,9 @@ public: // Resizes the region into which this WebGraphicsContext3D is drawing. virtual void reshape(int width, int height) = 0; + // Query whether it is built on top of compliant GLES2 implementation. + virtual bool isGLES2Compliant() = 0; + // Helper for software compositing path. Reads back the frame buffer into // the memory region pointed to by "pixels" with size "bufferSize". It is // expected that the storage for "pixels" covers (4 * width * height) bytes. diff --git a/WebKit/chromium/public/WebInputElement.h b/WebKit/chromium/public/WebInputElement.h index 0fec63f..a7a71b0 100644 --- a/WebKit/chromium/public/WebInputElement.h +++ b/WebKit/chromium/public/WebInputElement.h @@ -90,12 +90,6 @@ namespace WebKit { WEBKIT_API void setAutofilled(bool); WEBKIT_API void dispatchFormControlChangeEvent(); WEBKIT_API void setSelectionRange(int, int); - // DEPRECATED: The following two methods have been moved to WebFormControlElement. - WEBKIT_API WebString name() const; - // Returns the name that should be used for the specified |element| when - // storing AutoFill data. This is either the field name or its id, an - // empty string if it has no name and no id. - WEBKIT_API WebString nameForAutofill() const; #if WEBKIT_IMPLEMENTATION WebInputElement(const WTF::PassRefPtr<WebCore::HTMLInputElement>&); diff --git a/WebKit/chromium/public/WebKitClient.h b/WebKit/chromium/public/WebKitClient.h index 38b131d..97d25a8 100644 --- a/WebKit/chromium/public/WebKitClient.h +++ b/WebKit/chromium/public/WebKitClient.h @@ -49,6 +49,7 @@ class WebApplicationCacheHost; class WebApplicationCacheHostClient; class WebClipboard; class WebCookieJar; +class WebFileSystem; class WebGLES2Context; class WebGraphicsContext3D; class WebIndexedDatabase; @@ -70,6 +71,9 @@ public: // Must return non-null. virtual WebMimeRegistry* mimeRegistry() { return 0; } + // Must return non-null. + virtual WebFileSystem* fileSystem() { return 0; } + // May return null if sandbox support is not necessary virtual WebSandboxSupport* sandboxSupport() { return 0; } @@ -85,10 +89,6 @@ public: // Return a LocalStorage namespace that corresponds to the following path. virtual WebStorageNamespace* createLocalStorageNamespace(const WebString& path, unsigned quota) { return 0; } - // Return a new SessionStorage namespace. - // THIS IS DEPRECATED. WebViewClient::getSessionStorageNamespace() is the new way to access this. - virtual WebStorageNamespace* createSessionStorageNamespace() { return 0; } - // Called when storage events fire. virtual void dispatchStorageEvent(const WebString& key, const WebString& oldValue, const WebString& newValue, const WebString& origin, @@ -263,7 +263,7 @@ public: virtual void stopSharedTimer() { } // Callable from a background WebKit thread. - virtual void callOnMainThread(void (*func)()) { } + virtual void callOnMainThread(void (*func)(void*), void* context) { } // WebGL -------------------------------------------------------------- diff --git a/WebKit/chromium/public/WebNode.h b/WebKit/chromium/public/WebNode.h index 5a87da0..792ede5 100644 --- a/WebKit/chromium/public/WebNode.h +++ b/WebKit/chromium/public/WebNode.h @@ -101,6 +101,11 @@ public: WEBKIT_API void simulateClick(); WEBKIT_API WebNodeList getElementsByTagName(const WebString&) const; + // Returns true if the node has a non-empty bounding box in layout. + // This does not 100% guarantee the user can see it, but is pretty close. + // Note: This method only works properly after layout has occurred. + WEBKIT_API bool hasNonEmptyBoundingBox() const; + // Deprecated. Use to() instead. template<typename T> T toElement() { diff --git a/WebKit/chromium/public/WebNotification.h b/WebKit/chromium/public/WebNotification.h index 9d64e2a..ab747e3 100644 --- a/WebKit/chromium/public/WebNotification.h +++ b/WebKit/chromium/public/WebNotification.h @@ -75,6 +75,9 @@ public: WEBKIT_API WebString title() const; WEBKIT_API WebString body() const; + WEBKIT_API WebString dir() const; + WEBKIT_API WebString replaceId() const; + // Called to indicate the notification has been displayed. WEBKIT_API void dispatchDisplayEvent(); diff --git a/WebKit/chromium/public/WebRuntimeFeatures.h b/WebKit/chromium/public/WebRuntimeFeatures.h index 40a5952..03ff681 100644 --- a/WebKit/chromium/public/WebRuntimeFeatures.h +++ b/WebKit/chromium/public/WebRuntimeFeatures.h @@ -74,6 +74,9 @@ public: WEBKIT_API static void enablePushState(bool); WEBKIT_API static bool isPushStateEnabled(bool); + WEBKIT_API static void enableTouch(bool); + WEBKIT_API static bool isTouchEnabled(); + private: WebRuntimeFeatures(); }; diff --git a/WebKit/chromium/public/WebSecurityPolicy.h b/WebKit/chromium/public/WebSecurityPolicy.h index 815f471..ac0031d 100644 --- a/WebKit/chromium/public/WebSecurityPolicy.h +++ b/WebKit/chromium/public/WebSecurityPolicy.h @@ -55,9 +55,18 @@ public: WEBKIT_API static void registerURLSchemeAsSecure(const WebString&); // Support for whitelisting access to origins beyond the same-origin policy. + WEBKIT_API static void addOriginAccessWhitelistEntry( + const WebURL& sourceOrigin, const WebString& destinationProtocol, + const WebString& destinationHost, bool allowDestinationSubdomains); + WEBKIT_API static void removeOriginAccessWhitelistEntry( + const WebURL& sourceOrigin, const WebString& destinationProtocol, + const WebString& destinationHost, bool allowDestinationSubdomains); + WEBKIT_API static void resetOriginAccessWhitelists(); + // DEPRECATED: Phase on of renaming to addOriginAccessWhitelistEntry. WEBKIT_API static void whiteListAccessFromOrigin( const WebURL& sourceOrigin, const WebString& destinationProtocol, const WebString& destinationHost, bool allowDestinationSubdomains); + // DEPRECATED: Phase on of renaming to resetOriginAccessWhitelists.. WEBKIT_API static void resetOriginAccessWhiteLists(); // Returns whether the url should be allowed to see the referrer diff --git a/WebKit/chromium/public/WebSettings.h b/WebKit/chromium/public/WebSettings.h index 6339ded..356d9fa 100644 --- a/WebKit/chromium/public/WebSettings.h +++ b/WebKit/chromium/public/WebSettings.h @@ -72,6 +72,7 @@ public: virtual void setAuthorAndUserStylesEnabled(bool) = 0; virtual void setUsesPageCache(bool) = 0; virtual void setDownloadableBinaryFontsEnabled(bool) = 0; + virtual void setJavaScriptCanAccessClipboard(bool) = 0; virtual void setXSSAuditorEnabled(bool) = 0; virtual void setLocalStorageEnabled(bool) = 0; virtual void setEditableLinkBehaviorNeverLive() = 0; diff --git a/WebKit/chromium/public/WebStorageNamespace.h b/WebKit/chromium/public/WebStorageNamespace.h index da92a77..4b648d4 100644 --- a/WebKit/chromium/public/WebStorageNamespace.h +++ b/WebKit/chromium/public/WebStorageNamespace.h @@ -48,7 +48,11 @@ public: // If path is empty, data will not persist. You should call delete on the returned // object when you're finished. WEBKIT_API static WebStorageNamespace* createLocalStorageNamespace(const WebString& backingDirectoryPath, unsigned quota); - WEBKIT_API static WebStorageNamespace* createSessionStorageNamespace(); + WEBKIT_API static WebStorageNamespace* createSessionStorageNamespace(unsigned quota); + WEBKIT_API static WebStorageNamespace* createSessionStorageNamespace() + { + return createSessionStorageNamespace(noQuota); + } static const unsigned noQuota = UINT_MAX; diff --git a/WebKit/chromium/public/win/WebThemeEngine.h b/WebKit/chromium/public/WebThemeEngine.h index b563608..1fccb0e 100644 --- a/WebKit/chromium/public/win/WebThemeEngine.h +++ b/WebKit/chromium/public/WebThemeEngine.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -31,21 +31,23 @@ #ifndef WebThemeEngine_h #define WebThemeEngine_h -#include "../WebCanvas.h" -#include "../WebColor.h" +#include "WebCanvas.h" +#include "WebColor.h" namespace WebKit { struct WebRect; +struct WebSize; +class WebThemeEngine { +public: +#ifdef WIN32 // The part and state parameters correspond to values defined by the // Windows Theme API (see // http://msdn.microsoft.com/en-us/library/bb773187(VS.85).aspx ). // The classicState parameter corresponds to the uState // parameter of the Windows DrawFrameControl() function. // See the definitions in <vsstyle.h> and <winuser.h>. -class WebThemeEngine { -public: virtual void paintButton( WebCanvas*, int part, int state, int classicState, const WebRect&) = 0; @@ -73,6 +75,45 @@ public: virtual void paintTrackbar( WebCanvas*, int part, int state, int classicState, const WebRect&) = 0; +#endif + + // WebThemeEngine was originally used only on Windows, hence its platform- + // specific parameters. This is new cross-platform theming API, and we'll + // switch the code to using these APIs on all platforms instead. + enum Part { + PartScrollbarDownArrow, + PartScrollbarLeftArrow, + PartScrollbarRightArrow, + PartScrollbarUpArrow, + PartScrollbarHorizontalThumb, + PartScrollbarVerticalThumb, + PartScrollbarHoriztonalTrack, + PartScrollbarVerticalTrack, + }; + + enum State { + StateDisabled, + StateHot, + StateHover, + StateNormal, + StatePressed, + }; + + struct ScrollbarTrackExtraParams { + int alignX; + int alignY; + }; + + union ExtraParams { + ScrollbarTrackExtraParams scrollbarTrack; + }; + + // Gets the size of the given theme component. For variable sized items + // like vertical scrollbar tracks, the width will be the required width of + // the track while the height will be the minimum height. + virtual void getSize(Part, WebSize*) {} + virtual void paint( + WebCanvas*, Part, State, const WebRect&, const ExtraParams&) {} }; } // namespace WebKit diff --git a/WebKit/chromium/public/WebURLRequest.h b/WebKit/chromium/public/WebURLRequest.h index 41443b4..408aad7 100644 --- a/WebKit/chromium/public/WebURLRequest.h +++ b/WebKit/chromium/public/WebURLRequest.h @@ -67,7 +67,9 @@ public: TargetIsFontResource = 5, TargetIsImage = 6, TargetIsObject = 7, - TargetIsMedia = 8 + TargetIsMedia = 8, + TargetIsWorker = 9, + TargetIsSharedWorker = 10 }; ~WebURLRequest() { reset(); } diff --git a/WebKit/chromium/public/WebView.h b/WebKit/chromium/public/WebView.h index 5a043f2..9ed98c6 100644 --- a/WebKit/chromium/public/WebView.h +++ b/WebKit/chromium/public/WebView.h @@ -225,13 +225,6 @@ public: // AutoFill / Autocomplete --------------------------------------------- - // DEPRECATED: WebView::applyAutocompleteSuggestions is the new way to - // access this. - virtual void applyAutofillSuggestions( - const WebNode&, - const WebVector<WebString>& suggestions, - int defaultSuggestionIndex) = 0; - // Notifies the WebView that AutoFill suggestions are available for a node. virtual void applyAutoFillSuggestions( const WebNode&, @@ -246,11 +239,8 @@ public: const WebVector<WebString>& suggestions, int defaultSuggestionIndex) = 0; - // DEPRECATED: WebView::hideSuggestionsPopup is the new way to access this. - virtual void hideAutofillPopup() = 0; - - // Hides the suggestions popup if any are showing. - virtual void hideSuggestionsPopup() = 0; + // Hides any popup (suggestions, selects...) that might be showing. + virtual void hidePopups() = 0; // Context menu -------------------------------------------------------- diff --git a/WebKit/chromium/public/WebViewClient.h b/WebKit/chromium/public/WebViewClient.h index c2a96dc..98e0485 100644 --- a/WebKit/chromium/public/WebViewClient.h +++ b/WebKit/chromium/public/WebViewClient.h @@ -60,6 +60,7 @@ struct WebConsoleMessage; struct WebContextMenuData; struct WebPoint; struct WebPopupMenuInfo; +struct WebWindowFeatures; // Since a WebView is a WebWidget, a WebViewClient is a WebWidgetClient. // Virtual inheritance allows an implementation of WebWidgetClient to be @@ -71,16 +72,13 @@ public: // Create a new related WebView. This method must clone its session storage // so any subsequent calls to createSessionStorageNamespace conform to the // WebStorage specification. - virtual WebView* createView(WebFrame* creator) { return 0; } + virtual WebView* createView(WebFrame* creator, + const WebWindowFeatures& features) { return 0; } // Create a new WebPopupMenu. In the second form, the client is // responsible for rendering the contents of the popup menu. virtual WebWidget* createPopupMenu(WebPopupType) { return 0; } virtual WebWidget* createPopupMenu(const WebPopupMenuInfo&) { return 0; } - // Deprecated methods. - virtual WebWidget* createPopupMenu() { return 0; } - virtual WebWidget* createPopupMenu(bool activatable) { return 0; } - // Create a session storage namespace object associated with this WebView. virtual WebStorageNamespace* createSessionStorageNamespace() { return 0; } diff --git a/WebKit/chromium/public/WebWidget.h b/WebKit/chromium/public/WebWidget.h index 9dfeefc..b1feee9 100644 --- a/WebKit/chromium/public/WebWidget.h +++ b/WebKit/chromium/public/WebWidget.h @@ -90,6 +90,10 @@ public: // Changes the text direction of the selected input node. virtual void setTextDirection(WebTextDirection) = 0; + // Returns true if the WebWidget uses GPU accelerated compositing + // to render its contents. + virtual bool isAcceleratedCompositingActive() const = 0; + protected: ~WebWidget() { } }; diff --git a/WebKit/chromium/public/WebWindowFeatures.h b/WebKit/chromium/public/WebWindowFeatures.h new file mode 100644 index 0000000..2e7278a --- /dev/null +++ b/WebKit/chromium/public/WebWindowFeatures.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2010 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 WebWindowFeatures_h +#define WebWindowFeatures_h + +#include "WebCommon.h" +#include "WebString.h" +#include "WebVector.h" + +#if WEBKIT_IMPLEMENTATION +#include "WindowFeatures.h" +#endif + +namespace WebKit { + +struct WebWindowFeatures { + float x; + bool xSet; + float y; + bool ySet; + float width; + bool widthSet; + float height; + bool heightSet; + + bool menuBarVisible; + bool statusBarVisible; + bool toolBarVisible; + bool locationBarVisible; + bool scrollbarsVisible; + bool resizable; + + bool fullscreen; + bool dialog; + WebVector<WebString> additionalFeatures; + + WebWindowFeatures() + : xSet(false) + , ySet(false) + , widthSet(false) + , heightSet(false) + , menuBarVisible(true) + , statusBarVisible(true) + , toolBarVisible(true) + , locationBarVisible(true) + , scrollbarsVisible(true) + , resizable(true) + , fullscreen(false) + , dialog(false) + { + } + + +#if WEBKIT_IMPLEMENTATION + WebWindowFeatures(const WebCore::WindowFeatures& f) + : xSet(f.xSet) + , ySet(f.ySet) + , widthSet(f.widthSet) + , heightSet(f.heightSet) + , menuBarVisible(f.menuBarVisible) + , statusBarVisible(f.statusBarVisible) + , toolBarVisible(f.toolBarVisible) + , locationBarVisible(f.locationBarVisible) + , scrollbarsVisible(f.scrollbarsVisible) + , resizable(f.resizable) + , fullscreen(f.fullscreen) + , dialog(f.dialog) + , additionalFeatures(f.additionalFeatures) + { + } +#endif +}; + +} // namespace WebKit + +#endif diff --git a/WebKit/chromium/src/ChromeClientImpl.cpp b/WebKit/chromium/src/ChromeClientImpl.cpp index c7acab5..74f0bd8 100644 --- a/WebKit/chromium/src/ChromeClientImpl.cpp +++ b/WebKit/chromium/src/ChromeClientImpl.cpp @@ -74,6 +74,7 @@ #include "WebURLRequest.h" #include "WebViewClient.h" #include "WebViewImpl.h" +#include "WebWindowFeatures.h" #include "WindowFeatures.h" #include "WrappedResourceRequest.h" @@ -233,7 +234,7 @@ Page* ChromeClientImpl::createWindow( return 0; WebViewImpl* newView = static_cast<WebViewImpl*>( - m_webView->client()->createView(WebFrameImpl::fromFrame(frame))); + m_webView->client()->createView(WebFrameImpl::fromFrame(frame), features)); if (!newView) return 0; @@ -622,15 +623,11 @@ void ChromeClientImpl::popupOpened(PopupContainer* popupContainer, } else { webwidget = m_webView->client()->createPopupMenu( convertPopupType(popupContainer->popupType())); - // Try the deprecated methods. - // FIXME: Remove the deprecated methods once the Chromium side use the - // new method. - if (!webwidget) - webwidget = m_webView->client()->createPopupMenu(); - if (!webwidget) - webwidget = m_webView->client()->createPopupMenu(false); + // We only notify when the WebView has to handle the popup, as when + // the popup is handled externally, the fact that a popup is showing is + // transparent to the WebView. + m_webView->popupOpened(popupContainer); } - m_webView->popupOpened(popupContainer); static_cast<WebPopupMenuImpl*>(webwidget)->Init(popupContainer, bounds); } diff --git a/WebKit/chromium/src/ChromiumBridge.cpp b/WebKit/chromium/src/ChromiumBridge.cpp index cffd166..a0e8d3b 100644 --- a/WebKit/chromium/src/ChromiumBridge.cpp +++ b/WebKit/chromium/src/ChromiumBridge.cpp @@ -40,6 +40,7 @@ #include "WebCookieJar.h" #include "WebCursorInfo.h" #include "WebData.h" +#include "WebFileSystem.h" #include "WebFrameClient.h" #include "WebFrameImpl.h" #include "WebImage.h" @@ -270,63 +271,118 @@ void ChromiumBridge::prefetchDNS(const String& hostname) bool ChromiumBridge::fileExists(const String& path) { + if (webKitClient()->fileSystem()) + return webKitClient()->fileSystem()->fileExists(path); return webKitClient()->fileExists(path); } bool ChromiumBridge::deleteFile(const String& path) { + if (webKitClient()->fileSystem()) + return webKitClient()->fileSystem()->deleteFile(path); return webKitClient()->deleteFile(path); } bool ChromiumBridge::deleteEmptyDirectory(const String& path) { + if (webKitClient()->fileSystem()) + return webKitClient()->fileSystem()->deleteEmptyDirectory(path); return webKitClient()->deleteEmptyDirectory(path); } bool ChromiumBridge::getFileSize(const String& path, long long& result) { + if (webKitClient()->fileSystem()) + return webKitClient()->fileSystem()->getFileSize(path, result); return webKitClient()->getFileSize(path, result); } bool ChromiumBridge::getFileModificationTime(const String& path, time_t& result) { double modificationTime; - if (!webKitClient()->getFileModificationTime(path, modificationTime)) - return false; + if (webKitClient()->fileSystem()) { + if (!webKitClient()->fileSystem()->getFileModificationTime(path, modificationTime)) + return false; + } else { + if (!webKitClient()->getFileModificationTime(path, modificationTime)) + return false; + } result = static_cast<time_t>(modificationTime); return true; } String ChromiumBridge::directoryName(const String& path) { + if (webKitClient()->fileSystem()) + return webKitClient()->fileSystem()->directoryName(path); return webKitClient()->directoryName(path); } String ChromiumBridge::pathByAppendingComponent(const String& path, const String& component) { + if (webKitClient()->fileSystem()) + return webKitClient()->fileSystem()->pathByAppendingComponent(path, component); return webKitClient()->pathByAppendingComponent(path, component); } bool ChromiumBridge::makeAllDirectories(const String& path) { + if (webKitClient()->fileSystem()) + return webKitClient()->fileSystem()->makeAllDirectories(path); return webKitClient()->makeAllDirectories(path); } String ChromiumBridge::getAbsolutePath(const String& path) { + if (webKitClient()->fileSystem()) + return webKitClient()->fileSystem()->getAbsolutePath(path); return webKitClient()->getAbsolutePath(path); } bool ChromiumBridge::isDirectory(const String& path) { + if (webKitClient()->fileSystem()) + return webKitClient()->fileSystem()->isDirectory(path); return webKitClient()->isDirectory(path); } KURL ChromiumBridge::filePathToURL(const String& path) { + if (webKitClient()->fileSystem()) + return webKitClient()->fileSystem()->filePathToURL(path); return webKitClient()->filePathToURL(path); } +PlatformFileHandle ChromiumBridge::openFile(const String& path, FileOpenMode mode) +{ + return webKitClient()->fileSystem()->openFile(path, mode); +} + +void ChromiumBridge::closeFile(PlatformFileHandle& handle) +{ + webKitClient()->fileSystem()->closeFile(handle); +} + +long long ChromiumBridge::seekFile(PlatformFileHandle handle, long long offset, FileSeekOrigin origin) +{ + return webKitClient()->fileSystem()->seekFile(handle, offset, origin); +} + +bool ChromiumBridge::truncateFile(PlatformFileHandle handle, long long offset) +{ + return webKitClient()->fileSystem()->truncateFile(handle, offset); +} + +int ChromiumBridge::readFromFile(PlatformFileHandle handle, char* data, int length) +{ + return webKitClient()->fileSystem()->readFromFile(handle, data, length); +} + +int ChromiumBridge::writeToFile(PlatformFileHandle handle, const char* data, int length) +{ + return webKitClient()->fileSystem()->writeToFile(handle, data, length); +} + // Font ----------------------------------------------------------------------- #if OS(WINDOWS) diff --git a/WebKit/chromium/src/ChromiumThreading.cpp b/WebKit/chromium/src/ChromiumThreading.cpp index 902a433..c6fefac 100644 --- a/WebKit/chromium/src/ChromiumThreading.cpp +++ b/WebKit/chromium/src/ChromiumThreading.cpp @@ -38,13 +38,9 @@ namespace WTF { -void ChromiumThreading::initializeMainThread() +void ChromiumThreading::callOnMainThread(void (*func)(void*), void* context) { -} - -void ChromiumThreading::scheduleDispatchFunctionsOnMainThread() -{ - WebKit::webKitClient()->callOnMainThread(&WTF::dispatchFunctionsFromMainThread); + WebKit::webKitClient()->callOnMainThread(func, context); } } // namespace WTF diff --git a/WebKit/chromium/src/FrameLoaderClientImpl.cpp b/WebKit/chromium/src/FrameLoaderClientImpl.cpp index 135392b..17d9416 100644 --- a/WebKit/chromium/src/FrameLoaderClientImpl.cpp +++ b/WebKit/chromium/src/FrameLoaderClientImpl.cpp @@ -628,14 +628,9 @@ void FrameLoaderClientImpl::dispatchDidNavigateWithinPage() bool isNewNavigation; webView->didCommitLoad(&isNewNavigation); - if (m_webFrame->client()) { + if (m_webFrame->client()) m_webFrame->client()->didNavigateWithinPage(m_webFrame, isNewNavigation); - // FIXME: Remove this notification once it is no longer consumed downstream. - if (isHashChange) - m_webFrame->client()->didChangeLocationWithinPage(m_webFrame, isNewNavigation); - } - // Generate didStopLoading if loader is completed. if (webView->client() && loaderCompleted) webView->client()->didStopLoading(); @@ -726,6 +721,12 @@ void FrameLoaderClientImpl::dispatchDidReceiveTitle(const String& title) m_webFrame->client()->didReceiveTitle(m_webFrame, title); } +void FrameLoaderClientImpl::dispatchDidChangeIcons() +{ + if (m_webFrame->client()) + m_webFrame->client()->didChangeIcons(m_webFrame); +} + void FrameLoaderClientImpl::dispatchDidCommitLoad() { WebViewImpl* webview = m_webFrame->viewImpl(); @@ -788,12 +789,14 @@ void FrameLoaderClientImpl::dispatchDidFinishLoad() void FrameLoaderClientImpl::dispatchDidFirstLayout() { + if (m_webFrame->client()) + m_webFrame->client()->didFirstLayout(m_webFrame); } void FrameLoaderClientImpl::dispatchDidFirstVisuallyNonEmptyLayout() { - // FIXME: called when webkit finished layout of a page that was visually non-empty. - // All resources have not necessarily finished loading. + if (m_webFrame->client()) + m_webFrame->client()->didFirstVisuallyNonEmptyLayout(m_webFrame); } Frame* FrameLoaderClientImpl::dispatchCreatePage() @@ -949,6 +952,12 @@ void FrameLoaderClientImpl::dispatchUnableToImplementPolicy(const ResourceError& m_webFrame->client()->unableToImplementPolicyWithError(m_webFrame, error); } +void FrameLoaderClientImpl::dispatchWillSendSubmitEvent(HTMLFormElement* form) +{ + if (m_webFrame->client()) + m_webFrame->client()->willSendSubmitEvent(m_webFrame, WebFormElement(form)); +} + void FrameLoaderClientImpl::dispatchWillSubmitForm(FramePolicyFunction function, PassRefPtr<FormState> formState) { diff --git a/WebKit/chromium/src/FrameLoaderClientImpl.h b/WebKit/chromium/src/FrameLoaderClientImpl.h index 1cbc1de..c163f62 100644 --- a/WebKit/chromium/src/FrameLoaderClientImpl.h +++ b/WebKit/chromium/src/FrameLoaderClientImpl.h @@ -102,6 +102,7 @@ public: virtual void dispatchDidReceiveIcon(); virtual void dispatchDidStartProvisionalLoad(); virtual void dispatchDidReceiveTitle(const WebCore::String& title); + virtual void dispatchDidChangeIcons(); virtual void dispatchDidCommitLoad(); virtual void dispatchDidFailProvisionalLoad(const WebCore::ResourceError&); virtual void dispatchDidFailLoad(const WebCore::ResourceError&); @@ -116,6 +117,7 @@ public: virtual void dispatchDecidePolicyForNavigationAction(WebCore::FramePolicyFunction function, const WebCore::NavigationAction& action, const WebCore::ResourceRequest& request, PassRefPtr<WebCore::FormState> form_state); virtual void cancelPolicyCheck(); virtual void dispatchUnableToImplementPolicy(const WebCore::ResourceError&); + virtual void dispatchWillSendSubmitEvent(WebCore::HTMLFormElement*); virtual void dispatchWillSubmitForm(WebCore::FramePolicyFunction, PassRefPtr<WebCore::FormState>); virtual void dispatchDidLoadMainResource(WebCore::DocumentLoader*); virtual void revertToProvisionalState(WebCore::DocumentLoader*); diff --git a/WebKit/chromium/src/GraphicsContext3D.cpp b/WebKit/chromium/src/GraphicsContext3D.cpp index 0f9c959..e51f433 100644 --- a/WebKit/chromium/src/GraphicsContext3D.cpp +++ b/WebKit/chromium/src/GraphicsContext3D.cpp @@ -111,6 +111,8 @@ public: void beginPaint(WebGLRenderingContext* context); void endPaint(); + bool isGLES2Compliant() const; + //---------------------------------------------------------------------- // Entry points for WebGL. // @@ -617,6 +619,11 @@ rt GraphicsContext3DInternal::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 DELEGATE_TO_IMPL_R(makeContextCurrent, bool) DELEGATE_TO_IMPL_1R(sizeInBytes, int, int) +bool GraphicsContext3DInternal::isGLES2Compliant() const +{ + return m_impl->isGLES2Compliant(); +} + DELEGATE_TO_IMPL_1(activeTexture, unsigned long) DELEGATE_TO_IMPL_2_X12(attachShader, WebGLProgram*, WebGLShader*) @@ -1202,41 +1209,10 @@ DELEGATE_TO_INTERNAL_3(stencilOp, unsigned long, unsigned long, unsigned long) DELEGATE_TO_INTERNAL_4(stencilOpSeparate, unsigned long, unsigned long, unsigned long, unsigned long) DELEGATE_TO_INTERNAL_9R(texImage2D, unsigned, unsigned, unsigned, unsigned, unsigned, unsigned, unsigned, unsigned, void*, int) - -int GraphicsContext3D::texImage2D(unsigned target, unsigned level, Image* image, - bool flipY, bool premultiplyAlpha) -{ - Vector<uint8_t> imageData; - unsigned int format, internalFormat; - if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) - return -1; - return m_internal->texImage2D(target, level, internalFormat, - image->width(), image->height(), 0, - format, UNSIGNED_BYTE, imageData.data()); -} - DELEGATE_TO_INTERNAL_3(texParameterf, unsigned, unsigned, float) DELEGATE_TO_INTERNAL_3(texParameteri, unsigned, unsigned, int) - DELEGATE_TO_INTERNAL_9R(texSubImage2D, unsigned, unsigned, unsigned, unsigned, unsigned, unsigned, unsigned, unsigned, void*, int) -int GraphicsContext3D::texSubImage2D(unsigned target, - unsigned level, - unsigned xoffset, - unsigned yoffset, - Image* image, - bool flipY, - bool premultiplyAlpha) -{ - Vector<uint8_t> imageData; - unsigned int format, internalFormat; - if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) - return -1; - return m_internal->texSubImage2D(target, level, xoffset, yoffset, - image->width(), image->height(), - format, UNSIGNED_BYTE, imageData.data()); -} - DELEGATE_TO_INTERNAL_2(uniform1f, long, float) DELEGATE_TO_INTERNAL_3(uniform1fv, long, float*, int) DELEGATE_TO_INTERNAL_2(uniform1i, long, int) @@ -1291,6 +1267,11 @@ DELEGATE_TO_INTERNAL_1(deleteTexture, unsigned) DELEGATE_TO_INTERNAL_1(synthesizeGLError, unsigned long) +bool GraphicsContext3D::isGLES2Compliant() const +{ + return m_internal->isGLES2Compliant(); +} + } // namespace WebCore #endif // ENABLE(3D_CANVAS) diff --git a/WebKit/chromium/src/SharedWorkerRepository.cpp b/WebKit/chromium/src/SharedWorkerRepository.cpp index f0a8ec8..a2b513f 100644 --- a/WebKit/chromium/src/SharedWorkerRepository.cpp +++ b/WebKit/chromium/src/SharedWorkerRepository.cpp @@ -70,6 +70,7 @@ public: , m_name(name) , m_webWorker(webWorker) , m_port(port) + , m_scriptLoader(ResourceRequestBase::TargetIsSharedWorker) , m_loading(false) { } diff --git a/WebKit/chromium/src/StorageAreaProxy.cpp b/WebKit/chromium/src/StorageAreaProxy.cpp index 0e44250..5311b65 100644 --- a/WebKit/chromium/src/StorageAreaProxy.cpp +++ b/WebKit/chromium/src/StorageAreaProxy.cpp @@ -125,8 +125,12 @@ void StorageAreaProxy::storageEvent(const String& key, const String& oldValue, c frames.append(frame); } - for (unsigned i = 0; i < frames.size(); ++i) - frames[i]->document()->enqueueEvent(StorageEvent::create(eventNames().storageEvent, key, oldValue, newValue, sourceFrame->document()->url(), frames[i]->domWindow()->sessionStorage())); + for (unsigned i = 0; i < frames.size(); ++i) { + ExceptionCode ec = 0; + Storage* storage = frames[i]->domWindow()->sessionStorage(ec); + if (!ec) + frames[i]->document()->enqueueEvent(StorageEvent::create(eventNames().storageEvent, key, oldValue, newValue, sourceFrame->document()->url(), storage)); + } } else { // Send events to every page. const HashSet<Page*>& pages = page->group().pages(); diff --git a/WebKit/chromium/src/StorageEventDispatcherImpl.cpp b/WebKit/chromium/src/StorageEventDispatcherImpl.cpp index ae25d44..631753b 100644 --- a/WebKit/chromium/src/StorageEventDispatcherImpl.cpp +++ b/WebKit/chromium/src/StorageEventDispatcherImpl.cpp @@ -71,13 +71,11 @@ void StorageEventDispatcherImpl::dispatchStorageEvent(const String& key, const S } } - // FIXME: Figure out how to pass in the document URI. for (unsigned i = 0; i < frames.size(); ++i) { ExceptionCode ec = 0; Storage* storage = frames[i]->domWindow()->localStorage(ec); if (!ec) - frames[i]->document()->dispatchWindowEvent(StorageEvent::create(eventNames().storageEvent, key, oldValue, newValue, - url, storage)); + frames[i]->document()->dispatchWindowEvent(StorageEvent::create(eventNames().storageEvent, key, oldValue, newValue, url, storage)); } } diff --git a/WebKit/chromium/src/SuggestionsPopupMenuClient.cpp b/WebKit/chromium/src/SuggestionsPopupMenuClient.cpp index aaf9036..dd7d9b8 100644 --- a/WebKit/chromium/src/SuggestionsPopupMenuClient.cpp +++ b/WebKit/chromium/src/SuggestionsPopupMenuClient.cpp @@ -156,11 +156,9 @@ void SuggestionsPopupMenuClient::initialize(HTMLInputElement* textField, FontDescription fontDescription; RenderTheme::defaultTheme()->systemFont(CSSValueWebkitControl, fontDescription); + RenderStyle* style = m_textField->computedStyle(); + fontDescription.setComputedSize(style->fontDescription().computedSize()); - // Use a smaller font size to match IE/Firefox. - // FIXME: http://crbug.com/7376 use the system size instead of a - // fixed font size value. - fontDescription.setComputedSize(12.0); Font font(fontDescription, 0, 0); font.update(textField->document()->styleSelector()->fontSelector()); // The direction of text in popup menu is set the same as the direction of diff --git a/WebKit/chromium/src/WebElement.cpp b/WebKit/chromium/src/WebElement.cpp index 3ed16e6..25a396e 100644 --- a/WebKit/chromium/src/WebElement.cpp +++ b/WebKit/chromium/src/WebElement.cpp @@ -32,6 +32,8 @@ #include "WebElement.h" #include "Element.h" +#include "RenderBoxModelObject.h" +#include "RenderObject.h" #include <wtf/PassRefPtr.h> using namespace WebCore; diff --git a/WebKit/chromium/src/WebFormElement.cpp b/WebKit/chromium/src/WebFormElement.cpp index 610c36d..7952479 100644 --- a/WebKit/chromium/src/WebFormElement.cpp +++ b/WebKit/chromium/src/WebFormElement.cpp @@ -78,18 +78,6 @@ void WebFormElement::getNamedElements(const WebString& name, result.assign(tempVector); } -void WebFormElement::getInputElements(WebVector<WebInputElement>& result) const -{ - const HTMLFormElement* form = constUnwrap<HTMLFormElement>(); - Vector<RefPtr<HTMLInputElement> > tempVector; - for (size_t i = 0; i < form->formElements.size(); i++) { - if (form->formElements[i]->hasLocalName(HTMLNames::inputTag)) - tempVector.append(static_cast<HTMLInputElement*>( - form->formElements[i])); - } - result.assign(tempVector); -} - void WebFormElement::getFormControlElements(WebVector<WebFormControlElement>& result) const { const HTMLFormElement* form = constUnwrap<HTMLFormElement>(); diff --git a/WebKit/chromium/src/WebGraphicsContext3DDefaultImpl.cpp b/WebKit/chromium/src/WebGraphicsContext3DDefaultImpl.cpp index 2ff1c11..52bc645 100644 --- a/WebKit/chromium/src/WebGraphicsContext3DDefaultImpl.cpp +++ b/WebKit/chromium/src/WebGraphicsContext3DDefaultImpl.cpp @@ -464,6 +464,11 @@ int WebGraphicsContext3DDefaultImpl::sizeInBytes(int type) return 0; } +bool WebGraphicsContext3DDefaultImpl::isGLES2Compliant() +{ + return false; +} + static int createTextureObject(GLenum target) { GLuint texture = 0; @@ -1050,7 +1055,23 @@ void WebGraphicsContext3DDefaultImpl::getFramebufferAttachmentParameteriv(unsign glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value); } -DELEGATE_TO_GL_2(getIntegerv, GetIntegerv, unsigned long, int*) +void WebGraphicsContext3DDefaultImpl::getIntegerv(unsigned long pname, int* value) +{ + // Need to emulate IMPLEMENTATION_COLOR_READ_FORMAT/TYPE for GL. Any valid + // combination should work, but GL_RGB/GL_UNSIGNED_BYTE might be the most + // useful for desktop WebGL users. + makeContextCurrent(); + switch (pname) { + case 0x8B9B: // IMPLEMENTATION_COLOR_READ_FORMAT + *value = GL_RGB; + break; + case 0x8B9A: // IMPLEMENTATION_COLOR_READ_TYPE + *value = GL_UNSIGNED_BYTE; + break; + default: + glGetIntegerv(pname, value); + } +} DELEGATE_TO_GL_3(getProgramiv, GetProgramiv, WebGLId, unsigned long, int*) diff --git a/WebKit/chromium/src/WebGraphicsContext3DDefaultImpl.h b/WebKit/chromium/src/WebGraphicsContext3DDefaultImpl.h index cc283e3..2518a37 100644 --- a/WebKit/chromium/src/WebGraphicsContext3DDefaultImpl.h +++ b/WebKit/chromium/src/WebGraphicsContext3DDefaultImpl.h @@ -75,6 +75,8 @@ public: virtual int sizeInBytes(int type); + virtual bool isGLES2Compliant(); + virtual void reshape(int width, int height); virtual bool readBackFramebuffer(unsigned char* pixels, size_t bufferSize); diff --git a/WebKit/chromium/src/WebInputElement.cpp b/WebKit/chromium/src/WebInputElement.cpp index 1eab91f..2f65ad2 100644 --- a/WebKit/chromium/src/WebInputElement.cpp +++ b/WebKit/chromium/src/WebInputElement.cpp @@ -94,24 +94,6 @@ void WebInputElement::setSelectionRange(int start, int end) { unwrap<HTMLInputElement>()->setSelectionRange(start, end); } - -WebString WebInputElement::name() const -{ - return constUnwrap<HTMLInputElement>()->name(); -} - -WebString WebInputElement::nameForAutofill() const -{ - String name = constUnwrap<HTMLInputElement>()->name(); - String trimmedName = name.stripWhiteSpace(); - if (!trimmedName.isEmpty()) - return trimmedName; - name = constUnwrap<HTMLInputElement>()->getAttribute(HTMLNames::idAttr); - trimmedName = name.stripWhiteSpace(); - if (!trimmedName.isEmpty()) - return trimmedName; - return String(); -} WebInputElement::WebInputElement(const PassRefPtr<HTMLInputElement>& elem) : WebFormControlElement(elem) diff --git a/WebKit/chromium/src/WebKit.cpp b/WebKit/chromium/src/WebKit.cpp index a8e1851..8346ef8 100644 --- a/WebKit/chromium/src/WebKit.cpp +++ b/WebKit/chromium/src/WebKit.cpp @@ -56,6 +56,7 @@ void initialize(WebKitClient* webKitClient) s_webKitClient = webKitClient; WTF::initializeThreading(); + WTF::initializeMainThread(); WebCore::AtomicString::init(); // Chromium sets the minimum interval timeout to 4ms, overriding the diff --git a/WebKit/chromium/src/WebNode.cpp b/WebKit/chromium/src/WebNode.cpp index e050c79..90bbb34 100644 --- a/WebKit/chromium/src/WebNode.cpp +++ b/WebKit/chromium/src/WebNode.cpp @@ -178,6 +178,11 @@ WebNodeList WebNode::getElementsByTagName(const WebString& tag) const return WebNodeList(m_private->getElementsByTagName(tag)); } +bool WebNode::hasNonEmptyBoundingBox() const +{ + return m_private->hasNonEmptyBoundingBox(); +} + WebNode::WebNode(const PassRefPtr<Node>& node) : m_private(node) { diff --git a/WebKit/chromium/src/WebNotification.cpp b/WebKit/chromium/src/WebNotification.cpp index 5200d17..5ae1557 100644 --- a/WebKit/chromium/src/WebNotification.cpp +++ b/WebKit/chromium/src/WebNotification.cpp @@ -94,6 +94,16 @@ WebString WebNotification::body() const return m_private->contents().body(); } +WebString WebNotification::dir() const +{ + return m_private->dir(); +} + +WebString WebNotification::replaceId() const +{ + return m_private->replaceId(); +} + void WebNotification::dispatchDisplayEvent() { RefPtr<Event> event = Event::create("display", false, true); diff --git a/WebKit/chromium/src/WebPasswordFormData.cpp b/WebKit/chromium/src/WebPasswordFormData.cpp index 64b1754..eb230d5 100644 --- a/WebKit/chromium/src/WebPasswordFormData.cpp +++ b/WebKit/chromium/src/WebPasswordFormData.cpp @@ -162,7 +162,10 @@ WebPasswordFormData::WebPasswordFormData(const WebFormElement& webForm) KURL fullOrigin(ParsedURLString, form->document()->documentURI()); // Calculate the canonical action URL - KURL fullAction = frame->loader()->completeURL(form->action()); + String action = form->action(); + if (action.isNull()) + action = ""; // missing 'action' attribute implies current URL + KURL fullAction = frame->loader()->completeURL(action); if (!fullAction.isValid()) return; diff --git a/WebKit/chromium/src/WebPluginContainerImpl.cpp b/WebKit/chromium/src/WebPluginContainerImpl.cpp index 2cdf255..b207a25 100644 --- a/WebKit/chromium/src/WebPluginContainerImpl.cpp +++ b/WebKit/chromium/src/WebPluginContainerImpl.cpp @@ -128,10 +128,10 @@ void WebPluginContainerImpl::invalidateRect(const IntRect& rect) parent()->hostWindow()->invalidateContentsAndWindow(damageRect, false /*immediate*/); } -void WebPluginContainerImpl::setFocus() +void WebPluginContainerImpl::setFocus(bool focused) { - Widget::setFocus(); - m_webPlugin->updateFocus(true); + Widget::setFocus(focused); + m_webPlugin->updateFocus(focused); } void WebPluginContainerImpl::show() diff --git a/WebKit/chromium/src/WebPluginContainerImpl.h b/WebKit/chromium/src/WebPluginContainerImpl.h index 3160394..4163ee5 100644 --- a/WebKit/chromium/src/WebPluginContainerImpl.h +++ b/WebKit/chromium/src/WebPluginContainerImpl.h @@ -67,7 +67,7 @@ public: virtual void setFrameRect(const WebCore::IntRect&); virtual void paint(WebCore::GraphicsContext*, const WebCore::IntRect&); virtual void invalidateRect(const WebCore::IntRect&); - virtual void setFocus(); + virtual void setFocus(bool); virtual void show(); virtual void hide(); virtual void handleEvent(WebCore::Event*); diff --git a/WebKit/chromium/src/WebPopupMenuImpl.h b/WebKit/chromium/src/WebPopupMenuImpl.h index 7390394..ca50b81 100644 --- a/WebKit/chromium/src/WebPopupMenuImpl.h +++ b/WebKit/chromium/src/WebPopupMenuImpl.h @@ -75,6 +75,7 @@ public: int targetStart, int targetEnd, const WebString& text); virtual bool queryCompositionStatus(bool* enabled, WebRect* caretRect); virtual void setTextDirection(WebTextDirection direction); + virtual bool isAcceleratedCompositingActive() const { return false; } // WebPopupMenuImpl void Init(WebCore::FramelessScrollView* widget, diff --git a/WebKit/chromium/src/WebRuntimeFeatures.cpp b/WebKit/chromium/src/WebRuntimeFeatures.cpp index 464834d..8e73d6f 100644 --- a/WebKit/chromium/src/WebRuntimeFeatures.cpp +++ b/WebKit/chromium/src/WebRuntimeFeatures.cpp @@ -210,4 +210,20 @@ bool WebRuntimeFeatures::isPushStateEnabled(bool enable) return RuntimeEnabledFeatures::pushStateEnabled(); } +void WebRuntimeFeatures::enableTouch(bool enable) +{ +#if ENABLE(TOUCH_EVENTS) + RuntimeEnabledFeatures::setTouchEnabled(enable); +#endif +} + +bool WebRuntimeFeatures::isTouchEnabled() +{ +#if ENABLE(TOUCH_EVENTS) + return RuntimeEnabledFeatures::touchEnabled(); +#else + return false; +#endif +} + } // namespace WebKit diff --git a/WebKit/chromium/src/WebSecurityPolicy.cpp b/WebKit/chromium/src/WebSecurityPolicy.cpp index 24ef7d1..cb7ded0 100644 --- a/WebKit/chromium/src/WebSecurityPolicy.cpp +++ b/WebKit/chromium/src/WebSecurityPolicy.cpp @@ -56,7 +56,8 @@ void WebSecurityPolicy::registerURLSchemeAsSecure(const WebString& scheme) SecurityOrigin::registerURLSchemeAsSecure(scheme); } -void WebSecurityPolicy::whiteListAccessFromOrigin(const WebURL& sourceOrigin, +void WebSecurityPolicy::addOriginAccessWhitelistEntry( + const WebURL& sourceOrigin, const WebString& destinationProtocol, const WebString& destinationHost, bool allowDestinationSubdomains) @@ -66,11 +67,38 @@ void WebSecurityPolicy::whiteListAccessFromOrigin(const WebURL& sourceOrigin, destinationHost, allowDestinationSubdomains); } -void WebSecurityPolicy::resetOriginAccessWhiteLists() +void WebSecurityPolicy::removeOriginAccessWhitelistEntry( + const WebURL& sourceOrigin, + const WebString& destinationProtocol, + const WebString& destinationHost, + bool allowDestinationSubdomains) +{ + SecurityOrigin::removeOriginAccessWhitelistEntry( + *SecurityOrigin::create(sourceOrigin), destinationProtocol, + destinationHost, allowDestinationSubdomains); +} + +void WebSecurityPolicy::resetOriginAccessWhitelists() { SecurityOrigin::resetOriginAccessWhitelists(); } +// To be removed when Chromium's test_shell has proper references. +void WebSecurityPolicy::whiteListAccessFromOrigin(const WebURL& sourceOrigin, + const WebString& destinationProtocol, + const WebString& destinationHost, + bool allowDestinationSubdomains) +{ + addOriginAccessWhitelistEntry(sourceOrigin, + destinationProtocol, destinationHost, + allowDestinationSubdomains); +} + +void WebSecurityPolicy::resetOriginAccessWhiteLists() +{ + resetOriginAccessWhitelists(); +} + bool WebSecurityPolicy::shouldHideReferrer(const WebURL& url, const WebString& referrer) { return SecurityOrigin::shouldHideReferrer(url, referrer); diff --git a/WebKit/chromium/src/WebSettingsImpl.cpp b/WebKit/chromium/src/WebSettingsImpl.cpp index 9e0fa91..3adf3ac 100644 --- a/WebKit/chromium/src/WebSettingsImpl.cpp +++ b/WebKit/chromium/src/WebSettingsImpl.cpp @@ -200,6 +200,11 @@ void WebSettingsImpl::setDownloadableBinaryFontsEnabled(bool enabled) m_settings->setDownloadableBinaryFontsEnabled(enabled); } +void WebSettingsImpl::setJavaScriptCanAccessClipboard(bool enabled) +{ + m_settings->setJavaScriptCanAccessClipboard(enabled); +} + void WebSettingsImpl::setXSSAuditorEnabled(bool enabled) { m_settings->setXSSAuditorEnabled(enabled); diff --git a/WebKit/chromium/src/WebSettingsImpl.h b/WebKit/chromium/src/WebSettingsImpl.h index 7a809c7..54c660b 100644 --- a/WebKit/chromium/src/WebSettingsImpl.h +++ b/WebKit/chromium/src/WebSettingsImpl.h @@ -74,6 +74,7 @@ public: virtual void setAuthorAndUserStylesEnabled(bool); virtual void setUsesPageCache(bool); virtual void setDownloadableBinaryFontsEnabled(bool); + virtual void setJavaScriptCanAccessClipboard(bool); virtual void setXSSAuditorEnabled(bool); virtual void setLocalStorageEnabled(bool); virtual void setEditableLinkBehaviorNeverLive(); diff --git a/WebKit/chromium/src/WebStorageNamespaceImpl.cpp b/WebKit/chromium/src/WebStorageNamespaceImpl.cpp index 66be027..5fc6e16 100644 --- a/WebKit/chromium/src/WebStorageNamespaceImpl.cpp +++ b/WebKit/chromium/src/WebStorageNamespaceImpl.cpp @@ -45,9 +45,9 @@ WebStorageNamespace* WebStorageNamespace::createLocalStorageNamespace(const WebS return new WebStorageNamespaceImpl(WebCore::StorageNamespaceImpl::localStorageNamespace(path, quota)); } -WebStorageNamespace* WebStorageNamespace::createSessionStorageNamespace() +WebStorageNamespace* WebStorageNamespace::createSessionStorageNamespace(unsigned quota) { - return new WebStorageNamespaceImpl(WebCore::StorageNamespaceImpl::sessionStorageNamespace(noQuota)); + return new WebStorageNamespaceImpl(WebCore::StorageNamespaceImpl::sessionStorageNamespace(quota)); } WebStorageNamespaceImpl::WebStorageNamespaceImpl(PassRefPtr<WebCore::StorageNamespace> storageNamespace) diff --git a/WebKit/chromium/src/WebViewImpl.cpp b/WebKit/chromium/src/WebViewImpl.cpp index 671a8c9..81a4ff3 100644 --- a/WebKit/chromium/src/WebViewImpl.cpp +++ b/WebKit/chromium/src/WebViewImpl.cpp @@ -183,7 +183,9 @@ void WebView::willEnterModalLoop() PageGroup* pageGroup = PageGroup::pageGroup(pageGroupName); ASSERT(pageGroup); - ASSERT(!pageGroup->pages().isEmpty()); + + if (pageGroup->pages().isEmpty()) + return; // Pick any page in the page group since we are deferring all pages. pageGroupLoadDeferrer = new PageGroupLoadDeferrer(*pageGroup->pages().begin(), true); @@ -191,9 +193,6 @@ void WebView::willEnterModalLoop() void WebView::didExitModalLoop() { - // The embedder must have called willEnterNestedEventLoop. - ASSERT(pageGroupLoadDeferrer); - delete pageGroupLoadDeferrer; pageGroupLoadDeferrer = 0; } @@ -243,13 +242,14 @@ WebViewImpl::WebViewImpl(WebViewClient* client) , m_haveMouseCapture(false) #if USE(ACCELERATED_COMPOSITING) , m_layerRenderer(0) - , m_isAcceleratedCompositing(false) + , m_isAcceleratedCompositingActive(false) #endif { // WebKit/win/WebView.cpp does the same thing, except they call the // KJS specific wrapper around this method. We need to have threading // initialized because CollatorICU requires it. WTF::initializeThreading(); + WTF::initializeMainThread(); // set to impossible point so we always get the first mouse pos m_lastMousePosition = WebPoint(-1, -1); @@ -326,9 +326,15 @@ void WebViewImpl::mouseDown(const WebMouseEvent& event) if (!mainFrameImpl() || !mainFrameImpl()->frameView()) return; - // If there is a select popup opened, close it as the user is clicking on - // the page (outside of the popup). - hideSelectPopup(); + // If there is a select popup open, close it as the user is clicking on + // the page (outside of the popup). We also save it so we can prevent a + // click on the select element from immediately reopening the popup. + RefPtr<WebCore::PopupContainer> selectPopup; + if (event.button == WebMouseEvent::ButtonLeft) { + selectPopup = m_selectPopup; + hideSelectPopup(); + ASSERT(!m_selectPopup); + } m_lastMouseDownPoint = WebPoint(event.x, event.y); m_haveMouseCapture = true; @@ -362,6 +368,13 @@ void WebViewImpl::mouseDown(const WebMouseEvent& event) static_cast<EditorClientImpl*>(m_page->editorClient())-> showFormAutofillForNode(clickedNode.get()); } + if (m_selectPopup && m_selectPopup == selectPopup) { + // That click triggered a select popup which is the same as the one that + // was showing before the click. It means the user clicked the select + // while the popup was showing, and as a result we first closed then + // immediately reopened the select popup. It needs to be closed. + hideSelectPopup(); + } // Dispatch the contextmenu event regardless of if the click was swallowed. // On Windows, we handle it on mouse up, not down. @@ -849,6 +862,14 @@ void WebViewImpl::popupClosed(WebCore::PopupContainer* popupContainer) } } +void WebViewImpl::hideSuggestionsPopup() +{ + if (m_suggestionsPopupShowing) { + m_suggestionsPopup->hidePopup(); + m_suggestionsPopupShowing = false; + } +} + Frame* WebViewImpl::focusedWebCoreFrame() { return m_page.get() ? m_page->focusController()->focusedOrMainFrame() : 0; @@ -931,7 +952,7 @@ void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect) { #if USE(ACCELERATED_COMPOSITING) - if (!isAcceleratedCompositing()) { + if (!isAcceleratedCompositingActive()) { #endif WebFrameImpl* webframe = mainFrameImpl(); if (webframe) @@ -1267,6 +1288,15 @@ void WebViewImpl::setTextDirection(WebTextDirection direction) } } +bool WebViewImpl::isAcceleratedCompositingActive() const +{ +#if USE(ACCELERATED_COMPOSITING) + return m_isAcceleratedCompositingActive; +#else + return false; +#endif +} + // WebView -------------------------------------------------------------------- WebSettings* WebViewImpl::settings() @@ -1667,14 +1697,6 @@ WebAccessibilityObject WebViewImpl::accessibilityObject() document->axObjectCache()->getOrCreate(document->renderer())); } -void WebViewImpl::applyAutofillSuggestions( - const WebNode& node, - const WebVector<WebString>& suggestions, - int defaultSuggestionIndex) -{ - applyAutocompleteSuggestions(node, suggestions, defaultSuggestionIndex); -} - void WebViewImpl::applyAutoFillSuggestions( const WebNode& node, const WebVector<WebString>& names, @@ -1789,19 +1811,12 @@ void WebViewImpl::applyAutocompleteSuggestions( } } -void WebViewImpl::hideAutofillPopup() +void WebViewImpl::hidePopups() { + hideSelectPopup(); hideSuggestionsPopup(); } -void WebViewImpl::hideSuggestionsPopup() -{ - if (m_suggestionsPopupShowing) { - m_suggestionsPopup->hidePopup(); - m_suggestionsPopupShowing = false; - } -} - void WebViewImpl::performCustomContextMenuAction(unsigned action) { if (!m_page) @@ -2038,29 +2053,29 @@ bool WebViewImpl::tabsToLinks() const #if USE(ACCELERATED_COMPOSITING) void WebViewImpl::setRootGraphicsLayer(WebCore::PlatformLayer* layer) { - setAcceleratedCompositing(layer ? true : false); + setIsAcceleratedCompositingActive(layer ? true : false); if (m_layerRenderer) m_layerRenderer->setRootLayer(layer); } -void WebViewImpl::setAcceleratedCompositing(bool accelerated) +void WebViewImpl::setIsAcceleratedCompositingActive(bool active) { - if (m_isAcceleratedCompositing == accelerated) + if (m_isAcceleratedCompositingActive == active) return; - if (accelerated) { + if (active) { m_layerRenderer = LayerRendererChromium::create(); if (m_layerRenderer) - m_isAcceleratedCompositing = true; + m_isAcceleratedCompositingActive = true; } else { m_layerRenderer = 0; - m_isAcceleratedCompositing = false; + m_isAcceleratedCompositingActive = false; } } void WebViewImpl::updateRootLayerContents(const WebRect& rect) { - if (!isAcceleratedCompositing()) + if (!isAcceleratedCompositingActive()) return; WebFrameImpl* webframe = mainFrameImpl(); diff --git a/WebKit/chromium/src/WebViewImpl.h b/WebKit/chromium/src/WebViewImpl.h index ba2dc25..0bed223 100644 --- a/WebKit/chromium/src/WebViewImpl.h +++ b/WebKit/chromium/src/WebViewImpl.h @@ -100,6 +100,7 @@ public: virtual bool queryCompositionStatus(bool* enabled, WebRect* caretRect); virtual void setTextDirection(WebTextDirection direction); + virtual bool isAcceleratedCompositingActive() const; // WebView methods: virtual void initializeMainFrame(WebFrameClient*); @@ -156,10 +157,6 @@ public: virtual WebDevToolsAgent* devToolsAgent(); virtual void setDevToolsAgent(WebDevToolsAgent*); virtual WebAccessibilityObject accessibilityObject(); - virtual void applyAutofillSuggestions( - const WebNode&, - const WebVector<WebString>& suggestions, - int defaultSuggestionIndex); virtual void applyAutoFillSuggestions( const WebNode&, const WebVector<WebString>& names, @@ -169,8 +166,7 @@ public: const WebNode&, const WebVector<WebString>& suggestions, int defaultSuggestionIndex); - virtual void hideAutofillPopup(); - virtual void hideSuggestionsPopup(); + virtual void hidePopups(); virtual void setScrollbarColors(unsigned inactiveColor, unsigned activeColor, unsigned trackColor); @@ -299,6 +295,8 @@ public: void popupOpened(WebCore::PopupContainer* popupContainer); void popupClosed(WebCore::PopupContainer* popupContainer); + void hideSuggestionsPopup(); + // HACK: currentInputEvent() is for ChromeClientImpl::show(), until we can // fix WebKit to pass enough information up into ChromeClient::show() so we // can decide if the window.open event was caused by a middle-mouse click @@ -343,7 +341,6 @@ private: // Returns true if the view was scrolled. bool scrollViewWithKeyboard(int keyCode, int modifiers); - // Hides the select popup if one is opened. void hideSelectPopup(); // Converts |pos| from window coordinates to contents coordinates and gets @@ -358,8 +355,7 @@ private: DragAction); #if USE(ACCELERATED_COMPOSITING) - void setAcceleratedCompositing(bool); - bool isAcceleratedCompositing() const { return m_isAcceleratedCompositing; } + void setIsAcceleratedCompositingActive(bool); void updateRootLayerContents(const WebRect&); #endif @@ -495,7 +491,7 @@ private: #if USE(ACCELERATED_COMPOSITING) OwnPtr<WebCore::LayerRendererChromium> m_layerRenderer; - bool m_isAcceleratedCompositing; + bool m_isAcceleratedCompositingActive; #endif static const WebInputEvent* m_currentInputEvent; }; diff --git a/WebKit/chromium/src/WebWorkerBase.cpp b/WebKit/chromium/src/WebWorkerBase.cpp index da51414..8e26560 100644 --- a/WebKit/chromium/src/WebWorkerBase.cpp +++ b/WebKit/chromium/src/WebWorkerBase.cpp @@ -51,30 +51,6 @@ namespace WebKit { #if ENABLE(WORKERS) -// Dummy WebViewDelegate - we only need it in Worker process to load a -// 'shadow page' which will initialize WebCore loader. -class WorkerWebFrameClient : public WebFrameClient { -public: - // Tell the loader to load the data into the 'shadow page' synchronously, - // so we can grab the resulting Document right after load. - virtual void didCreateDataSource(WebFrame* frame, WebDataSource* ds) - { - static_cast<WebDataSourceImpl*>(ds)->setDeferMainResourceDataLoad(false); - } - - // Lazy allocate and leak this instance. - static WorkerWebFrameClient* sharedInstance() - { - static WorkerWebFrameClient client; - return &client; - } - -private: - WorkerWebFrameClient() - { - } -}; - // This function is called on the main thread to force to initialize some static // values used in WebKit before any worker thread is started. This is because in // our worker processs, we do not run any WebKit code in main thread and thus @@ -103,6 +79,9 @@ WebWorkerBase::WebWorkerBase() WebWorkerBase::~WebWorkerBase() { ASSERT(m_webView); + WebFrameImpl* webFrame = static_cast<WebFrameImpl*>(m_webView->mainFrame()); + if (webFrame) + webFrame->setClient(0); m_webView->close(); } @@ -122,7 +101,7 @@ void WebWorkerBase::initializeLoader(const WebURL& url) // infrastructure. ASSERT(!m_webView); m_webView = WebView::create(0); - m_webView->initializeMainFrame(WorkerWebFrameClient::sharedInstance()); + m_webView->initializeMainFrame(this); WebFrameImpl* webFrame = static_cast<WebFrameImpl*>(m_webView->mainFrame()); @@ -151,6 +130,20 @@ void WebWorkerBase::invokeTaskMethod(void* param) delete task; } +void WebWorkerBase::didCreateDataSource(WebFrame*, WebDataSource* ds) +{ + // Tell the loader to load the data into the 'shadow page' synchronously, + // so we can grab the resulting Document right after load. + static_cast<WebDataSourceImpl*>(ds)->setDeferMainResourceDataLoad(false); +} + +WebApplicationCacheHost* WebWorkerBase::createApplicationCacheHost(WebFrame*, WebApplicationCacheHostClient* appcacheHostClient) +{ + if (commonClient()) + return commonClient()->createApplicationCacheHost(appcacheHostClient); + return 0; +} + // WorkerObjectProxy ----------------------------------------------------------- void WebWorkerBase::postMessageToWorkerObject(PassRefPtr<SerializedScriptValue> message, diff --git a/WebKit/chromium/src/WebWorkerBase.h b/WebKit/chromium/src/WebWorkerBase.h index 1252770..a470ee4 100644 --- a/WebKit/chromium/src/WebWorkerBase.h +++ b/WebKit/chromium/src/WebWorkerBase.h @@ -34,6 +34,7 @@ #if ENABLE(WORKERS) #include "ScriptExecutionContext.h" +#include "WebFrameClient.h" #include "WorkerLoaderProxy.h" #include "WorkerObjectProxy.h" #include <wtf/PassOwnPtr.h> @@ -44,6 +45,8 @@ class WorkerThread; } namespace WebKit { +class WebApplicationCacheHost; +class WebApplicationCacheHostClient; class WebCommonWorkerClient; class WebSecurityOrigin; class WebString; @@ -56,7 +59,8 @@ class WebWorkerClient; // code used by both implementation classes, including implementations of the // WorkerObjectProxy and WorkerLoaderProxy interfaces. class WebWorkerBase : public WebCore::WorkerObjectProxy - , public WebCore::WorkerLoaderProxy { + , public WebCore::WorkerLoaderProxy + , public WebFrameClient { public: WebWorkerBase(); virtual ~WebWorkerBase(); @@ -80,6 +84,10 @@ public: virtual void postTaskForModeToWorkerContext( PassOwnPtr<WebCore::ScriptExecutionContext::Task>, const WebCore::String& mode); + // WebFrameClient methods to support resource loading thru the 'shadow page'. + virtual void didCreateDataSource(WebFrame*, WebDataSource*); + virtual WebApplicationCacheHost* createApplicationCacheHost(WebFrame*, WebApplicationCacheHostClient*); + // Executes the given task on the main thread. static void dispatchTaskToMainThread(PassOwnPtr<WebCore::ScriptExecutionContext::Task>); diff --git a/WebKit/chromium/src/WebWorkerClientImpl.h b/WebKit/chromium/src/WebWorkerClientImpl.h index 4bdc332..907499a 100644 --- a/WebKit/chromium/src/WebWorkerClientImpl.h +++ b/WebKit/chromium/src/WebWorkerClientImpl.h @@ -94,6 +94,7 @@ public: // FIXME: Notifications not yet supported in workers. return 0; } + virtual WebApplicationCacheHost* createApplicationCacheHost(WebApplicationCacheHostClient*) { return 0; } private: virtual ~WebWorkerClientImpl(); diff --git a/WebKit/chromium/src/js/DebuggerAgent.js b/WebKit/chromium/src/js/DebuggerAgent.js index 8230616..67e54aa 100644 --- a/WebKit/chromium/src/js/DebuggerAgent.js +++ b/WebKit/chromium/src/js/DebuggerAgent.js @@ -182,6 +182,7 @@ devtools.DebuggerAgent.prototype.initUI = function() for (var scriptId in this.parsedScripts_) { var script = this.parsedScripts_[scriptId]; WebInspector.parsedScriptSource(scriptId, script.getUrl(), undefined /* script source */, script.getLineOffset() + 1); + this.restoreBreakpoints_(scriptId, script.getUrl()); } return; } @@ -245,7 +246,7 @@ devtools.DebuggerAgent.prototype.pauseExecution = function() * @param {number} line Number of the line for the breakpoint. * @param {?string} condition The breakpoint condition. */ -devtools.DebuggerAgent.prototype.addBreakpoint = function(sourceId, line, condition) +devtools.DebuggerAgent.prototype.addBreakpoint = function(sourceId, line, enabled, condition) { var script = this.parsedScripts_[sourceId]; if (!script) @@ -263,7 +264,7 @@ devtools.DebuggerAgent.prototype.addBreakpoint = function(sourceId, line, condit this.urlToBreakpoints_[script.getUrl()] = breakpoints; } - var breakpointInfo = new devtools.BreakpointInfo(line); + var breakpointInfo = new devtools.BreakpointInfo(line, enabled, condition); breakpoints[line] = breakpointInfo; commandArguments = { @@ -278,7 +279,7 @@ devtools.DebuggerAgent.prototype.addBreakpoint = function(sourceId, line, condit if (breakpointInfo) return; - breakpointInfo = new devtools.BreakpointInfo(line); + breakpointInfo = new devtools.BreakpointInfo(line, enabled, condition); script.addBreakpointInfo(breakpointInfo); commandArguments = { @@ -290,6 +291,9 @@ devtools.DebuggerAgent.prototype.addBreakpoint = function(sourceId, line, condit }; } + if (!enabled) + return; + var cmd = new devtools.DebugCommand("setbreakpoint", commandArguments); this.requestNumberToBreakpointInfo_[cmd.getSequenceNumber()] = breakpointInfo; @@ -305,18 +309,11 @@ devtools.DebuggerAgent.prototype.addBreakpoint = function(sourceId, line, condit /** * Changes given line of the script. */ -devtools.DebuggerAgent.prototype.editScriptLine = function(sourceId, line, newContent, callback) +devtools.DebuggerAgent.prototype.editScriptSource = function(sourceId, newContent, callback) { - var script = this.parsedScripts_[sourceId]; - if (!script || !script.source) - return; - - var lines = script.source.split("\n"); - lines[line] = newContent; - var commandArguments = { "script_id": sourceId, - "new_source": lines.join("\n") + "new_source": newContent }; var cmd = new devtools.DebugCommand("changelive", commandArguments); @@ -962,6 +959,7 @@ devtools.DebuggerAgent.prototype.addScriptInfo_ = function(script, msg) if (this.scriptsPanelInitialized_) { // Only report script as parsed after scripts panel has been shown. WebInspector.parsedScriptSource(script.id, script.name, script.source, script.lineOffset + 1); + this.restoreBreakpoints_(script.id, script.name); } }; @@ -1085,6 +1083,23 @@ devtools.DebuggerAgent.prototype.formatCallFrame_ = function(stackFrame) /** + * Restores breakpoints associated with the URL of a newly parsed script. + * @param {number} sourceID The id of the script. + * @param {string} scriptUrl URL of the script. + */ +devtools.DebuggerAgent.prototype.restoreBreakpoints_ = function(sourceID, scriptUrl) +{ + var breakpoints = this.urlToBreakpoints_[scriptUrl]; + for (var line in breakpoints) { + if (parseInt(line) == line) { + var v8Line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(parseInt(line)); + WebInspector.restoredBreakpoint(sourceID, scriptUrl, v8Line, breakpoints[line].enabled(), breakpoints[line].condition()); + } + } +}; + + +/** * Collects properties for an object from the debugger response. * @param {Object} object An object from the debugger protocol response. * @param {Array.<WebInspector.ObjectPropertyProxy>} result An array to put the @@ -1279,9 +1294,11 @@ devtools.ScriptInfo.prototype.removeBreakpointInfo = function(breakpoint) * @param {number} line Breakpoint 0-based line number in the containing script. * @constructor */ -devtools.BreakpointInfo = function(line) +devtools.BreakpointInfo = function(line, enabled, condition) { this.line_ = line; + this.enabled_ = enabled; + this.condition_ = condition; this.v8id_ = -1; this.removed_ = false; }; @@ -1316,7 +1333,7 @@ devtools.BreakpointInfo.prototype.setV8Id = function(id) /** - * Marks this breakpoint as removed from the front-end. + * Marks this breakpoint as removed from the front-end. */ devtools.BreakpointInfo.prototype.markAsRemoved = function() { @@ -1335,6 +1352,24 @@ devtools.BreakpointInfo.prototype.isRemoved = function() /** + * @return {boolean} Whether this breakpoint is enabled. + */ +devtools.BreakpointInfo.prototype.enabled = function() +{ + return this.enabled_; +}; + + +/** + * @return {?string} Breakpoint condition. + */ +devtools.BreakpointInfo.prototype.condition = function() +{ + return this.condition_; +}; + + +/** * Call stack frame data. * @param {string} id CallFrame id. * @param {string} type CallFrame type. diff --git a/WebKit/chromium/src/js/DebuggerScript.js b/WebKit/chromium/src/js/DebuggerScript.js index 75c5467..7c4d126 100644 --- a/WebKit/chromium/src/js/DebuggerScript.js +++ b/WebKit/chromium/src/js/DebuggerScript.js @@ -33,18 +33,29 @@ function debuggerScriptConstructor() { var DebuggerScript = {}; DebuggerScript._breakpoints = {}; +DebuggerScript.PauseOnExceptionsState = { + DontPauseOnExceptions : 0, + PauseOnAllExceptions : 1, + PauseOnUncaughtExceptions: 2 +}; + +DebuggerScript._pauseOnExceptionsState = DebuggerScript.PauseOnExceptionsState.DontPauseOnExceptions; +Debug.clearBreakOnException(); +Debug.clearBreakOnUncaughtException(); DebuggerScript.getAfterCompileScript = function(execState, args) { return DebuggerScript._formatScript(args.eventData.script_.script_); } -DebuggerScript.getScripts = function(execState, args) +DebuggerScript.getScripts = function(contextData) { var scripts = Debug.scripts(); var result = []; for (var i = 0; i < scripts.length; ++i) { - result.push(DebuggerScript._formatScript(scripts[i])); + var script = scripts[i]; + if (contextData === script.context_data) + result.push(DebuggerScript._formatScript(script)); } return result; } @@ -92,6 +103,26 @@ DebuggerScript.removeBreakpoint = function(execState, args) delete DebuggerScript._breakpoints[key]; } +DebuggerScript.pauseOnExceptionsState = function() +{ + return DebuggerScript._pauseOnExceptionsState; +} + +DebuggerScript.setPauseOnExceptionsState = function(newState) +{ + DebuggerScript._pauseOnExceptionsState = newState; + + if (DebuggerScript.PauseOnExceptionsState.PauseOnAllExceptions === newState) + Debug.setBreakOnException(); + else + Debug.clearBreakOnException(); + + if (DebuggerScript.PauseOnExceptionsState.PauseOnUncaughtExceptions === newState) + Debug.setBreakOnUncaughtException(); + else + Debug.clearBreakOnUncaughtException(); +} + DebuggerScript.currentCallFrame = function(execState, args) { var frameCount = execState.frameCount(); @@ -160,7 +191,7 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror, callerFrame) var sourceID = script && script.id(); // Get line number. - var line = DebuggerScript._v8ToWwebkitLineNumber(frameMirror.sourceLine()); + var line = DebuggerScript._v8ToWebkitLineNumber(frameMirror.sourceLine()); // Get this object. var thisObject = frameMirror.details_.receiver(); @@ -201,7 +232,7 @@ DebuggerScript._webkitToV8LineNumber = function(line) return line - 1; }; -DebuggerScript._v8ToWwebkitLineNumber = function(line) +DebuggerScript._v8ToWebkitLineNumber = function(line) { return line + 1; }; diff --git a/WebKit/chromium/src/js/DevTools.js b/WebKit/chromium/src/js/DevTools.js index a530fe5..59b88db 100644 --- a/WebKit/chromium/src/js/DevTools.js +++ b/WebKit/chromium/src/js/DevTools.js @@ -190,6 +190,23 @@ WebInspector.loaded = function() InspectorFrontendHost.loaded(); }; +devtools.domContentLoaded = function() +{ + var queryParams = window.location.search; + if (queryParams) { + var params = queryParams.substring(1).split("&"); + var paramsObject = {}; + for (var i = 0; i < params.length; ++i) { + var pair = params[i].split("="); + paramsObject[pair[0]] = pair[1]; + } + WebInspector.setAttachedWindow(paramsObject.docked); + if (paramsObject.toolbar_color && paramsObject.text_color) + WebInspector.setToolbarColors(paramsObject.toolbar_color, paramsObject.text_color); + } +} +document.addEventListener("DOMContentLoaded", devtools.domContentLoaded, false); + if (!window.v8ScriptDebugServerEnabled) { @@ -415,78 +432,14 @@ WebInspector.setToolbarColors = function(backgroundColor, color) document.head.appendChild(WebInspector._themeStyleElement); } WebInspector._themeStyleElement.textContent = - "body #toolbar, body.inactive #toolbar {\ + "#toolbar {\ background-image: none !important;\ background-color: " + backgroundColor + " !important;\ }\ \ - body .status-bar {\ - background-image: url(Images/statusbarBackgroundChromium2.png) !important;\ - background-color: " + backgroundColor + " !important;\ - }\ - \ - body button.status-bar-item {\ - background-image: none !important;\ - }\ - \ - button.status-bar-item {\ - background-image: none;\ - border-right: 1px solid " + backgroundColor + ";\ - }\ - \ - .status-bar {\ - background-image: none;\ - color: " + color + ";\ - }\ - \ - body #drawer {\ - background-image: none !important;\ - }\ - \ - #drawer-status-bar {\ - background-image: url(Images/statusbarBackgroundChromium2.png);\ - background-color: " + backgroundColor + ";\ - }\ - \ - \ - body.drawer-visible #main-status-bar {\ - background-image: url(Images/statusbarBackgroundChromium2.png) !important;\ - }\ - \ - body .crumbs .crumb, body .crumbs .crumb.end {\ - -webkit-border-image: url(Images/segmentChromium2.png) 0 12 0 2 !important;\ - background-color: " + backgroundColor + " !important;\ - }\ - \ - body .crumbs .crumb:hover, body .crumbs .crumb.dimmed:hover {\ - -webkit-border-image: url(Images/segmentHoverChromium2.png) 0 12 0 2 !important;\ - }\ - \ - body .crumbs .crumb.end {\ - -webkit-border-image: url(Images/segmentChromium2.png) 0 12 0 2 !important;\ - }\ - \ - body .crumbs .crumb.selected:hover, body .crumbs .crumb.selected.end, .crumbs .crumb.selected.end:hover {\ - -webkit-border-image: url(Images/segmentSelectedChromium2.png) 0 12 0 2 !important;\ - }\ - \ - body select.status-bar-item {\ - -webkit-border-image: url(Images/statusbarMenuButtonChromium2.png) 0 17 0 2 !important;\ - background-color: " + backgroundColor + " !important;\ - text-shadow: none !important;\ - }\ - \ - .glyph {\ - background-color: " + color + ";\ - }\ - \ - button.status-bar-item .glyph.shadow {\ - display: none;\ - }\ - \ - .crumbs, .crumbs .crumb:hover, #drawer .scope-bar:not(.console-filter-top) li, .toolbar-label, select.status-bar-item {\ + .toolbar-label {\ + color: " + color + " !important;\ text-shadow: none;\ - color: " + color + ";\ }"; } diff --git a/WebKit/chromium/src/js/Images/segmentChromium.png b/WebKit/chromium/src/js/Images/segmentChromium.png Binary files differindex 607559b..f4248e1 100755 --- a/WebKit/chromium/src/js/Images/segmentChromium.png +++ b/WebKit/chromium/src/js/Images/segmentChromium.png diff --git a/WebKit/chromium/src/js/Images/segmentChromium2.png b/WebKit/chromium/src/js/Images/segmentChromium2.png Binary files differdeleted file mode 100755 index e94f570..0000000 --- a/WebKit/chromium/src/js/Images/segmentChromium2.png +++ /dev/null diff --git a/WebKit/chromium/src/js/Images/segmentHoverChromium2.png b/WebKit/chromium/src/js/Images/segmentHoverChromium2.png Binary files differdeleted file mode 100755 index 4d4a211..0000000 --- a/WebKit/chromium/src/js/Images/segmentHoverChromium2.png +++ /dev/null diff --git a/WebKit/chromium/src/js/Images/segmentSelectedChromium2.png b/WebKit/chromium/src/js/Images/segmentSelectedChromium2.png Binary files differdeleted file mode 100755 index f2b695b..0000000 --- a/WebKit/chromium/src/js/Images/segmentSelectedChromium2.png +++ /dev/null diff --git a/WebKit/chromium/src/js/Images/statusbarBackgroundChromium.png b/WebKit/chromium/src/js/Images/statusbarBackgroundChromium.png Binary files differindex 9d326ac..7a760c1 100755 --- a/WebKit/chromium/src/js/Images/statusbarBackgroundChromium.png +++ b/WebKit/chromium/src/js/Images/statusbarBackgroundChromium.png diff --git a/WebKit/chromium/src/js/Images/statusbarBackgroundChromium2.png b/WebKit/chromium/src/js/Images/statusbarBackgroundChromium2.png Binary files differdeleted file mode 100755 index 12d62b1..0000000 --- a/WebKit/chromium/src/js/Images/statusbarBackgroundChromium2.png +++ /dev/null diff --git a/WebKit/chromium/src/js/Images/statusbarBottomBackgroundChromium.png b/WebKit/chromium/src/js/Images/statusbarBottomBackgroundChromium.png Binary files differindex 7c7db0a..e3bc944 100755 --- a/WebKit/chromium/src/js/Images/statusbarBottomBackgroundChromium.png +++ b/WebKit/chromium/src/js/Images/statusbarBottomBackgroundChromium.png diff --git a/WebKit/chromium/src/js/Images/statusbarButtonsChromium.png b/WebKit/chromium/src/js/Images/statusbarButtonsChromium.png Binary files differindex 0c6635d..136d5a8 100755 --- a/WebKit/chromium/src/js/Images/statusbarButtonsChromium.png +++ b/WebKit/chromium/src/js/Images/statusbarButtonsChromium.png diff --git a/WebKit/chromium/src/js/Images/statusbarMenuButtonChromium.png b/WebKit/chromium/src/js/Images/statusbarMenuButtonChromium.png Binary files differindex bf26684..5ff61d9 100755 --- a/WebKit/chromium/src/js/Images/statusbarMenuButtonChromium.png +++ b/WebKit/chromium/src/js/Images/statusbarMenuButtonChromium.png diff --git a/WebKit/chromium/src/js/Images/statusbarMenuButtonChromium2.png b/WebKit/chromium/src/js/Images/statusbarMenuButtonChromium2.png Binary files differdeleted file mode 100755 index 9527ac8..0000000 --- a/WebKit/chromium/src/js/Images/statusbarMenuButtonChromium2.png +++ /dev/null diff --git a/WebKit/chromium/src/js/InspectorControllerImpl.js b/WebKit/chromium/src/js/InspectorControllerImpl.js index becc076..5c3e8bd 100644 --- a/WebKit/chromium/src/js/InspectorControllerImpl.js +++ b/WebKit/chromium/src/js/InspectorControllerImpl.js @@ -128,8 +128,7 @@ if (!window.v8ScriptDebugServerEnabled) { devtools.InspectorBackendImpl.prototype.setBreakpoint = function(sourceID, line, enabled, condition) { this.removeBreakpoint(sourceID, line); - if (enabled) - devtools.tools.getDebuggerAgent().addBreakpoint(sourceID, line, condition); + devtools.tools.getDebuggerAgent().addBreakpoint(sourceID, line, enabled, condition); }; @@ -139,10 +138,10 @@ devtools.InspectorBackendImpl.prototype.removeBreakpoint = function(sourceID, li }; -devtools.InspectorBackendImpl.prototype.editScriptLine = function(callID, sourceID, line, newContent) +devtools.InspectorBackendImpl.prototype.editScriptSource = function(callID, sourceID, newContent) { - devtools.tools.getDebuggerAgent().editScriptLine(sourceID, line, newContent, function(newFullBody) { - WebInspector.didEditScriptLine(callID, newFullBody); + devtools.tools.getDebuggerAgent().editScriptSource(sourceID, newContent, function(newFullBody) { + WebInspector.didEditScriptSource(callID, newFullBody); }); }; diff --git a/WebKit/chromium/src/js/devTools.css b/WebKit/chromium/src/js/devTools.css index bb33f72..6b4b3e5 100755 --- a/WebKit/chromium/src/js/devTools.css +++ b/WebKit/chromium/src/js/devTools.css @@ -15,12 +15,8 @@ body.attached #toolbar { /* Chrome theme overrides */ -body.platform-windows #toolbar { - background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(242, 247, 253)), to(rgb(223, 234, 248))); -} - -body.platform-windows.inactive #toolbar { - background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(248, 248, 248)), to(rgb(237, 237, 237))); +body.platform-windows #toolbar, body.platform-windows.inactive #toolbar { + background-image: none; } body.detached.platform-mac-leopard #toolbar { @@ -39,6 +35,12 @@ body.detached.platform-mac-snowleopard.inactive #toolbar { background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(215, 215, 215)), to(rgb(207, 207, 207))) !important; } +body.platform-linux #scripts-files { + font-size: 11px; + font-weight: normal; + line-height: 12px; +} + /* Heap Profiler Styles */ .heap-snapshot-status-bar-item .glyph { @@ -151,77 +153,79 @@ body.detached.platform-mac-snowleopard.inactive #toolbar { left: 25%; } -body.platform-windows .section > .header { +.section > .header { border: 1px solid rgb(92, 116, 157); background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(105, 133, 180)), to(rgb(92, 116, 157))); } -body.platform-windows .console-group-messages .section > .header { +.console-group-messages .section > .header { padding: 0 8px 0 0; background-image: none; border: none; min-height: 0; } -body.platform-windows #resources-filter { +#resources-filter { background: -webkit-gradient(linear, left top, left bottom, from(rgb(233, 233, 233)), to(rgb(233, 233, 233))); } -body.platform-windows .crumbs .crumb { +.crumbs .crumb { -webkit-border-image: url(Images/segmentChromium.png) 0 12 0 2; + margin-right: -3px; + padding-left: 6px; } -body.platform-windows .crumbs .crumb.end { +.crumbs .crumb.end { -webkit-border-image: url(Images/segmentEndChromium.png) 0 2 0 2; } -body.platform-windows .crumbs .crumb.selected { +.crumbs .crumb.selected { -webkit-border-image: url(Images/segmentSelectedChromium.png) 0 12 0 2; color: white; text-shadow: rgba(255, 255, 255, 0.5) 0 0px 0; } -body.platform-windows .crumbs .crumb.selected:hover { +.crumbs .crumb.selected:hover { -webkit-border-image: url(Images/segmentSelectedChromium.png) 0 12 0 2; } -body.platform-windows .crumbs .crumb.selected.end, .crumbs .crumb.selected.end:hover { +.crumbs .crumb.selected.end, .crumbs .crumb.selected.end:hover { -webkit-border-image: url(Images/segmentSelectedEndChromium.png) 0 2 0 2; } -body.platform-windows .crumbs .crumb:hover { +.crumbs .crumb:hover { -webkit-border-image: url(Images/segmentHoverChromium.png) 0 12 0 2; } -body.platform-windows .crumbs .crumb.dimmed:hover { +.crumbs .crumb.dimmed:hover { -webkit-border-image: url(Images/segmentHoverChromium.png) 0 12 0 2; } -body.platform-windows .crumbs .crumb.end:hover { +.crumbs .crumb.end:hover { -webkit-border-image: url(Images/segmentHoverEndChromium.png) 0 2 0 2; } -body.platform-windows body.drawer-visible #main-status-bar { +body.drawer-visible #main-status-bar { background-image: url(Images/statusbarResizerVertical.png), url(Images/statusbarBackgroundChromium.png); } -body.platform-windows .status-bar { +.status-bar { background-image: url(Images/statusbarBackgroundChromium.png); } -body.platform-windows button.status-bar-item { +button.status-bar-item { background-image: url(Images/statusbarButtonsChromium.png); } -body.platform-windows select.status-bar-item:active { +select.status-bar-item:active { -webkit-border-image: url(Images/statusbarMenuButtonSelectedChromium.png) 0 17 0 2; } -body.platform-windows #drawer { +#drawer { background-image: url(Images/statusbarBottomBackgroundChromium.png); } -body.platform-windows select.status-bar-item { +select.status-bar-item { -webkit-border-image: url(Images/statusbarMenuButtonChromium.png) 0 17 0 2; } diff --git a/WebKit/chromium/tests/DragImageTest.cpp b/WebKit/chromium/tests/DragImageTest.cpp index 6c9718e..7b7d4ee 100644 --- a/WebKit/chromium/tests/DragImageTest.cpp +++ b/WebKit/chromium/tests/DragImageTest.cpp @@ -118,19 +118,29 @@ TEST(DragImageTest, NonNullHandling) EXPECT_EQ(1, size.width()); EXPECT_EQ(1, size.height()); - // This is not implemented, so we don't do any output validation. dragImage = dissolveDragImageToFraction(dragImage, 0.5); ASSERT_TRUE(dragImage); deleteDragImage(dragImage); } -TEST(DragImageTest, CreateDragImageReturningNull) +TEST(DragImageTest, CreateDragImage) { - // Tests that the DrageImage implementation doesn't choke on null values - // of nativeImageForCurrentFrame(). - TestImage testImage((IntSize())); - EXPECT_FALSE(createDragImageFromImage(&testImage)); + { + // Tests that the DrageImage implementation doesn't choke on null values + // of nativeImageForCurrentFrame(). + TestImage testImage((IntSize())); + EXPECT_FALSE(createDragImageFromImage(&testImage)); + } + + { + // Tests that the drag image is a deep copy. + TestImage testImage(IntSize(1, 1)); + DragImageRef dragImage = createDragImageFromImage(&testImage); + ASSERT_TRUE(dragImage); + SkAutoLockPixels lock1(*dragImage), lock2(*testImage.nativeImageForCurrentFrame()); + EXPECT_NE(dragImage->getPixels(), testImage.nativeImageForCurrentFrame()->getPixels()); + } } } // anonymous namespace diff --git a/WebKit/efl/DefaultTheme/default.edc b/WebKit/efl/DefaultTheme/default.edc new file mode 100644 index 0000000..7e0fe48 --- /dev/null +++ b/WebKit/efl/DefaultTheme/default.edc @@ -0,0 +1,76 @@ +/* + Copyright (C) 2008,2009 INdT - Instituto Nokia de Tecnologia + Copyright (C) 2009,2010 ProFUSION embedded systems + Copyright (C) 2009,2010 Samsung Electronics + + This file 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 file 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. +*/ + +color_classes { + color_class { + name: "webkit/selection/active"; + color: 255 255 255 255; /* foreground */ + color2: 32 0 200 255; /* background */ + } + color_class { + name: "webkit/selection/inactive"; + color: 255 255 255 255; /* foreground */ + color2: 128 0 255 128; /* background */ + } + color_class { + name: "webkit/focus_ring"; + color: 26 182 240 255; /* foreground */ + /* no background, consider transparent */ + } + color_class { + name: "webkit/button/text"; + color: 32 32 32 255; + /* no background, consider transparent */ + } + color_class { + name: "webkit/combo/text"; + color: 32 32 32 255; + /* no background, consider transparent */ + } + color_class { + name: "webkit/entry/text"; + color: 32 32 32 255; + /* no background, consider transparent */ + } + color_class { + name: "webkit/search/text"; + color: 32 32 32 255; + /* no background, consider transparent */ + } +} + +collections { + group { name: "webkit/base"; + /* specific colors and all, used to listen for color_class changes */ + } + +#include "widget/button/button.edc" +#include "widget/entry/entry.edc" +#include "widget/scrollbar/scrollbar.edc" +#include "widget/radio/radio.edc" +#include "widget/check/check.edc" +#include "widget/entry/entry.edc" +#include "widget/combo/combo.edc" +#include "widget/file/file.edc" +#include "widget/search/field/search_field.edc" +#include "widget/search/cancel/search_cancel.edc" +#include "widget/search/decoration/search_decoration.edc" +} diff --git a/WebKit/efl/DefaultTheme/widget/button/button.edc b/WebKit/efl/DefaultTheme/widget/button/button.edc new file mode 100644 index 0000000..603daa0 --- /dev/null +++ b/WebKit/efl/DefaultTheme/widget/button/button.edc @@ -0,0 +1,176 @@ +/* + Copyright (C) 2008,2009 INdT - Instituto Nokia de Tecnologia + Copyright (C) 2009,2010 ProFUSION embedded systems + Copyright (C) 2009,2010 Samsung Electronics + + This file 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 file 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. +*/ + + group { + name: "webkit/widget/button"; + + images { + image: "widget/button/img_button_normal.png" COMP; + image: "widget/button/img_button_press.png" COMP; + image: "widget/button/img_button_hover.png" COMP; + image: "widget/button/img_button_focus.png" COMP; + } + + script { + public isEnabled; + public isPressed; + public isChecked; + public isFocused; + public isHovered; + + public show() { + + if (get_int(isEnabled) == 1) { + set_state(PART:"button", "default", 0.0); + if (get_int(isFocused) == 1) { + set_state(PART:"button", "focused", 0.0); + if (get_int(isPressed) == 1) + set_state(PART:"button", "pressed", 0.0); + } + else if (get_int(isHovered) == 1) { + set_state(PART:"button", "hovered", 0.0); + if (get_int(isPressed) == 1) + set_state(PART:"button", "pressed", 0.0); + + } + } + else + set_state(PART:"button", "disabled", 0.0); + } + } + + parts { + + part { + name: "button"; + type: IMAGE; + description { + state: "default" 0.0; + min: 25 10; + image { + normal: "widget/button/img_button_normal.png"; + border: 6 6 6 6; + } + } + description { + state: "pressed" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/button/img_button_press.png"; + border: 8 8 8 8; + } + } + description { + state: "disabled" 0.0; + inherit: "default" 0.0; + color: 255 255 255 150; + } + description { + state: "hovered" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/button/img_button_hover.png"; + border: 6 6 6 6; + } + } + description { + state: "focused" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/button/img_button_focus.png"; + border: 6 6 6 6; + } + } + } + + part { + name: "text_confinement"; + type: RECT; + description { + state: "default" 0.0; + color: 0 0 0 0; + rel1 { + relative: 0.0 0.0; + offset: 10 5; + } + rel2 { + relative: 1.0 1.0; + offset: -11 -6; + } + } + } + } + + programs { + program { + name: "enabled"; + signal: "enabled"; + script { + set_int(isEnabled, 1); + show(); + } + } + program { + name: "pressed"; + signal: "pressed"; + script { + set_int(isPressed, 1); + show(); + } + } + program { + name: "checked"; + signal: "checked"; + script { + set_int(isChecked, 1); + show(); + } + } + program { + name: "focused"; + signal: "focused"; + script { + set_int(isFocused, 1); + show(); + } + } + program { + name: "hovered"; + signal: "hovered"; + script { + set_int(isHovered, 1); + show(); + } + } + program { + name: "reset"; + signal: "reset"; + script { + set_int(isEnabled, 0); + set_int(isPressed, 0); + set_int(isChecked, 0); + set_int(isFocused, 0); + set_int(isHovered, 0); + show(); + } + } + } + } diff --git a/WebKit/efl/DefaultTheme/widget/check/check.edc b/WebKit/efl/DefaultTheme/widget/check/check.edc new file mode 100644 index 0000000..86490f6 --- /dev/null +++ b/WebKit/efl/DefaultTheme/widget/check/check.edc @@ -0,0 +1,181 @@ +/* + Copyright (C) 2008,2009 INdT - Instituto Nokia de Tecnologia + Copyright (C) 2009,2010 ProFUSION embedded systems + Copyright (C) 2009,2010 Samsung Electronics + + This file 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 file 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. +*/ + + group { + + name: "webkit/widget/checkbox"; + min: 14 14; + + images { + image: "widget/check/img_check_on.png" COMP; + image: "widget/check/img_check_off.png" COMP; + image: "widget/check/img_check_off_focus.png" COMP; + image: "widget/check/img_check_on_focus.png" COMP; + image: "widget/check/img_check_off_hover.png" COMP; + image: "widget/check/img_check_on_hover.png" COMP; + } + + script { + public isEnabled; + public isPressed; + public isChecked; + public isFocused; + public isHovered; + + public show() { + if (get_int(isEnabled) == 1) { + set_state(PART:"check_button", "default", 0.0); + if (get_int(isChecked) == 1) { + set_state(PART:"check_button", "enabled_checked", 0.0); + if (get_int(isFocused) == 1) + set_state(PART:"check_button", "focus_checked", 0.0); + if (get_int(isHovered) == 1 && get_int(isFocused) == 0) + set_state(PART:"check_button", "hovered_checked", 0.0); + } + else { + if (get_int(isFocused) == 1) + set_state(PART:"check_button", "focused", 0.0); + if (get_int(isHovered) == 1 && get_int(isFocused) == 0) + set_state(PART:"check_button", "hovered", 0.0); + } + } + else { + set_state(PART:"check_button", "disabled", 0.0); + if (get_int(isChecked) == 1) + set_state(PART:"check_button", "disabled_checked", 0.0); + } + } + } + + parts { + part { + name: "check_button"; + type: IMAGE; + description { + state: "default" 0.0; + min: 14 14; + max: 14 14; + image { + normal: "widget/check/img_check_off.png"; + } + } + description { + state: "enabled_checked" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/check/img_check_on.png"; + } + } + description { + state: "disabled_checked" 0.0; + inherit: "enabled_checked" 0.0; + color: 255 255 255 150; + } + description { + state: "disabled" 0.0; + inherit: "default" 0.0; + color: 255 255 255 150; + } + description { + state: "hovered_checked" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/check/img_check_on_hover.png"; + } + } + description { + state: "hovered" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/check/img_check_off_hover.png"; + } + } + description { + state: "focus_checked" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/check/img_check_on_focus.png"; + } + } + description { + state: "focused" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/check/img_check_off_focus.png"; + } + } + } + } + programs { + program { + name: "enabled"; + signal: "enabled"; + script { + set_int(isEnabled, 1); + show(); + } + } + program { + name: "pressed"; + signal: "pressed"; + script { + set_int(isPressed, 1); + show(); + } + } + program { + name: "checked"; + signal: "checked"; + script { + set_int(isChecked, 1); + show(); + } + } + program { + name: "focused"; + signal: "focused"; + script { + set_int(isFocused, 1); + show(); + } + } + program { + name: "hovered"; + signal: "hovered"; + script { + set_int(isHovered, 1); + show(); + } + } + program { + name: "reset"; + signal: "reset"; + script { + set_int(isEnabled, 0); + set_int(isPressed, 0); + set_int(isChecked, 0); + set_int(isFocused, 0); + set_int(isHovered, 0); + show(); + } + } + } + } diff --git a/WebKit/efl/DefaultTheme/widget/combo/combo.edc b/WebKit/efl/DefaultTheme/widget/combo/combo.edc new file mode 100644 index 0000000..9c436cc --- /dev/null +++ b/WebKit/efl/DefaultTheme/widget/combo/combo.edc @@ -0,0 +1,306 @@ +/* + Copyright (C) 2008,2009 INdT - Instituto Nokia de Tecnologia + Copyright (C) 2009,2010 ProFUSION embedded systems + Copyright (C) 2009,2010 Samsung Electronics + + This file 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 file 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. +*/ + +group { + name: "webkit/widget/combo"; + + images { + image: "widget/combo/combo_normal.png" COMP; + image: "widget/combo/combo_normal_button.png" COMP; + image: "widget/combo/combo_hover.png" COMP; + image: "widget/combo/combo_hover_button.png" COMP; + image: "widget/combo/combo_focus.png" COMP; + image: "widget/combo/combo_focus_button.png" COMP; + image: "widget/combo/combo_press.png" COMP; + image: "widget/combo/combo_press_button.png" COMP; + image: "widget/combo/icon.png" COMP; + } + + script { + public isEnabled; + public isPressed; + public isChecked; + public isFocused; + public isHovered; + + public show() { + if (get_int(isEnabled) == 1) { + set_state(PART:"combo", "default", 0.0); + set_state(PART:"combo_button", "default", 0.0); + set_state(PART:"combo_button_icon", "default", 0.0); + if (get_int(isFocused) == 1) { + set_state(PART:"combo", "focused", 0.0); + set_state(PART:"combo_button", "focused", 0.0); + if (get_int(isPressed) == 1) { + set_state(PART:"combo", "pressed", 0.0); + set_state(PART:"combo_button", "pressed", 0.0); + } + } + else if (get_int(isHovered) == 1) { + set_state(PART:"combo", "hovered", 0.0); + set_state(PART:"combo_button", "hovered", 0.0); + if (get_int(isPressed) == 1) { + set_state(PART:"combo", "pressed", 0.0); + set_state(PART:"combo_button", "pressed", 0.0); + } + } + } + else { + set_state(PART:"combo", "disabled", 0.0); + set_state(PART:"combo_button", "disabled", 0.0); + set_state(PART:"combo_button_icon", "disabled", 0.0); + } + } + } + + parts { + part { + name: "clipper"; + type: RECT; + description { + min: 35 27; + state: "default" 0.0; + } + } + + part { + name: "combo_clipper"; + type: RECT; + clip_to: "clipper"; + description { + state: "default" 0.0; + rel1.to: "clipper"; + rel2 { + to: "clipper"; + offset: -32 -1; + } + } + } + + part { + name: "combo"; + type: IMAGE; + clip_to: "combo_clipper"; + description { + state: "default" 0.0; + min: 36 20; + image { + normal: "widget/combo/combo_normal.png"; + border: 7 7 7 7; + } + } + description { + state: "disabled" 0.0; + inherit: "default" 0.0; + color: 255 255 255 150; + } + description { + state: "hovered" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/combo/combo_hover.png"; + border: 7 7 7 7; + } + } + description { + state: "focused" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/combo/combo_focus.png"; + border: 7 7 7 7; + } + } + description { + state: "pressed" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/combo/combo_press.png"; + border: 7 7 7 7; + } + } + } + + part { + name: "bt_combo_clipper"; + type: RECT; + clip_to: "clipper"; + description { + state: "default" 0.0; + rel1 { + to: "combo_clipper"; + relative: 1.0 0.0; + } + rel2 { + to: "clipper"; + relative: 1.0 1.0; + } + } + } + + part { + name: "combo_button"; + type: IMAGE; + clip_to: "bt_combo_clipper"; + description { + state: "default" 0.0; + min: 18 20; // 3 + 5 + image width (10), 5 + 5 + image height (10) + rel1.to: "bt_combo_clipper"; + image { + normal: "widget/combo/combo_normal_button.png"; + border: 3 5 5 5; + } + } + description { + state: "disabled" 0.0; + inherit: "default" 0.0; + color: 255 255 255 150; + rel1.to: "bt_combo_clipper"; + } + description { + state: "hovered" 0.0; + inherit: "default" 0.0; + rel1.to: "bt_combo_clipper"; + image { + normal: "widget/combo/combo_hover_button.png"; + border: 3 5 5 5; + } + } + description { + state: "focused" 0.0; + inherit: "default" 0.0; + rel1.to: "bt_combo_clipper"; + image { + normal: "widget/combo/combo_focus_button.png"; + border: 6 7 7 7; + } + } + description { + state: "pressed" 0.0; + inherit: "default" 0.0; + rel1.to: "bt_combo_clipper"; + image { + normal: "widget/combo/combo_press_button.png"; + border: 6 8 8 8; + } + } + } + + + part { + name: "combo_button_icon"; + type: IMAGE; + clip_to: "bt_combo_clipper"; + description { + state: "default" 0.0; + min: 17 13; + max: 17 13; + color: 255 255 255 150; + rel1 { + to: "bt_combo_clipper"; + relative: 0.5 0.5; + offset: 0 1; + } + rel2 { + to: "bt_combo_clipper"; + relative: 0.5 0.5; + } + fixed: 1 1; + image { + normal: "widget/combo/icon.png"; + border: 5 5 0 0; + } + } + description { + state: "disabled" 0.0; + inherit: "default" 0.0; + color: 255 255 255 50; + image { + normal: "widget/combo/icon.png"; + border: 5 5 0 0; + } + } + } + + part { + name: "text_confinement"; + type: RECT; + description { + state: "default" 0.0; + color: 0 0 0 0; + rel1 { + to: "combo_clipper"; + offset: 10 5; + } + rel2 { + to: "combo_clipper"; + offset: -6 -6; + } + } + } + } + + programs { + program { + name: "enabled"; + signal: "enabled"; + script { + set_int(isEnabled, 1); + show(); + } + } + program { + name: "pressed"; + signal: "pressed"; + script { + set_int(isPressed, 1); + show(); + } + } + program { + name: "focused"; + signal: "focused"; + script { + set_int(isFocused, 1); + show(); + } + } + program { + name: "hovered"; + signal: "hovered"; + script { + set_int(isHovered, 1); + show(); + } + } + program { + name: "reset"; + signal: "reset"; + script { + set_int(isEnabled, 0); + set_int(isPressed, 0); + set_int(isChecked, 0); + set_int(isFocused, 0); + set_int(isHovered, 0); + show(); + } + } + } +} diff --git a/WebKit/efl/DefaultTheme/widget/entry/entry.edc b/WebKit/efl/DefaultTheme/widget/entry/entry.edc new file mode 100644 index 0000000..613ee59 --- /dev/null +++ b/WebKit/efl/DefaultTheme/widget/entry/entry.edc @@ -0,0 +1,167 @@ +/* + Copyright (C) 2008,2009 INdT - Instituto Nokia de Tecnologia + Copyright (C) 2009,2010 ProFUSION embedded systems + Copyright (C) 2009,2010 Samsung Electronics + + This file 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 file 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. +*/ + + group { + name: "webkit/widget/entry"; + + images { + image: "widget/entry/img_normal.png" COMP; + image: "widget/entry/img_focused.png" COMP; + image: "widget/entry/img_hovered.png" COMP; + } + + script { + public isEnabled; + public isPressed; + public isChecked; + public isFocused; + public isHovered; + + public show() { + if (get_int(isEnabled) == 1) { + set_state(PART:"entry", "default", 0.0); + if (get_int(isPressed) == 1) + set_state(PART:"entry", "pressed", 0.0); + if (get_int(isFocused) == 1) + set_state(PART:"entry", "focused", 0.0); + if (get_int(isHovered) == 1 && get_int(isFocused) == 0) + set_state(PART:"entry", "hovered", 0.0); + } + else + set_state(PART:"entry", "disabled", 0.0); + } + + } + + parts { + part { + name: "entry"; + type: IMAGE; + description { + state: "default" 0.0; + min: 14 14; + rel1 { + relative: 0.0 0.0; + offset: 0 0; + } + rel2 { + relative: 1.0 1.0; + offset: -1 -1; + } + image { + normal: "widget/entry/img_normal.png"; + border: 7 7 7 7; + } + } + description { + state: "disabled" 0.0; + inherit: "default" 0.0; + color: 255 255 255 150; + } + description { + state: "focused" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/entry/img_focused.png"; + border: 7 7 7 7; + } + } + description { + state: "pressed" 0.0; + inherit: "focused" 0.0; + } + description { + state: "hovered" 0.0; + inherit: "focused" 0.0; + image { + normal: "widget/entry/img_hovered.png"; + border: 7 7 7 7; + } + } + } + + part { + name: "text_confinement"; + type: RECT; + description { + state: "default" 0.0; + color: 0 0 0 0; + rel1.offset: 4 6; // <- 6 because of the blink cursor + rel2.offset: -4 -5; // <- due to the image + } + } + } + + programs { + program { + name: "enabled"; + signal: "enabled"; + script { + set_int(isEnabled, 1); + show(); + } + } + program { + name: "pressed"; + signal: "pressed"; + script { + set_int(isPressed, 1); + show(); + } + } + program { + name: "checked"; + signal: "checked"; + script { + set_int(isChecked, 1); + show(); + } + } + program { + name: "focused"; + signal: "focused"; + script { + set_int(isFocused, 1); + show(); + } + } + program { + name: "hovered"; + signal: "hovered"; + script { + set_int(isHovered, 1); + show(); + } + } + program { + name: "reset"; + signal: "reset"; + script { + set_int(isEnabled, 0); + set_int(isPressed, 0); + set_int(isChecked, 0); + set_int(isFocused, 0); + set_int(isHovered, 0); + show(); + } + } + } + } diff --git a/WebKit/efl/DefaultTheme/widget/file/file.edc b/WebKit/efl/DefaultTheme/widget/file/file.edc new file mode 100644 index 0000000..40afcc7 --- /dev/null +++ b/WebKit/efl/DefaultTheme/widget/file/file.edc @@ -0,0 +1,148 @@ +/* + Copyright (C) 2008,2009 INdT - Instituto Nokia de Tecnologia + Copyright (C) 2009,2010 ProFUSION embedded systems + Copyright (C) 2009,2010 Samsung Electronics + + This file 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 file 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. +*/ + +group { + name: "webkit/widget/file"; + + images { + image: "widget/file/file_normal.png" COMP; + image: "widget/file/file_hover.png" COMP; + image: "widget/file/file_focus.png" COMP; + image: "widget/file/file_press.png" COMP; + } + + script { + public isEnabled; + public isPressed; + public isChecked; + public isFocused; + public isHovered; + + public show() { + if (get_int(isEnabled) == 1) { + set_state(PART:"file", "default", 0.0); + if (get_int(isFocused) == 1) { + set_state(PART:"file", "focused", 0.0); + if (get_int(isPressed) == 1) + set_state(PART:"file", "pressed", 0.0); + } + else if (get_int(isHovered) == 1) { + set_state(PART:"file", "hovered", 0.0); + if (get_int(isPressed) == 1) + set_state(PART:"file", "pressed", 0.0); + + } + } + else + set_state(PART:"file", "disabled", 0.0); + } + } + + parts { + part { + name: "file"; + type: IMAGE; + description { + state: "default" 0.0; + image { + normal: "widget/file/file_normal.png"; + border: 8 8 8 8; + } + } + description { + state: "disabled" 0.0; + inherit: "default" 0.0; + color: 255 255 255 150; + } + description { + state: "hovered" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/file/file_hover.png"; + border: 8 8 8 8; + } + } + description { + state: "focused" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/file/file_focus.png"; + border: 8 8 8 8; + } + } + description { + state: "pressed" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/file/file_press.png"; + border: 8 8 8 8; + } + } + } + } + + programs { + program { + name: "enabled"; + signal: "enabled"; + script { + set_int(isEnabled, 1); + show(); + } + } + program { + name: "pressed"; + signal: "pressed"; + script { + set_int(isPressed, 1); + show(); + } + } + program { + name: "focused"; + signal: "focused"; + script { + set_int(isFocused, 1); + show(); + } + } + program { + name: "hovered"; + signal: "hovered"; + script { + set_int(isHovered, 1); + show(); + } + } + program { + name: "reset"; + signal: "reset"; + script { + set_int(isEnabled, 0); + set_int(isPressed, 0); + set_int(isChecked, 0); + set_int(isFocused, 0); + set_int(isHovered, 0); + show(); + } + } + } + } diff --git a/WebKit/efl/DefaultTheme/widget/radio/radio.edc b/WebKit/efl/DefaultTheme/widget/radio/radio.edc new file mode 100644 index 0000000..38a6da9 --- /dev/null +++ b/WebKit/efl/DefaultTheme/widget/radio/radio.edc @@ -0,0 +1,181 @@ +/* + Copyright (C) 2008,2009 INdT - Instituto Nokia de Tecnologia + Copyright (C) 2009,2010 ProFUSION embedded systems + Copyright (C) 2009,2010 Samsung Electronics + + This file 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 file 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. +*/ + + group { + name: "webkit/widget/radio"; + min: 16 16; + + images { + image: "widget/radio/img_radio_on.png" COMP; + image: "widget/radio/img_radio_off.png" COMP; + image: "widget/radio/img_radio_on_focus.png" COMP; + image: "widget/radio/img_radio_off_focus.png" COMP; + image: "widget/radio/img_radio_on_hover.png" COMP; + image: "widget/radio/img_radio_off_hover.png" COMP; + } + + script { + public isEnabled; + public isPressed; + public isChecked; + public isFocused; + public isHovered; + + public show() { + if (get_int(isEnabled) == 1) { + set_state(PART:"radio_button", "default", 0.0); + if (get_int(isChecked) == 1) { + set_state(PART:"radio_button", "enabled_checked", 0.0); + if (get_int(isFocused) == 1) + set_state(PART:"radio_button", "focus_checked", 0.0); + if (get_int(isHovered) == 1 && get_int(isFocused) == 0) + set_state(PART:"radio_button", "hovered_checked", 0.0); + } + else { + if (get_int(isFocused) == 1) + set_state(PART:"radio_button", "focused", 0.0); + if (get_int(isHovered) == 1 && get_int(isFocused) == 0) + set_state(PART:"radio_button", "hovered", 0.0); + } + } + else { + set_state(PART:"radio_button", "disabled", 0.0); + if (get_int(isChecked) == 1) + set_state(PART:"radio_button", "disabled_checked", 0.0); + } + } + } + + parts { + part { + name: "radio_button"; + type: IMAGE; + description { + state: "default" 0.0; + min: 16 16; + max: 16 16; + image { + normal: "widget/radio/img_radio_off.png"; + } + } + description { + state: "enabled_checked" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/radio/img_radio_on.png"; + } + } + description { + state: "disabled_checked" 0.0; + inherit: "enabled_checked" 0.0; + color: 255 255 255 150; + } + description { + state: "disabled" 0.0; + inherit: "default" 0.0; + color: 255 255 255 150; + } + description { + state: "hovered_checked" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/radio/img_radio_on_hover.png"; + } + } + description { + state: "hovered" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/radio/img_radio_off_hover.png"; + } + } + description { + state: "focus_checked" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/radio/img_radio_on_focus.png"; + } + } + description { + state: "focused" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/radio/img_radio_off_focus.png"; + } + } + } + } + + programs { + program { + name: "enabled"; + signal: "enabled"; + script { + set_int(isEnabled, 1); + show(); + } + } + program { + name: "pressed"; + signal: "pressed"; + script { + set_int(isPressed, 1); + show(); + } + } + program { + name: "checked"; + signal: "checked"; + script { + set_int(isChecked, 1); + show(); + } + } + program { + name: "focused"; + signal: "focused"; + script { + set_int(isFocused, 1); + show(); + } + } + program { + name: "hovered"; + signal: "hovered"; + script { + set_int(isHovered, 1); + show(); + } + } + program { + name: "reset"; + signal: "reset"; + script { + set_int(isEnabled, 0); + set_int(isPressed, 0); + set_int(isChecked, 0); + set_int(isFocused, 0); + set_int(isHovered, 0); + show(); + } + } + } + } diff --git a/WebKit/efl/DefaultTheme/widget/scrollbar/scrollbar.edc b/WebKit/efl/DefaultTheme/widget/scrollbar/scrollbar.edc new file mode 100644 index 0000000..4f59784 --- /dev/null +++ b/WebKit/efl/DefaultTheme/widget/scrollbar/scrollbar.edc @@ -0,0 +1,317 @@ +/* + Copyright (C) 2008,2009 INdT - Instituto Nokia de Tecnologia + Copyright (C) 2009,2010 ProFUSION embedded systems + Copyright (C) 2009,2010 Samsung Electronics + + This file 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 file 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. +*/ + +group { + name: "scrollbar.vertical"; + + min: 10 0; /* if > 0, this is the minimum size that will be allocated. + * If wants to draw on top, just overflow usign edje's rel1/rel2 + */ + + images { + image: "widget/scrollbar/scrollbar_v.png" COMP; + image: "widget/scrollbar/scrollbar_knob_v.png" COMP; + } + + script { + public hide_timer; + + public hide_timer_cb(val) { + run_program(PROGRAM:"hide"); + return 0; + } + + public hide_timer_stop() { + new id = get_int(hide_timer); + if (id <= 0) + return; + + cancel_timer(id); + set_int(hide_timer, 0); + } + + public hide_timer_start() { + set_int(hide_timer, timer(1.0, "hide_timer_cb", 0)); + } + + public message(Msg_Type:type, id, ...) { + if ((id == 0) && (type == MSG_FLOAT_SET)) { + new Float:vy, Float:sy; + + vy = getfarg(2); + sy = getfarg(3); + + if (vy >= 0.0) { + set_drag_size(PART:"img.knob", 1.0, sy); + set_drag(PART:"img.knob", 0.0, vy); + run_program(PROGRAM:"show"); + } else + run_program(PROGRAM:"hide"); + + hide_timer_stop(); + hide_timer_start(); + } + } + + public update_drag_pos() { + new Float:x, Float:y; + get_drag(PART:"img.knob", x, y); + send_message(MSG_FLOAT, 1, y); + } + } + + parts { + part { + name: "rect.base"; + type: RECT; + description { + min: 10 0; + max: 10 999999; + state: "default" 0.0; + color: 255 255 255 0; + } + } + part { + name: "rect.clipper"; + type: RECT; + description { + state: "default" 0.0; + color: 255 255 255 255; + } + description { + state: "hidden" 0.0; + color: 255 255 255 128; + } + } + + part { + name: "img.scrollbar"; + type: IMAGE; + mouse_events: 0; + clip_to: "rect.clipper"; + description { + state: "default" 0.0; + image { + normal: "widget/scrollbar/scrollbar_v.png"; + border: 0 0 6 6; + } + } + } + + part { + name: "img.knob"; + type: IMAGE; + mouse_events: 1; + clip_to: "rect.clipper"; + dragable { + x: 0 0 0; + y: 1 1 0; + confine: "rect.base"; + } + description { + state: "default" 0.0; + min: 10 10; + max: 10 999999; + image { + normal: "widget/scrollbar/scrollbar_knob_v.png"; + border: 0 0 6 6; + } + } + } + } + programs { + program { + name: "load"; + signal: "load"; + action: STATE_SET "hidden" 0.0; + target: "rect.clipper"; + } + program { + name: "hide"; + action: STATE_SET "hidden" 0.0; + transition: ACCELERATE 0.5; + target: "rect.clipper"; + } + + program { + name: "show"; + action: STATE_SET "default" 0.0; + target: "rect.clipper"; + } + + program { + name: "dragged"; + signal: "drag"; + source: "img.knob"; + script { + update_drag_pos(); + } + } + } +} + +group { + name: "scrollbar.horizontal"; + + min: 0 10; /* if > 0, this is the minimum size that will be allocated. + * If wants to draw on top, just overflow usign edje's rel1/rel2 + */ + + images { + image: "widget/scrollbar/scrollbar_h.png" COMP; + image: "widget/scrollbar/scrollbar_knob_h.png" COMP; + } + + script { + public hide_timer; + + public hide_timer_cb(val) { + run_program(PROGRAM:"hide"); + return 0; + } + + public hide_timer_stop() { + new id = get_int(hide_timer); + if (id <= 0) + return; + + cancel_timer(id); + set_int(hide_timer, 0); + } + + public hide_timer_start() { + set_int(hide_timer, timer(1.0, "hide_timer_cb", 0)); + } + + public message(Msg_Type:type, id, ...) { + if ((id == 0) && (type == MSG_FLOAT_SET)) { + new Float:vx, Float:sx; + + vx = getfarg(2); + sx = getfarg(3); + + if (vx >= 0.0) { + set_drag_size(PART:"img.knob", sx, 1.0); + set_drag(PART:"img.knob", vx, 0.0); + run_program(PROGRAM:"show"); + } else + run_program(PROGRAM:"hide"); + + hide_timer_stop(); + hide_timer_start(); + } + } + + public update_drag_pos() { + new Float:x, Float:y; + get_drag(PART:"img.knob", x, y); + send_message(MSG_FLOAT, 1, x); + } + } + + parts { + part { + name: "rect.base"; + type: RECT; + description { + state: "default" 0.0; + min: 0 10; + max: 999999 10; + color: 255 255 255 0; + } + } + part { + name: "rect.clipper"; + type: RECT; + description { + state: "default" 0.0; + color: 255 255 255 255; + } + description { + state: "hidden" 0.0; + color: 255 255 255 128; + } + } + + part { + name: "img.scrollbar"; + type: IMAGE; + mouse_events: 0; + clip_to: "rect.clipper"; + description { + state: "default" 0.0; + image { + normal: "widget/scrollbar/scrollbar_h.png"; + border: 6 6 0 0; + } + } + } + + part { + name: "img.knob"; + type: IMAGE; + mouse_events: 1; + clip_to: "rect.clipper"; + dragable { + x: 1 1 0; + y: 0 0 0; + confine: "rect.base"; + } + description { + state: "default" 0.0; + min: 10 10; + image { + normal: "widget/scrollbar/scrollbar_knob_h.png"; + border: 6 6 0 0; + } + } + } + } + programs { + program { + name: "load"; + signal: "load"; + action: STATE_SET "hidden" 0.0; + target: "rect.clipper"; + } + program { + name: "hide"; + action: STATE_SET "hidden" 0.0; + transition: ACCELERATE 0.5; + target: "rect.clipper"; + } + + program { + name: "show"; + action: STATE_SET "default" 0.0; + target: "rect.clipper"; + } + + program { + name: "dragged"; + signal: "drag"; + source: "img.knob"; + script { + update_drag_pos(); + } + } + } +} diff --git a/WebKit/efl/DefaultTheme/widget/search/cancel/search_cancel.edc b/WebKit/efl/DefaultTheme/widget/search/cancel/search_cancel.edc new file mode 100644 index 0000000..d4a1a20 --- /dev/null +++ b/WebKit/efl/DefaultTheme/widget/search/cancel/search_cancel.edc @@ -0,0 +1,131 @@ +/* + Copyright (C) 2008,2009 INdT - Instituto Nokia de Tecnologia + Copyright (C) 2009,2010 ProFUSION embedded systems + Copyright (C) 2009,2010 Samsung Electronics + + This file 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 file 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. +*/ + +group { + name: "webkit/widget/search/cancel_button"; + alias: "webkit/widget/search/results_button"; // TODO + + images { + image: "widget/search/cancel/cancel_normal_button2.png" COMP; + } + + script { + public isEnabled; + public isPressed; + public isChecked; + public isFocused; + public isHovered; + + public show() { + if (get_int(isEnabled) == 1) { + set_state(PART:"cancel_button", "default", 0.0); + if (get_int(isFocused) == 1) + set_state(PART:"cancel_button", "focused", 0.0); + if (get_int(isPressed) == 1) + set_state(PART:"cancel_button", "pressed", 0.0); + if (get_int(isHovered) == 1) + set_state(PART:"cancel_button", "hovered", 0.0); + } + else + set_state(PART:"cancel_button", "disabled", 0.0); + } + } + + parts { + part { + name: "cancel_button"; + type: IMAGE; + description { + state: "default" 0.0; + min: 21 20; + rel1.offset: 0 -6; + rel2.offset: -1 0; + image { + normal: "widget/search/cancel/cancel_normal_button2.png"; + } + } + description { + state: "disabled" 0.0; + inherit: "default" 0.0; + color: 255 255 255 150; + } + description { + state: "hovered" 0.0; + inherit: "default" 0.0; + } + description { + state: "focused" 0.0; + inherit: "default" 0.0; + } + description { + state: "pressed" 0.0; + inherit: "default" 0.0; + } + } + } + + programs { + program { + name: "enabled"; + signal: "enabled"; + script { + set_int(isEnabled, 1); + show(); + } + } + program { + name: "pressed"; + signal: "pressed"; + script { + set_int(isPressed, 1); + show(); + } + } + program { + name: "focused"; + signal: "focused"; + script { + set_int(isFocused, 1); + show(); + } + } + program { + name: "hovered"; + signal: "hovered"; + script { + set_int(isHovered, 1); + show(); + } + } + program { + name: "reset"; + signal: "reset"; + script { + set_int(isEnabled, 0); + set_int(isPressed, 0); + set_int(isChecked, 0); + set_int(isFocused, 0); + set_int(isHovered, 0); + show(); + } + } + } +} diff --git a/WebKit/efl/DefaultTheme/widget/search/decoration/search_decoration.edc b/WebKit/efl/DefaultTheme/widget/search/decoration/search_decoration.edc new file mode 100644 index 0000000..4159138 --- /dev/null +++ b/WebKit/efl/DefaultTheme/widget/search/decoration/search_decoration.edc @@ -0,0 +1,132 @@ +/* + Copyright (C) 2008,2009 INdT - Instituto Nokia de Tecnologia + Copyright (C) 2009,2010 ProFUSION embedded systems + Copyright (C) 2009,2010 Samsung Electronics + + This file 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 file 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. +*/ + +group { + name: "webkit/widget/search/decoration"; + alias: "webkit/widget/search/results_decoration"; //TODO + + images { + image: "widget/search/decoration/decoration_normal_button.png" COMP; + } + + script { + public isEnabled; + public isPressed; + public isChecked; + public isFocused; + public isHovered; + + public show() { + if (get_int(isEnabled) == 1) { + set_state(PART:"decoration", "default", 0.0); + if (get_int(isFocused) == 1) + set_state(PART:"decoration", "focused", 0.0); + if (get_int(isPressed) == 1) + set_state(PART:"decoration", "pressed", 0.0); + if (get_int(isHovered) == 1) + set_state(PART:"decoration", "hovered", 0.0); + } + else + set_state(PART:"decoration", "disabled", 0.0); + } + } + + parts { + part { + name: "decoration"; + type: IMAGE; + description { + state: "default" 0.0; + min: 20 20; + rel1.offset: 0 -4; + rel2.offset: -1 0; + image { + normal: "widget/search/decoration/decoration_normal_button.png"; + border: 0 0 8 8; + } + } + description { + state: "disabled" 0.0; + inherit: "default" 0.0; + color: 255 255 255 150; + } + description { + state: "hovered" 0.0; + inherit: "default" 0.0; + } + description { + state: "focused" 0.0; + inherit: "default" 0.0; + } + description { + state: "pressed" 0.0; + inherit: "default" 0.0; + } + } + } + + programs { + program { + name: "enabled"; + signal: "enabled"; + script { + set_int(isEnabled, 1); + show(); + } + } + program { + name: "pressed"; + signal: "pressed"; + script { + set_int(isPressed, 1); + show(); + } + } + program { + name: "focused"; + signal: "focused"; + script { + set_int(isFocused, 1); + show(); + } + } + program { + name: "hovered"; + signal: "hovered"; + script { + set_int(isHovered, 1); + show(); + } + } + program { + name: "reset"; + signal: "reset"; + script { + set_int(isEnabled, 0); + set_int(isPressed, 0); + set_int(isChecked, 0); + set_int(isFocused, 0); + set_int(isHovered, 0); + show(); + } + } + } +} diff --git a/WebKit/efl/DefaultTheme/widget/search/field/search_field.edc b/WebKit/efl/DefaultTheme/widget/search/field/search_field.edc new file mode 100644 index 0000000..e9be229 --- /dev/null +++ b/WebKit/efl/DefaultTheme/widget/search/field/search_field.edc @@ -0,0 +1,151 @@ +/* + Copyright (C) 2008,2009 INdT - Instituto Nokia de Tecnologia + Copyright (C) 2009,2010 ProFUSION embedded systems + Copyright (C) 2009,2010 Samsung Electronics + + This file 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 file 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. +*/ + +group { + name: "webkit/widget/search/field"; + + images { + image: "widget/search/field/field_normal.png" COMP; + image: "widget/search/field/field_focused.png" COMP; + image: "widget/search/field/field_hovered.png" COMP; + } + + script { + public isEnabled; + public isPressed; + public isChecked; + public isFocused; + public isHovered; + + public show() { + if (get_int(isEnabled) == 1) { + set_state(PART:"search_field", "default", 0.0); + if (get_int(isFocused) == 1) + set_state(PART:"search_field", "focused", 0.0); + if (get_int(isPressed) == 1) + set_state(PART:"search_field", "pressed", 0.0); + if (get_int(isFocused) == 0 && get_int(isHovered) == 1) + set_state(PART:"search_field", "hovered", 0.0); + } + else + set_state(PART:"search_field", "disabled", 0.0); + } + } + + parts { + part { + name: "search_field"; + type: IMAGE; + description { + state: "default" 0.0; + min: 89 20; + image { + normal: "widget/search/field/field_normal.png"; + border: 8 8 8 8; + } + } + description { + state: "disabled" 0.0; + inherit: "default" 0.0; + color: 255 255 255 150; + } + description { + state: "focused" 0.0; + inherit: "default" 0.0; + image { + normal: "widget/search/field/field_focused.png"; + border: 8 8 8 8; + } + } + description { + state: "hovered" 0.0; + inherit: "focused" 0.0; + image { + normal: "widget/search/field/field_hovered.png"; + border: 8 8 8 8; + } + } + description { + state: "pressed" 0.0; + inherit: "focused" 0.0; + } + } + + part { + name: "text_confinement"; + type: RECT; + description { + state: "default" 0.0; + color: 0 0 0 0; + rel1.offset: 4 6; // <- 6 because of the blink cursor + rel2.offset: -4 -5; // <- due to the image + } + } + + } + + programs { + program { + name: "enabled"; + signal: "enabled"; + script { + set_int(isEnabled, 1); + show(); + } + } + program { + name: "pressed"; + signal: "pressed"; + script { + set_int(isPressed, 1); + show(); + } + } + program { + name: "focused"; + signal: "focused"; + script { + set_int(isFocused, 1); + show(); + } + } + program { + name: "hovered"; + signal: "hovered"; + script { + set_int(isHovered, 1); + show(); + } + } + program { + name: "reset"; + signal: "reset"; + script { + set_int(isEnabled, 0); + set_int(isPressed, 0); + set_int(isChecked, 0); + set_int(isFocused, 0); + set_int(isHovered, 0); + show(); + } + } + } + } diff --git a/WebKit/efl/EWebLauncher/main.c b/WebKit/efl/EWebLauncher/main.c index 6a9e4fb..b0c64bf 100644 --- a/WebKit/efl/EWebLauncher/main.c +++ b/WebKit/efl/EWebLauncher/main.c @@ -31,7 +31,6 @@ #include <ctype.h> #include <Ecore.h> -#include <Ecore_Data.h> #include <Ecore_Evas.h> #include <Ecore_File.h> #include <Ecore_Getopt.h> @@ -42,6 +41,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -54,8 +54,6 @@ printf(format, ##args); \ } while (0) -#define REL_THEME_PATH "../../../WebKit/efl/DefaultTheme/default.edj" - #define MIN_ZOOM_LEVEL 0 #define DEFAULT_ZOOM_LEVEL 5 #define MAX_ZOOM_LEVEL 13 @@ -136,11 +134,11 @@ typedef struct _ELauncher { const char *userAgent; } ELauncher; -void browserDestroy(Ecore_Evas *ee); -void closeWindow(Ecore_Evas *ee); -int browserCreate(const char *url, const char *theme, const char *userAgent, Eina_Rectangle geometry, const char *engine, unsigned char isFullscreen); +static void browserDestroy(Ecore_Evas *ee); +static void closeWindow(Ecore_Evas *ee); +static int browserCreate(const char *url, const char *theme, const char *userAgent, Eina_Rectangle geometry, const char *engine, unsigned char isFullscreen); -void +static void print_history(Eina_List *list) { Eina_List *l; @@ -173,7 +171,7 @@ print_history(Eina_List *list) } } -void +static void zoom_level_set(Evas_Object *webview, int level) { float factor = ((float) zoomLevels[level]) / 100.0; @@ -185,53 +183,6 @@ zoom_level_set(Evas_Object *webview, int level) ewk_view_zoom_animated_set(webview, factor, 0.5, cx, cy); } -char* -join_path(const char *base, const char *path) -{ - char separator[] = "/"; - - char tmp[PATH_MAX + 1]; - char result[PATH_MAX + 1]; - result[0] = tmp[0] = '\0'; - - char *str = strdup(path); - - char *token = NULL; - token = strtok(str, separator); - int count = 0; - do { - if (!strcmp(token, "..")) - count++; - else - strcat(tmp, token); - token = strtok(NULL, separator); - if (!token) - break; - if (tmp[0]) - strcat(tmp, separator); - } while (EINA_TRUE); - - free(str); - str = strdup(base); - - char *base_ptr; - while (count--) { - base_ptr = strrchr(str, separator[0]); - if (!base_ptr) { - free(str); - return NULL; // couldn't resolve path - } - *base_ptr = '\0'; - } - - strcat(result, str); - strcat(result, separator); - strcat(result, tmp); - free(str); - - return strdup(result); -} - static void on_ecore_evas_resize(Ecore_Evas *ee) { @@ -394,7 +345,7 @@ on_tooltip_text_set(void* user_data, Evas_Object* webview, void* event_info) info("%s\n", text); } -void +static void on_mouse_down(void* data, Evas* e, Evas_Object* webview, void* event_info) { Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down*) event_info; @@ -402,19 +353,19 @@ on_mouse_down(void* data, Evas* e, Evas_Object* webview, void* event_info) evas_object_focus_set(webview, !evas_object_focus_get(webview)); } -void +static void on_focus_out(void *data, Evas *e, Evas_Object *obj, void *event_info) { info("the webview lost keyboard focus\n"); } -void +static void on_focus_in(void *data, Evas *e, Evas_Object *obj, void *event_info) { info("the webview gained keyboard focus\n"); } -void +static void on_resized(void *data, Evas *e, Evas_Object *obj, void *event_info) { Evas_Coord w, h; @@ -422,7 +373,7 @@ on_resized(void *data, Evas *e, Evas_Object *obj, void *event_info) ewk_view_fixed_layout_size_set(obj, w, h); } -void +static void on_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info) { Evas_Event_Key_Down *ev = (Evas_Event_Key_Down*) event_info; @@ -530,7 +481,7 @@ on_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info) } } -void +static void on_browser_del(void *data, Evas *evas, Evas_Object *browser, void *event) { ELauncher *app = (ELauncher*) data; @@ -542,13 +493,13 @@ on_browser_del(void *data, Evas *evas, Evas_Object *browser, void *event) evas_object_event_callback_del(app->browser, EVAS_CALLBACK_DEL, on_browser_del); } -void +static void on_closeWindow(Ecore_Evas *ee) { browserDestroy(ee); } -int +static int quit(Eina_Bool success, const char *msg) { edje_shutdown(); @@ -565,7 +516,7 @@ quit(Eina_Bool success, const char *msg) return EXIT_SUCCESS; } -int +static int browserCreate(const char *url, const char *theme, const char *userAgent, Eina_Rectangle geometry, const char *engine, unsigned char isFullscreen) { if ((geometry.w <= 0) && (geometry.h <= 0)) { @@ -653,7 +604,7 @@ browserCreate(const char *url, const char *theme, const char *userAgent, Eina_Re return 1; } -void +static void browserDestroy(Ecore_Evas *ee) { ecore_evas_free(ee); @@ -661,7 +612,7 @@ browserDestroy(Ecore_Evas *ee) ecore_main_loop_quit(); } -void +static void closeWindow(Ecore_Evas *ee) { Eina_List *l; @@ -690,6 +641,29 @@ main_signal_exit(void *data, int ev_type, void *ev) return 1; } +static char * +findThemePath(void) +{ + const char **itr, *locations[] = { + "./default.edj", + "./WebKit/efl/DefaultTheme/default.edj", + "../WebKit/efl/DefaultTheme/default.edj", + DATA_DIR"/themes/default.edj", + NULL + }; + + for (itr = locations; *itr; itr++) { + struct stat st; + if (!stat(*itr, &st)) { + char path[PATH_MAX]; + if (realpath(*itr, path)) + return strdup(path); + } + } + + return NULL; +} + int main(int argc, char *argv[]) { @@ -750,7 +724,7 @@ main(int argc, char *argv[]) if (sudoWorkaround) strcat(getenv("HOME"), "blah"); - themePath = join_path(argv[0], REL_THEME_PATH); + themePath = findThemePath(); ewk_init(); tmp = getenv("TMPDIR"); diff --git a/WebKit/efl/WebCoreSupport/ChromeClientEfl.cpp b/WebKit/efl/WebCoreSupport/ChromeClientEfl.cpp index 1174f83..31b53c8 100644 --- a/WebKit/efl/WebCoreSupport/ChromeClientEfl.cpp +++ b/WebKit/efl/WebCoreSupport/ChromeClientEfl.cpp @@ -49,7 +49,7 @@ using namespace WebCore; -static inline Evas_Object* kit(WebCore::Frame* frame) +static inline Evas_Object* kit(Frame* frame) { if (!frame) return 0; @@ -60,7 +60,7 @@ static inline Evas_Object* kit(WebCore::Frame* frame) namespace WebCore { -ChromeClientEfl::ChromeClientEfl(Evas_Object *view) +ChromeClientEfl::ChromeClientEfl(Evas_Object* view) : m_view(view) { } @@ -213,7 +213,7 @@ bool ChromeClientEfl::canRunBeforeUnloadConfirmPanel() return true; } -bool ChromeClientEfl::runBeforeUnloadConfirmPanel(const String& message, WebCore::Frame* frame) +bool ChromeClientEfl::runBeforeUnloadConfirmPanel(const String& message, Frame* frame) { return runJavaScriptConfirm(frame, message); } @@ -274,31 +274,11 @@ IntRect ChromeClientEfl::windowResizerRect() const return IntRect(); } -void ChromeClientEfl::repaint(const IntRect& windowRect, bool contentChanged, bool immediate, bool repaintContentOnly) -{ - Evas_Coord x, y, w, h; - - if (!contentChanged) - return; - - x = windowRect.x(); - y = windowRect.y(); - w = windowRect.width(); - h = windowRect.height(); - ewk_view_repaint(m_view, x, y, w, h); -} - void ChromeClientEfl::contentsSizeChanged(Frame* frame, const IntSize& size) const { ewk_frame_contents_size_changed(kit(frame), size.width(), size.height()); } -bool ChromeClientEfl::scroll(const IntSize& delta, const IntRect& scrollViewRect, const IntRect& clipRect, bool canBlit, bool isMainFrame) -{ - ewk_view_scroll(m_view, delta.width(), delta.height(), scrollViewRect.x(), scrollViewRect.y(), scrollViewRect.width(), scrollViewRect.height(), clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height(), isMainFrame); - return canBlit; -} - IntRect ChromeClientEfl::windowToScreen(const IntRect& rect) const { notImplemented(); @@ -327,7 +307,7 @@ void ChromeClientEfl::mouseDidMoveOverElement(const HitTestResult& hit, unsigned if (isLink) { KURL url = hit.absoluteLinkURL(); if (!url.isEmpty() && url != m_hoveredLinkURL) { - const char *link[2]; + const char* link[2]; TextDirection dir; CString urlStr = url.prettyURL().utf8(); CString titleStr = hit.title(dir).utf8(); @@ -370,7 +350,7 @@ void ChromeClientEfl::exceededDatabaseQuota(Frame* frame, const String& database ewk_view_exceeded_database_quota(m_view, kit(frame), databaseName.utf8().data()); } -void ChromeClientEfl::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChooser) +void ChromeClientEfl::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> prpFileChooser) { notImplemented(); } @@ -392,4 +372,60 @@ void ChromeClientEfl::requestGeolocationPermissionForFrame(Frame*, Geolocation*) notImplemented(); } +void ChromeClientEfl::cancelGeolocationPermissionRequestForFrame(Frame*, Geolocation*) +{ + notImplemented(); +} + +void ChromeClientEfl::cancelGeolocationPermissionForFrame(Frame*, Geolocation*) +{ + notImplemented(); +} + +void ChromeClientEfl::invalidateContents(const IntRect& updateRect, bool immediate) +{ + notImplemented(); +} + +void ChromeClientEfl::invalidateWindow(const IntRect& updateRect, bool immediate) +{ + notImplemented(); +} + +void ChromeClientEfl::invalidateContentsAndWindow(const IntRect& updateRect, bool immediate) +{ + Evas_Coord x, y, w, h; + + x = updateRect.x(); + y = updateRect.y(); + w = updateRect.width(); + h = updateRect.height(); + ewk_view_repaint(m_view, x, y, w, h); +} + +void ChromeClientEfl::invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate) +{ + invalidateContentsAndWindow(updateRect, immediate); +} + +void ChromeClientEfl::scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) +{ + ewk_view_scroll(m_view, scrollDelta.width(), scrollDelta.height(), rectToScroll.x(), rectToScroll.y(), rectToScroll.width(), rectToScroll.height(), clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height(), EINA_TRUE); +} + +void ChromeClientEfl::cancelGeolocationPermissionRequestForFrame(Frame*) +{ + notImplemented(); +} + +void ChromeClientEfl::iconForFiles(const Vector<String, 0u>&, PassRefPtr<FileChooser>) +{ + notImplemented(); +} + +void ChromeClientEfl::chooseIconForFiles(const Vector<String>&, FileChooser*) +{ + notImplemented(); +} + } diff --git a/WebKit/efl/WebCoreSupport/ChromeClientEfl.h b/WebKit/efl/WebCoreSupport/ChromeClientEfl.h index 0e17806..8df8483 100644 --- a/WebKit/efl/WebCoreSupport/ChromeClientEfl.h +++ b/WebKit/efl/WebCoreSupport/ChromeClientEfl.h @@ -31,7 +31,7 @@ namespace WebCore { class ChromeClientEfl : public ChromeClient { public: - explicit ChromeClientEfl(Evas_Object *view); + explicit ChromeClientEfl(Evas_Object* view); virtual ~ChromeClientEfl(); virtual void chromeDestroyed(); @@ -49,7 +49,7 @@ public: virtual bool canTakeFocus(FocusDirection); virtual void takeFocus(FocusDirection); - virtual void focusedNodeChanged(WebCore::Node*); + virtual void focusedNodeChanged(Node*); virtual Page* createWindow(Frame*, const FrameLoadRequest&, const WindowFeatures&); virtual void show(); @@ -88,9 +88,7 @@ public: virtual IntRect windowResizerRect() const; - virtual void repaint(const IntRect&, bool contentChanged, bool immediate = false, bool repaintContentOnly = false); virtual void contentsSizeChanged(Frame*, const IntSize&) const; - virtual bool scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect, bool canBlit, bool isMainFrame); virtual IntPoint screenToWindow(const IntPoint&) const; virtual IntRect windowToScreen(const IntRect&) const; virtual PlatformPageClient platformPageClient() const; @@ -111,6 +109,7 @@ public: #endif virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>); + virtual void chooseIconForFiles(const Vector<String>&, FileChooser*); virtual void formStateDidChange(const Node*); virtual PassOwnPtr<HTMLParserQuirks> createHTMLParserQuirks() { return 0; } @@ -120,8 +119,18 @@ public: virtual void scrollRectIntoView(const IntRect&, const ScrollView*) const {} virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*); - - Evas_Object *m_view; + virtual void cancelGeolocationPermissionRequestForFrame(Frame*, Geolocation*); + virtual void cancelGeolocationPermissionForFrame(Frame*, Geolocation*); + + virtual void invalidateContents(const IntRect&, bool); + virtual void invalidateWindow(const IntRect&, bool); + virtual void invalidateContentsAndWindow(const IntRect&, bool); + virtual void invalidateContentsForSlowScroll(const IntRect&, bool); + virtual void scroll(const IntSize&, const IntRect&, const IntRect&); + virtual void cancelGeolocationPermissionRequestForFrame(Frame*); + virtual void iconForFiles(const Vector<String, 0u>&, PassRefPtr<FileChooser>); + + Evas_Object* m_view; KURL m_hoveredLinkURL; }; } diff --git a/WebKit/efl/WebCoreSupport/FrameLoaderClientEfl.cpp b/WebKit/efl/WebCoreSupport/FrameLoaderClientEfl.cpp index 8a7fd2d..2358fab 100644 --- a/WebKit/efl/WebCoreSupport/FrameLoaderClientEfl.cpp +++ b/WebKit/efl/WebCoreSupport/FrameLoaderClientEfl.cpp @@ -188,7 +188,7 @@ void FrameLoaderClientEfl::committedLoad(DocumentLoader* loader, const char* dat FrameLoader* fl = loader->frameLoader(); if (m_firstData) { - fl->setEncoding(m_response.textEncodingName(), false); + fl->writer()->setEncoding(m_response.textEncodingName(), false); m_firstData = false; } fl->addData(data, length); @@ -666,7 +666,7 @@ void FrameLoaderClientEfl::finishedLoading(DocumentLoader* loader) if (!m_pluginView) { if (m_firstData) { FrameLoader* fl = loader->frameLoader(); - fl->setEncoding(m_response.textEncodingName(), false); + fl->writer()->setEncoding(m_response.textEncodingName(), false); m_firstData = false; } } else { @@ -711,7 +711,7 @@ void FrameLoaderClientEfl::dispatchDidFailLoading(DocumentLoader* loader, unsign { if (m_firstData) { FrameLoader* fl = loader->frameLoader(); - fl->setEncoding(m_response.textEncodingName(), false); + fl->writer()->setEncoding(m_response.textEncodingName(), false); m_firstData = false; } @@ -829,7 +829,7 @@ void FrameLoaderClientEfl::setMainDocumentError(DocumentLoader* loader, const Re { if (!m_pluginView) { if (m_firstData) { - loader->frameLoader()->setEncoding(m_response.textEncodingName(), false); + loader->frameLoader()->writer()->setEncoding(m_response.textEncodingName(), false); m_firstData = false; } } else { diff --git a/WebKit/efl/WebCoreSupport/FrameLoaderClientEfl.h b/WebKit/efl/WebCoreSupport/FrameLoaderClientEfl.h index 47b5621..581ec85 100644 --- a/WebKit/efl/WebCoreSupport/FrameLoaderClientEfl.h +++ b/WebKit/efl/WebCoreSupport/FrameLoaderClientEfl.h @@ -121,6 +121,7 @@ class FrameLoaderClientEfl : public FrameLoaderClient { virtual void dispatchUnableToImplementPolicy(const ResourceError&); + virtual void dispatchWillSendSubmitEvent(HTMLFormElement*) { } virtual void dispatchWillSubmitForm(FramePolicyFunction, WTF::PassRefPtr<FormState>); virtual void dispatchDidLoadMainResource(DocumentLoader*); diff --git a/WebKit/efl/ewebkit.pc.in b/WebKit/efl/ewebkit.pc.in index 24f66e8..f58e5bf 100644 --- a/WebKit/efl/ewebkit.pc.in +++ b/WebKit/efl/ewebkit.pc.in @@ -1,11 +1,11 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include Name: WebKit-EFL Description: Web content engine for EFL applications -Version: @VERSION@ +Version: @PROJECT_VERSION@ Requires: cairo evas ecore -Libs: -L${libdir} -lewebkit +Libs: -L${libdir} -lewebkit @EXTRA_EWEBKIT_LINK@ Cflags: -I${includedir}/EWebKit diff --git a/WebKit/efl/ewk/ewk_frame.cpp b/WebKit/efl/ewk/ewk_frame.cpp index 73d1d29..5e93a05 100644 --- a/WebKit/efl/ewk/ewk_frame.cpp +++ b/WebKit/efl/ewk/ewk_frame.cpp @@ -988,7 +988,12 @@ Eina_Bool ewk_frame_zoom_set(Evas_Object* o, float zoom) { EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE); - sd->frame->setZoomFactor(zoom, sd->zoom_text_only); + WebCore::ZoomMode zoomMode; + if (sd->zoom_text_only) + zoomMode = WebCore::ZoomTextOnly; + else + zoomMode = WebCore::ZoomPage; + sd->frame->setZoomFactor(zoom, zoomMode); return EINA_TRUE; } @@ -1022,7 +1027,12 @@ Eina_Bool ewk_frame_zoom_text_only_set(Evas_Object* o, Eina_Bool setting) return EINA_TRUE; sd->zoom_text_only = setting; - sd->frame->setZoomFactor(sd->frame->zoomFactor(), setting); + WebCore::ZoomMode zoomMode; + if (sd->zoom_text_only) + zoomMode = WebCore::ZoomTextOnly; + else + zoomMode = WebCore::ZoomPage; + sd->frame->setZoomFactor(sd->frame->zoomFactor(), zoomMode); return EINA_TRUE; } @@ -1424,45 +1434,45 @@ static inline Eina_Bool _ewk_frame_handle_key_scrolling(WebCore::Frame* frame, c int keyCode = event.windowsVirtualKeyCode(); switch (keyCode) { - case WebCore::VK_SPACE: + case VK_SPACE: granularity = WebCore::ScrollByPage; if (event.shiftKey()) direction = WebCore::ScrollUp; else direction = WebCore::ScrollDown; break; - case WebCore::VK_NEXT: + case VK_NEXT: granularity = WebCore::ScrollByPage; direction = WebCore::ScrollDown; break; - case WebCore::VK_PRIOR: + case VK_PRIOR: granularity = WebCore::ScrollByPage; direction = WebCore::ScrollUp; break; - case WebCore::VK_HOME: + case VK_HOME: granularity = WebCore::ScrollByDocument; direction = WebCore::ScrollUp; break; - case WebCore::VK_END: + case VK_END: granularity = WebCore::ScrollByDocument; direction = WebCore::ScrollDown; break; - case WebCore::VK_LEFT: + case VK_LEFT: granularity = WebCore::ScrollByLine; direction = WebCore::ScrollLeft; break; - case WebCore::VK_RIGHT: + case VK_RIGHT: granularity = WebCore::ScrollByLine; direction = WebCore::ScrollRight; break; - case WebCore::VK_UP: + case VK_UP: direction = WebCore::ScrollUp; if (event.ctrlKey()) granularity = WebCore::ScrollByDocument; else granularity = WebCore::ScrollByLine; break; - case WebCore::VK_DOWN: + case VK_DOWN: direction = WebCore::ScrollDown; if (event.ctrlKey()) granularity = WebCore::ScrollByDocument; @@ -1823,22 +1833,5 @@ void ewk_frame_force_layout(Evas_Object* o) WTF::PassRefPtr<WebCore::Widget> ewk_frame_plugin_create(Evas_Object* o, const WebCore::IntSize& pluginSize, WebCore::HTMLPlugInElement* element, const WebCore::KURL& url, const WTF::Vector<WebCore::String>& paramNames, const WTF::Vector<WebCore::String>& paramValues, const WebCore::String& mimeType, bool loadManually) { - DBG("o=%p, size=%dx%d, element=%p, url=%s, mimeType=%s", - o, pluginSize.width(), pluginSize.height(), element, - url.prettyURL().utf8().data(), mimeType.utf8().data()); - - EWK_FRAME_SD_GET_OR_RETURN(o, sd, 0); - - // TODO: emit signal and ask webkit users if something else should be done. - // like creating another x window (see gtk, it allows users to create - // GtkPluginWidget. - - WTF::RefPtr<WebCore::PluginView> pluginView = WebCore::PluginView::create - (sd->frame, pluginSize, element, url, paramNames, paramValues, - mimeType, loadManually); - - if (pluginView->status() == WebCore::PluginStatusLoadedSuccessfully) - return pluginView; - return 0; } diff --git a/WebKit/efl/ewk/ewk_main.cpp b/WebKit/efl/ewk/ewk_main.cpp index 2c69b36..ee9a656 100644 --- a/WebKit/efl/ewk/ewk_main.cpp +++ b/WebKit/efl/ewk/ewk_main.cpp @@ -24,9 +24,9 @@ #include "EWebKit.h" #include "Logging.h" #include "PageCache.h" -#include "PageGroup.h" #include "ewk_private.h" #include "runtime/InitializeThreading.h" +#include "wtf/Threading.h" #include <Ecore.h> #include <Ecore_Evas.h> @@ -103,6 +103,7 @@ int ewk_init(void) #endif JSC::initializeThreading(); + WTF::initializeMainThread(); WebCore::InitializeLoggingChannelsIfNecessary(); // Page cache capacity (in pages). Comment from Mac port: diff --git a/WebKit/efl/ewk/ewk_view.cpp b/WebKit/efl/ewk/ewk_view.cpp index eeb6535..d981459 100644 --- a/WebKit/efl/ewk/ewk_view.cpp +++ b/WebKit/efl/ewk/ewk_view.cpp @@ -494,7 +494,7 @@ static WTF::PassRefPtr<WebCore::Frame> _ewk_view_core_frame_new(Ewk_View_Smart_D return WebCore::Frame::create(priv->page, owner, flc); } -static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_0; +static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL; static Ewk_View_Private_Data* _ewk_view_priv_new(Ewk_View_Smart_Data* sd) { @@ -1392,7 +1392,7 @@ char* ewk_view_selection_get(const Evas_Object* o) { EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0); EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0); - WebCore::CString s = priv->page->focusController()->focusedOrMainFrame()->selectedText().utf8(); + WTF::CString s = priv->page->focusController()->focusedOrMainFrame()->selectedText().utf8(); if (s.isNull()) return 0; return strdup(s.data()); diff --git a/WebKit/gtk/ChangeLog b/WebKit/gtk/ChangeLog index 0affc25..24c7023 100644 --- a/WebKit/gtk/ChangeLog +++ b/WebKit/gtk/ChangeLog @@ -1,3 +1,251 @@ +2010-05-06 Martin Robinson <mrobinson@webkit.org> + + Reviewed by Xan Lopez. + + Remove use of GOwnPtr to hold GObject types. + https://bugs.webkit.org/show_bug.cgi?id=38669 + + Change use of GOwnPtr to GRefPtr to types which are natively reference-counted. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::dispatchWillSendRequest): Change GOwnPtr to GRefPtr in some places. + (WebKit::FrameLoaderClient::dispatchDecidePolicyForMIMEType): Ditto. + * webkit/webkitnetworkrequest.cpp: + (webkit_network_request_new_with_core_request): Ditto. + * webkit/webkitnetworkresponse.cpp: + (webkit_network_response_new_with_core_response): Ditto. + * webkit/webkitprivate.cpp: Remove GOwnPtr reference counting template specialization. + * webkit/webkitprivate.h: Ditto. + +2010-05-06 Martin Robinson <mrobinson@webkit.org> + + Reviewed by Gustavo Noronha Silva. + + [GTK] Enable DOM clipboard and drag-and-drop access + https://bugs.webkit.org/show_bug.cgi?id=30623 + + Convert dragging portion of drag-and-drop to use DataObjectGtk. + + * WebCoreSupport/DragClientGtk.cpp: + (WebKit::DragClient::willPerformDragDestinationAction): Remove the notImplemented. It is implemented, it's just a no-op. + (WebKit::DragClient::startDrag): Start the drag context via the ClipboardGtk and PasteboardHelper now. + * WebCoreSupport/DragClientGtk.h: Small style fix. + * webkit/webkitprivate.h: Add a HashMap of contexts and DataObjects here to to represent all current drag operations. + * webkit/webkitwebview.cpp: + (webkit_web_view_dispose): Clear all data objects during disposal. + (webkit_web_view_drag_end): When a drag is over, just remove it from the map. + (webkit_web_view_drag_data_get): To get the drag data, just grab it from the DataObject. + +2010-05-03 Abhishek Arya <inferno@chromium.org> + + Reviewed by Adam Barth. + + Add support for controlling clipboard access from javascript. + Clipboard access from javascript is disabled by default. + https://bugs.webkit.org/show_bug.cgi?id=27751 + + * webkit/webkitwebsettings.cpp: + (webkit_web_settings_class_init): + (webkit_web_settings_set_property): + (webkit_web_settings_get_property): + (webkit_web_settings_copy): + * webkit/webkitwebview.cpp: + (webkit_web_view_update_settings): + (webkit_web_view_settings_notify): + +2010-05-03 Jens Alfke <snej@chromium.org> + + Reviewed by Darin Fisher. + + [chromium] Add "willSendSubmitEvent" hook to WebFrameClient and FrameLoaderClient + https://bugs.webkit.org/show_bug.cgi?id=38397 + + No tests (functionality is exposed only through native WebKit API.) + + * WebCoreSupport/FrameLoaderClientGtk.h: + (WebKit::FrameLoaderClient::dispatchWillSendSubmitEvent): + +2010-05-01 Xan Lopez <xlopez@igalia.com> + + Reviewed by Oliver Hunt. + + [GTK] GObject DOM bindings + https://bugs.webkit.org/show_bug.cgi?id=33590 + + Test webkit_dom_document_get_links. + + * tests/testdomdocument.c: + (test_dom_document_get_links): + (main): + +2010-04-29 Xan Lopez <xlopez@igalia.com> + + Reviewed by Gustavo Noronha. + + [GTK] GObject DOM bindings + https://bugs.webkit.org/show_bug.cgi?id=33590 + + Test webkit_dom_document_get_element_by_id; + + * tests/testdomdocument.c: + (test_dom_document_get_element_by_id): + (main): + +2010-04-29 Xan Lopez <xlopez@igalia.com> + + Reviewed by Gustavo Noronha. + + [GTK] GObject DOM bindings + https://bugs.webkit.org/show_bug.cgi?id=33590 + + Test webkit_dom_document_get_elements_by_class_name. + + * tests/testdomdocument.c: + (test_dom_document_get_elements_by_class_name): + (main): + +2010-04-29 Xan Lopez <xlopez@igalia.com> + + Reviewed by Gustavo Noronha. + + [GTK] GObject DOM bindings + https://bugs.webkit.org/show_bug.cgi?id=33590 + + Test webkit_dom_document_get_elements_by_tag_name. + + * tests/testdomdocument.c: + (test_dom_document_get_elements_by_tag_name): + (main): + +2010-04-29 Xan Lopez <xlopez@igalia.com> + + Reviewed by Gustavo Noronha. + + [GTK] GObject DOM bindings + https://bugs.webkit.org/show_bug.cgi?id=33590 + + Move WebKitDOMDocument unit tests to their own file. + + * tests/testdomdocument.c: Added. + (finish_loading): + (dom_document_fixture_setup): + (dom_document_fixture_teardown): + (test_dom_document_title): + (main): + * tests/testwebview.c: + +2010-04-29 Xan Lopez <xlopez@igalia.com> + + Reviewed by Gustavo Noronha. + + [GTK] GObject DOM bindings + https://bugs.webkit.org/show_bug.cgi?id=33590 + + Include <webkit/webkitdom.h> in the main webkit.h header. + + * webkit/webkit.h: + +2010-04-25 Sam Weinig <sam@webkit.org> + + Reviewed by Maciej Stachowiak. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38097 + Disentangle initializing the main thread from initializing threading + + * webkit/webkitprivate.cpp: + (webkit_init): Add call to initializeMainThread. + +2010-04-22 Dave Moore <davemoore@chromium.org> + + Reviewed by Dimitri Glazkov. + + Added notification when the favicons for a page are changed + from a script. + The Document object will notify the frame loader, which will + notify the client. Implementations of FrameLoaderClient will + have to add one method; dispatchDidChangeIcons(). + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::dispatchDidChangeIcons): + * WebCoreSupport/FrameLoaderClientGtk.h: + +2010-04-22 Xan Lopez <xlopez@igalia.com> + + Reviewed by Gustavo Noronha. + + [GTK] GObject DOM bindings + https://bugs.webkit.org/show_bug.cgi?id=33590 + + Add webkit_web_view_get_document to retrieve the WebKitDOMDocument + from a WebKitWebView, and a very simple test for it. + + * tests/testwebview.c: + * webkit/webkitwebview.cpp: + (webkit_web_view_get_document): + * webkit/webkitwebview.h: + +2010-04-22 Diego Escalante Urrelo <descalante@igalia.com> + + Reviewed by Xan Lopez. + + [Gtk] Evaluate and create tests for all the AtkRole's implemented by + WebKitGtk + https://bugs.webkit.org/show_bug.cgi?id=34449 + + Expand testatkroles to test ATK_ROLE_COMBO_BOX. + + * tests/testatkroles.c: + (test_webkit_atk_get_role_combobox): + (main): + +2010-04-22 Diego Escalante Urrelo <descalante@igalia.com> + + Reviewed by Xan Lopez. + + [Gtk] Evaluate and create tests for all the AtkRole's implemented by + WebKitGtk + https://bugs.webkit.org/show_bug.cgi?id=34449 + + Expand testatkroles to test ATK_ROLE_SEPARATOR. + + * tests/testatkroles.c: + (test_webkit_atk_get_role_separator): + (main): + +2010-04-22 Adam Barth <abarth@webkit.org> + + Unreviewed, rolling out r58069. + http://trac.webkit.org/changeset/58069 + https://bugs.webkit.org/show_bug.cgi?id=27751 + + Broke compile on Windows. + + * webkit/webkitwebsettings.cpp: + (webkit_web_settings_class_init): + (webkit_web_settings_set_property): + (webkit_web_settings_get_property): + (webkit_web_settings_copy): + * webkit/webkitwebview.cpp: + (webkit_web_view_update_settings): + (webkit_web_view_settings_notify): + +2010-04-22 Abhishek Arya <inferno@chromium.org> + + Reviewed by Adam Barth. + + Add support for controlling clipboard access from javascript. + Clipboard access from javascript is disabled by default. + https://bugs.webkit.org/show_bug.cgi?id=27751 + + * webkit/webkitwebsettings.cpp: + (webkit_web_settings_class_init): + (webkit_web_settings_set_property): + (webkit_web_settings_get_property): + (webkit_web_settings_copy): + * webkit/webkitwebview.cpp: + (webkit_web_view_update_settings): + (webkit_web_view_settings_notify): + 2010-04-21 Jakub Wieczorek <jwieczorek@webkit.org> Reviewed by Darin Adler. diff --git a/WebKit/gtk/WebCoreSupport/DragClientGtk.cpp b/WebKit/gtk/WebCoreSupport/DragClientGtk.cpp index f4b0df1..900fb61 100644 --- a/WebKit/gtk/WebCoreSupport/DragClientGtk.cpp +++ b/WebKit/gtk/WebCoreSupport/DragClientGtk.cpp @@ -1,4 +1,6 @@ /* + * Copyright (C) Igalia S.L. + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -17,11 +19,16 @@ #include "config.h" #include "DragClientGtk.h" +#include "ClipboardGtk.h" +#include "DataObjectGtk.h" #include "Document.h" #include "Element.h" #include "Frame.h" +#include "GRefPtrGtk.h" #include "NotImplemented.h" +#include "PasteboardHelper.h" #include "RenderObject.h" +#include "webkitprivate.h" #include "webkitwebview.h" #include <gtk/gtk.h> @@ -41,7 +48,6 @@ DragClient::DragClient(WebKitWebView* webView) void DragClient::willPerformDragDestinationAction(DragDestinationAction, DragData*) { - notImplemented(); } void DragClient::willPerformDragSourceAction(DragSourceAction, const IntPoint& startPos, Clipboard*) @@ -61,50 +67,29 @@ DragSourceAction DragClient::dragSourceActionMaskForPoint(const IntPoint&) return DragSourceActionAny; } -void DragClient::startDrag(DragImageRef image, const IntPoint& dragImageOrigin, const IntPoint& eventPos, Clipboard*, Frame* frame, bool linkDrag) +void DragClient::startDrag(DragImageRef image, const IntPoint& dragImageOrigin, const IntPoint& eventPos, Clipboard* clipboard, Frame* frame, bool linkDrag) { - Element* targetElement = frame->document()->elementFromPoint(m_startPos.x(), m_startPos.y()); - bool imageDrag = false; - - if (targetElement) - imageDrag = targetElement->renderer()->isImage(); - - GdkAtom textHtml = gdk_atom_intern_static_string("text/html"); - GdkAtom netscapeUrl = gdk_atom_intern_static_string("_NETSCAPE_URL"); - - GtkTargetList* targetList = gtk_target_list_new(NULL, 0); - gtk_target_list_add(targetList, textHtml, 0, WEBKIT_WEB_VIEW_TARGET_INFO_HTML); - gtk_target_list_add_text_targets(targetList, WEBKIT_WEB_VIEW_TARGET_INFO_TEXT); - - if (linkDrag || imageDrag) { - gtk_target_list_add(targetList, netscapeUrl, 0, WEBKIT_WEB_VIEW_TARGET_INFO_NETSCAPE_URL); - gtk_target_list_add_uri_targets(targetList, WEBKIT_WEB_VIEW_TARGET_INFO_URI_LIST); - } - - if (imageDrag) - gtk_target_list_add_image_targets(targetList, WEBKIT_WEB_VIEW_TARGET_INFO_IMAGE, false); + ClipboardGtk* clipboardGtk = reinterpret_cast<ClipboardGtk*>(clipboard); GdkDragAction dragAction = GDK_ACTION_COPY; - if (linkDrag) { - dragAction = GDK_ACTION_LINK; - if (imageDrag) - dragAction = (GdkDragAction)(dragAction | GDK_ACTION_COPY); - } + if (linkDrag) + dragAction = (GdkDragAction) (dragAction | GDK_ACTION_LINK); + WebKitWebView* webView = webkit_web_frame_get_web_view(kit(frame)); + RefPtr<DataObjectGtk> dataObject = clipboardGtk->dataObject(); + + GRefPtr<GtkTargetList> targetList(clipboardGtk->helper()->targetListForDataObject(dataObject.get())); GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS); reinterpret_cast<GdkEventButton*>(event)->window = gtk_widget_get_window(GTK_WIDGET(m_webView)); reinterpret_cast<GdkEventButton*>(event)->time = GDK_CURRENT_TIME; - GdkDragContext* context = gtk_drag_begin(GTK_WIDGET(m_webView), - targetList, dragAction, 1, event); - g_object_ref(context); + GdkDragContext* context = gtk_drag_begin(GTK_WIDGET(m_webView), targetList.get(), dragAction, 1, event); + webView->priv->draggingDataObjects.set(context, dataObject); if (image) gtk_drag_set_icon_pixbuf(context, image, eventPos.x() - dragImageOrigin.x(), eventPos.y() - dragImageOrigin.y()); else gtk_drag_set_icon_default(context); - - gtk_target_list_unref(targetList); } DragImageRef DragClient::createDragImageForLink(KURL&, const String&, Frame*) diff --git a/WebKit/gtk/WebCoreSupport/DragClientGtk.h b/WebKit/gtk/WebCoreSupport/DragClientGtk.h index 97ea72a..6604940 100644 --- a/WebKit/gtk/WebCoreSupport/DragClientGtk.h +++ b/WebKit/gtk/WebCoreSupport/DragClientGtk.h @@ -51,9 +51,9 @@ namespace WebKit { virtual void dragControllerDestroyed(); - private: - WebKitWebView* m_webView; - WebCore::IntPoint m_startPos; + private: + WebKitWebView* m_webView; + WebCore::IntPoint m_startPos; }; } diff --git a/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp b/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp index 27ff3c8..fd2d7ed 100644 --- a/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp +++ b/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp @@ -200,19 +200,19 @@ static char* toString(unsigned long identifier) void FrameLoaderClient::dispatchWillSendRequest(WebCore::DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse) { - GOwnPtr<WebKitNetworkResponse> networkResponse(0); + GRefPtr<WebKitNetworkResponse> networkResponse(0); // We are adding one more resource to the load, or maybe we are // just redirecting a load. if (redirectResponse.isNull()) static_cast<WebKit::DocumentLoader*>(loader)->increaseLoadCount(identifier); else - networkResponse.set(webkit_network_response_new_with_core_response(redirectResponse)); + networkResponse = adoptGRef(webkit_network_response_new_with_core_response(redirectResponse)); WebKitWebView* webView = getViewFromFrame(m_frame); GOwnPtr<gchar> identifierString(toString(identifier)); WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get()); - GOwnPtr<WebKitNetworkRequest> networkRequest(webkit_network_request_new_with_core_request(request)); + GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(webkit_network_request_new_with_core_request(request))); if (!redirectResponse.isNull()) { // This is a redirect, so we need to update the WebResource's knowledge @@ -312,7 +312,7 @@ void FrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction poli if (isHandled) return; - GOwnPtr<WebKitNetworkResponse> networkResponse(webkit_web_frame_get_network_response(m_frame)); + GRefPtr<WebKitNetworkResponse> networkResponse(adoptGRef(webkit_web_frame_get_network_response(m_frame))); if (networkResponse) { ResourceResponse response = core(networkResponse.get()); if (response.isAttachment()) { @@ -753,6 +753,11 @@ void FrameLoaderClient::dispatchDidReceiveTitle(const String& title) } } +void FrameLoaderClient::dispatchDidChangeIcons() +{ + notImplemented(); +} + void FrameLoaderClient::dispatchDidCommitLoad() { if (m_loadingErrorPage) diff --git a/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h b/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h index 3819b9f..2eeeb35 100644 --- a/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h +++ b/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h @@ -82,6 +82,7 @@ namespace WebKit { virtual void dispatchDidReceiveIcon(); virtual void dispatchDidStartProvisionalLoad(); virtual void dispatchDidReceiveTitle(const WebCore::String&); + virtual void dispatchDidChangeIcons(); virtual void dispatchDidCommitLoad(); virtual void dispatchDidFailProvisionalLoad(const WebCore::ResourceError&); virtual void dispatchDidFailLoad(const WebCore::ResourceError&); @@ -100,6 +101,7 @@ namespace WebKit { virtual void dispatchUnableToImplementPolicy(const WebCore::ResourceError&); + virtual void dispatchWillSendSubmitEvent(WebCore::HTMLFormElement*) { } virtual void dispatchWillSubmitForm(WebCore::FramePolicyFunction, WTF::PassRefPtr<WebCore::FormState>); virtual void dispatchDidLoadMainResource(WebCore::DocumentLoader*); diff --git a/WebKit/gtk/tests/testatkroles.c b/WebKit/gtk/tests/testatkroles.c index d3ade6e..5fd08b0 100644 --- a/WebKit/gtk/tests/testatkroles.c +++ b/WebKit/gtk/tests/testatkroles.c @@ -34,6 +34,8 @@ #define HTML_PARAGRAPH "<html><body><p>This is a test.</p></body></html>" #define HTML_SECTION "<html><body><div>This is a test.</div></body></html>" #define HTML_TABLE "<html><body><table border='1'><tr><td>This is</td><td>a test.</td></tr></table></body></html>" +#define HTML_SEPARATOR "<html><body><hr/></body></html>" +#define HTML_COMBOBOX "<html><body><select size='1'><option>one</option><option>two</option><option>three</option></select></body></html>" /* Form roles */ #define HTML_FORM "<html><body><form>This is a test.</form></body></html>" #define HTML_CHECK_BOX "<html><body><input type='checkbox' />This is a test.</body></html>" @@ -175,6 +177,37 @@ static void test_webkit_atk_get_role_table(AtkRolesFixture* fixture, gconstpoint get_child_and_test_role(fixture->documentFrame, 0, ATK_ROLE_TABLE); } +static void test_webkit_atk_get_role_separator(AtkRolesFixture *fixture, gconstpointer data) +{ + get_child_and_test_role(fixture->documentFrame, 0, ATK_ROLE_SEPARATOR); +} + +static void test_webkit_atk_get_role_combobox(AtkRolesFixture *fixture, gconstpointer data) +{ + AtkObject* comboboxMenu; + + // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of. + fixture->obj = atk_object_ref_accessible_child(fixture->documentFrame, 0); + g_assert(fixture->obj); + + fixture->obj = atk_object_ref_accessible_child(fixture->obj, 0); + g_assert(fixture->obj); + fixture->role = atk_object_get_role(fixture->obj); + g_assert(fixture->role == ATK_ROLE_COMBO_BOX); + + comboboxMenu = atk_object_ref_accessible_child(fixture->obj, 0); + g_assert(comboboxMenu); + fixture->role = atk_object_get_role(comboboxMenu); + g_assert(fixture->role == ATK_ROLE_MENU); + + get_child_and_test_role(comboboxMenu, 0, ATK_ROLE_MENU_ITEM); + get_child_and_test_role(comboboxMenu, 1, ATK_ROLE_MENU_ITEM); + get_child_and_test_role(comboboxMenu, 2, ATK_ROLE_MENU_ITEM); + + g_object_unref(fixture->obj); + g_object_unref(comboboxMenu); +} + /* Form roles */ static void test_webkit_atk_get_role_form(AtkRolesFixture *fixture, gconstpointer data) { @@ -322,6 +355,18 @@ int main(int argc, char** argv) test_webkit_atk_get_role_table, atk_roles_fixture_teardown); + g_test_add("/webkit/atk/test_webkit_atk_get_role_separator", + AtkRolesFixture, HTML_SEPARATOR, + atk_roles_fixture_setup, + test_webkit_atk_get_role_separator, + atk_roles_fixture_teardown); + + g_test_add("/webkit/atk/test_webkit_atk_get_role_combobox", + AtkRolesFixture, HTML_COMBOBOX, + atk_roles_fixture_setup, + test_webkit_atk_get_role_combobox, + atk_roles_fixture_teardown); + /* Form roles */ g_test_add("/webkit/atk/test_webkit_atk_get_role_form", AtkRolesFixture, HTML_FORM, diff --git a/WebKit/gtk/tests/testdomdocument.c b/WebKit/gtk/tests/testdomdocument.c new file mode 100644 index 0000000..4c677ea --- /dev/null +++ b/WebKit/gtk/tests/testdomdocument.c @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2010 Igalia S.L. + * + * 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 "test_utils.h" + +#include <glib.h> +#include <glib/gstdio.h> +#include <gtk/gtk.h> +#include <webkit/webkit.h> + +#if GLIB_CHECK_VERSION(2, 16, 0) && GTK_CHECK_VERSION(2, 14, 0) + +#define HTML_DOCUMENT_TITLE "<html><head><title>This is the title</title></head><body></body></html>" +#define HTML_DOCUMENT_ELEMENTS "<html><body><ul><li>1</li><li>2</li><li>3</li></ul></body></html>" +#define HTML_DOCUMENT_ELEMENTS_CLASS "<html><body><div class=\"test\"></div><div class=\"strange\"></div><div class=\"test\"></div></body></html>" +#define HTML_DOCUMENT_ELEMENTS_ID "<html><body><div id=\"testok\"></div><div id=\"testbad\">first</div><div id=\"testbad\">second</div></body></html>" +#define HTML_DOCUMENT_LINKS "<html><body><a href=\"about:blank\">blank</a><a href=\"http://www.google.com\">google</a><a href=\"http://www.webkit.org\">webkit</a></body></html>" + +typedef struct { + GtkWidget* webView; + GMainLoop* loop; +} DomDocumentFixture; + +static gboolean finish_loading(DomDocumentFixture* fixture) +{ + if (g_main_loop_is_running(fixture->loop)) + g_main_loop_quit(fixture->loop); + + return FALSE; +} + +static void dom_document_fixture_setup(DomDocumentFixture* fixture, gconstpointer data) +{ + fixture->loop = g_main_loop_new(NULL, TRUE); + fixture->webView = webkit_web_view_new(); + g_object_ref_sink(fixture->webView); + + if (data != NULL) + webkit_web_view_load_string(WEBKIT_WEB_VIEW (fixture->webView), (const char*) data, NULL, NULL, NULL); + + g_idle_add((GSourceFunc)finish_loading, fixture); + g_main_loop_run(fixture->loop); +} + +static void dom_document_fixture_teardown(DomDocumentFixture* fixture, gconstpointer data) +{ + g_object_unref(fixture->webView); + g_main_loop_unref(fixture->loop); +} + +static void test_dom_document_title(DomDocumentFixture* fixture, gconstpointer data) +{ + g_assert(fixture); + WebKitWebView* view = (WebKitWebView*)fixture->webView; + g_assert(view); + WebKitDOMDocument* document = webkit_web_view_get_dom_document(view); + g_assert(document); + gchar* title = webkit_dom_document_get_title(document); + g_assert(title); + g_assert_cmpstr(title, ==, "This is the title"); + g_free(title); + webkit_dom_document_set_title(document, (gchar*)"This is the second title"); + title = webkit_dom_document_get_title(document); + g_assert(title); + g_assert_cmpstr(title, ==, "This is the second title"); + g_free(title); +} + +static void test_dom_document_get_elements_by_tag_name(DomDocumentFixture* fixture, gconstpointer data) +{ + g_assert(fixture); + WebKitWebView* view = (WebKitWebView*)fixture->webView; + g_assert(view); + WebKitDOMDocument* document = webkit_web_view_get_dom_document(view); + g_assert(document); + WebKitDOMNodeList* list = webkit_dom_document_get_elements_by_tag_name(document, (gchar*)"li"); + g_assert(list); + gulong length = webkit_dom_node_list_get_length(list); + g_assert_cmpint(length, ==, 3); + + guint i; + + for (i = 0; i < length; i++) { + WebKitDOMNode* item = webkit_dom_node_list_item(list, i); + g_assert(item); + WebKitDOMElement* element = (WebKitDOMElement*)item; + g_assert(element); + g_assert_cmpstr(webkit_dom_element_get_tag_name(element), ==, "LI"); + WebKitDOMHTMLElement* htmlElement = (WebKitDOMHTMLElement*)element; + char* n = g_strdup_printf("%d", i+1); + g_assert_cmpstr(webkit_dom_html_element_get_inner_text(htmlElement), ==, n); + g_free(n); + } +} + +static void test_dom_document_get_elements_by_class_name(DomDocumentFixture* fixture, gconstpointer data) +{ + g_assert(fixture); + WebKitWebView* view = (WebKitWebView*)fixture->webView; + g_assert(view); + WebKitDOMDocument* document = webkit_web_view_get_dom_document(view); + g_assert(document); + WebKitDOMNodeList* list = webkit_dom_document_get_elements_by_class_name(document, (gchar*)"test"); + g_assert(list); + gulong length = webkit_dom_node_list_get_length(list); + g_assert_cmpint(length, ==, 2); + + guint i; + + for (i = 0; i < length; i++) { + WebKitDOMNode* item = webkit_dom_node_list_item(list, i); + g_assert(item); + WebKitDOMElement* element = (WebKitDOMElement*)item; + g_assert(element); + g_assert_cmpstr(webkit_dom_element_get_tag_name(element), ==, "DIV"); + } +} + +static void test_dom_document_get_element_by_id(DomDocumentFixture* fixture, gconstpointer data) +{ + g_assert(fixture); + WebKitWebView* view = (WebKitWebView*)fixture->webView; + g_assert(view); + WebKitDOMDocument* document = webkit_web_view_get_dom_document(view); + g_assert(document); + WebKitDOMElement* element = webkit_dom_document_get_element_by_id(document, (gchar*)"testok"); + g_assert(element); + element = webkit_dom_document_get_element_by_id(document, (gchar*)"this-id-does-not-exist"); + g_assert(element == 0); + /* The DOM spec says the return value is undefined when there's + * more than one element with the same id; in our case the first + * one will be returned */ + element = webkit_dom_document_get_element_by_id(document, (gchar*)"testbad"); + g_assert(element); + WebKitDOMHTMLElement* htmlElement = (WebKitDOMHTMLElement*)element; + g_assert_cmpstr(webkit_dom_html_element_get_inner_text(htmlElement), ==, (gchar*)"first"); +} + +static void test_dom_document_get_links(DomDocumentFixture* fixture, gconstpointer data) +{ + g_assert(fixture); + WebKitWebView* view = (WebKitWebView*)fixture->webView; + g_assert(view); + WebKitDOMDocument* document = webkit_web_view_get_dom_document(view); + g_assert(document); + WebKitDOMHTMLCollection *collection = webkit_dom_document_get_links(document); + g_assert(collection); + gulong length = webkit_dom_html_collection_get_length(collection); + g_assert_cmpint(length, ==, 3); + + guint i; + + for (i = 0; i < length; i++) { + static const char* names[] = { "blank", "google", "webkit" }; + static const char* uris[] = { "about:blank", "http://www.google.com/", "http://www.webkit.org/" }; + WebKitDOMNode *node = webkit_dom_html_collection_item(collection, i); + g_assert(node); + WebKitDOMElement* element = (WebKitDOMElement*)node; + g_assert_cmpstr(webkit_dom_element_get_tag_name(element), ==, "A"); + WebKitDOMHTMLElement *htmlElement = (WebKitDOMHTMLElement*)element; + g_assert_cmpstr(webkit_dom_html_element_get_inner_text(htmlElement), ==, names[i]); + WebKitDOMHTMLAnchorElement *anchor = (WebKitDOMHTMLAnchorElement*)element; + g_assert_cmpstr(webkit_dom_html_anchor_element_get_href(anchor), ==, uris[i]); + } +} + +int main(int argc, char** argv) +{ + if (!g_thread_supported()) + g_thread_init(NULL); + + gtk_test_init(&argc, &argv, NULL); + + g_test_bug_base("https://bugs.webkit.org/"); + + g_test_add("/webkit/domdocument/test_title", + DomDocumentFixture, HTML_DOCUMENT_TITLE, + dom_document_fixture_setup, + test_dom_document_title, + dom_document_fixture_teardown); + + g_test_add("/webkit/domdocument/test_get_elements_by_tag_name", + DomDocumentFixture, HTML_DOCUMENT_ELEMENTS, + dom_document_fixture_setup, + test_dom_document_get_elements_by_tag_name, + dom_document_fixture_teardown); + + g_test_add("/webkit/domdocument/test_get_elements_by_class_name", + DomDocumentFixture, HTML_DOCUMENT_ELEMENTS_CLASS, + dom_document_fixture_setup, + test_dom_document_get_elements_by_class_name, + dom_document_fixture_teardown); + + g_test_add("/webkit/domdocument/test_get_element_by_id", + DomDocumentFixture, HTML_DOCUMENT_ELEMENTS_ID, + dom_document_fixture_setup, + test_dom_document_get_element_by_id, + dom_document_fixture_teardown); + + g_test_add("/webkit/domdocument/test_get_links", + DomDocumentFixture, HTML_DOCUMENT_LINKS, + dom_document_fixture_setup, + test_dom_document_get_links, + dom_document_fixture_teardown); + + return g_test_run(); +} + +#else +int main(int argc, char** argv) +{ + g_critical("You will need at least glib-2.16.0 and gtk-2.14.0 to run the unit tests. Doing nothing now."); + return 0; +} + +#endif diff --git a/WebKit/gtk/webkit/webkit.h b/WebKit/gtk/webkit/webkit.h index 17b197b..fc71c2c 100644 --- a/WebKit/gtk/webkit/webkit.h +++ b/WebKit/gtk/webkit/webkit.h @@ -23,6 +23,7 @@ #include <webkit/webkitversion.h> #include <webkit/webkitdefines.h> +#include <webkit/webkitdom.h> #include <webkit/webkitdownload.h> #include <webkit/webkitgeolocationpolicydecision.h> #include <webkit/webkithittestresult.h> diff --git a/WebKit/gtk/webkit/webkitnetworkrequest.cpp b/WebKit/gtk/webkit/webkitnetworkrequest.cpp index 78044aa..c72abbd 100644 --- a/WebKit/gtk/webkit/webkitnetworkrequest.cpp +++ b/WebKit/gtk/webkit/webkitnetworkrequest.cpp @@ -21,7 +21,6 @@ #include "config.h" #include "webkitnetworkrequest.h" -#include "GOwnPtr.h" #include "ResourceRequest.h" #include "webkitprivate.h" #include <wtf/text/CString.h> @@ -165,7 +164,7 @@ static void webkit_network_request_init(WebKitNetworkRequest* request) // for internal use only WebKitNetworkRequest* webkit_network_request_new_with_core_request(const WebCore::ResourceRequest& resourceRequest) { - GOwnPtr<SoupMessage> soupMessage(resourceRequest.toSoupMessage()); + GRefPtr<SoupMessage> soupMessage(adoptGRef(resourceRequest.toSoupMessage())); if (soupMessage) return WEBKIT_NETWORK_REQUEST(g_object_new(WEBKIT_TYPE_NETWORK_REQUEST, "message", soupMessage.get(), NULL)); diff --git a/WebKit/gtk/webkit/webkitnetworkresponse.cpp b/WebKit/gtk/webkit/webkitnetworkresponse.cpp index 33bcd28..6745b94 100644 --- a/WebKit/gtk/webkit/webkitnetworkresponse.cpp +++ b/WebKit/gtk/webkit/webkitnetworkresponse.cpp @@ -22,7 +22,7 @@ #include "config.h" #include "webkitnetworkresponse.h" -#include "GOwnPtr.h" +#include "GRefPtr.h" #include "ResourceResponse.h" #include "webkitprivate.h" @@ -161,7 +161,7 @@ static void webkit_network_response_init(WebKitNetworkResponse* response) // for internal use only WebKitNetworkResponse* webkit_network_response_new_with_core_response(const WebCore::ResourceResponse& resourceResponse) { - GOwnPtr<SoupMessage> soupMessage(resourceResponse.toSoupMessage()); + GRefPtr<SoupMessage> soupMessage(adoptGRef(resourceResponse.toSoupMessage())); if (soupMessage) return WEBKIT_NETWORK_RESPONSE(g_object_new(WEBKIT_TYPE_NETWORK_RESPONSE, "message", soupMessage.get(), NULL)); diff --git a/WebKit/gtk/webkit/webkitprivate.cpp b/WebKit/gtk/webkit/webkitprivate.cpp index 971922f..d274708 100644 --- a/WebKit/gtk/webkit/webkitprivate.cpp +++ b/WebKit/gtk/webkit/webkitprivate.cpp @@ -19,9 +19,8 @@ */ #include "config.h" - -#include "webkitsoupauthdialog.h" #include "webkitprivate.h" + #include "ApplicationCacheStorage.h" #include "Chrome.h" #include "ChromeClientGtk.h" @@ -31,7 +30,6 @@ #include "GtkVersioning.h" #include "HitTestResult.h" #include "IconDatabase.h" -#include <libintl.h> #include "Logging.h" #include "PageCache.h" #include "PageGroup.h" @@ -41,11 +39,14 @@ #include "ResourceHandleClient.h" #include "ResourceHandleInternal.h" #include "ResourceResponse.h" -#include <runtime/InitializeThreading.h> #include "SecurityOrigin.h" -#include <stdlib.h> #include "TextEncodingRegistry.h" #include "webkitnetworkresponse.h" +#include "webkitsoupauthdialog.h" +#include <libintl.h> +#include <runtime/InitializeThreading.h> +#include <stdlib.h> +#include <wtf/Threading.h> #if ENABLE(DATABASE) #include "DatabaseTracker.h" @@ -177,34 +178,6 @@ PasteboardHelperGtk* pasteboardHelperInstance() } /** end namespace WebKit */ -namespace WTF { - -template <> void freeOwnedGPtr<SoupMessage>(SoupMessage* soupMessage) -{ - if (soupMessage) - g_object_unref(soupMessage); -} - -template <> void freeOwnedGPtr<WebKitNetworkRequest>(WebKitNetworkRequest* request) -{ - if (request) - g_object_unref(request); -} - -template <> void freeOwnedGPtr<WebKitNetworkResponse>(WebKitNetworkResponse* response) -{ - if (response) - g_object_unref(response); -} - -template <> void freeOwnedGPtr<WebKitWebResource>(WebKitWebResource* resource) -{ - if (resource) - g_object_unref(resource); -} - -} - static GtkWidget* currentToplevelCallback(WebKitSoupAuthDialog* feature, SoupMessage* message, gpointer userData) { gpointer messageData = g_object_get_data(G_OBJECT(message), "resourceHandle"); @@ -246,6 +219,8 @@ void webkit_init() bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); JSC::initializeThreading(); + WTF::initializeMainThread(); + WebCore::InitializeLoggingChannelsIfNecessary(); // We make sure the text codecs have been initialized, because diff --git a/WebKit/gtk/webkit/webkitprivate.h b/WebKit/gtk/webkit/webkitprivate.h index 2642d50..057b0e5 100644 --- a/WebKit/gtk/webkit/webkitprivate.h +++ b/WebKit/gtk/webkit/webkitprivate.h @@ -2,6 +2,7 @@ * Copyright (C) 2007, 2008, 2009 Holger Hans Peter Freyther * Copyright (C) 2008 Jan Michael C. Alonzo * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2010 Igalia S.L. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -46,6 +47,7 @@ #include "ArchiveResource.h" #include "BackForwardList.h" +#include "DataObjectGtk.h" #include <enchant.h> #include "GOwnPtr.h" #include "Geolocation.h" @@ -149,6 +151,8 @@ extern "C" { char* mainResourceIdentifier; GHashTable* subResources; char* tooltipText; + + HashMap<GdkDragContext*, RefPtr<WebCore::DataObjectGtk> > draggingDataObjects; }; #define WEBKIT_WEB_FRAME_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_WEB_FRAME, WebKitWebFramePrivate)) @@ -377,11 +381,4 @@ extern "C" { webkit_web_frame_layout(WebKitWebFrame* frame); } -namespace WTF { - template <> void freeOwnedGPtr<SoupMessage>(SoupMessage*); - template <> void freeOwnedGPtr<WebKitNetworkRequest>(WebKitNetworkRequest*); - template <> void freeOwnedGPtr<WebKitNetworkResponse>(WebKitNetworkResponse*); - template <> void freeOwnedGPtr<WebKitWebResource>(WebKitWebResource*); -} - #endif diff --git a/WebKit/gtk/webkit/webkitwebsettings.cpp b/WebKit/gtk/webkit/webkitwebsettings.cpp index 5d2d658..d61f3ff 100644 --- a/WebKit/gtk/webkit/webkitwebsettings.cpp +++ b/WebKit/gtk/webkit/webkitwebsettings.cpp @@ -96,6 +96,7 @@ struct _WebKitWebSettingsPrivate { gboolean enable_spatial_navigation; gchar* user_agent; gboolean javascript_can_open_windows_automatically; + gboolean javascript_can_access_clipboard; gboolean enable_offline_web_application_cache; WebKitEditingBehavior editing_behavior; gboolean enable_universal_access_from_file_uris; @@ -145,6 +146,7 @@ enum { PROP_ENABLE_SPATIAL_NAVIGATION, PROP_USER_AGENT, PROP_JAVASCRIPT_CAN_OPEN_WINDOWS_AUTOMATICALLY, + PROP_JAVASCRIPT_CAN_ACCESS_CLIPBOARD, PROP_ENABLE_OFFLINE_WEB_APPLICATION_CACHE, PROP_EDITING_BEHAVIOR, PROP_ENABLE_UNIVERSAL_ACCESS_FROM_FILE_URIS, @@ -623,6 +625,22 @@ static void webkit_web_settings_class_init(WebKitWebSettingsClass* klass) _("Whether JavaScript can open windows automatically"), FALSE, flags)); + + /** + * WebKitWebSettings:javascript-can-access-clipboard + * + * Whether JavaScript can access Clipboard. + * + * Since: 1.3.0 + */ + g_object_class_install_property(gobject_class, + PROP_JAVASCRIPT_CAN_ACCESS_CLIPBOARD, + g_param_spec_boolean("javascript-can-access-clipboard", + _("JavaScript can access Clipboard"), + _("Whether JavaScript can access Clipboard"), + FALSE, + flags)); + /** * WebKitWebSettings:enable-offline-web-application-cache * @@ -1023,6 +1041,9 @@ static void webkit_web_settings_set_property(GObject* object, guint prop_id, con case PROP_JAVASCRIPT_CAN_OPEN_WINDOWS_AUTOMATICALLY: priv->javascript_can_open_windows_automatically = g_value_get_boolean(value); break; + case PROP_JAVASCRIPT_CAN_ACCESS_CLIPBOARD: + priv->javascript_can_access_clipboard = g_value_get_boolean(value); + break; case PROP_ENABLE_OFFLINE_WEB_APPLICATION_CACHE: priv->enable_offline_web_application_cache = g_value_get_boolean(value); break; @@ -1161,6 +1182,9 @@ static void webkit_web_settings_get_property(GObject* object, guint prop_id, GVa case PROP_JAVASCRIPT_CAN_OPEN_WINDOWS_AUTOMATICALLY: g_value_set_boolean(value, priv->javascript_can_open_windows_automatically); break; + case PROP_JAVASCRIPT_CAN_ACCESS_CLIPBOARD: + g_value_set_boolean(value, priv->javascript_can_access_clipboard); + break; case PROP_ENABLE_OFFLINE_WEB_APPLICATION_CACHE: g_value_set_boolean(value, priv->enable_offline_web_application_cache); break; @@ -1255,6 +1279,7 @@ WebKitWebSettings* webkit_web_settings_copy(WebKitWebSettings* web_settings) "enable-spatial-navigation", priv->enable_spatial_navigation, "user-agent", webkit_web_settings_get_user_agent(web_settings), "javascript-can-open-windows-automatically", priv->javascript_can_open_windows_automatically, + "javascript-can-access-clipboard", priv->javascript_can_access_clipboard, "enable-offline-web-application-cache", priv->enable_offline_web_application_cache, "editing-behavior", priv->editing_behavior, "enable-universal-access-from-file-uris", priv->enable_universal_access_from_file_uris, diff --git a/WebKit/gtk/webkit/webkitwebview.cpp b/WebKit/gtk/webkit/webkitwebview.cpp index 22f6d04..10a082c 100644 --- a/WebKit/gtk/webkit/webkitwebview.cpp +++ b/WebKit/gtk/webkit/webkitwebview.cpp @@ -81,6 +81,7 @@ #include "ResourceHandle.h" #include "ScriptValue.h" #include "Scrollbar.h" +#include "webkit/WebKitDOMDocumentPrivate.h" #include <wtf/text/CString.h> #include <gdk/gdkkeysyms.h> @@ -1123,6 +1124,8 @@ static void webkit_web_view_dispose(GObject* object) priv->subResources = NULL; } + priv->draggingDataObjects.clear(); + G_OBJECT_CLASS(webkit_web_view_parent_class)->dispose(object); } @@ -1233,126 +1236,26 @@ static void webkit_web_view_screen_changed(GtkWidget* widget, GdkScreen* previou static void webkit_web_view_drag_end(GtkWidget* widget, GdkDragContext* context) { - g_object_unref(context); -} - -struct DNDContentsRequest -{ - gint info; - GtkSelectionData* dnd_selection_data; - - gboolean is_url_label_request; - gchar* url; -}; - -void clipboard_contents_received(GtkClipboard* clipboard, GtkSelectionData* selection_data, gpointer data) -{ - DNDContentsRequest* contents_request = reinterpret_cast<DNDContentsRequest*>(data); - - if (contents_request->is_url_label_request) { - // We have received contents of the label clipboard. Use them to form - // required structures. When formed, enhance the dnd's selection data - // with them and return. - - // If the label is empty, use the url itself. - gchar* url_label = reinterpret_cast<gchar*>(gtk_selection_data_get_text(selection_data)); - if (!url_label) - url_label = g_strdup(contents_request->url); - - gchar* data = 0; - switch (contents_request->info) { - case WEBKIT_WEB_VIEW_TARGET_INFO_URI_LIST: - data = g_strdup_printf("%s\r\n%s\r\n", contents_request->url, url_label); - break; - case WEBKIT_WEB_VIEW_TARGET_INFO_NETSCAPE_URL: - data = g_strdup_printf("%s\n%s", contents_request->url, url_label); - break; - } - - if (data) { - gtk_selection_data_set(contents_request->dnd_selection_data, - contents_request->dnd_selection_data->target, 8, - reinterpret_cast<const guchar*>(data), strlen(data)); - g_free(data); - } - - g_free(url_label); - g_free(contents_request->url); - g_free(contents_request); + WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(WEBKIT_WEB_VIEW(widget)); + // This might happen if a drag is still in progress after a WebKitWebView + // is diposed and before it is finalized. + if (!priv->draggingDataObjects.contains(context)) return; - } - switch (contents_request->info) { - case WEBKIT_WEB_VIEW_TARGET_INFO_HTML: - case WEBKIT_WEB_VIEW_TARGET_INFO_TEXT: - { - gchar* data = reinterpret_cast<gchar*>(gtk_selection_data_get_text(selection_data)); - if (data) { - gtk_selection_data_set(contents_request->dnd_selection_data, - contents_request->dnd_selection_data->target, 8, - reinterpret_cast<const guchar*>(data), - strlen(data)); - g_free(data); - } - break; - } - case WEBKIT_WEB_VIEW_TARGET_INFO_IMAGE: - { - GdkPixbuf* pixbuf = gtk_selection_data_get_pixbuf(selection_data); - if (pixbuf) { - gtk_selection_data_set_pixbuf(contents_request->dnd_selection_data, pixbuf); - g_object_unref(pixbuf); - } - break; - } - case WEBKIT_WEB_VIEW_TARGET_INFO_URI_LIST: - case WEBKIT_WEB_VIEW_TARGET_INFO_NETSCAPE_URL: - // URL's label is stored in another clipboard, so we store URL into - // contents request, mark the latter as an url label request - // and request for contents of the label clipboard. - contents_request->is_url_label_request = TRUE; - contents_request->url = reinterpret_cast<gchar*>(gtk_selection_data_get_text(selection_data)); - - gtk_clipboard_request_contents(gtk_clipboard_get(gdk_atom_intern_static_string("WebKitClipboardUrlLabel")), - selection_data->target, clipboard_contents_received, contents_request); - break; - } + priv->draggingDataObjects.remove(context); } -static void webkit_web_view_drag_data_get(GtkWidget* widget, GdkDragContext* context, GtkSelectionData* selection_data, guint info, guint time_) -{ - GdkAtom selection_atom = GDK_NONE; - GdkAtom target_atom = selection_data->target; - - switch (info) { - case WEBKIT_WEB_VIEW_TARGET_INFO_HTML: - selection_atom = gdk_atom_intern_static_string("WebKitClipboardHtml"); - // HTML markup data is set as text, therefor, we need a text-like target atom - target_atom = gdk_atom_intern_static_string("UTF8_STRING"); - break; - case WEBKIT_WEB_VIEW_TARGET_INFO_TEXT: - selection_atom = gdk_atom_intern_static_string("WebKitClipboardText"); - break; - case WEBKIT_WEB_VIEW_TARGET_INFO_IMAGE: - selection_atom = gdk_atom_intern_static_string("WebKitClipboardImage"); - break; - case WEBKIT_WEB_VIEW_TARGET_INFO_URI_LIST: - case WEBKIT_WEB_VIEW_TARGET_INFO_NETSCAPE_URL: - selection_atom = gdk_atom_intern_static_string("WebKitClipboardUrl"); - // We require URL and label, which are both stored in text format - // and are needed to be retrieved as such. - target_atom = gdk_atom_intern_static_string("UTF8_STRING"); - break; - } +static void webkit_web_view_drag_data_get(GtkWidget* widget, GdkDragContext* context, GtkSelectionData* selectionData, guint info, guint) +{ + WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(WEBKIT_WEB_VIEW(widget)); - DNDContentsRequest* contents_request = g_new(DNDContentsRequest, 1); - contents_request->info = info; - contents_request->is_url_label_request = FALSE; - contents_request->dnd_selection_data = selection_data; + // This might happen if a drag is still in progress after a WebKitWebView + // is diposed and before it is finalized. + if (!priv->draggingDataObjects.contains(context)) + return; - gtk_clipboard_request_contents(gtk_clipboard_get(selection_atom), target_atom, - clipboard_contents_received, contents_request); + pasteboardHelperInstance()->fillSelectionData(selectionData, info, priv->draggingDataObjects.get(context).get()); } #if GTK_CHECK_VERSION(2, 12, 0) @@ -2695,7 +2598,8 @@ static void webkit_web_view_update_settings(WebKitWebView* webView) gboolean autoLoadImages, autoShrinkImages, printBackgrounds, enableScripts, enablePlugins, enableDeveloperExtras, resizableTextAreas, enablePrivateBrowsing, enableCaretBrowsing, enableHTML5Database, enableHTML5LocalStorage, - enableXSSAuditor, enableSpatialNavigation, javascriptCanOpenWindows, enableOfflineWebAppCache, + enableXSSAuditor, enableSpatialNavigation, javascriptCanOpenWindows, + javaScriptCanAccessClipboard, enableOfflineWebAppCache, enableUniversalAccessFromFileURI, enableFileAccessFromFileURI, enableDOMPaste, tabKeyCyclesThroughElements, enableSiteSpecificQuirks, usePageCache, enableJavaApplet; @@ -2725,6 +2629,7 @@ static void webkit_web_view_update_settings(WebKitWebView* webView) "enable-xss-auditor", &enableXSSAuditor, "enable-spatial-navigation", &enableSpatialNavigation, "javascript-can-open-windows-automatically", &javascriptCanOpenWindows, + "javascript-can-access-clipboard", &javaScriptCanAccessClipboard, "enable-offline-web-application-cache", &enableOfflineWebAppCache, "editing-behavior", &editingBehavior, "enable-universal-access-from-file-uris", &enableUniversalAccessFromFileURI, @@ -2760,6 +2665,7 @@ static void webkit_web_view_update_settings(WebKitWebView* webView) settings->setXSSAuditorEnabled(enableXSSAuditor); settings->setSpatialNavigationEnabled(enableSpatialNavigation); settings->setJavaScriptCanOpenWindowsAutomatically(javascriptCanOpenWindows); + settings->setJavaScriptCanAccessClipboard(javaScriptCanAccessClipboard); settings->setOfflineWebApplicationCacheEnabled(enableOfflineWebAppCache); settings->setEditingBehavior(core(editingBehavior)); settings->setAllowUniversalAccessFromFileURLs(enableUniversalAccessFromFileURI); @@ -2857,6 +2763,8 @@ static void webkit_web_view_settings_notify(WebKitWebSettings* webSettings, GPar settings->setSpatialNavigationEnabled(g_value_get_boolean(&value)); else if (name == g_intern_string("javascript-can-open-windows-automatically")) settings->setJavaScriptCanOpenWindowsAutomatically(g_value_get_boolean(&value)); + else if (name == g_intern_string("javascript-can-access-clipboard")) + settings->setJavaScriptCanAccessClipboard(g_value_get_boolean(&value)); else if (name == g_intern_string("enable-offline-web-application-cache")) settings->setOfflineWebApplicationCacheEnabled(g_value_get_boolean(&value)); else if (name == g_intern_string("editing-behavior")) @@ -4431,3 +4339,27 @@ WebKitCacheModel webkit_get_cache_model() webkit_init(); return cacheModel; } + +/** + * webkit_web_view_get_dom_document: + * @webView: a #WebKitWebView + * + * Returns: the #WebKitDOMDocument currently loaded in the @webView + * + * Since: 1.3.0 + **/ +WebKitDOMDocument* +webkit_web_view_get_dom_document(WebKitWebView* webView) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0); + + Frame* coreFrame = core(webView)->mainFrame(); + if (!coreFrame) + return 0; + + Document* doc = coreFrame->document(); + if (!doc) + return 0; + + return static_cast<WebKitDOMDocument*>(kit(doc)); +} diff --git a/WebKit/gtk/webkit/webkitwebview.h b/WebKit/gtk/webkit/webkitwebview.h index e69de0a..865ae9d 100644 --- a/WebKit/gtk/webkit/webkitwebview.h +++ b/WebKit/gtk/webkit/webkitwebview.h @@ -27,6 +27,7 @@ #include <JavaScriptCore/JSBase.h> #include <webkit/webkitdefines.h> +#include <webkit/webkitdom.h> #include <webkit/webkitwebbackforwardlist.h> #include <webkit/webkitwebframe.h> #include <webkit/webkitwebhistoryitem.h> @@ -381,6 +382,9 @@ webkit_set_cache_model (WebKitCacheModel cache_mode WEBKIT_API WebKitCacheModel webkit_get_cache_model (void); +WEBKIT_API WebKitDOMDocument * +webkit_web_view_get_dom_document (WebKitWebView *webView); + G_END_DECLS #endif diff --git a/WebKit/haiku/ChangeLog b/WebKit/haiku/ChangeLog index f09c456..c821f12 100644 --- a/WebKit/haiku/ChangeLog +++ b/WebKit/haiku/ChangeLog @@ -1,3 +1,15 @@ +2010-05-03 Jens Alfke <snej@chromium.org> + + Reviewed by Darin Fisher. + + [chromium] Add "willSendSubmitEvent" hook to WebFrameClient and FrameLoaderClient + https://bugs.webkit.org/show_bug.cgi?id=38397 + + No tests (functionality is exposed only through native WebKit API.) + + * WebCoreSupport/FrameLoaderClientHaiku.h: + (WebCore::FrameLoaderClientHaiku::dispatchWillSendSubmitEvent): + 2010-04-20 Adam Barth <abarth@webkit.org> Reviewed by Eric Seidel. diff --git a/WebKit/haiku/WebCoreSupport/FrameLoaderClientHaiku.h b/WebKit/haiku/WebCoreSupport/FrameLoaderClientHaiku.h index cf2fb06..073c0c3 100644 --- a/WebKit/haiku/WebCoreSupport/FrameLoaderClientHaiku.h +++ b/WebKit/haiku/WebCoreSupport/FrameLoaderClientHaiku.h @@ -112,6 +112,7 @@ namespace WebCore { virtual void dispatchShow(); virtual void cancelPolicyCheck(); + virtual void dispatchWillSendSubmitEvent(HTMLFormElement*) { } virtual void dispatchWillSubmitForm(FramePolicyFunction, PassRefPtr<FormState>); virtual void dispatchDidLoadMainResource(DocumentLoader*); diff --git a/WebKit/mac/Carbon/CarbonWindowAdapter.mm b/WebKit/mac/Carbon/CarbonWindowAdapter.mm index ba1da71..c57bc37 100644 --- a/WebKit/mac/Carbon/CarbonWindowAdapter.mm +++ b/WebKit/mac/Carbon/CarbonWindowAdapter.mm @@ -74,6 +74,7 @@ #import <WebCore/WebCoreObjCExtras.h> #import <runtime/InitializeThreading.h> +#import <wtf/Threading.h> #import "WebKitLogging.h" #import "WebNSObjectExtras.h" @@ -269,6 +270,7 @@ static OSStatus NSCarbonWindowHandleEvent(EventHandlerCallRef inEventHandlerCall + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebKit/mac/ChangeLog b/WebKit/mac/ChangeLog index e45527f..d7aa5bf 100644 --- a/WebKit/mac/ChangeLog +++ b/WebKit/mac/ChangeLog @@ -1,3 +1,546 @@ +2010-05-06 Anders Carlsson <andersca@apple.com> + + Reviewed by Darin Adler and Dan Bernstein.. + + REGRESSION (r51617): when plugins are disabled, plugins show up as garbage characters + https://bugs.webkit.org/show_bug.cgi?id=38698 + <rdar://problem/7942075> + + When the plug-in database is initialized, we will register all the MIME types it supports with the global + WebView dictionary. When plug-ins are disabled for a single web view, the MIME types still need to be + in the global mapping (because other web views might still have plug-ins enabled). + + Prior to r51617 we would always look at the plug-in database to determine that the MIME type belongs to a + plug-in, but now we won't even touch the plug-in database when plug-ins are disabled. + + In order to fix this, a new set of registered MIME types that are known to be plug-ins is added. When + +[WebView _viewClass:andRepresentationClass:forMIMEType:allowingPlugins:] is called and allowingPlugins is FALSE + we check if the MIME type is a known plug-in MIME type and return false in that case. + + * Plugins/WebPluginDatabase.mm: + (-[WebPluginDatabase refresh]): + (-[WebPluginDatabase _removePlugin:]): + * WebView/WebView.mm: + (knownPluginMIMETypes): + (+[WebView _registerPluginMIMEType:]): + (+[WebView _unregisterPluginMIMEType:]): + (+[WebView _viewClass:andRepresentationClass:forMIMEType:allowingPlugins:]): + * WebView/WebViewInternal.h: + +2010-05-06 Dan Bernstein <mitz@apple.com> + + Reviewed by Simon Fraser. + + <rdar://problem/7951285> REGRESSION (r58847): Composited iframe content obscures Safari's application chrome + + Fixed this other regression from r58847. The regression was caused by overriding -visibleRect to + return the WebClipView’s full bounds. AppKit uses -visibleRect to determine the geometry + of the surface for the child WebFrameView. The fix is to restrict the special behavior of + -[WebClipView visibleRect] to when AppKit is consulting it for the purpose of invalidating + areas while scrolling. + + * WebView/WebClipView.h: + * WebView/WebClipView.mm: + (-[WebClipView visibleRect]): If the WebClipView is not scrolling, always return + [super visibleRect]. + (-[WebClipView _immediateScrollToPoint:]): Override this internal NSClipView method + to set a flag telling -visibleRect that the view is scrolling. + * WebView/WebView.mm: + (layerSyncRunLoopObserverCallBack): Ensure that screen updates, disabled by AppKit + when it thinks an upcoming window flush will re-enable them, are enabled here in + case the -setNeedsDisplayInRect: override has prevented the window from needing to be + flushed. + +2010-05-06 Steve Block <steveblock@google.com> + + Reviewed by Eric Seidel. + + MAC_JAVA_BRIDGE should be renamed JAVA_BRIDGE + https://bugs.webkit.org/show_bug.cgi?id=38544 + + * WebCoreSupport/WebFrameLoaderClient.h: + * WebCoreSupport/WebFrameLoaderClient.mm: + +2010-05-05 Dan Bernstein <mitz@apple.com> + + Reviewed by Mark Rowe. + + Fixed a crash when closing Top Sites after r58847. + + * WebView/WebFrameView.mm: + (-[WebFrameView webFrame]): Null-check _private. + +2010-05-05 Dan Bernstein <mitz@apple.com> + + Rubber-stamped by Mark Rowe. + + Fixed test crashes after r58847. + + * WebView/WebHTMLView.mm: + (setNeedsDisplayInRect): Null-check the frame. + +2010-05-05 Dan Bernstein <mitz@apple.com> + + Reviewed by Simon Fraser. + + <rdar://problem/7932072> Iframes in composited layers don’t repaint correctly (affects Yahoo! Mail with Flash Player 10.1) + https://bugs.webkit.org/show_bug.cgi?id=38427 + + * WebView/WebClipView.m: Renamed to WebClipView.mm. + * WebView/WebClipView.mm: + (-[WebClipView visibleRect]): Added this override, which for instances used for WebFrameViews in + composited layers, returns the clip view’s entire bounds. This prevents drawing from being clipped to + AppKit’s idea of what part of the view would be visible if it was drawn as part of the view hierarchy. + Since it is drawn into a compositing layer, that’s irrelevant, and we should not be clipping. + * WebView/WebHTMLView.mm: + (setCursor): Style tweak. + (setNeedsDisplayInRect): Added. Replaces the default implementation of -[NSView setNeedsDisplayInRect:], + so that if the receiver is a descendant of a WebFrameView that draws into a composited layer, the invalidation + is routed back through the WebCore FrameView, which propagates it to the layer. + (+[WebHTMLViewPrivate initialize]): Swizzle the setNeedsDisplayInRect: override in. + (-[WebHTMLView visibleRect]): Removed whitespace. + * WebView/WebView.mm: + (layerSyncRunLoopObserverCallBack): If we bailed out on syncing, due to pending layout, do an eager layout + in preparation for the displaying of compositing layers. + +2010-05-05 John Sullivan <sullivan@apple.com> + + <rdar://problem/7942606> Output appears in Console when exiting Safari with multiple windows opened + + Reviewed by Mark Rowe. + + * WebView/WebView.mm: + (+[WebView closeAllWebViews]): + Make copy of allWebViewsSet to avoid mutating it while iterating through it. + +2010-05-04 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Dan Bernstein. + + Improve check for drawing into the window that was added in r58623 + https://bugs.webkit.org/show_bug.cgi?id=38562 + + Rather than assuming that any non-bitmap context is the window's context, + compare the current graphics context with -[NSWindow graphicsContext] to + determine that we're drawing into the window. + + * WebView/WebHTMLView.mm: + (-[WebHTMLView drawRect:]): + +2010-05-04 Ada Chan <adachan@apple.com> + + Reviewed by David Kilzer. + + https://bugs.webkit.org/show_bug.cgi?id=38555 + + Small code refactoring: move the logic to figure out the path to the + databases directory to another method. + + * Storage/WebDatabaseManager.mm: + (databasesDirectoryPath): + (WebKitInitializeDatabasesIfNecessary): + +2010-05-04 Beth Dakin <bdakin@apple.com> + + Reviewed by Mike Thole. + + Fix for <rdar://problem/7818509> Crash occurs when exiting Safari + + We can avoid this crash if we call [self _removeFromAllWebViewsSet] + even in the case when we are doing a fastDocumentTeardown. This is + a much safer approach. + * WebView/WebView.mm: + (-[WebView _close]): + +2010-05-03 Abhishek Arya <inferno@chromium.org> + + Reviewed by Adam Barth. + + Add support for controlling clipboard access from javascript. + Clipboard access from javascript is disabled by default. + https://bugs.webkit.org/show_bug.cgi?id=27751 + + * WebView/WebPreferenceKeysPrivate.h: + * WebView/WebPreferences.mm: + (+[WebPreferences initialize]): + (-[WebPreferences javaScriptCanAccessClipboard]): + (-[WebPreferences setJavaScriptCanAccessClipboard:]): + * WebView/WebPreferencesPrivate.h: + * WebView/WebView.mm: + (-[WebView _preferencesChangedNotification:]): + +2010-05-03 Jens Alfke <snej@chromium.org> + + Reviewed by Darin Fisher. + + [chromium] Add "willSendSubmitEvent" hook to WebFrameClient and FrameLoaderClient + https://bugs.webkit.org/show_bug.cgi?id=38397 + + No tests (functionality is exposed only through native WebKit API.) + + * WebCoreSupport/WebFrameLoaderClient.h: + (WebFrameLoaderClient::dispatchWillSendSubmitEvent): + +2010-04-30 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Dan Bernstein. + + <rdar://problem/7477071> REGRESSION: Bad flicker when wheel-scrolling Google Maps, iPad gallery and other sites + + Sites that frequently toggle content in and out of compositing layers (like http://www.tumblr.com/boothed) + can cause flickering because of unsychronized compositing layer and view-based updates. There were two + underlying issues: + + 1. On SnowLeopard, AppKit can throttle window updates, thus breaking an assumption that + NSView drawing will happen on the runloop cycle after a repaint. This provided a window + for the layerSyncRunLoopObserver to fire and commit layer changes too early. + + Fix this by having the layerSyncRunLoopObserver in WebView check to see if a display is pending, + and not commit layer changes in that case. We'll commit layer changes later when we + finally draw. + + 2. The change in r49269 was wrong; it was attempting to fix an issue that was actually caused + by -drawRects: coming in for page snapshots. The correct approach is to avoid hitting the + synchronization and update disabling code in WebHTMLView for draws that are not to the screen. + + * WebView/WebHTMLView.mm: + (-[WebHTMLView drawRect:]): + * WebView/WebView.mm: + (layerSyncRunLoopObserverCallBack): + (-[WebView _scheduleCompositingLayerSync]): + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Part of the previous part (forgot to save). + + * Plugins/WebNetscapePluginView.mm: + (-[WebNetscapePluginView stopTimers]): + (-[WebNetscapePluginView startTimers]): + (-[WebNetscapePluginView checkIfAllowedToLoadURL:frame:callbackFunc:context:]): + (-[WebNetscapePluginView _containerCheckResult:contextInfo:]): + (-[WebNetscapePluginView cancelCheckIfAllowedToLoadURL:]): + (-[WebNetscapePluginView scheduleTimerWithInterval:repeat:timerFunc:]): + (-[WebNetscapePluginView unscheduleTimer:]): + (-[WebNetscapePluginView getVariable:forURL:value:length:]): + (-[WebNetscapePluginView setVariable:forURL:value:length:]): + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Reviewed by Darin Adler. + + Use C99 integer types in more places. + + * Plugins/WebNetscapePluginView.mm: + (getNPRect): + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Fix Tiger build. + + * Plugins/WebBaseNetscapePluginStream.h: + * Plugins/WebBaseNetscapePluginStream.mm: + (WebNetscapePluginStream::startStream): + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Another 32-bit build fix. + + * Plugins/WebNetscapePluginView.mm: + (-[WebNetscapePluginView saveAndSetNewPortStateForUpdate:]): + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Fix 32-bit build (again). + + * Plugins/WebNetscapeContainerCheckContextInfo.h: + * Plugins/WebNetscapeContainerCheckContextInfo.mm: + (-[WebNetscapeContainerCheckContextInfo initWithCheckRequestID:callbackFunc:context:]): + (-[WebNetscapeContainerCheckContextInfo checkRequestID]): + (-[WebNetscapeContainerCheckContextInfo callback]): + * Plugins/WebNetscapePluginPackage.h: + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Fix 32-bit build. + + * Plugins/WebNetscapeContainerCheckContextInfo.h: + * Plugins/WebNetscapeContainerCheckContextInfo.mm: + (-[WebNetscapeContainerCheckContextInfo initWithCheckRequestID:callbackFunc:context:]): + * Plugins/WebNetscapeContainerCheckPrivate.h: + * Plugins/WebNetscapePluginPackage.mm: + (functionPointerForTVector): + * Plugins/WebNetscapePluginView.mm: + (PluginTimer::PluginTimer): + (-[WebNetscapePluginView checkIfAllowedToLoadURL:frame:callbackFunc:context:]): + (-[WebNetscapePluginView scheduleTimerWithInterval:repeat:timerFunc:]): + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Reviewed by Timothy Hatcher. + + Next step towards fixing + + https://bugs.webkit.org/show_bug.cgi?id=20784 + move npapi.h to C99 integer types + + Use the C99 types everywhere. The "old" types are still around but will be removed + in a subsequent commit. + + * Plugins/WebBaseNetscapePluginStream.h: + * Plugins/WebBaseNetscapePluginStream.mm: + (WebNetscapePluginStream::deliverData): + * Plugins/WebNetscapePluginView.h: + * Plugins/WebNetscapePluginView.mm: + (-[WebNetscapePluginView saveAndSetNewPortStateForUpdate:]): + (-[WebNetscapePluginView getAuthenticationInfoWithProtocol:host:port:scheme:realm:username:usernameLength:password:passwordLength:]): + * Plugins/npapi.mm: + (NPN_MemAlloc): + (NPN_MemFlush): + (NPN_PostURLNotify): + (NPN_PostURL): + (NPN_Write): + (NPN_ScheduleTimer): + (NPN_UnscheduleTimer): + (NPN_GetValueForURL): + (NPN_SetValueForURL): + (NPN_GetAuthenticationInfo): + (WKN_CheckIfAllowedToLoadURL): + (WKN_CancelCheckIfAllowedToLoadURL): + +2010-04-29 Anders Carlsson <andersca@apple.com> + + Reviewed by Dan Bernstein. + + First part of + https://bugs.webkit.org/show_bug.cgi?id=20784 + move npapi.h to C99 integer types. + + * MigrateHeaders.make: + +2010-04-28 Mike Thole <mthole@apple.com> + + Reviewed by David Kilzer. + + Add canAuthenticateAgainstProtectionSpace() to frame loader so that a protection space + can be inspected before attempting to authenticate against it + https://bugs.webkit.org/show_bug.cgi?id=38271 + + * WebCoreSupport/WebFrameLoaderClient.h: + * WebCoreSupport/WebFrameLoaderClient.mm: + (WebFrameLoaderClient::canAuthenticateAgainstProtectionSpace): + Added. If the resource load delegate implements the callback, use its answer. If it does + not, then only send authentication challenges for pre-10.6 protection spaces, which matches + CFNetwork's default behavior. + * WebView/WebDelegateImplementationCaching.h: + * WebView/WebDelegateImplementationCaching.mm: + (CallResourceLoadDelegateReturningBoolean): Added case for passing three objects. + * WebView/WebResourceLoadDelegatePrivate.h: + Added private SPI definition: webView:resource:canAuthenticateAgainstProtectionSpace:forDataSource: + * WebView/WebView.mm: + (-[WebView _cacheResourceLoadDelegateImplementations]): + +2010-04-28 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Sam Weinig. + + <rdar://problem/7918719> ASSERT(isMainThread()) from Font::setShouldUseSmoothing() + + Ensure that the WebView +initialize method initializes threading, so that things are correctly + initialized when the first call into the WebKit framework is via a WebView class method. + + * WebView/WebView.mm: + (+[WebView initialize]): + +2010-04-28 Darin Adler <darin@apple.com> + + Reviewed by Adele Peterson. + + REGRESSION: Autoscroll does not work in Mail messages + https://bugs.webkit.org/show_bug.cgi?id=38267 + rdar://problem/7559799 + + The machinery to make autoscrolling work on Mac OS X when a WebView is embedded in another + view had gotten broken in multiple ways. For some reason, a combination of bugs made it + partly work until around r48064. This brings it back. + + * WebCoreSupport/WebChromeClient.mm: + (WebChromeClient::scrollRectIntoView): When converting coordinates, use the document view + rather than the WebView itself. This logic may not be correct for the case where + usesDocumentViews is NO, but that is currently an experimental mode and can be fixed later. + +2010-04-27 Shinichiro Hamaji <hamaji@chromium.org> + + Reviewed by Darin Adler and Eric Seidel. + + Add layoutTestController.setPrinting() + https://bugs.webkit.org/show_bug.cgi?id=37203 + + * Misc/WebCoreStatistics.h: + * Misc/WebCoreStatistics.mm: + (-[WebFrame renderTreeAsExternalRepresentationForPrinting:]): + +2010-04-25 Sam Weinig <sam@webkit.org> + + Reviewed by Maciej Stachowiak. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38097 + Disentangle initializing the main thread from initializing threading + + Calls initializeMainThreadToProcessMainThread since there is no way to ensure + that the initialize method will be called on the main thread. + + * Carbon/CarbonWindowAdapter.mm: + (+[CarbonWindowAdapter initialize]): Add call to initializeMainThreadToProcessMainThread. + * History/WebBackForwardList.mm: + (+[WebBackForwardList initialize]): Ditto. + * History/WebHistoryItem.mm: + (+[WebHistoryItem initialize]): Ditto. + * Misc/WebElementDictionary.mm: + (+[WebElementDictionary initialize]): Ditto. + * Misc/WebIconDatabase.mm: + (+[WebIconDatabase initialize]): Ditto. + * Plugins/Hosted/WebHostedNetscapePluginView.mm: + (+[WebHostedNetscapePluginView initialize]): Ditto. + * Plugins/WebBaseNetscapePluginView.mm: + (+[WebBaseNetscapePluginView initialize]): Ditto. + * Plugins/WebBasePluginPackage.mm: + (+[WebBasePluginPackage initialize]): Ditto. + * Plugins/WebNetscapePluginView.mm: + (+[WebNetscapePluginView initialize]): Ditto. + * WebCoreSupport/WebEditorClient.mm: + (+[WebEditCommand initialize]): Ditto. + * WebCoreSupport/WebFrameLoaderClient.mm: + (+[WebFramePolicyListener initialize]): Ditto. + * WebView/WebArchive.mm: + (+[WebArchivePrivate initialize]): Ditto. + * WebView/WebDataSource.mm: + (+[WebDataSourcePrivate initialize]): Ditto. + * WebView/WebHTMLView.mm: + (+[WebHTMLViewPrivate initialize]): Ditto. + (+[WebHTMLView initialize]): Ditto. + * WebView/WebResource.mm: + (+[WebResourcePrivate initialize]): Ditto. + * WebView/WebTextIterator.mm: + (+[WebTextIteratorPrivate initialize]): Ditto. + * WebView/WebView.mm: + * WebView/WebViewData.mm: Ditto. + (+[WebViewPrivate initialize]): Ditto. + +2010-04-24 Dan Bernstein <mitz@apple.com> + + Reviewed by Darin Adler. + + <rdar://problem/7903728> REGRESSION (r51617): WebView fails to load plug-in MIME types + https://bugs.webkit.org/show_bug.cgi?id=38085 + + WebView was calling -_webView in a few places where it should have just used itself. It never + makes sense for WebView to call -_webView on itself, and these calls look like they were copied + from similar code in WebHTMLView, WebFrameView and WebDataSource, where -_webView has a different, + useful meaning. + + * WebView/WebView.mm: + (-[WebView drawSingleRect:]): Replaced [self _webView] with self. + (-[WebView _viewClass:andRepresentationClass:forMIMEType:]): Replaced [[self _webView] preferences] + with _private->preferences. + (-[WebView _canShowMIMEType:]): Ditto. + +2010-04-23 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Anders Carlsson. + + <rdar://problem/7894489> When printing Flash, send a drawRect event, rather than NPPrint + + When printing Flash plug-ins in 32-bit, send a drawRect event with a CGContextRef, rather than calling + NPPrint with a GWorldPtr, since Flash prefers the CGContext path. + + * Plugins/WebNetscapePluginView.mm: + (-[WebNetscapePluginView drawRect:]): + +2010-04-22 David Kilzer <ddkilzer@apple.com> + + <http://webkit.org/b/38029> +[WebTextIteratorPrivate initialize] is missing call to JSC::initializeThreading() + + Reviewed by Timothy Hatcher. + + Every other Objective-C class that calls + WebCoreObjCFinalizeOnMainThread(self) in +initialize also calls + JSC::initializeThreading(). The WebTextIteratorPrivate class + was the only one missing this call. + + * WebView/WebTextIterator.mm: + (+[WebTextIteratorPrivate initialize]): Added call to + JSC::initializeThreading(). + +2010-04-22 Alexey Proskuryakov <ap@apple.com> + + Rubber-stamped by Mark Rowe. + + <rdar://problem/7805969> REGRESSION: iTunes unable to play trailers + + Undo the changes made for https://bugs.webkit.org/show_bug.cgi?id=35215 (<rdar://problem/7673157>) + for now. Clients rely on the old behavior, so a fix that changes it will need to account for + those. + + * WebCoreSupport/WebFrameLoaderClient.mm: (WebFrameLoaderClient::createPlugin): Pass pluginURL + instead of baseURL again. + +2010-04-22 Dave Moore <davemoore@chromium.org> + + Reviewed by Dimitri Glazkov. + + Added notification when the favicons for a page are changed + from a script. + The Document object will notify the frame loader, which will + notify the client. Implementations of FrameLoaderClient will + have to add one method; dispatchDidChangeIcons(). + + https://bugs.webkit.org/show_bug.cgi?id=33812 + + * WebCoreSupport/WebFrameLoaderClient.h: + * WebCoreSupport/WebFrameLoaderClient.mm: + (WebFrameLoaderClient::dispatchDidChangeIcons): + +2010-04-22 Adam Barth <abarth@webkit.org> + + Unreviewed, rolling out r58069. + http://trac.webkit.org/changeset/58069 + https://bugs.webkit.org/show_bug.cgi?id=27751 + + Broke compile on Windows. + + * WebView/WebPreferenceKeysPrivate.h: + * WebView/WebPreferences.mm: + (+[WebPreferences initialize]): + * WebView/WebPreferencesPrivate.h: + * WebView/WebView.mm: + (-[WebView _preferencesChangedNotification:]): + +2010-04-22 Abhishek Arya <inferno@chromium.org> + + Reviewed by Adam Barth. + + Add support for controlling clipboard access from javascript. + Clipboard access from javascript is disabled by default. + https://bugs.webkit.org/show_bug.cgi?id=27751 + + * WebView/WebPreferenceKeysPrivate.h: + * WebView/WebPreferences.mm: + (+[WebPreferences initialize]): + (-[WebPreferences javaScriptCanAccessClipboard]): + (-[WebPreferences setJavaScriptCanAccessClipboard:]): + * WebView/WebPreferencesPrivate.h: + * WebView/WebView.mm: + (-[WebView _preferencesChangedNotification:]): + +2010-04-21 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Shinichiro Hamaji. + + https://bugs.webkit.org/show_bug.cgi?id=37964 + Fix a typo in comments - Korean encoding name is windows-949, not windows-939 + + * WebView/WebPreferences.mm: (+[WebPreferences _setInitialDefaultTextEncodingToSystemEncoding]): + 2010-04-21 Mark Rowe <mrowe@apple.com> Tiger build fix. diff --git a/WebKit/mac/Configurations/Version.xcconfig b/WebKit/mac/Configurations/Version.xcconfig index 6aeb263..cc5943e 100644 --- a/WebKit/mac/Configurations/Version.xcconfig +++ b/WebKit/mac/Configurations/Version.xcconfig @@ -22,7 +22,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAJOR_VERSION = 533; -MINOR_VERSION = 6; +MINOR_VERSION = 9; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/WebKit/mac/History/WebBackForwardList.mm b/WebKit/mac/History/WebBackForwardList.mm index f206fda..6d9e998 100644 --- a/WebKit/mac/History/WebBackForwardList.mm +++ b/WebKit/mac/History/WebBackForwardList.mm @@ -49,6 +49,7 @@ #import <wtf/Assertions.h> #import <wtf/RetainPtr.h> #import <wtf/StdLibExtras.h> +#import <wtf/Threading.h> using namespace WebCore; @@ -100,6 +101,7 @@ WebBackForwardList *kit(BackForwardList* backForwardList) + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebKit/mac/History/WebHistoryItem.mm b/WebKit/mac/History/WebHistoryItem.mm index 91bc610..48baa7c 100644 --- a/WebKit/mac/History/WebHistoryItem.mm +++ b/WebKit/mac/History/WebHistoryItem.mm @@ -53,6 +53,7 @@ #import <runtime/InitializeThreading.h> #import <wtf/Assertions.h> #import <wtf/StdLibExtras.h> +#import <wtf/Threading.h> // Private keys used in the WebHistoryItem's dictionary representation. // see 3245793 for explanation of "lastVisitedDate" @@ -95,6 +96,7 @@ void WKNotifyHistoryItemChanged(HistoryItem*) + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebKit/mac/MigrateHeaders.make b/WebKit/mac/MigrateHeaders.make index 061169e..96c0a71 100644 --- a/WebKit/mac/MigrateHeaders.make +++ b/WebKit/mac/MigrateHeaders.make @@ -185,6 +185,7 @@ all : \ $(PUBLIC_HEADERS_DIR)/npapi.h \ $(PUBLIC_HEADERS_DIR)/npfunctions.h \ $(PUBLIC_HEADERS_DIR)/npruntime.h \ + $(PUBLIC_HEADERS_DIR)/nptypes.h \ # ifeq ($(findstring ENABLE_SVG_DOM_OBJC_BINDINGS,$(FEATURE_DEFINES)), ENABLE_SVG_DOM_OBJC_BINDINGS) diff --git a/WebKit/mac/Misc/WebCoreStatistics.h b/WebKit/mac/Misc/WebCoreStatistics.h index d205083..a11c064 100644 --- a/WebKit/mac/Misc/WebCoreStatistics.h +++ b/WebKit/mac/Misc/WebCoreStatistics.h @@ -83,7 +83,7 @@ @end @interface WebFrame (WebKitDebug) -- (NSString *)renderTreeAsExternalRepresentation; +- (NSString *)renderTreeAsExternalRepresentationForPrinting:(BOOL)forPrinting; - (NSString *)counterValueForElement:(DOMElement*)element; - (int)pageNumberForElement:(DOMElement*)element:(float)pageWidthInPixels:(float)pageHeightInPixels; - (int)numberOfPages:(float)pageWidthInPixels:(float)pageHeightInPixels; diff --git a/WebKit/mac/Misc/WebCoreStatistics.mm b/WebKit/mac/Misc/WebCoreStatistics.mm index 1351fe5..c3fc23e 100644 --- a/WebKit/mac/Misc/WebCoreStatistics.mm +++ b/WebKit/mac/Misc/WebCoreStatistics.mm @@ -255,9 +255,9 @@ using namespace WebCore; @implementation WebFrame (WebKitDebug) -- (NSString *)renderTreeAsExternalRepresentation +- (NSString *)renderTreeAsExternalRepresentationForPrinting:(BOOL)forPrinting { - return externalRepresentation(_private->coreFrame); + return externalRepresentation(_private->coreFrame, forPrinting ? RenderAsTextPrintingMode : RenderAsTextBehaviorNormal); } - (NSString *)counterValueForElement:(DOMElement*)element diff --git a/WebKit/mac/Misc/WebElementDictionary.mm b/WebKit/mac/Misc/WebElementDictionary.mm index 7779392..6b2eb3d 100644 --- a/WebKit/mac/Misc/WebElementDictionary.mm +++ b/WebKit/mac/Misc/WebElementDictionary.mm @@ -43,6 +43,7 @@ #import <WebKit/DOMCore.h> #import <WebKit/DOMExtensions.h> #import <runtime/InitializeThreading.h> +#import <wtf/Threading.h> using namespace WebCore; @@ -64,6 +65,7 @@ static void cacheValueForKey(const void *key, const void *value, void *self) + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebKit/mac/Misc/WebIconDatabase.mm b/WebKit/mac/Misc/WebIconDatabase.mm index 0ded0d5..f53bffa 100644 --- a/WebKit/mac/Misc/WebIconDatabase.mm +++ b/WebKit/mac/Misc/WebIconDatabase.mm @@ -42,6 +42,8 @@ #import <WebCore/IntSize.h> #import <WebCore/SharedBuffer.h> #import <WebCore/ThreadCheck.h> +#import <runtime/InitializeThreading.h> +#import <wtf/Threading.h> using namespace WebCore; @@ -88,6 +90,12 @@ static WebIconDatabaseClient* defaultClient() @implementation WebIconDatabase ++ (void)initialize +{ + JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); +} + + (WebIconDatabase *)sharedIconDatabase { static WebIconDatabase *database = nil; diff --git a/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm b/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm index cd3724e..9da1b53 100644 --- a/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm +++ b/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm @@ -46,6 +46,7 @@ #import <WebCore/runtime_root.h> #import <runtime/InitializeThreading.h> #import <wtf/Assertions.h> +#import <wtf/Threading.h> using namespace WebCore; using namespace WebKit; @@ -60,6 +61,7 @@ extern "C" { + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebKit/mac/Plugins/WebBaseNetscapePluginStream.h b/WebKit/mac/Plugins/WebBaseNetscapePluginStream.h index a28793a..8fbe262 100644 --- a/WebKit/mac/Plugins/WebBaseNetscapePluginStream.h +++ b/WebKit/mac/Plugins/WebBaseNetscapePluginStream.h @@ -104,8 +104,8 @@ private: RetainPtr<NSString> m_mimeType; NPP m_plugin; - uint16 m_transferMode; - int32 m_offset; + uint16_t m_transferMode; + int32_t m_offset; NPStream m_stream; RetainPtr<NSString> m_path; int m_fileDescriptor; diff --git a/WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm b/WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm index 232a6c4..7322d31 100644 --- a/WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm +++ b/WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm @@ -220,8 +220,8 @@ void WebNetscapePluginStream::startStream(NSURL *url, long long expectedContentL m_stream.url = strdup([m_responseURL.get() _web_URLCString]); m_stream.ndata = this; - m_stream.end = expectedContentLength > 0 ? (uint32)expectedContentLength : 0; - m_stream.lastmodified = (uint32)[lastModifiedDate timeIntervalSince1970]; + m_stream.end = expectedContentLength > 0 ? (uint32_t)expectedContentLength : 0; + m_stream.lastmodified = (uint32_t)[lastModifiedDate timeIntervalSince1970]; m_stream.notifyData = m_notifyData; if (headers) { @@ -507,12 +507,12 @@ void WebNetscapePluginStream::deliverData() RefPtr<WebNetscapePluginStream> protect(this); - int32 totalBytes = [m_deliveryData.get() length]; - int32 totalBytesDelivered = 0; + int32_t totalBytes = [m_deliveryData.get() length]; + int32_t totalBytesDelivered = 0; while (totalBytesDelivered < totalBytes) { PluginStopDeferrer deferrer(m_pluginView.get()); - int32 deliveryBytes = m_pluginFuncs->writeready(m_plugin, &m_stream); + int32_t deliveryBytes = m_pluginFuncs->writeready(m_plugin, &m_stream); LOG(Plugins, "NPP_WriteReady responseURL=%@ bytes=%d", m_responseURL.get(), deliveryBytes); if (m_isTerminated) @@ -533,7 +533,7 @@ void WebNetscapePluginStream::deliverData() cancelLoadAndDestroyStreamWithError(pluginCancelledConnectionError()); return; } - deliveryBytes = min<int32>(deliveryBytes, [subdata length]); + deliveryBytes = min<int32_t>(deliveryBytes, [subdata length]); m_offset += deliveryBytes; totalBytesDelivered += deliveryBytes; LOG(Plugins, "NPP_Write responseURL=%@ bytes=%d total-delivered=%d/%d", m_responseURL.get(), deliveryBytes, m_offset, m_stream.end); diff --git a/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm b/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm index eec80f8..acd5152 100644 --- a/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm +++ b/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm @@ -41,7 +41,6 @@ #import "WebView.h" #import "WebViewInternal.h" -#import <WebCore/WebCoreObjCExtras.h> #import <WebCore/AuthenticationMac.h> #import <WebCore/BitmapImage.h> #import <WebCore/Credential.h> @@ -56,9 +55,11 @@ #import <WebCore/ProtectionSpace.h> #import <WebCore/RenderView.h> #import <WebCore/RenderWidget.h> +#import <WebCore/WebCoreObjCExtras.h> #import <WebKit/DOMPrivate.h> #import <runtime/InitializeThreading.h> #import <wtf/Assertions.h> +#import <wtf/Threading.h> #import <wtf/text/CString.h> #define LoginWindowDidSwitchFromUserNotification @"WebLoginWindowDidSwitchFromUserNotification" @@ -115,6 +116,7 @@ String WebHaltablePlugin::pluginName() const + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebKit/mac/Plugins/WebBasePluginPackage.mm b/WebKit/mac/Plugins/WebBasePluginPackage.mm index 1bddbcf..f186b81 100644 --- a/WebKit/mac/Plugins/WebBasePluginPackage.mm +++ b/WebKit/mac/Plugins/WebBasePluginPackage.mm @@ -28,13 +28,14 @@ #import <WebKit/WebBasePluginPackage.h> +#import <WebCore/WebCoreObjCExtras.h> #import <WebKit/WebKitNSStringExtras.h> -#import <WebKit/WebNetscapePluginPackage.h> #import <WebKit/WebNSObjectExtras.h> +#import <WebKit/WebNetscapePluginPackage.h> #import <WebKit/WebPluginPackage.h> -#import <WebCore/WebCoreObjCExtras.h> #import <runtime/InitializeThreading.h> #import <wtf/Assertions.h> +#import <wtf/Threading.h> #import <wtf/Vector.h> #import <WebKitSystemInterface.h> @@ -63,6 +64,7 @@ + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebKit/mac/Plugins/WebNetscapeContainerCheckContextInfo.h b/WebKit/mac/Plugins/WebNetscapeContainerCheckContextInfo.h index e9b14a7..dcd4dd4 100644 --- a/WebKit/mac/Plugins/WebNetscapeContainerCheckContextInfo.h +++ b/WebKit/mac/Plugins/WebNetscapeContainerCheckContextInfo.h @@ -31,14 +31,14 @@ #if ENABLE(NETSCAPE_PLUGIN_API) @interface WebNetscapeContainerCheckContextInfo : NSObject { - uint32 _checkRequestID; - void (*_callback)(NPP npp, uint32, NPBool, void *); + uint32_t _checkRequestID; + void (*_callback)(NPP npp, uint32_t, NPBool, void *); void *_context; } -- (id)initWithCheckRequestID:(uint32)checkRequestID callbackFunc:(void (*)(NPP npp, uint32 checkID, NPBool allowed, void* context))callbackFunc context:(void*)context; -- (uint32)checkRequestID; -- (void (*)(NPP npp, uint32, NPBool, void*))callback; +- (id)initWithCheckRequestID:(uint32_t)checkRequestID callbackFunc:(void (*)(NPP npp, uint32_t checkID, NPBool allowed, void* context))callbackFunc context:(void*)context; +- (uint32_t)checkRequestID; +- (void (*)(NPP npp, uint32_t, NPBool, void*))callback; - (void*)context; @end diff --git a/WebKit/mac/Plugins/WebNetscapeContainerCheckContextInfo.mm b/WebKit/mac/Plugins/WebNetscapeContainerCheckContextInfo.mm index 34a0ec1..8991c95 100644 --- a/WebKit/mac/Plugins/WebNetscapeContainerCheckContextInfo.mm +++ b/WebKit/mac/Plugins/WebNetscapeContainerCheckContextInfo.mm @@ -29,7 +29,7 @@ @implementation WebNetscapeContainerCheckContextInfo -- (id)initWithCheckRequestID:(uint32)checkRequestID callbackFunc:(void (*)(NPP npp, uint32 checkID, NPBool allowed, void* context))callbackFunc context:(void*)context +- (id)initWithCheckRequestID:(uint32_t)checkRequestID callbackFunc:(void (*)(NPP npp, uint32_t checkID, NPBool allowed, void* context))callbackFunc context:(void*)context { self = [super init]; if (!self) @@ -41,12 +41,12 @@ return self; } -- (uint32)checkRequestID +- (uint32_t)checkRequestID { return _checkRequestID; } -- (void (*)(NPP npp, uint32, NPBool, void*))callback +- (void (*)(NPP npp, uint32_t, NPBool, void*))callback { return _callback; } diff --git a/WebKit/mac/Plugins/WebNetscapeContainerCheckPrivate.h b/WebKit/mac/Plugins/WebNetscapeContainerCheckPrivate.h index dfde2f7..799680b 100644 --- a/WebKit/mac/Plugins/WebNetscapeContainerCheckPrivate.h +++ b/WebKit/mac/Plugins/WebNetscapeContainerCheckPrivate.h @@ -40,17 +40,17 @@ extern "C" { #define WKNVBrowserContainerCheckFuncsVersionHasGetLocation 2 -typedef uint32 (*WKN_CheckIfAllowedToLoadURLProcPtr)(NPP npp, const char* url, const char* frame, void (*callbackFunc)(NPP npp, uint32, NPBool allowed, void* context), void* context); -typedef void (*WKN_CancelCheckIfAllowedToLoadURLProcPtr)(NPP npp, uint32); +typedef uint32_t (*WKN_CheckIfAllowedToLoadURLProcPtr)(NPP npp, const char* url, const char* frame, void (*callbackFunc)(NPP npp, uint32_t, NPBool allowed, void* context), void* context); +typedef void (*WKN_CancelCheckIfAllowedToLoadURLProcPtr)(NPP npp, uint32_t); typedef char* (*WKN_ResolveURLProcPtr)(NPP npp, const char* url, const char* target); -uint32 WKN_CheckIfAllowedToLoadURL(NPP npp, const char* url, const char* frame, void (*callbackFunc)(NPP npp, uint32, NPBool allowed, void* context), void* context); -void WKN_CancelCheckIfAllowedToLoadURL(NPP npp, uint32); +uint32_t WKN_CheckIfAllowedToLoadURL(NPP npp, const char* url, const char* frame, void (*callbackFunc)(NPP npp, uint32_t, NPBool allowed, void* context), void* context); +void WKN_CancelCheckIfAllowedToLoadURL(NPP npp, uint32_t); char* WKN_ResolveURL(NPP npp, const char* url, const char* target); typedef struct _WKNBrowserContainerCheckFuncs { - uint16 size; - uint16 version; + uint16_t size; + uint16_t version; WKN_CheckIfAllowedToLoadURLProcPtr checkIfAllowedToLoadURL; WKN_CancelCheckIfAllowedToLoadURLProcPtr cancelCheckIfAllowedToLoadURL; diff --git a/WebKit/mac/Plugins/WebNetscapePluginPackage.h b/WebKit/mac/Plugins/WebNetscapePluginPackage.h index 010956d..1d4c893 100644 --- a/WebKit/mac/Plugins/WebNetscapePluginPackage.h +++ b/WebKit/mac/Plugins/WebNetscapePluginPackage.h @@ -47,8 +47,8 @@ typedef enum { NPPluginFuncs pluginFuncs; NPNetscapeFuncs browserFuncs; - uint16 pluginSize; - uint16 pluginVersion; + uint16_t pluginSize; + uint16_t pluginVersion; ResFileRefNum resourceRef; diff --git a/WebKit/mac/Plugins/WebNetscapePluginPackage.mm b/WebKit/mac/Plugins/WebNetscapePluginPackage.mm index 5c10d95..5651e7e 100644 --- a/WebKit/mac/Plugins/WebNetscapePluginPackage.mm +++ b/WebKit/mac/Plugins/WebNetscapePluginPackage.mm @@ -697,11 +697,11 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer); FunctionPointer functionPointerForTVector(TransitionVector tvp) { - const uint32 temp[6] = {0x3D800000, 0x618C0000, 0x800C0000, 0x804C0004, 0x7C0903A6, 0x4E800420}; - uint32 *newGlue = NULL; + const uint32_t temp[6] = {0x3D800000, 0x618C0000, 0x800C0000, 0x804C0004, 0x7C0903A6, 0x4E800420}; + uint32_t *newGlue = NULL; if (tvp != NULL) { - newGlue = (uint32 *)malloc(sizeof(temp)); + newGlue = (uint32_t *)malloc(sizeof(temp)); if (newGlue != NULL) { unsigned i; for (i = 0; i < 6; i++) newGlue[i] = temp[i]; diff --git a/WebKit/mac/Plugins/WebNetscapePluginView.h b/WebKit/mac/Plugins/WebNetscapePluginView.h index 5bc4467..b2debfa 100644 --- a/WebKit/mac/Plugins/WebNetscapePluginView.h +++ b/WebKit/mac/Plugins/WebNetscapePluginView.h @@ -89,13 +89,13 @@ typedef union PluginPort { BOOL inSetWindow; BOOL shouldStopSoon; - uint32 currentTimerID; - HashMap<uint32, PluginTimer*>* timers; + uint32_t currentTimerID; + HashMap<uint32_t, PluginTimer*>* timers; unsigned pluginFunctionCallDepth; - int32 specifiedHeight; - int32 specifiedWidth; + int32_t specifiedHeight; + int32_t specifiedWidth; HashSet<RefPtr<WebNetscapePluginStream> > streams; RetainPtr<NSMutableDictionary> _pendingFrameLoads; @@ -104,7 +104,7 @@ typedef union PluginPort { BOOL _isSilverlight; NSMutableDictionary *_containerChecksInProgress; - uint32 _currentContainerCheckRequestID; + uint32_t _currentContainerCheckRequestID; } + (WebNetscapePluginView *)currentPluginView; @@ -146,8 +146,8 @@ typedef union PluginPort { - (void)handleMouseEntered:(NSEvent *)event; - (void)handleMouseExited:(NSEvent *)event; -- (uint32)checkIfAllowedToLoadURL:(const char*)urlCString frame:(const char*)frameNameCString callbackFunc:(void (*)(NPP npp, uint32 checkID, NPBool allowed, void* context))callbackFunc context:(void*)context; -- (void)cancelCheckIfAllowedToLoadURL:(uint32)checkID; +- (uint32_t)checkIfAllowedToLoadURL:(const char*)urlCString frame:(const char*)frameNameCString callbackFunc:(void (*)(NPP npp, uint32_t checkID, NPBool allowed, void* context))callbackFunc context:(void*)context; +- (void)cancelCheckIfAllowedToLoadURL:(uint32_t)checkID; @end @@ -172,14 +172,14 @@ typedef union PluginPort { - (void)forceRedraw; - (NPError)getVariable:(NPNVariable)variable value:(void *)value; - (NPError)setVariable:(NPPVariable)variable value:(void *)value; -- (uint32)scheduleTimerWithInterval:(uint32)interval repeat:(NPBool)repeat timerFunc:(void (*)(NPP npp, uint32 timerID))timerFunc; -- (void)unscheduleTimer:(uint32)timerID; +- (uint32_t)scheduleTimerWithInterval:(uint32_t)interval repeat:(NPBool)repeat timerFunc:(void (*)(NPP npp, uint32_t timerID))timerFunc; +- (void)unscheduleTimer:(uint32_t)timerID; - (NPError)popUpContextMenu:(NPMenu *)menu; -- (NPError)getVariable:(NPNURLVariable)variable forURL:(const char*)url value:(char**)value length:(uint32*)length; -- (NPError)setVariable:(NPNURLVariable)variable forURL:(const char*)url value:(const char*)value length:(uint32)length; -- (NPError)getAuthenticationInfoWithProtocol:(const char*) protocol host:(const char*)host port:(int32)port scheme:(const char*)scheme realm:(const char*)realm - username:(char**)username usernameLength:(uint32*)usernameLength - password:(char**)password passwordLength:(uint32*)passwordLength; +- (NPError)getVariable:(NPNURLVariable)variable forURL:(const char*)url value:(char**)value length:(uint32_t*)length; +- (NPError)setVariable:(NPNURLVariable)variable forURL:(const char*)url value:(const char*)value length:(uint32_t)length; +- (NPError)getAuthenticationInfoWithProtocol:(const char*) protocol host:(const char*)host port:(int32_t)port scheme:(const char*)scheme realm:(const char*)realm + username:(char**)username usernameLength:(uint32_t*)usernameLength + password:(char**)password passwordLength:(uint32_t*)passwordLength; - (char*)resolveURL:(const char*)url forTarget:(const char*)target; @end diff --git a/WebKit/mac/Plugins/WebNetscapePluginView.mm b/WebKit/mac/Plugins/WebNetscapePluginView.mm index 388b84b..ebc3f85 100644 --- a/WebKit/mac/Plugins/WebNetscapePluginView.mm +++ b/WebKit/mac/Plugins/WebNetscapePluginView.mm @@ -30,13 +30,13 @@ #import "WebNetscapePluginView.h" +#import "WebBaseNetscapePluginStream.h" #import "WebDataSourceInternal.h" #import "WebDefaultUIDelegate.h" #import "WebFrameInternal.h" #import "WebFrameView.h" #import "WebKitErrorsPrivate.h" #import "WebKitLogging.h" -#import "WebNetscapeContainerCheckPrivate.h" #import "WebKitNSStringExtras.h" #import "WebKitSystemInterface.h" #import "WebNSDataExtras.h" @@ -45,18 +45,16 @@ #import "WebNSURLExtras.h" #import "WebNSURLRequestExtras.h" #import "WebNSViewExtras.h" -#import "WebNetscapePluginPackage.h" -#import "WebBaseNetscapePluginStream.h" -#import "WebPluginContainerCheck.h" #import "WebNetscapeContainerCheckContextInfo.h" +#import "WebNetscapeContainerCheckPrivate.h" #import "WebNetscapePluginEventHandler.h" -#import "WebPreferences.h" +#import "WebNetscapePluginPackage.h" +#import "WebPluginContainerCheck.h" #import "WebPluginRequest.h" -#import "WebViewInternal.h" +#import "WebPreferences.h" #import "WebUIDelegatePrivate.h" +#import "WebViewInternal.h" #import <Carbon/Carbon.h> -#import <runtime/JSLock.h> -#import <WebCore/npruntime_impl.h> #import <WebCore/CookieJar.h> #import <WebCore/DocumentLoader.h> #import <WebCore/Element.h> @@ -71,12 +69,15 @@ #import <WebCore/SoftLinking.h> #import <WebCore/WebCoreObjCExtras.h> #import <WebCore/WebCoreURLResponse.h> +#import <WebCore/npruntime_impl.h> #import <WebKit/DOMPrivate.h> #import <WebKit/WebUIDelegate.h> +#import <objc/objc-runtime.h> #import <runtime/InitializeThreading.h> +#import <runtime/JSLock.h> #import <wtf/Assertions.h> +#import <wtf/Threading.h> #import <wtf/text/CString.h> -#import <objc/objc-runtime.h> #define LoginWindowDidSwitchFromUserNotification @"WebLoginWindowDidSwitchFromUserNotification" #define LoginWindowDidSwitchToUserNotification @"WebLoginWindowDidSwitchToUserNotification" @@ -112,9 +113,9 @@ static const double ThrottledTimerInterval = 0.25; class PluginTimer : public TimerBase { public: - typedef void (*TimerFunc)(NPP npp, uint32 timerID); + typedef void (*TimerFunc)(NPP npp, uint32_t timerID); - PluginTimer(NPP npp, uint32 timerID, uint32 interval, NPBool repeat, TimerFunc timerFunc) + PluginTimer(NPP npp, uint32_t timerID, uint32_t interval, NPBool repeat, TimerFunc timerFunc) : m_npp(npp) , m_timerID(timerID) , m_interval(interval) @@ -147,8 +148,8 @@ private: } NPP m_npp; - uint32 m_timerID; - uint32 m_interval; + uint32_t m_timerID; + uint32_t m_interval; NPBool m_repeat; TimerFunc m_timerFunc; }; @@ -188,6 +189,7 @@ typedef struct { + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif @@ -252,20 +254,20 @@ static UInt32 getQDPixelFormatForBitmapContext(CGContextRef context) static inline void getNPRect(const CGRect& cgr, NPRect& npr) { - npr.top = static_cast<uint16>(cgr.origin.y); - npr.left = static_cast<uint16>(cgr.origin.x); - npr.bottom = static_cast<uint16>(CGRectGetMaxY(cgr)); - npr.right = static_cast<uint16>(CGRectGetMaxX(cgr)); + npr.top = static_cast<uint16_t>(cgr.origin.y); + npr.left = static_cast<uint16_t>(cgr.origin.x); + npr.bottom = static_cast<uint16_t>(CGRectGetMaxY(cgr)); + npr.right = static_cast<uint16_t>(CGRectGetMaxX(cgr)); } #endif static inline void getNPRect(const NSRect& nr, NPRect& npr) { - npr.top = static_cast<uint16>(nr.origin.y); - npr.left = static_cast<uint16>(nr.origin.x); - npr.bottom = static_cast<uint16>(NSMaxY(nr)); - npr.right = static_cast<uint16>(NSMaxX(nr)); + npr.top = static_cast<uint16_t>(nr.origin.y); + npr.left = static_cast<uint16_t>(nr.origin.x); + npr.bottom = static_cast<uint16_t>(NSMaxY(nr)); + npr.right = static_cast<uint16_t>(NSMaxX(nr)); } - (PortState)saveAndSetNewPortStateForUpdate:(BOOL)forUpdate @@ -304,10 +306,10 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) #endif window.type = NPWindowTypeWindow; - window.x = (int32)boundsInWindow.origin.x; - window.y = (int32)boundsInWindow.origin.y; - window.width = static_cast<uint32>(NSWidth(boundsInWindow)); - window.height = static_cast<uint32>(NSHeight(boundsInWindow)); + window.x = (int32_t)boundsInWindow.origin.x; + window.y = (int32_t)boundsInWindow.origin.y; + window.width = static_cast<uint32_t>(NSWidth(boundsInWindow)); + window.height = static_cast<uint32_t>(NSHeight(boundsInWindow)); // "Clip-out" the plug-in when: // 1) it's not really in a window or off-screen or has no height or width. @@ -353,8 +355,8 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) CGrafPtr port = GetWindowPort(windowRef); GetPortBounds(port, &portBounds); nPort.qdPort.port = port; - nPort.qdPort.portx = (int32)-boundsInWindow.origin.x; - nPort.qdPort.porty = (int32)-boundsInWindow.origin.y; + nPort.qdPort.portx = (int32_t)-boundsInWindow.origin.x; + nPort.qdPort.porty = (int32_t)-boundsInWindow.origin.y; window.window = &nPort; PortState_QD *qdPortState = (PortState_QD*)malloc(sizeof(PortState_QD)); @@ -417,8 +419,8 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) origin.x = offscreenBounds.left - origin.x * (axisFlip.x - origin.x); origin.y = offscreenBounds.bottom + origin.y * (axisFlip.y - origin.y); - nPort.qdPort.portx = static_cast<int32>(-boundsInWindow.origin.x + origin.x); - nPort.qdPort.porty = static_cast<int32>(-boundsInWindow.origin.y - origin.y); + nPort.qdPort.portx = static_cast<int32_t>(-boundsInWindow.origin.x + origin.x); + nPort.qdPort.porty = static_cast<int32_t>(-boundsInWindow.origin.y - origin.y); window.x = 0; window.y = 0; window.window = &nPort; @@ -697,8 +699,8 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) if (!timers) return; - HashMap<uint32, PluginTimer*>::const_iterator end = timers->end(); - for (HashMap<uint32, PluginTimer*>::const_iterator it = timers->begin(); it != end; ++it) { + HashMap<uint32_t, PluginTimer*>::const_iterator end = timers->end(); + for (HashMap<uint32_t, PluginTimer*>::const_iterator it = timers->begin(); it != end; ++it) { PluginTimer* timer = it->second; timer->stop(); } @@ -715,8 +717,8 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) if (!timers) return; - HashMap<uint32, PluginTimer*>::const_iterator end = timers->end(); - for (HashMap<uint32, PluginTimer*>::const_iterator it = timers->begin(); it != end; ++it) { + HashMap<uint32_t, PluginTimer*>::const_iterator end = timers->end(); + for (HashMap<uint32_t, PluginTimer*>::const_iterator it = timers->begin(); it != end; ++it) { PluginTimer* timer = it->second; ASSERT(!timer->isActive()); timer->start(_isCompletelyObscured); @@ -1235,9 +1237,9 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) } } -- (uint32)checkIfAllowedToLoadURL:(const char*)urlCString frame:(const char*)frameNameCString - callbackFunc:(void (*)(NPP npp, uint32 checkID, NPBool allowed, void* context))callbackFunc - context:(void*)context +- (uint32_t)checkIfAllowedToLoadURL:(const char*)urlCString frame:(const char*)frameNameCString + callbackFunc:(void (*)(NPP npp, uint32_t checkID, NPBool allowed, void* context))callbackFunc + context:(void*)context { if (!_containerChecksInProgress) _containerChecksInProgress = [[NSMutableDictionary alloc] init]; @@ -1266,7 +1268,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) - (void)_containerCheckResult:(PolicyAction)policy contextInfo:(id)contextInfo { ASSERT([contextInfo isKindOfClass:[WebNetscapeContainerCheckContextInfo class]]); - void (*pluginCallback)(NPP npp, uint32, NPBool, void*) = [contextInfo callback]; + void (*pluginCallback)(NPP npp, uint32_t, NPBool, void*) = [contextInfo callback]; if (!pluginCallback) { ASSERT_NOT_REACHED(); @@ -1276,7 +1278,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) pluginCallback([self plugin], [contextInfo checkRequestID], (policy == PolicyUse), [contextInfo context]); } -- (void)cancelCheckIfAllowedToLoadURL:(uint32)checkID +- (void)cancelCheckIfAllowedToLoadURL:(uint32_t)checkID { WebPluginContainerCheck *check = (WebPluginContainerCheck *)[_containerChecksInProgress objectForKey:[NSNumber numberWithInt:checkID]]; @@ -1402,7 +1404,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) if (!_isStarted) return; - if ([NSGraphicsContext currentContextDrawingToScreen]) + if ([NSGraphicsContext currentContextDrawingToScreen] || _isFlash) [self sendDrawRectEvent:rect]; else { NSBitmapImageRep *printedPluginBitmap = [self _printedPluginBitmap]; @@ -2131,15 +2133,15 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) } } -- (uint32)scheduleTimerWithInterval:(uint32)interval repeat:(NPBool)repeat timerFunc:(void (*)(NPP npp, uint32 timerID))timerFunc +- (uint32_t)scheduleTimerWithInterval:(uint32_t)interval repeat:(NPBool)repeat timerFunc:(void (*)(NPP npp, uint32_t timerID))timerFunc { if (!timerFunc) return 0; if (!timers) - timers = new HashMap<uint32, PluginTimer*>; + timers = new HashMap<uint32_t, PluginTimer*>; - uint32 timerID; + uint32_t timerID; do { timerID = ++currentTimerID; @@ -2154,7 +2156,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) return timerID; } -- (void)unscheduleTimer:(uint32)timerID +- (void)unscheduleTimer:(uint32_t)timerID { if (!timers) return; @@ -2175,7 +2177,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) return NPERR_NO_ERROR; } -- (NPError)getVariable:(NPNURLVariable)variable forURL:(const char*)url value:(char**)value length:(uint32*)length +- (NPError)getVariable:(NPNURLVariable)variable forURL:(const char*)url value:(char**)value length:(uint32_t*)length { switch (variable) { case NPNURLVCookie: { @@ -2227,7 +2229,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) return NPERR_GENERIC_ERROR; } -- (NPError)setVariable:(NPNURLVariable)variable forURL:(const char*)url value:(const char*)value length:(uint32)length +- (NPError)setVariable:(NPNURLVariable)variable forURL:(const char*)url value:(const char*)value length:(uint32_t)length { switch (variable) { case NPNURLVCookie: { @@ -2253,9 +2255,9 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) return NPERR_GENERIC_ERROR; } -- (NPError)getAuthenticationInfoWithProtocol:(const char*)protocolStr host:(const char*)hostStr port:(int32)port scheme:(const char*)schemeStr realm:(const char*)realmStr - username:(char**)usernameStr usernameLength:(uint32*)usernameLength - password:(char**)passwordStr passwordLength:(uint32*)passwordLength +- (NPError)getAuthenticationInfoWithProtocol:(const char*)protocolStr host:(const char*)hostStr port:(int32_t)port scheme:(const char*)schemeStr realm:(const char*)realmStr + username:(char**)usernameStr usernameLength:(uint32_t*)usernameLength + password:(char**)passwordStr passwordLength:(uint32_t*)passwordLength { if (!protocolStr || !hostStr || !schemeStr || !realmStr || !usernameStr || !usernameLength || !passwordStr || !passwordLength) return NPERR_GENERIC_ERROR; diff --git a/WebKit/mac/Plugins/WebPluginDatabase.mm b/WebKit/mac/Plugins/WebPluginDatabase.mm index 1856fe1..34f5e0f 100644 --- a/WebKit/mac/Plugins/WebPluginDatabase.mm +++ b/WebKit/mac/Plugins/WebPluginDatabase.mm @@ -35,13 +35,13 @@ #import "WebFrameViewInternal.h" #import "WebHTMLRepresentation.h" #import "WebHTMLView.h" -#import "WebHTMLView.h" #import "WebKitLogging.h" #import "WebNSFileManagerExtras.h" #import "WebNetscapePluginPackage.h" #import "WebPluginController.h" #import "WebPluginPackage.h" #import "WebViewPrivate.h" +#import "WebViewInternal.h" #import <WebKitSystemInterface.h> #import <wtf/Assertions.h> @@ -296,7 +296,7 @@ static NSArray *additionalWebPlugInPaths; continue; if (self == sharedDatabase) - [WebView registerViewClass:[WebHTMLView class] representationClass:[WebHTMLRepresentation class] forMIMEType:MIMEType]; + [WebView _registerPluginMIMEType:MIMEType]; } [MIMETypes release]; @@ -415,7 +415,7 @@ static NSArray *additionalWebPlugInPaths; while ((MIMEType = [MIMETypeEnumerator nextObject])) { if ([registeredMIMETypes containsObject:MIMEType]) { if (self == sharedDatabase) - [WebView _unregisterViewClassAndRepresentationClassForMIMEType:MIMEType]; + [WebView _unregisterPluginMIMEType:MIMEType]; [registeredMIMETypes removeObject:MIMEType]; } } diff --git a/WebKit/mac/Plugins/npapi.mm b/WebKit/mac/Plugins/npapi.mm index 51c37ae..8b1cfd6 100644 --- a/WebKit/mac/Plugins/npapi.mm +++ b/WebKit/mac/Plugins/npapi.mm @@ -39,7 +39,7 @@ WebNetscapePluginView *pluginViewForInstance(NPP instance); // general plug-in to browser functions -void* NPN_MemAlloc(uint32 size) +void* NPN_MemAlloc(uint32_t size) { return malloc(size); } @@ -49,7 +49,7 @@ void NPN_MemFree(void* ptr) free(ptr); } -uint32 NPN_MemFlush(uint32 size) +uint32_t NPN_MemFlush(uint32_t size) { LOG(Plugins, "NPN_MemFlush"); return size; @@ -89,12 +89,12 @@ NPError NPN_GetURL(NPP instance, const char* URL, const char* target) return [pluginViewForInstance(instance) getURL:URL target:target]; } -NPError NPN_PostURLNotify(NPP instance, const char* URL, const char* target, uint32 len, const char* buf, NPBool file, void* notifyData) +NPError NPN_PostURLNotify(NPP instance, const char* URL, const char* target, uint32_t len, const char* buf, NPBool file, void* notifyData) { return [pluginViewForInstance(instance) postURLNotify:URL target:target len:len buf:buf file:file notifyData:notifyData]; } -NPError NPN_PostURL(NPP instance, const char* URL, const char* target, uint32 len, const char* buf, NPBool file) +NPError NPN_PostURL(NPP instance, const char* URL, const char* target, uint32_t len, const char* buf, NPBool file) { return [pluginViewForInstance(instance) postURL:URL target:target len:len buf:buf file:file]; } @@ -104,7 +104,7 @@ NPError NPN_NewStream(NPP instance, NPMIMEType type, const char* target, NPStrea return [pluginViewForInstance(instance) newStream:type target:target stream:stream]; } -int32 NPN_Write(NPP instance, NPStream* stream, int32 len, void* buffer) +int32_t NPN_Write(NPP instance, NPStream* stream, int32_t len, void* buffer) { return [pluginViewForInstance(instance) write:stream len:len buffer:buffer]; } @@ -176,12 +176,12 @@ void NPN_PluginThreadAsyncCall(NPP instance, void (*func) (void *), void *userDa PluginMainThreadScheduler::scheduler().scheduleCall(instance, func, userData); } -uint32 NPN_ScheduleTimer(NPP instance, uint32 interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32 timerID)) +uint32_t NPN_ScheduleTimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID)) { return [pluginViewForInstance(instance) scheduleTimerWithInterval:interval repeat:repeat timerFunc:timerFunc]; } -void NPN_UnscheduleTimer(NPP instance, uint32 timerID) +void NPN_UnscheduleTimer(NPP instance, uint32_t timerID) { [pluginViewForInstance(instance) unscheduleTimer:timerID]; } @@ -191,17 +191,17 @@ NPError NPN_PopUpContextMenu(NPP instance, NPMenu *menu) return [pluginViewForInstance(instance) popUpContextMenu:menu]; } -NPError NPN_GetValueForURL(NPP instance, NPNURLVariable variable, const char* url, char** value, uint32* len) +NPError NPN_GetValueForURL(NPP instance, NPNURLVariable variable, const char* url, char** value, uint32_t* len) { return [pluginViewForInstance(instance) getVariable:variable forURL:url value:value length:len]; } -NPError NPN_SetValueForURL(NPP instance, NPNURLVariable variable, const char* url, const char* value, uint32 len) +NPError NPN_SetValueForURL(NPP instance, NPNURLVariable variable, const char* url, const char* value, uint32_t len) { return [pluginViewForInstance(instance) setVariable:variable forURL:url value:value length:len]; } -NPError NPN_GetAuthenticationInfo(NPP instance, const char* protocol, const char* host, int32 port, const char* scheme, const char *realm, char** username, uint32* ulen, char** password, uint32* plen) +NPError NPN_GetAuthenticationInfo(NPP instance, const char* protocol, const char* host, int32_t port, const char* scheme, const char *realm, char** username, uint32_t* ulen, char** password, uint32_t* plen) { return [pluginViewForInstance(instance) getAuthenticationInfoWithProtocol:protocol host:host @@ -217,12 +217,12 @@ NPBool NPN_ConvertPoint(NPP instance, double sourceX, double sourceY, NPCoordina return [pluginViewForInstance(instance) convertFromX:sourceX andY:sourceY space:sourceSpace toX:destX andY:destY space:destSpace]; } -uint32 WKN_CheckIfAllowedToLoadURL(NPP instance, const char* url, const char* frame, void (*callbackFunc)(NPP npp, uint32, NPBool, void*), void* context) +uint32_t WKN_CheckIfAllowedToLoadURL(NPP instance, const char* url, const char* frame, void (*callbackFunc)(NPP npp, uint32_t, NPBool, void*), void* context) { return [pluginViewForInstance(instance) checkIfAllowedToLoadURL:url frame:frame callbackFunc:callbackFunc context:context]; } -void WKN_CancelCheckIfAllowedToLoadURL(NPP instance, uint32 checkID) +void WKN_CancelCheckIfAllowedToLoadURL(NPP instance, uint32_t checkID) { [pluginViewForInstance(instance) cancelCheckIfAllowedToLoadURL:checkID]; } diff --git a/WebKit/mac/Storage/WebDatabaseManager.mm b/WebKit/mac/Storage/WebDatabaseManager.mm index 2c58889..782f422 100644 --- a/WebKit/mac/Storage/WebDatabaseManager.mm +++ b/WebKit/mac/Storage/WebDatabaseManager.mm @@ -49,6 +49,8 @@ NSString *WebDatabaseDidModifyOriginNotification = @"WebDatabaseDidModifyOriginN NSString *WebDatabaseDidModifyDatabaseNotification = @"WebDatabaseDidModifyDatabaseNotification"; NSString *WebDatabaseIdentifierKey = @"WebDatabaseIdentifierKey"; +static NSString *databasesDirectoryPath(); + @implementation WebDatabaseManager + (WebDatabaseManager *) sharedWebDatabaseManager @@ -119,6 +121,16 @@ NSString *WebDatabaseIdentifierKey = @"WebDatabaseIdentifierKey"; @end +static NSString *databasesDirectoryPath() +{ + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + NSString *databasesDirectory = [defaults objectForKey:WebDatabaseDirectoryDefaultsKey]; + if (!databasesDirectory || ![databasesDirectory isKindOfClass:[NSString class]]) + databasesDirectory = @"~/Library/WebKit/Databases"; + + return [databasesDirectory stringByStandardizingPath]; +} + void WebKitInitializeDatabasesIfNecessary() { static BOOL initialized = NO; @@ -126,13 +138,7 @@ void WebKitInitializeDatabasesIfNecessary() return; // Set the database root path in WebCore - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - - NSString *databasesDirectory = [defaults objectForKey:WebDatabaseDirectoryDefaultsKey]; - if (!databasesDirectory || ![databasesDirectory isKindOfClass:[NSString class]]) - databasesDirectory = @"~/Library/WebKit/Databases"; - - DatabaseTracker::tracker().setDatabaseDirectoryPath([databasesDirectory stringByStandardizingPath]); + DatabaseTracker::tracker().setDatabaseDirectoryPath(databasesDirectoryPath()); // Set the DatabaseTrackerClient DatabaseTracker::tracker().setClient(WebDatabaseTrackerClient::sharedWebDatabaseTrackerClient()); diff --git a/WebKit/mac/WebCoreSupport/WebChromeClient.mm b/WebKit/mac/WebCoreSupport/WebChromeClient.mm index d27a19c..4e65751 100644 --- a/WebKit/mac/WebCoreSupport/WebChromeClient.mm +++ b/WebKit/mac/WebCoreSupport/WebChromeClient.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * * Redistribution and use in source and binary forms, with or without @@ -54,15 +54,14 @@ #import <WebCore/Frame.h> #import <WebCore/FrameLoadRequest.h> #import <WebCore/Geolocation.h> -#import <WebCore/HitTestResult.h> #import <WebCore/HTMLNames.h> +#import <WebCore/HitTestResult.h> #import <WebCore/Icon.h> #import <WebCore/IntRect.h> #import <WebCore/Page.h> #import <WebCore/PlatformScreen.h> #import <WebCore/PlatformString.h> #import <WebCore/ResourceRequest.h> -#import <WebCore/ScrollView.h> #import <WebCore/Widget.h> #import <WebCore/WindowFeatures.h> #import <wtf/PassRefPtr.h> @@ -499,17 +498,18 @@ void WebChromeClient::contentsSizeChanged(Frame*, const IntSize&) const { } -void WebChromeClient::scrollRectIntoView(const IntRect& r, const ScrollView* scrollView) const +void WebChromeClient::scrollRectIntoView(const IntRect& r, const ScrollView*) const { - // FIXME: This scrolling behavior should be under the control of the embedding client (rather than something - // we just do ourselves). - + // FIXME: This scrolling behavior should be under the control of the embedding client, + // perhaps in a delegate method, rather than something WebKit does unconditionally. + NSView *coordinateView = [m_webView _usesDocumentViews] + ? [[[m_webView mainFrame] frameView] documentView] : m_webView; NSRect rect = r; for (NSView *view = m_webView; view; view = [view superview]) { if ([view isKindOfClass:[NSClipView class]]) { NSClipView *clipView = (NSClipView *)view; NSView *documentView = [clipView documentView]; - [documentView scrollRectToVisible:[documentView convertRect:rect fromView:m_webView]]; + [documentView scrollRectToVisible:[documentView convertRect:rect fromView:coordinateView]]; } } } diff --git a/WebKit/mac/WebCoreSupport/WebEditorClient.mm b/WebKit/mac/WebCoreSupport/WebEditorClient.mm index 1e03d88..ec9024a 100644 --- a/WebKit/mac/WebCoreSupport/WebEditorClient.mm +++ b/WebKit/mac/WebCoreSupport/WebEditorClient.mm @@ -62,6 +62,7 @@ #import <WebCore/WebCoreObjCExtras.h> #import <runtime/InitializeThreading.h> #import <wtf/PassRefPtr.h> +#import <wtf/Threading.h> using namespace WebCore; using namespace WTF; @@ -94,6 +95,7 @@ static WebViewInsertAction kit(EditorInsertAction coreAction) + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h index d497513..60b1fbf 100644 --- a/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h +++ b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h @@ -42,6 +42,7 @@ namespace WebCore { class AuthenticationChallenge; class CachedFrame; class HistoryItem; + class ProtectionSpace; class String; class ResourceLoader; class ResourceRequest; @@ -79,6 +80,9 @@ private: virtual bool shouldUseCredentialStorage(WebCore::DocumentLoader*, unsigned long identifier); virtual void dispatchDidReceiveAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::AuthenticationChallenge&); virtual void dispatchDidCancelAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::AuthenticationChallenge&); +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + virtual bool canAuthenticateAgainstProtectionSpace(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::ProtectionSpace&); +#endif virtual void dispatchDidReceiveResponse(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::ResourceResponse&); virtual void dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long identifier, int lengthReceived); virtual void dispatchDidFinishLoading(WebCore::DocumentLoader*, unsigned long identifier); @@ -99,6 +103,7 @@ private: virtual void dispatchDidReceiveIcon(); virtual void dispatchDidStartProvisionalLoad(); virtual void dispatchDidReceiveTitle(const WebCore::String& title); + virtual void dispatchDidChangeIcons(); virtual void dispatchDidCommitLoad(); virtual void dispatchDidFailProvisionalLoad(const WebCore::ResourceError&); virtual void dispatchDidFailLoad(const WebCore::ResourceError&); @@ -120,6 +125,7 @@ private: virtual void dispatchUnableToImplementPolicy(const WebCore::ResourceError&); + virtual void dispatchWillSendSubmitEvent(WebCore::HTMLFormElement*) { } virtual void dispatchWillSubmitForm(WebCore::FramePolicyFunction, PassRefPtr<WebCore::FormState>); virtual void dispatchDidLoadMainResource(WebCore::DocumentLoader*); @@ -204,7 +210,7 @@ private: virtual void registerForIconNotification(bool listen); -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) virtual jobject javaApplet(NSView*); #endif diff --git a/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm index 0088eae..cf4b03c 100644 --- a/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm +++ b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm @@ -50,16 +50,16 @@ #import "WebFrameViewInternal.h" #import "WebHTMLRepresentationPrivate.h" #import "WebHTMLViewInternal.h" -#import "WebHistoryItemInternal.h" #import "WebHistoryInternal.h" +#import "WebHistoryItemInternal.h" #import "WebIconDatabaseInternal.h" #import "WebKitErrorsPrivate.h" #import "WebKitLogging.h" #import "WebKitNSStringExtras.h" -#import "WebNavigationData.h" #import "WebNSURLExtras.h" -#import "WebNetscapePluginView.h" +#import "WebNavigationData.h" #import "WebNetscapePluginPackage.h" +#import "WebNetscapePluginView.h" #import "WebPanelAuthenticationHandler.h" #import "WebPluginController.h" #import "WebPluginPackage.h" @@ -73,7 +73,6 @@ #import "WebUIDelegate.h" #import "WebUIDelegatePrivate.h" #import "WebViewInternal.h" -#import <WebKitSystemInterface.h> #import <WebCore/AuthenticationMac.h> #import <WebCore/BlockExceptions.h> #import <WebCore/CachedFrame.h> @@ -89,10 +88,10 @@ #import <WebCore/FrameTree.h> #import <WebCore/FrameView.h> #import <WebCore/HTMLAppletElement.h> -#import <WebCore/HTMLHeadElement.h> #import <WebCore/HTMLFormElement.h> #import <WebCore/HTMLFrameElement.h> #import <WebCore/HTMLFrameOwnerElement.h> +#import <WebCore/HTMLHeadElement.h> #import <WebCore/HTMLNames.h> #import <WebCore/HTMLPlugInElement.h> #import <WebCore/HistoryItem.h> @@ -115,10 +114,12 @@ #import <WebCore/Widget.h> #import <WebKit/DOMElement.h> #import <WebKit/DOMHTMLFormElement.h> +#import <WebKitSystemInterface.h> #import <runtime/InitializeThreading.h> #import <wtf/PassRefPtr.h> +#import <wtf/Threading.h> -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) #import "WebJavaPlugIn.h" #endif @@ -131,7 +132,7 @@ using namespace WebCore; using namespace HTMLNames; using namespace std; -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) @interface NSView (WebJavaPluginDetails) - (jobject)pollForAppletInWindow:(NSWindow *)window; @end @@ -413,6 +414,27 @@ void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoa [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:webChallenge window:window]; } +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) +bool WebFrameLoaderClient::canAuthenticateAgainstProtectionSpace(DocumentLoader* loader, unsigned long identifier, const ProtectionSpace& protectionSpace) +{ + WebView *webView = getWebView(m_webFrame.get()); + WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView); + + NSURLProtectionSpace *webProtectionSpace = mac(protectionSpace); + + if (implementations->canAuthenticateAgainstProtectionSpaceFunc) { + if (id resource = [webView _objectForIdentifier:identifier]) { + return CallResourceLoadDelegateReturningBoolean(NO, implementations->canAuthenticateAgainstProtectionSpaceFunc, webView, @selector(webView:resource:canAuthenticateAgainstProtectionSpace:forDataSource:), resource, webProtectionSpace, dataSource(loader)); + } + } + + // If our resource load delegate doesn't handle the question, then only send authentication + // challenges for pre-10.6 protection spaces. This is the same as the default implementation + // in CFNetwork. + return (protectionSpace.authenticationScheme() < ProtectionSpaceAuthenticationSchemeClientCertificateRequested); +} +#endif + void WebFrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge&challenge) { WebView *webView = getWebView(m_webFrame.get()); @@ -593,6 +615,11 @@ void WebFrameLoaderClient::dispatchDidReceiveTitle(const String& title) CallFrameLoadDelegate(implementations->didReceiveTitleForFrameFunc, webView, @selector(webView:didReceiveTitle:forFrame:), (NSString *)title, m_webFrame.get()); } +void WebFrameLoaderClient::dispatchDidChangeIcons() +{ + // FIXME: Implement this to allow container to update favicon. +} + void WebFrameLoaderClient::dispatchDidCommitLoad() { // Tell the client we've committed this URL. @@ -1531,7 +1558,8 @@ PassRefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize& size, HTMLP [NSNumber numberWithInt:loadManually ? WebPlugInModeFull : WebPlugInModeEmbed], WebPlugInModeKey, [NSNumber numberWithBool:!loadManually], WebPlugInShouldLoadMainResourceKey, kit(element), WebPlugInContainingElementKey, - baseURL, WebPlugInBaseURLKey, + // FIXME: We should be passing base URL, see <https://bugs.webkit.org/show_bug.cgi?id=35215>. + pluginURL, WebPlugInBaseURLKey, // pluginURL might be nil, so add it last nil]; NSView *view = CallUIDelegate(webView, selector, arguments); @@ -1647,7 +1675,7 @@ void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget) PassRefPtr<Widget> WebFrameLoaderClient::createJavaAppletWidget(const IntSize& size, HTMLAppletElement* element, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues) { -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) BEGIN_BLOCK_OBJC_EXCEPTIONS; NSView *view = nil; @@ -1708,7 +1736,7 @@ PassRefPtr<Widget> WebFrameLoaderClient::createJavaAppletWidget(const IntSize& s return adoptRef(new PluginWidget); #else return 0; -#endif // ENABLE(MAC_JAVA_BRIDGE) +#endif // ENABLE(JAVA_BRIDGE) } String WebFrameLoaderClient::overrideMediaType() const @@ -1767,7 +1795,7 @@ void WebFrameLoaderClient::didPerformFirstNavigation() const [preferences setCacheModel:WebCacheModelDocumentBrowser]; } -#if ENABLE(MAC_JAVA_BRIDGE) +#if ENABLE(JAVA_BRIDGE) jobject WebFrameLoaderClient::javaApplet(NSView* view) { if ([view respondsToSelector:@selector(webPlugInGetApplet)]) @@ -1786,6 +1814,7 @@ jobject WebFrameLoaderClient::javaApplet(NSView* view) + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebKit/mac/WebView/WebArchive.mm b/WebKit/mac/WebView/WebArchive.mm index 86e29c8..f07b51b 100644 --- a/WebKit/mac/WebView/WebArchive.mm +++ b/WebKit/mac/WebView/WebArchive.mm @@ -38,6 +38,7 @@ #import <WebCore/LegacyWebArchive.h> #import <WebCore/ThreadCheck.h> #import <WebCore/WebCoreObjCExtras.h> +#import <wtf/Threading.h> using namespace WebCore; @@ -66,6 +67,7 @@ static NSString * const WebSubframeArchivesKey = @"WebSubframeArchives"; + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebKit/mac/WebView/WebClipView.h b/WebKit/mac/WebView/WebClipView.h index 76cc50c..968d2de 100644 --- a/WebKit/mac/WebView/WebClipView.h +++ b/WebKit/mac/WebView/WebClipView.h @@ -31,6 +31,7 @@ @interface WebClipView : NSClipView { BOOL _haveAdditionalClip; + BOOL _isScrolling; NSRect _additionalClip; } diff --git a/WebKit/mac/WebView/WebClipView.m b/WebKit/mac/WebView/WebClipView.mm index b551145..ced5d8d 100644 --- a/WebKit/mac/WebView/WebClipView.m +++ b/WebKit/mac/WebView/WebClipView.mm @@ -28,10 +28,10 @@ #import "WebClipView.h" -#import <WebKit/WebHTMLView.h> -#import <WebKit/WebNSViewExtras.h> -#import <WebKit/WebViewPrivate.h> -#import <wtf/Assertions.h> +#import "WebFrameInternal.h" +#import "WebFrameView.h" +#import "WebViewPrivate.h" +#import <WebCore/FrameView.h> // WebClipView's entire reason for existing is to set the clip used by focus ring redrawing. // There's no easy way to prevent the focus ring from drawing outside the passed-in clip rectangle @@ -41,10 +41,16 @@ // FIXME: Change terminology from "additional clip" to "focus ring clip". +using namespace WebCore; + @interface NSView (WebViewMethod) - (WebView *)_webView; @end +@interface NSClipView (WebNSClipViewDetails) +- (void)_immediateScrollToPoint:(NSPoint)newOrigin; +@end + @implementation WebClipView - (id)initWithFrame:(NSRect)frame @@ -67,6 +73,34 @@ return self; } +#if USE(ACCELERATED_COMPOSITING) +- (NSRect)visibleRect +{ + if (!_isScrolling) + return [super visibleRect]; + + WebFrameView *webFrameView = (WebFrameView *)[[self superview] superview]; + if (![webFrameView isKindOfClass:[WebFrameView class]]) + return [super visibleRect]; + + if (Frame* coreFrame = core([webFrameView webFrame])) { + if (FrameView* frameView = coreFrame->view()) { + if (frameView->isEnclosedInCompositingLayer()) + return [self bounds]; + } + } + + return [super visibleRect]; +} + +- (void)_immediateScrollToPoint:(NSPoint)newOrigin +{ + _isScrolling = YES; + [super _immediateScrollToPoint:newOrigin]; + _isScrolling = NO; +} +#endif + - (void)resetAdditionalClip { ASSERT(_haveAdditionalClip); diff --git a/WebKit/mac/WebView/WebDataSource.mm b/WebKit/mac/WebView/WebDataSource.mm index d9622b3..b16aaa8 100644 --- a/WebKit/mac/WebView/WebDataSource.mm +++ b/WebKit/mac/WebView/WebDataSource.mm @@ -60,6 +60,7 @@ #import <WebKit/DOMPrivate.h> #import <runtime/InitializeThreading.h> #import <wtf/Assertions.h> +#import <wtf/Threading.h> using namespace WebCore; @@ -79,6 +80,7 @@ using namespace WebCore; + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebKit/mac/WebView/WebDelegateImplementationCaching.h b/WebKit/mac/WebView/WebDelegateImplementationCaching.h index 3ad064c..2aadc83 100644 --- a/WebKit/mac/WebView/WebDelegateImplementationCaching.h +++ b/WebKit/mac/WebView/WebDelegateImplementationCaching.h @@ -35,6 +35,9 @@ struct WebResourceDelegateImplementationCache { IMP didCancelAuthenticationChallengeFunc; IMP didReceiveAuthenticationChallengeFunc; +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + IMP canAuthenticateAgainstProtectionSpaceFunc; +#endif IMP identifierForRequestFunc; IMP willSendRequestFunc; IMP didReceiveResponseFunc; @@ -130,6 +133,7 @@ id CallResourceLoadDelegate(IMP, WebView *, SEL, id, NSInteger, id); id CallResourceLoadDelegate(IMP, WebView *, SEL, id, id, NSInteger, id); BOOL CallResourceLoadDelegateReturningBoolean(BOOL, IMP, WebView *, SEL, id, id); +BOOL CallResourceLoadDelegateReturningBoolean(BOOL, IMP, WebView *, SEL, id, id, id); id CallScriptDebugDelegate(IMP, WebView *, SEL, id, id, NSInteger, id); id CallScriptDebugDelegate(IMP, WebView *, SEL, id, NSInteger, id, NSInteger, id); diff --git a/WebKit/mac/WebView/WebDelegateImplementationCaching.mm b/WebKit/mac/WebView/WebDelegateImplementationCaching.mm index 54c4c33..d00d60b 100644 --- a/WebKit/mac/WebView/WebDelegateImplementationCaching.mm +++ b/WebKit/mac/WebView/WebDelegateImplementationCaching.mm @@ -547,6 +547,18 @@ BOOL CallResourceLoadDelegateReturningBoolean(BOOL result, IMP implementation, W return result; } +BOOL CallResourceLoadDelegateReturningBoolean(BOOL result, IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3) +{ + if (!self->_private->catchesDelegateExceptions) + return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id, id)>(objc_msgSend)(self->_private->resourceProgressDelegate, selector, self, object1, object2, object3); + @try { + return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id, id)>(objc_msgSend)(self->_private->resourceProgressDelegate, selector, self, object1, object2, object3); + } @catch(id exception) { + ReportDiscardedDelegateException(selector, exception); + } + return result; +} + id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, NSInteger integer, id object3) { return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, object2, integer, object3); diff --git a/WebKit/mac/WebView/WebFrameView.mm b/WebKit/mac/WebView/WebFrameView.mm index 9ded8e1..e76e3ca 100644 --- a/WebKit/mac/WebView/WebFrameView.mm +++ b/WebKit/mac/WebView/WebFrameView.mm @@ -372,7 +372,8 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl - (WebFrame *)webFrame { - return _private->webFrame; + // This method can be called beneath -[NSView dealloc] after _private has been cleared. + return _private ? _private->webFrame : nil; } - (void)setAllowsScrolling:(BOOL)flag diff --git a/WebKit/mac/WebView/WebHTMLView.mm b/WebKit/mac/WebView/WebHTMLView.mm index daeeb10..83d2e7b 100644 --- a/WebKit/mac/WebView/WebHTMLView.mm +++ b/WebKit/mac/WebView/WebHTMLView.mm @@ -118,6 +118,7 @@ #import <dlfcn.h> #import <limits> #import <runtime/InitializeThreading.h> +#import <wtf/Threading.h> #if USE(ACCELERATED_COMPOSITING) #import <QuartzCore/QuartzCore.h> @@ -179,7 +180,7 @@ static bool needsCursorRectsSupportAtPoint(NSWindow* window, NSPoint point) static IMP oldSetCursorForMouseLocationIMP; // Overriding an internal method is a hack; <rdar://problem/7662987> tracks finding a better solution. -static void setCursor(NSWindow* self, SEL cmd, NSPoint point) +static void setCursor(NSWindow *self, SEL cmd, NSPoint point) { if (needsCursorRectsSupportAtPoint(self, point)) oldSetCursorForMouseLocationIMP(self, cmd, point); @@ -221,6 +222,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName; - (void)_recursive:(BOOL)recurse displayRectIgnoringOpacity:(NSRect)displayRect inContext:(NSGraphicsContext *)context topView:(BOOL)topView; - (NSRect)_dirtyRect; - (void)_setDrawsOwnDescendants:(BOOL)drawsOwnDescendants; +- (BOOL)_drawnByAncestor; - (void)_propagateDirtyRectsToOpaqueAncestors; - (void)_windowChangedKeyState; #if USE(ACCELERATED_COMPOSITING) && defined(BUILDING_ON_LEOPARD) @@ -228,6 +230,42 @@ extern NSString *NSTextInputReplacementRangeAttributeName; #endif @end +#if USE(ACCELERATED_COMPOSITING) +static IMP oldSetNeedsDisplayInRectIMP; + +static void setNeedsDisplayInRect(NSView *self, SEL cmd, NSRect invalidRect) +{ + if (![self _drawnByAncestor]) { + oldSetNeedsDisplayInRectIMP(self, cmd, invalidRect); + return; + } + + static Class webFrameViewClass = [WebFrameView class]; + WebFrameView *enclosingWebFrameView = (WebFrameView *)self; + while (enclosingWebFrameView && ![enclosingWebFrameView isKindOfClass:webFrameViewClass]) + enclosingWebFrameView = (WebFrameView *)[enclosingWebFrameView superview]; + + if (!enclosingWebFrameView) { + oldSetNeedsDisplayInRectIMP(self, cmd, invalidRect); + return; + } + + Frame* coreFrame = core([enclosingWebFrameView webFrame]); + FrameView* frameView = coreFrame ? coreFrame->view() : 0; + if (!frameView || !frameView->isEnclosedInCompositingLayer()) { + oldSetNeedsDisplayInRectIMP(self, cmd, invalidRect); + return; + } + + NSRect invalidRectInWebFrameViewCoordinates = [enclosingWebFrameView convertRect:invalidRect fromView:self]; + IntRect invalidRectInFrameViewCoordinates(invalidRectInWebFrameViewCoordinates); + if (![enclosingWebFrameView isFlipped]) + invalidRectInFrameViewCoordinates.setY(frameView->frameRect().size().height() - invalidRectInFrameViewCoordinates.bottom()); + + frameView->invalidateRect(invalidRectInFrameViewCoordinates); +} +#endif // USE(ACCELERATED_COMPOSITING) + @interface NSApplication (WebNSApplicationDetails) - (void)speakString:(NSString *)string; @end @@ -490,6 +528,7 @@ static NSCellStateValue kit(TriState state) + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif @@ -501,7 +540,17 @@ static NSCellStateValue kit(TriState state) oldSetCursorForMouseLocationIMP = method_setImplementation(setCursorMethod, (IMP)setCursor); ASSERT(oldSetCursorForMouseLocationIMP); } -#else + +#if USE(ACCELERATED_COMPOSITING) + if (!oldSetNeedsDisplayInRectIMP) { + Method setNeedsDisplayInRectMethod = class_getInstanceMethod([NSView class], @selector(setNeedsDisplayInRect:)); + ASSERT(setNeedsDisplayInRectMethod); + oldSetNeedsDisplayInRectIMP = method_setImplementation(setNeedsDisplayInRectMethod, (IMP)setNeedsDisplayInRect); + ASSERT(oldSetNeedsDisplayInRectIMP); + } +#endif // USE(ACCELERATED_COMPOSITING) + +#else // defined(BUILDING_ON_TIGER) if (!oldSetCursorIMP) { Method setCursorMethod = class_getInstanceMethod([NSCursor class], @selector(set)); ASSERT(setCursorMethod); @@ -2317,6 +2366,7 @@ static bool matchesExtensionOrEquivalent(NSString *filename, NSString *extension [NSApp registerServicesMenuSendTypes:[[self class] _selectionPasteboardTypes] returnTypes:[[self class] _insertablePasteboardTypes]]; JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif @@ -3308,16 +3358,14 @@ WEBCORE_COMMAND(yankAndSelect) if (subviewsWereSetAside) [self _setAsideSubviews]; - + #if USE(ACCELERATED_COMPOSITING) - if ([webView _needsOneShotDrawingSynchronization]) { - // Disable screen updates so that any layer changes committed here - // don't show up on the screen before the window flush at the end - // of the current window display, but only if a window flush is actually - // going to happen. - NSWindow *window = [self window]; - if ([window viewsNeedDisplay]) - [window disableScreenUpdatesUntilFlush]; + // Only do the synchronization dance if we're drawing into the window, otherwise + // we risk disabling screen updates when no flush is pending. + if ([NSGraphicsContext currentContext] == [[self window] graphicsContext] && [webView _needsOneShotDrawingSynchronization]) { + // Disable screen updates to minimize the chances of the race between the CA + // display link and AppKit drawing causing flashes. + [[self window] disableScreenUpdatesUntilFlush]; // Make sure any layer changes that happened as a result of layout // via -viewWillDraw are committed. @@ -3332,7 +3380,7 @@ WEBCORE_COMMAND(yankAndSelect) { if (!([[self superview] isKindOfClass:[WebClipView class]])) return [super visibleRect]; - + WebClipView *clipView = (WebClipView *)[self superview]; BOOL hasAdditionalClip = [clipView hasAdditionalClip]; diff --git a/WebKit/mac/WebView/WebPreferenceKeysPrivate.h b/WebKit/mac/WebView/WebPreferenceKeysPrivate.h index e74d0e5..f4ae333 100644 --- a/WebKit/mac/WebView/WebPreferenceKeysPrivate.h +++ b/WebKit/mac/WebView/WebPreferenceKeysPrivate.h @@ -84,6 +84,7 @@ #define WebKitEnableFullDocumentTeardownPreferenceKey @"WebKitEnableFullDocumentTeardown" #define WebKitOfflineWebApplicationCacheEnabledPreferenceKey @"WebKitOfflineWebApplicationCacheEnabled" #define WebKitZoomsTextOnlyPreferenceKey @"WebKitZoomsTextOnly" +#define WebKitJavaScriptCanAccessClipboardPreferenceKey @"WebKitJavaScriptCanAccessClipboard" #define WebKitXSSAuditorEnabledPreferenceKey @"WebKitXSSAuditorEnabled" #define WebKitAcceleratedCompositingEnabledPreferenceKey @"WebKitAcceleratedCompositingEnabled" #define WebKitShowDebugBordersPreferenceKey @"WebKitShowDebugBorders" diff --git a/WebKit/mac/WebView/WebPreferences.mm b/WebKit/mac/WebView/WebPreferences.mm index 84a6e9e..9de8495 100644 --- a/WebKit/mac/WebView/WebPreferences.mm +++ b/WebKit/mac/WebView/WebPreferences.mm @@ -350,6 +350,7 @@ static WebCacheModel cacheModelForMainBundle(void) [NSNumber numberWithBool:NO], WebKitLocalFileContentSniffingEnabledPreferenceKey, [NSNumber numberWithBool:NO], WebKitOfflineWebApplicationCacheEnabledPreferenceKey, [NSNumber numberWithBool:YES], WebKitZoomsTextOnlyPreferenceKey, + [NSNumber numberWithBool:NO], WebKitJavaScriptCanAccessClipboardPreferenceKey, [NSNumber numberWithBool:YES], WebKitXSSAuditorEnabledPreferenceKey, [NSNumber numberWithBool:YES], WebKitAcceleratedCompositingEnabledPreferenceKey, [NSNumber numberWithBool:NO], WebKitShowDebugBordersPreferenceKey, @@ -831,6 +832,16 @@ static WebCacheModel cacheModelForMainBundle(void) [self _setBoolValue:flag forKey:WebKitZoomsTextOnlyPreferenceKey]; } +- (BOOL)javaScriptCanAccessClipboard +{ + return [self _boolValueForKey:WebKitJavaScriptCanAccessClipboardPreferenceKey]; +} + +- (void)setJavaScriptCanAccessClipboard:(BOOL)flag +{ + [self _setBoolValue:flag forKey:WebKitJavaScriptCanAccessClipboardPreferenceKey]; +} + - (BOOL)isXSSAuditorEnabled { return [self _boolValueForKey:WebKitXSSAuditorEnabledPreferenceKey]; @@ -1097,8 +1108,8 @@ static WebCacheModel cacheModelForMainBundle(void) { NSString *systemEncodingName = (NSString *)CFStringConvertEncodingToIANACharSetName([self _systemCFStringEncoding]); - // CFStringConvertEncodingToIANACharSetName() returns cp949 for kTextEncodingDOSKorean AKA "extended EUC-KR" AKA windows-939. - // ICU uses this name for a different encoding, so we need to change the name to a value that actually gives us windows-939. + // CFStringConvertEncodingToIANACharSetName() returns cp949 for kTextEncodingDOSKorean AKA "extended EUC-KR" AKA windows-949. + // ICU uses this name for a different encoding, so we need to change the name to a value that actually gives us windows-949. // In addition, this value must match what is used in Safari, see <rdar://problem/5579292>. // On some OS versions, the result is CP949 (uppercase). if ([systemEncodingName _webkit_isCaseInsensitiveEqualToString:@"cp949"]) diff --git a/WebKit/mac/WebView/WebPreferencesPrivate.h b/WebKit/mac/WebView/WebPreferencesPrivate.h index 0b5f969..ee785e9 100644 --- a/WebKit/mac/WebView/WebPreferencesPrivate.h +++ b/WebKit/mac/WebView/WebPreferencesPrivate.h @@ -107,6 +107,9 @@ extern NSString *WebPreferencesRemovedNotification; - (BOOL)zoomsTextOnly; - (void)setZoomsTextOnly:(BOOL)zoomsTextOnly; +- (BOOL)javaScriptCanAccessClipboard; +- (void)setJavaScriptCanAccessClipboard:(BOOL)flag; + - (BOOL)isXSSAuditorEnabled; - (void)setXSSAuditorEnabled:(BOOL)flag; diff --git a/WebKit/mac/WebView/WebResource.mm b/WebKit/mac/WebView/WebResource.mm index 735e213..73c0118 100644 --- a/WebKit/mac/WebView/WebResource.mm +++ b/WebKit/mac/WebView/WebResource.mm @@ -43,6 +43,7 @@ #import <WebCore/ThreadCheck.h> #import <WebCore/WebCoreObjCExtras.h> #import <WebCore/WebCoreURLResponse.h> +#import <wtf/Threading.h> using namespace WebCore; @@ -65,6 +66,7 @@ static NSString * const WebResourceResponseKey = @"WebResourceResponse" + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebKit/mac/WebView/WebResourceLoadDelegatePrivate.h b/WebKit/mac/WebView/WebResourceLoadDelegatePrivate.h index 6dc3f2d..45d9c09 100644 --- a/WebKit/mac/WebView/WebResourceLoadDelegatePrivate.h +++ b/WebKit/mac/WebView/WebResourceLoadDelegatePrivate.h @@ -43,6 +43,16 @@ - (void)webView:(WebView *)webView didLoadResourceFromMemoryCache:(NSURLRequest *)request response:(NSURLResponse *)response length:(WebNSInteger)length fromDataSource:(WebDataSource *)dataSource; - (BOOL)webView:(WebView *)webView resource:(id)identifier shouldUseCredentialStorageForDataSource:(WebDataSource *)dataSource; +#if WEBKIT_VERSION_MAX_ALLOWED > WEBKIT_VERSION_4_0 +/*! + @method webView:resource:canAuthenticateAgainstProtectionSpace:forDataSource: + @abstract Inspect an NSURLProtectionSpace before an authentication attempt is made. Only used on Snow Leopard or newer. + @param protectionSpace an NSURLProtectionSpace that will be used to generate an authentication challenge + @result Return YES if the resource load delegate is prepared to respond to an authentication challenge generated with protectionSpace, NO otherwise + */ +- (BOOL)webView:(WebView *)sender resource:(id)identifier canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace forDataSource:(WebDataSource *)dataSource; +#endif + @end #undef WebNSInteger diff --git a/WebKit/mac/WebView/WebTextIterator.mm b/WebKit/mac/WebView/WebTextIterator.mm index 457bece..6029faa 100644 --- a/WebKit/mac/WebView/WebTextIterator.mm +++ b/WebKit/mac/WebView/WebTextIterator.mm @@ -31,6 +31,8 @@ #import <JavaScriptCore/Vector.h> #import <WebCore/TextIterator.h> #import <WebCore/WebCoreObjCExtras.h> +#import <runtime/InitializeThreading.h> +#import <wtf/Threading.h> using namespace JSC; using namespace WebCore; @@ -45,6 +47,8 @@ using namespace WebCore; + (void)initialize { + JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebKit/mac/WebView/WebView.mm b/WebKit/mac/WebView/WebView.mm index b1b5c38..2442846 100644 --- a/WebKit/mac/WebView/WebView.mm +++ b/WebKit/mac/WebView/WebView.mm @@ -166,6 +166,7 @@ #import <wtf/RefCountedLeakCounter.h> #import <wtf/RefPtr.h> #import <wtf/StdLibExtras.h> +#import <wtf/Threading.h> #if ENABLE(DASHBOARD_SUPPORT) #import <WebKit/WebDashboardRegion.h> @@ -188,6 +189,7 @@ @interface NSWindow (WebNSWindowDetails) - (id)_oldFirstResponderBeforeBecoming; +- (void)_enableScreenUpdatesIfNeeded; @end using namespace WebCore; @@ -758,10 +760,9 @@ static bool shouldEnableLoadDeferring() @try { [[self mainFrame] _drawRect:rect contentsOnly:NO]; - WebView *webView = [self _webView]; - [[webView _UIDelegateForwarder] webView:webView didDrawRect:rect]; + [[self _UIDelegateForwarder] webView:self didDrawRect:rect]; - if (WebNodeHighlight *currentHighlight = [webView currentNodeHighlight]) + if (WebNodeHighlight *currentHighlight = [self currentNodeHighlight]) [currentHighlight setNeedsUpdateInTargetViewRect:rect]; [NSGraphicsContext restoreGraphicsState]; @@ -860,6 +861,25 @@ static bool shouldEnableLoadDeferring() return uniqueExtensions; } +static NSMutableSet *knownPluginMIMETypes() +{ + static NSMutableSet *mimeTypes = [[NSMutableSet alloc] init]; + + return mimeTypes; +} + ++ (void)_registerPluginMIMEType:(NSString *)MIMEType +{ + [WebView registerViewClass:[WebHTMLView class] representationClass:[WebHTMLRepresentation class] forMIMEType:MIMEType]; + [knownPluginMIMETypes() addObject:MIMEType]; +} + ++ (void)_unregisterPluginMIMEType:(NSString *)MIMEType +{ + [self _unregisterViewClassAndRepresentationClassForMIMEType:MIMEType]; + [knownPluginMIMETypes() removeObject:MIMEType]; +} + + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins { MIMEType = [MIMEType lowercaseString]; @@ -880,11 +900,20 @@ static bool shouldEnableLoadDeferring() } if (viewClass && repClass) { - // Special-case WebHTMLView for text types that shouldn't be shown. - if (viewClass == [WebHTMLView class] && - repClass == [WebHTMLRepresentation class] && - [[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType]) { - return NO; + if (viewClass == [WebHTMLView class] && repClass == [WebHTMLRepresentation class]) { + // Special-case WebHTMLView for text types that shouldn't be shown. + if ([[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType]) + return NO; + + // If the MIME type is a known plug-in we might not want to load it. + if (!allowPlugins && [knownPluginMIMETypes() containsObject:MIMEType]) { + BOOL isSupportedByWebKit = [[WebHTMLView supportedNonImageMIMETypes] containsObject:MIMEType] || + [[WebHTMLView supportedMIMETypes] containsObject:MIMEType]; + + // If this is a known plug-in MIME type and WebKit can't show it natively, we don't want to show it. + if (!isSupportedByWebKit) + return NO; + } } if (vClass) *vClass = viewClass; @@ -898,7 +927,7 @@ static bool shouldEnableLoadDeferring() - (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType { - if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType allowingPlugins:[[[self _webView] preferences] arePlugInsEnabled]]) + if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]]) return YES; if (_private->pluginDatabase) { @@ -935,7 +964,9 @@ static bool shouldEnableLoadDeferring() DOMWindow::dispatchAllPendingUnloadEvents(); // This will close the WebViews in a random order. Change this if close order is important. - NSEnumerator *enumerator = [(NSMutableSet *)allWebViewsSet objectEnumerator]; + // Make a new set to avoid mutating the set we are enumerating. + NSSet *webViewsToClose = [NSSet setWithSet:(NSSet *)allWebViewsSet]; + NSEnumerator *enumerator = [webViewsToClose objectEnumerator]; while (WebView *webView = [enumerator nextObject]) [webView close]; } @@ -1013,6 +1044,7 @@ static bool fastDocumentTeardownEnabled() return; _private->closed = YES; + [self _removeFromAllWebViewsSet]; [self _closingEventHandling]; @@ -1034,7 +1066,6 @@ static bool fastDocumentTeardownEnabled() if (Frame* mainFrame = [self _mainCoreFrame]) mainFrame->loader()->detachFromParent(); - [self _removeFromAllWebViewsSet]; [self setHostWindow:nil]; [self setDownloadDelegate:nil]; @@ -1345,6 +1376,7 @@ static bool fastDocumentTeardownEnabled() settings->setLocalFileContentSniffingEnabled([preferences localFileContentSniffingEnabled]); settings->setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]); settings->setZoomMode([preferences zoomsTextOnly] ? ZoomTextOnly : ZoomPage); + settings->setJavaScriptCanAccessClipboard([preferences javaScriptCanAccessClipboard]); settings->setXSSAuditorEnabled([preferences isXSSAuditorEnabled]); settings->setEnforceCSSMIMETypeInStrictMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1)); @@ -1379,6 +1411,9 @@ static inline IMP getMethod(id o, SEL s) cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:)); cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:)); cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:)); +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + cache->canAuthenticateAgainstProtectionSpaceFunc = getMethod(delegate, @selector(webView:resource:canAuthenticateAgainstProtectionSpace:forDataSource:)); +#endif cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:)); cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:)); cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:)); @@ -2460,6 +2495,8 @@ static PassOwnPtr<Vector<String> > toStringVector(NSArray* patterns) initialized = YES; InitWebCoreSystemInterface(); + JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedNotification object:nil]; @@ -2504,7 +2541,7 @@ static PassOwnPtr<Vector<String> > toStringVector(NSArray* patterns) - (BOOL)_canShowMIMEType:(NSString *)MIMEType { - return [[self class] _canShowMIMEType:MIMEType allowingPlugins:[[[self _webView] preferences] arePlugInsEnabled]]; + return [[self class] _canShowMIMEType:MIMEType allowingPlugins:[_private->preferences arePlugInsEnabled]]; } - (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType @@ -5604,9 +5641,27 @@ static WebFrameView *containingFrameView(NSView *view) static void layerSyncRunLoopObserverCallBack(CFRunLoopObserverRef, CFRunLoopActivity, void* info) { - WebView* webView = reinterpret_cast<WebView*>(info); - if ([webView _syncCompositingChanges]) + WebView *webView = reinterpret_cast<WebView*>(info); + NSWindow *window = [webView window]; + + // An NSWindow may not display in the next runloop cycle after dirtying due to delayed window display logic, + // in which case this observer can fire first. So if the window is due for a display, don't commit + // layer changes, otherwise they'll show on screen before the view drawing. + if ([window viewsNeedDisplay]) + return; + + if ([webView _syncCompositingChanges]) { [webView _clearLayerSyncLoopObserver]; + // AppKit may have disabled screen updates, thinking an upcoming window flush will re-enable them. + // In case setNeedsDisplayInRect() has prevented the window from needing to be flushed, re-enable screen + // updates here. + if (![window isFlushWindowDisabled]) + [window _enableScreenUpdatesIfNeeded]; + } else { + // Since the WebView does not need display, -viewWillDraw will not be called. Perform pending layout now, + // so that the layers draw with up-to-date layout. + [webView _viewWillDrawInternal]; + } } - (void)_scheduleCompositingLayerSync diff --git a/WebKit/mac/WebView/WebViewData.mm b/WebKit/mac/WebView/WebViewData.mm index bf81dad..06da58f 100644 --- a/WebKit/mac/WebView/WebViewData.mm +++ b/WebKit/mac/WebView/WebViewData.mm @@ -34,6 +34,7 @@ #import <WebCore/WebCoreObjCExtras.h> #import <objc/objc-auto.h> #import <runtime/InitializeThreading.h> +#import <wtf/Threading.h> BOOL applicationIsTerminating = NO; int pluginDatabaseClientCount = 0; @@ -43,6 +44,7 @@ int pluginDatabaseClientCount = 0; + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebKit/mac/WebView/WebViewInternal.h b/WebKit/mac/WebView/WebViewInternal.h index a2ce646..4643573 100644 --- a/WebKit/mac/WebView/WebViewInternal.h +++ b/WebKit/mac/WebView/WebViewInternal.h @@ -117,6 +117,8 @@ namespace WebCore { - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame; + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins; - (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType; ++ (void)_registerPluginMIMEType:(NSString *)MIMEType; ++ (void)_unregisterPluginMIMEType:(NSString *)MIMEType; + (BOOL)_canShowMIMEType:(NSString *)MIMEType allowingPlugins:(BOOL)allowPlugins; - (BOOL)_canShowMIMEType:(NSString *)MIMEType; + (NSString *)_MIMETypeForFile:(NSString *)path; diff --git a/WebKit/qt/Api/qgraphicswebview.cpp b/WebKit/qt/Api/qgraphicswebview.cpp index c865c4d..821e699 100644 --- a/WebKit/qt/Api/qgraphicswebview.cpp +++ b/WebKit/qt/Api/qgraphicswebview.cpp @@ -292,6 +292,7 @@ void QGraphicsWebViewPrivate::update(const QRect & dirtyRect) if (overlay) overlay->update(QRectF(dirtyRect)); #if USE(ACCELERATED_COMPOSITING) + updateCompositingScrollPosition(); syncLayers(); #endif } @@ -649,10 +650,13 @@ QVariant QGraphicsWebView::itemChange(GraphicsItemChange change, const QVariant& // fire 'CursorChange'. case ItemCursorChange: return value; - case ItemCursorHasChanged: - QEvent event(QEvent::CursorChange); - QApplication::sendEvent(this, &event); - return value; + case ItemCursorHasChanged: { + QEvent event(QEvent::CursorChange); + QApplication::sendEvent(this, &event); + return value; + } + default: + break; } return QGraphicsWidget::itemChange(change, value); diff --git a/WebKit/qt/Api/qwebelement.cpp b/WebKit/qt/Api/qwebelement.cpp index 8af7203..551346b 100644 --- a/WebKit/qt/Api/qwebelement.cpp +++ b/WebKit/qt/Api/qwebelement.cpp @@ -821,7 +821,7 @@ QString QWebElement::styleProperty(const QString &name, StyleResolveStrategy str int propID = cssPropertyID(name); - RefPtr<CSSComputedStyleDeclaration> style = computedStyle(m_element); + RefPtr<CSSComputedStyleDeclaration> style = computedStyle(m_element, true); if (!propID || !style) return QString(); diff --git a/WebKit/qt/Api/qwebkitversion.h b/WebKit/qt/Api/qwebkitversion.h index f0fbef0..de79dd1 100644 --- a/WebKit/qt/Api/qwebkitversion.h +++ b/WebKit/qt/Api/qwebkitversion.h @@ -17,7 +17,7 @@ Boston, MA 02110-1301, USA. */ -#include <qstring.h> +#include <QtCore/qstring.h> #ifndef qwebkitversion_h #define qwebkitversion_h diff --git a/WebKit/qt/Api/qwebpage.cpp b/WebKit/qt/Api/qwebpage.cpp index 0e11c15..c9fc210 100644 --- a/WebKit/qt/Api/qwebpage.cpp +++ b/WebKit/qt/Api/qwebpage.cpp @@ -81,8 +81,9 @@ #include "runtime/InitializeThreading.h" #include "PageGroup.h" #include "NotificationPresenterClientQt.h" -#include "QWebPageClient.h" +#include "PageClientQt.h" #include "WorkerThread.h" +#include "wtf/Threading.h" #include <QApplication> #include <QBasicTimer> @@ -120,126 +121,8 @@ using namespace WebCore; -void QWEBKIT_EXPORT qt_wrt_setViewMode(QWebPage* page, const QString& mode) -{ - QWebPagePrivate::priv(page)->viewMode = mode; - WebCore::Frame* frame = QWebFramePrivate::core(page->mainFrame()); - WebCore::FrameView* view = frame->view(); - frame->document()->updateStyleSelector(); - view->forceLayout(); -} - bool QWebPagePrivate::drtRun = false; -class QWebPageWidgetClient : public QWebPageClient { -public: - QWebPageWidgetClient(QWidget* view) - : view(view) - { - Q_ASSERT(view); - } - - virtual bool isQWidgetClient() const { return true; } - - virtual void scroll(int dx, int dy, const QRect&); - virtual void update(const QRect& dirtyRect); - virtual void setInputMethodEnabled(bool enable); - virtual bool inputMethodEnabled() const; -#if QT_VERSION >= 0x040600 - virtual void setInputMethodHint(Qt::InputMethodHint hint, bool enable); -#endif - -#ifndef QT_NO_CURSOR - virtual QCursor cursor() const; - virtual void updateCursor(const QCursor& cursor); -#endif - - virtual QPalette palette() const; - virtual int screenNumber() const; - virtual QWidget* ownerWidget() const; - virtual QRect geometryRelativeToOwnerWidget() const; - - virtual QObject* pluginParent() const; - - virtual QStyle* style() const; - - QWidget* view; -}; - -void QWebPageWidgetClient::scroll(int dx, int dy, const QRect& rectToScroll) -{ - view->scroll(qreal(dx), qreal(dy), rectToScroll); -} - -void QWebPageWidgetClient::update(const QRect & dirtyRect) -{ - view->update(dirtyRect); -} - -void QWebPageWidgetClient::setInputMethodEnabled(bool enable) -{ - view->setAttribute(Qt::WA_InputMethodEnabled, enable); -} - -bool QWebPageWidgetClient::inputMethodEnabled() const -{ - return view->testAttribute(Qt::WA_InputMethodEnabled); -} - -#if QT_VERSION >= 0x040600 -void QWebPageWidgetClient::setInputMethodHint(Qt::InputMethodHint hint, bool enable) -{ - if (enable) - view->setInputMethodHints(view->inputMethodHints() | hint); - else - view->setInputMethodHints(view->inputMethodHints() & ~hint); -} -#endif -#ifndef QT_NO_CURSOR -QCursor QWebPageWidgetClient::cursor() const -{ - return view->cursor(); -} - -void QWebPageWidgetClient::updateCursor(const QCursor& cursor) -{ - view->setCursor(cursor); -} -#endif - -QPalette QWebPageWidgetClient::palette() const -{ - return view->palette(); -} - -int QWebPageWidgetClient::screenNumber() const -{ -#if defined(Q_WS_X11) - return view->x11Info().screen(); -#endif - return 0; -} - -QWidget* QWebPageWidgetClient::ownerWidget() const -{ - return view; -} - -QRect QWebPageWidgetClient::geometryRelativeToOwnerWidget() const -{ - return view->geometry(); -} - -QObject* QWebPageWidgetClient::pluginParent() const -{ - return view; -} - -QStyle* QWebPageWidgetClient::style() const -{ - return view->style(); -} - // Lookup table mapping QWebPage::WebActions to the associated Editor commands static const char* editorCommandWebActions[] = { @@ -382,6 +265,7 @@ QWebPagePrivate::QWebPagePrivate(QWebPage *qq) { WebCore::InitializeLoggingChannelsIfNecessary(); JSC::initializeThreading(); + WTF::initializeMainThread(); WebCore::SecurityOrigin::setLocalLoadPolicy(WebCore::SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData); chromeClient = new ChromeClientQt(q); @@ -406,7 +290,7 @@ QWebPagePrivate::QWebPagePrivate(QWebPage *qq) #ifndef QT_NO_CONTEXTMENU currentContextMenu = 0; #endif - smartInsertDeleteEnabled = false; + smartInsertDeleteEnabled = true; selectTrailingWhitespaceEnabled = false; history.d = new QWebHistoryPrivate(page->backForwardList()); @@ -1054,10 +938,6 @@ void QWebPagePrivate::keyPressEvent(QKeyEvent *ev) handled = frame->eventHandler()->keyEvent(ev); if (!handled) { handled = true; - QFont defaultFont; - if (client) - defaultFont = client->ownerWidget()->font(); - QFontMetrics fm(defaultFont); if (!handleScrolling(ev, frame)) { switch (ev->key()) { case Qt::Key_Back: @@ -1248,6 +1128,9 @@ void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev) { WebCore::Frame *frame = page->focusController()->focusedOrMainFrame(); WebCore::Editor *editor = frame->editor(); +#if QT_VERSION >= 0x040600 + QInputMethodEvent::Attribute selection(QInputMethodEvent::Selection, 0, 0, QVariant()); +#endif if (!editor->canEdit()) { ev->ignore(); @@ -1264,6 +1147,7 @@ void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev) renderTextControl = toRenderTextControl(renderer); Vector<CompositionUnderline> underlines; + bool hasSelection = false; for (int i = 0; i < ev->attributes().size(); ++i) { const QInputMethodEvent::Attribute& a = ev->attributes().at(i); @@ -1287,10 +1171,8 @@ void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev) } #if QT_VERSION >= 0x040600 case QInputMethodEvent::Selection: { - if (renderTextControl) { - renderTextControl->setSelectionStart(qMin(a.start, (a.start + a.length))); - renderTextControl->setSelectionEnd(qMax(a.start, (a.start + a.length))); - } + selection = a; + hasSelection = true; break; } #endif @@ -1299,13 +1181,48 @@ void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev) if (!ev->commitString().isEmpty()) editor->confirmComposition(ev->commitString()); - else if (!ev->preeditString().isEmpty()) { + else { + // 1. empty preedit with a selection attribute, and start/end of 0 cancels composition + // 2. empty preedit with a selection attribute, and start/end of non-0 updates selection of current preedit text + // 3. populated preedit with a selection attribute, and start/end of 0 or non-0 updates selection of supplied preedit text + // 4. otherwise event is updating supplied pre-edit text QString preedit = ev->preeditString(); - editor->setComposition(preedit, underlines, preedit.length(), 0); +#if QT_VERSION >= 0x040600 + if (hasSelection) { + QString text = (renderTextControl) ? QString(renderTextControl->text()) : QString(); + if (preedit.isEmpty() && selection.start + selection.length > 0) + preedit = text; + editor->setComposition(preedit, underlines, + (selection.length < 0) ? selection.start + selection.length : selection.start, + (selection.length < 0) ? selection.start : selection.start + selection.length); + } else +#endif + editor->setComposition(preedit, underlines, preedit.length(), 0); } + ev->accept(); } +void QWebPagePrivate::dynamicPropertyChangeEvent(QDynamicPropertyChangeEvent* event) +{ + if (event->propertyName() == "_q_viewMode") { + QString mode = q->property("_q_viewMode").toString(); + if (mode != viewMode) { + viewMode = mode; + WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame()); + WebCore::FrameView* view = frame->view(); + frame->document()->updateStyleSelector(); + view->layout(); + } + } else if (event->propertyName() == "_q_HTMLTokenizerChunkSize") { + int chunkSize = q->property("_q_HTMLTokenizerChunkSize").toInt(); + q->handle()->page->setCustomHTMLTokenizerChunkSize(chunkSize); + } else if (event->propertyName() == "_q_HTMLTokenizerTimeDelay") { + double timeDelay = q->property("_q_HTMLTokenizerTimeDelay").toDouble(); + q->handle()->page->setCustomHTMLTokenizerTimeDelay(timeDelay); + } +} + void QWebPagePrivate::shortcutOverrideEvent(QKeyEvent* event) { WebCore::Frame* frame = page->focusController()->focusedOrMainFrame(); @@ -1437,7 +1354,7 @@ QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const // We can't access absoluteCaretBounds() while the view needs to layout. return QVariant(); } - return QVariant(frame->selection()->absoluteCaretBounds()); + return QVariant(view->contentsToWindow(frame->selection()->absoluteCaretBounds())); } case Qt::ImFont: { if (renderTextControl) { @@ -1854,12 +1771,12 @@ void QWebPage::setView(QWidget* view) if (d->client) { if (d->client->isQWidgetClient()) - static_cast<QWebPageWidgetClient*>(d->client)->view = view; + static_cast<PageClientQWidget*>(d->client)->view = view; return; } if (view) - d->client = new QWebPageWidgetClient(view); + d->client = new PageClientQWidget(view); } /*! @@ -1993,9 +1910,9 @@ QWebPage *QWebPage::createWindow(WebWindowType type) } /*! - This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin". - The \a classid, \a url, \a paramNames and \a paramValues correspond to the HTML object element attributes and - child elements to configure the embeddable object. + This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin". It is + called regardless of the value of QWebSettings::PluginsEnabled. The \a classid, \a url, \a paramNames and \a paramValues + correspond to the HTML object element attributes and child elements to configure the embeddable object. */ QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues) { @@ -2153,7 +2070,6 @@ void QWebPage::setViewportSize(const QSize &size) const if (frame->d->frame && frame->d->frame->view()) { WebCore::FrameView* view = frame->d->frame->view(); view->setFrameRect(QRect(QPoint(0, 0), size)); - view->forceLayout(); view->adjustViewSize(); } } @@ -2190,10 +2106,10 @@ void QWebPage::setPreferredContentsSize(const QSize &size) const if (size.isValid()) { view->setUseFixedLayout(true); view->setFixedLayoutSize(size); - view->forceLayout(); + view->layout(); } else if (view->useFixedLayout()) { view->setUseFixedLayout(false); - view->forceLayout(); + view->layout(); } } } @@ -2654,6 +2570,9 @@ bool QWebPage::event(QEvent *ev) d->touchEvent(static_cast<QTouchEvent*>(ev)); break; #endif + case QEvent::DynamicPropertyChange: + d->dynamicPropertyChangeEvent(static_cast<QDynamicPropertyChangeEvent*>(ev)); + break; default: return QObject::event(ev); } @@ -3137,233 +3056,255 @@ QWebPluginFactory *QWebPage::pluginFactory() const \o %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version. \endlist */ -QString QWebPage::userAgentForUrl(const QUrl& url) const +QString QWebPage::userAgentForUrl(const QUrl&) const { - Q_UNUSED(url) - QString ua = QLatin1String("Mozilla/5.0 (" + // splitting the string in three and user QStringBuilder is better than using QString::arg() + static QString firstPart; + static QString secondPart; + static QString thirdPart; + + if (firstPart.isNull() || secondPart.isNull() || thirdPart.isNull()) { + QString firstPartTemp; + firstPartTemp.reserve(150); + firstPartTemp += QString::fromLatin1("Mozilla/5.0 (" // Platform #ifdef Q_WS_MAC - "Macintosh" + "Macintosh" #elif defined Q_WS_QWS - "QtEmbedded" + "QtEmbedded" #elif defined Q_WS_WIN - "Windows" + "Windows" #elif defined Q_WS_X11 - "X11" + "X11" #elif defined Q_OS_SYMBIAN - "SymbianOS" + "SymbianOS" #else - "Unknown" + "Unknown" #endif - // Placeholder for Platform Version - "%1; " + ); - // Placeholder for security strength (N or U) - "%2; " + firstPartTemp += QString::fromLatin1("; "); + + // SSL support +#if !defined(QT_NO_OPENSSL) + // we could check QSslSocket::supportsSsl() here, but this makes + // OpenSSL, certificates etc being loaded in all cases were QWebPage + // is used. This loading is not needed for non-https. + firstPartTemp += QString::fromLatin1("U; "); + // this may lead to a false positive: We indicate SSL since it is + // compiled in even though supportsSsl() might return false +#else + firstPartTemp += QString::fromLatin1("N; "); +#endif - // Subplatform" + // Operating system #ifdef Q_OS_AIX - "AIX" + firstPartTemp += QString::fromLatin1("AIX"); #elif defined Q_OS_WIN32 - "%3" + + switch (QSysInfo::WindowsVersion) { + case QSysInfo::WV_32s: + firstPartTemp += QString::fromLatin1("Windows 3.1"); + break; + case QSysInfo::WV_95: + firstPartTemp += QString::fromLatin1("Windows 95"); + break; + case QSysInfo::WV_98: + firstPartTemp += QString::fromLatin1("Windows 98"); + break; + case QSysInfo::WV_Me: + firstPartTemp += QString::fromLatin1("Windows 98; Win 9x 4.90"); + break; + case QSysInfo::WV_NT: + firstPartTemp += QString::fromLatin1("WinNT4.0"); + break; + case QSysInfo::WV_2000: + firstPartTemp += QString::fromLatin1("Windows NT 5.0"); + break; + case QSysInfo::WV_XP: + firstPartTemp += QString::fromLatin1("Windows NT 5.1"); + break; + case QSysInfo::WV_2003: + firstPartTemp += QString::fromLatin1("Windows NT 5.2"); + break; + case QSysInfo::WV_VISTA: + firstPartTemp += QString::fromLatin1("Windows NT 6.0"); + break; + case QSysInfo::WV_WINDOWS7: + firstPartTemp += QString::fromLatin1("Windows NT 6.1"); + break; + case QSysInfo::WV_CE: + firstPartTemp += QString::fromLatin1("Windows CE"); + break; + case QSysInfo::WV_CENET: + firstPartTemp += QString::fromLatin1("Windows CE .NET"); + break; + case QSysInfo::WV_CE_5: + firstPartTemp += QString::fromLatin1("Windows CE 5.x"); + break; + case QSysInfo::WV_CE_6: + firstPartTemp += QString::fromLatin1("Windows CE 6.x"); + break; + } + #elif defined Q_OS_DARWIN #ifdef __i386__ || __x86_64__ - "Intel Mac OS X" + firstPartTemp += QString::fromLatin1("Intel Mac OS X"); #else - "PPC Mac OS X" + firstPartTemp += QString::fromLatin1("PPC Mac OS X"); #endif #elif defined Q_OS_BSDI - "BSD" + firstPartTemp += QString::fromLatin1("BSD"); #elif defined Q_OS_BSD4 - "BSD Four" + firstPartTemp += QString::fromLatin1("BSD Four"); #elif defined Q_OS_CYGWIN - "Cygwin" + firstPartTemp += QString::fromLatin1("Cygwin"); #elif defined Q_OS_DGUX - "DG/UX" + firstPartTemp += QString::fromLatin1("DG/UX"); #elif defined Q_OS_DYNIX - "DYNIX/ptx" + firstPartTemp += QString::fromLatin1("DYNIX/ptx"); #elif defined Q_OS_FREEBSD - "FreeBSD" + firstPartTemp += QString::fromLatin1("FreeBSD"); #elif defined Q_OS_HPUX - "HP-UX" + firstPartTemp += QString::fromLatin1("HP-UX"); #elif defined Q_OS_HURD - "GNU Hurd" + firstPartTemp += QString::fromLatin1("GNU Hurd"); #elif defined Q_OS_IRIX - "SGI Irix" + firstPartTemp += QString::fromLatin1("SGI Irix"); #elif defined Q_OS_LINUX - "Linux" + +#if defined(__x86_64__) + firstPartTemp += QString::fromLatin1("Linux x86_64"); +#elif defined(__i386__) + firstPartTemp += QString::fromLatin1("Linux i686"); +#else + firstPartTemp += QString::fromLatin1("Linux"); +#endif + #elif defined Q_OS_LYNX - "LynxOS" + firstPartTemp += QString::fromLatin1("LynxOS"); #elif defined Q_OS_NETBSD - "NetBSD" + firstPartTemp += QString::fromLatin1("NetBSD"); #elif defined Q_OS_OS2 - "OS/2" + firstPartTemp += QString::fromLatin1("OS/2"); #elif defined Q_OS_OPENBSD - "OpenBSD" + firstPartTemp += QString::fromLatin1("OpenBSD"); #elif defined Q_OS_OS2EMX - "OS/2" + firstPartTemp += QString::fromLatin1("OS/2"); #elif defined Q_OS_OSF - "HP Tru64 UNIX" + firstPartTemp += QString::fromLatin1("HP Tru64 UNIX"); #elif defined Q_OS_QNX6 - "QNX RTP Six" + firstPartTemp += QString::fromLatin1("QNX RTP Six"); #elif defined Q_OS_QNX - "QNX" + firstPartTemp += QString::fromLatin1("QNX"); #elif defined Q_OS_RELIANT - "Reliant UNIX" + firstPartTemp += QString::fromLatin1("Reliant UNIX"); #elif defined Q_OS_SCO - "SCO OpenServer" + firstPartTemp += QString::fromLatin1("SCO OpenServer"); #elif defined Q_OS_SOLARIS - "Sun Solaris" + firstPartTemp += QString::fromLatin1("Sun Solaris"); #elif defined Q_OS_ULTRIX - "DEC Ultrix" -#elif defined Q_WS_S60 - "Series60" -#elif defined Q_OS_UNIX - "UNIX BSD/SYSV system" -#elif defined Q_OS_UNIXWARE - "UnixWare Seven, Open UNIX Eight" -#else - "Unknown" -#endif - // Placeholder for SubPlatform Version - "%4; "); - - // Platform Version - QString osVer; -#ifdef Q_OS_SYMBIAN - QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion(); - switch (symbianVersion) { - case QSysInfo::SV_9_2: - osVer = "/9.2"; - break; - case QSysInfo::SV_9_3: - osVer = "/9.3"; - break; - case QSysInfo::SV_9_4: - osVer = "/9.4"; - break; - default: - osVer = "Unknown"; - } -#endif - ua = ua.arg(osVer); - - QChar securityStrength(QLatin1Char('N')); -#if !defined(QT_NO_OPENSSL) - // we could check QSslSocket::supportsSsl() here, but this makes - // OpenSSL, certificates etc being loaded in all cases were QWebPage - // is used. This loading is not needed for non-https. - securityStrength = QLatin1Char('U'); - // this may lead to a false positive: We indicate SSL since it is - // compiled in even though supportsSsl() might return false -#endif - ua = ua.arg(securityStrength); - -#if defined Q_OS_WIN32 - QString ver; - switch (QSysInfo::WindowsVersion) { - case QSysInfo::WV_32s: - ver = "Windows 3.1"; - break; - case QSysInfo::WV_95: - ver = "Windows 95"; - break; - case QSysInfo::WV_98: - ver = "Windows 98"; - break; - case QSysInfo::WV_Me: - ver = "Windows 98; Win 9x 4.90"; - break; - case QSysInfo::WV_NT: - ver = "WinNT4.0"; + firstPartTemp += QString::fromLatin1("DEC Ultrix"); +#elif defined Q_OS_SYMBIAN + firstPartTemp += QString::fromLatin1("SymbianOS"); + QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion(); + switch (symbianVersion) { + case QSysInfo::SV_9_2: + firstPartTemp += QString::fromLatin1("/9.2"); break; - case QSysInfo::WV_2000: - ver = "Windows NT 5.0"; + case QSysInfo::SV_9_3: + firstPartTemp += QString::fromLatin1("/9.3"); break; - case QSysInfo::WV_XP: - ver = "Windows NT 5.1"; + case QSysInfo::SV_9_4: + firstPartTemp += QString::fromLatin1("/9.4"); break; - case QSysInfo::WV_2003: - ver = "Windows NT 5.2"; + default: + firstPartTemp += QString::fromLatin1("/Unknown"); + } + +#if defined Q_WS_S60 + firstPartTemp += QLatin1Char(' '); + firstPartTemp += QString::fromLatin1("Series60"); + QSysInfo::S60Version s60Version = QSysInfo::s60Version(); + switch (s60Version) { + case QSysInfo::SV_S60_3_1: + firstPartTemp += QString::fromLatin1("/3.1"); break; - case QSysInfo::WV_VISTA: - ver = "Windows NT 6.0"; + case QSysInfo::SV_S60_3_2: + firstPartTemp += QString::fromLatin1("/3.2"); break; -#if QT_VERSION > 0x040500 - case QSysInfo::WV_WINDOWS7: - ver = "Windows NT 6.1"; + case QSysInfo::SV_S60_5_0: + firstPartTemp += QString::fromLatin1("/5.0"); break; + default: + firstPartTemp += QString::fromLatin1("/Unknown"); + } #endif - case QSysInfo::WV_CE: - ver = "Windows CE"; - break; - case QSysInfo::WV_CENET: - ver = "Windows CE .NET"; - break; - case QSysInfo::WV_CE_5: - ver = "Windows CE 5.x"; - break; - case QSysInfo::WV_CE_6: - ver = "Windows CE 6.x"; - break; - } - ua = QString(ua).arg(ver); + +#elif defined Q_OS_UNIX + firstPartTemp += QString::fromLatin1("UNIX BSD/SYSV system"); +#elif defined Q_OS_UNIXWARE + firstPartTemp += QString::fromLatin1("UnixWare Seven, Open UNIX Eight"); +#else + firstPartTemp += QString::fromLatin1("Unknown"); #endif - // SubPlatform Version - QString subPlatformVer; -#ifdef Q_OS_SYMBIAN - QSysInfo::S60Version s60Version = QSysInfo::s60Version(); - switch (s60Version) { - case QSysInfo::SV_S60_3_1: - subPlatformVer = "/3.1"; - break; - case QSysInfo::SV_S60_3_2: - subPlatformVer = "/3.2"; - break; - case QSysInfo::SV_S60_5_0: - subPlatformVer = "/5.0"; - break; - default: - subPlatformVer = " Unknown"; - } + // language is the split + firstPartTemp += QString::fromLatin1("; "); + firstPartTemp.squeeze(); + firstPart = firstPartTemp; + + QString secondPartTemp; + secondPartTemp.reserve(150); + secondPartTemp += QString::fromLatin1(") "); + + // webkit/qt version + secondPartTemp += QString::fromLatin1("AppleWebKit/"); + secondPartTemp += qWebKitVersion(); + secondPartTemp += QString::fromLatin1(" (KHTML, like Gecko) "); + + + // Application name split the third part + secondPartTemp.squeeze(); + secondPart = secondPartTemp; + + QString thirdPartTemp; + thirdPartTemp.reserve(150); +#if defined(Q_WS_S60) || defined(Q_WS_MAEMO_5) + thirdPartTemp + QLatin1String(" Mobile Safari/"); +#else + thirdPartTemp += QLatin1String(" Safari/"); #endif - ua = ua.arg(subPlatformVer); + thirdPartTemp += qWebKitVersion(); + thirdPartTemp.squeeze(); + thirdPart = thirdPartTemp; + Q_ASSERT(!firstPart.isNull()); + Q_ASSERT(!secondPart.isNull()); + Q_ASSERT(!thirdPart.isNull()); + } // Language - QLocale locale; + QString languageName; if (d->client && d->client->ownerWidget()) - locale = d->client->ownerWidget()->locale(); - QString name = locale.name(); - name[2] = QLatin1Char('-'); - ua.append(name); - ua.append(QLatin1String(") ")); - - // webkit/qt version - ua.append(QString(QLatin1String("AppleWebKit/%1 (KHTML, like Gecko) ")) - .arg(QString(qWebKitVersion()))); + languageName = d->client->ownerWidget()->locale().name(); + else + languageName = QLocale().name(); + languageName[2] = QLatin1Char('-'); // Application name/version QString appName = QCoreApplication::applicationName(); if (!appName.isEmpty()) { - ua.append(appName); QString appVer = QCoreApplication::applicationVersion(); if (!appVer.isEmpty()) - ua.append(QLatin1Char('/') + appVer); + appName.append(QLatin1Char('/') + appVer); } else { // Qt version - ua.append(QLatin1String("Qt/")); - ua.append(QLatin1String(qVersion())); + appName = QString::fromLatin1("Qt/") + QString::fromLatin1(qVersion()); } -#if defined(Q_WS_S60) || defined(Q_WS_MAEMO_5) - ua.append(QString(QLatin1String(" Mobile Safari/%1")).arg(qWebKitVersion())); -#else - ua.append(QString(QLatin1String(" Safari/%1")).arg(qWebKitVersion())); -#endif - return ua; + return firstPart + languageName + secondPart + appName + thirdPart; } diff --git a/WebKit/qt/Api/qwebpage_p.h b/WebKit/qt/Api/qwebpage_p.h index f40053b..7414716 100644 --- a/WebKit/qt/Api/qwebpage_p.h +++ b/WebKit/qt/Api/qwebpage_p.h @@ -113,6 +113,8 @@ public: void inputMethodEvent(QInputMethodEvent*); + void dynamicPropertyChangeEvent(QDynamicPropertyChangeEvent*); + void shortcutOverrideEvent(QKeyEvent*); void leaveEvent(QEvent*); void handleClipboard(QEvent*, Qt::MouseButton); diff --git a/WebKit/qt/Api/qwebsettings.cpp b/WebKit/qt/Api/qwebsettings.cpp index 1dff037..99fd812 100644 --- a/WebKit/qt/Api/qwebsettings.cpp +++ b/WebKit/qt/Api/qwebsettings.cpp @@ -48,9 +48,7 @@ #include <QUrl> #include <QFileInfo> -#if ENABLE(QT_BEARER) #include "NetworkStateNotifier.h" -#endif void QWEBKIT_EXPORT qt_networkAccessAllowed(bool isAllowed) { @@ -74,7 +72,6 @@ public: QString localStoragePath; QString offlineWebApplicationCachePath; qint64 offlineStorageDefaultQuota; - QUrl inspectorLocation; void apply(); WebCore::Settings* settings; @@ -187,8 +184,8 @@ void QWebSettingsPrivate::apply() global->attributes.value(QWebSettings::SpatialNavigationEnabled)); settings->setSpatialNavigationEnabled(value); - value = attributes.value(QWebSettings::JavascriptCanAccessClipboard, - global->attributes.value(QWebSettings::JavascriptCanAccessClipboard)); + value = attributes.value(QWebSettings::DOMPasteAllowed, + global->attributes.value(QWebSettings::DOMPasteAllowed)); settings->setDOMPasteAllowed(value); value = attributes.value(QWebSettings::DeveloperExtrasEnabled, @@ -238,6 +235,10 @@ void QWebSettingsPrivate::apply() global->attributes.value(QWebSettings::LocalContentCanAccessFileUrls)); settings->setAllowFileAccessFromFileURLs(value); + value = attributes.value(QWebSettings::JavaScriptCanAccessClipboard, + global->attributes.value(QWebSettings::JavaScriptCanAccessClipboard)); + settings->setJavaScriptCanAccessClipboard(value); + value = attributes.value(QWebSettings::XSSAuditingEnabled, global->attributes.value(QWebSettings::XSSAuditingEnabled)); settings->setXSSAuditorEnabled(value); @@ -298,7 +299,9 @@ QWebSettings* QWebSettings::globalSettings() Support for browser plugins can enabled by setting the \l{QWebSettings::PluginsEnabled}{PluginsEnabled} attribute. For many applications, this attribute is enabled for all pages by setting it on the - \l{globalSettings()}{global settings object}. + \l{globalSettings()}{global settings object}. QtWebKit will always ignore this setting + \when processing Qt plugins. The decision to allow a Qt plugin is made by the client + \in its reimplementation of QWebPage::createPlugin. \section1 Web Application Support @@ -367,13 +370,14 @@ QWebSettings* QWebSettings::globalSettings() programs. \value JavaEnabled Enables or disables Java applets. Currently Java applets are not supported. - \value PluginsEnabled Enables or disables plugins in Web pages. + \value PluginsEnabled Enables or disables plugins in Web pages. Qt plugins + with a mimetype such as "application/x-qt-plugin" are not affected by this setting. \value PrivateBrowsingEnabled Private browsing prevents WebKit from recording visited pages in the history and storing web page icons. \value JavascriptCanOpenWindows Specifies whether JavaScript programs can open new windows. - \value JavascriptCanAccessClipboard Specifies whether JavaScript programs - can read or write to the clipboard. + \value DOMPasteAllowed Specifies whether JavaScript programs can + read clipboard contents. \value DeveloperExtrasEnabled Enables extra tools for Web developers. Currently this enables the "Inspect" element in the context menu as well as the use of QWebInspector which controls the WebKit WebInspector @@ -401,6 +405,7 @@ QWebSettings* QWebSettings::globalSettings() QWebSettings::LocalStorageEnabled instead. \value LocalContentCanAccessRemoteUrls Specifies whether locally loaded documents are allowed to access remote urls. \value LocalContentCanAccessFileUrls Specifies whether locally loaded documents are allowed to access other local urls. + \value JavaScriptCanAccessClipboard Specifies whether JavaScript can access the clipboard. \value XSSAuditingEnabled Specifies whether load requests should be monitored for cross-site scripting attempts. \value AcceleratedCompositingEnabled This feature, when used in conjunction with QGraphicsWebView, accelerates animations of web content. CSS animations of the transform and @@ -998,31 +1003,6 @@ void QWebSettings::setLocalStoragePath(const QString& path) } /*! - \since 4.7 - - Specifies the \a location of a frontend to load with each web page when using Web Inspector. - - \sa inspectorUrl() -*/ -void QWebSettings::setInspectorUrl(const QUrl& location) -{ - d->inspectorLocation = location; - d->apply(); -} - -/*! - \since 4.7 - - Returns the location of the Web Inspector frontend. - - \sa setInspectorUrl() -*/ -QUrl QWebSettings::inspectorUrl() const -{ - return d->inspectorLocation; -} - -/*! \since 4.6 \relates QWebSettings diff --git a/WebKit/qt/Api/qwebsettings.h b/WebKit/qt/Api/qwebsettings.h index bd728d8..7355e33 100644 --- a/WebKit/qt/Api/qwebsettings.h +++ b/WebKit/qt/Api/qwebsettings.h @@ -55,7 +55,7 @@ public: PluginsEnabled, PrivateBrowsingEnabled, JavascriptCanOpenWindows, - JavascriptCanAccessClipboard, + DOMPasteAllowed, DeveloperExtrasEnabled, LinksIncludedInFocusChain, ZoomTextOnly, @@ -68,13 +68,14 @@ public: #endif LocalContentCanAccessRemoteUrls, DnsPrefetchEnabled, + JavaScriptCanAccessClipboard, XSSAuditingEnabled, AcceleratedCompositingEnabled, - WebGLEnabled, SpatialNavigationEnabled, LocalContentCanAccessFileUrls, TiledBackingStoreEnabled, - FrameFlatteningEnabled + FrameFlatteningEnabled, + WebGLEnabled }; enum WebGraphic { MissingImageGraphic, @@ -137,9 +138,6 @@ public: void setLocalStoragePath(const QString& path); QString localStoragePath() const; - void setInspectorUrl(const QUrl &location); - QUrl inspectorUrl() const; - static void clearMemoryCaches(); static void enablePersistentStorage(const QString& path = QString()); diff --git a/WebKit/qt/ChangeLog b/WebKit/qt/ChangeLog index 54f5f65..0ed6300 100644 --- a/WebKit/qt/ChangeLog +++ b/WebKit/qt/ChangeLog @@ -1,3 +1,534 @@ +2010-05-07 Simon Hausmann <simon.hausmann@nokia.com> + + Symbian build fix. + + [Qt] Updated the def file with absent exports. + + * symbian/eabi/QtWebKitu.def: + +2010-05-06 Andreas Kling <andreas.kling@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Patch to fix compilation warnings for QGraphicsWebView + https://bugs.webkit.org/show_bug.cgi?id=37428 + + Patch by Alexis Menard <alexis.menard@nokia.com> + + * Api/qgraphicswebview.cpp: + (QGraphicsWebView::itemChange): + +2010-05-06 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Replace public inspector url with private property for QtLauncher + https://bugs.webkit.org/show_bug.cgi?id=35340 + + Replace the public API with a private dynamic property until this feature + is ready. + + * Api/qwebsettings.cpp: + * Api/qwebsettings.h: + * WebCoreSupport/InspectorClientQt.cpp: + (WebCore::InspectorClientQt::openInspectorFrontend): + * symbian/bwins/QtWebKitu.def: + * symbian/eabi/QtWebKitu.def: + +2010-05-04 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] QWebPage viewMode property + https://bugs.webkit.org/show_bug.cgi?id=38119 + + Rename the property from wrt_viewMode to _q_viewMode. + + * Api/qwebpage.cpp: + (QWebPagePrivate::dynamicPropertyChangeEvent): + * tests/qwebpage/tst_qwebpage.cpp: + (tst_QWebPage::viewModes): + +2010-05-04 Simon Hausmann <simon.hausmann@nokia.com> + + Rubber-stamped by Tor Arne Vestbø. + + [Qt] Preserve binary compatibility with qtwebkit-2.0 branch + + Moved the WebGL attribute in QWebSettings to the end of the enum, + to ensure that the numeric values of the enum values following it + are the same as in the release branch. + + * Api/qwebsettings.h: + +2010-05-03 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Expose HTMLTokenizer yielding parameters + https://bugs.webkit.org/show_bug.cgi?id=37023 + + Enables to set TimeDelay and ChunkSize for + HTMLTokenizer. + + * Api/qwebpage.cpp: + (QWebPagePrivate::dynamicPropertyChangeEvent): + +2010-05-03 Abhishek Arya <inferno@chromium.org> + + Reviewed by Adam Barth. + + Add support for controlling clipboard access from javascript. + Clipboard access from javascript is disabled by default. + https://bugs.webkit.org/show_bug.cgi?id=27751 + + * Api/qwebsettings.cpp: + (QWebSettingsPrivate::apply): + * Api/qwebsettings.h: + +2010-05-03 Jens Alfke <snej@chromium.org> + + Reviewed by Darin Fisher. + + [chromium] Add "willSendSubmitEvent" hook to WebFrameClient and FrameLoaderClient + https://bugs.webkit.org/show_bug.cgi?id=38397 + + No tests (functionality is exposed only through native WebKit API.) + + * WebCoreSupport/FrameLoaderClientQt.h: + (WebCore::FrameLoaderClientQt::dispatchWillSendSubmitEvent): + +2010-05-03 Tor Arne Vestbø <tor.arne.vestbo@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Prune dead code in QWebPage + + * Api/qwebpage.cpp: + +2010-05-02 Tasuku Suzuki <tasuku.suzuki@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Fix compilation with QT_NO_BEARERMANAGEMENT + https://bugs.webkit.org/show_bug.cgi?id=38324 + + * Api/qwebsettings.cpp: + +2010-04-29 Janne Koskinen <janne.p.koskinen@digia.com> + + Reviewed by Simon Hausmann. + + [Qt] QtWebKit versioning added + https://bugs.webkit.org/show_bug.cgi?id=37207 + + QtWebkit releases separated from Qt release cycle. + + * qtwebkit_version.pri: Added. + +2010-05-02 Benjamin Poulain <benjamin.poulain@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] QWebPage::userAgentForUrl is terrible API + https://bugs.webkit.org/show_bug.cgi?id=33875 + + Simplify the creation of the user agent string to avoid some + overhead for each loaded url. + + The static part of the user agent is cached so it only have + to be made once. + This creation has been made in order to simplify the code. + + The two variable: application name and current language are + set dynamically when needed. + The default locale is non longer created if the widget locale + is used. + + * Api/qwebpage.cpp: + (QWebPage::userAgentForUrl): + * tests/qwebpage/tst_qwebpage.cpp: + (tst_QWebPage::userAgentApplicationName): + (tst_QWebPage::userAgentLocaleChange): + +2010-05-02 Noam Rosenthal <noam.rosenthal@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] GraphicsLayer: animation incorrect when scrolling + https://bugs.webkit.org/show_bug.cgi?id=38371 + + This is a regression introduced with the invalidate-on-scroll code path, that uses QGraphicsWebViewPrivate::update() + instead of QGraphicsWebViewPrivate::scroll(). The patch makes sure that the scrolling position is correct on + each content update - this shouldn't have a performance impact - the only overhead is an additional value-test on each update. + + Tested by http://www.the-art-of-web.com/css/css-animation/ + + * Api/qgraphicswebview.cpp: + (QGraphicsWebViewPrivate::update): + +2010-05-01 Robert Hogan <robert@webkit.org> + + Reviewed by Simon Hausmann. + + [Qt] Add smart paste support + + https://bugs.webkit.org/show_bug.cgi?id=38136 + + * Api/qwebpage.cpp: + (QWebPagePrivate::QWebPagePrivate): Enable smart paste support by default. + +2010-04-29 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Reinstate qt_drt_ symbol exports as of QtWebKit 4.6 release + https://bugs.webkit.org/show_bug.cgi?id=38304 + + This change provides backward compatibility with some previously + exported private symbols. No new functionality introduced. + + * WebCoreSupport/DumpRenderTreeSupportQt.cpp: + (qt_resumeActiveDOMObjects): + (qt_suspendActiveDOMObjects): + (qt_drt_clearFrameName): + (qt_drt_garbageCollector_collect): + (qt_drt_garbageCollector_collectOnAlternateThread): + (qt_drt_javaScriptObjectsCount): + (qt_drt_numberOfActiveAnimations): + (qt_drt_overwritePluginDirectories): + (qt_drt_pauseAnimation): + (qt_drt_pauseTransitionOfProperty): + (qt_drt_resetOriginAccessWhiteLists): + (qt_drt_run): + (qt_drt_setJavaScriptProfilingEnabled): + (qt_drt_whiteListAccessFromOrigin): + (qt_webpage_groupName): + (qt_webpage_setGroupName): + +2010-04-29 Benjamin Poulain <benjamin.poulain@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + Get rid of forceLayout() on FrameView + https://bugs.webkit.org/show_bug.cgi?id=38199 + + The function FrameView::forceLayout() is missleading + because it does not actually force the layout, the call is + equivalent to layout(). + + This patch replace the call to forceLayout() by layout() in Qt + to avoid the misunderstanding/improve readability. + + * Api/qwebpage.cpp: + (QWebPagePrivate::dynamicPropertyChangeEvent): + (QWebPage::setPreferredContentsSize): + * WebCoreSupport/DumpRenderTreeSupportQt.cpp: + (DumpRenderTreeSupportQt::setMediaType): + * WebCoreSupport/FrameLoaderClientQt.cpp: + (WebCore::FrameLoaderClientQt::forceLayout): + +2010-04-29 Andreas Kling <andreas.kling@nokia.com> + + Reviewed by Simon Hausmann. + + Remove unnecessary call to FrameView::forceLayout() in setViewportSize() + This prevents a double relayout on resize. + + https://bugs.webkit.org/show_bug.cgi?id=38179 + + Thanks to Nate Whetsell <nathan.whetsell@gmail.com> for spotting this. + + * Api/qwebpage.cpp: + (QWebPage::setViewportSize): + +2010-04-29 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Tor Arne Vestbø. + + [Qt] REGRESSION(r57982): tst_qwebpage::showModalDialog() crashes + https://bugs.webkit.org/show_bug.cgi?id=38314 + + Make sure that there's always a main frame when returning from createWindow() + to the caller in WebCore. + + * WebCoreSupport/ChromeClientQt.cpp: + (WebCore::ChromeClientQt::createWindow): + +2010-04-28 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Unreviewed, Qt build fix. + + [Qt] Guard the body of the function instead of the function for + exported functions. + + * WebCoreSupport/DumpRenderTreeSupportQt.cpp: + (DumpRenderTreeSupportQt::webInspectorExecuteScript): + (DumpRenderTreeSupportQt::webInspectorClose): + (DumpRenderTreeSupportQt::webInspectorShow): + (DumpRenderTreeSupportQt::setTimelineProfilingEnabled): + +2010-04-28 Antonio Gomes <tonikitoo@webkit.org>, Yi Shen <yi.4.shen@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] tst_QWebHistoryInterface::visitedLinks() fails + https://bugs.webkit.org/show_bug.cgi?id=37323 + + Patch fixes styleProperty method of QWebElement to make use of + CSSComputedStyleDeclaration::computedStyle 'allowVisitedStyle' parameter + and the corresponding failing QWebHistoryInterface::visitedLinks method. + + * Api/qwebelement.cpp: + (QWebElement::styleProperty): + * tests/qwebhistoryinterface/tst_qwebhistoryinterface.cpp: + (tst_QWebHistoryInterface::visitedLinks): + +2010-04-28 Luiz Agostini <luiz.agostini@openbossa.org> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] QWebPage viewMode property + https://bugs.webkit.org/show_bug.cgi?id=38119 + + Replacing method qt_wrt_setViewMode by wrt_viewMode property. + + * Api/qwebpage.cpp: + (QWebPagePrivate::dynamicPropertyChangeEvent): + (QWebPage::event): + * Api/qwebpage_p.h: + * tests/qwebpage/tst_qwebpage.cpp: + (tst_QWebPage::wrt_viewModes): + +2010-04-28 Janne Koskinen <janne.p.koskinen@digia.com> + + Reviewed by Simon Hausmann <simon.hausmann@nokia.com> + + [Qt] WINS DEF file freeze + + Updated WINSCW def file with added and removed symbols. + + * symbian/bwins/QtWebKitu.def: + +2010-04-25 Sam Weinig <sam@webkit.org> + + Reviewed by Maciej Stachowiak. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38097 + Disentangle initializing the main thread from initializing threading + + * Api/qwebpage.cpp: + (QWebPagePrivate::QWebPagePrivate): Add call to initializeMainThread. + +2010-04-26 Thiago Macieira <thiago.macieira@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Fix the include header <qstring.h> -> <QtCore/qstring.h> + + The module/header.h style inclusion removes the need to have -I$QTDIR/include/depending-module + in the include search path for the application. + + * Api/qwebkitversion.h: + +2010-04-26 Bruno Schmidt <bruno.schmidt@gmail.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Exposing an QVariantMap containing QObjectStar to Javascript + causes Segmentation Fault + https://bugs.webkit.org/show_bug.cgi?id=34729 + + If an QVariantMap containing QObjectStar is added to the to QtWebkit + Javascript, it's use causes Segmentation Fault. + It happens because, in the case QMetaType::QVariantMap, the "root" + object that is inside of a PassRefPtr is passed recursively inside a + loop to recover the content of the map, but the PassRefPtr semantics + prohibit its use inside a loop, so the "root" object mus be passed + using the method "PassRefPtr::get" in order to keep the current + reference. + + * tests/qwebframe/tst_qwebframe.cpp: + (MyQObject::MyQObject): new property variantMapProperty + (MyQObject::variantMapProperty): read variantMapProperty + (MyQObject::setVariantMapProperty): write variantMapProperty + +2010-04-25 Shinichiro Hamaji <hamaji@chromium.org> + + Reviewed by Simon Hausmann. + + [Qt] layoutTestController.counterValueForElementById crashes for a nonexistent ID + https://bugs.webkit.org/show_bug.cgi?id=34573 + + * WebCoreSupport/DumpRenderTreeSupportQt.cpp: + (DumpRenderTreeSupportQt::counterValueForElementById): + +2010-04-20 Robert Hogan <robert@webkit.org> + + Reviewed by Simon Hausmann. + + [Qt] Add more support for textInputController + + Add support for selectedRange(), setMarkedText(), insertText(), + and firstRectForCharacterRange(). + + https://bugs.webkit.org/show_bug.cgi?id=35702 + + * Api/qwebpage.cpp: + (QWebPagePrivate::inputMethodEvent): + * WebCoreSupport/DumpRenderTreeSupportQt.cpp: + (DumpRenderTreeSupportQt::selectedRange): + (DumpRenderTreeSupportQt::firstRectForCharacterRange): + * WebCoreSupport/DumpRenderTreeSupportQt.h: + * tests/qwebpage/tst_qwebpage.cpp: + (tst_QWebPage::inputMethods): + +2010-04-22 John Pavan <john.pavan@nokia.com> + + Reviewed by Laszlo Gombos. + + [Qt] inputMethodQuery returns coordinates in web page coordinates rather than in item coordinates. + https://bugs.webkit.org/show_bug.cgi?id=37163 + + + QWebPage::inputMethodQuery is modified so that it + returns coordinates in the widget's coordinate system. + Tests are added for QGraphicsWebView and QWebView + to verify that this behavior is correct after the webpage + has been scrolled. + + * Api/qwebpage.cpp: + (QWebPage::inputMethodQuery): + * tests/qgraphicswebview/tst_qgraphicswebview.cpp: + (tst_QGraphicsWebView::microFocusCoordinates): + * tests/qwebview/tst_qwebview.cpp: + (tst_QWebView::microFocusCoordinates): + +2010-04-22 Robert Hogan <robert@webkit.org> + + Reviewed by Simon Hausmann. + + [Qt] Fix createPlugin() tests in tst_qwebpage to match behaviour of Qt plugins + when PluginsEnabled is false. + + tst_qwebpage should have been updated as part of r56662. + (See https://bugs.webkit.org/show_bug.cgi?id=32196) + + Updated documentation of QWebPage::createPlugin and QWebSetting::pluginsEnabled + to match the new behaviour. + + * Api/qwebpage.cpp: Update docs. + * Api/qwebsettings.cpp: Update docs. + * tests/qwebpage/tst_qwebpage.cpp: + (createPlugin): + (tst_QWebPage::createPluginWithPluginsEnabled): + (tst_QWebPage::createPluginWithPluginsDisabled): + +2010-04-22 Dave Moore <davemoore@chromium.org> + + Reviewed by Dimitri Glazkov. + + Added notification when the favicons for a page are changed + from a script. + The Document object will notify the frame loader, which will + notify the client. Implementations of FrameLoaderClient will + have to add one method; dispatchDidChangeIcons(). + + https://bugs.webkit.org/show_bug.cgi?id=33812 + + * WebCoreSupport/FrameLoaderClientQt.cpp: + (WebCore::FrameLoaderClientQt::dispatchDidChangeIcons): + (WebCore::FrameLoaderClientQt::didChangeTitle): + * WebCoreSupport/FrameLoaderClientQt.h: + +2010-04-22 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Remove translatable strings from the hybridPixmap test. + https://bugs.webkit.org/show_bug.cgi?id=37867 + + * tests/hybridPixmap/widget.ui: + +2010-04-22 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Fix autotests .qrc file paths when built in Qt. + + Compiling auto-tests from qt/tests/auto/qweb* produced + failing tests since these .pro files include the + ones in WebKit/qt/tests and the .qrc file was + not added to RESOURCES + + * tests/benchmarks/loading/loading.pro: + * tests/benchmarks/painting/painting.pro: + * tests/qgraphicswebview/qgraphicswebview.pro: + * tests/qwebelement/qwebelement.pro: + * tests/qwebframe/qwebframe.pro: + * tests/qwebhistory/qwebhistory.pro: + * tests/qwebhistoryinterface/qwebhistoryinterface.pro: + * tests/qwebinspector/qwebinspector.pro: + * tests/qwebpage/qwebpage.pro: + * tests/qwebplugindatabase/qwebplugindatabase.pro: + * tests/qwebview/qwebview.pro: + * tests/tests.pri: + +2010-04-22 Adam Barth <abarth@webkit.org> + + Unreviewed, rolling out r58069. + http://trac.webkit.org/changeset/58069 + https://bugs.webkit.org/show_bug.cgi?id=27751 + + Broke compile on Windows. + + * Api/qwebsettings.cpp: + (QWebSettingsPrivate::apply): + * Api/qwebsettings.h: + +2010-04-22 Abhishek Arya <inferno@chromium.org> + + Reviewed by Adam Barth. + + Add support for controlling clipboard access from javascript. + Clipboard access from javascript is disabled by default. + https://bugs.webkit.org/show_bug.cgi?id=27751 + + * Api/qwebsettings.cpp: + (QWebSettingsPrivate::apply): + * Api/qwebsettings.h: + +2010-04-21 Jesus Sanchez-Palencia <jesus@webkit.org> + + Reviewed by Kenneth Rohde Christiansen. + + Add PageClientQWidget implementation based on the old + QWebPageWidgetClient to PageClientQt files. Also fix + QWebPage::setView() to use PageClientQWidget. + + [Qt] PageClientQt specific implementation for QWidget + https://bugs.webkit.org/show_bug.cgi?id=37858 + + * Api/qwebpage.cpp: + (QWebPage::setView): + * WebCoreSupport/PageClientQt.cpp: Added. + (WebCore::PageClientQWidget::scroll): + (WebCore::PageClientQWidget::update): + (WebCore::PageClientQWidget::setInputMethodEnabled): + (WebCore::PageClientQWidget::inputMethodEnabled): + (WebCore::PageClientQWidget::setInputMethodHint): + (WebCore::PageClientQWidget::cursor): + (WebCore::PageClientQWidget::updateCursor): + (WebCore::PageClientQWidget::palette): + (WebCore::PageClientQWidget::screenNumber): + (WebCore::PageClientQWidget::ownerWidget): + (WebCore::PageClientQWidget::geometryRelativeToOwnerWidget): + (WebCore::PageClientQWidget::pluginParent): + (WebCore::PageClientQWidget::style): + * WebCoreSupport/PageClientQt.h: Added. + (WebCore::PageClientQWidget::PageClientQWidget): + (WebCore::PageClientQWidget::isQWidgetClient): + 2010-04-21 Jakub Wieczorek <jwieczorek@webkit.org> Reviewed by Darin Adler. diff --git a/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp b/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp index 5ea072d..cf100f7 100644 --- a/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp +++ b/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp @@ -167,8 +167,12 @@ Page* ChromeClientQt::createWindow(Frame*, const FrameLoadRequest& request, cons if (!newPage) return 0; + // A call to QWebPage::mainFrame() implicitly creates the main frame. + // Make sure it exists, as WebCore expects it when returning from this call. + QWebFrame* mainFrame = newPage->mainFrame(); + if (!request.isEmpty()) - newPage->mainFrame()->load(request.resourceRequest().url()); + mainFrame->load(request.resourceRequest().url()); return newPage->d->page; } diff --git a/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.cpp b/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.cpp index 3f2e221..935be85 100644 --- a/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.cpp +++ b/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.cpp @@ -44,6 +44,7 @@ #if ENABLE(SVG) #include "SVGSMILElement.h" #endif +#include "TextIterator.h" #include "WorkerThread.h" #include "qwebframe.h" @@ -102,30 +103,36 @@ QString DumpRenderTreeSupportQt::webPageGroupName(QWebPage* page) return page->handle()->page->groupName(); } -#if ENABLE(INSPECTOR) void DumpRenderTreeSupportQt::webInspectorExecuteScript(QWebPage* page, long callId, const QString& script) { +#if ENABLE(INSPECTOR) if (!page->handle()->page->inspectorController()) return; page->handle()->page->inspectorController()->evaluateForTestInFrontend(callId, script); +#endif } void DumpRenderTreeSupportQt::webInspectorClose(QWebPage* page) { +#if ENABLE(INSPECTOR) if (!page->handle()->page->inspectorController()) return; page->handle()->page->inspectorController()->close(); +#endif } void DumpRenderTreeSupportQt::webInspectorShow(QWebPage* page) { +#if ENABLE(INSPECTOR) if (!page->handle()->page->inspectorController()) return; page->handle()->page->inspectorController()->show(); +#endif } void DumpRenderTreeSupportQt::setTimelineProfilingEnabled(QWebPage* page, bool enabled) { +#if ENABLE(INSPECTOR) InspectorController* controller = page->handle()->page->inspectorController(); if (!controller) return; @@ -133,9 +140,8 @@ void DumpRenderTreeSupportQt::setTimelineProfilingEnabled(QWebPage* page, bool e controller->startTimelineProfiler(); else controller->stopTimelineProfiler(); -} - #endif +} bool DumpRenderTreeSupportQt::hasDocumentElement(QWebFrame* frame) { @@ -264,8 +270,8 @@ QString DumpRenderTreeSupportQt::counterValueForElementById(QWebFrame* frame, co { Frame* coreFrame = QWebFramePrivate::core(frame); if (Document* document = coreFrame->document()) { - Element* element = document->getElementById(id); - return WebCore::counterValueForElement(element); + if (Element* element = document->getElementById(id)) + return WebCore::counterValueForElement(element); } return QString(); } @@ -341,7 +347,7 @@ void DumpRenderTreeSupportQt::setMediaType(QWebFrame* frame, const QString& type WebCore::FrameView* view = coreFrame->view(); view->setMediaType(type); coreFrame->document()->updateStyleSelector(); - view->forceLayout(); + view->layout(); } void DumpRenderTreeSupportQt::setSmartInsertDeleteEnabled(QWebPage* page, bool enabled) @@ -370,3 +376,129 @@ QString DumpRenderTreeSupportQt::markerTextForListItem(const QWebElement& listIt { return WebCore::markerTextForListItem(listItem.m_element); } + +QVariantList DumpRenderTreeSupportQt::selectedRange(QWebPage* page) +{ + WebCore::Frame* frame = page->handle()->page->focusController()->focusedOrMainFrame(); + QVariantList selectedRange; + RefPtr<Range> range = frame->selection()->toNormalizedRange().get(); + + Element* selectionRoot = frame->selection()->rootEditableElement(); + Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement(); + + RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset()); + ASSERT(testRange->startContainer() == scope); + int startPosition = TextIterator::rangeLength(testRange.get()); + + ExceptionCode ec; + testRange->setEnd(range->endContainer(), range->endOffset(), ec); + ASSERT(testRange->startContainer() == scope); + int endPosition = TextIterator::rangeLength(testRange.get()); + + selectedRange << startPosition << (endPosition - startPosition); + + return selectedRange; + +} + +QVariantList DumpRenderTreeSupportQt::firstRectForCharacterRange(QWebPage* page, int location, int length) +{ + WebCore::Frame* frame = page->handle()->page->focusController()->focusedOrMainFrame(); + QVariantList rect; + + if ((location + length < location) && (location + length != 0)) + length = 0; + + Element* selectionRoot = frame->selection()->rootEditableElement(); + Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement(); + RefPtr<Range> range = TextIterator::rangeFromLocationAndLength(scope, location, length); + + if (!range) + return QVariantList(); + + QRect resultRect = frame->firstRectForRange(range.get()); + rect << resultRect.x() << resultRect.y() << resultRect.width() << resultRect.height(); + return rect; +} + +// Provide a backward compatibility with previously exported private symbols as of QtWebKit 4.6 release + +void QWEBKIT_EXPORT qt_resumeActiveDOMObjects(QWebFrame* frame) +{ + DumpRenderTreeSupportQt::resumeActiveDOMObjects(frame); +} + +void QWEBKIT_EXPORT qt_suspendActiveDOMObjects(QWebFrame* frame) +{ + DumpRenderTreeSupportQt::suspendActiveDOMObjects(frame); +} + +void QWEBKIT_EXPORT qt_drt_clearFrameName(QWebFrame* frame) +{ + DumpRenderTreeSupportQt::clearFrameName(frame); +} + +void QWEBKIT_EXPORT qt_drt_garbageCollector_collect() +{ + DumpRenderTreeSupportQt::garbageCollectorCollect(); +} + +void QWEBKIT_EXPORT qt_drt_garbageCollector_collectOnAlternateThread(bool waitUntilDone) +{ + DumpRenderTreeSupportQt::garbageCollectorCollectOnAlternateThread(waitUntilDone); +} + +int QWEBKIT_EXPORT qt_drt_javaScriptObjectsCount() +{ + return DumpRenderTreeSupportQt::javaScriptObjectsCount(); +} + +int QWEBKIT_EXPORT qt_drt_numberOfActiveAnimations(QWebFrame* frame) +{ + return DumpRenderTreeSupportQt::numberOfActiveAnimations(frame); +} + +void QWEBKIT_EXPORT qt_drt_overwritePluginDirectories() +{ + DumpRenderTreeSupportQt::overwritePluginDirectories(); +} + +bool QWEBKIT_EXPORT qt_drt_pauseAnimation(QWebFrame* frame, const QString& animationName, double time, const QString& elementId) +{ + return DumpRenderTreeSupportQt::pauseAnimation(frame, animationName, time, elementId); +} + +bool QWEBKIT_EXPORT qt_drt_pauseTransitionOfProperty(QWebFrame* frame, const QString& propertyName, double time, const QString &elementId) +{ + return DumpRenderTreeSupportQt::pauseTransitionOfProperty(frame, propertyName, time, elementId); +} + +void QWEBKIT_EXPORT qt_drt_resetOriginAccessWhiteLists() +{ + DumpRenderTreeSupportQt::resetOriginAccessWhiteLists(); +} + +void QWEBKIT_EXPORT qt_drt_run(bool b) +{ + DumpRenderTreeSupportQt::setDumpRenderTreeModeEnabled(b); +} + +void QWEBKIT_EXPORT qt_drt_setJavaScriptProfilingEnabled(QWebFrame* frame, bool enabled) +{ + DumpRenderTreeSupportQt::setJavaScriptProfilingEnabled(frame, enabled); +} + +void QWEBKIT_EXPORT qt_drt_whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains) +{ + DumpRenderTreeSupportQt::whiteListAccessFromOrigin(sourceOrigin, destinationProtocol, destinationHost, allowDestinationSubdomains); +} + +QString QWEBKIT_EXPORT qt_webpage_groupName(QWebPage* page) +{ + return DumpRenderTreeSupportQt::webPageGroupName(page); +} + +void QWEBKIT_EXPORT qt_webpage_setGroupName(QWebPage* page, const QString& groupName) +{ + DumpRenderTreeSupportQt::webPageSetGroupName(page, groupName); +} diff --git a/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h b/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h index b92b86a..c0187df 100644 --- a/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h +++ b/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h @@ -24,6 +24,7 @@ #define DumpRenderTreeSupportQt_h #include "qwebkitglobal.h" +#include <QVariant> #include "qwebelement.h" @@ -42,6 +43,8 @@ public: static bool isCommandEnabled(QWebPage* page, const QString& name); static void setSmartInsertDeleteEnabled(QWebPage* page, bool enabled); static void setSelectTrailingWhitespaceEnabled(QWebPage* page, bool enabled); + static QVariantList selectedRange(QWebPage* page); + static QVariantList firstRectForCharacterRange(QWebPage* page, int location, int length); static bool pauseAnimation(QWebFrame*, const QString& name, double time, const QString& elementId); static bool pauseTransitionOfProperty(QWebFrame*, const QString& name, double time, const QString& elementId); diff --git a/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp b/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp index f93b1cc..a0b06fb 100644 --- a/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp +++ b/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp @@ -258,7 +258,7 @@ void FrameLoaderClientQt::forceLayout() { FrameView* view = m_frame->view(); if (view) - view->forceLayout(true); + view->layout(true); } @@ -381,6 +381,19 @@ void FrameLoaderClientQt::dispatchDidReceiveTitle(const String& title) } +void FrameLoaderClientQt::dispatchDidChangeIcons() +{ + if (dumpFrameLoaderCallbacks) + printf("%s - didChangeIcons\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame))); + + if (!m_webFrame) + return; + + // FIXME: To be notified of changing icon URLS add notification + // emit iconsChanged(); +} + + void FrameLoaderClientQt::dispatchDidCommitLoad() { if (dumpFrameLoaderCallbacks) @@ -525,7 +538,7 @@ void FrameLoaderClientQt::willChangeTitle(DocumentLoader*) } -void FrameLoaderClientQt::didChangeTitle(DocumentLoader *) +void FrameLoaderClientQt::didChangeTitle(DocumentLoader*) { // no need for, dispatchDidReceiveTitle is the right callback } diff --git a/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h b/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h index 2756871..9c968a0 100644 --- a/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h +++ b/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h @@ -109,6 +109,7 @@ namespace WebCore { virtual void dispatchDidReceiveIcon(); virtual void dispatchDidStartProvisionalLoad(); virtual void dispatchDidReceiveTitle(const String& title); + virtual void dispatchDidChangeIcons(); virtual void dispatchDidCommitLoad(); virtual void dispatchDidFailProvisionalLoad(const ResourceError&); virtual void dispatchDidFailLoad(const WebCore::ResourceError&); @@ -127,6 +128,7 @@ namespace WebCore { virtual void dispatchUnableToImplementPolicy(const WebCore::ResourceError&); + virtual void dispatchWillSendSubmitEvent(HTMLFormElement*) { } virtual void dispatchWillSubmitForm(FramePolicyFunction, PassRefPtr<FormState>); virtual void dispatchDidLoadMainResource(DocumentLoader*); diff --git a/WebKit/qt/WebCoreSupport/InspectorClientQt.cpp b/WebKit/qt/WebCoreSupport/InspectorClientQt.cpp index 7fabbda..a3dd9dd 100644 --- a/WebKit/qt/WebCoreSupport/InspectorClientQt.cpp +++ b/WebKit/qt/WebCoreSupport/InspectorClientQt.cpp @@ -88,12 +88,13 @@ void InspectorClientQt::openInspectorFrontend(WebCore::InspectorController*) InspectorClientWebPage* inspectorPage = new InspectorClientWebPage(inspectorView); inspectorView->setPage(inspectorPage); - QUrl inspectorUrl = m_inspectedWebPage->settings()->inspectorUrl(); + QWebInspector* inspector = m_inspectedWebPage->d->getOrCreateInspector(); + QUrl inspectorUrl = inspector->property("_q_inspectorUrl").toUrl(); if (!inspectorUrl.isValid()) inspectorUrl = QUrl("qrc:/webkit/inspector/inspector.html"); inspectorView->page()->mainFrame()->load(inspectorUrl); m_inspectedWebPage->d->inspectorFrontend = inspectorView; - m_inspectedWebPage->d->getOrCreateInspector()->d->setFrontend(inspectorView); + inspector->d->setFrontend(inspectorView); inspectorView->page()->d->page->inspectorController()->setInspectorFrontendClient(new InspectorFrontendClientQt(m_inspectedWebPage, inspectorView)); } diff --git a/WebKit/qt/WebCoreSupport/PageClientQt.cpp b/WebKit/qt/WebCoreSupport/PageClientQt.cpp new file mode 100644 index 0000000..611bab7 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/PageClientQt.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * 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 "PageClientQt.h" + +#if defined(Q_WS_X11) +#include <QX11Info> +#endif + +namespace WebCore { + +void PageClientQWidget::scroll(int dx, int dy, const QRect& rectToScroll) +{ + view->scroll(qreal(dx), qreal(dy), rectToScroll); +} + +void PageClientQWidget::update(const QRect & dirtyRect) +{ + view->update(dirtyRect); +} + +void PageClientQWidget::setInputMethodEnabled(bool enable) +{ + view->setAttribute(Qt::WA_InputMethodEnabled, enable); +} + +bool PageClientQWidget::inputMethodEnabled() const +{ + return view->testAttribute(Qt::WA_InputMethodEnabled); +} + +#if QT_VERSION >= 0x040600 +void PageClientQWidget::setInputMethodHint(Qt::InputMethodHint hint, bool enable) +{ + if (enable) + view->setInputMethodHints(view->inputMethodHints() | hint); + else + view->setInputMethodHints(view->inputMethodHints() & ~hint); +} +#endif + +#ifndef QT_NO_CURSOR +QCursor PageClientQWidget::cursor() const +{ + return view->cursor(); +} + +void PageClientQWidget::updateCursor(const QCursor& cursor) +{ + view->setCursor(cursor); +} +#endif + +QPalette PageClientQWidget::palette() const +{ + return view->palette(); +} + +int PageClientQWidget::screenNumber() const +{ +#if defined(Q_WS_X11) + return view->x11Info().screen(); +#endif + return 0; +} + +QWidget* PageClientQWidget::ownerWidget() const +{ + return view; +} + +QRect PageClientQWidget::geometryRelativeToOwnerWidget() const +{ + return view->geometry(); +} + +QObject* PageClientQWidget::pluginParent() const +{ + return view; +} + +QStyle* PageClientQWidget::style() const +{ + return view->style(); +} + +} diff --git a/WebKit/qt/WebCoreSupport/PageClientQt.h b/WebKit/qt/WebCoreSupport/PageClientQt.h new file mode 100644 index 0000000..3f09564 --- /dev/null +++ b/WebKit/qt/WebCoreSupport/PageClientQt.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * 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 PageClientQt_h +#define PageClientQt_h + +#include "QWebPageClient.h" + +#include <QtGui/qwidget.h> + + +namespace WebCore { + +class PageClientQWidget : public QWebPageClient { +public: + PageClientQWidget(QWidget* view) + : view(view) + { + Q_ASSERT(view); + } + + virtual bool isQWidgetClient() const { return true; } + + virtual void scroll(int dx, int dy, const QRect&); + virtual void update(const QRect& dirtyRect); + virtual void setInputMethodEnabled(bool enable); + virtual bool inputMethodEnabled() const; +#if QT_VERSION >= 0x040600 + virtual void setInputMethodHint(Qt::InputMethodHint hint, bool enable); +#endif + +#ifndef QT_NO_CURSOR + virtual QCursor cursor() const; + virtual void updateCursor(const QCursor& cursor); +#endif + + virtual QPalette palette() const; + virtual int screenNumber() const; + virtual QWidget* ownerWidget() const; + virtual QRect geometryRelativeToOwnerWidget() const; + + virtual QObject* pluginParent() const; + + virtual QStyle* style() const; + + QWidget* view; +}; + +} +#endif // PageClientQt diff --git a/WebKit/qt/qtwebkit_version.pri b/WebKit/qt/qtwebkit_version.pri new file mode 100644 index 0000000..1656f2d --- /dev/null +++ b/WebKit/qt/qtwebkit_version.pri @@ -0,0 +1,4 @@ +QT_WEBKIT_VERSION = 4.8.0 +QT_WEBKIT_MAJOR_VERSION = 4 +QT_WEBKIT_MINOR_VERSION = 8 +QT_WEBKIT_PATCH_VERSION = 0 diff --git a/WebKit/qt/symbian/bwins/QtWebKitu.def b/WebKit/qt/symbian/bwins/QtWebKitu.def index 086e986..729b97c 100644 --- a/WebKit/qt/symbian/bwins/QtWebKitu.def +++ b/WebKit/qt/symbian/bwins/QtWebKitu.def @@ -623,5 +623,30 @@ EXPORTS ?qt_networkAccessAllowed@@YAX_N@Z @ 622 NONAME ; void qt_networkAccessAllowed(bool) ?qt_resumeActiveDOMObjects@@YAXPAVQWebFrame@@@Z @ 623 NONAME ; void qt_resumeActiveDOMObjects(class QWebFrame *) ?qt_suspendActiveDOMObjects@@YAXPAVQWebFrame@@@Z @ 624 NONAME ; void qt_suspendActiveDOMObjects(class QWebFrame *) - ?qtwebkit_webframe_scrollRecursively@@YA_NPAVQWebFrame@@HH@Z @ 625 NONAME ; bool qtwebkit_webframe_scrollRecursively(class QWebFrame *, int, int) + ?qtwebkit_webframe_scrollRecursively@@YA_NPAVQWebFrame@@HH@Z @ 625 NONAME ABSENT ; bool qtwebkit_webframe_scrollRecursively(class QWebFrame *, int, int) + ?closeEvent@QWebInspector@@MAEXPAVQCloseEvent@@@Z @ 626 NONAME ; void QWebInspector::closeEvent(class QCloseEvent *) + ?inspectorUrl@QWebSettings@@QBE?AVQUrl@@XZ @ 627 NONAME ABSENT ; class QUrl QWebSettings::inspectorUrl(void) const + ?isTiledBackingStoreFrozen@QGraphicsWebView@@QBE_NXZ @ 628 NONAME ; bool QGraphicsWebView::isTiledBackingStoreFrozen(void) const + ?pageChanged@QWebFrame@@IAEXXZ @ 629 NONAME ; void QWebFrame::pageChanged(void) + ?qt_drt_enableCaretBrowsing@@YAXPAVQWebPage@@_N@Z @ 630 NONAME ; void qt_drt_enableCaretBrowsing(class QWebPage *, bool) + ?qt_drt_evaluateScriptInIsolatedWorld@@YAXPAVQWebFrame@@HABVQString@@@Z @ 631 NONAME ; void qt_drt_evaluateScriptInIsolatedWorld(class QWebFrame *, int, class QString const &) + ?qt_drt_hasDocumentElement@@YA_NPAVQWebFrame@@@Z @ 632 NONAME ; bool qt_drt_hasDocumentElement(class QWebFrame *) + ?qt_drt_numberOfPages@@YAHPAVQWebFrame@@MM@Z @ 633 NONAME ; int qt_drt_numberOfPages(class QWebFrame *, float, float) + ?qt_drt_pageNumberForElementById@@YAHPAVQWebFrame@@ABVQString@@MM@Z @ 634 NONAME ; int qt_drt_pageNumberForElementById(class QWebFrame *, class QString const &, float, float) + ?qt_drt_pauseSVGAnimation@@YA_NPAVQWebFrame@@ABVQString@@N1@Z @ 635 NONAME ; bool qt_drt_pauseSVGAnimation(class QWebFrame *, class QString const &, double, class QString const &) + ?qt_drt_setDomainRelaxationForbiddenForURLScheme@@YAX_NABVQString@@@Z @ 636 NONAME ; void qt_drt_setDomainRelaxationForbiddenForURLScheme(bool, class QString const &) + ?qt_drt_setFrameFlatteningEnabled@@YAXPAVQWebPage@@_N@Z @ 637 NONAME ; void qt_drt_setFrameFlatteningEnabled(class QWebPage *, bool) + ?qt_drt_setMediaType@@YAXPAVQWebFrame@@ABVQString@@@Z @ 638 NONAME ; void qt_drt_setMediaType(class QWebFrame *, class QString const &) + ?qt_drt_setTimelineProfilingEnabled@@YAXPAVQWebPage@@_N@Z @ 639 NONAME ; void qt_drt_setTimelineProfilingEnabled(class QWebPage *, bool) + ?qt_drt_webinspector_close@@YAXPAVQWebPage@@@Z @ 640 NONAME ; void qt_drt_webinspector_close(class QWebPage *) + ?qt_drt_webinspector_executeScript@@YAXPAVQWebPage@@JABVQString@@@Z @ 641 NONAME ; void qt_drt_webinspector_executeScript(class QWebPage *, long, class QString const &) + ?qt_drt_webinspector_show@@YAXPAVQWebPage@@@Z @ 642 NONAME ; void qt_drt_webinspector_show(class QWebPage *) + ?qt_drt_workerThreadCount@@YAHXZ @ 643 NONAME ; int qt_drt_workerThreadCount(void) + ?qt_wrt_setViewMode@@YAXPAVQWebPage@@ABVQString@@@Z @ 644 NONAME ; void qt_wrt_setViewMode(class QWebPage *, class QString const &) + ?qtwebkit_webframe_scrollRecursively@@YAXPAVQWebFrame@@HHABVQPoint@@@Z @ 645 NONAME ; void qtwebkit_webframe_scrollRecursively(class QWebFrame *, int, int, class QPoint const &) + ?resizesToContents@QGraphicsWebView@@QBE_NXZ @ 646 NONAME ; bool QGraphicsWebView::resizesToContents(void) const + ?scrollToAnchor@QWebFrame@@QAEXABVQString@@@Z @ 647 NONAME ; void QWebFrame::scrollToAnchor(class QString const &) + ?setInspectorUrl@QWebSettings@@QAEXABVQUrl@@@Z @ 648 NONAME ABSENT ; void QWebSettings::setInspectorUrl(class QUrl const &) + ?setResizesToContents@QGraphicsWebView@@QAEX_N@Z @ 649 NONAME ; void QGraphicsWebView::setResizesToContents(bool) + ?setTiledBackingStoreFrozen@QGraphicsWebView@@QAEX_N@Z @ 650 NONAME ; void QGraphicsWebView::setTiledBackingStoreFrozen(bool) diff --git a/WebKit/qt/symbian/eabi/QtWebKitu.def b/WebKit/qt/symbian/eabi/QtWebKitu.def index 145fe0b..6ccaaa7 100644 --- a/WebKit/qt/symbian/eabi/QtWebKitu.def +++ b/WebKit/qt/symbian/eabi/QtWebKitu.def @@ -650,7 +650,7 @@ EXPORTS _ZlsR11QDataStreamRK11QWebHistory @ 649 NONAME _ZrsR11QDataStreamR11QWebHistory @ 650 NONAME _Z32qt_drt_whiteListAccessFromOriginRK7QStringS1_S1_b @ 651 NONAME - _Z33qt_drt_counterValueForElementByIdP9QWebFrameRK7QString @ 652 NONAME + _Z33qt_drt_counterValueForElementByIdP9QWebFrameRK7QString @ 652 NONAME ABSENT _Z34qt_drt_resetOriginAccessWhiteListsv @ 653 NONAME _ZN11QWebElement17removeAllChildrenEv @ 654 NONAME _ZN11QWebElement6renderEP8QPainter @ 655 NONAME @@ -698,25 +698,25 @@ EXPORTS _ZN9QWebFrame17scrollRecursivelyEii @ 697 NONAME ABSENT _ZN16QGraphicsWebView20setResizesToContentsEb @ 698 NONAME _ZNK16QGraphicsWebView17resizesToContentsEv @ 699 NONAME - _Z20qt_drt_numberOfPagesP9QWebFrameff @ 700 NONAME - _Z24qt_drt_pauseSVGAnimationP9QWebFrameRK7QStringdS3_ @ 701 NONAME - _Z24qt_drt_webinspector_showP8QWebPage @ 702 NONAME - _Z24qt_drt_workerThreadCountv @ 703 NONAME - _Z25qt_drt_hasDocumentElementP9QWebFrame @ 704 NONAME - _Z25qt_drt_webinspector_closeP8QWebPage @ 705 NONAME - _Z31qt_drt_pageNumberForElementByIdP9QWebFrameRK7QStringff @ 706 NONAME - _Z33qt_drt_webinspector_executeScriptP8QWebPagelRK7QString @ 707 NONAME - _Z34qt_drt_setTimelineProfilingEnabledP8QWebPageb @ 708 NONAME - _Z32qt_drt_setFrameFlatteningEnabledP8QWebPageb @ 709 NONAME - _Z36qt_drt_evaluateScriptInIsolatedWorldP9QWebFrameiRK7QString @ 710 NONAME - _Z47qt_drt_setDomainRelaxationForbiddenForURLSchemebRK7QString @ 711 NONAME + _Z20qt_drt_numberOfPagesP9QWebFrameff @ 700 NONAME ABSENT + _Z24qt_drt_pauseSVGAnimationP9QWebFrameRK7QStringdS3_ @ 701 NONAME ABSENT + _Z24qt_drt_webinspector_showP8QWebPage @ 702 NONAME ABSENT + _Z24qt_drt_workerThreadCountv @ 703 NONAME ABSENT + _Z25qt_drt_hasDocumentElementP9QWebFrame @ 704 NONAME ABSENT + _Z25qt_drt_webinspector_closeP8QWebPage @ 705 NONAME ABSENT + _Z31qt_drt_pageNumberForElementByIdP9QWebFrameRK7QStringff @ 706 NONAME ABSENT + _Z33qt_drt_webinspector_executeScriptP8QWebPagelRK7QString @ 707 NONAME ABSENT + _Z34qt_drt_setTimelineProfilingEnabledP8QWebPageb @ 708 NONAME ABSENT + _Z32qt_drt_setFrameFlatteningEnabledP8QWebPageb @ 709 NONAME ABSENT + _Z36qt_drt_evaluateScriptInIsolatedWorldP9QWebFrameiRK7QString @ 710 NONAME ABSENT + _Z47qt_drt_setDomainRelaxationForbiddenForURLSchemebRK7QString @ 711 NONAME ABSENT _ZN9QWebFrame11pageChangedEv @ 712 NONAME _ZN9QWebFrame14scrollToAnchorERK7QString @ 713 NONAME - _ZN12QWebSettings15setInspectorUrlERK4QUrl @ 714 NONAME + _ZN12QWebSettings15setInspectorUrlERK4QUrl @ 714 NONAME ABSENT _ZN13QWebInspector10closeEventEP11QCloseEvent @ 715 NONAME _ZN16QGraphicsWebView26setTiledBackingStoreFrozenEb @ 716 NONAME _ZNK16QGraphicsWebView25isTiledBackingStoreFrozenEv @ 717 NONAME - _Z18qt_wrt_setViewModeP8QWebPageRK7QString @ 718 NONAME - _Z19qt_drt_setMediaTypeP9QWebFrameRK7QString @ 719 NONAME - _Z26qt_drt_enableCaretBrowsingP8QWebPageb @ 720 NONAME - _ZNK12QWebSettings12inspectorUrlEv @ 721 NONAME + _Z18qt_wrt_setViewModeP8QWebPageRK7QString @ 718 NONAME ABSENT + _Z19qt_drt_setMediaTypeP9QWebFrameRK7QString @ 719 NONAME ABSENT + _Z26qt_drt_enableCaretBrowsingP8QWebPageb @ 720 NONAME ABSENT + _ZNK12QWebSettings12inspectorUrlEv @ 721 NONAME ABSENT diff --git a/WebKit/qt/tests/benchmarks/loading/loading.pro b/WebKit/qt/tests/benchmarks/loading/loading.pro index 024211f..99c64a5 100644 --- a/WebKit/qt/tests/benchmarks/loading/loading.pro +++ b/WebKit/qt/tests/benchmarks/loading/loading.pro @@ -1,2 +1,3 @@ isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../../.. include(../../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/benchmarks/painting/painting.pro b/WebKit/qt/tests/benchmarks/painting/painting.pro index b4fc56a..99c64a5 100644 --- a/WebKit/qt/tests/benchmarks/painting/painting.pro +++ b/WebKit/qt/tests/benchmarks/painting/painting.pro @@ -1,2 +1,3 @@ isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../../.. -include(../../tests.pri)
\ No newline at end of file +include(../../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/hybridPixmap/widget.ui b/WebKit/qt/tests/hybridPixmap/widget.ui index 4f2b3b8..272d6a7 100644 --- a/WebKit/qt/tests/hybridPixmap/widget.ui +++ b/WebKit/qt/tests/hybridPixmap/widget.ui @@ -11,14 +11,14 @@ </rect> </property> <property name="windowTitle"> - <string>Widget</string> + <string notr="true">Widget</string> </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> <widget class="WebView" name="webView" native="true"> <property name="url" stdset="0"> <url> - <string>about:blank</string> + <string notr="true">about:blank</string> </url> </property> </widget> @@ -28,7 +28,7 @@ <item> <widget class="QLabel" name="lbl1"> <property name="text"> - <string/> + <string notr="true"/> </property> </widget> </item> @@ -47,21 +47,21 @@ </size> </property> <property name="text"> - <string>Image from Qt to HTML</string> + <string notr="true">Image from Qt to HTML</string> </property> </widget> </item> <item> <widget class="QLabel" name="lbl3"> <property name="text"> - <string>Pixmap from Qt to HTML</string> + <string notr="true">Pixmap from Qt to HTML</string> </property> </widget> </item> <item> <widget class="QLabel" name="lbl4"> <property name="text"> - <string/> + <string notr="true"/> </property> </widget> </item> diff --git a/WebKit/qt/tests/qgraphicswebview/qgraphicswebview.pro b/WebKit/qt/tests/qgraphicswebview/qgraphicswebview.pro index d056014..e915d60 100644 --- a/WebKit/qt/tests/qgraphicswebview/qgraphicswebview.pro +++ b/WebKit/qt/tests/qgraphicswebview/qgraphicswebview.pro @@ -1,2 +1,3 @@ isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. -include(../tests.pri)
\ No newline at end of file +include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qgraphicswebview/tst_qgraphicswebview.cpp b/WebKit/qt/tests/qgraphicswebview/tst_qgraphicswebview.cpp index 657e09f..14f5820 100644 --- a/WebKit/qt/tests/qgraphicswebview/tst_qgraphicswebview.cpp +++ b/WebKit/qt/tests/qgraphicswebview/tst_qgraphicswebview.cpp @@ -31,6 +31,7 @@ class tst_QGraphicsWebView : public QObject private slots: void qgraphicswebview(); void crashOnViewlessWebPages(); + void microFocusCoordinates(); }; void tst_QGraphicsWebView::qgraphicswebview() @@ -102,6 +103,40 @@ void tst_QGraphicsWebView::crashOnViewlessWebPages() QVERIFY(waitForSignal(page, SIGNAL(loadFinished(bool)))); } +void tst_QGraphicsWebView::microFocusCoordinates() +{ + QWebPage* page = new QWebPage; + QGraphicsWebView* webView = new QGraphicsWebView; + webView->setPage( page ); + QGraphicsView* view = new QGraphicsView; + QGraphicsScene* scene = new QGraphicsScene(view); + view->setScene(scene); + scene->addItem(webView); + view->setGeometry(QRect(0,0,500,500)); + + page->mainFrame()->setHtml("<html><body>" \ + "<input type='text' id='input1' style='font--family: serif' value='' maxlength='20'/><br>" \ + "<canvas id='canvas1' width='500' height='500'/>" \ + "<input type='password'/><br>" \ + "<canvas id='canvas2' width='500' height='500'/>" \ + "</body></html>"); + + page->mainFrame()->setFocus(); + + QVariant initialMicroFocus = page->inputMethodQuery(Qt::ImMicroFocus); + QVERIFY(initialMicroFocus.isValid()); + + page->mainFrame()->scroll(0,300); + + QVariant currentMicroFocus = page->inputMethodQuery(Qt::ImMicroFocus); + QVERIFY(currentMicroFocus.isValid()); + + QCOMPARE(initialMicroFocus.toRect().translated(QPoint(0,-300)), currentMicroFocus.toRect()); + + delete view; +} + + QTEST_MAIN(tst_QGraphicsWebView) #include "tst_qgraphicswebview.moc" diff --git a/WebKit/qt/tests/qwebelement/qwebelement.pro b/WebKit/qt/tests/qwebelement/qwebelement.pro index d056014..e915d60 100644 --- a/WebKit/qt/tests/qwebelement/qwebelement.pro +++ b/WebKit/qt/tests/qwebelement/qwebelement.pro @@ -1,2 +1,3 @@ isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. -include(../tests.pri)
\ No newline at end of file +include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qwebframe/qwebframe.pro b/WebKit/qt/tests/qwebframe/qwebframe.pro index d056014..e915d60 100644 --- a/WebKit/qt/tests/qwebframe/qwebframe.pro +++ b/WebKit/qt/tests/qwebframe/qwebframe.pro @@ -1,2 +1,3 @@ isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. -include(../tests.pri)
\ No newline at end of file +include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp b/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp index 5f5a2f2..bea7a67 100644 --- a/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp +++ b/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp @@ -57,6 +57,7 @@ class MyQObject : public QObject Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty) Q_PROPERTY(QVariant variantProperty READ variantProperty WRITE setVariantProperty) Q_PROPERTY(QVariantList variantListProperty READ variantListProperty WRITE setVariantListProperty) + Q_PROPERTY(QVariantMap variantMapProperty READ variantMapProperty WRITE setVariantMapProperty) Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty) Q_PROPERTY(QStringList stringListProperty READ stringListProperty WRITE setStringListProperty) Q_PROPERTY(QByteArray byteArrayProperty READ byteArrayProperty WRITE setByteArrayProperty) @@ -106,7 +107,12 @@ public: m_writeOnlyValue(789), m_readOnlyValue(987), m_objectStar(0), - m_qtFunctionInvoked(-1) { } + m_qtFunctionInvoked(-1) + { + m_variantMapValue.insert("a", QVariant(123)); + m_variantMapValue.insert("b", QVariant(QLatin1String("foo"))); + m_variantMapValue.insert("c", QVariant::fromValue<QObject*>(this)); + } ~MyQObject() { } @@ -131,6 +137,13 @@ public: m_variantListValue = value; } + QVariantMap variantMapProperty() const { + return m_variantMapValue; + } + void setVariantMapProperty(const QVariantMap &value) { + m_variantMapValue = value; + } + QString stringProperty() const { return m_stringValue; } @@ -483,6 +496,7 @@ private: int m_intValue; QVariant m_variantValue; QVariantList m_variantListValue; + QVariantMap m_variantMapValue; QString m_stringValue; QStringList m_stringListValue; QByteArray m_byteArrayValue; @@ -759,6 +773,21 @@ void tst_QWebFrame::getSetStaticProperty() { QString type; + QVariant ret = evalJSV("myObject.variantMapProperty", type); + QCOMPARE(type, sObject); + QCOMPARE(ret.type(), QVariant::Map); + QVariantMap vm = ret.value<QVariantMap>(); + QCOMPARE(vm.size(), 3); + QCOMPARE(vm.value("a").toInt(), 123); + QCOMPARE(vm.value("b").toString(), QLatin1String("foo")); + QCOMPARE(vm.value("c").value<QObject*>(), m_myObject); + } + QCOMPARE(evalJS("myObject.variantMapProperty.a === 123"), sTrue); + QCOMPARE(evalJS("myObject.variantMapProperty.b === 'foo'"), sTrue); + QCOMPARE(evalJS("myObject.variantMapProperty.c.variantMapProperty.b === 'foo'"), sTrue); + + { + QString type; QVariant ret = evalJSV("myObject.stringListProperty", type); QCOMPARE(type, sArray); QCOMPARE(ret.type(), QVariant::List); diff --git a/WebKit/qt/tests/qwebhistory/qwebhistory.pro b/WebKit/qt/tests/qwebhistory/qwebhistory.pro index d056014..e915d60 100644 --- a/WebKit/qt/tests/qwebhistory/qwebhistory.pro +++ b/WebKit/qt/tests/qwebhistory/qwebhistory.pro @@ -1,2 +1,3 @@ isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. -include(../tests.pri)
\ No newline at end of file +include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qwebhistoryinterface/qwebhistoryinterface.pro b/WebKit/qt/tests/qwebhistoryinterface/qwebhistoryinterface.pro index d056014..e915d60 100644 --- a/WebKit/qt/tests/qwebhistoryinterface/qwebhistoryinterface.pro +++ b/WebKit/qt/tests/qwebhistoryinterface/qwebhistoryinterface.pro @@ -1,2 +1,3 @@ isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. -include(../tests.pri)
\ No newline at end of file +include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qwebhistoryinterface/tst_qwebhistoryinterface.cpp b/WebKit/qt/tests/qwebhistoryinterface/tst_qwebhistoryinterface.cpp index 435cada..84b12d2 100644 --- a/WebKit/qt/tests/qwebhistoryinterface/tst_qwebhistoryinterface.cpp +++ b/WebKit/qt/tests/qwebhistoryinterface/tst_qwebhistoryinterface.cpp @@ -23,6 +23,7 @@ #include <qwebpage.h> #include <qwebview.h> #include <qwebframe.h> +#include <qwebelement.h> #include <qwebhistoryinterface.h> #include <QDebug> @@ -85,9 +86,10 @@ public: void tst_QWebHistoryInterface::visitedLinks() { QWebHistoryInterface::setDefaultInterface(new FakeHistoryImplementation); - m_view->setHtml("<html><body><a href='http://www.trolltech.com'>Trolltech</a></body></html>"); - QCOMPARE(m_page->mainFrame()->evaluateJavaScript("document.querySelectorAll(':visited').length;").toString(), - QString::fromLatin1("1")); + m_view->setHtml("<html><style>:link{color:green}:visited{color:red}</style><body><a href='http://www.trolltech.com' id='vlink'>Trolltech</a></body></html>"); + QWebElement anchor = m_view->page()->mainFrame()->findFirstElement("a[id=vlink]"); + QString linkColor = anchor.styleProperty("color", QWebElement::ComputedStyle); + QCOMPARE(linkColor, QString::fromLatin1("rgb(255, 0, 0)")); } QTEST_MAIN(tst_QWebHistoryInterface) diff --git a/WebKit/qt/tests/qwebinspector/qwebinspector.pro b/WebKit/qt/tests/qwebinspector/qwebinspector.pro index ac51929..e915d60 100644 --- a/WebKit/qt/tests/qwebinspector/qwebinspector.pro +++ b/WebKit/qt/tests/qwebinspector/qwebinspector.pro @@ -1,2 +1,3 @@ isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qwebpage/qwebpage.pro b/WebKit/qt/tests/qwebpage/qwebpage.pro index d056014..e915d60 100644 --- a/WebKit/qt/tests/qwebpage/qwebpage.pro +++ b/WebKit/qt/tests/qwebpage/qwebpage.pro @@ -1,2 +1,3 @@ isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. -include(../tests.pri)
\ No newline at end of file +include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp b/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp index c857b00..795216d 100644 --- a/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp +++ b/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp @@ -24,6 +24,7 @@ #include <QDir> #include <QGraphicsWidget> #include <QLineEdit> +#include <QLocale> #include <QMenu> #include <QPushButton> #include <QtTest/QtTest> @@ -81,7 +82,8 @@ private slots: void modified(); void contextMenuCrash(); void database(); - void createPlugin(); + void createPluginWithPluginsEnabled(); + void createPluginWithPluginsDisabled(); void destroyPlugin_data(); void destroyPlugin(); void createViewlessPlugin_data(); @@ -106,6 +108,10 @@ private slots: void errorPageExtension(); void errorPageExtensionInIFrames(); void errorPageExtensionInFrameset(); + void userAgentApplicationName(); + void userAgentLocaleChange(); + + void viewModes(); void crashTests_LazyInitializationOfMainFrame(); @@ -354,6 +360,21 @@ void tst_QWebPage::userStyleSheet() QCOMPARE(networkManager->requestedUrls.at(0), QUrl("http://does.not/exist.png")); } +void tst_QWebPage::viewModes() +{ + m_view->setHtml("<body></body>"); + m_page->setProperty("_q_viewMode", "minimized"); + + QVariant empty = m_page->mainFrame()->evaluateJavaScript("window.styleMedia.matchMedium(\"(-webkit-view-mode)\")"); + QVERIFY(empty.type() == QVariant::Bool && empty.toBool()); + + QVariant minimized = m_page->mainFrame()->evaluateJavaScript("window.styleMedia.matchMedium(\"(-webkit-view-mode: minimized)\")"); + QVERIFY(minimized.type() == QVariant::Bool && minimized.toBool()); + + QVariant maximized = m_page->mainFrame()->evaluateJavaScript("window.styleMedia.matchMedium(\"(-webkit-view-mode: maximized)\")"); + QVERIFY(maximized.type() == QVariant::Bool && !maximized.toBool()); +} + void tst_QWebPage::modified() { m_page->mainFrame()->setUrl(QUrl("data:text/html,<body>blub")); @@ -519,27 +540,20 @@ protected: } }; -void tst_QWebPage::createPlugin() +static void createPlugin(QWebView *view) { - QSignalSpy loadSpy(m_view, SIGNAL(loadFinished(bool))); + QSignalSpy loadSpy(view, SIGNAL(loadFinished(bool))); - PluginPage* newPage = new PluginPage(m_view); - m_view->setPage(newPage); + PluginPage* newPage = new PluginPage(view); + view->setPage(newPage); - // plugins not enabled by default, so the plugin shouldn't be loaded - m_view->setHtml(QString("<html><body><object type='application/x-qt-plugin' classid='pushbutton' id='mybutton'/></body></html>")); + // type has to be application/x-qt-plugin + view->setHtml(QString("<html><body><object type='application/x-foobarbaz' classid='pushbutton' id='mybutton'/></body></html>")); QTRY_COMPARE(loadSpy.count(), 1); QCOMPARE(newPage->calls.count(), 0); - m_view->settings()->setAttribute(QWebSettings::PluginsEnabled, true); - - // type has to be application/x-qt-plugin - m_view->setHtml(QString("<html><body><object type='application/x-foobarbaz' classid='pushbutton' id='mybutton'/></body></html>")); + view->setHtml(QString("<html><body><object type='application/x-qt-plugin' classid='pushbutton' id='mybutton'/></body></html>")); QTRY_COMPARE(loadSpy.count(), 2); - QCOMPARE(newPage->calls.count(), 0); - - m_view->setHtml(QString("<html><body><object type='application/x-qt-plugin' classid='pushbutton' id='mybutton'/></body></html>")); - QTRY_COMPARE(loadSpy.count(), 3); QCOMPARE(newPage->calls.count(), 1); { PluginPage::CallInfo ci = newPage->calls.takeFirst(); @@ -570,11 +584,11 @@ void tst_QWebPage::createPlugin() QCOMPARE(newPage->mainFrame()->evaluateJavaScript("mybutton.clicked.toString()").toString(), QString::fromLatin1("function clicked() {\n [native code]\n}")); - m_view->setHtml(QString("<html><body><table>" + view->setHtml(QString("<html><body><table>" "<tr><object type='application/x-qt-plugin' classid='lineedit' id='myedit'/></tr>" "<tr><object type='application/x-qt-plugin' classid='pushbutton' id='mybutton'/></tr>" "</table></body></html>"), QUrl("http://foo.bar.baz")); - QTRY_COMPARE(loadSpy.count(), 4); + QTRY_COMPARE(loadSpy.count(), 3); QCOMPARE(newPage->calls.count(), 2); { PluginPage::CallInfo ci = newPage->calls.takeFirst(); @@ -606,14 +620,22 @@ void tst_QWebPage::createPlugin() QVERIFY(ci.returnValue != 0); QVERIFY(ci.returnValue->inherits("QPushButton")); } +} - m_view->settings()->setAttribute(QWebSettings::PluginsEnabled, false); - - m_view->setHtml(QString("<html><body><object type='application/x-qt-plugin' classid='pushbutton' id='mybutton'/></body></html>")); - QTRY_COMPARE(loadSpy.count(), 5); - QCOMPARE(newPage->calls.count(), 0); +void tst_QWebPage::createPluginWithPluginsEnabled() +{ + m_view->settings()->setAttribute(QWebSettings::PluginsEnabled, true); + createPlugin(m_view); } +void tst_QWebPage::createPluginWithPluginsDisabled() +{ + // Qt Plugins should be loaded by QtWebKit even when PluginsEnabled is + // false. The client decides whether a Qt plugin is enabled or not when + // it decides whether or not to instantiate it. + m_view->settings()->setAttribute(QWebSettings::PluginsEnabled, false); + createPlugin(m_view); +} // Standard base class for template PluginTracerPage. In tests it is used as interface. class PluginCounterPage : public QWebPage { @@ -1404,11 +1426,16 @@ void tst_QWebPage::inputMethods() QString selectionValue = variant.value<QString>(); QCOMPARE(selectionValue, QString("eb")); - //Set selection with negative length - inputAttributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 6, -5, QVariant()); + //Cancel current composition first + inputAttributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 0, 0, QVariant()); QInputMethodEvent eventSelection2("",inputAttributes); page->event(&eventSelection2); + //Set selection with negative length + inputAttributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 6, -5, QVariant()); + QInputMethodEvent eventSelection3("",inputAttributes); + page->event(&eventSelection3); + //ImAnchorPosition variant = page->inputMethodQuery(Qt::ImAnchorPosition); anchorPosition = variant.toInt(); @@ -1741,6 +1768,38 @@ void tst_QWebPage::errorPageExtensionInFrameset() m_view->setPage(0); } +class FriendlyWebPage : public QWebPage +{ +public: + friend class tst_QWebPage; +}; + +void tst_QWebPage::userAgentApplicationName() +{ + const QString oldApplicationName = QCoreApplication::applicationName(); + FriendlyWebPage page; + + const QString applicationNameMarker = QString::fromUtf8("StrangeName\342\210\236"); + QCoreApplication::setApplicationName(applicationNameMarker); + QVERIFY(page.userAgentForUrl(QUrl()).contains(applicationNameMarker)); + + QCoreApplication::setApplicationName(oldApplicationName); +} + +void tst_QWebPage::userAgentLocaleChange() +{ + FriendlyWebPage page; + m_view->setPage(&page); + + const QString markerString = QString::fromLatin1(" nn-NO)"); + + if (page.userAgentForUrl(QUrl()).contains(markerString)) + QSKIP("marker string already present", SkipSingle); + + m_view->setLocale(QLocale(QString::fromLatin1("nn_NO"))); + QVERIFY(page.userAgentForUrl(QUrl()).contains(markerString)); +} + void tst_QWebPage::crashTests_LazyInitializationOfMainFrame() { { diff --git a/WebKit/qt/tests/qwebplugindatabase/qwebplugindatabase.pro b/WebKit/qt/tests/qwebplugindatabase/qwebplugindatabase.pro index ac51929..e915d60 100644 --- a/WebKit/qt/tests/qwebplugindatabase/qwebplugindatabase.pro +++ b/WebKit/qt/tests/qwebplugindatabase/qwebplugindatabase.pro @@ -1,2 +1,3 @@ isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qwebview/qwebview.pro b/WebKit/qt/tests/qwebview/qwebview.pro index 4ca2bf6..e915d60 100644 --- a/WebKit/qt/tests/qwebview/qwebview.pro +++ b/WebKit/qt/tests/qwebview/qwebview.pro @@ -1 +1,3 @@ -include(../tests.pri)
\ No newline at end of file +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. +include(../tests.pri) +exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc diff --git a/WebKit/qt/tests/qwebview/tst_qwebview.cpp b/WebKit/qt/tests/qwebview/tst_qwebview.cpp index ebcf4bb..100399e 100644 --- a/WebKit/qt/tests/qwebview/tst_qwebview.cpp +++ b/WebKit/qt/tests/qwebview/tst_qwebview.cpp @@ -48,6 +48,7 @@ private slots: void reusePage_data(); void reusePage(); + void microFocusCoordinates(); void crashTests(); }; @@ -203,6 +204,31 @@ void tst_QWebView::crashTests() QTRY_VERIFY(tester.m_executed); // If fail it means that the test wasn't executed. } +void tst_QWebView::microFocusCoordinates() +{ + QWebPage* page = new QWebPage; + QWebView* webView = new QWebView; + webView->setPage( page ); + + page->mainFrame()->setHtml("<html><body>" \ + "<input type='text' id='input1' style='font--family: serif' value='' maxlength='20'/><br>" \ + "<canvas id='canvas1' width='500' height='500'/>" \ + "<input type='password'/><br>" \ + "<canvas id='canvas2' width='500' height='500'/>" \ + "</body></html>"); + + page->mainFrame()->setFocus(); + + QVariant initialMicroFocus = page->inputMethodQuery(Qt::ImMicroFocus); + QVERIFY(initialMicroFocus.isValid()); + + page->mainFrame()->scroll(0,50); + + QVariant currentMicroFocus = page->inputMethodQuery(Qt::ImMicroFocus); + QVERIFY(currentMicroFocus.isValid()); + + QCOMPARE(initialMicroFocus.toRect().translated(QPoint(0,-50)), currentMicroFocus.toRect()); +} QTEST_MAIN(tst_QWebView) #include "tst_qwebview.moc" diff --git a/WebKit/qt/tests/tests.pri b/WebKit/qt/tests/tests.pri index 0bdf6f6..525e662 100644 --- a/WebKit/qt/tests/tests.pri +++ b/WebKit/qt/tests/tests.pri @@ -2,14 +2,13 @@ TEMPLATE = app CONFIG -= app_bundle VPATH += $$_PRO_FILE_PWD_ +# Add the tst_ prefix, In QTDIR_build it's done by qttest_p4.prf !CONFIG(QTDIR_build):TARGET = tst_$$TARGET SOURCES += $${TARGET}.cpp INCLUDEPATH += \ $$PWD \ $$PWD/../Api -exists($$_PRO_FILE_PWD_/$${TARGET}.qrc):RESOURCES += $$_PRO_FILE_PWD_/$${TARGET}.qrc - include(../../../WebKit.pri) QT += testlib network diff --git a/WebKit/win/ChangeLog b/WebKit/win/ChangeLog index 287a9be..c342ab0 100644 --- a/WebKit/win/ChangeLog +++ b/WebKit/win/ChangeLog @@ -1,3 +1,269 @@ +2010-05-06 Adam Roben <aroben@apple.com> + + Bail out of WebView::paint when there's nothing to paint + + Fixes <http://webkit.org/b/38670> <rdar://problem/7947105> REGRESSION + (r58067): Crash in WebView::paint when Web Inspector is docked and + window is resized so small that WebView disappears + + When the WebView is 0-sized, ensureBackingStore() bails out without + creating a bitmap, leaving m_backingStoreBitmap null. Before r58067, + m_backingStoreBitmap was an HBITMAP, so we were happily passing along + a null HBITMAP to various Windows APIs. These calls would fail but not + crash. r58067 changed m_backingStoreBitmap to a RefCountedHBITMAP, and + dereferencing a null RefCountedHBITMAP* of course crashes. + + Reviewed by Steve Falkenburg. + + * WebView.cpp: + (WebView::paint): Bail if the rect to paint is empty. + +2010-05-06 Steve Falkenburg <sfalken@apple.com> + + Reviewed by Adam Roben. + + WebFrame::paintDocumentRectToContext paints content at the wrong location + https://bugs.webkit.org/show_bug.cgi?id=38651 + + * WebFrame.cpp: + (WebFrame::paintDocumentRectToContext): + +2010-05-05 Stuart Morgan <stuartmorgan@chromium.org> + + Reviewed by Darin Fisher. + + Update setFocus for the new boolean argument; no behavioral change. + + https://bugs.webkit.org/show_bug.cgi?id=37961 + + * WebCoreSupport/EmbeddedWidget.cpp: + (EmbeddedWidget::setFocus): + * WebCoreSupport/EmbeddedWidget.h: + +2010-05-03 Abhishek Arya <inferno@chromium.org> + + Reviewed by Adam Barth. + + Add support for controlling clipboard access from javascript. + Clipboard access from javascript is disabled by default. + https://bugs.webkit.org/show_bug.cgi?id=27751 + + * Interfaces/IWebPreferencesPrivate.idl: + * WebPreferenceKeysPrivate.h: + * WebPreferences.cpp: + (WebPreferences::initializeDefaultSettings): + (WebPreferences::javaScriptCanAccessClipboard): + (WebPreferences::setJavaScriptCanAccessClipboard): + * WebPreferences.h: + * WebView.cpp: + (WebView::notifyPreferencesChanged): + +2010-05-03 Jens Alfke <snej@chromium.org> + + Reviewed by Darin Fisher. + + [chromium] Add "willSendSubmitEvent" hook to WebFrameClient and FrameLoaderClient + https://bugs.webkit.org/show_bug.cgi?id=38397 + + No tests (functionality is exposed only through native WebKit API.) + + * WebFrame.h: + +2010-04-30 Jon Honeycutt <jhoneycutt@apple.com> + + Caret may fail to blink if a focus handler brings up a modal dialog + https://bugs.webkit.org/show_bug.cgi?id=38372 + + Reviewed by Darin Adler. + + * WebView.cpp: + (WebView::handleMouseEvent): + If the message is WM_CANCELMODE, which indicates that we our capturing + of mouse events has been cancelled, tell the EventHandler. + It's possible to re-enter this function if handling a mouse event allows + the message loop to run; moved up the call to setMouseActivated(), so + that if we do re-enter this function, the later mouse event will not be + considered as activating the window. + (WebView::WebViewWndProc): + Handle WM_CANCELMODE by calling handleMouseEvent(). + +2010-04-29 Anders Carlsson <andersca@apple.com> + + Reviewed by Dan Bernstein. + + First part of + https://bugs.webkit.org/show_bug.cgi?id=20784 + move npapi.h to C99 integer types. + + * WebKit.vcproj/WebKit.vcproj: + +2010-04-28 Beth Dakin <bdakin@apple.com> + + Reviewed by Darin Adler. + + Fix for <rdar://problem/7474349> + + Add a synchronous display mechanism for WKCACFLayerRenderer. + + * Interfaces/IWebViewPrivate.idl: + * Interfaces/WebKit.idl: + * WebView.cpp: + (WebView::WebView): + (WebView::updateRootLayerContents): + (WebView::nextDisplayIsSynchronous): + * WebView.h: + +2010-04-28 Steve Falkenburg <sfalken@apple.com> + + Reviewed by Maciej Stachowiak. + + WebView drawing code may access null backing store dirty region + https://bugs.webkit.org/show_bug.cgi?id=38245 + <rdar://problem/7916101> REGRESSION (r58067): All loaded pages fail to display after running iBench HTML test (intermittent) + + * WebView.cpp: + (WebView::updateBackingStore): Add null check for m_backingStoreDirtyRegion. + +2010-04-27 Jon Honeycutt <jhoneycutt@apple.com> + + <rdar://problem/7911140> Hitting the "delete" key goes back twice + + Reviewed by Maciej Stachowiak. + + * WebView.cpp: + (WebView::keyDown): + Return true if we navigated back or forward from the key event to + prevent the event from being propagated further. + +2010-04-25 Sam Weinig <sam@webkit.org> + + Reviewed by Maciej Stachowiak. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38097 + Disentangle initializing the main thread from initializing threading + + * WebKitClassFactory.cpp: + (WebKitClassFactory::WebKitClassFactory): Add call to initializeMainThread. + * WebView.cpp: + (WebView::WebView): Ditto. + +2010-04-25 Yury Semikhatsky <yurys@chromium.org> + + Reviewed by Pavel Feldman. + + Web Inspector: inspector client shouldn't check if it can be opened + docked if it is already in that state. + + https://bugs.webkit.org/show_bug.cgi?id=37946 + + * WebCoreSupport/WebInspectorClient.cpp: + (WebInspectorFrontendClient::WebInspectorFrontendClient): + (WebInspectorFrontendClient::showWindowWithoutNotifications): + * WebCoreSupport/WebInspectorClient.h: + +2010-04-24 Steve Falkenburg <sfalken@apple.com> + + Reviewed by Sam Weinig. + + Typo in Geolocation code causes crashes when updates are stopped + https://bugs.webkit.org/show_bug.cgi?id=38089 + <rdar://problem/7904104> Crash closing geolocation tab after allowing to use geolocation + + * WebCoreSupport/WebGeolocationControllerClient.cpp: + (WebGeolocationControllerClient::stopUpdating): Call unregister instead of register. + +2010-04-23 Andy Estes <aestes@apple.com> + + Rubber stamped by Steve Falkenburg. + + Roll out http://trac.webkit.org/changeset/55385. + + <rdar://problem/7884444> + + * Interfaces/IWebUIDelegatePrivate.idl: + * Interfaces/WebKit.idl: + * WebCoreSupport/WebFrameLoaderClient.cpp: + (WebFrameLoaderClient::createPlugin): + +2010-04-22 Dave Moore <davemoore@chromium.org> + + Reviewed by Dimitri Glazkov. + + Added notification when the favicons for a page are changed + from a script. + The Document object will notify the frame loader, which will + notify the client. Implementations of FrameLoaderClient will + have to add one method; dispatchDidChangeIcons(). + + https://bugs.webkit.org/show_bug.cgi?id=33812 + + * Interfaces/IWebFrameLoadDelegatePrivate2.idl: + * WebCoreSupport/WebFrameLoaderClient.cpp: + (WebFrameLoaderClient::dispatchDidChangeIcons): + * WebCoreSupport/WebFrameLoaderClient.h: + * WebFrame.cpp: + (WebFrame::didChangeIcons): + * WebFrame.h: + +2010-04-22 Adam Barth <abarth@webkit.org> + + Unreviewed, rolling out r58069. + http://trac.webkit.org/changeset/58069 + https://bugs.webkit.org/show_bug.cgi?id=27751 + + Broke compile on Windows. + + * Interfaces/IWebPreferencesPrivate.idl: + * WebPreferenceKeysPrivate.h: + * WebPreferences.cpp: + (WebPreferences::initializeDefaultSettings): + * WebPreferences.h: + * WebView.cpp: + (WebView::notifyPreferencesChanged): + +2010-04-22 Abhishek Arya <inferno@chromium.org> + + Reviewed by Adam Barth. + + Add support for controlling clipboard access from javascript. + Clipboard access from javascript is disabled by default. + https://bugs.webkit.org/show_bug.cgi?id=27751 + + * Interfaces/IWebPreferencesPrivate.idl: + * WebPreferenceKeysPrivate.h: + * WebPreferences.cpp: + (WebPreferences::initializeDefaultSettings): + (WebPreferences::javaScriptCanAccessClipboard): + (WebPreferences::setJavaScriptCanAccessClipboard): + * WebPreferences.h: + * WebView.cpp: + (WebView::notifyPreferencesChanged): + +2010-04-21 Andy Estes <aestes@apple.com> + + Reviewed by Maciej Stachowiak. + + Reference count WebView's backing store bitmap to prevent + deleteBackingStore() from freeing the bitmap while it is still being + referenced by Core Animation. + + https://bugs.webkit.org/show_bug.cgi?id=37954 + + * WebView.cpp: + (WebView::ensureBackingStore): + (WebView::addToDirtyRegion): + (WebView::scrollBackingStore): + (WebView::updateBackingStore): + (WebView::paint): + (WebView::backingStore): + (releaseBackingStoreCallback): deref m_backingStoreBitmap once Core + Animation has dropeed its reference to the memory. + (WebView::updateRootLayerContents): ref m_backingStoreBitmap before + passing the memory to Core Animation to prevent deleteBackingStore() + from freeing it while it is still referenced by CA. + * WebView.h: Make m_backingStoreBitmap a RefCountedGDIHandle<HBITMAP>, + and make m_backingStoreDirtyRegion a RefCountedGDIHandle<HRGN>. + 2010-04-20 Adam Barth <abarth@webkit.org> Reviewed by Eric Seidel. diff --git a/WebKit/win/Interfaces/IWebFrameLoadDelegatePrivate2.idl b/WebKit/win/Interfaces/IWebFrameLoadDelegatePrivate2.idl index 7e07c55..b1eb87a 100644 --- a/WebKit/win/Interfaces/IWebFrameLoadDelegatePrivate2.idl +++ b/WebKit/win/Interfaces/IWebFrameLoadDelegatePrivate2.idl @@ -52,4 +52,5 @@ interface IWebFrameLoadDelegatePrivate2 : IWebFrameLoadDelegatePrivate HRESULT didPushStateWithinPageForFrame([in] IWebView* webView, [in] IWebFrame* frame); HRESULT didReplaceStateWithinPageForFrame([in] IWebView* webView, [in] IWebFrame* frame); HRESULT didPopStateWithinPageForFrame([in] IWebView* webView, [in] IWebFrame* frame); + HRESULT didChangeIcons([in] IWebView* webView, [in] IWebFrame* frame); } diff --git a/WebKit/win/Interfaces/IWebPreferencesPrivate.idl b/WebKit/win/Interfaces/IWebPreferencesPrivate.idl index 76ee3fa..2cb4037 100644 --- a/WebKit/win/Interfaces/IWebPreferencesPrivate.idl +++ b/WebKit/win/Interfaces/IWebPreferencesPrivate.idl @@ -109,4 +109,7 @@ interface IWebPreferencesPrivate : IUnknown HRESULT setShowRepaintCounter([in] BOOL); HRESULT showRepaintCounter([out, retval] BOOL*); + + HRESULT javaScriptCanAccessClipboard([out, retval] BOOL *enabled); + HRESULT setJavaScriptCanAccessClipboard([in] BOOL enabled); } diff --git a/WebKit/win/Interfaces/IWebUIDelegatePrivate.idl b/WebKit/win/Interfaces/IWebUIDelegatePrivate.idl index d9702de..215c427 100755 --- a/WebKit/win/Interfaces/IWebUIDelegatePrivate.idl +++ b/WebKit/win/Interfaces/IWebUIDelegatePrivate.idl @@ -33,7 +33,6 @@ import "IWebView.idl"; cpp_quote("#define WebEmbeddedViewAttributesKey TEXT(\"WebEmbeddedViewAttributesKey\")") cpp_quote("#define WebEmbeddedViewBaseURLKey TEXT(\"WebEmbeddedViewBaseURLKey\")") -cpp_quote("#define WebEmbeddedViewSourceURLKey TEXT(\"WebEmbeddedViewSourceURLKey\")") cpp_quote("#define WebEmbeddedViewContainingElementKey TEXT(\"WebEmbeddedViewContainingElementKey\")") cpp_quote("#define WebEmbeddedViewMIMETypeKey TEXT(\"WebEmbeddedViewMIMETypeKey\")") diff --git a/WebKit/win/Interfaces/IWebViewPrivate.idl b/WebKit/win/Interfaces/IWebViewPrivate.idl index 17378ce..77ef4ac 100644 --- a/WebKit/win/Interfaces/IWebViewPrivate.idl +++ b/WebKit/win/Interfaces/IWebViewPrivate.idl @@ -231,4 +231,6 @@ interface IWebViewPrivate : IUnknown HRESULT setDomainRelaxationForbiddenForURLScheme([in] BOOL forbidden, [in] BSTR scheme); HRESULT registerURLSchemeAsSecure([in] BSTR scheme); + + HRESULT nextDisplayIsSynchronous(); } diff --git a/WebKit/win/Interfaces/WebKit.idl b/WebKit/win/Interfaces/WebKit.idl index d25cdfe..98f5da8 100644 --- a/WebKit/win/Interfaces/WebKit.idl +++ b/WebKit/win/Interfaces/WebKit.idl @@ -300,3 +300,4 @@ library WebKit [default] interface IWebUserContentURLPattern; } } + diff --git a/WebKit/win/WebCoreSupport/EmbeddedWidget.cpp b/WebKit/win/WebCoreSupport/EmbeddedWidget.cpp index 463a986..371ff3a 100644 --- a/WebKit/win/WebCoreSupport/EmbeddedWidget.cpp +++ b/WebKit/win/WebCoreSupport/EmbeddedWidget.cpp @@ -133,12 +133,12 @@ void EmbeddedWidget::frameRectsChanged() } } -void EmbeddedWidget::setFocus() +void EmbeddedWidget::setFocus(bool focused) { - if (m_window) + if (m_window && focused) SetFocus(m_window); - Widget::setFocus(); + Widget::setFocus(focused); } void EmbeddedWidget::show() diff --git a/WebKit/win/WebCoreSupport/EmbeddedWidget.h b/WebKit/win/WebCoreSupport/EmbeddedWidget.h index 7930e0f..ccd3451 100644 --- a/WebKit/win/WebCoreSupport/EmbeddedWidget.h +++ b/WebKit/win/WebCoreSupport/EmbeddedWidget.h @@ -62,7 +62,7 @@ private: virtual void invalidateRect(const WebCore::IntRect&); virtual void setFrameRect(const WebCore::IntRect&); virtual void frameRectsChanged(); - virtual void setFocus(); + virtual void setFocus(bool); virtual void show(); virtual void hide(); virtual WebCore::IntRect windowClipRect() const; diff --git a/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp b/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp index fc75ea4..48f7f3b 100644 --- a/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp +++ b/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp @@ -372,6 +372,20 @@ void WebFrameLoaderClient::dispatchDidReceiveTitle(const String& title) frameLoadDelegate->didReceiveTitle(webView, BString(title), m_webFrame); } +void WebFrameLoaderClient::dispatchDidChangeIcons() +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv; + if (FAILED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) || !frameLoadDelegatePriv) + return; + + COMPtr<IWebFrameLoadDelegatePrivate2> frameLoadDelegatePriv2(Query, frameLoadDelegatePriv); + if (!frameLoadDelegatePriv2) + return; + + frameLoadDelegatePriv2->didChangeIcons(webView, m_webFrame); +} + void WebFrameLoaderClient::dispatchDidCommitLoad() { WebView* webView = m_webFrame->webView(); @@ -837,8 +851,7 @@ PassRefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize& pluginSize, HashMap<String, COMVariant> arguments; arguments.set(WebEmbeddedViewAttributesKey, viewArgumentsBag); - arguments.set(WebEmbeddedViewSourceURLKey, url.string()); - arguments.set(WebEmbeddedViewBaseURLKey, element->document()->baseURI().string()); + arguments.set(WebEmbeddedViewBaseURLKey, url.string()); arguments.set(WebEmbeddedViewContainingElementKey, containingElement); arguments.set(WebEmbeddedViewMIMETypeKey, mimeType); diff --git a/WebKit/win/WebCoreSupport/WebFrameLoaderClient.h b/WebKit/win/WebCoreSupport/WebFrameLoaderClient.h index 0d89b2a..97d9a34 100644 --- a/WebKit/win/WebCoreSupport/WebFrameLoaderClient.h +++ b/WebKit/win/WebCoreSupport/WebFrameLoaderClient.h @@ -71,6 +71,7 @@ public: virtual void dispatchDidReceiveIcon(); virtual void dispatchDidStartProvisionalLoad(); virtual void dispatchDidReceiveTitle(const WebCore::String&); + virtual void dispatchDidChangeIcons(); virtual void dispatchDidCommitLoad(); virtual void dispatchDidFinishDocumentLoad(); virtual void dispatchDidFinishLoad(); diff --git a/WebKit/win/WebCoreSupport/WebGeolocationControllerClient.cpp b/WebKit/win/WebCoreSupport/WebGeolocationControllerClient.cpp index db5ed90..daacd6c 100644 --- a/WebKit/win/WebCoreSupport/WebGeolocationControllerClient.cpp +++ b/WebKit/win/WebCoreSupport/WebGeolocationControllerClient.cpp @@ -55,7 +55,7 @@ void WebGeolocationControllerClient::stopUpdating() COMPtr<IWebGeolocationProvider> provider; if (FAILED(m_webView->geolocationProvider(&provider))) return; - provider->registerWebView(m_webView.get()); + provider->unregisterWebView(m_webView.get()); } GeolocationPosition* WebGeolocationControllerClient::lastPosition() diff --git a/WebKit/win/WebCoreSupport/WebInspectorClient.cpp b/WebKit/win/WebCoreSupport/WebInspectorClient.cpp index 16ad172..3c263e5 100644 --- a/WebKit/win/WebCoreSupport/WebInspectorClient.cpp +++ b/WebKit/win/WebCoreSupport/WebInspectorClient.cpp @@ -213,7 +213,6 @@ WebInspectorFrontendClient::WebInspectorFrontendClient(WebView* inspectedWebView , m_frontendHwnd(frontendHwnd) , m_frontendWebView(frontendWebView) , m_frontendWebViewHwnd(frontendWebViewHwnd) - , m_shouldAttachWhenShown(false) , m_attached(false) , m_destroyingInspectorView(false) { @@ -354,14 +353,19 @@ void WebInspectorFrontendClient::showWindowWithoutNotifications() ASSERT(m_frontendWebView); ASSERT(m_inspectedWebViewHwnd); - // If no preference is set - default to an attached window. This is important for inspector LayoutTests. - String shouldAttach = m_inspectedWebView->page()->inspectorController()->setting(InspectorController::inspectorStartsAttachedSettingName()); - m_shouldAttachWhenShown = shouldAttach != "false"; - - if (m_shouldAttachWhenShown && !canAttachWindow()) - m_shouldAttachWhenShown = false; - - if (!m_shouldAttachWhenShown) { + bool shouldAttach = false; + if (m_attached) + shouldAttach = true; + else { + // If no preference is set - default to an attached window. This is important for inspector LayoutTests. + String shouldAttachPref = m_inspectedWebView->page()->inspectorController()->setting(InspectorController::inspectorStartsAttachedSettingName()); + shouldAttach = shouldAttachPref != "false"; + + if (shouldAttach && !canAttachWindow()) + shouldAttach = false; + } + + if (!shouldAttach) { // Put the Inspector's WebView inside our window and show it. m_frontendWebView->setHostWindow(reinterpret_cast<OLE_HANDLE>(m_frontendHwnd)); SendMessage(m_frontendHwnd, WM_SIZE, 0, 0); diff --git a/WebKit/win/WebCoreSupport/WebInspectorClient.h b/WebKit/win/WebCoreSupport/WebInspectorClient.h index 455e3a1..64773a5 100644 --- a/WebKit/win/WebCoreSupport/WebInspectorClient.h +++ b/WebKit/win/WebCoreSupport/WebInspectorClient.h @@ -112,7 +112,6 @@ private: COMPtr<WebView> m_frontendWebView; HWND m_frontendWebViewHwnd; - bool m_shouldAttachWhenShown; bool m_attached; WebCore::String m_inspectedURL; diff --git a/WebKit/win/WebFrame.cpp b/WebKit/win/WebFrame.cpp index 01cc2b1..3d9c8a8 100644 --- a/WebKit/win/WebFrame.cpp +++ b/WebKit/win/WebFrame.cpp @@ -346,13 +346,8 @@ HRESULT STDMETHODCALLTYPE WebFrame::paintDocumentRectToContext( GraphicsContext gc(dc); gc.setShouldIncludeChildWindows(true); gc.save(); - LONG width = rect.right - rect.left; - LONG height = rect.bottom - rect.top; - FloatRect dirtyRect; - dirtyRect.setWidth(width); - dirtyRect.setHeight(height); + IntRect dirtyRect(rect); gc.clip(dirtyRect); - gc.translate(-rect.left, -rect.top); view->paintContents(&gc, rect); gc.restore(); @@ -1544,6 +1539,11 @@ void WebFrame::didChangeTitle(DocumentLoader*) notImplemented(); } +void WebFrame::didChangeIcons(DocumentLoader*) +{ + notImplemented(); +} + bool WebFrame::canHandleRequest(const ResourceRequest& request) const { return WebView::canHandleRequest(request); diff --git a/WebKit/win/WebFrame.h b/WebKit/win/WebFrame.h index 0f1e4d8..d053d3b 100644 --- a/WebKit/win/WebFrame.h +++ b/WebKit/win/WebFrame.h @@ -286,11 +286,13 @@ public: virtual void detachedFromParent2(); virtual void detachedFromParent3(); virtual void cancelPolicyCheck(); + virtual void dispatchWillSendSubmitEvent(WebCore::HTMLFormElement*) { } virtual void dispatchWillSubmitForm(WebCore::FramePolicyFunction, PassRefPtr<WebCore::FormState>); virtual void revertToProvisionalState(WebCore::DocumentLoader*); virtual void setMainFrameDocumentReady(bool); virtual void willChangeTitle(WebCore::DocumentLoader*); virtual void didChangeTitle(WebCore::DocumentLoader*); + virtual void didChangeIcons(WebCore::DocumentLoader*); virtual bool canHandleRequest(const WebCore::ResourceRequest&) const; virtual bool canShowMIMEType(const WebCore::String& MIMEType) const; virtual bool representationExistsForURLScheme(const WebCore::String& URLScheme) const; diff --git a/WebKit/win/WebKit.vcproj/WebKit.vcproj b/WebKit/win/WebKit.vcproj/WebKit.vcproj index 36345ed..76b5e7b 100644 --- a/WebKit/win/WebKit.vcproj/WebKit.vcproj +++ b/WebKit/win/WebKit.vcproj/WebKit.vcproj @@ -88,7 +88,7 @@ />
<Tool
Name="VCPostBuildEventTool"
- CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(ProjectDir)\..\WebLocalizableStrings.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitGraphics.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitCOMAPI.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebPreferenceKeysPrivate.h" "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npfunctions.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npapi.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime_internal.h" "$(WebKitOutputDir)\include\WebKit"

mkdir 2>NUL "$(OutDir)\WebKit.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"
mkdir 2>NUL "$(OutDir)\WebKit.resources\en.lproj"
xcopy /y /d "$(ProjectDir)..\..\English.lproj\Localizable.strings" "$(OutDir)\WebKit.resources\en.lproj\"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(ProjectDir)\..\WebLocalizableStrings.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitGraphics.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitCOMAPI.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebPreferenceKeysPrivate.h" "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npapi.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npfunctions.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime_internal.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\nptypes.h" "$(WebKitOutputDir)\include\WebKit"

mkdir 2>NUL "$(OutDir)\WebKit.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"
mkdir 2>NUL "$(OutDir)\WebKit.resources\en.lproj"
xcopy /y /d "$(ProjectDir)..\..\English.lproj\Localizable.strings" "$(OutDir)\WebKit.resources\en.lproj\"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
<Configuration
@@ -165,7 +165,7 @@ />
<Tool
Name="VCPostBuildEventTool"
- CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(ProjectDir)\..\WebLocalizableStrings.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitGraphics.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitCOMAPI.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebPreferenceKeysPrivate.h" "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npfunctions.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npapi.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime_internal.h" "$(WebKitOutputDir)\include\WebKit"

mkdir 2>NUL "$(OutDir)\WebKit.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"
mkdir 2>NUL "$(OutDir)\WebKit.resources\en.lproj"
xcopy /y /d "$(ProjectDir)..\..\English.lproj\Localizable.strings" "$(OutDir)\WebKit.resources\en.lproj\"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(ProjectDir)\..\WebLocalizableStrings.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitGraphics.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitCOMAPI.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebPreferenceKeysPrivate.h" "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npapi.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npfunctions.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime_internal.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\nptypes.h" "$(WebKitOutputDir)\include\WebKit"

mkdir 2>NUL "$(OutDir)\WebKit.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"
mkdir 2>NUL "$(OutDir)\WebKit.resources\en.lproj"
xcopy /y /d "$(ProjectDir)..\..\English.lproj\Localizable.strings" "$(OutDir)\WebKit.resources\en.lproj\"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
<Configuration
@@ -242,7 +242,7 @@ />
<Tool
Name="VCPostBuildEventTool"
- CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(ProjectDir)\..\WebLocalizableStrings.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitGraphics.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitCOMAPI.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebPreferenceKeysPrivate.h" "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npfunctions.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npapi.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime_internal.h" "$(WebKitOutputDir)\include\WebKit"

mkdir 2>NUL "$(OutDir)\WebKit.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"
mkdir 2>NUL "$(OutDir)\WebKit.resources\en.lproj"
xcopy /y /d "$(ProjectDir)..\..\English.lproj\Localizable.strings" "$(OutDir)\WebKit.resources\en.lproj\"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(ProjectDir)\..\WebLocalizableStrings.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitGraphics.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitCOMAPI.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebPreferenceKeysPrivate.h" "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npapi.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npfunctions.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime_internal.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\nptypes.h" "$(WebKitOutputDir)\include\WebKit"

mkdir 2>NUL "$(OutDir)\WebKit.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"
mkdir 2>NUL "$(OutDir)\WebKit.resources\en.lproj"
xcopy /y /d "$(ProjectDir)..\..\English.lproj\Localizable.strings" "$(OutDir)\WebKit.resources\en.lproj\"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
<Configuration
@@ -319,7 +319,7 @@ />
<Tool
Name="VCPostBuildEventTool"
- CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(ProjectDir)\..\WebLocalizableStrings.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitGraphics.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitCOMAPI.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebPreferenceKeysPrivate.h" "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npfunctions.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npapi.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime_internal.h" "$(WebKitOutputDir)\include\WebKit"

mkdir 2>NUL "$(OutDir)\WebKit.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"
mkdir 2>NUL "$(OutDir)\WebKit.resources\en.lproj"
xcopy /y /d "$(ProjectDir)..\..\English.lproj\Localizable.strings" "$(OutDir)\WebKit.resources\en.lproj\"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(ProjectDir)\..\WebLocalizableStrings.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitGraphics.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitCOMAPI.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebPreferenceKeysPrivate.h" "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npapi.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npfunctions.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime_internal.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\nptypes.h" "$(WebKitOutputDir)\include\WebKit"

mkdir 2>NUL "$(OutDir)\WebKit.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"
mkdir 2>NUL "$(OutDir)\WebKit.resources\en.lproj"
xcopy /y /d "$(ProjectDir)..\..\English.lproj\Localizable.strings" "$(OutDir)\WebKit.resources\en.lproj\"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
<Configuration
@@ -398,7 +398,7 @@ />
<Tool
Name="VCPostBuildEventTool"
- CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(ProjectDir)\..\WebLocalizableStrings.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitGraphics.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitCOMAPI.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebPreferenceKeysPrivate.h" "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npfunctions.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npapi.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime_internal.h" "$(WebKitOutputDir)\include\WebKit"

mkdir 2>NUL "$(OutDir)\WebKit.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"
mkdir 2>NUL "$(OutDir)\WebKit.resources\en.lproj"
xcopy /y /d "$(ProjectDir)..\..\English.lproj\Localizable.strings" "$(OutDir)\WebKit.resources\en.lproj\"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(ProjectDir)\..\WebLocalizableStrings.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitGraphics.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitCOMAPI.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebPreferenceKeysPrivate.h" "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npapi.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npfunctions.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime_internal.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\nptypes.h" "$(WebKitOutputDir)\include\WebKit"

mkdir 2>NUL "$(OutDir)\WebKit.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"
mkdir 2>NUL "$(OutDir)\WebKit.resources\en.lproj"
xcopy /y /d "$(ProjectDir)..\..\English.lproj\Localizable.strings" "$(OutDir)\WebKit.resources\en.lproj\"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
<Configuration
@@ -475,7 +475,7 @@ />
<Tool
Name="VCPostBuildEventTool"
- CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(ProjectDir)\..\WebLocalizableStrings.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitGraphics.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitCOMAPI.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebPreferenceKeysPrivate.h" "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npfunctions.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npapi.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime_internal.h" "$(WebKitOutputDir)\include\WebKit"

mkdir 2>NUL "$(OutDir)\WebKit.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"
mkdir 2>NUL "$(OutDir)\WebKit.resources\en.lproj"
xcopy /y /d "$(ProjectDir)..\..\English.lproj\Localizable.strings" "$(OutDir)\WebKit.resources\en.lproj\"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(ProjectDir)\..\WebLocalizableStrings.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitGraphics.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebKitCOMAPI.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(ProjectDir)\..\WebPreferenceKeysPrivate.h" "$(WebKitOutputDir)\include\WebKit"

xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npapi.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npfunctions.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\npruntime_internal.h" "$(WebKitOutputDir)\include\WebKit"
xcopy /y /d "$(WebKitOutputDir)\include\WebCore\nptypes.h" "$(WebKitOutputDir)\include\WebKit"

mkdir 2>NUL "$(OutDir)\WebKit.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"
mkdir 2>NUL "$(OutDir)\WebKit.resources\en.lproj"
xcopy /y /d "$(ProjectDir)..\..\English.lproj\Localizable.strings" "$(OutDir)\WebKit.resources\en.lproj\"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
</Configurations>
diff --git a/WebKit/win/WebKitClassFactory.cpp b/WebKit/win/WebKitClassFactory.cpp index 8a956e3..0e6a689 100644 --- a/WebKit/win/WebKitClassFactory.cpp +++ b/WebKit/win/WebKitClassFactory.cpp @@ -57,10 +57,9 @@ #include "WebUserContentURLPattern.h" #include "WebView.h" #include "WebWorkersPrivate.h" -#pragma warning(push, 0) #include <JavaScriptCore/InitializeThreading.h> #include <WebCore/SoftLinking.h> -#pragma warning(pop) +#include <wtf/Threading.h> // WebKitClassFactory --------------------------------------------------------- #if USE(SAFARI_THEME) @@ -87,6 +86,7 @@ WebKitClassFactory::WebKitClassFactory(CLSID targetClass) #endif JSC::initializeThreading(); + WTF::initializeMainThread(); gClassCount++; gClassNameCount.add("WebKitClassFactory"); diff --git a/WebKit/win/WebPreferenceKeysPrivate.h b/WebKit/win/WebPreferenceKeysPrivate.h index c57934c..c49a96d 100644 --- a/WebKit/win/WebPreferenceKeysPrivate.h +++ b/WebKit/win/WebPreferenceKeysPrivate.h @@ -125,6 +125,8 @@ #define WebKitZoomsTextOnlyPreferenceKey "WebKitZoomsTextOnly" +#define WebKitJavaScriptCanAccessClipboardPreferenceKey "WebKitJavaScriptCanAccessClipboard" + #define WebKitXSSAuditorEnabledPreferenceKey "WebKitXSSAuditorEnabled" #define WebKitUseHighResolutionTimersPreferenceKey "WebKitUseHighResolutionTimers" diff --git a/WebKit/win/WebPreferences.cpp b/WebKit/win/WebPreferences.cpp index b5937cb..33e904d 100644 --- a/WebKit/win/WebPreferences.cpp +++ b/WebKit/win/WebPreferences.cpp @@ -206,6 +206,7 @@ void WebPreferences::initializeDefaultSettings() CFDictionaryAddValue(defaults, CFSTR(WebKitWebSecurityEnabledPreferenceKey), kCFBooleanTrue); CFDictionaryAddValue(defaults, CFSTR(WebKitAllowUniversalAccessFromFileURLsPreferenceKey), kCFBooleanFalse); CFDictionaryAddValue(defaults, CFSTR(WebKitAllowFileAccessFromFileURLsPreferenceKey), kCFBooleanTrue); + CFDictionaryAddValue(defaults, CFSTR(WebKitJavaScriptCanAccessClipboardPreferenceKey), kCFBooleanFalse); CFDictionaryAddValue(defaults, CFSTR(WebKitXSSAuditorEnabledPreferenceKey), kCFBooleanTrue); CFDictionaryAddValue(defaults, CFSTR(WebKitFrameFlatteningEnabledPreferenceKey), kCFBooleanFalse); CFDictionaryAddValue(defaults, CFSTR(WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey), kCFBooleanTrue); @@ -809,6 +810,20 @@ HRESULT STDMETHODCALLTYPE WebPreferences::setAllowFileAccessFromFileURLs( return S_OK; } +HRESULT STDMETHODCALLTYPE WebPreferences::javaScriptCanAccessClipboard( + /* [retval][out] */ BOOL* enabled) +{ + *enabled = boolValueForKey(CFSTR(WebKitJavaScriptCanAccessClipboardPreferenceKey)); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebPreferences::setJavaScriptCanAccessClipboard( + /* [in] */ BOOL enabled) +{ + setBoolValue(CFSTR(WebKitJavaScriptCanAccessClipboardPreferenceKey), enabled); + return S_OK; +} + HRESULT STDMETHODCALLTYPE WebPreferences::isXSSAuditorEnabled( /* [retval][out] */ BOOL* enabled) { diff --git a/WebKit/win/WebPreferences.h b/WebKit/win/WebPreferences.h index 241178d..cfdefa8 100644 --- a/WebKit/win/WebPreferences.h +++ b/WebKit/win/WebPreferences.h @@ -368,6 +368,12 @@ public: virtual HRESULT STDMETHODCALLTYPE setAllowFileAccessFromFileURLs( /* [in] */ BOOL allowAccess); + virtual HRESULT STDMETHODCALLTYPE javaScriptCanAccessClipboard( + /* [retval][out] */ BOOL* enabled); + + virtual HRESULT STDMETHODCALLTYPE setJavaScriptCanAccessClipboard( + /* [in] */ BOOL enabled); + virtual HRESULT STDMETHODCALLTYPE isXSSAuditorEnabled( /* [retval][out] */ BOOL* enabled); diff --git a/WebKit/win/WebView.cpp b/WebKit/win/WebView.cpp index da2c436..3a6a51f 100644 --- a/WebKit/win/WebView.cpp +++ b/WebKit/win/WebView.cpp @@ -123,6 +123,7 @@ #include <WebCore/SimpleFontData.h> #include <WebCore/TypingCommand.h> #include <WebCore/WindowMessageBroadcaster.h> +#include <wtf/Threading.h> #if ENABLE(CLIENT_BASED_GEOLOCATION) #include <WebCore/GeolocationController.h> @@ -340,8 +341,10 @@ WebView::WebView() #if USE(ACCELERATED_COMPOSITING) , m_isAcceleratedCompositing(false) #endif + , m_nextDisplayIsSynchronous(false) { JSC::initializeThreading(); + WTF::initializeMainThread(); m_backingStoreSize.cx = m_backingStoreSize.cy = 0; @@ -758,7 +761,7 @@ bool WebView::ensureBackingStore() BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(IntSize(m_backingStoreSize)); void* pixels = NULL; - m_backingStoreBitmap.set(::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pixels, NULL, 0)); + m_backingStoreBitmap = RefCountedHBITMAP::create(::CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0)); return true; } @@ -782,11 +785,11 @@ void WebView::addToDirtyRegion(HRGN newRegion) if (m_backingStoreDirtyRegion) { HRGN combinedRegion = ::CreateRectRgn(0,0,0,0); - ::CombineRgn(combinedRegion, m_backingStoreDirtyRegion.get(), newRegion, RGN_OR); + ::CombineRgn(combinedRegion, m_backingStoreDirtyRegion->handle(), newRegion, RGN_OR); ::DeleteObject(newRegion); - m_backingStoreDirtyRegion.set(combinedRegion); + m_backingStoreDirtyRegion = RefCountedHRGN::create(combinedRegion); } else - m_backingStoreDirtyRegion.set(newRegion); + m_backingStoreDirtyRegion = RefCountedHRGN::create(newRegion); #if USE(ACCELERATED_COMPOSITING) if (m_layerRenderer) @@ -815,7 +818,7 @@ void WebView::scrollBackingStore(FrameView* frameView, int dx, int dy, const Int // Collect our device context info and select the bitmap to scroll. HDC windowDC = ::GetDC(m_viewWindow); HDC bitmapDC = ::CreateCompatibleDC(windowDC); - ::SelectObject(bitmapDC, m_backingStoreBitmap.get()); + ::SelectObject(bitmapDC, m_backingStoreBitmap->handle()); // Scroll the bitmap. RECT scrollRectWin(scrollViewRect); @@ -892,7 +895,7 @@ void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStore if (!dc) { windowDC = ::GetDC(m_viewWindow); bitmapDC = ::CreateCompatibleDC(windowDC); - ::SelectObject(bitmapDC, m_backingStoreBitmap.get()); + ::SelectObject(bitmapDC, m_backingStoreBitmap->handle()); } if (m_backingStoreBitmap && (m_backingStoreDirtyRegion || backingStoreCompletelyDirty)) { @@ -902,10 +905,10 @@ void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStore view->layoutIfNeededRecursive(); Vector<IntRect> paintRects; - if (!backingStoreCompletelyDirty) { + if (!backingStoreCompletelyDirty && m_backingStoreDirtyRegion) { RECT regionBox; - ::GetRgnBox(m_backingStoreDirtyRegion.get(), ®ionBox); - getUpdateRects(m_backingStoreDirtyRegion.get(), regionBox, paintRects); + ::GetRgnBox(m_backingStoreDirtyRegion->handle(), ®ionBox); + getUpdateRects(m_backingStoreDirtyRegion->handle(), regionBox, paintRects); } else { RECT clientRect; ::GetClientRect(m_viewWindow, &clientRect); @@ -942,8 +945,6 @@ void WebView::paint(HDC dc, LPARAM options) return; FrameView* frameView = coreFrame->view(); - m_paintCount++; - RECT rcPaint; HDC hdc; OwnPtr<HRGN> region; @@ -968,9 +969,17 @@ void WebView::paint(HDC dc, LPARAM options) windowsToPaint = PaintWebViewAndChildren; } + if (::IsRectEmpty(&rcPaint)) { + if (!dc) + EndPaint(m_viewWindow, &ps); + return; + } + + m_paintCount++; + HDC bitmapDC = ::CreateCompatibleDC(hdc); bool backingStoreCompletelyDirty = ensureBackingStore(); - ::SelectObject(bitmapDC, m_backingStoreBitmap.get()); + ::SelectObject(bitmapDC, m_backingStoreBitmap->handle()); // Update our backing store if needed. updateBackingStore(frameView, bitmapDC, backingStoreCompletelyDirty, windowsToPaint); @@ -1323,12 +1332,19 @@ bool WebView::handleMouseEvent(UINT message, WPARAM wParam, LPARAM lParam) static MouseButton globalPrevButton; static LONG globalPrevMouseDownTime; + if (message == WM_CANCELMODE) { + m_page->mainFrame()->eventHandler()->lostMouseCapture(); + return true; + } + // Create our event. // On WM_MOUSELEAVE we need to create a mouseout event, so we force the position // of the event to be at (MINSHORT, MINSHORT). LPARAM position = (message == WM_MOUSELEAVE) ? ((MINSHORT << 16) | MINSHORT) : lParam; PlatformMouseEvent mouseEvent(m_viewWindow, message, wParam, position, m_mouseActivated); - + + setMouseActivated(false); + bool insideThreshold = abs(globalPrevPoint.x() - mouseEvent.pos().x()) < ::GetSystemMetrics(SM_CXDOUBLECLK) && abs(globalPrevPoint.y() - mouseEvent.pos().y()) < ::GetSystemMetrics(SM_CYDOUBLECLK); LONG messageTime = ::GetMessageTime(); @@ -1387,7 +1403,6 @@ bool WebView::handleMouseEvent(UINT message, WPARAM wParam, LPARAM lParam) ::TrackMouseEvent(m_mouseOutTracker.get()); } } - setMouseActivated(false); return handled; } @@ -1862,10 +1877,10 @@ bool WebView::keyDown(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown) // We need to handle back/forward using either Backspace(+Shift) or Ctrl+Left/Right Arrow keys. if ((virtualKeyCode == VK_BACK && keyEvent.shiftKey()) || (virtualKeyCode == VK_RIGHT && keyEvent.ctrlKey())) - m_page->goForward(); - else if (virtualKeyCode == VK_BACK || (virtualKeyCode == VK_LEFT && keyEvent.ctrlKey())) - m_page->goBack(); - + return m_page->goForward(); + if (virtualKeyCode == VK_BACK || (virtualKeyCode == VK_LEFT && keyEvent.ctrlKey())) + return m_page->goBack(); + // Need to scroll the page if the arrow keys, pgup/dn, or home/end are hit. ScrollDirection direction; ScrollGranularity granularity; @@ -2019,6 +2034,7 @@ LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, case WM_MBUTTONUP: case WM_RBUTTONUP: case WM_MOUSELEAVE: + case WM_CANCELMODE: if (Frame* coreFrame = core(mainFrameImpl)) if (coreFrame->view()->didFirstLayout()) handled = webView->handleMouseEvent(message, wParam, lParam); @@ -4657,6 +4673,11 @@ HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification) return hr; settings->setAllowFileAccessFromFileURLs(!!enabled); + hr = prefsPrivate->javaScriptCanAccessClipboard(&enabled); + if (FAILED(hr)) + return hr; + settings->setJavaScriptCanAccessClipboard(!!enabled); + hr = prefsPrivate->isXSSAuditorEnabled(&enabled); if (FAILED(hr)) return hr; @@ -5616,7 +5637,7 @@ HRESULT STDMETHODCALLTYPE WebView::backingStore( { if (!hBitmap) return E_POINTER; - *hBitmap = reinterpret_cast<OLE_HANDLE>(m_backingStoreBitmap.get()); + *hBitmap = reinterpret_cast<OLE_HANDLE>(m_backingStoreBitmap->handle()); return S_OK; } @@ -6116,6 +6137,14 @@ void WebView::setAcceleratedCompositing(bool accelerated) } } +void releaseBackingStoreCallback(void* info, const void* data, size_t size) +{ + // Release the backing store bitmap previously retained by updateRootLayerContents(). + ASSERT(info); + if (info) + static_cast<RefCountedHBITMAP*>(info)->deref(); +} + void WebView::updateRootLayerContents() { if (!m_backingStoreBitmap || !m_layerRenderer) @@ -6123,13 +6152,12 @@ void WebView::updateRootLayerContents() // Get the backing store into a CGImage BITMAP bitmap; - GetObject(m_backingStoreBitmap.get(), sizeof(bitmap), &bitmap); - int bmSize = bitmap.bmWidthBytes * bitmap.bmHeight; - RetainPtr<CFDataRef> data(AdoptCF, - CFDataCreateWithBytesNoCopy( - 0, static_cast<UInt8*>(bitmap.bmBits), - bmSize, kCFAllocatorNull)); - RetainPtr<CGDataProviderRef> cgData(AdoptCF, CGDataProviderCreateWithCFData(data.get())); + GetObject(m_backingStoreBitmap->handle(), sizeof(bitmap), &bitmap); + size_t bmSize = bitmap.bmWidthBytes * bitmap.bmHeight; + RetainPtr<CGDataProviderRef> cgData(AdoptCF, + CGDataProviderCreateWithData(static_cast<void*>(m_backingStoreBitmap.get()), + bitmap.bmBits, bmSize, + releaseBackingStoreCallback)); RetainPtr<CGColorSpaceRef> space(AdoptCF, CGColorSpaceCreateDeviceRGB()); RetainPtr<CGImageRef> backingStoreImage(AdoptCF, CGImageCreate(bitmap.bmWidth, bitmap.bmHeight, 8, bitmap.bmBitsPixel, @@ -6138,8 +6166,17 @@ void WebView::updateRootLayerContents() cgData.get(), 0, false, kCGRenderingIntentDefault)); + // Retain the backing store bitmap so that it is not deleted by deleteBackingStore() + // while still in use within CA. When CA is done with the bitmap, it will + // call releaseBackingStoreCallback(), which will release the backing store bitmap. + m_backingStoreBitmap->ref(); + // Hand the CGImage to CACF for compositing - m_layerRenderer->setRootContents(backingStoreImage.get()); + if (m_nextDisplayIsSynchronous) { + m_layerRenderer->setRootContentsAndDisplay(backingStoreImage.get()); + m_nextDisplayIsSynchronous = false; + } else + m_layerRenderer->setRootContents(backingStoreImage.get()); // Set the frame and scroll position Frame* coreFrame = core(m_mainFrame); @@ -6295,6 +6332,12 @@ HRESULT WebView::registerURLSchemeAsSecure(BSTR scheme) return S_OK; } +HRESULT WebView::nextDisplayIsSynchronous() +{ + m_nextDisplayIsSynchronous = true; + return S_OK; +} + class EnumTextMatches : public IEnumTextMatches { long m_ref; diff --git a/WebKit/win/WebView.h b/WebKit/win/WebView.h index 48f3ef8..7c10039 100644 --- a/WebKit/win/WebView.h +++ b/WebKit/win/WebView.h @@ -32,12 +32,14 @@ #include "WebPreferences.h" #include <WebCore/DragActions.h> #include <WebCore/IntRect.h> +#include <WebCore/RefCountedGDIHandle.h> #include <WebCore/Timer.h> #include <WebCore/WindowMessageListener.h> #include <WebCore/WKCACFLayer.h> #include <WebCore/WKCACFLayerRenderer.h> #include <wtf/HashSet.h> #include <wtf/OwnPtr.h> +#include <wtf/RefPtr.h> class FullscreenVideoController; class WebBackForwardList; @@ -45,6 +47,9 @@ class WebFrame; class WebInspector; class WebInspectorClient; +typedef WebCore::RefCountedGDIHandle<HBITMAP> RefCountedHBITMAP; +typedef WebCore::RefCountedGDIHandle<HRGN> RefCountedHRGN; + WebView* kit(WebCore::Page*); WebCore::Page* core(IWebView*); @@ -781,6 +786,8 @@ public: virtual HRESULT STDMETHODCALLTYPE setDomainRelaxationForbiddenForURLScheme(BOOL forbidden, BSTR scheme); virtual HRESULT STDMETHODCALLTYPE registerURLSchemeAsSecure(BSTR); + virtual HRESULT STDMETHODCALLTYPE nextDisplayIsSynchronous(); + // WebView bool shouldUseEmbeddedView(const WebCore::String& mimeType) const; @@ -939,9 +946,9 @@ protected: WebFrame* m_mainFrame; WebCore::Page* m_page; - OwnPtr<HBITMAP> m_backingStoreBitmap; + RefPtr<RefCountedHBITMAP> m_backingStoreBitmap; SIZE m_backingStoreSize; - OwnPtr<HRGN> m_backingStoreDirtyRegion; + RefPtr<RefCountedHRGN> m_backingStoreDirtyRegion; COMPtr<IWebEditingDelegate> m_editingDelegate; COMPtr<IWebFrameLoadDelegate> m_frameLoadDelegate; @@ -1015,6 +1022,8 @@ protected: OwnPtr<WebCore::WKCACFLayerRenderer> m_layerRenderer; bool m_isAcceleratedCompositing; #endif + + bool m_nextDisplayIsSynchronous; }; #endif diff --git a/WebKit/wx/ChangeLog b/WebKit/wx/ChangeLog index 6e04904..4f09956 100644 --- a/WebKit/wx/ChangeLog +++ b/WebKit/wx/ChangeLog @@ -1,3 +1,69 @@ +2010-05-03 Kevin Watters <kevinwatters@gmail.com> + + Reviewed by Kevin Ollivier. + + Build and use Mac's ComplexTextController to support complex text in wx. + https://bugs.webkit.org/show_bug.cgi?id=38482 + + * WebView.cpp: + (wxWebView::Create): + * wscript: + +2010-05-03 Kevin Watters <kevinwatters@gmail.com> + + Reviewed by Kevin Ollivier. + + Provide access to GrantUniversalAccess to allow enabling of XSS support. + https://bugs.webkit.org/show_bug.cgi?id=38481 + + * WebFrame.cpp: + (wxWebFrame::GrantUniversalAccess): + * WebFrame.h: + * WebView.cpp: + (wxWebView::GetParseMode): + (wxWebView::GrantUniversalAccess): + * WebView.h: + +2010-05-03 Jens Alfke <snej@chromium.org> + + Reviewed by Darin Fisher. + + [chromium] Add "willSendSubmitEvent" hook to WebFrameClient and FrameLoaderClient + https://bugs.webkit.org/show_bug.cgi?id=38397 + + No tests (functionality is exposed only through native WebKit API.) + + * WebKitSupport/FrameLoaderClientWx.h: + (WebCore::FrameLoaderClientWx::dispatchWillSendSubmitEvent): + +2010-04-25 Sam Weinig <sam@webkit.org> + + Reviewed by Maciej Stachowiak. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38097 + Disentangle initializing the main thread from initializing threading + + * WebView.cpp: + (wxWebView::Create): Add call to initializeMainThread. + +2010-04-25 Kevin Watters <kevinwatters@gmail.com> + + Reviewed by Kevin Ollivier. + + Update focus handling code to match current approaches used by other platforms, + and fix focus handling for corner cases such as when a mouse down pops up a dialog. + + https://bugs.webkit.org/show_bug.cgi?id=38086 + + * WebView.cpp: + (wxWebView::Create): + (wxWebView::OnTLWActivated): + (wxWebView::OnPaint): + (wxWebView::OnMouseEvents): + (wxWebView::OnSetFocus): + (wxWebView::OnKillFocus): + * WebView.h: + 2010-04-20 Adam Barth <abarth@webkit.org> Reviewed by Eric Seidel. diff --git a/WebKit/wx/WebFrame.cpp b/WebKit/wx/WebFrame.cpp index 78427e4..2515de4 100644 --- a/WebKit/wx/WebFrame.cpp +++ b/WebKit/wx/WebFrame.cpp @@ -426,3 +426,9 @@ wxWebKitParseMode wxWebFrame::GetParseMode() const return NoDocument; } + +void wxWebFrame::GrantUniversalAccess() +{ + if (m_impl->frame && m_impl->frame->document()) + m_impl->frame->document()->securityOrigin()->grantUniversalAccess(); +} diff --git a/WebKit/wx/WebFrame.h b/WebKit/wx/WebFrame.h index 95a0691..fec6257 100644 --- a/WebKit/wx/WebFrame.h +++ b/WebKit/wx/WebFrame.h @@ -146,6 +146,8 @@ public: wxWebKitParseMode GetParseMode() const; + void GrantUniversalAccess(); + private: float m_textMagnifier; bool m_isEditable; diff --git a/WebKit/wx/WebKitSupport/FrameLoaderClientWx.h b/WebKit/wx/WebKitSupport/FrameLoaderClientWx.h index e9f566b..95ef2e6 100644 --- a/WebKit/wx/WebKitSupport/FrameLoaderClientWx.h +++ b/WebKit/wx/WebKitSupport/FrameLoaderClientWx.h @@ -113,6 +113,7 @@ namespace WebCore { virtual void dispatchShow(); virtual void cancelPolicyCheck(); + virtual void dispatchWillSendSubmitEvent(HTMLFormElement*) { } virtual void dispatchWillSubmitForm(FramePolicyFunction, PassRefPtr<FormState>); virtual void dispatchDidLoadMainResource(DocumentLoader*); diff --git a/WebKit/wx/WebView.cpp b/WebKit/wx/WebView.cpp index 95730b9..cfa402f 100644 --- a/WebKit/wx/WebView.cpp +++ b/WebKit/wx/WebView.cpp @@ -254,6 +254,13 @@ wxWebViewCachePolicy wxWebView::GetCachePolicy() return gs_cachePolicy; } +#if OS(DARWIN) +// prototype - function is in WebKitSystemInterface.mm +extern "C" { +void InitWebCoreSystemInterface(void); +} +#endif + BEGIN_EVENT_TABLE(wxWebView, wxWindow) EVT_PAINT(wxWebView::OnPaint) EVT_SIZE(wxWebView::OnSize) @@ -295,6 +302,10 @@ wxWebView::wxWebView(wxWindow* parent, int id, const wxPoint& position, bool wxWebView::Create(wxWindow* parent, int id, const wxPoint& position, const wxSize& size, long style, const wxString& name) { +#if OS(DARWIN) + InitWebCoreSystemInterface(); +#endif + if ( (style & wxBORDER_MASK) == 0) style |= wxBORDER_NONE; @@ -302,6 +313,7 @@ bool wxWebView::Create(wxWindow* parent, int id, const wxPoint& position, return false; WTF::initializeThreading(); + WTF::initializeMainThread(); // This is necessary because we are using SharedTimerWin.cpp on Windows, // due to a problem with exceptions getting eaten when using the callback @@ -340,6 +352,9 @@ bool wxWebView::Create(wxWindow* parent, int id, const wxPoint& position, SetDatabasesEnabled(true); #endif + wxWindow* tlw = wxGetTopLevelParent(this); + tlw->Connect(-1, wxEVT_ACTIVATE, wxActivateEventHandler(wxWebView::OnTLWActivated)); + m_isInitialized = true; return true; @@ -359,6 +374,15 @@ wxWebView::~wxWebView() m_impl->page = 0; } +void wxWebView::OnTLWActivated(wxActivateEvent& event) +{ + if (m_impl && m_impl->page && m_impl->page->focusController()) + m_impl->page->focusController()->setActive(event.GetActive()); + + event.Skip(); + +} + void wxWebView::Stop() { if (m_mainFrame) @@ -528,13 +552,6 @@ void wxWebView::OnPaint(wxPaintEvent& event) if (m_beingDestroyed || !m_mainFrame) return; - // WebView active state is based on TLW active state. - wxTopLevelWindow* tlw = dynamic_cast<wxTopLevelWindow*>(wxGetTopLevelParent(this)); - if (tlw && tlw->IsActive()) - m_impl->page->focusController()->setActive(true); - else { - m_impl->page->focusController()->setActive(false); - } WebCore::Frame* frame = m_mainFrame->GetFrame(); if (!frame || !frame->view()) return; @@ -620,6 +637,21 @@ void wxWebView::OnMouseEvents(wxMouseEvent& event) return; } + // If an event, such as a right-click event, leads to a focus change (e.g. it + // raises a dialog), WebKit never gets the mouse up event and never relinquishes + // mouse capture. This leads to WebKit handling mouse events, such as modifying + // the selection, while other controls or top level windows have the focus. + // I'm not sure if this is the right place to handle this, but I can't seem to + // find a precedent on how to handle this in other ports. + if (wxWindow::FindFocus() != this) { + while (HasCapture()) + ReleaseMouse(); + + frame->eventHandler()->setMousePressed(false); + + return; + } + int clickCount = event.ButtonDClick() ? 2 : 1; if (clickCount == 1 && m_impl->tripleClickTimer.IsRunning()) { @@ -882,26 +914,35 @@ void wxWebView::OnKeyEvents(wxKeyEvent& event) void wxWebView::OnSetFocus(wxFocusEvent& event) { - WebCore::Frame* frame = 0; - if (m_mainFrame) - frame = m_mainFrame->GetFrame(); - - if (frame) { - frame->selection()->setFocused(true); - } + if (m_impl && m_impl->page && m_impl->page->focusController()) { + m_impl->page->focusController()->setFocused(true); + m_impl->page->focusController()->setActive(true); + if (!m_impl->page->focusController()->focusedFrame() && m_mainFrame) + m_impl->page->focusController()->setFocusedFrame(m_mainFrame->GetFrame()); + } + event.Skip(); } void wxWebView::OnKillFocus(wxFocusEvent& event) { - WebCore::Frame* frame = 0; - if (m_mainFrame) - frame = m_mainFrame->GetFrame(); - - if (frame) { - frame->selection()->setFocused(false); + if (m_impl && m_impl->page && m_impl->page->focusController()) { + m_impl->page->focusController()->setFocused(false); + + // We also handle active state in OnTLWActivated, but if a user does not + // call event.Skip() in their own EVT_ACTIVATE handler, we won't get those + // callbacks. So we handle active state here as well as a fallback. + wxTopLevelWindow* tlw = dynamic_cast<wxTopLevelWindow*>(wxGetTopLevelParent(this)); + if (tlw && tlw->IsActive()) + m_impl->page->focusController()->setActive(true); + else + m_impl->page->focusController()->setActive(false); } + + while (HasCapture()) + ReleaseMouse(); + event.Skip(); } @@ -997,4 +1038,10 @@ wxWebKitParseMode wxWebView::GetParseMode() const return m_mainFrame->GetParseMode(); return NoDocument; -}
\ No newline at end of file +} + +void wxWebView::GrantUniversalAccess() +{ + if (m_mainFrame) + m_mainFrame->GrantUniversalAccess(); +} diff --git a/WebKit/wx/WebView.h b/WebKit/wx/WebView.h index f7b41dc..075deaf 100644 --- a/WebKit/wx/WebView.h +++ b/WebKit/wx/WebView.h @@ -214,6 +214,12 @@ public: wxWebSettings GetWebSettings(); wxWebKitParseMode GetParseMode() const; + + /* + This method allows cross site-scripting (XSS) in the WebView. + Use with caution! + */ + void GrantUniversalAccess(); protected: @@ -226,6 +232,7 @@ protected: void OnKeyEvents(wxKeyEvent& event); void OnSetFocus(wxFocusEvent& event); void OnKillFocus(wxFocusEvent& event); + void OnTLWActivated(wxActivateEvent& event); private: // any class wishing to process wxWindows events must use this macro diff --git a/WebKit/wx/wscript b/WebKit/wx/wscript index b5ba580..61fa903 100644 --- a/WebKit/wx/wscript +++ b/WebKit/wx/wscript @@ -81,6 +81,13 @@ def pre_build(bld): bld.env.CXXDEPS_WEBCORE = Utils.h_file(libwebcore) def build(bld): + + import TaskGen + + if sys.platform.startswith('darwin'): + TaskGen.task_gen.mappings['.mm'] = TaskGen.task_gen.mappings['.cxx'] + TaskGen.task_gen.mappings['.m'] = TaskGen.task_gen.mappings['.cxx'] + bld.add_pre_fun(pre_build) bld.env.LIBDIR = output_dir @@ -95,6 +102,11 @@ def build(bld): uselib_local = '', install_path = output_dir) + exts = ['.c', '.cpp'] + if sys.platform.startswith('darwin'): + exts.append('.mm') + obj.includes += '../mac/WebCoreSupport ../../WebCore/platform/mac' + obj.source = "../mac/WebCoreSupport/WebSystemInterface.m" obj.find_sources_in_dirs(webkit_dirs) if building_on_win32: diff --git a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg index cd5e4e1..151225f 100644 --- a/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg +++ b/WebKitTools/BuildSlaveSupport/build.webkit.org-config/master.cfg @@ -239,10 +239,24 @@ class RunWebKitTests(shell.Test): class NewRunWebKitTests(RunWebKitTests): command = ["./WebKitTools/Scripts/new-run-webkit-tests", "--noshow-results", - "--results-directory", "layout-test-results", + "--verbose", "--results-directory", "layout-test-results", WithProperties("--%(configuration)s")] +class RunPythonTests(shell.Test): + name = "webkitpy-test" + description = ["python-tests running"] + descriptionDone = ["python-tests"] + command = ["python", "./WebKitTools/Scripts/test-webkitpy"] + + +class RunPerlTests(shell.Test): + name = "webkitperl-test" + description = ["perl-tests running"] + descriptionDone = ["perl-tests"] + command = ["perl", "./WebKitTools/Scripts/test-webkitperl"] + + class RunGtkAPITests(shell.Test): name = "API tests" description = ["API tests running"] @@ -348,6 +362,11 @@ class TestFactory(Factory): self.addStep(ExtractBuiltProduct) self.addStep(RunJavaScriptCoreTests, skipBuild=True) self.addStep(RunWebKitTests, skipBuild=(platform == 'win')) + # Tiger's Python 2.3 is too old. WebKit Python requires 2.5+. + # Sadly we have no way to detect the version on the slave from here. + if platform != "mac-tiger": + self.addStep(RunPythonTests) + self.addStep(RunPerlTests) self.addStep(ArchiveTestResults) self.addStep(UploadTestResults) self.addStep(ExtractTestResults) @@ -359,6 +378,11 @@ class BuildAndTestFactory(Factory): self.addStep(CompileWebKit) self.addStep(RunJavaScriptCoreTests) self.addStep(self.TestClass) + # Tiger's Python 2.3 is too old. WebKit Python requires 2.5+. + # Sadly we have no way to detect the version on the slave from here. + if platform != "mac-tiger": + self.addStep(RunPythonTests) + self.addStep(RunPerlTests) self.addStep(ArchiveTestResults) self.addStep(UploadTestResults) self.addStep(ExtractTestResults) @@ -373,8 +397,8 @@ class NewBuildAndTestFactory(BuildAndTestFactory): def loadBuilderConfig(c): + # FIXME: These file handles are leaked. passwords = simplejson.load(open('passwords.json')) - config = simplejson.load(open('config.json')) # use webkitpy's buildbot module to test for core builders diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog index a03ae52..70b10f0 100644 --- a/WebKitTools/ChangeLog +++ b/WebKitTools/ChangeLog @@ -1,3 +1,2420 @@ +2010-05-07 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Daniel Bates. + + Refactored VCSUtils.pm's parse-related methods to leave inapplicable + hash values unset instead of setting them to "undef". + + https://bugs.webkit.org/show_bug.cgi?id=38724 + + Preferring "not set" over "undef" keeps the unit tests smaller and + easier to maintain. Otherwise, we would have to update every unit + test case each time we add support for a new key-value pair -- + instead of just the relevant ones. + + * Scripts/VCSUtils.pm: + - In parseGitDiffHeader(), adjusted the handling of these key-values: + executableBitDelta and isBinary. + - In parseSvnDiffHeader(), adjusted the handling of these key-values: + copiedFromPath, isBinary, and sourceRevision. + - In parseDiffHeader(), adjusted the handling of these key-values: + isGit and isSvn. + - In parseDiff(), adjusted the handling of these key-values: + isBinary, isGit, isSvn, and sourceRevision. + + * Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl: + - Updated the unit tests as necessary. + + * Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl: + - Updated the unit tests as necessary. + + * Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl: + - Updated the unit tests as necessary. + + * Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl: + - Updated the unit tests as necessary. + +2010-05-06 Mark Rowe <mrowe@apple.com> + + Rubber-stamped by Dan Bernstein. + + Exclude leaks due to <rdar://problem/7815391> from the output. + + * Scripts/old-run-webkit-tests: + +2010-05-06 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r58933. + http://trac.webkit.org/changeset/58933 + https://bugs.webkit.org/show_bug.cgi?id=38717 + + "Broke all websocket tests on Tiger" (Requested by eseidel on + #webkit). + + * Scripts/new-run-webkit-websocketserver: + * Scripts/old-run-webkit-tests: + * Scripts/run-webkit-websocketserver: + * Scripts/webkitpy/layout_tests/port/websocket_server.py: + * Scripts/webkitpy/thirdparty/__init__.py: + * Scripts/webkitpy/thirdparty/pywebsocket/COPYING: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/MANIFEST.in: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/README: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/README.webkit: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/example/echo_client.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/example/echo_wsh.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/example/handler_map.txt: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/__init__.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/dispatch.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/handshake.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/headerparserhandler.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/memorizingfile.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/msgutil.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/standalone.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/mod_pywebsocket/util.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/setup.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/config.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/mock.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/run_all.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/test_dispatch.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/test_handshake.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/test_memorizingfile.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/test_mock.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/test_msgutil.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/test_util.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/README: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/blank_wsh.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/origin_check_wsh.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/exception_in_transfer_wsh.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/no_wsh_at_the_end.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/non_callable_wsh.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/plain_wsh.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/wrong_handshake_sig_wsh.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/handlers/sub/wrong_transfer_sig_wsh.py: Added. + * Scripts/webkitpy/thirdparty/pywebsocket/test/testdata/hello.pl: Added. + +2010-05-06 Fumitoshi Ukai <ukai@chromium.org> + + Reviewed by David Levin. + + WebSocket: pywebsocket 0.5 + https://bugs.webkit.org/show_bug.cgi?id=38034 + + Remove pywebsocket from webkitpy/thirdparty. + Make pywebsocket autoinstalled. + + * Scripts/new-run-webkit-websocketserver: + Add --output-dir option. + * Scripts/old-run-webkit-tests: + Use new-run-webkit-websocketserver, rather than directly run pywebsocket's standalone.py + * Scripts/run-webkit-websocketserver: + Ditto. + * Scripts/webkitpy/layout_tests/port/websocket_server.py: + Use autoinstalled pywebsocket. + * Scripts/webkitpy/thirdparty/__init__.py: + Autoinstall pywebsocket + * Scripts/webkitpy/thirdparty/pywebsocket: Removed. + +2010-05-06 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Daniel Bates. + + svn-apply now understands the Git diff "copy from" syntax when the + similarity index is 100%. + + https://bugs.webkit.org/show_bug.cgi?id=38628 + + * Scripts/VCSUtils.pm: + - Adjusted parseGitDiffHeader() to parse the "copy from" and + "similarity index" lines. + + * Scripts/svn-unapply: + - Adjusted the patch() subroutine so that copies are recognized + as file additions. + + * Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl: + - Added unit tests for the cases of a copy with similarity index + 100% and less than 100%. + +2010-05-06 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Daniel Bates. + + Removed the need for svn-apply and -unapply to re-parse whether + a diff is binary or not. + + https://bugs.webkit.org/show_bug.cgi?id=38320 + + * Scripts/VCSUtils.pm: + - Adjusted parseGitDiffHeader() to set the isBinary key. + - Adjusted parseSvnDiffHeader() to set the isBinary key. + - Adjusted parseDiffHeader() to set the isBinary key. + - Changed the scmFormat key set by parseDiffHeader() to + isGit and isSvn keys. + - Adjusted parseDiff() to set the isBinary, isGit, and isSvn keys. + + * Scripts/svn-apply: + - Updated the patch() method to use the isBinary, isGit, and + isSvn keys. + + * Scripts/svn-unapply: + - Updated the patch() method to use the isBinary and isSvn keys. + + * Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl: + - Updated the unit tests as necessary. + - Added a test case to test that the isBinary key is getting set properly. + + * Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl: + - Updated the unit tests as necessary. + + * Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl: + - Updated the unit tests as necessary. + + * Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl: + - Updated the unit tests as necessary. + +2010-05-06 Kent Tamura <tkent@chromium.org> + + Reviewed by Dimitri Glazkov. + + [DRT/Chromium] Add support for resources on Mac + https://bugs.webkit.org/show_bug.cgi?id=38637 + + Repack webkit_chromium_resources.pak, webkit_strings_en-US.pak, + and webkit_resources.pak, and put them as Mac bundle resource. + The 'actions' section is almost same as a part of test_shell.gypi. + + * DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp: + +2010-05-06 Csaba Osztrogonác <ossy@webkit.org> + + [Qt] Unreviewed buildfix after r58917. + + * DumpRenderTree/qt/LayoutTestControllerQt.h: Missing function declaration added. + +2010-05-06 Anders Carlsson <andersca@apple.com> + + Reviewed by Darin Adler and Dan Bernstein.. + + REGRESSION (r51617): when plugins are disabled, plugins show up as garbage characters + https://bugs.webkit.org/show_bug.cgi?id=38698 + <rdar://problem/7942075> + + Add a 'setPluginsEnabled' layoutTestController function for disabling plug-ins. This is only implemented on Mac currently + because the bug that needs this functionality is mac specific. + + * DumpRenderTree/LayoutTestController.cpp: + (setPluginsEnabledCallback): + (LayoutTestController::staticFunctions): + * DumpRenderTree/LayoutTestController.h: + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + (LayoutTestController::setPluginsEnabled): + * DumpRenderTree/mac/DumpRenderTree.mm: + (resetDefaultsToConsistentValues): + * DumpRenderTree/mac/LayoutTestControllerMac.mm: + (LayoutTestController::setPluginsEnabled): + * DumpRenderTree/qt/LayoutTestControllerQt.cpp: + (LayoutTestController::setPluginsEnabled): + * DumpRenderTree/win/LayoutTestControllerWin.cpp: + (LayoutTestController::setPluginsEnabled): + * DumpRenderTree/wx/LayoutTestControllerWx.cpp: + (LayoutTestController::setPluginsEnabled): + +2010-05-06 Jochen Eisinger <jochen@chromium.org> + + Reviewed by Dimitri Glazkov. + + Make ImageDiff depend on WebKit. When compiled from within Chromium, WTF is not a standalone dynamic library but depends on WebKit. + https://bugs.webkit.org/show_bug.cgi?id=38632 + + * DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp: + +2010-05-06 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Replace public inspector url with private property for QtLauncher + https://bugs.webkit.org/show_bug.cgi?id=35340 + + Replace the public API with a private dynamic property until this feature + is ready. + + * QtLauncher/main.cpp: + (LauncherWindow::init): + +2010-05-05 Joseph Pecoraro <joepeck@webkit.org> + + Reviewed by Pavel Feldman. + + Web Inspector: build-webkit --inspector-frontend Should Exclude *.re2js + https://bugs.webkit.org/show_bug.cgi?id=38449 + + * Scripts/webkitdirs.pm: + +2010-05-05 Charles Wei <charles.wei@torchmobile.com.cn> + + Reviewed by George Staikos + + This patch adds WCSS -wap-input-format and -wap-input-required support to WebKit + Make the test cases in fast/wcss optionional only when WCSS is enabled. + + https://bugs.webkit.org/show_bug.cgi?id=37848 + + * Scripts/old-run-webkit-tests: + * Scripts/webkitperl/features.pm: + +2010-05-05 Kent Tamura <tkent@chromium.org> + + Reviewed by Eric Seidel. + + [DRT/Chromium] Remove InitWebCoreSystemInterface() call + https://bugs.webkit.org/show_bug.cgi?id=38624 + + Chromium r45167 <http://src.chromium.org/viewvc/chrome?view=rev&revision=45167> + added InitWebCoreSystemInterface() to webkit/support/platform_support_mac.mm. + So we don't need to call it from DumpRenderTree.cpp anymore. + + * DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp: + * DumpRenderTree/chromium/DumpRenderTree.cpp: + (main): Remove InitWebCoreSystemInterface(). + +2010-05-05 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Eric Seidel. + + new-run-webkit-tests: clean up newline handling in printing + + The new printing module seems to handle newlines somewhat + inconsistently, especially in --verbose mode. This change cleans up + the code to make things more consistent and adds a bunch of unit tests. + + https://bugs.webkit.org/show_bug.cgi?id=38616 + + * Scripts/webkitpy/common/array_stream.py: Added. + * Scripts/webkitpy/common/array_stream_unittest.py: Added. + * Scripts/webkitpy/layout_tests/layout_package/metered_stream.py: + * Scripts/webkitpy/layout_tests/layout_package/metered_stream_unittest.py: Added. + * Scripts/webkitpy/layout_tests/layout_package/printing.py: + * Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py: + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py: + +2010-05-05 James Robinson <jamesr@chromium.org> + + Reviewed by Adam Barth. + + Ban the single letter 'l' as an identifier name + http://trac.webkit.org/changeset/58844 + + Add a lint rule to ban the single letter 'l' as an identifier name + since it is very easy to confuse with the numeral '1', especially + in code like WebCore/css/CSSHelper.cpp. + + See http://trac.webkit.org/changeset/58844 as an example of a bug + caused by confusing short variable names. + + * Scripts/webkitpy/style/checkers/cpp.py: + * Scripts/webkitpy/style/checkers/cpp_unittest.py: + +2010-05-04 Eric Seidel <eric@webkit.org> + + Reviewed by Shinichiro Hamaji. + + PrettyPatch.pretty_diff("") should not hang + https://bugs.webkit.org/show_bug.cgi?id=38552 + + Also found a bug in PrettyPatch.pretty_diff where it would + hang when passed "" as input. + + I suspect there may be bugs in prettify.rb (or our use there-of) + where it can hang, which would then cause the testing thread to hang. + + * Scripts/webkitpy/common/prettypatch.py: + - Don't hang when passed "" + * Scripts/webkitpy/common/prettypatch_unittest.py: + - Test that we don't hang when passed "" + * Scripts/webkitpy/layout_tests/port/base.py: + - Add a FIXME that we should share code with prettypatch.rb + +2010-05-04 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Eric Seidel. + + new-run-webkit-tests: turn off threading on the Chromium Mac port until + we can stabilize the port more and figure out why it is hanging so + frequently. + + https://bugs.webkit.org/show_bug.cgi?id=38553 + + * Scripts/webkitpy/layout_tests/port/chromium_mac.py: + - override default_child_processes() and log a warning + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + - fix a typo that caused us to print a method object instead of the + value the method object returns in the case where there is only + one child process. + * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py: + - Add unit tests for the output of run_webkit_tests - in this case, + the handling of --child-processes and --print config + +2010-05-04 Timothy Hatcher <timothy@apple.com> + + Fix the find command in extract-localizable-strings so skip + directories are correctly skipped and header files are searched. + + https://bugs.webkit.org/show_bug.cgi?id=38545 + rdar://problem/7941295 + + Reviewed by Darin Adler. + + * Scripts/extract-localizable-strings: Append -o after each -prune + so -and isn't implied. Surround all the -name arguments so they get + an implied -print action. Removed check for "icu". Skip any header that + ends in LocalizableStrings.h, so SafariLocalizableStrings.h is skipped. + * Scripts/update-webkit-localizable-strings: Add the two icu directories + to the skip list. + +2010-05-04 Jesus Sanchez-Palencia <jesus@webkit.org> + + Reviewed by Eric Seidel. + + Wrong documentation on 'webkit-patch help land'. + https://bugs.webkit.org/show_bug.cgi?id=37871 + + Small fix on the help documentation for webkit-patch + land. + + * Scripts/webkitpy/tool/commands/download.py: + +2010-05-04 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] QWebPage viewMode property + https://bugs.webkit.org/show_bug.cgi?id=38119 + + Rename the property from wrt_viewMode to _q_viewMode. + + * DumpRenderTree/qt/LayoutTestControllerQt.cpp: + (LayoutTestController::setViewModeMediaFeature): + +2010-05-04 Jochen Eisinger <jochen@chromium.org> + + Reviewed by Jeremy Orlow. + + Fix typo in run_webkit_tests.py: s/_print\./_printer./ + https://bugs.webkit.org/show_bug.cgi?id=38515 + + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + +2010-05-04 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Eric Seidel. + + This revision completes the terminology change from "processor" to + "checker" for the CarriageReturnProcessor, CppProcessor, + PythonProcessor, and TextProcessor classes, etc. + + https://bugs.webkit.org/show_bug.cgi?id=38262 + + The word "processor" currently has two uses in our code. This + revision renames the lower-level use to "checker" and preserves the + word "processor" for higher-level, more general uses. This + revision also makes whatever other name changes that logically + followed from this change. + + * Scripts/check-webkit-style: + - Updated references to PatchChecker. + + * Scripts/webkitpy/style/checker.py: + - Renamed the StyleCheckerConfiguration class to + StyleProcessorConfiguration. + - Renamed the ProcessorDispatcher class to CheckerDispatcher, and + made similar changes for the class's method names. + - Renamed the PatchChecker class to PatchReader. + - Updated the file as necessary to accommodate the other class + renames in this patch. + + * Scripts/webkitpy/style/checker_unittest.py: + - Updated the unit test code as necessary. + + * Scripts/webkitpy/style/checkers/common.py: + - Renamed the CarriageReturnProcessor class to CarriageReturnChecker, + and changed its process() method to check(). + + * Scripts/webkitpy/style/checkers/common_unittest.py: + - Updated the unit test code as necessary. + + * Scripts/webkitpy/style/checkers/cpp.py: + - Renamed the CppProcessor class to CppChecker, and renamed its + process() method to check(). + + * Scripts/webkitpy/style/checkers/cpp_unittest.py: + - Updated the unit test code as necessary. + + * Scripts/webkitpy/style/checkers/python.py: + - Renamed the PythonProcessor class to PythonChecker, and renamed + its process() method to check(). + + * Scripts/webkitpy/style/checkers/python_unittest.py: + - Updated the unit test code as necessary. + + * Scripts/webkitpy/style/checkers/text.py: + - Renamed the TextProcessor class to TextChecker, and renamed + its process() method to check(). + + * Scripts/webkitpy/style/checkers/text_unittest.py: + - Updated the unit test code as necessary. + + * Scripts/webkitpy/style/error_handlers.py: + - Updated the code as necessary. + + * Scripts/webkitpy/style/error_handlers_unittest.py: + - Updated the unit test code as necessary. + +2010-05-04 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Eric Seidel. + + Adjusted svn-apply and -unapply to accept git diffs generated + using the --no-prefix flag. + + https://bugs.webkit.org/show_bug.cgi?id=32438 + + * Scripts/VCSUtils.pm: + - Loosened the regular expression for the "diff --git" line to + match when the --no-prefix flag is used with "git diff". + - Also refactored the code parsing the first line so that the + script exits with an error message if the first line cannot + be parsed. + * Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl: + - Added a unit test case for the --no-prefix case. + +2010-05-04 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Daniel Bates. + + Changed VCSUtils.pm's parseDiffHeader() to call the new + parseGitDiffHeader() method. + + https://bugs.webkit.org/show_bug.cgi?id=38454 + + This revision makes more progress towards adding executable-bit + support to svn-apply and svn-unapply. It also makes more progress + towards refactoring the code into a more maintainable form. + + * Scripts/VCSUtils.pm: + - Removed gitdiff2svndiff(). + - Removed the Git-specific logic from parseDiffHeader() and + renamed it parseSvnDiffHeader(). + - Added a new parseDiffHeader() subroutine which calls + parseSvnDiffHeader() or parseGitDiffHeader() depending on + the format of the first header line. + + * Scripts/webkitperl/VCSUtils_unittest/gitdiff2svndiff.pl: Removed. + * Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl: + - Removed most of the test cases since these cases are now + covered by the unit tests for parseSvnDiffHeader() and + parseGitDiffHeader(). + + * Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl: Added. + - Copied the SVN unit tests from parseDiffHeader.pl and updated + them as necessary. + +2010-05-03 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Builders should run the perl and python unit tests on every commit + https://bugs.webkit.org/show_bug.cgi?id=37976 + + The unit tests take a few seconds to run, so they should not + have any noticable effect on builder speed. + + We're running the tests everywhere but Tiger as Tiger's + Python version is ancient. + I would have rather have detected the python version of the + slave but I couldn't find any API to do that, and I didn't want + to hack version detection into test-webkitpy (at least not yet). + + * BuildSlaveSupport/build.webkit.org-config/master.cfg: + +2010-05-03 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Adam Barth. + + Fixed a recent REGRESSION that caused svn-apply and -unapply to + skip over changes to the first file in a diff if leading junk was + present (like in an e-mail diff) and if the --force option was used. + + https://bugs.webkit.org/show_bug.cgi?id=38507 + + * Scripts/svn-apply: + - Removed the bit of code at the beginning of the patch() + subroutine that checks for the "Index:" line at the beginning + of a file diff (since the parsePatch() subroutine already + checks this). + + * Scripts/svn-unapply: + - Removed the bit of code at the beginning of the patch() + subroutine that checks for the "Index:" line at the beginning + of a file diff (since the parsePatch() subroutine already + checks this). + +2010-05-03 Chris Jerdonek <cjerdonek@webkit.org> + + Unreviewed. + + Adjusted the ChangeLog entry below for r58732 (bug 35804) to reflect + the fact that the change will not become active until the patch + for bug 38454 lands. + +2010-05-03 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Eric Seidel. + + Added code for svn-apply and -unapply to display an instructive error + message if the --binary flag is left off the "git diff" command + for diffs containing binary file differences. + + https://bugs.webkit.org/show_bug.cgi?id=35804 + + This change will become active when parseDiffHeader() is modified + to call parseGitDiffHeader (see bug 38454). + + * Scripts/VCSUtils.pm: + - Adjusted parseDiffHeader() to exit with an appropriate error message + if it encounters a line of the form "Binary files <path1> and + <path2> differ". + +2010-05-03 Dirk Pranke <dpranke@chromium.org> + + Unreviewed, build fix. + + new-run-webkit-tests: r58728 broke the buildbot logic for parsing the + output of the log; specifying --verbose should basically be equivalent + to --print everything, but instead it was equivalent to not specifying + --print and getting the default set. Now, --verbose acts as if + --print everything was implicitly specified as the default (you can + still override it if you specify both; this is a somewhat debatable + call). + + https://bugs.webkit.org/show_bug.cgi?id=38504 + + * Scripts/webkitpy/layout_tests/layout_package/printing.py: + +2010-05-03 Dirk Pranke <dpranke@chromium.org> + + Unreviewed, build fix. + + new-run-webkit-tests: Fix minor precedence bug introduced in r58728 where we printed + "-\n" 78 times instead of "-" 78 times followed by a single "\n". + + * Scripts/webkitpy/layout_tests/layout_package/printing.py: + +2010-05-03 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Eric Seidel. + + new-run-webkit-tests: refactor a large chunk of the printing/logging + code out of run-webkit-tests py (almost 300 lines out of 1900). + + This change also renames --log to --print (to be slightly more + descriptive). I've also added better help messages for printing. + + The new code has unit tests! + + There is still more code to be moved, but this patch is big enough as + it is. Namely, still to move are the printing of the actual results + and the timing statistics, which should move another 300-400 lines + out of the file. + + Notable changes to run_webkit_tests.py beyond code simply moving: + * MeteredStream is now hidden under the new printing.Printer class. + All the references to self._meter now point to self._printer. + * All logging configuration is done in printing.configure_logging() + * Instead of using write() lambdas to control what is and isn't + printed, we use separate methods on the printer object. This will + make it easier to grep which print statements are printed + under protection of each flag. + * The print_results flag I added a few revs back to suppress printing + in the unit tests has been replaced with --print nothing. + * The ResultSummary class now stores the entire TestResult for each + test, not just the actual result type. + * summarize_unexpected_results() got moved from a method on TestRunner + to a standalone function. This should move into a separate file + along with the ResultSummary class and the TestResult class + * The --trace option added recently has been replaced by + '--print trace-everything' and '--print trace-unexpected' + + https://bugs.webkit.org/show_bug.cgi?id=38018 + + * Scripts/new-run-webkit-tests: + - update to new entry points in run_webkit_tests.py + * Scripts/webkitpy/layout_tests/layout_package/metered_stream.py: + - fix a minor nit where we were printing an empty string where + we didn't need to + * Scripts/webkitpy/layout_tests/layout_package/printing.py: Added. + * Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py: Added + * Scripts/webkitpy/layout_tests/port/test.py: + - implement relative_test_filename() and expected_filename() so + we can test printing unexpected results in a platform-neutral + way + * Scripts/webkitpy/run_webkit_test.py: + - move a lot of the printing code into printing.py + - change the signatures of the exported entry points for easier + unit testing + * Scripts/webkitpy/run_webkit_tests_unittest.py: + - update w/ changes to run_webkit_tests entry points. + +2010-05-03 Kevin Watters <kevinwatters@gmail.com> + + Reviewed by Kevin Ollivier. + + [wx] Build and use Mac's ComplexTextController to support complex text in wx. + https://bugs.webkit.org/show_bug.cgi?id=38482 + + * wx/build/settings.py: + +2010-05-03 Abhishek Arya <inferno@chromium.org> + + Reviewed by Adam Barth. + + Add support for controlling clipboard access from javascript. + Clipboard access from javascript is enabled in test framework. + https://bugs.webkit.org/show_bug.cgi?id=27751 + + * DumpRenderTree/LayoutTestController.cpp: + (setJavaScriptCanAccessClipboardCallback): + (LayoutTestController::staticFunctions): + * DumpRenderTree/LayoutTestController.h: + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::LayoutTestController): + (LayoutTestController::setJavaScriptCanAccessClipboard): + (LayoutTestController::overridePreference): + * DumpRenderTree/chromium/LayoutTestController.h: + * DumpRenderTree/chromium/TestShell.cpp: + (TestShell::resetWebSettings): + * DumpRenderTree/gtk/DumpRenderTree.cpp: + (resetDefaultsToConsistentValues): + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + (LayoutTestController::setJavaScriptCanAccessClipboard): + * DumpRenderTree/mac/DumpRenderTree.mm: + (resetDefaultsToConsistentValues): + * DumpRenderTree/mac/LayoutTestControllerMac.mm: + (LayoutTestController::setJavaScriptCanAccessClipboard): + * DumpRenderTree/qt/DumpRenderTreeQt.cpp: + (WebCore::WebPage::WebPage): + (WebCore::WebPage::resetSettings): + * DumpRenderTree/qt/LayoutTestControllerQt.cpp: + (LayoutTestController::setJavaScriptCanAccessClipboard): + * DumpRenderTree/qt/LayoutTestControllerQt.h: + * DumpRenderTree/win/DumpRenderTree.cpp: + (resetDefaultsToConsistentValues): + * DumpRenderTree/win/LayoutTestControllerWin.cpp: + (LayoutTestController::setJavaScriptCanAccessClipboard): + * DumpRenderTree/wx/LayoutTestControllerWx.cpp: + (LayoutTestController::setJavaScriptCanAccessClipboard): + +2010-05-03 Anders Carlsson <andersca@apple.com> + + Reviewed by Adam Roben. + + Maui MiniBrowser: Add an option to show/hide the web view + https://bugs.webkit.org/show_bug.cgi?id=38486 + + * MiniBrowser/win/BrowserWindow.cpp: + (BrowserWindow::createWindow): + Set the background brush to something other than null. + + (BrowserWindow::onCommand): + Show and hide the web view accordingly. + + * MiniBrowser/win/MiniBrowser.rc: + * MiniBrowser/win/resource.h: + Add new menu item. + +2010-05-03 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Daniel Bates. + + Added a parseGitDiffHeader() subroutine to VCSUtils.pm that + parses any changes to the executable bit in a Git diff. + + https://bugs.webkit.org/show_bug.cgi?id=38425 + + This revision is more preparation towards adding "executable bit" + support to svn-apply and svn-unapply. No code is going "live" in + this change except for the new unit tests in test-webkitperl. + + * Scripts/VCSUtils.pm: + - Added isExecutable() to determine whether a file mode has the + executable bit set or not. + - Added parseGitDiffHeader() to parse the header of a Git diff. + + * Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl: Added. + - Added unit tests for parseGitDiffHeader(). + +2010-05-03 Daniel Bates <dbates@rim.com> + + Reviewed by Chris Jerdonek. + + https://bugs.webkit.org/show_bug.cgi?id=38447 + + Refactor the unit tests in VCSUtils_unittest/parseDiff.pl to use + Test::More::is_deeply like we do in VCSUtils_unittest/parseDiffHeader.pl. + + * Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl: + +2010-05-02 Chris Jerdonek <cjerdonek@webkit.org> + + Unreviewed. + + Corrected a file path in the ChangeLog entry for r58663 (bug 38319) below. + +2010-05-02 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Eric Seidel. + + https://bugs.webkit.org/show_bug.cgi?id=38319 + + * Scripts/VCSUtils.pm: + - In parseDiffHeader()-- + - Added an "scmFormat" hash key to the return value to represent + whether the diff is Git or SVN formatted. + - Adjusted the code so the value of "copiedFromPath" will + be undef rather than "does not exist" if the file was not + copied. + + * Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl: + - Added a FIXME to refactor these unit tests to use is_deeply(). + + * Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl: + - Updated the unit tests to test the "scmFormat" value. + - Simplified the unit tests by refactoring them to use is_deeply(). + +2010-05-01 Daniel Bates <dbates@rim.com> + + Reviewed by Chris Jerdonek. + + https://bugs.webkit.org/show_bug.cgi?id=38423 + + Adds infrastructure to change the file mode of a file using + the appropriate SCM-specific routines. + + No functionality was changed, so no new tests. + + * Scripts/VCSUtils.pm: Added subroutines scmToggleExecutableBit, + scmAddExecutableBit, and scmRemoveExecutableBit. + * Scripts/svn-apply: Check for the hash key executableBitDelta + and toggle the executable bit. + * Scripts/svn-unapply: Ditto. + +2010-04-30 Chris Marrin <cmarrin@apple.com> + + Reviewed by Simon Fraser. + + Enabled accelerated compositing in DRT for Windows + https://bugs.webkit.org/show_bug.cgi?id=38404 + + * DumpRenderTree/win/DumpRenderTree.cpp: + (main): + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Try to fix GTK+ build. + + * DumpRenderTree/unix/TestNetscapePlugin/TestNetscapePlugin.cpp: + (webkit_test_plugin_new_stream): + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Fix build. + + * DumpRenderTree/unix/TestNetscapePlugin/TestNetscapePlugin.cpp: + +2010-04-30 Anders Carlsson <andersca@apple.com> + + Reviewed by Timothy Hatcher. + + Next step towards fixing + + https://bugs.webkit.org/show_bug.cgi?id=20784 + move npapi.h to C99 integer types + + Use the C99 types everywhere. The "old" types are still around but will be removed + in a subsequent commit. + + * DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp: + (int32VariantToIdentifier): + (doubleVariantToIdentifier): + (testIdentifierToInt): + (testGetIntIdentifier): + * DumpRenderTree/TestNetscapePlugIn.subproj/main.cpp: + (NPP_New): + (NPP_NewStream): + (NPP_WriteReady): + (NPP_Write): + (NPP_HandleEvent): + * DumpRenderTree/win/TestNetscapePlugin/main.cpp: + (NPP_New): + (NPP_NewStream): + (NPP_WriteReady): + (NPP_Write): + (NPP_HandleEvent): + +2010-04-30 Steve Block <steveblock@google.com> + + Reviewed by Jeremy Orlow. + + Changed Steve Block from committer to reviewer. + + * Scripts/webkitpy/common/config/committers.py: + +2010-04-28 Ojan Vafai <ojan@chromium.org> + + Reviewed by Eric Seidel. + + webkit-patch doesn't work if a git repo is tracking multiple svn repos + https://bugs.webkit.org/show_bug.cgi?id=38290 + + Getting the tests to pass required getting our SVN repo to more closely + match the real svn.webkit.org repo by having a trunk directory. + That involved adding an extra commit at the beginning and thus changing + all the commit numbers in the tests. + + * Scripts/webkitpy/common/checkout/scm.py: + +2010-04-29 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + new-run-webkit-tests can deadlock with Chromium's TestShell + https://bugs.webkit.org/show_bug.cgi?id=38298 + + Fix _write_command_and_read_line to never send unicode() to + test_shell, instead to always encode as utf-8. This was causing + random hangs because if test_shell ever encounters a \0 in the + stream it can deadlock with NRWT. + + There is still a deadlock bug to fix in NRWT/test_shell design, however + this fix should make the deadlock occur less often. + + * Scripts/webkitpy/layout_tests/port/chromium.py: + * Scripts/webkitpy/layout_tests/port/chromium_unittest.py: + +2010-04-29 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Eric Seidel. + + Refactored svn-apply and svn-unapply to use the new + parsePatch() subroutine. + + https://bugs.webkit.org/show_bug.cgi?id=34033 + + * Scripts/VCSUtils.pm: + - Consolidated %diffHash documentation. + - Added prepareParsedPatch(). + + * Scripts/svn-apply: + - Replaced main while loop with calls to parsePatch() and + prepareParsedPatch(). + + * Scripts/svn-unapply: + - Replaced main while loop with calls to parsePatch() and + prepareParsedPatch(). + + * Scripts/test-webkitperl: + - Changed to render relative test paths rather than absolute + test paths. + + * Scripts/webkitperl/VCSUtils_unittest/prepareParsedPatch.pl: Added. + - Added unit tests for prepareParsedPatch(). + +2010-04-28 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Eric Seidel. + + Added to VCSUtils's parseDiffHeader() support for binary patches. + + https://bugs.webkit.org/show_bug.cgi?id=38094 + + The parseDiffHeader() function is part of new patch-parsing code + for svn-apply and svn-unapply that will go live in a subsequent + revision. + + * Scripts/VCSUtils.pm: + - Added logic to parseDiffHeader() to recognize the ending of + the header portion of a binary diff. + + * Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl: + - Added unit test cases for SVN and Git binary diffs. + +2010-04-28 Eric Seidel <eric@webkit.org> + + Reviewed by David Levin. + + Document that subprocess.poll/wait are not threadsafe + https://bugs.webkit.org/show_bug.cgi?id=38289 + + * Scripts/webkitpy/common/system/executive.py: + * Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py: + * Scripts/webkitpy/layout_tests/port/chromium.py: + * Scripts/webkitpy/layout_tests/port/http_server.py: + * Scripts/webkitpy/layout_tests/port/server_process.py: + * Scripts/webkitpy/layout_tests/port/websocket_server.py: + +2010-04-28 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Daniel Bates. + + Removed the dividing line (i.e. "====...") logic from the code + called by svn-apply and svn-unapply. + + https://bugs.webkit.org/show_bug.cgi?id=38093 + + The dividing line logic is unnecessary. Removing it simplifies the + code and makes some subsequent changes easier. + + * Scripts/VCSUtils.pm: + - Removed the logic in gitdiff2svndiff() to convert the git + "index" line to an SVN dividing line. + - Adjusted the logic similarly in parseDiffHeader(). + + * Scripts/webkitperl/VCSUtils_unittest/gitdiff2svndiff.pl: + - Updated the unit tests as necessary. + + * Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl: + - Updated the unit tests as necessary. + - Corrected an error in the unit tests whereby all elements + of an array were referencing the same element rather than + distinct elements -- causing unit test failures to be masked. + + * Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl: + - Updated the unit tests as necessary. + - Made the same unit test correction as above for parseDiff.pl. + +2010-04-28 Evan Stade <estade@chromium.org> + + Unreviewed. + + * Scripts/webkitpy/common/config/committers.py: adding myself as a committer + +2010-04-28 Sam Weinig <sam@webkit.org> + + Reviewed by Mark Rowe. + + Add MiniBrowser to the lists of modules to build and only build it on + SnowLeopard and later. + + * Makefile: + * MiniBrowser/Makefile: + +2010-04-28 Sam Weinig <sam@webkit.org> + + Reviewed by Mark Rowe. + + Make running MiniBrowser.app without explicitly setting DYLD_FRAMEWORK_PATH. + + * MiniBrowser/MiniBrowser.xcodeproj/project.pbxproj: + * MiniBrowser/mac/make-launchable.sh: Added. + +2010-04-28 Eric Seidel <eric@webkit.org> + + Reviewed by David Levin. + + Audit all uses of subprocess in webkitpy + https://bugs.webkit.org/show_bug.cgi?id=38284 + + After further discussions with Jeffrey Yasskin + about http://bugs.python.org/issue2320 + and related issues of using subprocess from + multiple threads, I have learned that subprocess + is known to be non-threadsafe through recent + Python 2.7 builds. + + I'm attempting to lessen our exposure to these + subprocess bugs by auditing each use of subprocess + in webkitpy. I did not find any unsafe calls + in my audit, but I did remove numerous unneeded + import subprocess lines. + + * Scripts/webkitpy/common/checkout/api.py: + * Scripts/webkitpy/common/net/bugzilla.py: + * Scripts/webkitpy/common/system/deprecated_logging_unittest.py: + * Scripts/webkitpy/common/system/user.py: + * Scripts/webkitpy/layout_tests/port/base.py: + * Scripts/webkitpy/layout_tests/port/chromium_linux.py: + * Scripts/webkitpy/layout_tests/port/chromium_mac.py: + * Scripts/webkitpy/layout_tests/port/chromium_mac_unittest.py: Added. + * Scripts/webkitpy/layout_tests/port/chromium_win.py: + * Scripts/webkitpy/layout_tests/port/gtk.py: + * Scripts/webkitpy/layout_tests/port/mac.py: + * Scripts/webkitpy/layout_tests/port/qt.py: + * Scripts/webkitpy/layout_tests/port/webkit.py: + * Scripts/webkitpy/layout_tests/port/win.py: + +2010-04-28 Darin Adler <darin@apple.com> + + Ignore a directory the Python tools creates. + + * Scripts/webkitpy/style: Modified property svn:ignore. + +2010-04-28 Darin Adler <darin@apple.com> + + * Scripts/extract-localizable-strings: Fix minor mistake in + argument checking. + +2010-04-28 Luiz Agostini <luiz.agostini@openbossa.org> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] QWebPage viewMode property + https://bugs.webkit.org/show_bug.cgi?id=38119 + + Replacing method qt_wrt_setViewMode by wrt_viewMode property. + + * DumpRenderTree/qt/LayoutTestControllerQt.cpp: + (LayoutTestController::setViewModeMediaFeature): + +2010-04-28 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Shinichiro Hamaji. + + Adjusted check-webkit-style so that files with file type NONE + are automatically skipped without warning. + + https://bugs.webkit.org/show_bug.cgi?id=38197 + + This change simplifies configuring which files to skip. It also + addresses an issue whereby check-webkit-style was unintentionally + checking .vcproj files for carriage returns. + + * Scripts/webkitpy/style/checker.py: + - Moved the C++, Python, and text file extensions to new + module-level configuration variables. + - Removed .pyc from the _SKIPPED_FILES_WITHOUT_WARNING configuration + variable. + - Changed the numeric values of the FileType enum so that + FileType.NONE evaluates to False. + - For ProcessorDispatcher.should_skip_without_warning(): + - Changed the method to return True for FileType.NONE files. + - Made ChangeLog files an exception to getting skipped. + - Changed the StyleProcessor.process() method to raise an + exception if given a file path that should not be processed. + + * Scripts/webkitpy/style/checker_unittest.py: + - Updated the unit tests and added more test cases as necessary. + +2010-04-28 Eric Seidel <eric@webkit.org> + + Reviewed by Jeremy Orlow. + + webkitpy: ScriptError('Failed to run "[u\'taskkill.exe\', u\'/f\', u\'/im\', u\'httpd.exe\']" exit_code: 128',) + https://bugs.webkit.org/show_bug.cgi?id=38248 + + The previous code did not check the return code of taskkill. + When I moved that callsite from using subprocess.call to + Executive.run_command having a non-zero return code became an error. + + In this change I've centralized our killall handling in executive, + and added tests for it to make sure it works. + + Currently kill_process and kill_all swallow exceptions in the cases + where the process(es) to be killed do(es) not exist. + + * Scripts/webkitpy/common/system/executive.py: + * Scripts/webkitpy/common/system/executive_unittest.py: + * Scripts/webkitpy/layout_tests/port/chromium_linux.py: + * Scripts/webkitpy/layout_tests/port/chromium_mac.py: + * Scripts/webkitpy/layout_tests/port/chromium_win.py: + * Scripts/webkitpy/layout_tests/port/gtk.py: + * Scripts/webkitpy/layout_tests/port/mac.py: + * Scripts/webkitpy/layout_tests/port/qt.py: + * Scripts/webkitpy/layout_tests/port/win.py: + +2010-04-28 Eric Seidel <eric@webkit.org> + + Reviewed by Shinichiro Hamaji. + + wdiff_text throws ScriptError because wdiff returns non-zero when files differ + https://bugs.webkit.org/show_bug.cgi?id=38246 + + wdiff returns 0 when files are the same, 1 when they differ. + run_command by default raises ScriptError if the return code is non-zero. + Fixed this by adding a custom error handler which only raises if the + return code is not 1. + + I broke up the huge wdiff_text() method into little pieces + for easier unit testing. There is only one functional change here + and that is the addition of the custom error handler. + + * Scripts/webkitpy/layout_tests/port/base.py: + * Scripts/webkitpy/layout_tests/port/base_unittest.py: + +2010-04-28 Fumitoshi Ukai <ukai@chromium.org> + + Unreviewed build fix. + + * DumpRenderTree/chromium/TestShell.cpp: + (TestShell::dumpImage): format '%u' expects type 'unsigned int', but argument 2 has type 'size_t'. + * DumpRenderTree/chromium/WebViewHost.cpp: + (WebViewHost::willSendRequest): too few arguments for format. + +2010-04-27 Shinichiro Hamaji <hamaji@chromium.org> + + Reviewed by Darin Adler and Eric Seidel. + + Add layoutTestController.setPrinting() + https://bugs.webkit.org/show_bug.cgi?id=37203 + + * DumpRenderTree/LayoutTestController.cpp: + (LayoutTestController::LayoutTestController): + (setPrintingCallback): + (LayoutTestController::staticFunctions): + * DumpRenderTree/LayoutTestController.h: + (LayoutTestController::isPrinting): + (LayoutTestController::setIsPrinting): + * DumpRenderTree/mac/DumpRenderTree.mm: + (dump): + +2010-04-27 Michael Nordman <michaeln@google.com> + + Reviewed by Dmitry Titov. + + [Chromium] Add two things to the webkit API to support appcaches in workers. + 1) WebURLRequest TargetTypes for worker and shared worker main resources. + 2) Factory method on class WebCommonWorkerClient to + createApplicationCacheHost() for the associated worker. + + https://bugs.webkit.org/show_bug.cgi?id=38147 + + * DumpRenderTree/chromium/TestWebWorker.h add a stub impl of the factory method + (TestWebWorker::createApplicationCacheHost): + +2010-04-27 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + run-bindings-tests doesn't work in an SVN checkout + https://bugs.webkit.org/show_bug.cgi?id=38225 + + Previously detect_scm_system needed an absolute path for SVN. Now we + accept a relative path. + + * Scripts/webkitpy/common/checkout/scm.py: + * Scripts/webkitpy/common/checkout/scm_unittest.py: + +2010-04-27 Sam Weinig <sam@webkit.org> + + Reviewed by Stephanie Lewis. + + Always build WebKit2 when building on SnowLeopard and later. + + * Scripts/build-webkit: + +2010-04-27 Sam Weinig <sam@webkit.org> + + Reviewed by Maciej Stachowiak. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38238 + Allow both WebKit and WebKit2 to link to the same WebCore.framework + + * Scripts/build-webkit: Remove the UMBRELLA_LDFLAGS override when building + WebCore for WebKit2, it is no longer necessary. + +2010-04-27 James Robinson <jamesr@chromium.org> + + Reviewed by David Levin. + + Fix a typo in chromium.py that causes NRWT to fail in --verbose + mode in a Chromium checkout. + https://bugs.webkit.org/show_bug.cgi?id=38234 + + * Scripts/webkitpy/layout_tests/port/chromium.py: + +2010-04-27 Darin Fisher <darin@chromium.org> + + Reviewed by Dimitri Glazkov. + + [Chromium] Remove deprecated form of didChangeLocationWithinPage + https://bugs.webkit.org/show_bug.cgi?id=38178 + + Switch over to implementing didNavigateWithinPage. + + * DumpRenderTree/chromium/WebViewHost.cpp: + (TestWebViewDelegate::didNavigateWithinPage): + (WebViewHost::didChangeLocationWithinPage): + * DumpRenderTree/chromium/WebViewHost.h: + +2010-04-27 Evan Martin <evan@chromium.org> + + Unreviewed. + + Adding myself to commmitters list. + + * Scripts/webkitpy/common/config/committers.py: + +2010-04-27 Adam Barth <abarth@webkit.org> + + Reviewed by Darin Adler. + + run-bindings-tests should use --reset-results instead of --overwrite + https://bugs.webkit.org/show_bug.cgi?id=38200 + + As requested by Ojan. + + * Scripts/run-bindings-tests: + +2010-04-27 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + REGRESSION(r58261): webkit-patch edit-changelogs is broken + https://bugs.webkit.org/show_bug.cgi?id=38204 + + In 58261, we added code to abstract step that interrogates the squash + and git_commit options, but it doesn't declare that it uses those + options. That means any command that doesn't happen to declare those + options might be broken if it uses the cached_lookup mechanism. + + * Scripts/webkitpy/tool/steps/abstractstep.py: + * Scripts/webkitpy/tool/steps/applypatch.py: + * Scripts/webkitpy/tool/steps/applypatchwithlocalcommit.py: + * Scripts/webkitpy/tool/steps/build.py: + * Scripts/webkitpy/tool/steps/checkstyle.py: + * Scripts/webkitpy/tool/steps/cleanworkingdirectory.py: + * Scripts/webkitpy/tool/steps/closebug.py: + * Scripts/webkitpy/tool/steps/closebugforlanddiff.py: + * Scripts/webkitpy/tool/steps/commit.py: + * Scripts/webkitpy/tool/steps/confirmdiff.py: + * Scripts/webkitpy/tool/steps/createbug.py: + * Scripts/webkitpy/tool/steps/ensurebuildersaregreen.py: + * Scripts/webkitpy/tool/steps/ensurelocalcommitifneeded.py: + * Scripts/webkitpy/tool/steps/obsoletepatches.py: + * Scripts/webkitpy/tool/steps/postcodereview.py: + * Scripts/webkitpy/tool/steps/postdiff.py: + * Scripts/webkitpy/tool/steps/preparechangelog.py: + * Scripts/webkitpy/tool/steps/runtests.py: + * Scripts/webkitpy/tool/steps/update.py: + * Scripts/webkitpy/tool/steps/updatechangelogswithreviewer.py: + * Scripts/webkitpy/tool/steps/validatereviewer.py: + +2010-04-27 Eric Seidel <eric@webkit.org> + + Reviewed by David Levin. + + prepare-ChangeLog --bug fails on some CYGWIN installs due to missing certs + https://bugs.webkit.org/show_bug.cgi?id=38212 + + * Scripts/prepare-ChangeLog: + - Pass --insecure to curl to work around CYGWIN missing certs. + +2010-04-27 Sam Weinig <sam@webkit.org> + + Rubber-stamped by Beth Dakin. + + It is no longer necessary to set ENABLE_EXPERIMENTAL_SINGLE_VIEW_MODE + or WTF_USE_WEB_THREAD. Remove them. + + * Scripts/build-webkit: + +2010-04-27 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by David Levin. + + Changed Chris Jerdonek from committer to reviewer. + + * Scripts/webkitpy/common/config/committers.py: + +2010-04-27 Benjamin Poulain <benjamin.poulain@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] QGraphicsWebView: Arrow keys scroll the graphics-view instead of the web-page + https://bugs.webkit.org/show_bug.cgi?id=35834 + + The scene should always have the size of the web view otherwhise it is + possible to scroll the graphics view. + + * QtLauncher/webview.cpp: + (WebViewGraphicsBased::resizeEvent): + +2010-04-27 Diego Gonzalez <diegohcg@webkit.org> + + Unreviewed. + + Adding myself to committers.py + + * Scripts/webkitpy/common/config/committers.py: + +2010-04-27 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + [chromium] new-run-webkit-tests hangs on Chromium Bots (OS X and Linux) + https://bugs.webkit.org/show_bug.cgi?id=37987 + + After further research, I believe the hang is caused by: + http://bugs.python.org/issue2320 + Basically Popen() is not reentrant. + The workaround is to pass close_fds=True to Popen() on Mac/Linux. + + I fixed our main Popen wrapper "Executive.run_command" to use close_fds=True + when appropriate. + + I audited all places we call Popen() and either moved them to run_command + or left a FIXME that they are not thread safe. A few places I added the + close_fds workaround there and left an explanitory note. + + * Scripts/webkitpy/common/checkout/scm_unittest.py: + - Added note that this Popen use is not threadsafe. + * Scripts/webkitpy/common/system/executive.py: + - Fixed our Executive.run_* to workaround python bug 2320. + * Scripts/webkitpy/common/system/user.py: + _ Added note that this Popen use is not threadsafe. + * Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py: ditto. + * Scripts/webkitpy/layout_tests/port/apache_http_server.py: ditto. + * Scripts/webkitpy/layout_tests/port/base.py: + - Change wdiff back to using run_command now that we believe it + to be threadsafe. + * Scripts/webkitpy/layout_tests/port/chromium.py: + - Fix to use Executive in places. + - Pass self._executive down to the Driver for easier unit testing. + * Scripts/webkitpy/layout_tests/port/chromium_win.py: + - Re-factor to use a _kill_all method. + - Made the _kill_all method use run_command to be threadsafe. + * Scripts/webkitpy/layout_tests/port/http_server.py: + - Add FIXME about using Executive. + * Scripts/webkitpy/layout_tests/port/server_process.py: + - Use Executive to be threadsafe. + * Scripts/webkitpy/layout_tests/port/webkit.py: + - Pass self._executive down to the Driver. + * Scripts/webkitpy/layout_tests/port/websocket_server.py: + - Add note about Popen not being threadsafe. + * Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py: + - Move one caller to run_command add notes about moving others. + +2010-04-27 Adam Barth <abarth@webkit.org> + + Reviewed by Maciej Stachowiak. + + REGRESSION(r58261): webkit-patch upload does not work in an SVN checkout. + https://bugs.webkit.org/show_bug.cgi?id=38186 + + Unfortunately, we don't have a good way of testing this change because + our test coverage of the scm.py API is poor... + + * Scripts/webkitpy/common/checkout/scm.py: + * Scripts/webkitpy/tool/steps/preparechangelog.py: + +2010-04-26 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Remove unused code from text_diff.py + https://bugs.webkit.org/show_bug.cgi?id=38170 + + * Scripts/webkitpy/layout_tests/test_types/text_diff.py: + - Remove is_render_tree_dump which appears unused. + +2010-04-26 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + webkit-patch pretty-diff is broken + https://bugs.webkit.org/show_bug.cgi?id=38172 + + We need to register for these options because they're used when we look + up the diff. + + * Scripts/webkitpy/tool/steps/confirmdiff.py: + +2010-04-26 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Add ObjC and GObject to run-bindings-test + https://bugs.webkit.org/show_bug.cgi?id=38168 + + * Scripts/run-bindings-tests: + +2010-04-26 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Add testing infrastructure for JSC bindings generator + https://bugs.webkit.org/show_bug.cgi?id=38167 + + Add support for testing more than one bindings. Also, converted the + script to PEP8 style. + + * Scripts/run-bindings-tests: + +2010-04-26 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Refactor results.html generation out into a new method and test it + https://bugs.webkit.org/show_bug.cgi?id=38164 + + Hopefully this results in no change in functionality. + + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + * Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py: + +2010-04-26 Adam Barth <abarth@webkit.org> + + Unreviewed, rolling out r58265. + http://trac.webkit.org/changeset/58265 + https://bugs.webkit.org/show_bug.cgi?id=38021 + + This change prevents me from uploading patches. It also breaks sheriff-bot. + + * Scripts/webkitpy/tool/steps/options.py: + +2010-04-26 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + [chromium] new-run-webkit-tests hangs on Chromium Bots (OS X and Linux) + https://bugs.webkit.org/show_bug.cgi?id=37987 + + Rolled out: + http://trac.webkit.org/changeset/58062 + http://trac.webkit.org/changeset/58060 + http://trac.webkit.org/changeset/58059 + http://trac.webkit.org/changeset/58055 + http://trac.webkit.org/changeset/58054 + and parts of: + http://trac.webkit.org/changeset/58050 + + I also wrote some new comments and a tiny amount of new + code to help make ChromiumDriver.run_test easier to read. + + In order to unit-test my new code, I had to change ChromiumDriver + to not automatically start itself when created. That ended up + being a lot of plumbing, but is hopefully easier to understand now. + + There are no tests for the (restored) wdiff code. wdiff does not + exist on all systems, so for now we will assume it worked since + it is just old code being reverted. + + * Scripts/webkitpy/layout_tests/driver_test.py: + - Use create_driver instead of start_driver, and be sure to call .stop() + * Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py: + - Use create_driver instead of start_driver + * Scripts/webkitpy/layout_tests/port/base.py: + - Added a comment to explain that diffs are binary files. + - Various patch reverts relating to wdiff + - Add Driver._command_wrapper to share code between WebKitDriver and ChromiumDriver. + - Made _command_wrapper use shlex.split to get rid of the FIXME. + * Scripts/webkitpy/layout_tests/port/base_unittest.py: Added. + - test the new _command_wrapper + * Scripts/webkitpy/layout_tests/port/chromium.py: + - Use _command_wrapper to get rid of a bunch of ugly code. + - Make __init__ stop auto-starting. + - Rename create_driver to start_driver. + - Added _write_command_and_read_line to make it possible to + put a FIXME next to read_line() w/o having to put it in two places. + - Moved test_shell command building into _test_shell_command and tested it. + - Fix comments to say test_shell since ChromiumDriver is test_shell only. + * Scripts/webkitpy/layout_tests/port/chromium_unittest.py: Added. + - Test the new test_shell_command method. + * Scripts/webkitpy/layout_tests/port/dryrun.py: + - Rename create_driver to start_driver. + * Scripts/webkitpy/layout_tests/port/test.py: + - Rename create_driver to start_driver. + * Scripts/webkitpy/layout_tests/port/webkit.py: + - Rename create_driver to start_driver. + - Treat output as binary arrays. + * Scripts/webkitpy/layout_tests/test_types/test_type_base.py: + - Treat diff files as binary. + * Scripts/webkitpy/layout_tests/test_types/text_diff.py: + - Treat diff files as binary. + +2010-04-26 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Move bindings test directory into the scripts directory + https://bugs.webkit.org/show_bug.cgi?id=38161 + + Change script to point to the new location of these data files. + + * Scripts/run-bindings-tests: + +2010-04-26 Adam Barth <abarth@webkit.org> + + Unreviewed. Mark run-bindings-tests executable so we can execute it. + + * Scripts/run-bindings-tests: + +2010-04-26 Tony Chang <tony@chromium.org> + + Reviewed by David Levin. + + [chromium] build-webkit --chromium should build release by default + https://bugs.webkit.org/show_bug.cgi?id=38028 + + * Scripts/build-dumprendertree: Also should build release by default + * Scripts/build-webkit: Make sure to pass command line args through + * Scripts/webkitdirs.pm: Build the right configuration + +2010-04-26 Ojan Vafai <ojan@chromium.org> + + Reviewed by Eric Seidel. + + complete rietveld bugzilla integration + https://bugs.webkit.org/show_bug.cgi?id=38021 + + Makes --fancy-review the default. All this means is that the patch will + be uploaded to rietveld in addition to bugs.webkit.org. + + * Scripts/webkitpy/tool/steps/options.py: + +2010-04-26 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Shinichiro Hamaji. + + For check-webkit-style, renamed the style/processors/ directory + to style/checkers/. + + https://bugs.webkit.org/show_bug.cgi?id=38122 + + * Scripts/webkitpy/style/checker.py: + - Updated import statements. + + * Scripts/webkitpy/style/checker_unittest.py: + - Updated import statements. + + * Scripts/webkitpy/style/checkers: Copied from WebKitTools/Scripts/webkitpy/style/processors. + * Scripts/webkitpy/style/processors: Removed. + * Scripts/webkitpy/style/processors/__init__.py: Removed. + * Scripts/webkitpy/style/processors/common.py: Removed. + * Scripts/webkitpy/style/processors/common_unittest.py: Removed. + * Scripts/webkitpy/style/processors/cpp.py: Removed. + * Scripts/webkitpy/style/processors/cpp_unittest.py: Removed. + * Scripts/webkitpy/style/processors/python.py: Removed. + * Scripts/webkitpy/style/processors/python_unittest.py: Removed. + * Scripts/webkitpy/style/processors/python_unittest_input.py: Removed. + * Scripts/webkitpy/style/processors/text.py: Removed. + * Scripts/webkitpy/style/processors/text_unittest.py: Removed. + +2010-04-06 Ojan Vafai <ojan@chromium.org> + + Reviewed by Adam Barth. + + Include git commits in the diff for webkit-patch upload/land. + https://bugs.webkit.org/show_bug.cgi?id=36394 + + Adds --squash, --no-squash and --git-commit. + + --git-commit will use a specific local commit for land/upload. + If a commit-range is specified, then that range is treated as + a single squashed commit. + + --squash will squash all local changes including working copy changes + into a single patch. + + --no-squash is the legacy behavior (upload only considers the working copy, + land commits the working copy and then each local commit separately to SVN) + + If neither is specified, then an informative error is raised if there is + more than one local commit or when there are local commit(s) and working + copy changes. + + If the webkit-patch.squash git config parameter is set, then + that will be respected instead of raising an error. + + * Scripts/check-webkit-style: + * Scripts/webkitpy/common/checkout/api.py: + * Scripts/webkitpy/common/checkout/api_unittest.py: + * Scripts/webkitpy/common/checkout/scm.py: + * Scripts/webkitpy/common/checkout/scm_unittest.py: + * Scripts/webkitpy/style/optparser.py: + --git-since is removed and --git-commit no longer implies commit_id.. + Instead, it treats that individual commit, but also supports commit ranges + (e.g. commit_id..) as arguments. + * Scripts/webkitpy/style/optparser_unittest.py: + * Scripts/webkitpy/style_references.py: + * Scripts/webkitpy/tool/commands/download.py: + * Scripts/webkitpy/tool/commands/upload.py: + * Scripts/webkitpy/tool/main.py: + * Scripts/webkitpy/tool/mocktool.py: + * Scripts/webkitpy/tool/steps/abstractstep.py: + * Scripts/webkitpy/tool/steps/applypatchwithlocalcommit.py: + * Scripts/webkitpy/tool/steps/checkstyle.py: + * Scripts/webkitpy/tool/steps/commit.py: + * Scripts/webkitpy/tool/steps/options.py: + * Scripts/webkitpy/tool/steps/postdiff.py: + * Scripts/webkitpy/tool/steps/preparechangelog.py: + * Scripts/webkitpy/tool/steps/preparechangelogforrevert.py: + * Scripts/webkitpy/tool/steps/updatechangelogswithreviewer.py: + * Scripts/webkitpy/tool/steps/validatereviewer.py: + +2010-04-26 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Shinichiro Hamaji. + + Deleted the StyleChecker-related classes that are no longer + being used. + + https://bugs.webkit.org/show_bug.cgi?id=38118 + + * Scripts/webkitpy/style/checker.py: + - Deleted the DeprecatedStyleChecker class. + + * Scripts/webkitpy/style/checker_unittest.py: + - Deleted the StyleCheckerTest, StyleCheckerCheckFileBase, + StyleCheckerCheckFileTest, and StyleCheckerCheckPathsTest classes. + +2010-04-26 Chris Jerdonek <cjerdonek@webkit.org> + + Reviewed by Shinichiro Hamaji. + + Changed the StyleChecker class to use the new TextFileReader class. + + https://bugs.webkit.org/show_bug.cgi?id=37066 + + This revision separates the code responsible for reading and iterating + over text files from the rest of check-webkit-style. + + * Scripts/check-webkit-style: + - Changed the script to use the new StyleProcessor and + TextFileReader classes instead of the StyleChecker class. + + * Scripts/webkitpy/style/checker.py: + - Added a FIXME to rename many of uses of the word "processor" to + "checker". We did this to clarify the difference between + ProcessorBase instances passed to the TextFileReader and + classes that process and check lines for style. + - Added a FIXME to remove FileType.NONE as a possible return value + of ProcessorDispatcher._file_type(). This will better consolidate + the logic of which files should be skipped. + - Added a FIXME to delete the StyleChecker class. + - Added the StyleProcessor class which implements ProcessorBase. + This class is responsible for processing lines to check style + (but not for reading files). For each file, this class creates + creates both a carriage-return checker and a format-specific + style checker (e.g. one of C++, Python, etc). + - Updated the PatchChecker class to use a TextFileReader instance + instead of a StyleChecker. + + * Scripts/webkitpy/style/checker_unittest.py: + - Added the StyleProcessor_EndToEndTest class to do "end-to-end" + tests of the StyleProcessor class. + - Added the StyleProcessor_CodeCoverageTest to test the + StyleProcessor class with more complete code coverage. + Unlike the StyleProcessor_EndToEndTest class, this class makes + heavy use of mock parameters. + - Added FIXME's to delete the unit test classes that are no + longer needed. + - Updated the PatchCheckerTest class to use a MockTextFileReader + instead of a MockStyleChecker. + + * Scripts/webkitpy/style/filereader.py: + - Updated the TextFileReader class to use the preferred logic + of checking file existence at the beginning of the process_file() + method instead of in the except block, per + https://bugs.webkit.org/show_bug.cgi?id=37122 + + * Scripts/webkitpy/style/filereader_unittest.py: + - In the TextFileReaderTest class: + - Moved the test_process_file__should_not_process() method. + - Added a test_process_file__file_stdin() method to test + the file path "-". + +2010-04-20 Robert Hogan <robert@webkit.org> + + Reviewed by Simon Hausmann. + + [Qt] Add more support for textInputController + + Add support for selectedRange(), setMarkedText(), insertText(), + and firstRectForCharacterRange(). + + Unskip tests: + + fast/forms/input-maxlength-ime-preedit.html + fast/forms/input-maxlength-ime-completed.html + fast/text/international/thai-cursor-position.html + fast/events/ime-composition-events-001.html + editing/selection/5825350-1.html + editing/selection/5825350-2.html + editing/selection/mixed-editability-10.html + + https://bugs.webkit.org/show_bug.cgi?id=35702 + + * DumpRenderTree/qt/TextInputControllerQt.cpp: + (TextInputController::setMarkedText): + (TextInputController::insertText): + (TextInputController::selectedRange): + (TextInputController::firstRectForCharacterRange): + * DumpRenderTree/qt/TextInputControllerQt.h: + +2010-04-23 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + check-webkit-style complains about non-utf8 data in layout test result + https://bugs.webkit.org/show_bug.cgi?id=38027 + + The problem was we were assuming patch files/diff output as utf-8. + Turns out they're not. We have to treat them as binary data because + a single patch may have multiple text files in it with conflicting encodings! + + * Scripts/webkitpy/common/checkout/api.py: + - contents_at_revision returns a byte array, so decode it to unicode + before passing it to parse_latest_entry_from_file + * Scripts/webkitpy/common/checkout/api_unittest.py: + - Update our mock mock_contents_at_revision to match the encoding + semantics of the real one. + * Scripts/webkitpy/common/checkout/scm.py: + - Be careful not to decode output which may contain file contents + (like diff, cat or show) as the encoding for that content is unknown. + * Scripts/webkitpy/common/checkout/scm_unittest.py: + - Update our tests to use both latin1 and utf-8 encoded data. + * Scripts/webkitpy/common/net/bugzilla.py: + - _fill_attachment_form should not assume unicode data. Callers + may wish to attach other types of files to bugs. + * Scripts/webkitpy/common/prettypatch.py: + - Diffs are byte arrays, deal with them as such. + * Scripts/webkitpy/common/prettypatch_unittest.py: + - Test to make sure we handle diffs with multiple conflicting encodings. + * Scripts/webkitpy/common/system/executive_unittest.py: + - Make sure that our unicode support does not break our + byte array input support for run_command. + +2010-04-23 Sam Weinig <sam@webkit.org> + + Reviewed by David Levin. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38060 + Split up Threading.h + + Add necessary forwarding headers. + + * DumpRenderTree/ForwardingHeaders/wtf/Atomics.h: Added. + * DumpRenderTree/ForwardingHeaders/wtf/ThreadSafeShared.h: Added. + * DumpRenderTree/ForwardingHeaders/wtf/ThreadingPrimitives.h: Added. + +2010-04-23 Xiaomei Ji <xji@chromium.org> + + No need to review. + + Add xji as committer. + + * Scripts/webkitpy/common/config/committers.py: + +2010-04-23 Kevin Ollivier <kevino@theolliviers.com> + + [wx] Build fix, add platform stub for new LayoutTestController method. + + * DumpRenderTree/wx/LayoutTestControllerWx.cpp: + (LayoutTestController::markerTextForListItem): + +2010-04-19 Dirk Pranke <dpranke@chromium.org> + + Reviewed by Adam Barth. + + new-run-webkit-tests: add a "--retry-failures" flag and a + "--no-retry-failures" flag (the former is the default). Also, rename + "--print-unexpected-results" and "--retry-unexpected-results" to + "--print-last-failures" and "--retry-last-failures" because the + retry flag was confusing. The new flag names aren't great, but + hopefully they're less confusing. + + https://bugs.webkit.org/show_bug.cgi?id=37838 + + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + +2010-04-22 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38022 + Move isMainThread predicate function to MainThread.h + + Added forwarding header for MainThread.h + + * DumpRenderTree/ForwardingHeaders/wtf/MainThread.h: Added. + +2010-04-23 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Disable Netscape plugin support for minimal configuration + https://bugs.webkit.org/show_bug.cgi?id=38026 + + Pass the minimal configuration option to Qt build system + as part of the CONFIG variable. + + * Scripts/build-webkit: + +2010-04-22 Fumitoshi Ukai <ukai@chromium.org> + + Unreviewed fix. + + * Scripts/webkitpy/layout_tests/port/websocket_server.py: fix NameError: global name 'f' is not defined. + +2010-04-22 James Robinson <jamesr@chromium.org> + + Reviewed by Adam Barth. + + Revert 58077 and follow-ups. It's broken. + https://bugs.webkit.org/show_bug.cgi?id=37664 + + * Scripts/new-run-webkit-httpd: + * Scripts/new-run-webkit-websocketserver: + * Scripts/webkitpy/layout_tests/port/chromium_win.py: + * Scripts/webkitpy/layout_tests/port/http_server.py: + * Scripts/webkitpy/layout_tests/port/websocket_server.py: + +2010-04-22 Yaar Schnitman <yaar@chromium.org> + + Reviewed by Adam Barth. + + Integrate v8 testing utility with webkit tests + https://bugs.webkit.org/show_bug.cgi?id=37731 + + * Scripts/run-bindings-tests: Added. + +2010-04-22 Eric Seidel <eric@webkit.org> + + Reviewed by Dimitri Glazkov. + + new-run-webkit-tests --verbose shows ever-increasing #EOF lines + https://bugs.webkit.org/show_bug.cgi?id=37794 + + * Scripts/webkitpy/layout_tests/port/webkit.py: + - Remove the assert() since our ServerProcess code does not always + seem to be reading the full stderr output (or we're not waiting for it to). + +2010-04-22 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Add code to help debug new-run-webkit-test hangs on the Chromium bots + https://bugs.webkit.org/show_bug.cgi?id=38011 + + I can see no reasonable way to test this change. + Stubbing out sys._current_frames() and traceback.extract_stack + seems folly. Dumping real data would have line number + (and possibly other call stack) variance between runs. + + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + - Add _dump_thread_states and _dump_thread_states_if_necessary + to have our main thread dump the states of all threads every + 60 seconds when running in verbose mode. + - Better document what is going on in our main loop. + +2010-04-22 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=38002 + Add rudimentary statistics gathering for WebKit2 + + * MiniBrowser/MiniBrowser.xcodeproj/project.pbxproj: + * MiniBrowser/mac/AppDelegate.h: + * MiniBrowser/mac/AppDelegate.m: + (-[BrowserAppDelegate init]): + (-[BrowserAppDelegate newWindow:]): + (-[BrowserAppDelegate getCurrentPageNamespace]): + (-[BrowserAppDelegate _setProcessModel:]): + (-[BrowserAppDelegate showStatisticsWindow:]): + (-[BrowserAppDelegate applicationWillTerminate:]): + * MiniBrowser/mac/BrowserStatisticsWindow.xib: Added. + * MiniBrowser/mac/BrowserStatisticsWindowController.h: Added. + * MiniBrowser/mac/BrowserStatisticsWindowController.m: Added. + (-[BrowserStatisticsWindowController initWithThreadedWKContextRef:processWKContextRef:]): + (-[BrowserStatisticsWindowController dealloc]): + (-[BrowserStatisticsWindowController windowDidLoad]): + (-[BrowserStatisticsWindowController refreshStatistics:]): + * MiniBrowser/mac/BrowserWindowController.h: + * MiniBrowser/mac/English.lproj/MainMenu.xib: + * MiniBrowser/mac/MiniBrowser_Prefix.pch: + +2010-04-22 Dave Moore <davemoore@chromium.org> + + Reviewed by Dimitri Glazkov. + + Add test support for icon changes. + + https://bugs.webkit.org/show_bug.cgi?id=33812 + + * DumpRenderTree/LayoutTestController.cpp: + (LayoutTestController::LayoutTestController): + (dumpIconChangesCallback): + (LayoutTestController::staticFunctions): + * DumpRenderTree/LayoutTestController.h: + (LayoutTestController::dumpIconChanges): + (LayoutTestController::setDumpIconChanges): + * DumpRenderTree/win/FrameLoadDelegate.cpp: + (FrameLoadDelegate::didChangeIcons): + * DumpRenderTree/win/FrameLoadDelegate.h: + * WinLauncher/WinLauncher.h: + (WinLauncherWebHost::didChangeIcons): + +2010-04-22 Eric Seidel <eric@webkit.org> + + Unreviewed. Script fix. Will ask dpranke to look tomorrow. + + new-run-webkit-tests --verbose shows ever-increasing #EOF lines + https://bugs.webkit.org/show_bug.cgi?id=37794 + + The bots are seeing cases where .error is sometimes empty. + Lets make the code not crash in that case for now. + + * Scripts/webkitpy/layout_tests/port/webkit.py: + +2010-04-22 Fumitoshi Ukai <ukai@chromium.org> + + Unreviewed fix. + + * Scripts/webkitpy/layout_tests/port/websocket_server.py: fix NameError: global name 'f' is not defined. + +2010-04-22 Fumitoshi Ukai <ukai@chromium.org> + + Unreviewed fix. + + * Scripts/new-run-webkit-websocketserver: PyWebSocket no longer takes keyword argument 'register_cygwin'. + +2010-04-22 Eric Seidel <eric@webkit.org> + + Unreviewed. Restore the Leopard bots to using + old-run-webkit-tests for now. + + * Scripts/run-webkit-tests: + +2010-04-22 Fumitoshi Ukai <ukai@chromium.org> + + Unreviewed fix. + + * Scripts/webkitpy/layout_tests/port/http_server.py: fix NameError: global name 'env' is not defined. + +2010-04-22 Fumitoshi Ukai <ukai@chromium.org> + + Unreviewed fix. + + * Scripts/webkitpy/layout_tests/port/websocket_server.py: fix NameError: global name 'env' is not defined. + +2010-04-22 Fumitoshi Ukai <ukai@chromium.org> + + Reviewed by Adam Barth. + + Chromium: Add --chromium option to new-run-webkit-websocketserver + https://bugs.webkit.org/show_bug.cgi?id=37664 + + Move cygwin setup logic in chromium_win.py. + + * Scripts/new-run-webkit-httpd: remove register_cygwin parameter to pass http_server. + * Scripts/new-run-webkit-websocketserver: add --chromium flag + * Scripts/webkitpy/layout_tests/port/chromium_win.py: setup for cygwin + * Scripts/webkitpy/layout_tests/port/http_server.py: remove cygwin setup logic + * Scripts/webkitpy/layout_tests/port/websocket_server.py: remove cygwin setup logic + +2010-04-22 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + new-run-webkit-tests --verbose shows ever-increasing #EOF lines + https://bugs.webkit.org/show_bug.cgi?id=37794 + + * Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py: + - Fix the log message to explain that this is stderr output, not test output. + * Scripts/webkitpy/layout_tests/port/webkit.py: + - Be sure to reset the server_process.error after reading (seems like the wrong + place to do this, but at least this fixes the bug and dpranke and I can talk + about better designs later). + - Also remove the #EOF from the stderr output before returning it. + +2010-04-22 Eric Seidel <eric@webkit.org> + + Unreviewed. Fixing new-run-webkit-tests on the bots. + + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + - Fixing _compat_shim_option to take variable keyword args. + - Turns out that nargs + callback is ignored unless type is specified. + So I added the type so that the option was properly consumed. + This was why new-run-webkit-tests couldn't find any tests, it + was looking for them under "20" because that was the argument + which should have been consumed by --exit-after-n-failures. + +2010-04-22 Tony Chang <tony@chromium.org> + + Not reviewed, build fix for chromium Windows. + + [chromium] fix ImageDiff compile on windows + https://bugs.webkit.org/show_bug.cgi?id=37979 + + * DumpRenderTree/chromium/ImageDiff.cpp: + +2010-04-22 Adam Barth <abarth@webkit.org> + + Unreviewed, rolling out r58069. + http://trac.webkit.org/changeset/58069 + https://bugs.webkit.org/show_bug.cgi?id=27751 + + Broke compile on Windows. + + * DumpRenderTree/LayoutTestController.cpp: + (LayoutTestController::staticFunctions): + * DumpRenderTree/LayoutTestController.h: + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::LayoutTestController): + (LayoutTestController::overridePreference): + * DumpRenderTree/chromium/LayoutTestController.h: + * DumpRenderTree/chromium/TestShell.cpp: + (TestShell::resetWebSettings): + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + * DumpRenderTree/mac/DumpRenderTree.mm: + (resetDefaultsToConsistentValues): + * DumpRenderTree/mac/LayoutTestControllerMac.mm: + * DumpRenderTree/qt/DumpRenderTreeQt.cpp: + (WebCore::WebPage::WebPage): + (WebCore::WebPage::resetSettings): + * DumpRenderTree/qt/LayoutTestControllerQt.cpp: + * DumpRenderTree/qt/LayoutTestControllerQt.h: + * DumpRenderTree/win/DumpRenderTree.cpp: + (resetDefaultsToConsistentValues): + * DumpRenderTree/win/LayoutTestControllerWin.cpp: + * DumpRenderTree/wx/LayoutTestControllerWx.cpp: + +2010-04-22 Eric Seidel <eric@webkit.org> + + Unreviewed. Just adding logging. + + Adding logging to help debug why the Leopard Bot + can't find any tests to run. + + * Scripts/webkitpy/layout_tests/layout_package/test_files.py: + * Scripts/webkitpy/layout_tests/port/base.py: + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: + - Make it a fatal error to have no tests to run. + +2010-04-22 Abhishek Arya <inferno@chromium.org> + + Reviewed by Adam Barth. + + Add support for controlling clipboard access from javascript. + Clipboard access from javascript is enabled in test framework. + https://bugs.webkit.org/show_bug.cgi?id=27751 + + * DumpRenderTree/LayoutTestController.cpp: + (setJavaScriptCanAccessClipboardCallback): + (LayoutTestController::staticFunctions): + * DumpRenderTree/LayoutTestController.h: + * DumpRenderTree/chromium/LayoutTestController.cpp: + (LayoutTestController::LayoutTestController): + (LayoutTestController::setJavaScriptCanAccessClipboard): + (LayoutTestController::overridePreference): + * DumpRenderTree/chromium/LayoutTestController.h: + * DumpRenderTree/chromium/TestShell.cpp: + (TestShell::resetWebSettings): + * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: + (LayoutTestController::setJavaScriptCanAccessClipboard): + * DumpRenderTree/mac/DumpRenderTree.mm: + (resetDefaultsToConsistentValues): + * DumpRenderTree/mac/LayoutTestControllerMac.mm: + (LayoutTestController::setJavaScriptCanAccessClipboard): + * DumpRenderTree/qt/DumpRenderTreeQt.cpp: + (WebCore::WebPage::WebPage): + (WebCore::WebPage::resetSettings): + * DumpRenderTree/qt/LayoutTestControllerQt.cpp: + (LayoutTestController::setJavaScriptCanAccessClipboard): + * DumpRenderTree/qt/LayoutTestControllerQt.h: + * DumpRenderTree/win/DumpRenderTree.cpp: + (resetDefaultsToConsistentValues): + * DumpRenderTree/win/LayoutTestControllerWin.cpp: + (LayoutTestController::setJavaScriptCanAccessClipboard): + * DumpRenderTree/wx/LayoutTestControllerWx.cpp: + (LayoutTestController::setJavaScriptCanAccessClipboard): + +2010-04-21 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + webkit-patch can't fetch attachments on security bugs + https://bugs.webkit.org/show_bug.cgi?id=37975 + + Instead of calling CURL, we just need to use our Mechanize object, + which understand bugs.webkit.org authentication. + + * Scripts/webkitpy/common/checkout/api.py: + * Scripts/webkitpy/common/net/bugzilla.py: + +2010-04-21 Eric Seidel <eric@webkit.org> + + Unreviewed. Temporary commit, will roll-out before morning. + + Turning on new-run-webkit-tests for the Leopard build bot + for testing of the harness. + Users should not noctice (except for the results.html difference). + + * Scripts/run-webkit-tests: + +2010-04-21 Eric Seidel <eric@webkit.org> + + Unreviewed. Fix typo in my previous fix attempt. + + REGRESSION(57531): the commit-queue still hates Tor Arne Vestbø + https://bugs.webkit.org/show_bug.cgi?id=37765 + + More on-the-bot debugging, sigh. I wish I had a local build. + + * Scripts/webkitpy/layout_tests/port/base.py: + +2010-04-21 Eric Seidel <eric@webkit.org> + + Unreviewed. Fix typo in my previous fix attempt. + + REGRESSION(57531): the commit-queue still hates Tor Arne Vestbø + https://bugs.webkit.org/show_bug.cgi?id=37765 + + * Scripts/webkitpy/layout_tests/port/base.py: + - Add self. to class variable access. + +2010-04-21 Eric Seidel <eric@webkit.org> + + Unreviewed. Another attempt to fix NRWT for chromium. + + REGRESSION(57531): the commit-queue still hates Tor Arne Vestbø + https://bugs.webkit.org/show_bug.cgi?id=37765 + + * Scripts/webkitpy/layout_tests/port/base.py: + - wdiff_text was returning a byte array instead of a + unicode string. The simple fix was to just decode + the result. However, seeing so much duplicated code + with Executive made me cry, so I re-wrote the function + to be more like pretty_patch_text and use run_command + (which already knows how to handle unicode). + +2010-04-21 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Windows tests buildbots are too slow to be core builders + https://bugs.webkit.org/show_bug.cgi?id=37970 + + It's 10:45. The Windows test bots are still hours behind. They're too + slow to be core builders. When they get fast, we can add them back. + + * Scripts/webkitpy/common/net/buildbot.py: + * Scripts/webkitpy/common/net/buildbot_unittest.py: + +2010-04-21 Eric Seidel <eric@webkit.org> + + Unreviewed. Attempt one more time to fix NRWT for chromium. + + REGRESSION(57531): the commit-queue still hates Tor Arne Vestbø + https://bugs.webkit.org/show_bug.cgi?id=37765 + + I'm debugging in the blind because I don't have a chromium + build on this laptop. + + * Scripts/webkitpy/layout_tests/port/chromium.py: + - Apply the previous fix to a second caller. + +2010-04-21 Eric Seidel <eric@webkit.org> + + Unreviewed. Attempt one more time to fix NRWT for chromium. + + REGRESSION(57531): the commit-queue still hates Tor Arne Vestbø + https://bugs.webkit.org/show_bug.cgi?id=37765 + + * Scripts/webkitpy/layout_tests/port/chromium.py: + - Fix handling of test_shell output so that we always + decode it as utf-8. + Unlike DumpRenderTree test_shell does not ever return + pixel data. It spits out the pixel dumps in a separate + file, thus all output over stdout is utf-8 text. + +2010-04-21 Eric Seidel <eric@webkit.org> + + Unreviewed. Attempt one more time to fix NRWT for chromium. + + REGRESSION(57531): the commit-queue still hates Tor Arne Vestbø + https://bugs.webkit.org/show_bug.cgi?id=37765 + + * Scripts/webkitpy/layout_tests/test_types/image_diff.py: + - Pass encoding to _save_baseline_data and write_output_files + * Scripts/webkitpy/layout_tests/test_types/test_type_base.py: + - Make _save_baseline_data and write_output_files take an encoding. + * Scripts/webkitpy/layout_tests/test_types/text_diff.py: + - Pass encoding to _save_baseline_data and write_output_files + +2010-04-21 No'am Rosenthal <noam.rosenthal@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] QtLauncher: make FPS measurement accurate + https://bugs.webkit.org/show_bug.cgi?id=37934 + + Instead of counting paints, which are not interchangeable with frames that + the user sees, we now set an arbitrary timer for FPS measurements. The idea is + that if the main thread is delayed for any reason, that timer would be delayed + as well. + + * QtLauncher/QtLauncher.pro: + * QtLauncher/fpstimer.cpp: Added. + (FpsTimer::FpsTimer): + (FpsTimer::numFrames): + (FpsTimer::start): + (FpsTimer::stop): + (FpsTimer::timerEvent): + * QtLauncher/fpstimer.h: Added. + * QtLauncher/webview.cpp: + (WebViewGraphicsBased::setFrameRateMeasurementEnabled): + (WebViewGraphicsBased::updateFrameRate): + (WebViewGraphicsBased::paintEvent): + * QtLauncher/webview.h: + +2010-04-21 Eric Seidel <eric@webkit.org> + + Unreviewed, just adding missing ":" in python file. + + REGRESSION(57531): the commit-queue still hates Tor Arne Vestbø + https://bugs.webkit.org/show_bug.cgi?id=37765 + + new-run-webkit-tests --chromium was borked. + + * Scripts/webkitpy/layout_tests/port/chromium.py: + +2010-04-21 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + REGRESSION(57531): the commit-queue still hates Tor Arne Vestbø + https://bugs.webkit.org/show_bug.cgi?id=37765 + + Third time is the charm. I've fixed all the + new-run-webkit-tests regressions from previous attempts. + + I fixed the queue to not ignore Tor as a reviwer in r57531, + but instead it throws an exception every time his name is in a patch. + + This fixes our Executive.run_command code to work around a Popen + bug http://bugs.python.org/issue5290 whereby python versions before 2.6 + do not correctly handle unicode objects as input or output to + Popen.communicate. + + Following the advice of: + http://farmdev.com/talks/unicode/ + I have changed all of webkitpy to use unicode() objects as strings + instead of str objects (which in Python 3 are renamed "bytes"). + + String literals were left as "foo" instead of converting to u"foo" + as u"foo" is only required if the string has a non-ascii code point. + Python is smart about comparing str() and unicode() values and will + log an error to the console if the comparison is ever invalid. + + Executive.run* now correctly accept and return unicode() objects. + I attempted to fix all the places that we call .write() to make sure we + encode any unicode() objects into utf-8. + + I removed several uses of StringIO. StringIO should generally always be + passed a unicode() value. + + Likewise I replaced most calls to open() with codecs.open(). + codecs.open() matches Python 3 open semantics in requiring an encoding + parameter. Files opened with codecs.open() with a unicode-compatible + encoding will vend unicode() objects from their read() calls, like how + StringIO created with a unicode() object will do. + + I also deployed "with" statements wider (now that the project has + settled on Python 2.5) to close a bunch of file descriptor leaks. + + * Scripts/webkitpy/common/checkout/api_unittest.py: + - Read/write utf-8 files instead of ascii. + - Update the tests to use test for proper unicode() handling. + * Scripts/webkitpy/common/checkout/changelog.py: + - Document that parse_latest_entry_from_file expects + file-like objects which return unicode strings. + * Scripts/webkitpy/common/checkout/changelog_unittest.py: + - Use unicode() strings instead of str() byte arrays. + - Deploy "with" to close file descriptor leaks. + * Scripts/webkitpy/common/checkout/commitinfo.py: + - Remove unneeded import. + * Scripts/webkitpy/common/checkout/scm.py: + - Remove use of str(). + * Scripts/webkitpy/common/checkout/scm_unittest.py: + - Read/write utf-8 files and use unicode() strings in testing. + * Scripts/webkitpy/common/config/committers.py: + - Use \u instead of \x to make slightly clearer what we're doing. + * Scripts/webkitpy/common/net/bugzilla.py: + - Add a new _string_contents() method and explain why + we have to call unicode() on the result of soup.string + and why it's safe to do so w/o needing to pass a codec name. + - Remove the (unused) support for passing a file object to add_patch_to_bug(). + * Scripts/webkitpy/common/net/buildbot.py: + - Use unicode() instead of str() when needing to coax a + NavigableString object into a unicode() object. + * Scripts/webkitpy/common/net/buildbot_unittest.py: + - Add a test which contains a unicode builder name. + * Scripts/webkitpy/common/net/statusserver.py: + - Remove use of str() + * Scripts/webkitpy/common/prettypatch.py: + - Write out the patch file as utf-8. + * Scripts/webkitpy/common/system/autoinstall.py: + - Write out files with a explicit encodings. + - Deploy "with" to close file descriptor leaks. + * Scripts/webkitpy/common/system/deprecated_logging.py: + - Write out log files as utf-8. + * Scripts/webkitpy/common/system/executive.py: + - Make run* properly take and return unicode() objects. + - Cleaned up input handling in run_command a little by adding + a _compute_input() method which can return early instead of having + such a long/cluttered if-block. + * Scripts/webkitpy/common/system/executive_unittest.py: + - Added a unit test to make sure we don't break Tor again! + * Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py: + - Write out the test list as utf-8. + * Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py: + - Write out json files as utf-8. + * Scripts/webkitpy/layout_tests/port/apache_http_server.py: + - Deploy "with" to close file descriptor leaks. + * Scripts/webkitpy/layout_tests/port/chromium.py: Add Executive.py FIXME. + * Scripts/webkitpy/layout_tests/port/chromium_linux.py: ditto. + * Scripts/webkitpy/layout_tests/port/chromium_mac.py: ditto. + * Scripts/webkitpy/layout_tests/port/gtk.py: ditto. + * Scripts/webkitpy/layout_tests/port/mac.py: ditto. + * Scripts/webkitpy/layout_tests/port/mac_unittest.py: + - Make the skipped file parsing test unicode. + * Scripts/webkitpy/layout_tests/port/qt.py: Add Executive.py FIXME. + * Scripts/webkitpy/layout_tests/port/server_process.py: ditto. + * Scripts/webkitpy/layout_tests/port/webkit.py: + - Deploy "with" to close file descriptor leaks. + * Scripts/webkitpy/layout_tests/port/websocket_server.py: + - Make explicit the encodings of log files and pid files. + * Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py: + - Make encodings explicit and deploy "with". + * Scripts/webkitpy/layout_tests/run_webkit_tests.py: ditto. + * Scripts/webkitpy/layout_tests/test_types/image_diff.py: ditto. + * Scripts/webkitpy/layout_tests/test_types/test_type_base.py: ditto. + * Scripts/webkitpy/layout_tests/test_types/text_diff.py: ditto. + * Scripts/webkitpy/style/filereader_unittest.py: ditto. + * Scripts/webkitpy/thirdparty/__init__.py: ditto. + * Scripts/webkitpy/tool/commands/earlywarningsystem.py: + - Removed extra import. + * Scripts/webkitpy/tool/commands/queues.py: + - No need to map args to strings now that run_command does. + - Update test results to match args changes. + - Document our global argument hacks. + * Scripts/webkitpy/tool/commands/upload.py: + - Pass the diff directly to add_patch_to_bug instead of creating a StringIO file wrapper. + * Scripts/webkitpy/tool/mocktool.py: + - Rename add_patch_to_bug argument to match bugzilla.py + * Scripts/webkitpy/tool/steps/abstractstep.py: + - Executive.run_* now require lists instead of strings. + The lack of this change was what broke webkit-patch + for svn users the first time this was landed. + * Scripts/webkitpy/tool/steps/postdiff.py: + - Pass the diff directly to add_patch_to_bug instead of creating a StringIO file wrapper. + * Scripts/webkitpy/tool/steps/postdiffforcommit.py: ditto + * Scripts/webkitpy/tool/steps/postdiffforrevert.py: ditto + * Scripts/webkitpy/tool/steps/steps_unittest.py: + - Fixed spurious logging seen when running test-webkitpy + 2010-04-21 Chris Fleizach <cfleizach@apple.com> Reviewed by Alexey Proskuryakov. diff --git a/WebKitTools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp b/WebKitTools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp index 82b8671..7167bf2 100644 --- a/WebKitTools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp +++ b/WebKitTools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp @@ -87,7 +87,6 @@ '.', '<(webkit_api_dir)', '<(webkit_top)/JavaScriptCore', - '<(webkit_top)/WebKit/mac/WebCoreSupport', # For WebSystemInterface.h '<(chromium_src_dir)', ], 'defines': [ @@ -125,29 +124,51 @@ '../chromium/WebViewHost.cpp', '../chromium/WebViewHost.h', ], - 'mac_bundle_resources': [ - '../qt/fonts/AHEM____.TTF', - '../fonts/WebKitWeightWatcher100.ttf', - '../fonts/WebKitWeightWatcher200.ttf', - '../fonts/WebKitWeightWatcher300.ttf', - '../fonts/WebKitWeightWatcher400.ttf', - '../fonts/WebKitWeightWatcher500.ttf', - '../fonts/WebKitWeightWatcher600.ttf', - '../fonts/WebKitWeightWatcher700.ttf', - '../fonts/WebKitWeightWatcher800.ttf', - '../fonts/WebKitWeightWatcher900.ttf', - ], 'conditions': [ ['OS=="mac"', { 'dependencies': ['LayoutTestHelper'], - }], - ], + 'mac_bundle_resources': [ + '../qt/fonts/AHEM____.TTF', + '../fonts/WebKitWeightWatcher100.ttf', + '../fonts/WebKitWeightWatcher200.ttf', + '../fonts/WebKitWeightWatcher300.ttf', + '../fonts/WebKitWeightWatcher400.ttf', + '../fonts/WebKitWeightWatcher500.ttf', + '../fonts/WebKitWeightWatcher600.ttf', + '../fonts/WebKitWeightWatcher700.ttf', + '../fonts/WebKitWeightWatcher800.ttf', + '../fonts/WebKitWeightWatcher900.ttf', + ], + 'actions': [ + { + 'action_name': 'repack_locale', + 'variables': { + 'repack_path': '<(chromium_src_dir)/tools/data_pack/repack.py', + 'pak_inputs': [ + '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_chromium_resources.pak', + '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_strings_en-US.pak', + '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_resources.pak', + ]}, + 'inputs': [ + '<(repack_path)', + '<@(pak_inputs)', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/repack/DumpRenderTree.pak', + ], + 'action': ['python', '<(repack_path)', '<@(_outputs)', '<@(pak_inputs)'], + 'process_outputs_as_mac_bundle_resources': 1, + }, + ], # actions + }], # mac + ], # conditions }, { 'target_name': 'ImageDiff', 'type': 'executable', 'dependencies': [ + '<(webkit_api_dir)/WebKit.gyp:webkit', '<(webkit_top)/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp:wtf', '<(chromium_src_dir)/gfx/gfx.gyp:gfx', ], diff --git a/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/Atomics.h b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/Atomics.h new file mode 100644 index 0000000..37b1892 --- /dev/null +++ b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/Atomics.h @@ -0,0 +1 @@ +#include <JavaScriptCore/Atomics.h> diff --git a/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/MainThread.h b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/MainThread.h new file mode 100644 index 0000000..ff75971 --- /dev/null +++ b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/MainThread.h @@ -0,0 +1 @@ +#include <JavaScriptCore/MainThread.h> diff --git a/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/ThreadSafeShared.h b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/ThreadSafeShared.h new file mode 100644 index 0000000..4a7a77f --- /dev/null +++ b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/ThreadSafeShared.h @@ -0,0 +1 @@ +#include <JavaScriptCore/ThreadSafeShared.h> diff --git a/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/ThreadingPrimitives.h b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/ThreadingPrimitives.h new file mode 100644 index 0000000..a7ee117 --- /dev/null +++ b/WebKitTools/DumpRenderTree/ForwardingHeaders/wtf/ThreadingPrimitives.h @@ -0,0 +1 @@ +#include <JavaScriptCore/ThreadingPrimitives.h> diff --git a/WebKitTools/DumpRenderTree/LayoutTestController.cpp b/WebKitTools/DumpRenderTree/LayoutTestController.cpp index a736160..f564afa 100644 --- a/WebKitTools/DumpRenderTree/LayoutTestController.cpp +++ b/WebKitTools/DumpRenderTree/LayoutTestController.cpp @@ -56,6 +56,7 @@ LayoutTestController::LayoutTestController(const std::string& testPathOrURL, con , m_dumpSourceAsWebArchive(false) , m_dumpStatusCallbacks(false) , m_dumpTitleChanges(false) + , m_dumpIconChanges(false) , m_dumpVisitedLinksCallback(false) , m_dumpWillCacheResponse(false) , m_callCloseOnWebViews(true) @@ -75,6 +76,7 @@ LayoutTestController::LayoutTestController(const std::string& testPathOrURL, con , m_isGeolocationPermissionSet(false) , m_geolocationPermission(false) , m_handlesAuthenticationChallenges(false) + , m_isPrinting(false) , m_testPathOrURL(testPathOrURL) , m_expectedPixelHash(expectedPixelHash) { @@ -187,6 +189,13 @@ static JSValueRef dumpTitleChangesCallback(JSContextRef context, JSObjectRef fun return JSValueMakeUndefined(context); } +static JSValueRef dumpIconChangesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setDumpIconChanges(true); + return JSValueMakeUndefined(context); +} + static JSValueRef dumpWillCacheResponseCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); @@ -928,6 +937,18 @@ static JSValueRef setPrivateBrowsingEnabledCallback(JSContextRef context, JSObje return JSValueMakeUndefined(context); } +static JSValueRef setJavaScriptCanAccessClipboardCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setJavaScriptCanAccessClipboard(JSValueToBoolean(context, arguments[0])); + + return JSValueMakeUndefined(context); +} + static JSValueRef setXSSAuditorEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { // Has mac & windows implementation @@ -951,6 +972,13 @@ static JSValueRef setSpatialNavigationEnabledCallback(JSContextRef context, JSOb return JSValueMakeUndefined(context); } +static JSValueRef setPrintingCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setIsPrinting(true); + return JSValueMakeUndefined(context); +} + static JSValueRef setFrameFlatteningEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { @@ -1133,6 +1161,18 @@ static JSValueRef setPopupBlockingEnabledCallback(JSContextRef context, JSObject return JSValueMakeUndefined(context); } +static JSValueRef setPluginsEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setPluginsEnabled(JSValueToBoolean(context, arguments[0])); + + return JSValueMakeUndefined(context); +} + static JSValueRef setSmartInsertDeleteEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { if (argumentCount < 1) @@ -1515,6 +1555,7 @@ JSStaticFunction* LayoutTestController::staticFunctions() { "dumpSourceAsWebArchive", dumpSourceAsWebArchiveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "dumpStatusCallbacks", dumpStatusCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "dumpTitleChanges", dumpTitleChangesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "dumpIconChanges", dumpIconChangesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "dumpWillCacheResponse", dumpWillCacheResponseCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "elementDoesAutoCompleteForElementWithId", elementDoesAutoCompleteForElementWithIdCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "encodeHostName", encodeHostNameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -1573,6 +1614,8 @@ JSStaticFunction* LayoutTestController::staticFunctions() { "setPOSIXLocale", setPOSIXLocaleCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setPersistentUserStyleSheetLocation", setPersistentUserStyleSheetLocationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setPopupBlockingEnabled", setPopupBlockingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setPluginsEnabled", setPluginsEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setPrinting", setPrintingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setPrivateBrowsingEnabled", setPrivateBrowsingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setSelectTrailingWhitespaceEnabled", setSelectTrailingWhitespaceEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setSmartInsertDeleteEnabled", setSmartInsertDeleteEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -1588,6 +1631,7 @@ JSStaticFunction* LayoutTestController::staticFunctions() { "setWillSendRequestReturnsNull", setWillSendRequestReturnsNullCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setWillSendRequestReturnsNullOnRedirect", setWillSendRequestReturnsNullOnRedirectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setWindowIsKey", setWindowIsKeyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setJavaScriptCanAccessClipboard", setJavaScriptCanAccessClipboardCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setXSSAuditorEnabled", setXSSAuditorEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "showWebInspector", showWebInspectorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "testOnscreen", testOnscreenCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, diff --git a/WebKitTools/DumpRenderTree/LayoutTestController.h b/WebKitTools/DumpRenderTree/LayoutTestController.h index 198a9f3..c6da2ff 100644 --- a/WebKitTools/DumpRenderTree/LayoutTestController.h +++ b/WebKitTools/DumpRenderTree/LayoutTestController.h @@ -81,10 +81,12 @@ public: void setDomainRelaxationForbiddenForURLScheme(bool forbidden, JSStringRef scheme); void setIconDatabaseEnabled(bool iconDatabaseEnabled); void setJavaScriptProfilingEnabled(bool profilingEnabled); + void setJavaScriptCanAccessClipboard(bool flag); void setMainFrameIsFirstResponder(bool flag); void setMockGeolocationError(int code, JSStringRef message); void setMockGeolocationPosition(double latitude, double longitude, double accuracy); void setPersistentUserStyleSheetLocation(JSStringRef path); + void setPluginsEnabled(bool flag); void setPopupBlockingEnabled(bool flag); void setPrivateBrowsingEnabled(bool flag); void setSelectTrailingWhitespaceEnabled(bool flag); @@ -156,6 +158,9 @@ public: bool dumpTitleChanges() const { return m_dumpTitleChanges; } void setDumpTitleChanges(bool dumpTitleChanges) { m_dumpTitleChanges = dumpTitleChanges; } + bool dumpIconChanges() const { return m_dumpIconChanges; } + void setDumpIconChanges(bool dumpIconChanges) { m_dumpIconChanges = dumpIconChanges; } + bool dumpVisitedLinksCallback() const { return m_dumpVisitedLinksCallback; } void setDumpVisitedLinksCallback(bool dumpVisitedLinksCallback) { m_dumpVisitedLinksCallback = dumpVisitedLinksCallback; } @@ -208,6 +213,9 @@ public: bool handlesAuthenticationChallenges() const { return m_handlesAuthenticationChallenges; } void setHandlesAuthenticationChallenges(bool handlesAuthenticationChallenges) { m_handlesAuthenticationChallenges = handlesAuthenticationChallenges; } + bool isPrinting() const { return m_isPrinting; } + void setIsPrinting(bool isPrinting) { m_isPrinting = isPrinting; } + const std::string& authenticationUsername() const { return m_authenticationUsername; } void setAuthenticationUsername(std::string username) { m_authenticationUsername = username; } @@ -278,6 +286,7 @@ private: bool m_dumpSourceAsWebArchive; bool m_dumpStatusCallbacks; bool m_dumpTitleChanges; + bool m_dumpIconChanges; bool m_dumpVisitedLinksCallback; bool m_dumpWillCacheResponse; bool m_callCloseOnWebViews; @@ -297,6 +306,7 @@ private: bool m_isGeolocationPermissionSet; bool m_geolocationPermission; bool m_handlesAuthenticationChallenges; + bool m_isPrinting; std::string m_authenticationUsername; std::string m_authenticationPassword; diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp index 7d388d0..83f420f 100644 --- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/PluginObject.cpp @@ -357,7 +357,7 @@ static NPIdentifier stringVariantToIdentifier(NPVariant variant) static NPIdentifier int32VariantToIdentifier(NPVariant variant) { assert(NPVARIANT_IS_INT32(variant)); - int32 integer = NPVARIANT_TO_INT32(variant); + int32_t integer = NPVARIANT_TO_INT32(variant); return browser->getintidentifier(integer); } @@ -366,7 +366,7 @@ static NPIdentifier doubleVariantToIdentifier(NPVariant variant) assert(NPVARIANT_IS_DOUBLE(variant)); double value = NPVARIANT_TO_DOUBLE(variant); // Sadly there is no "getdoubleidentifier" - int32 integer = static_cast<int32>(value); + int32_t integer = static_cast<int32_t>(value); return browser->getintidentifier(integer); } @@ -402,7 +402,7 @@ static bool testIdentifierToInt(PluginObject*, const NPVariant* args, uint32_t a NPIdentifier identifier = variantToIdentifier(args[0]); if (!identifier) return false; - int32 integer = browser->intfromidentifier(identifier); + int32_t integer = browser->intfromidentifier(identifier); INT32_TO_NPVARIANT(integer, *result); return true; } @@ -552,7 +552,7 @@ static bool testGetIntIdentifier(PluginObject*, const NPVariant* args, uint32_t return false; NPIdentifier identifier = browser->getintidentifier((int)NPVARIANT_TO_DOUBLE(args[0])); - INT32_TO_NPVARIANT((int32)(long long)identifier, *result); + INT32_TO_NPVARIANT((int32_t)(long long)identifier, *result); return true; } diff --git a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/main.cpp b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/main.cpp index a552774..eff9c1c 100644 --- a/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/main.cpp +++ b/WebKitTools/DumpRenderTree/TestNetscapePlugIn.subproj/main.cpp @@ -66,7 +66,7 @@ void NP_Shutdown(void) static void executeScript(const PluginObject* obj, const char* script); -NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char *argn[], char *argv[], NPSavedData *saved) +NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char *argn[], char *argv[], NPSavedData *saved) { bool forceCarbon = false; @@ -219,7 +219,7 @@ static void executeScript(const PluginObject* obj, const char* script) browser->releasevariantvalue(&browserResult); } -NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype) +NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16_t *stype) { PluginObject* obj = static_cast<PluginObject*>(instance->pdata); obj->stream = stream; @@ -252,12 +252,12 @@ NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) return NPERR_NO_ERROR; } -int32 NPP_WriteReady(NPP instance, NPStream *stream) +int32_t NPP_WriteReady(NPP instance, NPStream *stream) { return 0; } -int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer) +int32_t NPP_Write(NPP instance, NPStream *stream, int32_t offset, int32_t len, void *buffer) { return 0; } @@ -401,7 +401,7 @@ static int16_t handleEventCocoa(NPP instance, PluginObject* obj, NPCocoaEvent* e return 0; } -int16 NPP_HandleEvent(NPP instance, void *event) +int16_t NPP_HandleEvent(NPP instance, void *event) { PluginObject* obj = static_cast<PluginObject*>(instance->pdata); if (!obj->eventLogging) diff --git a/WebKitTools/DumpRenderTree/chromium/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/chromium/DumpRenderTree.cpp index c81480f..a964518 100644 --- a/WebKitTools/DumpRenderTree/chromium/DumpRenderTree.cpp +++ b/WebKitTools/DumpRenderTree/chromium/DumpRenderTree.cpp @@ -33,9 +33,6 @@ #include "TestShell.h" #include "webkit/support/webkit_support.h" #include <wtf/Vector.h> -#if OS(MAC_OS_X) -#include "WebSystemInterface.h" -#endif using namespace std; @@ -61,10 +58,6 @@ static void runTest(TestShell& shell, TestParams& params, const string& testName int main(int argc, char* argv[]) { -#if OS(MAC_OS_X) - // Need to call before instantiate WebKitClient. - InitWebCoreSystemInterface(); -#endif webkit_support::SetUpTestEnvironment(); TestParams params; diff --git a/WebKitTools/DumpRenderTree/chromium/ImageDiff.cpp b/WebKitTools/DumpRenderTree/chromium/ImageDiff.cpp index 81d5f62..27e9946 100644 --- a/WebKitTools/DumpRenderTree/chromium/ImageDiff.cpp +++ b/WebKitTools/DumpRenderTree/chromium/ImageDiff.cpp @@ -40,11 +40,15 @@ #include <algorithm> #include <stdio.h> #include <string.h> -#include <string> #include <vector> #include <wtf/OwnArrayPtr.h> #include <wtf/Vector.h> +#if OS(WINDOWS) +#include <windows.h> +#define PATH_MAX MAX_PATH +#endif + using namespace gfx; using namespace std; diff --git a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp index d0dca69..21b168c 100644 --- a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp +++ b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp @@ -139,6 +139,7 @@ LayoutTestController::LayoutTestController(TestShell* shell) bindMethod("setPrivateBrowsingEnabled", &LayoutTestController::setPrivateBrowsingEnabled); bindMethod("setUseDashboardCompatibilityMode", &LayoutTestController::setUseDashboardCompatibilityMode); + bindMethod("setJavaScriptCanAccessClipboard", &LayoutTestController::setJavaScriptCanAccessClipboard); bindMethod("setXSSAuditorEnabled", &LayoutTestController::setXSSAuditorEnabled); bindMethod("evaluateScriptInIsolatedWorld", &LayoutTestController::evaluateScriptInIsolatedWorld); bindMethod("overridePreference", &LayoutTestController::overridePreference); @@ -881,6 +882,13 @@ void LayoutTestController::setPrivateBrowsingEnabled(const CppArgumentList& argu result->setNull(); } +void LayoutTestController::setJavaScriptCanAccessClipboard(const CppArgumentList& arguments, CppVariant* result) +{ + if (arguments.size() > 0 && arguments[0].isBool()) + m_shell->webView()->settings()->setJavaScriptCanAccessClipboard(arguments[0].value.boolValue); + result->setNull(); +} + void LayoutTestController::setXSSAuditorEnabled(const CppArgumentList& arguments, CppVariant* result) { if (arguments.size() > 0 && arguments[0].isBool()) @@ -1007,6 +1015,8 @@ void LayoutTestController::overridePreference(const CppArgumentList& arguments, settings->setJavaEnabled(cppVariantToBool(value)); else if (key == "WebKitUsesPageCachePreferenceKey") settings->setUsesPageCache(cppVariantToBool(value)); + else if (key == "WebKitJavaScriptCanAccessClipboard") + settings->setJavaScriptCanAccessClipboard(cppVariantToBool(value)); else if (key == "WebKitXSSAuditorEnabled") settings->setXSSAuditorEnabled(cppVariantToBool(value)); else if (key == "WebKitLocalStorageEnabledPreferenceKey") diff --git a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h index a8639da..ca8b014 100644 --- a/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h +++ b/WebKitTools/DumpRenderTree/chromium/LayoutTestController.h @@ -213,6 +213,7 @@ public: void setCallCloseOnWebViews(const CppArgumentList&, CppVariant*); void setPrivateBrowsingEnabled(const CppArgumentList&, CppVariant*); + void setJavaScriptCanAccessClipboard(const CppArgumentList&, CppVariant*); void setXSSAuditorEnabled(const CppArgumentList&, CppVariant*); void evaluateScriptInIsolatedWorld(const CppArgumentList&, CppVariant*); void overridePreference(const CppArgumentList&, CppVariant*); diff --git a/WebKitTools/DumpRenderTree/chromium/TestShell.cpp b/WebKitTools/DumpRenderTree/chromium/TestShell.cpp index d2bc110..e4229fe 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestShell.cpp +++ b/WebKitTools/DumpRenderTree/chromium/TestShell.cpp @@ -138,6 +138,7 @@ void TestShell::resetWebSettings(WebView& webView) settings->setMinimumFontSize(1); settings->setMinimumLogicalFontSize(9); settings->setJavaScriptCanOpenWindowsAutomatically(true); + settings->setJavaScriptCanAccessClipboard(true); settings->setDOMPasteAllowed(true); settings->setDeveloperExtrasEnabled(false); settings->setNeedsSiteSpecificQuirks(true); @@ -540,7 +541,7 @@ string TestShell::dumpImage(skia::PlatformCanvas* canvas, const string& expected static_cast<int>(sourceBitmap.rowBytes()), discardTransparency, &png); printf("Content-Type: image/png\n"); - printf("Content-Length: %u\n", png.size()); + printf("Content-Length: %lu\n", png.size()); // Write to disk. if (fwrite(&png[0], 1, png.size(), stdout) != png.size()) FATAL("Short write to stdout.\n"); diff --git a/WebKitTools/DumpRenderTree/chromium/TestWebWorker.h b/WebKitTools/DumpRenderTree/chromium/TestWebWorker.h index 899514e..f28cc20 100644 --- a/WebKitTools/DumpRenderTree/chromium/TestWebWorker.h +++ b/WebKitTools/DumpRenderTree/chromium/TestWebWorker.h @@ -79,6 +79,7 @@ public: } virtual WebKit::WebWorker* createWorker(WebKit::WebWorkerClient*) { return 0; } virtual WebKit::WebNotificationPresenter* notificationPresenter() { return 0; } + virtual WebKit::WebApplicationCacheHost* createApplicationCacheHost(WebKit::WebApplicationCacheHostClient*) { return 0; } private: ~TestWebWorker() {} diff --git a/WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp b/WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp index 95b1c7e..6ea1de1 100644 --- a/WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp +++ b/WebKitTools/DumpRenderTree/chromium/WebViewHost.cpp @@ -840,14 +840,19 @@ void WebViewHost::didFinishLoad(WebFrame* frame) locationChangeDone(frame); } -void WebViewHost::didChangeLocationWithinPage(WebFrame* frame, bool isNewNavigation) +void WebViewHost::didNavigateWithinPage(WebFrame* frame, bool isNewNavigation) { frame->dataSource()->setExtraData(m_pendingExtraData.release()); + + updateForCommittedLoad(frame, isNewNavigation); +} + +void WebViewHost::didChangeLocationWithinPage(WebFrame* frame) +{ if (m_shell->shouldDumpFrameLoadCallbacks()) { printFrameDescription(frame); fputs(" - didChangeLocationWithinPageForFrame\n", stdout); } - updateForCommittedLoad(frame, isNewNavigation); } void WebViewHost::assignIdentifierToRequest(WebFrame*, unsigned identifier, const WebURLRequest& request) @@ -867,7 +872,7 @@ void WebViewHost::willSendRequest(WebFrame*, unsigned identifier, WebURLRequest& GURL mainDocumentURL = request.firstPartyForCookies(); printResourceDescription(identifier); printf(" - willSendRequest <NSURLRequest URL %s, main document URL %s," - " http method %s> redirectResponse %s\n", + " http method %s> redirectResponse ", descriptionSuitableForTestResult(requestURL).c_str(), URLDescription(mainDocumentURL).c_str(), request.httpMethod().utf8().data()); diff --git a/WebKitTools/DumpRenderTree/chromium/WebViewHost.h b/WebKitTools/DumpRenderTree/chromium/WebViewHost.h index fd1e0f5..c5bed7a 100644 --- a/WebKitTools/DumpRenderTree/chromium/WebViewHost.h +++ b/WebKitTools/DumpRenderTree/chromium/WebViewHost.h @@ -163,7 +163,8 @@ class WebViewHost : public WebKit::WebViewClient, public WebKit::WebFrameClient, virtual void didHandleOnloadEvents(WebKit::WebFrame*); virtual void didFailLoad(WebKit::WebFrame*, const WebKit::WebURLError&); virtual void didFinishLoad(WebKit::WebFrame*); - virtual void didChangeLocationWithinPage(WebKit::WebFrame*, bool isNewNavigation); + virtual void didNavigateWithinPage(WebKit::WebFrame*, bool isNewNavigation); + virtual void didChangeLocationWithinPage(WebKit::WebFrame*); virtual void assignIdentifierToRequest(WebKit::WebFrame*, unsigned identifier, const WebKit::WebURLRequest&); virtual void willSendRequest(WebKit::WebFrame*, unsigned identifier, WebKit::WebURLRequest&, const WebKit::WebURLResponse&); virtual void didReceiveResponse(WebKit::WebFrame*, unsigned identifier, const WebKit::WebURLResponse&); diff --git a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp index e37613d..0f3ca38 100644 --- a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp +++ b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp @@ -325,6 +325,7 @@ static void resetDefaultsToConsistentValues() "enable-html5-local-storage", TRUE, "enable-xss-auditor", FALSE, "enable-spatial-navigation", FALSE, + "javascript-can-access-clipboard", TRUE, "javascript-can-open-windows-automatically", TRUE, "enable-offline-web-application-cache", TRUE, "enable-universal-access-from-file-uris", TRUE, diff --git a/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp b/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp index 58d2631..4ffab88 100644 --- a/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp +++ b/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp @@ -362,6 +362,15 @@ void LayoutTestController::setPrivateBrowsingEnabled(bool flag) g_object_set(G_OBJECT(settings), "enable-private-browsing", flag, NULL); } +void LayoutTestController::setJavaScriptCanAccessClipboard(bool flag) +{ + WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); + ASSERT(view); + + WebKitWebSettings* settings = webkit_web_view_get_settings(view); + g_object_set(G_OBJECT(settings), "javascript-can-access-clipboard", flag, NULL); +} + void LayoutTestController::setXSSAuditorEnabled(bool flag) { WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); @@ -457,6 +466,11 @@ void LayoutTestController::setPopupBlockingEnabled(bool flag) } +void LayoutTestController::setPluginsEnabled(bool flag) +{ + // FIXME: Implement +} + bool LayoutTestController::elementDoesAutoCompleteForElementWithId(JSStringRef id) { // FIXME: implement diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm index 0210cf0..25b9f4f 100644 --- a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm @@ -427,10 +427,12 @@ static void resetDefaultsToConsistentValues() [preferences setXSSAuditorEnabled:NO]; [preferences setExperimentalNotificationsEnabled:NO]; [preferences setPluginAllowedRunTime:1]; + [preferences setPlugInsEnabled:YES]; [preferences setPrivateBrowsingEnabled:NO]; [preferences setAuthorAndUserStylesEnabled:YES]; [preferences setJavaScriptCanOpenWindowsAutomatically:YES]; + [preferences setJavaScriptCanAccessClipboard:YES]; [preferences setOfflineWebApplicationCacheEnabled:YES]; [preferences setDeveloperExtrasEnabled:NO]; [preferences setLoadsImagesAutomatically:YES]; @@ -1085,7 +1087,7 @@ void dump() resultMimeType = @"application/x-webarchive"; } else { sizeWebViewForCurrentTest(); - resultString = [mainFrame renderTreeAsExternalRepresentation]; + resultString = [mainFrame renderTreeAsExternalRepresentationForPrinting:gLayoutTestController->isPrinting()]; } if (resultString && !resultData) @@ -1116,6 +1118,7 @@ void dump() } if (dumpPixels && !dumpAsText) + // FIXME: when isPrinting is set, dump the image with page separators. dumpWebViewAsPixelsAndCompareWithExpected(gLayoutTestController->expectedPixelHash()); puts("#EOF"); // terminate the (possibly empty) pixels block diff --git a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm index e62e411..29a5812 100644 --- a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm +++ b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm @@ -371,6 +371,16 @@ void LayoutTestController::setPopupBlockingEnabled(bool popupBlockingEnabled) [[[mainFrame webView] preferences] setJavaScriptCanOpenWindowsAutomatically:!popupBlockingEnabled]; } +void LayoutTestController::setPluginsEnabled(bool pluginsEnabled) +{ + [[[mainFrame webView] preferences] setPlugInsEnabled:pluginsEnabled]; +} + +void LayoutTestController::setJavaScriptCanAccessClipboard(bool enabled) +{ + [[[mainFrame webView] preferences] setJavaScriptCanAccessClipboard:enabled]; +} + void LayoutTestController::setTabKeyCyclesThroughElements(bool cycles) { [[mainFrame webView] setTabKeyCyclesThroughElements:cycles]; diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp index 2c2db92..9d2a065 100644 --- a/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp +++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp @@ -148,13 +148,14 @@ WebPage::WebPage(QObject* parent, DumpRenderTree* drt) globalSettings->setFontSize(QWebSettings::DefaultFixedFontSize, 13); globalSettings->setAttribute(QWebSettings::JavascriptCanOpenWindows, true); - globalSettings->setAttribute(QWebSettings::JavascriptCanAccessClipboard, true); + globalSettings->setAttribute(QWebSettings::DOMPasteAllowed, true); globalSettings->setAttribute(QWebSettings::LinksIncludedInFocusChain, false); globalSettings->setAttribute(QWebSettings::PluginsEnabled, true); globalSettings->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true); globalSettings->setAttribute(QWebSettings::JavascriptEnabled, true); globalSettings->setAttribute(QWebSettings::PrivateBrowsingEnabled, false); globalSettings->setAttribute(QWebSettings::SpatialNavigationEnabled, false); + globalSettings->setAttribute(QWebSettings::JavaScriptCanAccessClipboard, true); connect(this, SIGNAL(geometryChangeRequested(const QRect &)), this, SLOT(setViewGeometry(const QRect & ))); @@ -190,6 +191,7 @@ void WebPage::resetSettings() settings()->resetAttribute(QWebSettings::OfflineWebApplicationCacheEnabled); settings()->resetAttribute(QWebSettings::LocalContentCanAccessRemoteUrls); settings()->resetAttribute(QWebSettings::PluginsEnabled); + settings()->resetAttribute(QWebSettings::JavaScriptCanAccessClipboard); m_drt->layoutTestController()->setCaretBrowsingEnabled(false); m_drt->layoutTestController()->setFrameFlatteningEnabled(false); diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp index b95fe23..3f92b8a 100644 --- a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp +++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp @@ -37,7 +37,6 @@ #include <QLocale> #include <qwebsettings.h> -extern void qt_wrt_setViewMode(QWebPage* page, const QString& mode); extern void qt_dump_editing_callbacks(bool b); extern void qt_dump_frame_loader(bool b); extern void qt_dump_resource_load_callbacks(bool b); @@ -141,7 +140,7 @@ QString LayoutTestController::counterValueForElementById(const QString& id) void LayoutTestController::setViewModeMediaFeature(const QString& mode) { - qt_wrt_setViewMode(m_drt->webPage(), mode); + m_drt->webPage()->setProperty("_q_viewMode", mode); } int LayoutTestController::webHistoryItemCount() @@ -394,6 +393,11 @@ void LayoutTestController::setPopupBlockingEnabled(bool enable) m_drt->webPage()->settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, !enable); } +void LayoutTestController::setPluginsEnabled(bool flag) +{ + // FIXME: Implement +} + void LayoutTestController::setPOSIXLocale(const QString& locale) { QLocale qlocale(locale); @@ -410,6 +414,11 @@ void LayoutTestController::setMainFrameIsFirstResponder(bool isFirst) //FIXME: only need this for the moment: https://bugs.webkit.org/show_bug.cgi?id=32990 } +void LayoutTestController::setJavaScriptCanAccessClipboard(bool enable) +{ + m_drt->webPage()->settings()->setAttribute(QWebSettings::JavaScriptCanAccessClipboard, enable); +} + void LayoutTestController::setXSSAuditorEnabled(bool enable) { // Set XSSAuditingEnabled globally so that windows created by the test inherit it too. diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h index df645e1..44b80b7 100644 --- a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h +++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h @@ -139,11 +139,13 @@ public slots: void setFixedContentsSize(int width, int height); void setPrivateBrowsingEnabled(bool enable); void setSpatialNavigationEnabled(bool enabled); + void setPluginsEnabled(bool flag); void setPopupBlockingEnabled(bool enable); void setPOSIXLocale(const QString& locale); void resetLoadFinished() { m_loadFinished = false; } void setWindowIsKey(bool isKey); void setMainFrameIsFirstResponder(bool isFirst); + void setJavaScriptCanAccessClipboard(bool enable); void setXSSAuditorEnabled(bool enable); void setCaretBrowsingEnabled(bool enable); void setViewModeMediaFeature(const QString& mode); diff --git a/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.cpp b/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.cpp index 7b8f120..e0c9b61 100644 --- a/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.cpp +++ b/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.cpp @@ -28,8 +28,10 @@ */ #include "config.h" #include "TextInputControllerQt.h" +#include "../../../WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h" #include <QApplication> +#include <QInputMethodEvent> #include <QKeyEvent> TextInputController::TextInputController(QWebPage* parent) @@ -127,3 +129,32 @@ void TextInputController::doCommand(const QString& command) QKeyEvent event2(QEvent::KeyRelease, keycode, modifiers); QApplication::sendEvent(parent(), &event2); } + +void TextInputController::setMarkedText(const QString& string, int start, int end) +{ + QList<QInputMethodEvent::Attribute> attributes; +#if QT_VERSION >= 0x040600 + QInputMethodEvent::Attribute selection(QInputMethodEvent::Selection, start, end, QVariant()); + attributes << selection; +#endif + QInputMethodEvent event(string, attributes); + QApplication::sendEvent(parent(), &event); +} + +void TextInputController::insertText(const QString& string) +{ + QList<QInputMethodEvent::Attribute> attributes; + QInputMethodEvent event(string, attributes); + event.setCommitString(string); + QApplication::sendEvent(parent(), &event); +} + +QVariantList TextInputController::selectedRange() +{ + return DumpRenderTreeSupportQt::selectedRange(qobject_cast<QWebPage*>(parent())); +} + +QVariantList TextInputController::firstRectForCharacterRange(int location, int length) +{ + return DumpRenderTreeSupportQt::firstRectForCharacterRange(qobject_cast<QWebPage*>(parent()), location, length); +} diff --git a/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.h b/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.h index 7c7433e..0210984 100644 --- a/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.h +++ b/WebKitTools/DumpRenderTree/qt/TextInputControllerQt.h @@ -31,6 +31,7 @@ #include <QList> #include <QObject> +#include <QVariant> #include <QString> #include "qwebpage.h" @@ -41,14 +42,14 @@ public: public slots: void doCommand(const QString& command); -// void setMarkedText(const QString& str, int from, int length); + void setMarkedText(const QString& string, int start, int end); // bool hasMarkedText(); // void unmarkText(); // QList<int> markedRange(); -// QList<int> selectedRange(); + QVariantList selectedRange(); // void validAttributesForMarkedText(); -// void inserText(const QString&); -// void firstRectForCharacterRange(); + void insertText(const QString& string); + QVariantList firstRectForCharacterRange(int location, int length); // void characterIndexForPoint(int, int); // void substringFromRange(int, int); // void conversationIdentifier(); diff --git a/WebKitTools/DumpRenderTree/unix/TestNetscapePlugin/TestNetscapePlugin.cpp b/WebKitTools/DumpRenderTree/unix/TestNetscapePlugin/TestNetscapePlugin.cpp index a3c6773..e960a06 100644 --- a/WebKitTools/DumpRenderTree/unix/TestNetscapePlugin/TestNetscapePlugin.cpp +++ b/WebKitTools/DumpRenderTree/unix/TestNetscapePlugin/TestNetscapePlugin.cpp @@ -171,7 +171,7 @@ webkit_test_plugin_new_stream(NPP instance, NPMIMEType /*type*/, NPStream *stream, NPBool /*seekable*/, - uint16* stype) + uint16_t* stype) { PluginObject* obj = static_cast<PluginObject*>(instance->pdata); obj->stream = stream; @@ -210,13 +210,13 @@ webkit_test_plugin_stream_as_file(NPP /*instance*/, NPStream* /*stream*/, const { } -static int32 +static int32_t webkit_test_plugin_write_ready(NPP /*instance*/, NPStream* /*stream*/) { return 0; } -static int32 +static int32_t webkit_test_plugin_write(NPP /*instance*/, NPStream* /*stream*/, int32_t /*offset*/, diff --git a/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp index f9b40d1..e96adae 100644 --- a/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp +++ b/WebKitTools/DumpRenderTree/win/DumpRenderTree.cpp @@ -795,6 +795,7 @@ static void resetDefaultsToConsistentValues(IWebPreferences* preferences) prefsPrivate->setDeveloperExtrasEnabled(FALSE); prefsPrivate->setExperimentalNotificationsEnabled(TRUE); prefsPrivate->setShouldPaintNativeControls(FALSE); // FIXME - need to make DRT pass with Windows native controls <http://bugs.webkit.org/show_bug.cgi?id=25592> + prefsPrivate->setJavaScriptCanAccessClipboard(TRUE); prefsPrivate->setXSSAuditorEnabled(FALSE); prefsPrivate->setFrameFlatteningEnabled(FALSE); prefsPrivate->setOfflineWebApplicationCacheEnabled(TRUE); @@ -1259,6 +1260,7 @@ int main(int argc, char* argv[]) standardPreferencesPrivate->setShouldPaintNativeControls(FALSE); standardPreferences->setJavaScriptEnabled(TRUE); standardPreferences->setDefaultFontSize(16); + standardPreferences->setAcceleratedCompositingEnabled(true); if (printSupportedFeatures) { BOOL acceleratedCompositingAvailable; diff --git a/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.cpp b/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.cpp index 29f99ab..cf4d221 100644 --- a/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.cpp +++ b/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.cpp @@ -189,6 +189,16 @@ HRESULT STDMETHODCALLTYPE FrameLoadDelegate::didReceiveTitle( return S_OK; } +HRESULT STDMETHODCALLTYPE FrameLoadDelegate::didChangeIcons( + /* [in] */ IWebView* webView, + /* [in] */ IWebFrame* frame) +{ + if (!done && gLayoutTestController->dumpIconChanges()) + printf("%s - didChangeIcons\n", descriptionSuitableForTestResult(frame).c_str()); + + return S_OK; +} + void FrameLoadDelegate::processWork() { // if another load started, then wait for it to complete. diff --git a/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.h b/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.h index 329c17f..4cd5e11 100644 --- a/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.h +++ b/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.h @@ -74,6 +74,10 @@ public: /* [in] */ BSTR title, /* [in] */ IWebFrame *frame); + virtual HRESULT STDMETHODCALLTYPE didChangeIcons( + /* [in] */ IWebView *webView, + /* [in] */ IWebFrame *frame); + virtual HRESULT STDMETHODCALLTYPE didReceiveIcon( /* [in] */ IWebView *webView, /* [in] */ OLE_HANDLE image, diff --git a/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp b/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp index 24ddc3b..112b355 100644 --- a/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp +++ b/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp @@ -483,6 +483,28 @@ void LayoutTestController::setPopupBlockingEnabled(bool enabled) preferences->setJavaScriptCanOpenWindowsAutomatically(!enabled); } +void LayoutTestController::setPluginsEnabled(bool flag) +{ + // FIXME: Implement +} + +void LayoutTestController::setJavaScriptCanAccessClipboard(bool enabled) +{ + COMPtr<IWebView> webView; + if (FAILED(frame->webView(&webView))) + return; + + COMPtr<IWebPreferences> preferences; + if (FAILED(webView->preferences(&preferences))) + return; + + COMPtr<IWebPreferencesPrivate> prefsPrivate(Query, preferences); + if (!prefsPrivate) + return; + + prefsPrivate->setJavaScriptCanAccessClipboard(enabled); +} + void LayoutTestController::setTabKeyCyclesThroughElements(bool shouldCycle) { COMPtr<IWebView> webView; diff --git a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.cpp b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.cpp index eeacb7e..89873b6 100644 --- a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.cpp +++ b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.cpp @@ -85,13 +85,13 @@ static void executeScript(const PluginObject* object, const char* script) browser->releasevariantvalue(&browserResult); } -NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char *argn[], char *argv[], NPSavedData *saved) +NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char *argn[], char *argv[], NPSavedData *saved) { if (browser->version >= 14) { PluginObject* obj = (PluginObject*)browser->createobject(instance, getPluginClass()); instance->pdata = obj; - for (int16 i = 0; i < argc; i++) { + for (int16_t i = 0; i < argc; i++) { if (_stricmp(argn[i], "onstreamload") == 0 && !obj->onStreamLoad) obj->onStreamLoad = _strdup(argv[i]); else if (_stricmp(argn[i], "onStreamDestroy") == 0 && !obj->onStreamDestroy) @@ -166,7 +166,7 @@ NPError NPP_SetWindow(NPP instance, NPWindow *window) return NPERR_NO_ERROR; } -NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype) +NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16_t *stype) { PluginObject* obj = (PluginObject*)instance->pdata; @@ -196,12 +196,12 @@ NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) return NPERR_NO_ERROR; } -int32 NPP_WriteReady(NPP instance, NPStream *stream) +int32_t NPP_WriteReady(NPP instance, NPStream *stream) { return 0; } -int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer) +int32_t NPP_Write(NPP instance, NPStream *stream, int32_t offset, int32_t len, void *buffer) { return 0; } @@ -214,7 +214,7 @@ void NPP_Print(NPP instance, NPPrint *platformPrint) { } -int16 NPP_HandleEvent(NPP instance, void *event) +int16_t NPP_HandleEvent(NPP instance, void *event) { PluginObject *obj = (PluginObject*)instance->pdata; if (!obj->eventLogging) diff --git a/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp b/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp index 873e8d8..bc157be 100644 --- a/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp +++ b/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp @@ -167,6 +167,11 @@ void LayoutTestController::setPrivateBrowsingEnabled(bool privateBrowsingEnabled // FIXME: implement } +void LayoutTestController::setJavaScriptCanAccessClipboard(bool enabled) +{ + // FIXME: implement +} + void LayoutTestController::setXSSAuditorEnabled(bool enabled) { // FIXME: implement @@ -197,6 +202,11 @@ void LayoutTestController::setPopupBlockingEnabled(bool popupBlockingEnabled) // FIXME: implement } +void LayoutTestController::setPluginsEnabled(bool flag) +{ + // FIXME: Implement +} + bool LayoutTestController::elementDoesAutoCompleteForElementWithId(JSStringRef id) { // FIXME: implement @@ -423,6 +433,11 @@ JSRetainPtr<JSStringRef> LayoutTestController::layerTreeAsText() const return 0; } +JSRetainPtr<JSStringRef> LayoutTestController::markerTextForListItem(JSContextRef context, JSValueRef nodeObject) const +{ + return 0; +} + JSValueRef LayoutTestController::computedStyleIncludingVisitedInfo(JSContextRef, JSValueRef) { return 0; diff --git a/WebKitTools/Makefile b/WebKitTools/Makefile index 92f5b25..c1f1991 100644 --- a/WebKitTools/Makefile +++ b/WebKitTools/Makefile @@ -1,4 +1,4 @@ -MODULES = DumpRenderTree +MODULES = DumpRenderTree MiniBrowser all: @for dir in $(MODULES); do ${MAKE} $@ -C $$dir; exit_status=$$?; \ diff --git a/WebKitTools/MiniBrowser/Makefile b/WebKitTools/MiniBrowser/Makefile index 1f1dbbc..61cd475 100644 --- a/WebKitTools/MiniBrowser/Makefile +++ b/WebKitTools/MiniBrowser/Makefile @@ -1,2 +1,21 @@ +# Build MiniBrowser only on SnowLeopard and later. + +OSX_VERSION ?= $(shell sw_vers -productVersion | cut -d. -f 2) +BUILD_MINIBROWSER = $(shell (( $(OSX_VERSION) >= 6 )) && echo "YES" ) + +ifeq "$(BUILD_MINIBROWSER)" "YES" + SCRIPTS_PATH = ../Scripts include ../../Makefile.shared + +else + +all: ; + +debug d development dev develop: ; + +release r deployment dep deploy: ; + +clean: ; + +endif diff --git a/WebKitTools/MiniBrowser/MiniBrowser.xcodeproj/project.pbxproj b/WebKitTools/MiniBrowser/MiniBrowser.xcodeproj/project.pbxproj index 6c5b9a1..4518dd3 100644 --- a/WebKitTools/MiniBrowser/MiniBrowser.xcodeproj/project.pbxproj +++ b/WebKitTools/MiniBrowser/MiniBrowser.xcodeproj/project.pbxproj @@ -15,6 +15,8 @@ BC329498116A941B008635D0 /* BrowserWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC329497116A941B008635D0 /* BrowserWindowController.m */; }; BC3294A3116A9852008635D0 /* BrowserWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC3294A1116A9852008635D0 /* BrowserWindow.xib */; }; BC8FB5A8116AA1FE0080D413 /* WebKit2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC8FB5A7116AA1FE0080D413 /* WebKit2.framework */; }; + BCE625EE117FC80E00572433 /* BrowserStatisticsWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCE625ED117FC80E00572433 /* BrowserStatisticsWindow.xib */; }; + BCE625F1117FC82700572433 /* BrowserStatisticsWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCE625F0117FC82700572433 /* BrowserStatisticsWindowController.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -29,11 +31,15 @@ 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; }; 8D1107310486CEB800E47090 /* MiniBrowser-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "MiniBrowser-Info.plist"; path = "mac/MiniBrowser-Info.plist"; sourceTree = "<group>"; }; 8D1107320486CEB800E47090 /* MiniBrowser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MiniBrowser.app; sourceTree = BUILT_PRODUCTS_DIR; }; + BC1770121188DF19007D9E9A /* make-launchable.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = "make-launchable.sh"; path = "mac/make-launchable.sh"; sourceTree = "<group>"; }; BC329486116A92E2008635D0 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = mac/main.m; sourceTree = "<group>"; }; BC329496116A941B008635D0 /* BrowserWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BrowserWindowController.h; path = mac/BrowserWindowController.h; sourceTree = "<group>"; }; BC329497116A941B008635D0 /* BrowserWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BrowserWindowController.m; path = mac/BrowserWindowController.m; sourceTree = "<group>"; }; BC3294A2116A9852008635D0 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = mac/English.lproj/BrowserWindow.xib; sourceTree = "<group>"; }; BC8FB5A7116AA1FE0080D413 /* WebKit2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = WebKit2.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + BCE625ED117FC80E00572433 /* BrowserStatisticsWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = BrowserStatisticsWindow.xib; path = mac/BrowserStatisticsWindow.xib; sourceTree = "<group>"; }; + BCE625EF117FC82700572433 /* BrowserStatisticsWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BrowserStatisticsWindowController.h; path = mac/BrowserStatisticsWindowController.h; sourceTree = "<group>"; }; + BCE625F0117FC82700572433 /* BrowserStatisticsWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BrowserStatisticsWindowController.m; path = mac/BrowserStatisticsWindowController.m; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -56,6 +62,8 @@ 256AC3D90F4B6AC300CF3369 /* AppDelegate.m */, BC329496116A941B008635D0 /* BrowserWindowController.h */, BC329497116A941B008635D0 /* BrowserWindowController.m */, + BCE625EF117FC82700572433 /* BrowserStatisticsWindowController.h */, + BCE625F0117FC82700572433 /* BrowserStatisticsWindowController.m */, ); name = Classes; sourceTree = "<group>"; @@ -93,6 +101,7 @@ 080E96DDFE201D6D7F000001 /* Classes */, 29B97315FDCFA39411CA2CEA /* Other Sources */, 29B97317FDCFA39411CA2CEA /* Resources */, + BC1770481188EB05007D9E9A /* Scripts */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, ); @@ -115,6 +124,7 @@ 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */, BC3294A1116A9852008635D0 /* BrowserWindow.xib */, 1DDD58140DA1D0A300B32029 /* MainMenu.xib */, + BCE625ED117FC80E00572433 /* BrowserStatisticsWindow.xib */, ); name = Resources; sourceTree = "<group>"; @@ -128,6 +138,14 @@ name = Frameworks; sourceTree = "<group>"; }; + BC1770481188EB05007D9E9A /* Scripts */ = { + isa = PBXGroup; + children = ( + BC1770121188DF19007D9E9A /* make-launchable.sh */, + ); + name = Scripts; + sourceTree = "<group>"; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -138,6 +156,7 @@ 8D1107290486CEB800E47090 /* Resources */, 8D11072C0486CEB800E47090 /* Sources */, 8D11072E0486CEB800E47090 /* Frameworks */, + BC17701E1188DFB4007D9E9A /* Make Launchable */, ); buildRules = ( ); @@ -174,11 +193,29 @@ 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */, 1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */, BC3294A3116A9852008635D0 /* BrowserWindow.xib in Resources */, + BCE625EE117FC80E00572433 /* BrowserStatisticsWindow.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + BC17701E1188DFB4007D9E9A /* Make Launchable */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Make Launchable"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "mac/make-launchable.sh\n"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 8D11072C0486CEB800E47090 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -187,6 +224,7 @@ 256AC3DA0F4B6AC300CF3369 /* AppDelegate.m in Sources */, BC329487116A92E2008635D0 /* main.m in Sources */, BC329498116A941B008635D0 /* BrowserWindowController.m in Sources */, + BCE625F1117FC82700572433 /* BrowserStatisticsWindowController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/WebKitTools/MiniBrowser/mac/AppDelegate.h b/WebKitTools/MiniBrowser/mac/AppDelegate.h index 79683f3..73efe32 100644 --- a/WebKitTools/MiniBrowser/mac/AppDelegate.h +++ b/WebKitTools/MiniBrowser/mac/AppDelegate.h @@ -23,17 +23,16 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#import <Cocoa/Cocoa.h> -#import <WebKit2/WebKit2.h> - @interface BrowserAppDelegate : NSObject <NSApplicationDelegate> { WKProcessModel currentProcessModel; - WKPageNamespaceRef pageNamespace; + WKPageNamespaceRef threadPageNamespace; + WKPageNamespaceRef processPageNamespace; } -- (WKPageNamespaceRef)getPageNamespace; +- (WKPageNamespaceRef)getCurrentPageNamespace; - (IBAction)setSharedProcessProcessModel:(id)sender; - (IBAction)setSharedThreadProcessModel:(id)sender; +- (IBAction)showStatisticsWindow:(id)sender; @end diff --git a/WebKitTools/MiniBrowser/mac/AppDelegate.m b/WebKitTools/MiniBrowser/mac/AppDelegate.m index e10deb1..64037fa 100644 --- a/WebKitTools/MiniBrowser/mac/AppDelegate.m +++ b/WebKitTools/MiniBrowser/mac/AppDelegate.m @@ -24,10 +24,11 @@ */ #import "AppDelegate.h" + #import "BrowserWindowController.h" +#import "BrowserStatisticsWindowController.h" static NSString *defaultURL = @"http://webkit.org/"; -static const WKProcessModel defaultProcessModel = kWKProcessModelSecondaryProcess; @implementation BrowserAppDelegate @@ -39,6 +40,14 @@ static const WKProcessModel defaultProcessModel = kWKProcessModelSecondaryProces currentProcessModel = kWKProcessModelSecondaryThread; else currentProcessModel = kWKProcessModelSecondaryProcess; + + WKContextRef threadContext = WKContextCreateWithProcessModel(kWKProcessModelSecondaryThread); + threadPageNamespace = WKPageNamespaceCreate(threadContext); + WKContextRelease(threadContext); + + WKContextRef processContext = WKContextCreateWithProcessModel(kWKProcessModelSecondaryProcess); + processPageNamespace = WKPageNamespaceCreate(processContext); + WKContextRelease(processContext); } return self; @@ -46,21 +55,15 @@ static const WKProcessModel defaultProcessModel = kWKProcessModelSecondaryProces - (IBAction)newWindow:(id)sender { - BrowserWindowController *controller = [[BrowserWindowController alloc] initWithPageNamespace:[self getPageNamespace]]; + BrowserWindowController *controller = [[BrowserWindowController alloc] initWithPageNamespace:[self getCurrentPageNamespace]]; [[controller window] makeKeyAndOrderFront:sender]; [controller loadURLString:defaultURL]; } -- (WKPageNamespaceRef)getPageNamespace +- (WKPageNamespaceRef)getCurrentPageNamespace { - if (!pageNamespace) { - WKContextRef context = WKContextCreateWithProcessModel(currentProcessModel); - pageNamespace = WKPageNamespaceCreate(context); - WKContextRelease(context); - } - - return pageNamespace; + return (currentProcessModel == kWKProcessModelSecondaryThread) ? threadPageNamespace : processPageNamespace; } - (BOOL)validateMenuItem:(NSMenuItem *)menuItem @@ -78,10 +81,6 @@ static const WKProcessModel defaultProcessModel = kWKProcessModelSecondaryProces return; currentProcessModel = processModel; - if (pageNamespace) { - WKPageNamespaceRelease(pageNamespace); - pageNamespace = 0; - } } - (IBAction)setSharedProcessProcessModel:(id)sender @@ -94,6 +93,16 @@ static const WKProcessModel defaultProcessModel = kWKProcessModelSecondaryProces [self _setProcessModel:kWKProcessModelSecondaryThread]; } +- (IBAction)showStatisticsWindow:(id)sender +{ + static BrowserStatisticsWindowController* windowController; + if (!windowController) + windowController = [[BrowserStatisticsWindowController alloc] initWithThreadedWKContextRef:WKPageNamespaceGetContext(threadPageNamespace) + processWKContextRef:WKPageNamespaceGetContext(processPageNamespace)]; + + [[windowController window] makeKeyAndOrderFront:self]; +} + - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { [self newWindow:self]; @@ -103,14 +112,18 @@ static const WKProcessModel defaultProcessModel = kWKProcessModelSecondaryProces { NSArray* windows = [NSApp windows]; for (NSWindow* window in windows) { - BrowserWindowController *controller = (BrowserWindowController *)[window delegate]; - [controller applicationTerminating]; + id delegate = [window delegate]; + if ([delegate isKindOfClass:[BrowserWindowController class]]) { + BrowserWindowController *controller = (BrowserWindowController *)delegate; + [controller applicationTerminating]; + } } + + WKPageNamespaceRelease(threadPageNamespace); + threadPageNamespace = 0; - if (pageNamespace) { - WKPageNamespaceRelease(pageNamespace); - pageNamespace = 0; - } + WKPageNamespaceRelease(processPageNamespace); + processPageNamespace = 0; } @end diff --git a/WebKitTools/MiniBrowser/mac/BrowserStatisticsWindow.xib b/WebKitTools/MiniBrowser/mac/BrowserStatisticsWindow.xib new file mode 100644 index 0000000..ae2b5f8 --- /dev/null +++ b/WebKitTools/MiniBrowser/mac/BrowserStatisticsWindow.xib @@ -0,0 +1,974 @@ +<?xml version="1.0" encoding="UTF-8"?> +<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10"> + <data> + <int key="IBDocument.SystemTarget">1060</int> + <string key="IBDocument.SystemVersion">10D573</string> + <string key="IBDocument.InterfaceBuilderVersion">762</string> + <string key="IBDocument.AppKitVersion">1038.29</string> + <string key="IBDocument.HIToolboxVersion">460.00</string> + <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> + <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string> + <string key="NS.object.0">762</string> + </object> + <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> + <bool key="EncodedWithXMLCoder">YES</bool> + <integer value="2"/> + </object> + <object class="NSArray" key="IBDocument.PluginDependencies"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + </object> + <object class="NSMutableDictionary" key="IBDocument.Metadata"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys" id="0"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + </object> + <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSCustomObject" id="1001"> + <string key="NSClassName">BrowserStatisticsWindowController</string> + </object> + <object class="NSCustomObject" id="1003"> + <string key="NSClassName">FirstResponder</string> + </object> + <object class="NSCustomObject" id="1004"> + <string key="NSClassName">NSApplication</string> + </object> + <object class="NSWindowTemplate" id="1005"> + <int key="NSWindowStyleMask">15</int> + <int key="NSWindowBacking">2</int> + <string key="NSWindowRect">{{196, 352}, {398, 158}}</string> + <int key="NSWTFlags">544735232</int> + <string key="NSWindowTitle">Window</string> + <string key="NSWindowClass">NSWindow</string> + <nil key="NSViewClass"/> + <string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string> + <object class="NSView" key="NSWindowView" id="1006"> + <reference key="NSNextResponder"/> + <int key="NSvFlags">256</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSBox" id="349928848"> + <reference key="NSNextResponder" ref="1006"/> + <int key="NSvFlags">45</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSView" id="737205069"> + <reference key="NSNextResponder" ref="349928848"/> + <int key="NSvFlags">256</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMatrix" id="840724334"> + <reference key="NSNextResponder" ref="737205069"/> + <int key="NSvFlags">256</int> + <string key="NSFrame">{{18, 14}, {318, 42}}</string> + <reference key="NSSuperview" ref="737205069"/> + <bool key="NSEnabled">YES</bool> + <int key="NSNumRows">3</int> + <int key="NSNumCols">3</int> + <object class="NSMutableArray" key="NSCells"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSTextFieldCell" id="66669903"> + <int key="NSCellFlags">68288064</int> + <int key="NSCellFlags2">71435264</int> + <string key="NSContents"/> + <object class="NSFont" key="NSSupport" id="57559"> + <string key="NSName">LucidaGrande-Bold</string> + <double key="NSSize">11</double> + <int key="NSfFlags">16</int> + </object> + <reference key="NSControlView" ref="840724334"/> + <object class="NSColor" key="NSBackgroundColor" id="159766406"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes> + </object> + </object> + <object class="NSColor" key="NSTextColor" id="822671316"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlTextColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MAA</bytes> + </object> + </object> + </object> + <object class="NSTextFieldCell" id="792638244"> + <int key="NSCellFlags">68288064</int> + <int key="NSCellFlags2">71435264</int> + <string key="NSContents">Shared Process</string> + <reference key="NSSupport" ref="57559"/> + <reference key="NSControlView" ref="840724334"/> + <int key="NSTag">1</int> + <reference key="NSBackgroundColor" ref="159766406"/> + <reference key="NSTextColor" ref="822671316"/> + </object> + <object class="NSTextFieldCell" id="220500282"> + <int key="NSCellFlags">68288064</int> + <int key="NSCellFlags2">71435264</int> + <string key="NSContents">Shared Thread</string> + <reference key="NSSupport" ref="57559"/> + <reference key="NSControlView" ref="840724334"/> + <reference key="NSBackgroundColor" ref="159766406"/> + <reference key="NSTextColor" ref="822671316"/> + </object> + <object class="NSTextFieldCell" id="822378002"> + <int key="NSCellFlags">68288064</int> + <int key="NSCellFlags2">71435264</int> + <string key="NSContents">Pages</string> + <reference key="NSSupport" ref="57559"/> + <reference key="NSControlView" ref="840724334"/> + <reference key="NSBackgroundColor" ref="159766406"/> + <reference key="NSTextColor" ref="822671316"/> + </object> + <object class="NSTextFieldCell" id="665973187"> + <int key="NSCellFlags">68288064</int> + <int key="NSCellFlags2">71435264</int> + <string key="NSContents">-100</string> + <object class="NSFont" key="NSSupport" id="422232155"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">11</double> + <int key="NSfFlags">16</int> + </object> + <reference key="NSControlView" ref="840724334"/> + <int key="NSTag">11</int> + <reference key="NSBackgroundColor" ref="159766406"/> + <reference key="NSTextColor" ref="822671316"/> + </object> + <object class="NSTextFieldCell" id="534624797"> + <int key="NSCellFlags">68288064</int> + <int key="NSCellFlags2">71435264</int> + <string key="NSContents">-100</string> + <reference key="NSSupport" ref="422232155"/> + <reference key="NSControlView" ref="840724334"/> + <int key="NSTag">21</int> + <reference key="NSBackgroundColor" ref="159766406"/> + <reference key="NSTextColor" ref="822671316"/> + </object> + <object class="NSTextFieldCell" id="576107244"> + <int key="NSCellFlags">68288064</int> + <int key="NSCellFlags2">71435264</int> + <string key="NSContents">Frames</string> + <reference key="NSSupport" ref="57559"/> + <reference key="NSControlView" ref="840724334"/> + <reference key="NSBackgroundColor" ref="159766406"/> + <reference key="NSTextColor" ref="822671316"/> + </object> + <object class="NSTextFieldCell" id="775125133"> + <int key="NSCellFlags">68288064</int> + <int key="NSCellFlags2">71435264</int> + <string key="NSContents">-100</string> + <reference key="NSSupport" ref="422232155"/> + <reference key="NSControlView" ref="840724334"/> + <int key="NSTag">12</int> + <reference key="NSBackgroundColor" ref="159766406"/> + <reference key="NSTextColor" ref="822671316"/> + </object> + <object class="NSTextFieldCell" id="1058484862"> + <int key="NSCellFlags">68288064</int> + <int key="NSCellFlags2">71435264</int> + <string key="NSContents">-100</string> + <reference key="NSSupport" ref="422232155"/> + <reference key="NSControlView" ref="840724334"/> + <int key="NSTag">22</int> + <reference key="NSBackgroundColor" ref="159766406"/> + <reference key="NSTextColor" ref="822671316"/> + </object> + </object> + <string key="NSCellSize">{106, 14}</string> + <string key="NSIntercellSpacing">{0, 0}</string> + <int key="NSMatrixFlags">-2080374784</int> + <nil key="NSCellClass"/> + <object class="NSTextFieldCell" key="NSProtoCell" id="609012621"> + <int key="NSCellFlags">68288064</int> + <int key="NSCellFlags2">71435264</int> + <string key="NSContents">Page Namespaces</string> + <reference key="NSSupport" ref="57559"/> + <reference key="NSBackgroundColor" ref="159766406"/> + <reference key="NSTextColor" ref="822671316"/> + </object> + <int key="NSSelectedRow">-1</int> + <int key="NSSelectedCol">-1</int> + <reference key="NSBackgroundColor" ref="159766406"/> + <reference key="NSCellBackgroundColor" ref="159766406"/> + </object> + </object> + <string key="NSFrame">{{1, 1}, {354, 66}}</string> + <reference key="NSSuperview" ref="349928848"/> + </object> + </object> + <string key="NSFrame">{{25, 56}, {356, 82}}</string> + <reference key="NSSuperview" ref="1006"/> + <string key="NSOffsets">{0, 0}</string> + <object class="NSTextFieldCell" key="NSTitleCell"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">0</int> + <string key="NSContents">Statistics</string> + <object class="NSFont" key="NSSupport"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">11</double> + <int key="NSfFlags">3100</int> + </object> + <object class="NSColor" key="NSBackgroundColor"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">textBackgroundColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MQA</bytes> + </object> + </object> + <object class="NSColor" key="NSTextColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MCAwLjgwMDAwMDAxMTkAA</bytes> + </object> + </object> + <reference key="NSContentView" ref="737205069"/> + <int key="NSBorderType">1</int> + <int key="NSBoxType">0</int> + <int key="NSTitlePosition">2</int> + <bool key="NSTransparent">NO</bool> + </object> + <object class="NSButton" id="913385411"> + <reference key="NSNextResponder" ref="1006"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{288, 12}, {96, 32}}</string> + <reference key="NSSuperview" ref="1006"/> + <bool key="NSEnabled">YES</bool> + <object class="NSButtonCell" key="NSCell" id="465163606"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">134217728</int> + <string key="NSContents">Refresh</string> + <object class="NSFont" key="NSSupport"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">13</double> + <int key="NSfFlags">1044</int> + </object> + <reference key="NSControlView" ref="913385411"/> + <int key="NSButtonFlags">-2038284033</int> + <int key="NSButtonFlags2">129</int> + <string key="NSAlternateContents"/> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">200</int> + <int key="NSPeriodicInterval">25</int> + </object> + </object> + </object> + <string key="NSFrameSize">{398, 158}</string> + <reference key="NSSuperview"/> + </object> + <string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string> + <string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string> + </object> + </object> + <object class="IBObjectContainer" key="IBDocument.Objects"> + <object class="NSMutableArray" key="connectionRecords"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">window</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="1005"/> + </object> + <int key="connectionID">3</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">delegate</string> + <reference key="source" ref="1005"/> + <reference key="destination" ref="1001"/> + </object> + <int key="connectionID">4</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">refreshStatistics:</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="913385411"/> + </object> + <int key="connectionID">83</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">_basicStatsMatrix</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="840724334"/> + </object> + <int key="connectionID">84</int> + </object> + </object> + <object class="IBMutableOrderedSet" key="objectRecords"> + <object class="NSArray" key="orderedObjects"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBObjectRecord"> + <int key="objectID">0</int> + <reference key="object" ref="0"/> + <reference key="children" ref="1000"/> + <nil key="parent"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-2</int> + <reference key="object" ref="1001"/> + <reference key="parent" ref="0"/> + <string key="objectName">File's Owner</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-1</int> + <reference key="object" ref="1003"/> + <reference key="parent" ref="0"/> + <string key="objectName">First Responder</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-3</int> + <reference key="object" ref="1004"/> + <reference key="parent" ref="0"/> + <string key="objectName">Application</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">1</int> + <reference key="object" ref="1005"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="1006"/> + </object> + <reference key="parent" ref="0"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">2</int> + <reference key="object" ref="1006"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="349928848"/> + <reference ref="913385411"/> + </object> + <reference key="parent" ref="1005"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">5</int> + <reference key="object" ref="349928848"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="840724334"/> + </object> + <reference key="parent" ref="1006"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">37</int> + <reference key="object" ref="913385411"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="465163606"/> + </object> + <reference key="parent" ref="1006"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">38</int> + <reference key="object" ref="465163606"/> + <reference key="parent" ref="913385411"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">75</int> + <reference key="object" ref="840724334"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="1058484862"/> + <reference ref="534624797"/> + <reference ref="220500282"/> + <reference ref="792638244"/> + <reference ref="66669903"/> + <reference ref="665973187"/> + <reference ref="822378002"/> + <reference ref="775125133"/> + <reference ref="576107244"/> + <reference ref="609012621"/> + </object> + <reference key="parent" ref="349928848"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">87</int> + <reference key="object" ref="1058484862"/> + <reference key="parent" ref="840724334"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">86</int> + <reference key="object" ref="534624797"/> + <reference key="parent" ref="840724334"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">85</int> + <reference key="object" ref="220500282"/> + <reference key="parent" ref="840724334"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">48</int> + <reference key="object" ref="792638244"/> + <reference key="parent" ref="840724334"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">42</int> + <reference key="object" ref="66669903"/> + <reference key="parent" ref="840724334"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">46</int> + <reference key="object" ref="665973187"/> + <reference key="parent" ref="840724334"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">43</int> + <reference key="object" ref="822378002"/> + <reference key="parent" ref="840724334"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">47</int> + <reference key="object" ref="775125133"/> + <reference key="parent" ref="840724334"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">44</int> + <reference key="object" ref="576107244"/> + <reference key="parent" ref="840724334"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">82</int> + <reference key="object" ref="609012621"/> + <reference key="parent" ref="840724334"/> + </object> + </object> + </object> + <object class="NSMutableDictionary" key="flattenedProperties"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>1.IBEditorWindowLastContentRect</string> + <string>1.IBPluginDependency</string> + <string>1.IBWindowTemplateEditedContentRect</string> + <string>1.NSWindowTemplate.visibleAtLaunch</string> + <string>1.WindowOrigin</string> + <string>1.editorWindowContentRectSynchronizationRect</string> + <string>2.IBPluginDependency</string> + <string>37.IBPluginDependency</string> + <string>38.IBPluginDependency</string> + <string>5.IBPluginDependency</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>{{362, 638}, {398, 158}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{362, 638}, {398, 158}}</string> + <integer value="1"/> + <string>{196, 240}</string> + <string>{{202, 428}, {480, 270}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + </object> + </object> + <object class="NSMutableDictionary" key="unlocalizedProperties"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference key="dict.sortedKeys" ref="0"/> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + </object> + <nil key="activeLocalization"/> + <object class="NSMutableDictionary" key="localizations"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference key="dict.sortedKeys" ref="0"/> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + </object> + <nil key="sourceID"/> + <int key="maxID">88</int> + </object> + <object class="IBClassDescriber" key="IBDocument.Classes"> + <object class="NSMutableArray" key="referencedPartialClassDescriptions"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBPartialClassDescription"> + <string key="className">BrowserStatisticsWindowController</string> + <string key="superclassName">NSWindowController</string> + <object class="NSMutableDictionary" key="actions"> + <string key="NS.key.0">refreshStatistics:</string> + <string key="NS.object.0">id</string> + </object> + <object class="NSMutableDictionary" key="outlets"> + <string key="NS.key.0">_basicStatsMatrix</string> + <string key="NS.object.0">NSMatrix</string> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">mac/BrowserStatisticsWindowController.h</string> + </object> + </object> + </object> + <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBPartialClassDescription"> + <string key="className">NSActionCell</string> + <string key="superclassName">NSCell</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSActionCell.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSApplication</string> + <string key="superclassName">NSResponder</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="580408357"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSApplication.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSApplication</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="153722584"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSApplicationScripting.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSApplication</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="814670282"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSColorPanel.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSApplication</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSHelpManager.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSApplication</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSPageLayout.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSApplication</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSUserInterfaceItemSearching.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSBox</string> + <string key="superclassName">NSView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSBox.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSButton</string> + <string key="superclassName">NSControl</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSButton.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSButtonCell</string> + <string key="superclassName">NSActionCell</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSButtonCell.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSCell</string> + <string key="superclassName">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSCell.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSControl</string> + <string key="superclassName">NSView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="423015697"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSControl.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSFormatter</string> + <string key="superclassName">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSFormatter.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSMatrix</string> + <string key="superclassName">NSControl</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSMatrix.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSMenu</string> + <string key="superclassName">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="571428989"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSMenu.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSAccessibility.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <reference key="sourceIdentifier" ref="580408357"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <reference key="sourceIdentifier" ref="153722584"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <reference key="sourceIdentifier" ref="814670282"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <reference key="sourceIdentifier" ref="423015697"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSDictionaryController.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSDragging.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSFontManager.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSFontPanel.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSKeyValueBinding.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <reference key="sourceIdentifier" ref="571428989"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSNibLoading.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSOutlineView.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSPasteboard.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSSavePanel.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSTableView.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSToolbarItem.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="214998123"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSView.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSArchiver.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSClassDescription.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSError.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSObject.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSObjectScripting.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSPortCoder.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSScriptClassDescription.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSScriptKeyValueCoding.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSScriptObjectSpecifiers.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSScriptWhoseTests.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSThread.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSURL.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSURLDownload.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSResponder</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSInterfaceStyle.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSResponder</string> + <string key="superclassName">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSResponder.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSTextFieldCell</string> + <string key="superclassName">NSActionCell</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSTextFieldCell.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSClipView.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSMenuItem.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSRulerView.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSView</string> + <string key="superclassName">NSResponder</string> + <reference key="sourceIdentifier" ref="214998123"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSWindow</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSDrawer.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSWindow</string> + <string key="superclassName">NSResponder</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSWindow.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSWindow</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSWindowScripting.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSWindowController</string> + <string key="superclassName">NSResponder</string> + <object class="NSMutableDictionary" key="actions"> + <string key="NS.key.0">showWindow:</string> + <string key="NS.object.0">id</string> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSWindowController.h</string> + </object> + </object> + </object> + </object> + <int key="IBDocument.localizationMode">0</int> + <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string> + <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults"> + <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string> + <integer value="1060" key="NS.object.0"/> + </object> + <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies"> + <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string> + <integer value="3000" key="NS.object.0"/> + </object> + <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool> + <string key="IBDocument.LastKnownRelativeProjectPath">../MiniBrowser.xcodeproj</string> + <int key="IBDocument.defaultPropertyAccessControl">3</int> + </data> +</archive> diff --git a/WebKitTools/MiniBrowser/mac/BrowserStatisticsWindowController.h b/WebKitTools/MiniBrowser/mac/BrowserStatisticsWindowController.h new file mode 100644 index 0000000..6b4438f --- /dev/null +++ b/WebKitTools/MiniBrowser/mac/BrowserStatisticsWindowController.h @@ -0,0 +1,20 @@ +// +// BrowserStatisticsWindowController.h +// MiniBrowser +// +// Created by Sam Weinig on 4/21/10. +// Copyright 2010 Apple Inc. All rights reserved. +// + +@interface BrowserStatisticsWindowController : NSWindowController { + IBOutlet NSMatrix *_basicStatsMatrix; + + WKContextRef _threadContext; + WKContextRef _processContext; +} + +- (id)initWithThreadedWKContextRef:(WKContextRef)threadContext processWKContextRef:(WKContextRef)processContext; + +- (IBAction)refreshStatistics:(id)sender; + +@end diff --git a/WebKitTools/MiniBrowser/mac/BrowserStatisticsWindowController.m b/WebKitTools/MiniBrowser/mac/BrowserStatisticsWindowController.m new file mode 100644 index 0000000..bb5fc7d --- /dev/null +++ b/WebKitTools/MiniBrowser/mac/BrowserStatisticsWindowController.m @@ -0,0 +1,58 @@ +// +// BrowserStatisticsWindowController.m +// MiniBrowser +// +// Created by Sam Weinig on 4/21/10. +// Copyright 2010 Apple Inc. All rights reserved. +// + +#import "BrowserStatisticsWindowController.h" + +#import <WebKit2/WKContextPrivate.h> + +@implementation BrowserStatisticsWindowController + +- (id)initWithThreadedWKContextRef:(WKContextRef)threadContext processWKContextRef:(WKContextRef)processContext +{ + if (self = [super initWithWindowNibName:@"BrowserStatisticsWindow"]) { + _threadContext = WKContextRetain(threadContext); + _processContext = WKContextRetain(processContext); + } + + return self; +} + +- (void)dealloc +{ + WKContextRelease(_threadContext); + _threadContext = 0; + + WKContextRelease(_processContext); + _processContext = 0; + + [super dealloc]; +} + +- (void)windowDidLoad +{ + [super windowDidLoad]; + [self refreshStatistics:nil]; +} + +- (IBAction)refreshStatistics:(id)sender +{ + WKContextStatistics threadStats; + WKContextGetStatistics(_threadContext, &threadStats); + + WKContextStatistics processStats; + WKContextGetStatistics(_processContext, &processStats); + + [[_basicStatsMatrix cellWithTag:11] setIntValue:processStats.numberOfWKPages]; + [[_basicStatsMatrix cellWithTag:12] setIntValue:processStats.numberOfWKFrames]; + + [[_basicStatsMatrix cellWithTag:21] setIntValue:threadStats.numberOfWKPages]; + [[_basicStatsMatrix cellWithTag:22] setIntValue:threadStats.numberOfWKFrames]; + +} + +@end diff --git a/WebKitTools/MiniBrowser/mac/BrowserWindowController.h b/WebKitTools/MiniBrowser/mac/BrowserWindowController.h index f817e89..c638beb 100644 --- a/WebKitTools/MiniBrowser/mac/BrowserWindowController.h +++ b/WebKitTools/MiniBrowser/mac/BrowserWindowController.h @@ -23,10 +23,6 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#import <Cocoa/Cocoa.h> - -#import <WebKit2/WebKit2.h> - @interface BrowserWindowController : NSWindowController { IBOutlet NSProgressIndicator *progressIndicator; IBOutlet NSButton *reloadButton; diff --git a/WebKitTools/MiniBrowser/mac/English.lproj/MainMenu.xib b/WebKitTools/MiniBrowser/mac/English.lproj/MainMenu.xib index ca3010c..229611c 100644 --- a/WebKitTools/MiniBrowser/mac/English.lproj/MainMenu.xib +++ b/WebKitTools/MiniBrowser/mac/English.lproj/MainMenu.xib @@ -3,12 +3,12 @@ <data> <int key="IBDocument.SystemTarget">1060</int> <string key="IBDocument.SystemVersion">10D573</string> - <string key="IBDocument.InterfaceBuilderVersion">783</string> + <string key="IBDocument.InterfaceBuilderVersion">762</string> <string key="IBDocument.AppKitVersion">1038.29</string> <string key="IBDocument.HIToolboxVersion">460.00</string> <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string> - <string key="NS.object.0">783</string> + <string key="NS.object.0">762</string> </object> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -1348,6 +1348,24 @@ <reference key="NSOnImage" ref="35465992"/> <reference key="NSMixedImage" ref="502551668"/> </object> + <object class="NSMenuItem" id="864702084"> + <reference key="NSMenu" ref="865232259"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="208343368"> + <reference key="NSMenu" ref="865232259"/> + <string key="NSTitle">Show Statistics Window</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> <object class="NSMenuItem" id="162978490"> <reference key="NSMenu" ref="865232259"/> <bool key="NSIsDisabled">YES</bool> @@ -2117,6 +2135,14 @@ </object> <int key="connectionID">551</int> </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">showStatisticsWindow:</string> + <reference key="source" ref="976324537"/> + <reference key="destination" ref="208343368"/> + </object> + <int key="connectionID">554</int> + </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> @@ -3164,6 +3190,8 @@ <reference ref="162978490"/> <reference ref="137933275"/> <reference ref="1027125810"/> + <reference ref="864702084"/> + <reference ref="208343368"/> </object> <reference key="parent" ref="816668511"/> </object> @@ -3219,6 +3247,16 @@ <reference key="object" ref="1027125810"/> <reference key="parent" ref="865232259"/> </object> + <object class="IBObjectRecord"> + <int key="objectID">552</int> + <reference key="object" ref="208343368"/> + <reference key="parent" ref="865232259"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">553</int> + <reference key="object" ref="864702084"/> + <reference key="parent" ref="865232259"/> + </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> @@ -3446,6 +3484,8 @@ <string>546.IBPluginDependency</string> <string>548.IBPluginDependency</string> <string>550.IBPluginDependency</string> + <string>552.IBPluginDependency</string> + <string>553.IBPluginDependency</string> <string>56.IBPluginDependency</string> <string>56.ImportedFromIB2</string> <string>57.IBEditorWindowLastContentRect</string> @@ -3587,7 +3627,7 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{525, 802}, {197, 73}}</string> - <string>{{317, 945}, {517, 20}}</string> + <string>{{317, 836}, {517, 20}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{74, 862}</string> @@ -3693,7 +3733,7 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{759, 852}, {211, 93}}</string> + <string>{{759, 713}, {246, 123}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>{{944, 872}, {154, 43}}</string> @@ -3705,6 +3745,8 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1"/> <string>{{286, 129}, {275, 183}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -3756,7 +3798,7 @@ </object> </object> <nil key="sourceID"/> - <int key="maxID">551</int> + <int key="maxID">554</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> @@ -3770,30 +3812,13 @@ <bool key="EncodedWithXMLCoder">YES</bool> <string>setSharedProcessProcessModel:</string> <string>setSharedThreadProcessModel:</string> + <string>showStatisticsWindow:</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>id</string> <string>id</string> - </object> - </object> - <object class="NSMutableDictionary" key="actionInfosByName"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>setSharedProcessProcessModel:</string> - <string>setSharedThreadProcessModel:</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="IBActionInfo"> - <string key="name">setSharedProcessProcessModel:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">setSharedThreadProcessModel:</string> - <string key="candidateClassName">id</string> - </object> + <string>id</string> </object> </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> @@ -3808,13 +3833,6 @@ <string key="NS.key.0">window</string> <string key="NS.object.0">NSWindow</string> </object> - <object class="NSMutableDictionary" key="toOneOutletInfosByName"> - <string key="NS.key.0">window</string> - <object class="IBToOneOutletInfo" key="NS.object.0"> - <string key="name">window</string> - <string key="candidateClassName">NSWindow</string> - </object> - </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBUserSource</string> <string key="minorKey"/> @@ -3842,40 +3860,6 @@ <string>id</string> </object> </object> - <object class="NSMutableDictionary" key="actionInfosByName"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>fetch:</string> - <string>forceRepaint:</string> - <string>reload:</string> - <string>removeReinsertWebView:</string> - <string>showHideWebView:</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="IBActionInfo"> - <string key="name">fetch:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">forceRepaint:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">reload:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">removeReinsertWebView:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">showHideWebView:</string> - <string key="candidateClassName">id</string> - </object> - </object> - </object> <object class="NSMutableDictionary" key="outlets"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> @@ -3893,35 +3877,6 @@ <string>NSTextField</string> </object> </object> - <object class="NSMutableDictionary" key="toOneOutletInfosByName"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>containerView</string> - <string>progressIndicator</string> - <string>reloadButton</string> - <string>urlText</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="IBToOneOutletInfo"> - <string key="name">containerView</string> - <string key="candidateClassName">NSView</string> - </object> - <object class="IBToOneOutletInfo"> - <string key="name">progressIndicator</string> - <string key="candidateClassName">NSProgressIndicator</string> - </object> - <object class="IBToOneOutletInfo"> - <string key="name">reloadButton</string> - <string key="candidateClassName">NSButton</string> - </object> - <object class="IBToOneOutletInfo"> - <string key="name">urlText</string> - <string key="candidateClassName">NSTextField</string> - </object> - </object> - </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBProjectSource</string> <string key="minorKey">mac/BrowserWindowController.h</string> @@ -3943,25 +3898,6 @@ <string>id</string> </object> </object> - <object class="NSMutableDictionary" key="actionInfosByName"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>forceRepaint:</string> - <string>newWindow:</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="IBActionInfo"> - <string key="name">forceRepaint:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">newWindow:</string> - <string key="candidateClassName">id</string> - </object> - </object> - </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBUserSource</string> <string key="minorKey"/> @@ -4061,45 +3997,6 @@ <string>id</string> </object> </object> - <object class="NSMutableDictionary" key="actionInfosByName"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>printDocument:</string> - <string>revertDocumentToSaved:</string> - <string>runPageLayout:</string> - <string>saveDocument:</string> - <string>saveDocumentAs:</string> - <string>saveDocumentTo:</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="IBActionInfo"> - <string key="name">printDocument:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">revertDocumentToSaved:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">runPageLayout:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">saveDocument:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">saveDocumentAs:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">saveDocumentTo:</string> - <string key="candidateClassName">id</string> - </object> - </object> - </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDocument.h</string> @@ -4132,35 +4029,6 @@ <string>id</string> </object> </object> - <object class="NSMutableDictionary" key="actionInfosByName"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>clearRecentDocuments:</string> - <string>newDocument:</string> - <string>openDocument:</string> - <string>saveAllDocuments:</string> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="IBActionInfo"> - <string key="name">clearRecentDocuments:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">newDocument:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">openDocument:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo"> - <string key="name">saveAllDocuments:</string> - <string key="candidateClassName">id</string> - </object> - </object> - </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSDocumentController.h</string> @@ -4559,13 +4427,6 @@ <string key="NS.key.0">showWindow:</string> <string key="NS.object.0">id</string> </object> - <object class="NSMutableDictionary" key="actionInfosByName"> - <string key="NS.key.0">showWindow:</string> - <object class="IBActionInfo" key="NS.object.0"> - <string key="name">showWindow:</string> - <string key="candidateClassName">id</string> - </object> - </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBFrameworkSource</string> <string key="minorKey">AppKit.framework/Headers/NSWindowController.h</string> diff --git a/WebKitTools/MiniBrowser/mac/MiniBrowser_Prefix.pch b/WebKitTools/MiniBrowser/mac/MiniBrowser_Prefix.pch index bd7fc4b..af79d0f 100644 --- a/WebKitTools/MiniBrowser/mac/MiniBrowser_Prefix.pch +++ b/WebKitTools/MiniBrowser/mac/MiniBrowser_Prefix.pch @@ -26,3 +26,5 @@ #ifdef __OBJC__ #import <Cocoa/Cocoa.h> #endif + +#import <WebKit2/WebKit2.h> diff --git a/WebKitTools/MiniBrowser/mac/make-launchable.sh b/WebKitTools/MiniBrowser/mac/make-launchable.sh new file mode 100755 index 0000000..7fba058 --- /dev/null +++ b/WebKitTools/MiniBrowser/mac/make-launchable.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +# Copyright (C) 2010 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 INC. 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 INC. 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. + +echo "Making app bundle launchable"; +defaults write "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH%.plist}" LSEnvironment -dict DYLD_FRAMEWORK_PATH "${BUILT_PRODUCTS_DIR}" diff --git a/WebKitTools/MiniBrowser/win/BrowserWindow.cpp b/WebKitTools/MiniBrowser/win/BrowserWindow.cpp index afe7e42..861d641 100644 --- a/WebKitTools/MiniBrowser/win/BrowserWindow.cpp +++ b/WebKitTools/MiniBrowser/win/BrowserWindow.cpp @@ -109,7 +109,7 @@ void BrowserWindow::createWindow(int x, int y, int width, int height) windowClass.hInstance = MiniBrowser::shared().instance(); windowClass.hIcon = 0; windowClass.hCursor = ::LoadCursor(0, IDC_ARROW); - windowClass.hbrBackground = 0; + windowClass.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); windowClass.lpszMenuName = MAKEINTRESOURCE(IDR_MAINFRAME); windowClass.lpszClassName = L"MiniBrowser"; windowClass.hIconSm = 0; @@ -207,6 +207,17 @@ LRESULT BrowserWindow::onCommand(int commandID, bool& handled) case ID_FILE_CLOSE: ::PostMessage(m_window, WM_CLOSE, 0, 0); break; + case ID_DEBUG_SHOW_WEB_VIEW: { + HMENU menu = ::GetMenu(m_window); + bool shouldHide = ::GetMenuState(menu, ID_DEBUG_SHOW_WEB_VIEW, MF_BYCOMMAND) & MF_CHECKED; + + ::CheckMenuItem(menu, ID_DEBUG_SHOW_WEB_VIEW, MF_BYCOMMAND | (shouldHide ? MF_UNCHECKED : MF_CHECKED)); + + // Show or hide the web view. + HWND webViewWindow = WKViewGetWindow(m_browserView.webView()); + ::ShowWindow(webViewWindow, shouldHide ? SW_HIDE : SW_SHOW); + break; + } default: handled = false; } diff --git a/WebKitTools/MiniBrowser/win/MiniBrowser.rc b/WebKitTools/MiniBrowser/win/MiniBrowser.rc index 556b0f6..6ad0bdc 100644 --- a/WebKitTools/MiniBrowser/win/MiniBrowser.rc +++ b/WebKitTools/MiniBrowser/win/MiniBrowser.rc @@ -1,13 +1,31 @@ // Microsoft Visual C++ generated resource script.
//
#include "resource.h"
-#include "winresrc.h"
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
IDR_MAINFRAME MENU
BEGIN
POPUP "&File"
@@ -16,6 +34,10 @@ BEGIN MENUITEM SEPARATOR
MENUITEM "&Close", ID_FILE_CLOSE
END
+ POPUP "&Debug"
+ BEGIN
+ MENUITEM "&Show WebView", ID_DEBUG_SHOW_WEB_VIEW, CHECKED
+ END
END
@@ -26,5 +48,41 @@ END IDR_MAINFRAME_ACCEL ACCELERATORS
BEGIN
- "N", ID_FILE_NEW_WINDOW, VIRTKEY, CONTROL, NOINVERT
+ "N", ID_FILE_NEW_WINDOW, VIRTKEY, CONTROL, NOINVERT
END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.\0"
+END
+
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/WebKitTools/MiniBrowser/win/resource.h b/WebKitTools/MiniBrowser/win/resource.h index ce07800..b12b906 100644 --- a/WebKitTools/MiniBrowser/win/resource.h +++ b/WebKitTools/MiniBrowser/win/resource.h @@ -6,6 +6,7 @@ #define ID_FILE_NEW_WINDOW 32770 #define ID_FILE_OPEN 32771 #define ID_FILE_CLOSE 32772 +#define ID_DEBUG_SHOW_WEB_VIEW 32773 #define IDR_MAINFRAME 128 diff --git a/WebKitTools/QtLauncher/QtLauncher.pro b/WebKitTools/QtLauncher/QtLauncher.pro index 0873bda..a91cee9 100644 --- a/WebKitTools/QtLauncher/QtLauncher.pro +++ b/WebKitTools/QtLauncher/QtLauncher.pro @@ -8,6 +8,7 @@ SOURCES += \ utils.cpp \ webpage.cpp \ webview.cpp \ + fpstimer.cpp \ HEADERS += \ locationedit.h \ @@ -17,6 +18,7 @@ HEADERS += \ webinspector.h \ webpage.h \ webview.h \ + fpstimer.h \ CONFIG -= app_bundle CONFIG += uitools diff --git a/WebCore/svg/graphics/SVGPaintServerLinearGradient.cpp b/WebKitTools/QtLauncher/fpstimer.cpp index 08db2d2..3b72cef 100644 --- a/WebCore/svg/graphics/SVGPaintServerLinearGradient.cpp +++ b/WebKitTools/QtLauncher/fpstimer.cpp @@ -1,5 +1,7 @@ /* - * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -20,55 +22,56 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" - -#if ENABLE(SVG) -#include "SVGPaintServerLinearGradient.h" -#include "SVGRenderTreeAsText.h" +#include "fpstimer.h" -namespace WebCore { +#include <QDateTime> +#include <QTimerEvent> -SVGPaintServerLinearGradient::SVGPaintServerLinearGradient(const SVGGradientElement* owner) - : SVGPaintServerGradient(owner) -{ -} +// We save a maximum of 10000 frames, and purge 2000 at a time +#define MAX_FRAMES_SAVED 10000 +#define FRAMES_TO_PURGE_WHEN_FULL 2000 +// 60 FPS +#define FPS_MEASURE_INTERVAL 1000 / 60 -SVGPaintServerLinearGradient::~SVGPaintServerLinearGradient() +FpsTimer::FpsTimer(QObject* parent) + : QObject(parent) { } -FloatPoint SVGPaintServerLinearGradient::gradientStart() const +int FpsTimer::numFrames(int spanMillis) { - return m_start; -} + const QTime now = QTime::currentTime(); -void SVGPaintServerLinearGradient::setGradientStart(const FloatPoint& start) -{ - m_start = start; + int count = 0; + for (int i = m_frames.length() - 1; i >= 0; --i, ++count) { + int msecs = m_frames[i].msecsTo(now); + if (msecs < 0) + msecs += 24 * 60 * 60 * 1000; + if (msecs > spanMillis) + break; + } + return count; } -FloatPoint SVGPaintServerLinearGradient::gradientEnd() const +void FpsTimer::start() { - return m_end; + m_timer = startTimer(FPS_MEASURE_INTERVAL); } -void SVGPaintServerLinearGradient::setGradientEnd(const FloatPoint& end) +void FpsTimer::stop() { - m_end = end; + killTimer(m_timer); + m_frames.clear(); } -TextStream& SVGPaintServerLinearGradient::externalRepresentation(TextStream& ts) const +void FpsTimer::timerEvent(QTimerEvent* event) { - ts << "[type=LINEAR-GRADIENT] "; - SVGPaintServerGradient::externalRepresentation(ts); - ts << " [start=" << gradientStart() << "]" - << " [end=" << gradientEnd() << "]"; - return ts; + if (event->timerId() != m_timer) + return; + m_frames.append(QTime::currentTime()); + if (m_frames.length() > MAX_FRAMES_SAVED) + m_frames.erase(m_frames.begin(), m_frames.begin() + FRAMES_TO_PURGE_WHEN_FULL); } - -} // namespace WebCore - -#endif diff --git a/WebKitTools/QtLauncher/fpstimer.h b/WebKitTools/QtLauncher/fpstimer.h new file mode 100644 index 0000000..66d38eb --- /dev/null +++ b/WebKitTools/QtLauncher/fpstimer.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * 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 fpsmeasure_h +#define fpsmeasure_h + +#include <QObject> +#include <QSet> +#include <QTime> + +class FpsTimer : public QObject { + Q_OBJECT + +public: + FpsTimer(QObject* parent = 0); + int numFrames(int spanMillis = 1000); + +public Q_SLOTS: + void start(); + void stop(); + +protected slots: + virtual void timerEvent(QTimerEvent*); + +private: + int m_timer; + QList<QTime> m_frames; +}; + +#endif // FPSMEASURE_H diff --git a/WebKitTools/QtLauncher/main.cpp b/WebKitTools/QtLauncher/main.cpp index a03d135..748936b 100644 --- a/WebKitTools/QtLauncher/main.cpp +++ b/WebKitTools/QtLauncher/main.cpp @@ -237,10 +237,9 @@ void LauncherWindow::init(bool useGraphicsView) this, SLOT(showLinkHover(const QString&, const QString&))); connect(this, SIGNAL(enteredFullScreenMode(bool)), this, SLOT(toggleFullScreenMode(bool))); - if (!gInspectorUrl.isEmpty()) - page()->settings()->setInspectorUrl(gInspectorUrl); - m_inspector = new WebInspector(splitter); + if (!gInspectorUrl.isEmpty()) + m_inspector->setProperty("_q_inspectorUrl", gInspectorUrl); m_inspector->setPage(page()); m_inspector->hide(); connect(this, SIGNAL(destroyed()), m_inspector, SLOT(deleteLater())); diff --git a/WebKitTools/QtLauncher/webview.cpp b/WebKitTools/QtLauncher/webview.cpp index 8c94438..1467cf8 100644 --- a/WebKitTools/QtLauncher/webview.cpp +++ b/WebKitTools/QtLauncher/webview.cpp @@ -99,6 +99,7 @@ void WebViewGraphicsBased::resizeEvent(QResizeEvent* event) return; QRectF rect(QPoint(0, 0), event->size()); m_item->setGeometry(rect); + scene()->setSceneRect(rect); } void WebViewGraphicsBased::setFrameRateMeasurementEnabled(bool enabled) @@ -106,25 +107,24 @@ void WebViewGraphicsBased::setFrameRateMeasurementEnabled(bool enabled) m_measureFps = enabled; if (m_measureFps) { m_lastConsultTime = m_startTime = QTime::currentTime(); + m_fpsTimer.start(); m_updateTimer->start(); - } else + } else { + m_fpsTimer.stop(); m_updateTimer->stop(); + } } void WebViewGraphicsBased::updateFrameRate() { - QTime now = QTime::currentTime(); - + const QTime now = QTime::currentTime(); int interval = m_lastConsultTime.msecsTo(now); - int total = m_startTime.msecsTo(now); - - int average = total ? m_numPaintsTotal * 1000 / total : 0; - int current = interval ? m_numPaintsSinceLastMeasure * 1000 / interval : 0; + int frames = m_fpsTimer.numFrames(interval); + int current = interval ? frames * 1000 / interval : 0; emit currentFPSUpdated(current); m_lastConsultTime = now; - m_numPaintsSinceLastMeasure = 0; } void WebViewGraphicsBased::animatedFlip() @@ -156,8 +156,6 @@ void WebViewGraphicsBased::paintEvent(QPaintEvent* event) QGraphicsView::paintEvent(event); if (!m_measureFps) return; - m_numPaintsSinceLastMeasure++; - m_numPaintsTotal++; } static QMenu* createContextMenu(QWebPage* page, QPoint position) diff --git a/WebKitTools/QtLauncher/webview.h b/WebKitTools/QtLauncher/webview.h index e8c3226..30161bb 100644 --- a/WebKitTools/QtLauncher/webview.h +++ b/WebKitTools/QtLauncher/webview.h @@ -33,6 +33,7 @@ #ifndef webview_h #define webview_h +#include "fpstimer.h" #include "webpage.h" #include <qwebview.h> #include <qgraphicswebview.h> @@ -119,6 +120,7 @@ private: bool m_measureFps; qreal m_yRotation; bool m_resizesToContents; + FpsTimer m_fpsTimer; }; #endif diff --git a/WebKitTools/Scripts/VCSUtils.pm b/WebKitTools/Scripts/VCSUtils.pm index 25a319b..777fe7f 100644 --- a/WebKitTools/Scripts/VCSUtils.pm +++ b/WebKitTools/Scripts/VCSUtils.pm @@ -65,6 +65,7 @@ BEGIN { &normalizePath &parsePatch &pathRelativeToSVNRepositoryRootForPath + &prepareParsedPatch &runPatchCommand &svnRevisionForDirectory &svnStatus @@ -96,6 +97,40 @@ sub exitStatus($) return WEXITSTATUS($returnvalue); } +# Note, this method will not error if the file corresponding to the path does not exist. +sub scmToggleExecutableBit +{ + my ($path, $executableBitDelta) = @_; + return if ! -e $path; + if ($executableBitDelta == 1) { + scmAddExecutableBit($path); + } elsif ($executableBitDelta == -1) { + scmRemoveExecutableBit($path); + } +} + +sub scmAddExecutableBit($) +{ + my ($path) = @_; + + if (isSVN()) { + system("svn", "propset", "svn:executable", "on", $path) == 0 or die "Failed to run 'svn propset svn:executable on $path'."; + } elsif (isGit()) { + chmod(0755, $path); + } +} + +sub scmRemoveExecutableBit($) +{ + my ($path) = @_; + + if (isSVN()) { + system("svn", "propdel", "svn:executable", $path) == 0 or die "Failed to run 'svn propdel svn:executable $path'."; + } elsif (isGit()) { + chmod(0664, $path); + } +} + sub isGitDirectory($) { my ($dir) = @_; @@ -362,126 +397,298 @@ sub svnStatus($) return $svnStatus; } -# Convert a line of a git-formatted patch to SVN format, while -# preserving any end-of-line characters. -sub gitdiff2svndiff($) +# Return whether the given file mode is executable in the source control +# sense. We make this determination based on whether the executable bit +# is set for "others" rather than the stronger condition that it be set +# for the user, group, and others. This is sufficient for distinguishing +# the default behavior in Git and SVN. +# +# Args: +# $fileMode: A number or string representing a file mode in octal notation. +sub isExecutable($) { - $_ = shift @_; + my $fileMode = shift; - if (m#^diff --git \w/(.+) \w/([^\r\n]+)#) { - return "Index: $1$POSTMATCH"; - } - if (m#^index [0-9a-f]{7}\.\.[0-9a-f]{7} [0-9]{6}#) { - # FIXME: No need to return dividing line once parseDiffHeader() is used. - return "===================================================================$POSTMATCH"; - } - if (m#^--- \w/([^\r\n]+)#) { - return "--- $1$POSTMATCH"; - } - if (m#^\+\+\+ \w/([^\r\n]+)#) { - return "+++ $1$POSTMATCH"; - } - return $_; + return $fileMode % 2; } -# Parse the next diff header from the given file handle, and advance -# the file handle so the last line read is the first line after the -# parsed header block. +# Parse the next Git diff header from the given file handle, and advance +# the handle so the last line read is the first line after the header. # -# This subroutine dies if given leading junk or if the end of the header -# block could not be detected. The last line of a header block is a -# line beginning with "+++". +# This subroutine dies if given leading junk. # # Args: -# $fileHandle: advanced so the last line read is the first line of the -# next diff header. For SVN-formatted diffs, this is the -# "Index:" line. +# $fileHandle: advanced so the last line read from the handle is the first +# line of the header to parse. This should be a line +# beginning with "diff --git". # $line: the line last read from $fileHandle # # Returns ($headerHashRef, $lastReadLine): -# $headerHashRef: a hash reference representing a diff header -# copiedFromPath: if a file copy, the path from which the file was -# copied. Otherwise, undefined. -# indexPath: the path in the "Index:" line. -# sourceRevision: the revision number of the source. This is the same -# as the revision number the file was copied from, in -# the case of a file copy. -# svnConvertedText: the header text converted to SVN format. -# Unrecognized lines are discarded. -# $lastReadLine: the line last read from $fileHandle. This is the first -# line after the header ending. -sub parseDiffHeader($$) +# $headerHashRef: a hash reference representing a diff header, as follows-- +# copiedFromPath: the path from which the file was copied if the diff +# is a copy. +# executableBitDelta: the value 1 or -1 if the executable bit was added or +# removed, respectively. New and deleted files have +# this value only if the file is executable, in which +# case the value is 1 and -1, respectively. +# indexPath: the path of the target file. +# isBinary: the value 1 if the diff is for a binary file. +# svnConvertedText: the header text with some lines converted to SVN +# format. Git-specific lines are preserved. +# $lastReadLine: the line last read from $fileHandle. +sub parseGitDiffHeader($$) { my ($fileHandle, $line) = @_; - my $filter; - if ($line =~ m#^diff --git #) { - $filter = \&gitdiff2svndiff; - } - $line = &$filter($line) if $filter; + $_ = $line; + my $headerStartRegEx = qr#^diff --git (\w/)?(.+) (\w/)?([^\r\n]+)#; my $indexPath; - if ($line =~ /^Index: ([^\r\n]+)/) { - $indexPath = $1; + if (/$headerStartRegEx/) { + # The first and second paths can differ in the case of copies + # and renames. We use the second file path because it is the + # destination path. + $indexPath = $4; + # Use $POSTMATCH to preserve the end-of-line character. + $_ = "Index: $indexPath$POSTMATCH"; # Convert to SVN format. } else { - die("Could not parse first line of diff header: \"$line\"."); + die("Could not parse leading \"diff --git\" line: \"$line\"."); } + my $copiedFromPath; + my $foundHeaderEnding; + my $isBinary; + my $newExecutableBit = 0; + my $oldExecutableBit = 0; + my $similarityIndex; + my $svnConvertedText; + while (1) { + # Temporarily strip off any end-of-line characters to simplify + # regex matching below. + s/([\n\r]+)$//; + my $eol = $1; + + if (/^(deleted file|old) mode ([0-9]{6})/) { + $oldExecutableBit = (isExecutable($2) ? 1 : 0); + } elsif (/^new( file)? mode ([0-9]{6})/) { + $newExecutableBit = (isExecutable($2) ? 1 : 0); + } elsif (/^--- \S+/) { + $_ = "--- $indexPath"; # Convert to SVN format. + } elsif (/^\+\+\+ \S+/) { + $_ = "+++ $indexPath"; # Convert to SVN format. + $foundHeaderEnding = 1; + } elsif (/^similarity index (\d+)%/) { + $similarityIndex = $1; + } elsif (/^copy from (\S+)/) { + $copiedFromPath = $1; + # The "git diff" command includes a line of the form "Binary files + # <path1> and <path2> differ" if the --binary flag is not used. + } elsif (/^Binary files / ) { + die("Error: the Git diff contains a binary file without the binary data in ". + "line: \"$_\". Be sure to use the --binary flag when invoking \"git diff\" ". + "with diffs containing binary files."); + } elsif (/^GIT binary patch$/ ) { + $isBinary = 1; + $foundHeaderEnding = 1; + } + + $svnConvertedText .= "$_$eol"; # Also restore end-of-line characters. + + $_ = <$fileHandle>; # Not defined if end-of-file reached. + + last if (!defined($_) || /$headerStartRegEx/ || $foundHeaderEnding); + } + + my $executableBitDelta = $newExecutableBit - $oldExecutableBit; + my %header; + $header{copiedFromPath} = $copiedFromPath if ($copiedFromPath && $similarityIndex == 100); + $header{executableBitDelta} = $executableBitDelta if $executableBitDelta; + $header{indexPath} = $indexPath; + $header{isBinary} = $isBinary if $isBinary; + $header{svnConvertedText} = $svnConvertedText; + + return (\%header, $_); +} + +# Parse the next SVN diff header from the given file handle, and advance +# the handle so the last line read is the first line after the header. +# +# This subroutine dies if given leading junk or if it could not detect +# the end of the header block. +# +# Args: +# $fileHandle: advanced so the last line read from the handle is the first +# line of the header to parse. This should be a line +# beginning with "Index:". +# $line: the line last read from $fileHandle +# +# Returns ($headerHashRef, $lastReadLine): +# $headerHashRef: a hash reference representing a diff header, as follows-- +# copiedFromPath: the path from which the file was copied if the diff +# is a copy. +# indexPath: the path of the target file, which is the path found in +# the "Index:" line. +# isBinary: the value 1 if the diff is for a binary file. +# sourceRevision: the revision number of the source, if it exists. This +# is the same as the revision number the file was copied +# from, in the case of a file copy. +# svnConvertedText: the header text converted to a header with the paths +# in some lines corrected. +# $lastReadLine: the line last read from $fileHandle. +sub parseSvnDiffHeader($$) +{ + my ($fileHandle, $line) = @_; + + $_ = $line; + + my $headerStartRegEx = qr/^Index: /; + + if (!/$headerStartRegEx/) { + die("First line of SVN diff does not begin with \"Index \": \"$_\""); + } + + my $copiedFromPath; my $foundHeaderEnding; - my $lastReadLine; + my $indexPath; + my $isBinary; my $sourceRevision; - my $svnConvertedText = $line; - while (<$fileHandle>) { + my $svnConvertedText; + while (1) { # Temporarily strip off any end-of-line characters to simplify # regex matching below. s/([\n\r]+)$//; my $eol = $1; - $_ = &$filter($_) if $filter; - # Fix paths on ""---" and "+++" lines to match the leading # index line. - if (s/^--- \S+/--- $indexPath/) { + if (/^Index: ([^\r\n]+)/) { + $indexPath = $1; + } elsif (s/^--- \S+/--- $indexPath/) { # --- if (/^--- .+\(revision (\d+)\)/) { - $sourceRevision = $1 if ($1 != 0); + $sourceRevision = $1; if (/\(from (\S+):(\d+)\)$/) { # The "from" clause is created by svn-create-patch, in # which case there is always also a "revision" clause. - $header{copiedFromPath} = $1; + $copiedFromPath = $1; die("Revision number \"$2\" in \"from\" clause does not match " . "source revision number \"$sourceRevision\".") if ($2 != $sourceRevision); } } - $_ = "=" x 67 . "$eol$_"; # Prepend dividing line ===.... } elsif (s/^\+\+\+ \S+/+++ $indexPath/) { - # +++ $foundHeaderEnding = 1; - } else { - # Skip unrecognized lines. - next; + } elsif (/^Cannot display: file marked as a binary type.$/) { + $isBinary = 1; + $foundHeaderEnding = 1; } $svnConvertedText .= "$_$eol"; # Also restore end-of-line characters. - if ($foundHeaderEnding) { - $lastReadLine = <$fileHandle>; - last; - } - } # $lastReadLine is undef if while loop ran out. + + $_ = <$fileHandle>; # Not defined if end-of-file reached. + + last if (!defined($_) || /$headerStartRegEx/ || $foundHeaderEnding); + } if (!$foundHeaderEnding) { die("Did not find end of header block corresponding to index path \"$indexPath\"."); } + my %header; + + $header{copiedFromPath} = $copiedFromPath if $copiedFromPath; $header{indexPath} = $indexPath; - $header{sourceRevision} = $sourceRevision; + $header{isBinary} = $isBinary if $isBinary; + $header{sourceRevision} = $sourceRevision if $sourceRevision; $header{svnConvertedText} = $svnConvertedText; - return (\%header, $lastReadLine); + return (\%header, $_); } +# Parse the next diff header from the given file handle, and advance +# the handle so the last line read is the first line after the header. +# +# This subroutine dies if given leading junk or if it could not detect +# the end of the header block. +# +# Args: +# $fileHandle: advanced so the last line read from the handle is the first +# line of the header to parse. For SVN-formatted diffs, this +# is a line beginning with "Index:". For Git, this is a line +# beginning with "diff --git". +# $line: the line last read from $fileHandle +# +# Returns ($headerHashRef, $lastReadLine): +# $headerHashRef: a hash reference representing a diff header +# copiedFromPath: the path from which the file was copied if the diff +# is a copy. +# executableBitDelta: the value 1 or -1 if the executable bit was added or +# removed, respectively. New and deleted files have +# this value only if the file is executable, in which +# case the value is 1 and -1, respectively. +# indexPath: the path of the target file. +# isBinary: the value 1 if the diff is for a binary file. +# isGit: the value 1 if the diff is Git-formatted. +# isSvn: the value 1 if the diff is SVN-formatted. +# sourceRevision: the revision number of the source, if it exists. This +# is the same as the revision number the file was copied +# from, in the case of a file copy. +# svnConvertedText: the header text with some lines converted to SVN +# format. Git-specific lines are preserved. +# $lastReadLine: the line last read from $fileHandle. +sub parseDiffHeader($$) +{ + my ($fileHandle, $line) = @_; + + my $header; # This is a hash ref. + my $isGit; + my $isSvn; + my $lastReadLine; + + if ($line =~ /^Index:/) { + $isSvn = 1; + ($header, $lastReadLine) = parseSvnDiffHeader($fileHandle, $line); + } elsif ($line =~ /^diff --git/) { + $isGit = 1; + ($header, $lastReadLine) = parseGitDiffHeader($fileHandle, $line); + } else { + die("First line of diff does not begin with \"Index:\" or \"diff --git\": \"$line\""); + } + + $header->{isGit} = $isGit if $isGit; + $header->{isSvn} = $isSvn if $isSvn; + + return ($header, $lastReadLine); +} + +# FIXME: The %diffHash "object" should not have an svnConvertedText property. +# Instead, the hash object should store its information in a +# structured way as properties. This should be done in a way so +# that, if necessary, the text of an SVN or Git patch can be +# reconstructed from the information in those hash properties. +# +# A %diffHash is a hash representing a source control diff of a single +# file operation (e.g. a file modification, copy, or delete). +# +# These hashes appear, for example, in the parseDiff(), parsePatch(), +# and prepareParsedPatch() subroutines of this package. +# +# The corresponding values are-- +# +# copiedFromPath: the path from which the file was copied if the diff +# is a copy. +# indexPath: the path of the target file. For SVN-formatted diffs, +# this is the same as the path in the "Index:" line. +# isBinary: the value 1 if the diff is for a binary file. +# isGit: the value 1 if the diff is Git-formatted. +# isSvn: the value 1 if the diff is SVN-formatted. +# sourceRevision: the revision number of the source, if it exists. This +# is the same as the revision number the file was copied +# from, in the case of a file copy. +# svnConvertedText: the diff with some lines converted to SVN format. +# Git-specific lines are preserved. + # Parse one diff from a patch file created by svn-create-patch, and # advance the file handle so the last line read is the first line # of the next header block. @@ -494,14 +701,8 @@ sub parseDiffHeader($$) # $line: the line last read from $fileHandle. # # Returns ($diffHashRef, $lastReadLine): -# $diffHashRef: -# copiedFromPath: if a file copy, the path from which the file was -# copied. Otherwise, undefined. -# indexPath: the path in the "Index:" line. -# sourceRevision: the revision number of the source. This is the same -# as the revision number the file was copied from, in -# the case of a file copy. -# svnConvertedText: the diff converted to SVN format. +# $diffHashRef: A reference to a %diffHash. +# See the %diffHash documentation above. # $lastReadLine: the line last read from $fileHandle sub parseDiff($$) { @@ -538,9 +739,15 @@ sub parseDiff($$) } my %diffHashRef; - $diffHashRef{copiedFromPath} = $headerHashRef->{copiedFromPath}; + $diffHashRef{copiedFromPath} = $headerHashRef->{copiedFromPath} if $headerHashRef->{copiedFromPath}; + # FIXME: Add executableBitDelta as a key. $diffHashRef{indexPath} = $headerHashRef->{indexPath}; - $diffHashRef{sourceRevision} = $headerHashRef->{sourceRevision}; + $diffHashRef{isBinary} = $headerHashRef->{isBinary} if $headerHashRef->{isBinary}; + $diffHashRef{isGit} = $headerHashRef->{isGit} if $headerHashRef->{isGit}; + $diffHashRef{isSvn} = $headerHashRef->{isSvn} if $headerHashRef->{isSvn}; + $diffHashRef{sourceRevision} = $headerHashRef->{sourceRevision} if $headerHashRef->{sourceRevision}; + # FIXME: Remove the need for svnConvertedText. See the %diffHash + # code comments above for more information. $diffHashRef{svnConvertedText} = $svnText; return (\%diffHashRef, $line); @@ -553,8 +760,8 @@ sub parseDiff($$) # read from. # # Returns: -# @diffHashRefs: an array of diff hash references. See parseDiff() for -# a description of each $diffHashRef. +# @diffHashRefs: an array of diff hash references. +# See the %diffHash documentation above. sub parsePatch($) { my ($fileHandle) = @_; @@ -574,6 +781,78 @@ sub parsePatch($) return @diffHashRefs; } +# Prepare the results of parsePatch() for use in svn-apply and svn-unapply. +# +# Args: +# $shouldForce: Whether to continue processing if an unexpected +# state occurs. +# @diffHashRefs: An array of references to %diffHashes. +# See the %diffHash documentation above. +# +# Returns $preparedPatchHashRef: +# copyDiffHashRefs: A reference to an array of the $diffHashRefs in +# @diffHashRefs that represent file copies. The original +# ordering is preserved. +# nonCopyDiffHashRefs: A reference to an array of the $diffHashRefs in +# @diffHashRefs that do not represent file copies. +# The original ordering is preserved. +# sourceRevisionHash: A reference to a hash of source path to source +# revision number. +sub prepareParsedPatch($@) +{ + my ($shouldForce, @diffHashRefs) = @_; + + my %copiedFiles; + + # Return values + my @copyDiffHashRefs = (); + my @nonCopyDiffHashRefs = (); + my %sourceRevisionHash = (); + for my $diffHashRef (@diffHashRefs) { + my $copiedFromPath = $diffHashRef->{copiedFromPath}; + my $indexPath = $diffHashRef->{indexPath}; + my $sourceRevision = $diffHashRef->{sourceRevision}; + my $sourcePath; + + if (defined($copiedFromPath)) { + # Then the diff is a copy operation. + $sourcePath = $copiedFromPath; + + # FIXME: Consider printing a warning or exiting if + # exists($copiedFiles{$indexPath}) is true -- i.e. if + # $indexPath appears twice as a copy target. + $copiedFiles{$indexPath} = $sourcePath; + + push @copyDiffHashRefs, $diffHashRef; + } else { + # Then the diff is not a copy operation. + $sourcePath = $indexPath; + + push @nonCopyDiffHashRefs, $diffHashRef; + } + + if (defined($sourceRevision)) { + if (exists($sourceRevisionHash{$sourcePath}) && + ($sourceRevisionHash{$sourcePath} != $sourceRevision)) { + if (!$shouldForce) { + die "Two revisions of the same file required as a source:\n". + " $sourcePath:$sourceRevisionHash{$sourcePath}\n". + " $sourcePath:$sourceRevision"; + } + } + $sourceRevisionHash{$sourcePath} = $sourceRevision; + } + } + + my %preparedPatchHash; + + $preparedPatchHash{copyDiffHashRefs} = \@copyDiffHashRefs; + $preparedPatchHash{nonCopyDiffHashRefs} = \@nonCopyDiffHashRefs; + $preparedPatchHash{sourceRevisionHash} = \%sourceRevisionHash; + + return \%preparedPatchHash; +} + # If possible, returns a ChangeLog patch equivalent to the given one, # but with the newest ChangeLog entry inserted at the top of the # file -- i.e. no leading context and all lines starting with "+". diff --git a/WebKitTools/Scripts/build-dumprendertree b/WebKitTools/Scripts/build-dumprendertree index 14690a8..6502916 100755 --- a/WebKitTools/Scripts/build-dumprendertree +++ b/WebKitTools/Scripts/build-dumprendertree @@ -75,7 +75,7 @@ if (isAppleMacWebKit()) { $result = 0; } elsif (isChromium()) { if (isDarwin()) { - $result = buildXCodeProject("DumpRenderTree.gyp/DumpRenderTree", $clean, @ARGV); + $result = buildXCodeProject("DumpRenderTree.gyp/DumpRenderTree", $clean, "-configuration", configuration(), @ARGV); } elsif (isCygwin() || isWindows()) { # Windows build - builds the root visual studio solution. $result = buildChromiumVisualStudioProject("DumpRenderTree.gyp/DumpRenderTree.sln", $clean); diff --git a/WebKitTools/Scripts/build-webkit b/WebKitTools/Scripts/build-webkit index 2d172c5..3a3edb9 100755 --- a/WebKitTools/Scripts/build-webkit +++ b/WebKitTools/Scripts/build-webkit @@ -48,7 +48,6 @@ chdirWebKit(); my $showHelp = 0; my $clean = 0; my $minimal = 0; -my $webkit2 = 0; my $makeArgs; my $startTime = time(); @@ -224,7 +223,6 @@ Usage: $programName [options] [options to pass to build system] --chromium Build the Chromium port on Mac/Win/Linux --gtk Build the GTK+ port --qt Build the Qt port - --webkit2 Build the WebKit2 framework --inspector-frontend Copy changes to the inspector front-end files to the build directory --makeargs=<arguments> Optional Makefile flags @@ -238,7 +236,6 @@ my %options = ( 'clean' => \$clean, 'makeargs=s' => \$makeArgs, 'minimal' => \$minimal, - 'webkit2' => \$webkit2, ); # Build usage text and options list from features @@ -261,16 +258,7 @@ setConfiguration(); my $productDir = productDir(); # Check that all the project directories are there. -my @projects = ("JavaScriptCore", "WebCore"); - -if (!$webkit2) { - push @projects, "WebKit"; -} else { - push @projects, ("WebKit2", "WebKitTools/MiniBrowser"); -} - -# Only Apple builds JavaScriptGlue, and only on the Mac -splice @projects, 1, 0, "JavaScriptGlue" if isAppleMacWebKit(); +my @projects = ("JavaScriptCore", "WebCore", "WebKit"); my @otherDirs = ("WebKitLibraries"); for my $dir (@projects, @otherDirs) { @@ -306,8 +294,13 @@ if (isGtk()) { } } - # Copy library and header from WebKitLibraries to a findable place in the product directory. + # Apple builds JavaScriptGlue, and only on the Mac. + splice @projects, 1, 0, "JavaScriptGlue"; + + # WebKit2 is only supported in SnowLeopard and later at present. + push @projects, ("WebKit2", "WebKitTools/MiniBrowser") if osXVersion()->{"minor"} >= 6; + # Copy library and header from WebKitLibraries to a findable place in the product directory. my @librariesToCopy = ( "libWebKitSystemInterfaceTiger.a", "libWebKitSystemInterfaceLeopard.a", @@ -350,6 +343,10 @@ if (isGtk()) { foreach (@features) { push @options, "DEFINES+=$_->{define}=${$_->{value}}" if ${$_->{value}} != $_->{default}; } + + if ($minimal) { + push @options, "CONFIG+=minimal"; + } } # Force re-link of existing libraries if different than expected @@ -367,6 +364,7 @@ if (isWx()) { } if (isChromium()) { + @options = @ARGV; # Chromium doesn't build by project directories. @projects = (); my $result = buildChromium($clean, @options); @@ -389,18 +387,8 @@ for my $dir (@projects) { } elsif (isQt()) { $result = buildQMakeQtProject($dir, $clean, @options); } elsif (isAppleMacWebKit()) { - my @completeOptions = @options; - if ($webkit2 && $dir eq "WebCore") { - my @webKit2SpecificOverrides = ( - 'UMBRELLA_LDFLAGS=', - 'GCC_PREPROCESSOR_DEFINITIONS=$(GCC_PREPROCESSOR_DEFINITIONS) ' . - 'ENABLE_EXPERIMENTAL_SINGLE_VIEW_MODE=1 ' . - 'WTF_USE_WEB_THREAD=1 ' - ); - push @completeOptions, @webKit2SpecificOverrides; - } - - $result = buildXCodeProject($dir, $clean, @completeOptions, @ARGV); + $dir = "MiniBrowser" if $dir eq "WebKitTools/MiniBrowser"; + $result = buildXCodeProject($dir, $clean, @options, @ARGV); } elsif (isAppleWinWebKit()) { if ($dir eq "WebKit") { $result = buildVisualStudioProject("win/WebKit.vcproj/WebKit.sln", $clean); @@ -461,16 +449,10 @@ sub writeCongrats() print "\n"; print "===========================================================\n"; - if ($webkit2) { - print " WebKit2 is now built ($buildTime). \n"; - print " To run MiniBrowser with this newly-built code, use the\n"; - print " \"run-minibrowser\" script.\n"; - } else { - print " WebKit is now built ($buildTime). \n"; - if (!isChromium()) { - print " To run $launcherName with this newly-built code, use the\n"; - print " \"$launcherPath\" script.\n"; - } + print " WebKit is now built ($buildTime). \n"; + if (!isChromium()) { + print " To run $launcherName with this newly-built code, use the\n"; + print " \"$launcherPath\" script.\n"; } print "===========================================================\n"; } diff --git a/WebKitTools/Scripts/check-webkit-style b/WebKitTools/Scripts/check-webkit-style index 9897fbd..f74c3bd 100755 --- a/WebKitTools/Scripts/check-webkit-style +++ b/WebKitTools/Scripts/check-webkit-style @@ -50,7 +50,9 @@ import sys from webkitpy.style_references import detect_checkout import webkitpy.style.checker as checker -from webkitpy.style.checker import PatchChecker +from webkitpy.style.checker import PatchReader +from webkitpy.style.checker import StyleProcessor +from webkitpy.style.filereader import TextFileReader from webkitpy.style.main import change_directory _log = logging.getLogger("check-webkit-style") @@ -84,41 +86,42 @@ def main(): checker.configure_logging(stream=stderr, is_verbose=is_verbose) _log.debug("Verbose logging enabled.") + parser = checker.check_webkit_style_parser() + (paths, options) = parser.parse(args) + checkout = detect_checkout() if checkout is None: + if not paths: + _log.error("WebKit checkout not found: You must run this script " + "from within a WebKit checkout if you are not passing " + "specific paths to check.") + sys.exit(1) + checkout_root = None _log.debug("WebKit checkout not found for current directory.") else: checkout_root = checkout.root_path() _log.debug("WebKit checkout found with root: %s" % checkout_root) - parser = checker.check_webkit_style_parser() - (paths, options) = parser.parse(args) - - if checkout is None and not paths: - _log.error("WebKit checkout not found: You must run this script " - "from within a WebKit checkout if you are not passing " - "specific paths to check.") - sys.exit(1) - configuration = checker.check_webkit_style_configuration(options) - style_checker = checker.StyleChecker(configuration) paths = change_directory(checkout_root=checkout_root, paths=paths) + style_processor = StyleProcessor(configuration) + + file_reader = TextFileReader(style_processor) + if paths: - style_checker.check_paths(paths) + file_reader.process_paths(paths) else: - if options.git_commit: - patch = checkout.create_patch_since_local_commit(options.git_commit) - else: - patch = checkout.create_patch() - patch_checker = PatchChecker(style_checker) + patch = checkout.create_patch(options.git_commit, options.squash) + patch_checker = PatchReader(file_reader) patch_checker.check(patch) - error_count = style_checker.error_count - file_count = style_checker.file_count + error_count = style_processor.error_count + file_count = file_reader.file_count + _log.info("Total errors found: %d in %d files" % (error_count, file_count)) # We fail when style errors are found or there are no checked files. diff --git a/WebKitTools/Scripts/extract-localizable-strings b/WebKitTools/Scripts/extract-localizable-strings index cf4f8f0..b31550a 100755 --- a/WebKitTools/Scripts/extract-localizable-strings +++ b/WebKitTools/Scripts/extract-localizable-strings @@ -1,6 +1,6 @@ #!/usr/bin/perl -w -# Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved. +# Copyright (C) 2006, 2007, 2009, 2010 Apple Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -48,7 +48,7 @@ sub UnescapeHexSequence($); my %isDebugMacro = ( ASSERT_WITH_MESSAGE => 1, LOG_ERROR => 1, ERROR => 1, NSURL_ERROR => 1, FATAL => 1, LOG => 1, LOG_WARNING => 1, UI_STRING_LOCALIZE_LATER => 1, LPCTSTR_UI_STRING_LOCALIZE_LATER => 1, UNLOCALIZED_STRING => 1, UNLOCALIZED_LPCTSTR => 1, dprintf => 1, NSException => 1, NSLog => 1, printf => 1 ); -@ARGV >= 1 or die "Usage: extract-localizable-strings <exceptions file> [ directory... ]\nDid you mean to run update-webkit-localizable-strings instead?\n"; +@ARGV >= 2 or die "Usage: extract-localizable-strings <exceptions file> <file to update> [ directory... ]\nDid you mean to run update-webkit-localizable-strings instead?\n"; my $exceptionsFile = shift @ARGV; -f $exceptionsFile or die "Couldn't find exceptions file $exceptionsFile\n"; @@ -99,14 +99,13 @@ if (open EXCEPTIONS, $exceptionsFile) { my $quotedDirectoriesString = '"' . join('" "', @directories) . '"'; for my $dir (@directoriesToSkip) { - $quotedDirectoriesString .= ' -path "' . $dir . '" -prune'; + $quotedDirectoriesString .= ' -path "' . $dir . '" -prune -o'; } -my @files = ( split "\n", `find $quotedDirectoriesString -name "*.h" -o -name "*.m" -o -name "*.mm" -o -name "*.c" -o -name "*.cpp"` ); +my @files = ( split "\n", `find $quotedDirectoriesString \\( -name "*.h" -o -name "*.m" -o -name "*.mm" -o -name "*.c" -o -name "*.cpp" \\)` ); for my $file (sort @files) { - next if $file =~ /\/WebLocalizableStrings\.h$/; - next if $file =~ /\/icu\//; + next if $file =~ /\/\w+LocalizableStrings\.h$/; $file =~ s-^./--; diff --git a/WebKitTools/Scripts/new-run-webkit-tests b/WebKitTools/Scripts/new-run-webkit-tests index 2ebe1da..0728ee0 100755 --- a/WebKitTools/Scripts/new-run-webkit-tests +++ b/WebKitTools/Scripts/new-run-webkit-tests @@ -33,5 +33,4 @@ import sys import webkitpy.layout_tests.run_webkit_tests as run_webkit_tests if __name__ == '__main__': - options, args = run_webkit_tests.parse_args() - sys.exit(run_webkit_tests.main(options, args)) + sys.exit(run_webkit_tests.main()) diff --git a/WebKitTools/Scripts/old-run-webkit-tests b/WebKitTools/Scripts/old-run-webkit-tests index d5d7349..f6dbf5b 100755 --- a/WebKitTools/Scripts/old-run-webkit-tests +++ b/WebKitTools/Scripts/old-run-webkit-tests @@ -501,6 +501,10 @@ if (checkWebCoreFeatureSupport("WML", 0)) { $ignoredDirectories{'wml'} = 1; } +if (!checkWebCoreFeatureSupport("WCSS", 0)) { + $ignoredDirectories{'fast/wcss'} = 1; +} + if (!checkWebCoreFeatureSupport("XHTMLMP", 0)) { $ignoredDirectories{'fast/xhtmlmp'} = 1; } @@ -1149,6 +1153,7 @@ sub countAndPrintLeaks($$$) "QTKitMovieControllerView completeUISetup", # <rdar://problem/7155156> leak in QTKit "getVMInitArgs", # <rdar://problem/7714444> leak in Java "Java_java_lang_System_initProperties", # <rdar://problem/7714465> leak in Java + "glrCompExecuteKernel", # <rdar://problem/7815391> leak in graphics driver while using OpenGL ); } diff --git a/WebKitTools/Scripts/prepare-ChangeLog b/WebKitTools/Scripts/prepare-ChangeLog index b087f67..2ef1eb4 100755 --- a/WebKitTools/Scripts/prepare-ChangeLog +++ b/WebKitTools/Scripts/prepare-ChangeLog @@ -260,7 +260,9 @@ if ($bugNumber) { $bugURL = "https://bugs.webkit.org/show_bug.cgi?id=$bugNumber"; my $bugXMLURL = "$bugURL&ctype=xml"; # Perl has no built in XML processing, so we'll fetch and parse with curl and grep - my $descriptionLine = `curl --silent "$bugXMLURL" | grep short_desc`; + # Pass --insecure because some cygwin installs have no certs we don't + # care about validating that bugs.webkit.org is who it says it is here. + my $descriptionLine = `curl --insecure --silent "$bugXMLURL" | grep short_desc`; if ($descriptionLine !~ /<short_desc>(.*)<\/short_desc>/) { print STDERR " Bug $bugNumber has no bug description. Maybe you set wrong bug ID?\n"; print STDERR " The bug URL: $bugXMLURL\n"; diff --git a/WebKitTools/Scripts/run-bindings-tests b/WebKitTools/Scripts/run-bindings-tests new file mode 100755 index 0000000..56b2aff --- /dev/null +++ b/WebKitTools/Scripts/run-bindings-tests @@ -0,0 +1,136 @@ +#!/usr/bin/python +# Copyright (C) 2010 Google 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. +# + +# This script generates h and cpp file for TestObj.idl using the V8 code +# generator. Please execute the script whenever changes are made to +# CodeGeneratorV8.pm, and submit the changes in V8TestObj.h/cpp in the same +# patch. This makes it easier to track and review changes in generated code. +# To execute, invoke: 'python run_tests.py' + +import os +import os.path +import subprocess +import sys +import tempfile +from webkitpy.common.checkout import scm + + +def generate_from_idl(generator, idl_file, output_directory): + cmd = ['perl', '-w', + '-IWebCore/bindings/scripts', + 'WebCore/bindings/scripts/generate-bindings.pl', + # idl include directories (path relative to generate-bindings.pl) + '--include', '.', + '--defines', 'TESTING_%s' % generator, + '--generator', generator, + '--outputDir', output_directory, + idl_file] + return subprocess.call(cmd) == 0 + + +def detect_changes(work_directory, reference_directory): + changes_found = False + for output_file in os.listdir(work_directory): + print 'Detecting changes in %s...' % output_file + cmd = ['diff', + '-u', + os.path.join(reference_directory, output_file), + os.path.join(work_directory, output_file)] + if subprocess.call(cmd) != 0: + print 'Detected changes in %s (see above)' % output_file + changes_found = True + else: + print 'No changes found.' + + return changes_found + + +def run_tests(generator, input_directory, reference_directory, reset_results): + work_directory = reference_directory + + passed = True + for input_file in os.listdir(input_directory): + (name, extension) = os.path.splitext(input_file) + if extension != '.idl': + continue + print 'Testing the %s generator on %s' % (generator, input_file) + # Generate output into the work directory (either the given one or a + # temp one if not reset_results is performed) + if not reset_results: + work_directory = tempfile.mkdtemp() + if not generate_from_idl(generator, os.path.join(input_directory, + input_file), + work_directory): + passed = False + if reset_results: + print "Overwrote reference files" + continue + # Detect changes + if detect_changes(work_directory, reference_directory): + passed = False + + if not passed: + print '%s generator failed.' % generator + return passed + + +def main(argv): + """Runs WebCore bindings code generators on test IDL files and compares + the results with reference files. + + Options: + --reset-results: Overwrites the reference files with the generated results. + + """ + reset_results = "--reset-results" in argv + + current_scm = scm.detect_scm_system(os.curdir) + os.chdir(current_scm.checkout_root) + + all_tests_passed = True + + generators = [ + 'JS', + 'V8', + 'ObjC', + 'GObject', + ] + + for generator in generators: + input_directory = os.path.join('WebCore', 'bindings', 'scripts', 'test') + reference_directory = os.path.join('WebCore', 'bindings', 'scripts', 'test', generator) + if not run_tests(generator, input_directory, reference_directory, reset_results): + all_tests_passed = False + + if all_tests_passed: + print 'All tests passed!' + return 0 + else: + print '(To update the reference files, execute "run-bindings-test --reset-results")' + return -1 + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/WebKitTools/Scripts/run-webkit-tests b/WebKitTools/Scripts/run-webkit-tests index f28f20a..8fe8360 100755 --- a/WebKitTools/Scripts/run-webkit-tests +++ b/WebKitTools/Scripts/run-webkit-tests @@ -58,6 +58,8 @@ sub useNewRunWebKitTests() { # Change this check to control which platforms use # new-run-webkit-tests by default. + # Example: return runningOnBuildBot() && isLeopard(); + # would enable new-run-webkit-tests on only the leopard buildbots. return 0; } diff --git a/WebKitTools/Scripts/svn-apply b/WebKitTools/Scripts/svn-apply index 61d193d..b49ccec 100755 --- a/WebKitTools/Scripts/svn-apply +++ b/WebKitTools/Scripts/svn-apply @@ -123,72 +123,43 @@ my $repositoryRootPath = determineVCSRoot(); my %checkedDirectories; my %copiedFiles; -my @patches; -my %versions; - -my $copiedFromPath; -my $filter; -my $indexPath; -my $patch; -while (<>) { - s/([\n\r]+)$//mg; - my $eol = $1; - if (!defined($indexPath) && m#^diff --git \w/#) { - $filter = \&gitdiff2svndiff; - } - $_ = &$filter($_) if $filter; - if (/^Index: (.+)/) { - $indexPath = $1; - if ($patch) { - if (!$copiedFromPath) { - push @patches, $patch; - } - $copiedFromPath = ""; - $patch = ""; - } - } - if ($indexPath) { - # Fix paths on diff, ---, and +++ lines to match preceding Index: line. - s/\S+$/$indexPath/ if /^diff/; - s/^--- \S+/--- $indexPath/; - if (/^--- .+\(from (\S+):(\d+)\)$/) { - $copiedFromPath = $1; - $copiedFiles{$indexPath} = $copiedFromPath; - $versions{$copiedFromPath} = $2 if ($2 != 0); - } - elsif (/^--- .+\(revision (\d+)\)$/) { - $versions{$indexPath} = $1 if ($1 != 0); - } - if (s/^\+\+\+ \S+/+++ $indexPath/) { - $indexPath = ""; - } - } - $patch .= $_; - $patch .= $eol; -} -if ($patch && !$copiedFromPath) { - push @patches, $patch; -} +# Need to use a typeglob to pass the file handle as a parameter, +# otherwise get a bareword error. +my @diffHashRefs = parsePatch(*ARGV); + +print "Parsed " . @diffHashRefs . " diffs from patch file(s).\n"; + +my $preparedPatchHash = prepareParsedPatch($force, @diffHashRefs); + +my @copyDiffHashRefs = @{$preparedPatchHash->{copyDiffHashRefs}}; +my @nonCopyDiffHashRefs = @{$preparedPatchHash->{nonCopyDiffHashRefs}}; +my %sourceRevisions = %{$preparedPatchHash->{sourceRevisionHash}}; if ($merge) { die "--merge is currently only supported for SVN" unless isSVN(); # How do we handle Git patches applied to an SVN checkout here? - for my $file (sort keys %versions) { - my $version = $versions{$file}; + for my $file (sort keys %sourceRevisions) { + my $version = $sourceRevisions{$file}; print "Getting version $version of $file\n"; system("svn", "update", "-r", $version, $file) == 0 or die "Failed to run svn update -r $version $file."; } } -# Handle copied and moved files first since moved files may have their source deleted before the move. -for my $file (keys %copiedFiles) { - addDirectoriesIfNeeded(dirname($file)); - scmCopy($copiedFiles{$file}, $file); +# Handle copied and moved files first since moved files may have their +# source deleted before the move. +for my $copyDiffHashRef (@copyDiffHashRefs) { + my $indexPath = $copyDiffHashRef->{indexPath}; + my $copiedFromPath = $copyDiffHashRef->{copiedFromPath}; + + addDirectoriesIfNeeded(dirname($indexPath)); + scmCopy($copiedFromPath, $indexPath); + + $copiedFiles{$indexPath} = $copiedFromPath; } -for $patch (@patches) { - patch($patch); +for my $diffHashRef (@nonCopyDiffHashRefs) { + patch($diffHashRef); } removeDirectoriesIfNeeded(); @@ -326,30 +297,27 @@ sub isDirectoryEmptyForRemoval($) return $directoryIsEmpty; } +# Args: +# $diffHashRef: a diff hash reference of the type returned by parsePatch(). sub patch($) { - my ($patch) = @_; - return if !$patch; - - unless ($patch =~ m|^Index: ([^\r\n]+)|) { - my $separator = '-' x 67; - warn "Failed to find 'Index:' in:\n$separator\n$patch\n$separator\n"; - die unless $force; - return; - } - my $fullPath = $1; + my ($diffHashRef) = @_; + + my $patch = $diffHashRef->{svnConvertedText}; + + my $fullPath = $diffHashRef->{indexPath}; + my $isBinary = $diffHashRef->{isBinary}; + my $isGit = $diffHashRef->{isGit}; my $deletion = 0; my $addition = 0; - my $isBinary = 0; - my $isGitBinary = 0; + # FIXME: This information should be extracted from the diff file as + # part of the parsing stage, i.e. the call to parsePatch(). $addition = 1 if ($patch =~ /\n--- .+\(revision 0\)\r?\n/ || $patch =~ /\n@@ -0,0 .* @@/) && !exists($copiedFiles{$fullPath}); $deletion = 1 if $patch =~ /\n@@ .* \+0,0 @@/; - $isBinary = 1 if $patch =~ /\nCannot display: file marked as a binary type\./; - $isGitBinary = 1 if $patch =~ /\nGIT binary patch\n/; - if (!$addition && !$deletion && !$isBinary && !$isGitBinary) { + if (!$addition && !$deletion && !$isBinary) { # Standard patch, patch tool can handle this. if (basename($fullPath) eq "ChangeLog") { my $changeLogDotOrigExisted = -f "${fullPath}.orig"; @@ -364,11 +332,11 @@ sub patch($) addDirectoriesIfNeeded(dirname($fullPath)); if ($isBinary) { - # Binary change - handleBinaryChange($fullPath, $patch); - } elsif ($isGitBinary) { - # Git binary change - handleGitBinaryChange($fullPath, $patch); + if ($isGit) { + handleGitBinaryChange($fullPath, $patch); + } else { + handleBinaryChange($fullPath, $patch); + } } elsif ($deletion) { # Deletion applyPatch($patch, $fullPath, ["--force"]); @@ -383,6 +351,8 @@ sub patch($) system("svn", "stat", "$fullPath.orig") if isSVN() && -e "$fullPath.orig"; } } + + scmToggleExecutableBit($fullPath, $diffHashRef->{executableBitDelta}) if defined($diffHashRef->{executableBitDelta}); } sub removeDirectoriesIfNeeded() diff --git a/WebKitTools/Scripts/svn-unapply b/WebKitTools/Scripts/svn-unapply index eb20ca0..2ef7249 100755 --- a/WebKitTools/Scripts/svn-unapply +++ b/WebKitTools/Scripts/svn-unapply @@ -97,54 +97,24 @@ my $repositoryRootPath = determineVCSRoot(); my @copiedFiles; my %directoriesToCheck; -my $copiedFromPath; -my $filter; -my $indexPath; -my $patch; -while (<>) { - s/([\n\r]+)$//mg; - my $eol = $1; - if (!defined($indexPath) && m#^diff --git \w/#) { - $filter = \&gitdiff2svndiff; - } - $_ = &$filter($_) if $filter; - if (/^Index: (.+)/) { - $indexPath = $1; - if ($patch) { - if ($copiedFromPath) { - push @copiedFiles, $patch; - } else { - patch($patch); - } - $copiedFromPath = ""; - $patch = ""; - } - } - if ($indexPath) { - # Fix paths on diff, ---, and +++ lines to match preceding Index: line. - s/^--- \S+/--- $indexPath/; - if (/^--- .+\(from (\S+):\d+\)$/) { - $copiedFromPath = $1; - } - if (s/^\+\+\+ \S+/+++ $indexPath/) { - $indexPath = ""; - } - } - $patch .= $_; - $patch .= $eol; -} +# Need to use a typeglob to pass the file handle as a parameter, +# otherwise get a bareword error. +my @diffHashRefs = parsePatch(*ARGV); -if ($patch) { - if ($copiedFromPath) { - push @copiedFiles, $patch; - } else { - patch($patch); - } +print "Parsed " . @diffHashRefs . " diffs from patch file(s).\n"; + +my $preparedPatchHash = prepareParsedPatch($force, @diffHashRefs); + +my @copyDiffHashRefs = @{$preparedPatchHash->{copyDiffHashRefs}}; +my @nonCopyDiffHashRefs = @{$preparedPatchHash->{nonCopyDiffHashRefs}}; + +for my $diffHashRef (@nonCopyDiffHashRefs) { + patch($diffHashRef); } # Handle copied and moved files last since they may have had post-copy changes that have now been unapplied -for $patch (@copiedFiles) { - patch($patch); +for my $diffHashRef (@copyDiffHashRefs) { + patch($diffHashRef); } if (isSVN()) { @@ -163,28 +133,28 @@ sub checksum($) return $checksum; } +# Args: +# $diffHashRef: a diff hash reference of the type returned by parsePatch(). sub patch($) { - my ($patch) = @_; - return if !$patch; + my ($diffHashRef) = @_; + + my $patch = $diffHashRef->{svnConvertedText}; + + my $fullPath = $diffHashRef->{indexPath}; + my $isSvnBinary = $diffHashRef->{isBinary} && $diffHashRef->{isSvn}; - unless ($patch =~ m|^Index: ([^\r\n]+)|) { - my $separator = '-' x 67; - warn "Failed to find 'Index:' in:\n$separator\n$patch\n$separator\n"; - return; - } - my $fullPath = $1; $directoriesToCheck{dirname($fullPath)} = 1; my $deletion = 0; my $addition = 0; - my $isBinary = 0; - $addition = 1 if ($patch =~ /\n--- .+\(revision 0\)\n/ || $patch =~ /\n@@ -0,0 .* @@/); + # FIXME: This information should be extracted from the diff file as + # part of the parsing stage, i.e. the call to parsePatch(). + $addition = 1 if ($diffHashRef->{copiedFromPath} || $patch =~ /\n--- .+\(revision 0\)\n/ || $patch =~ /\n@@ -0,0 .* @@/); $deletion = 1 if $patch =~ /\n@@ .* \+0,0 @@/; - $isBinary = 1 if $patch =~ /\nCannot display: file marked as a binary type\./; - if (!$addition && !$deletion && !$isBinary) { + if (!$addition && !$deletion && !$isSvnBinary) { # Standard patch, patch tool can handle this. if (basename($fullPath) eq "ChangeLog") { my $changeLogDotOrigExisted = -f "${fullPath}.orig"; @@ -196,7 +166,8 @@ sub patch($) } else { # Either a deletion, an addition or a binary change. - if ($isBinary) { + # FIXME: Add support for Git binary files. + if ($isSvnBinary) { # Reverse binary change unlink($fullPath) if (-e $fullPath); system "svn", "revert", $fullPath; @@ -228,11 +199,17 @@ sub patch($) system "svn", "stat", $fullPath; } else { # Reverse addition + # + # FIXME: This should use the same logic as svn-apply's deletion + # code. In particular, svn-apply's scmRemove() subroutine + # should be used here. unapplyPatch($patch, $fullPath, ["--force"]); unlink($fullPath) if -z $fullPath; system "svn", "revert", $fullPath; } } + + scmToggleExecutableBit($fullPath, -1 * $diffHashRef->{executableBitDelta}) if defined($diffHashRef->{executableBitDelta}); } sub revertDirectories() diff --git a/WebKitTools/Scripts/test-webkitperl b/WebKitTools/Scripts/test-webkitperl index 2e31593..4e63b8a 100755 --- a/WebKitTools/Scripts/test-webkitperl +++ b/WebKitTools/Scripts/test-webkitperl @@ -39,10 +39,20 @@ use Test::Harness; use lib $FindBin::Bin; # so this script can be run from any directory. use VCSUtils; -# Use an absolute path so this script can be run from any directory. -my $scriptsDir = $FindBin::Bin; +# Change the working directory so that we can pass shorter, relative +# paths to runtests(), rather than longer, absolute paths. +# +# We change to the source root so the paths can be relative to the +# source root. These paths display on the screen, and their meaning +# will be clearer to the user if relative to the root, rather than to +# the Scripts directory, say. +# +# Source root is two levels up from the Scripts directory. +my $sourceRootDir = File::Spec->catfile($FindBin::Bin, "../.."); +chdir($sourceRootDir); -my $pattern = File::Spec->catfile($scriptsDir, "webkitperl/*_unittest/*.pl"); +# Relative to root +my $pattern = "WebKitTools/Scripts/webkitperl/*_unittest/*.pl"; my @files = <${pattern}>; # lists files alphabetically diff --git a/WebKitTools/Scripts/update-webkit-localizable-strings b/WebKitTools/Scripts/update-webkit-localizable-strings index 1d1f413..493a777 100755 --- a/WebKitTools/Scripts/update-webkit-localizable-strings +++ b/WebKitTools/Scripts/update-webkit-localizable-strings @@ -34,7 +34,7 @@ use FindBin; use lib $FindBin::Bin; use webkitdirs; -my @directoriesToScan = ("WebKit/mac", "WebKit/win"); +my @directoriesToScan = ("WebKit/mac", "WebKit/win", "-WebCore/icu", "-WebKit/mac/icu"); my $fileToUpdate = "WebKit/English.lproj/Localizable.strings"; my $exceptionsFile = "WebKit/StringsNotToBeLocalized.txt"; diff --git a/WebKitTools/Scripts/webkitdirs.pm b/WebKitTools/Scripts/webkitdirs.pm index 0b18373..4fecf6b 100644 --- a/WebKitTools/Scripts/webkitdirs.pm +++ b/WebKitTools/Scripts/webkitdirs.pm @@ -1098,7 +1098,7 @@ sub copyInspectorFrontendFiles print "*************************************************************\n"; die; } - return system "rsync", "-aut", "--exclude=/.DS_Store", "--exclude=.svn/", !isQt() ? "--exclude=/WebKit.qrc" : "", $sourceInspectorPath, $inspectorResourcesDirPath; + return system "rsync", "-aut", "--exclude=/.DS_Store", "--exclude=*.re2js", "--exclude=.svn/", !isQt() ? "--exclude=/WebKit.qrc" : "", $sourceInspectorPath, $inspectorResourcesDirPath; } sub buildXCodeProject($$@) @@ -1479,7 +1479,7 @@ sub buildChromium($@) my $result = 1; if (isDarwin()) { # Mac build - builds the root xcode project. - $result = buildXCodeProject("WebKit/chromium/WebKit", $clean, (@options)); + $result = buildXCodeProject("WebKit/chromium/WebKit", $clean, "-configuration", configuration(), @options); } elsif (isCygwin() || isWindows()) { # Windows build - builds the root visual studio solution. $result = buildChromiumVisualStudioProject("WebKit/chromium/WebKit.sln", $clean); diff --git a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/gitdiff2svndiff.pl b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/gitdiff2svndiff.pl deleted file mode 100644 index 93708d6..0000000 --- a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/gitdiff2svndiff.pl +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/perl -w -# -# Copyright (C) 2009, 2010 Chris Jerdonek (chris.jerdonek@gmail.com) -# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * 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. -# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT -# OWNER 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. - -# Unit tests of VCSUtils::gitdiff2svndiff() - -use strict; -use warnings; - -use Test::Simple tests => 20; -use VCSUtils; - -# We use this for display purposes, to keep each test title on one line. -sub excerptString($) -{ - my ($text) = @_; - - my $length = 25; - - my $shortened = substr($text, 0, $length); - $shortened .= "..." if (length($text) > $length); - - return $shortened; -} - -my $git_patch = <<END; -diff --git a/WebCore/rendering/style/StyleFlexibleBoxData.h b/WebCore/rendering/style/StyleFlexibleBoxData.h -index f5d5e74..3b6aa92 100644 ---- a/WebCore/rendering/style/StyleFlexibleBoxData.h -+++ b/WebCore/rendering/style/StyleFlexibleBoxData.h -@@ -47,7 +47,6 @@ public: -END - -my $svn_patch = <<END; -Index: WebCore/rendering/style/StyleFlexibleBoxData.h -=================================================================== ---- WebCore/rendering/style/StyleFlexibleBoxData.h -+++ WebCore/rendering/style/StyleFlexibleBoxData.h -@@ -47,7 +47,6 @@ public: -END - -my @gitLines = split("\n", $git_patch); -my @svnLines = split("\n", $svn_patch); - -# New test: check each git header line with different line endings -my $titleHeader = "gitdiff2svndiff: "; - -my @lineEndingPairs = ( # display name, value - ["", ""], - ["\\n", "\n"], - ["\\r\\n", "\r\n"], -); - -for (my $i = 0; $i < @gitLines; $i++) { - foreach my $pair (@lineEndingPairs) { - my $gitLine = $gitLines[$i] . $pair->[1]; - my $expected = $svnLines[$i] . $pair->[1]; - my $title = $titleHeader . excerptString($gitLine); - $title .= " [line-end: \"$pair->[0]\"]"; - - ok($expected eq gitdiff2svndiff($gitLine), $title); - } -} - -# New test -my $title = "gitdiff2svndiff: Convert mnemonic git diff to svn diff"; - -my @prefixes = ( - { 'a' => 'i', 'b' => 'w' }, # git-diff (compares the (i)ndex and the (w)ork tree) - { 'a' => 'c', 'b' => 'w' }, # git-diff HEAD (compares a (c)ommit and the (w)ork tree) - { 'a' => 'c', 'b' => 'i' }, # git diff --cached (compares a (c)ommit and the (i)ndex) - { 'a' => 'o', 'b' => 'w' }, # git-diff HEAD:file1 file2 (compares an (o)bject and a (w)ork tree entity) - { 'a' => '1', 'b' => '2' }, # git diff --no-index a b (compares two non-git things (1) and (2)) -); - -my $out = ""; - -foreach my $prefix (@prefixes) { - my $mnemonic_patch = $git_patch; - $mnemonic_patch =~ s/ a\// $prefix->{'a'}\//g; - $mnemonic_patch =~ s/ b\// $prefix->{'b'}\//g; - - $out = ""; - foreach my $line (split('\n', $mnemonic_patch)) { - $out .= gitdiff2svndiff($line) . "\n"; - } - - ok($svn_patch eq $out, $title . " (" . $prefix->{'a'} . "," . $prefix->{'b'} . ")"); -} - diff --git a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl index 2507d2d..9f112b2 100644 --- a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl +++ b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl @@ -30,13 +30,6 @@ use warnings; use Test::More; use VCSUtils; -my @diffHashRefKeys = ( # The $diffHashRef keys to check. - "copiedFromPath", - "indexPath", - "sourceRevision", - "svnConvertedText", -); - # The array of test cases. my @testCaseHashRefs = ( { @@ -53,7 +46,8 @@ Index: Makefile all: END - # Header keys to check + expectedReturn => [ +{ svnConvertedText => <<'END', # Same as input text Index: Makefile =================================================================== @@ -65,12 +59,52 @@ Index: Makefile all: END - copiedFromPath => undef, indexPath => "Makefile", + isSvn => 1, sourceRevision => "53052", - # Other values to check - lastReadLine => undef, - nextLine => undef, +}, +undef], + expectedNextLine => undef, +}, +{ + # New test + diffName => "SVN: binary file (isBinary true)", + inputText => <<'END', +Index: test_file.swf +=================================================================== +Cannot display: file marked as a binary type. +svn:mime-type = application/octet-stream + +Property changes on: test_file.swf +___________________________________________________________________ +Name: svn:mime-type + + application/octet-stream + + +Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA== +END + expectedReturn => [ +{ + svnConvertedText => <<'END', # Same as input text +Index: test_file.swf +=================================================================== +Cannot display: file marked as a binary type. +svn:mime-type = application/octet-stream + +Property changes on: test_file.swf +___________________________________________________________________ +Name: svn:mime-type + + application/octet-stream + + +Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA== +END + indexPath => "test_file.swf", + isBinary => 1, + isSvn => 1, +}, +undef], + expectedNextLine => undef, }, { # New test @@ -89,7 +123,8 @@ Index: Makefile all: END - # Header keys to check + expectedReturn => [ +{ svnConvertedText => <<'END', # Same as input text LEADING JUNK @@ -104,12 +139,12 @@ Index: Makefile all: END - copiedFromPath => undef, indexPath => "Makefile", + isSvn => 1, sourceRevision => "53052", - # Other values to check - lastReadLine => undef, - nextLine => undef, +}, +undef], + expectedNextLine => undef, }, { # New test @@ -122,7 +157,8 @@ Index: Makefile_new @@ -0,0 +1,1 @@ +MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools END - # Header keys to check + expectedReturn => [ +{ svnConvertedText => <<'END', # Same as input text Index: Makefile_new =================================================================== @@ -133,10 +169,11 @@ Index: Makefile_new END copiedFromPath => "Makefile", indexPath => "Makefile_new", + isSvn => 1, sourceRevision => "53131", - # Other values to check - lastReadLine => undef, - nextLine => undef, +}, +undef], + expectedNextLine => undef, }, { # New test @@ -152,7 +189,8 @@ Index: Makefile_new =================================================================== --- Makefile_new (revision 53131) (from Makefile:53131) END - # Header keys to check + expectedReturn => [ +{ svnConvertedText => <<'END', Index: Makefile =================================================================== @@ -161,12 +199,12 @@ Index: Makefile @@ -1,1 +0,0 @@ -MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools END - copiedFromPath => undef, indexPath => "Makefile", + isSvn => 1, sourceRevision => "53131", - # Other values to check - lastReadLine => "Index: Makefile_new\n", - nextLine => "===================================================================\n", +}, +"Index: Makefile_new\n"], + expectedNextLine => "===================================================================\n", }, { # New test @@ -184,7 +222,8 @@ index f5d5e74..3b6aa92 100644 +++ b/Makefile @@ -1,1 1,1 @@ public: END - # Header keys to check + expectedReturn => [ +{ svnConvertedText => <<'END', # Same as input text Index: Makefile =================================================================== @@ -198,13 +237,16 @@ index f5d5e74..3b6aa92 100644 +++ b/Makefile @@ -1,1 1,1 @@ public: END - copiedFromPath => undef, indexPath => "Makefile", + isSvn => 1, sourceRevision => "53131", - # Other values to check - lastReadLine => undef, - nextLine => undef, }, +undef], + expectedNextLine => undef, +}, +#### +# Git test cases +## { # New test diffName => "Git: simple", @@ -215,20 +257,20 @@ index f5d5e74..3b6aa92 100644 +++ b/Makefile @@ -1,1 1,1 @@ public: END - # Header keys to check + expectedReturn => [ +{ svnConvertedText => <<'END', Index: Makefile -=================================================================== +index f5d5e74..3b6aa92 100644 --- Makefile +++ Makefile @@ -1,1 1,1 @@ public: END - copiedFromPath => undef, indexPath => "Makefile", - sourceRevision => undef, - # Other values to check - lastReadLine => undef, - nextLine => undef, + isGit => 1, +}, +undef], + expectedNextLine => undef, }, { # New test @@ -243,10 +285,11 @@ Index: Makefile_new =================================================================== --- Makefile_new (revision 53131) (from Makefile:53131) END - # Header keys to check + expectedReturn => [ +{ svnConvertedText => <<'END', Index: Makefile -=================================================================== +index f5d5e74..3b6aa92 100644 --- Makefile +++ Makefile @@ -1,1 1,1 @@ public: @@ -254,75 +297,29 @@ Index: Makefile_new =================================================================== --- Makefile_new (revision 53131) (from Makefile:53131) END - copiedFromPath => undef, indexPath => "Makefile", - sourceRevision => undef, - # Other values to check - lastReadLine => undef, - nextLine => undef, + isGit => 1, +}, +undef], + expectedNextLine => undef, }, ); -# Return the arguments for each assertion per test case. -# -# In particular, the number of assertions per test case is the length -# of the return value of this subroutine on a sample input. -# -# Returns @assertionArgsArrayRefs: -# $assertionArgsArrayRef: A reference to an array of parameters to pass -# to each call to is(). The parameters are-- -# $got: The value obtained -# $expected: The expected value -# $testName: The name of the test -sub testParseDiffAssertionArgs($) -{ - my ($testCaseHashRef) = @_; +my $testCasesCount = @testCaseHashRefs; +plan(tests => 2 * $testCasesCount); # Total number of assertions. - my $fileHandle; - open($fileHandle, "<", \$testCaseHashRef->{inputText}); +foreach my $testCase (@testCaseHashRefs) { + my $testNameStart = "parseDiff(): $testCase->{diffName}: comparing"; + my $fileHandle; + open($fileHandle, "<", \$testCase->{inputText}); my $line = <$fileHandle>; - my ($diffHashRef, $lastReadLine) = VCSUtils::parseDiff($fileHandle, $line); - - my $testNameStart = "parseDiff(): [$testCaseHashRef->{diffName}] "; - - my @assertionArgsArrayRefs; # Return value - my @assertionArgs; - foreach my $diffHashRefKey (@diffHashRefKeys) { - my $testName = "${testNameStart}key=\"$diffHashRefKey\""; - @assertionArgs = ($diffHashRef->{$diffHashRefKey}, $testCaseHashRef->{$diffHashRefKey}, $testName); - push(@assertionArgsArrayRefs, \@assertionArgs); - } - - @assertionArgs = ($lastReadLine, $testCaseHashRef->{lastReadLine}, "${testNameStart}lastReadLine"); - push(@assertionArgsArrayRefs, \@assertionArgs); - - my $nextLine = <$fileHandle>; - @assertionArgs = ($nextLine, $testCaseHashRef->{nextLine}, "${testNameStart}nextLine"); - push(@assertionArgsArrayRefs, \@assertionArgs); - - return @assertionArgsArrayRefs; -} - -# Test parseDiff() for the given test case. -sub testParseDiff($) -{ - my ($testCaseHashRef) = @_; - - my @assertionArgsArrayRefs = testParseDiffAssertionArgs($testCaseHashRef); - - foreach my $arrayRef (@assertionArgsArrayRefs) { - # The parameters are -- is($got, $expected, $testName). - is($arrayRef->[0], $arrayRef->[1], $arrayRef->[2]); - } -} - -# Count the number of assertions per test case, using a sample test case. -my $assertionCount = testParseDiffAssertionArgs($testCaseHashRefs[0]); + my @got = VCSUtils::parseDiff($fileHandle, $line); + my $expectedReturn = $testCase->{expectedReturn}; -plan(tests => @testCaseHashRefs * $assertionCount); # Total number of tests + is_deeply(\@got, $expectedReturn, "$testNameStart return value."); -foreach my $testCaseHashRef (@testCaseHashRefs) { - testParseDiff($testCaseHashRef); + my $gotNextLine = <$fileHandle>; + is($gotNextLine, $testCase->{expectedNextLine}, "$testNameStart next read line."); } diff --git a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl index a7a3c26..8c20f65 100644 --- a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl +++ b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl @@ -36,68 +36,21 @@ use warnings; use Test::More; use VCSUtils; -my @diffHeaderHashRefKeys = ( # The $diffHeaderHashRef keys to check. - "copiedFromPath", - "indexPath", - "sourceRevision", - "svnConvertedText", -); - -# The array of test cases. +# The unit tests for parseGitDiffHeader() and parseSvnDiffHeader() +# already thoroughly test parsing each format. +# +# For parseDiffHeader(), it should suffice to verify that -- (1) for each +# format, the method can return non-trivial values back for each key +# supported by that format (e.g. "sourceRevision" for SVN), (2) the method +# correctly sets default values when specific key-values are not set +# (e.g. undef for "sourceRevision" for Git), and (3) key-values unique to +# this method are set correctly (e.g. "scmFormat"). my @testCaseHashRefs = ( -{ - # New test - diffName => "SVN: simple", - inputText => <<'END', -Index: WebKitTools/Scripts/VCSUtils.pm -=================================================================== ---- WebKitTools/Scripts/VCSUtils.pm (revision 53004) -+++ WebKitTools/Scripts/VCSUtils.pm (working copy) -@@ -32,6 +32,7 @@ use strict; - use warnings; -END - # Header keys to check - svnConvertedText => <<'END', -Index: WebKitTools/Scripts/VCSUtils.pm -=================================================================== ---- WebKitTools/Scripts/VCSUtils.pm (revision 53004) -+++ WebKitTools/Scripts/VCSUtils.pm (working copy) -END - copiedFromPath => undef, - indexPath => "WebKitTools/Scripts/VCSUtils.pm", - sourceRevision => "53004", - # Other values to check - lastReadLine => "@@ -32,6 +32,7 @@ use strict;\n", - nextLine => " use warnings;\n", -}, -{ - # New test - diffName => "SVN: new file", - inputText => <<'END', -Index: WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl -=================================================================== ---- WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl (revision 0) -+++ WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl (revision 0) -@@ -0,0 +1,262 @@ -+#!/usr/bin/perl -w -END - # Header keys to check - svnConvertedText => <<'END', -Index: WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl -=================================================================== ---- WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl (revision 0) -+++ WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl (revision 0) -END - copiedFromPath => undef, - indexPath => "WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl", - sourceRevision => undef, - # Other values to check - lastReadLine => "@@ -0,0 +1,262 @@\n", - nextLine => "+#!/usr/bin/perl -w\n", -}, -{ - # New test - diffName => "SVN: copy", +#### +# SVN test cases +## +{ # New test + diffName => "SVN: non-trivial copiedFromPath and sourceRevision values", inputText => <<'END', Index: index_path.py =================================================================== @@ -106,7 +59,8 @@ Index: index_path.py @@ -0,0 +1,7 @@ +# Python file... END - # Header keys to check + expectedReturn => [ +{ svnConvertedText => <<'END', Index: index_path.py =================================================================== @@ -115,174 +69,53 @@ Index: index_path.py END copiedFromPath => "copied_from_path.py", indexPath => "index_path.py", + isSvn => 1, sourceRevision => 53048, - # Other values to check - lastReadLine => "@@ -0,0 +1,7 @@\n", - nextLine => "+# Python file...\n", }, -{ - # New test - diffName => "SVN: \\r\\n lines", - inputText => <<END, # No single quotes to allow interpolation of "\r" -Index: index_path.py\r -===================================================================\r ---- index_path.py (revision 53048) (from copied_from_path.py:53048)\r -+++ index_path.py (working copy)\r -@@ -0,0 +1,7 @@\r -+# Python file...\r -END - # Header keys to check - svnConvertedText => <<END, # No single quotes to allow interpolation of "\r" -Index: index_path.py\r -===================================================================\r ---- index_path.py (revision 53048) (from copied_from_path.py:53048)\r -+++ index_path.py (working copy)\r -END - copiedFromPath => "copied_from_path.py", - indexPath => "index_path.py", - sourceRevision => 53048, - # Other values to check - lastReadLine => "@@ -0,0 +1,7 @@\r\n", - nextLine => "+# Python file...\r\n", +"@@ -0,0 +1,7 @@\n"], + expectedNextLine => "+# Python file...\n", }, -{ - # New test - diffName => "SVN: path corrections", +#### +# Git test cases +## +{ # New test case + diffName => "Git: Non-zero executable bit", inputText => <<'END', -Index: index_path.py -=================================================================== ---- bad_path (revision 53048) (from copied_from_path.py:53048) -+++ bad_path (working copy) -@@ -0,0 +1,7 @@ -+# Python file... -END - # Header keys to check - svnConvertedText => <<'END', -Index: index_path.py -=================================================================== ---- index_path.py (revision 53048) (from copied_from_path.py:53048) -+++ index_path.py (working copy) +diff --git a/foo.exe b/foo.exe +old mode 100644 +new mode 100755 END - copiedFromPath => "copied_from_path.py", - indexPath => "index_path.py", - sourceRevision => 53048, - # Other values to check - lastReadLine => "@@ -0,0 +1,7 @@\n", - nextLine => "+# Python file...\n", -}, + expectedReturn => [ { - # New test - diffName => "Git: simple", - inputText => <<'END', -diff --git a/WebCore/rendering/style/StyleFlexibleBoxData.h b/WebCore/rendering/style/StyleFlexibleBoxData.h -index f5d5e74..3b6aa92 100644 ---- a/WebCore/rendering/style/StyleFlexibleBoxData.h -+++ b/WebCore/rendering/style/StyleFlexibleBoxData.h -@@ -47,7 +47,6 @@ public: -END - # Header keys to check svnConvertedText => <<'END', -Index: WebCore/rendering/style/StyleFlexibleBoxData.h -=================================================================== ---- WebCore/rendering/style/StyleFlexibleBoxData.h -+++ WebCore/rendering/style/StyleFlexibleBoxData.h +Index: foo.exe +old mode 100644 +new mode 100755 END - copiedFromPath => undef, - indexPath => "WebCore/rendering/style/StyleFlexibleBoxData.h", - sourceRevision => undef, - # Other values to check - lastReadLine => "@@ -47,7 +47,6 @@ public:\n", - nextLine => undef, + executableBitDelta => 1, + indexPath => "foo.exe", + isGit => 1, }, -{ - # New test - diffName => "Git: unrecognized lines", - inputText => <<'END', -diff --git a/LayoutTests/http/tests/security/listener/xss-inactive-closure.html b/LayoutTests/http/tests/security/listener/xss-inactive-closure.html -new file mode 100644 -index 0000000..3c9f114 ---- /dev/null -+++ b/LayoutTests/http/tests/security/listener/xss-inactive-closure.html -@@ -0,0 +1,34 @@ -+<html> -END - # Header keys to check - svnConvertedText => <<'END', -Index: LayoutTests/http/tests/security/listener/xss-inactive-closure.html -=================================================================== ---- LayoutTests/http/tests/security/listener/xss-inactive-closure.html -+++ LayoutTests/http/tests/security/listener/xss-inactive-closure.html -END - copiedFromPath => undef, - indexPath => "LayoutTests/http/tests/security/listener/xss-inactive-closure.html", - sourceRevision => undef, - # Other values to check - lastReadLine => "@@ -0,0 +1,34 @@\n", - nextLine => "+<html>\n", +undef], + expectedNextLine => undef, }, ); -# Return the arguments for each assertion per test case. -# -# In particular, the number of assertions per test case is the length -# of the return value of this subroutine on a sample input. -# -# Returns @assertionArgsArrayRefs: -# $assertionArgsArrayRef: A reference to an array of parameters to pass -# to each call to is(). The parameters are-- -# $got: The value obtained -# $expected: The expected value -# $testName: The name of the test -sub testParseDiffHeaderAssertionArgs($) -{ - my ($testCaseHashRef) = @_; +my $testCasesCount = @testCaseHashRefs; +plan(tests => 2 * $testCasesCount); # Total number of assertions. - my $fileHandle; - open($fileHandle, "<", \$testCaseHashRef->{inputText}); +foreach my $testCase (@testCaseHashRefs) { + my $testNameStart = "parseDiffHeader(): $testCase->{diffName}: comparing"; + my $fileHandle; + open($fileHandle, "<", \$testCase->{inputText}); my $line = <$fileHandle>; - my ($headerHashRef, $lastReadLine) = VCSUtils::parseDiffHeader($fileHandle, $line); - - my $testNameStart = "parseDiffHeader(): [$testCaseHashRef->{diffName}] "; - - my @assertionArgsArrayRefs; # Return value - my @assertionArgs; - foreach my $diffHeaderHashRefKey (@diffHeaderHashRefKeys) { - my $testName = "${testNameStart}key=\"$diffHeaderHashRefKey\""; - @assertionArgs = ($headerHashRef->{$diffHeaderHashRefKey}, $testCaseHashRef->{$diffHeaderHashRefKey}, $testName); - push(@assertionArgsArrayRefs, \@assertionArgs); - } - - @assertionArgs = ($lastReadLine, $testCaseHashRef->{lastReadLine}, "${testNameStart}lastReadLine"); - push(@assertionArgsArrayRefs, \@assertionArgs); - - my $nextLine = <$fileHandle>; - @assertionArgs = ($nextLine, $testCaseHashRef->{nextLine}, "${testNameStart}nextLine"); - push(@assertionArgsArrayRefs, \@assertionArgs); - - return @assertionArgsArrayRefs; -} - -# Test parseDiffHeader() for the given test case. -sub testParseDiffHeader($) -{ - my ($testCaseHashRef) = @_; - - my @assertionArgsArrayRefs = testParseDiffHeaderAssertionArgs($testCaseHashRef); - - foreach my $arrayRef (@assertionArgsArrayRefs) { - # The parameters are -- is($got, $expected, $testName). - is($arrayRef->[0], $arrayRef->[1], $arrayRef->[2]); - } -} - -# Count the number of assertions per test case to calculate the total number -# of Test::More tests. We could have used any test case for the count. -my $assertionCount = testParseDiffHeaderAssertionArgs($testCaseHashRefs[0]); + my @got = VCSUtils::parseDiffHeader($fileHandle, $line); + my $expectedReturn = $testCase->{expectedReturn}; -plan(tests => @testCaseHashRefs * $assertionCount); # Total number of tests + is_deeply(\@got, $expectedReturn, "$testNameStart return value."); -foreach my $testCaseHashRef (@testCaseHashRefs) { - testParseDiffHeader($testCaseHashRef); + my $gotNextLine = <$fileHandle>; + is($gotNextLine, $testCase->{expectedNextLine}, "$testNameStart next read line."); } diff --git a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl new file mode 100644 index 0000000..9e2a88d --- /dev/null +++ b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl @@ -0,0 +1,366 @@ +#!/usr/bin/perl -w +# +# Copyright (C) 2010 Chris Jerdonek (cjerdonek@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 INC. 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 INC. 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. + +# Unit tests of parseGitDiffHeader(). + +use strict; +use warnings; + +use Test::More; +use VCSUtils; + +# The array of test cases. +my @testCaseHashRefs = ( +{ # New test + diffName => "Modified file", + inputText => <<'END', +diff --git a/foo.h b/foo.h +index f5d5e74..3b6aa92 100644 +--- a/foo.h ++++ b/foo.h +@@ -1 +1 @@ +-file contents ++new file contents +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: foo.h +index f5d5e74..3b6aa92 100644 +--- foo.h ++++ foo.h +END + indexPath => "foo.h", +}, +"@@ -1 +1 @@\n"], + expectedNextLine => "-file contents\n", +}, +{ # New test + diffName => "New file", + inputText => <<'END', +diff --git a/foo.h b/foo.h +new file mode 100644 +index 0000000..3c9f114 +--- /dev/null ++++ b/foo.h +@@ -0,0 +1,34 @@ ++<html> +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: foo.h +new file mode 100644 +index 0000000..3c9f114 +--- foo.h ++++ foo.h +END + indexPath => "foo.h", +}, +"@@ -0,0 +1,34 @@\n"], + expectedNextLine => "+<html>\n", +}, +{ # New test + diffName => "using --no-prefix", + inputText => <<'END', +diff --git foo.h foo.h +index c925780..9e65c43 100644 +--- foo.h ++++ foo.h +@@ -1,3 +1,17 @@ ++contents +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: foo.h +index c925780..9e65c43 100644 +--- foo.h ++++ foo.h +END + indexPath => "foo.h", +}, +"@@ -1,3 +1,17 @@\n"], + expectedNextLine => "+contents\n", +}, +#### +# Copy operations +## +{ # New test + diffName => "copy (with similarity index 100%)", + inputText => <<'END', +diff --git a/foo b/foo_new +similarity index 100% +copy from foo +copy to foo_new +diff --git a/bar b/bar +index d45dd40..3494526 100644 +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: foo_new +similarity index 100% +copy from foo +copy to foo_new +END + copiedFromPath => "foo", + indexPath => "foo_new", +}, +"diff --git a/bar b/bar\n"], + expectedNextLine => "index d45dd40..3494526 100644\n", +}, +{ # New test + diffName => "copy (with similarity index < 100%)", + inputText => <<'END', +diff --git a/foo b/foo_new +similarity index 99% +copy from foo +copy to foo_new +diff --git a/bar b/bar +index d45dd40..3494526 100644 +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: foo_new +similarity index 99% +copy from foo +copy to foo_new +END + indexPath => "foo_new", +}, +"diff --git a/bar b/bar\n"], + expectedNextLine => "index d45dd40..3494526 100644\n", +}, +#### +# Binary file test cases +## +{ + # New test case + diffName => "New binary file", + inputText => <<'END', +diff --git a/foo.gif b/foo.gif +new file mode 100644 +index 0000000000000000000000000000000000000000..64a9532e7794fcd791f6f12157406d9060151690 +GIT binary patch +literal 7 +OcmYex&reDa;sO8*F9L)B + +literal 0 +HcmV?d00001 + +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: foo.gif +new file mode 100644 +index 0000000000000000000000000000000000000000..64a9532e7794fcd791f6f12157406d9060151690 +GIT binary patch +END + indexPath => "foo.gif", + isBinary => 1, +}, +"literal 7\n"], + expectedNextLine => "OcmYex&reDa;sO8*F9L)B\n", +}, +{ + # New test case + diffName => "Deleted binary file", + inputText => <<'END', +diff --git a/foo.gif b/foo.gif +deleted file mode 100644 +index 323fae0..0000000 +GIT binary patch +literal 0 +HcmV?d00001 + +literal 7 +OcmYex&reDa;sO8*F9L)B + +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: foo.gif +deleted file mode 100644 +index 323fae0..0000000 +GIT binary patch +END + indexPath => "foo.gif", + isBinary => 1, +}, +"literal 0\n"], + expectedNextLine => "HcmV?d00001\n", +}, +#### +# Executable bit test cases +## +{ + # New test case + diffName => "Modified executable file", + inputText => <<'END', +diff --git a/foo b/foo +index d03e242..435ad3a 100755 +--- a/foo ++++ b/foo +@@ -1 +1 @@ +-file contents ++new file contents + +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: foo +index d03e242..435ad3a 100755 +--- foo ++++ foo +END + indexPath => "foo", +}, +"@@ -1 +1 @@\n"], + expectedNextLine => "-file contents\n", +}, +{ + # New test case + diffName => "Making file executable (last diff)", + inputText => <<'END', +diff --git a/foo.exe b/foo.exe +old mode 100644 +new mode 100755 +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: foo.exe +old mode 100644 +new mode 100755 +END + executableBitDelta => 1, + indexPath => "foo.exe", +}, +undef], + expectedNextLine => undef, +}, +{ + # New test case + diffName => "Making file executable (not last diff)", + inputText => <<'END', +diff --git a/foo.exe b/foo.exe +old mode 100644 +new mode 100755 +diff --git a/another_file.txt b/another_file.txt +index d03e242..435ad3a 100755 +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: foo.exe +old mode 100644 +new mode 100755 +END + executableBitDelta => 1, + indexPath => "foo.exe", +}, +"diff --git a/another_file.txt b/another_file.txt\n"], + expectedNextLine => "index d03e242..435ad3a 100755\n", +}, +{ + # New test case + diffName => "New executable file", + inputText => <<'END', +diff --git a/foo b/foo +new file mode 100755 +index 0000000..d03e242 +--- /dev/null ++++ b/foo +@@ -0,0 +1 @@ ++file contents + +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: foo +new file mode 100755 +index 0000000..d03e242 +--- foo ++++ foo +END + executableBitDelta => 1, + indexPath => "foo", +}, +"@@ -0,0 +1 @@\n"], + expectedNextLine => "+file contents\n", +}, +{ + # New test case + diffName => "Deleted executable file", + inputText => <<'END', +diff --git a/foo b/foo +deleted file mode 100755 +index d03e242..0000000 +--- a/foo ++++ /dev/null +@@ -1 +0,0 @@ +-file contents + +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: foo +deleted file mode 100755 +index d03e242..0000000 +--- foo ++++ foo +END + executableBitDelta => -1, + indexPath => "foo", +}, +"@@ -1 +0,0 @@\n"], + expectedNextLine => "-file contents\n", +}, +); + +my $testCasesCount = @testCaseHashRefs; +plan(tests => 2 * $testCasesCount); # Total number of assertions. + +foreach my $testCase (@testCaseHashRefs) { + my $testNameStart = "parseGitDiffHeader(): $testCase->{diffName}: comparing"; + + my $fileHandle; + open($fileHandle, "<", \$testCase->{inputText}); + my $line = <$fileHandle>; + + my @got = VCSUtils::parseGitDiffHeader($fileHandle, $line); + my $expectedReturn = $testCase->{expectedReturn}; + + is_deeply(\@got, $expectedReturn, "$testNameStart return value."); + + my $gotNextLine = <$fileHandle>; + is($gotNextLine, $testCase->{expectedNextLine}, "$testNameStart next read line."); +} diff --git a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl new file mode 100644 index 0000000..b732889 --- /dev/null +++ b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl @@ -0,0 +1,220 @@ +#!/usr/bin/perl -w +# +# Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com) +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +# OWNER 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. + +# Unit tests of parseSvnDiffHeader(). + +use strict; +use warnings; + +use Test::More; +use VCSUtils; + +# The array of test cases. +my @testCaseHashRefs = ( +{ + # New test + diffName => "simple diff", + inputText => <<'END', +Index: WebKitTools/Scripts/VCSUtils.pm +=================================================================== +--- WebKitTools/Scripts/VCSUtils.pm (revision 53004) ++++ WebKitTools/Scripts/VCSUtils.pm (working copy) +@@ -32,6 +32,7 @@ use strict; + use warnings; +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: WebKitTools/Scripts/VCSUtils.pm +=================================================================== +--- WebKitTools/Scripts/VCSUtils.pm (revision 53004) ++++ WebKitTools/Scripts/VCSUtils.pm (working copy) +END + indexPath => "WebKitTools/Scripts/VCSUtils.pm", + sourceRevision => "53004", +}, +"@@ -32,6 +32,7 @@ use strict;\n"], + expectedNextLine => " use warnings;\n", +}, +{ + # New test + diffName => "new file", + inputText => <<'END', +Index: WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl +=================================================================== +--- WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl (revision 0) ++++ WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl (revision 0) +@@ -0,0 +1,262 @@ ++#!/usr/bin/perl -w +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl +=================================================================== +--- WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl (revision 0) ++++ WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl (revision 0) +END + indexPath => "WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl", +}, +"@@ -0,0 +1,262 @@\n"], + expectedNextLine => "+#!/usr/bin/perl -w\n", +}, +{ + # New test + diffName => "copied file", + inputText => <<'END', +Index: index_path.py +=================================================================== +--- index_path.py (revision 53048) (from copied_from_path.py:53048) ++++ index_path.py (working copy) +@@ -0,0 +1,7 @@ ++# Python file... +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: index_path.py +=================================================================== +--- index_path.py (revision 53048) (from copied_from_path.py:53048) ++++ index_path.py (working copy) +END + copiedFromPath => "copied_from_path.py", + indexPath => "index_path.py", + sourceRevision => 53048, +}, +"@@ -0,0 +1,7 @@\n"], + expectedNextLine => "+# Python file...\n", +}, +{ + # New test + diffName => "contains \\r\\n lines", + inputText => <<END, # No single quotes to allow interpolation of "\r" +Index: index_path.py\r +===================================================================\r +--- index_path.py (revision 53048) (from copied_from_path.py:53048)\r ++++ index_path.py (working copy)\r +@@ -0,0 +1,7 @@\r ++# Python file...\r +END + expectedReturn => [ +{ + svnConvertedText => <<END, # No single quotes to allow interpolation of "\r" +Index: index_path.py\r +===================================================================\r +--- index_path.py (revision 53048) (from copied_from_path.py:53048)\r ++++ index_path.py (working copy)\r +END + copiedFromPath => "copied_from_path.py", + indexPath => "index_path.py", + sourceRevision => 53048, +}, +"@@ -0,0 +1,7 @@\r\n"], + expectedNextLine => "+# Python file...\r\n", +}, +{ + # New test + diffName => "contains path corrections", + inputText => <<'END', +Index: index_path.py +=================================================================== +--- bad_path (revision 53048) (from copied_from_path.py:53048) ++++ bad_path (working copy) +@@ -0,0 +1,7 @@ ++# Python file... +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: index_path.py +=================================================================== +--- index_path.py (revision 53048) (from copied_from_path.py:53048) ++++ index_path.py (working copy) +END + copiedFromPath => "copied_from_path.py", + indexPath => "index_path.py", + sourceRevision => 53048, +}, +"@@ -0,0 +1,7 @@\n"], + expectedNextLine => "+# Python file...\n", +}, +#### +# Binary test cases +## +{ + # New test + diffName => "binary file", + inputText => <<'END', +Index: test_file.swf +=================================================================== +Cannot display: file marked as a binary type. +svn:mime-type = application/octet-stream + +Property changes on: test_file.swf +___________________________________________________________________ +Name: svn:mime-type + + application/octet-stream + + +Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA== +END + expectedReturn => [ +{ + svnConvertedText => <<'END', +Index: test_file.swf +=================================================================== +Cannot display: file marked as a binary type. +END + indexPath => "test_file.swf", + isBinary => 1, +}, +"svn:mime-type = application/octet-stream\n"], + expectedNextLine => "\n", +}, +); + +my $testCasesCount = @testCaseHashRefs; +plan(tests => 2 * $testCasesCount); # Total number of assertions. + +foreach my $testCase (@testCaseHashRefs) { + my $testNameStart = "parseSvnDiffHeader(): $testCase->{diffName}: comparing"; + + my $fileHandle; + open($fileHandle, "<", \$testCase->{inputText}); + my $line = <$fileHandle>; + + my @got = VCSUtils::parseSvnDiffHeader($fileHandle, $line); + my $expectedReturn = $testCase->{expectedReturn}; + + is_deeply(\@got, $expectedReturn, "$testNameStart return value."); + + my $gotNextLine = <$fileHandle>; + is($gotNextLine, $testCase->{expectedNextLine}, "$testNameStart next read line."); +} diff --git a/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/prepareParsedPatch.pl b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/prepareParsedPatch.pl new file mode 100644 index 0000000..a7ae807 --- /dev/null +++ b/WebKitTools/Scripts/webkitperl/VCSUtils_unittest/prepareParsedPatch.pl @@ -0,0 +1,136 @@ +#!/usr/bin/perl -w +# +# Copyright (C) 2010 Chris Jerdonek (cjerdonek@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 INC. 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 INC. 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. + +# Unit tests of prepareParsedPatch(). + +use strict; +use warnings; + +use Test::More; +use VCSUtils; + +my $diffHashRef1 = { # not a copy, no source revision + copiedFromPath => undef, + indexPath => "indexPath1", + sourceRevision => undef, + svnConvertedText => "diff1", +}; +my $diffHashRef2 = { # not a copy, has source revision + copiedFromPath => undef, + indexPath => "indexPath2", + sourceRevision => 20, + svnConvertedText => "diff2", +}; +my $diffHashRef3 = { # a copy (copies always have source revision) + copiedFromPath => "sourcePath3", + indexPath => "indexPath2", # Deliberately choosing same as $diffHashRef2 + sourceRevision => 3, + svnConvertedText => "diff3", +}; + +my @testCases = ( +{ + # New test + testName => "zero diffs: empty array", + diffHashRefsInput => [], + expected => { + copyDiffHashRefs => [], + nonCopyDiffHashRefs => [], + sourceRevisionHash => {}, + }, +}, +{ + # New test + testName => "one diff: non-copy, no revision", + diffHashRefsInput => [$diffHashRef1], + expected => { + copyDiffHashRefs => [], + nonCopyDiffHashRefs => [$diffHashRef1], + sourceRevisionHash => {}, + }, +}, +{ + # New test + testName => "one diff: non-copy, has revision", + diffHashRefsInput => [$diffHashRef2], + expected => { + copyDiffHashRefs => [], + nonCopyDiffHashRefs => [$diffHashRef2], + sourceRevisionHash => { + "indexPath2" => 20, + } + }, +}, +{ + # New test + testName => "one diff: copy (has revision)", + diffHashRefsInput => [$diffHashRef3], + expected => { + copyDiffHashRefs => [$diffHashRef3], + nonCopyDiffHashRefs => [], + sourceRevisionHash => { + "sourcePath3" => 3, + } + }, +}, +{ + # New test + testName => "two diffs: two non-copies", + diffHashRefsInput => [$diffHashRef1, $diffHashRef2], + expected => { + copyDiffHashRefs => [], + nonCopyDiffHashRefs => [$diffHashRef1, $diffHashRef2], + sourceRevisionHash => { + "indexPath2" => 20, + } + }, +}, +{ + # New test + testName => "two diffs: non-copy and copy", + diffHashRefsInput => [$diffHashRef2, $diffHashRef3], + expected => { + copyDiffHashRefs => [$diffHashRef3], + nonCopyDiffHashRefs => [$diffHashRef2], + sourceRevisionHash => { + "sourcePath3" => 3, + "indexPath2" => 20, + } + }, +}, +); + +my $testCasesCount = @testCases; +plan(tests => $testCasesCount); + +foreach my $testCase (@testCases) { + my $testName = $testCase->{testName}; + my @diffHashRefs = @{$testCase->{diffHashRefsInput}}; + my $expected = $testCase->{expected}; + + my $got = prepareParsedPatch(0, @diffHashRefs); + + is_deeply($got, $expected, $testName); +} + diff --git a/WebKitTools/Scripts/webkitperl/features.pm b/WebKitTools/Scripts/webkitperl/features.pm index 1f88022..7ca924b 100644 --- a/WebKitTools/Scripts/webkitperl/features.pm +++ b/WebKitTools/Scripts/webkitperl/features.pm @@ -72,6 +72,7 @@ sub hasFeature($$) "3D Rendering" => "WebCoreHas3DRendering", "3D Canvas" => "WebGLShader", "WML" => "WMLElement", + "WCSS" => "parseWCSSInputProperty", "XHTMLMP" => "isXHTMLMPDocument", ); my $symbolName = $symbolForFeature{$featureName}; diff --git a/WebKitTools/Scripts/webkitpy/common/array_stream.py b/WebKitTools/Scripts/webkitpy/common/array_stream.py new file mode 100644 index 0000000..e425d02 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/common/array_stream.py @@ -0,0 +1,66 @@ +#!/usr/bin/python +# Copyright (C) 2010 Google 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: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +# OWNER 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. + +"""Package that private an array-based implementation of a stream.""" + + +class ArrayStream(object): + """Simple class that implmements a stream interface on top of an array. + + This is used primarily by unit test classes to mock output streams. It + performs a similar function to StringIO, but (a) it is write-only, and + (b) it can be used to retrieve each individual write(); StringIO + concatenates all of the writes together. + """ + + def __init__(self): + self._contents = [] + + def write(self, msg): + """Implement stream.write() by appending to the stream's contents.""" + self._contents.append(msg) + + def get(self): + """Return the contents of a stream (as an array).""" + return self._contents + + def reset(self): + """Empty the stream.""" + self._contents = [] + + def empty(self): + """Return whether the stream is empty.""" + return (len(self._contents) == 0) + + def flush(self): + """Flush the stream (a no-op implemented for compatibility).""" + pass + + def __repr__(self): + return '<ArrayStream: ' + str(self._contents) + '>' diff --git a/WebKitTools/Scripts/webkitpy/common/array_stream_unittest.py b/WebKitTools/Scripts/webkitpy/common/array_stream_unittest.py new file mode 100644 index 0000000..1a9b34a --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/common/array_stream_unittest.py @@ -0,0 +1,78 @@ +#!/usr/bin/python +# Copyright (C) 2010 Google 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: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +# OWNER 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. + +"""Unit tests for array_stream.py.""" + +import pdb +import unittest + +from webkitpy.common.array_stream import ArrayStream + + +class ArrayStreamTest(unittest.TestCase): + def assertEmpty(self, a_stream): + self.assertTrue(a_stream.empty()) + + def assertNotEmpty(self, a_stream): + self.assertFalse(a_stream.empty()) + + def assertContentsMatch(self, a_stream, contents): + self.assertEquals(a_stream.get(), contents) + + def test_basics(self): + a = ArrayStream() + self.assertEmpty(a) + self.assertContentsMatch(a, []) + + a.flush() + self.assertEmpty(a) + self.assertContentsMatch(a, []) + + a.write("foo") + a.write("bar") + self.assertNotEmpty(a) + self.assertContentsMatch(a, ["foo", "bar"]) + + a.flush() + self.assertNotEmpty(a) + self.assertContentsMatch(a, ["foo", "bar"]) + + a.reset() + self.assertEmpty(a) + self.assertContentsMatch(a, []) + + self.assertEquals(str(a), "<ArrayStream: []>") + + a.write("foo") + self.assertNotEmpty(a) + self.assertContentsMatch(a, ["foo"]) + self.assertEquals(str(a), "<ArrayStream: ['foo']>") + +if __name__ == '__main__': + unittest.main() diff --git a/WebKitTools/Scripts/webkitpy/common/checkout/api.py b/WebKitTools/Scripts/webkitpy/common/checkout/api.py index c4e2b69..a5ac939 100644 --- a/WebKitTools/Scripts/webkitpy/common/checkout/api.py +++ b/WebKitTools/Scripts/webkitpy/common/checkout/api.py @@ -27,7 +27,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os -import subprocess import StringIO from webkitpy.common.checkout.changelog import ChangeLog @@ -50,7 +49,11 @@ class Checkout(object): def _latest_entry_for_changelog_at_revision(self, changelog_path, revision): changelog_contents = self._scm.contents_at_revision(changelog_path, revision) - return ChangeLog.parse_latest_entry_from_file(StringIO.StringIO(changelog_contents)) + # contents_at_revision returns a byte array (str()), but we know + # that ChangeLog files are utf-8. parse_latest_entry_from_file + # expects a file-like object which vends unicode(), so we decode here. + changelog_file = StringIO.StringIO(changelog_contents.decode("utf-8")) + return ChangeLog.parse_latest_entry_from_file(changelog_file) def changelog_entries_for_revision(self, revision): changed_files = self._scm.changed_files_for_revision(revision) @@ -80,16 +83,16 @@ class Checkout(object): def bug_id_for_revision(self, revision): return self.commit_info_for_revision(revision).bug_id() - def modified_changelogs(self): + def modified_changelogs(self, git_commit, squash): # SCM returns paths relative to scm.checkout_root # Callers (especially those using the ChangeLog class) may # expect absolute paths, so this method returns absolute paths. - changed_files = self._scm.changed_files() + changed_files = self._scm.changed_files(git_commit, squash) absolute_paths = [os.path.join(self._scm.checkout_root, path) for path in changed_files] return [path for path in absolute_paths if self._is_path_to_changelog(path)] - def commit_message_for_this_commit(self): - changelog_paths = self.modified_changelogs() + def commit_message_for_this_commit(self, git_commit, squash): + changelog_paths = self.modified_changelogs(git_commit, squash) if not len(changelog_paths): raise ScriptError(message="Found no modified ChangeLogs, cannot create a commit message.\n" "All changes require a ChangeLog. See:\n" @@ -106,32 +109,29 @@ class Checkout(object): # FIXME: We should sort and label the ChangeLog messages like commit-log-editor does. return CommitMessage("".join(changelog_messages).splitlines()) - def bug_id_for_this_commit(self): + def bug_id_for_this_commit(self, git_commit, squash): try: - return parse_bug_id(self.commit_message_for_this_commit().message()) + return parse_bug_id(self.commit_message_for_this_commit(git_commit, squash).message()) except ScriptError, e: pass # We might not have ChangeLogs. def apply_patch(self, patch, force=False): # It's possible that the patch was not made from the root directory. # We should detect and handle that case. - # FIXME: Use Executive instead of subprocess here. - curl_process = subprocess.Popen(['curl', '--location', '--silent', '--show-error', patch.url()], stdout=subprocess.PIPE) # FIXME: Move _scm.script_path here once we get rid of all the dependencies. args = [self._scm.script_path('svn-apply')] if patch.reviewer(): args += ['--reviewer', patch.reviewer().full_name] if force: args.append('--force') - - run_command(args, input=curl_process.stdout) + run_command(args, input=patch.contents()) def apply_reverse_diff(self, revision): self._scm.apply_reverse_diff(revision) # We revert the ChangeLogs because removing lines from a ChangeLog # doesn't make sense. ChangeLogs are append only. - changelog_paths = self.modified_changelogs() + changelog_paths = self.modified_changelogs(git_commit=None, squash=False) if len(changelog_paths): self._scm.revert_files(changelog_paths) diff --git a/WebKitTools/Scripts/webkitpy/common/checkout/api_unittest.py b/WebKitTools/Scripts/webkitpy/common/checkout/api_unittest.py index e99caee..1436379 100644 --- a/WebKitTools/Scripts/webkitpy/common/checkout/api_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/checkout/api_unittest.py @@ -26,6 +26,9 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +from __future__ import with_statement + +import codecs import os import shutil import tempfile @@ -37,14 +40,14 @@ from webkitpy.common.checkout.scm import detect_scm_system, CommitMessage from webkitpy.common.system.outputcapture import OutputCapture from webkitpy.thirdparty.mock import Mock + # FIXME: Copied from scm_unittest.py -def write_into_file_at_path(file_path, contents): - new_file = open(file_path, 'w') - new_file.write(contents) - new_file.close() +def write_into_file_at_path(file_path, contents, encoding="utf-8"): + with codecs.open(file_path, "w", encoding) as file: + file.write(contents) -_changelog1entry1 = """2010-03-25 Eric Seidel <eric@webkit.org> +_changelog1entry1 = u"""2010-03-25 Tor Arne Vestb\u00f8 <vestbo@webkit.org> Unreviewed build fix to un-break webkit-patch land. @@ -53,7 +56,7 @@ _changelog1entry1 = """2010-03-25 Eric Seidel <eric@webkit.org> * Scripts/webkitpy/common/checkout/api.py: import scm.CommitMessage """ -_changelog1entry2 = """2010-03-25 Adam Barth <abarth@webkit.org> +_changelog1entry2 = u"""2010-03-25 Adam Barth <abarth@webkit.org> Reviewed by Eric Seidel. @@ -62,8 +65,8 @@ _changelog1entry2 = """2010-03-25 Adam Barth <abarth@webkit.org> * Scripts/webkitpy/common/checkout/api.py: """ -_changelog1 = "\n".join([_changelog1entry1, _changelog1entry2]) -_changelog2 = """2010-03-25 Eric Seidel <eric@webkit.org> +_changelog1 = u"\n".join([_changelog1entry1, _changelog1entry2]) +_changelog2 = u"""2010-03-25 Tor Arne Vestb\u00f8 <vestbo@webkit.org> Unreviewed build fix to un-break webkit-patch land. @@ -79,7 +82,7 @@ _changelog2 = """2010-03-25 Eric Seidel <eric@webkit.org> """ class CommitMessageForThisCommitTest(unittest.TestCase): - expected_commit_message = """2010-03-25 Eric Seidel <eric@webkit.org> + expected_commit_message = u"""2010-03-25 Tor Arne Vestb\u00f8 <vestbo@webkit.org> Unreviewed build fix to un-break webkit-patch land. @@ -87,7 +90,7 @@ class CommitMessageForThisCommitTest(unittest.TestCase): https://bugs.webkit.org/show_bug.cgi?id=36629 * Scripts/webkitpy/common/checkout/api.py: import scm.CommitMessage -2010-03-25 Eric Seidel <eric@webkit.org> +2010-03-25 Tor Arne Vestb\u00f8 <vestbo@webkit.org> Unreviewed build fix to un-break webkit-patch land. @@ -111,10 +114,11 @@ class CommitMessageForThisCommitTest(unittest.TestCase): # ChangeLog is difficult to mock at current. def test_commit_message_for_this_commit(self): checkout = Checkout(None) - checkout.modified_changelogs = lambda: ["ChangeLog1", "ChangeLog2"] + checkout.modified_changelogs = lambda git_commit, squash: ["ChangeLog1", "ChangeLog2"] output = OutputCapture() expected_stderr = "Parsing ChangeLog: ChangeLog1\nParsing ChangeLog: ChangeLog2\n" - commit_message = output.assert_outputs(self, checkout.commit_message_for_this_commit, expected_stderr=expected_stderr) + commit_message = output.assert_outputs(self, checkout.commit_message_for_this_commit, + kwargs={"git_commit": None, "squash": False}, expected_stderr=expected_stderr) self.assertEqual(commit_message.message(), self.expected_commit_message) @@ -124,7 +128,9 @@ class CheckoutTest(unittest.TestCase): def mock_contents_at_revision(changelog_path, revision): self.assertEqual(changelog_path, "foo") self.assertEqual(revision, "bar") - return _changelog1 + # contents_at_revision is expected to return a byte array (str) + # so we encode our unicode ChangeLog down to a utf-8 stream. + return _changelog1.encode("utf-8") scm.contents_at_revision = mock_contents_at_revision checkout = Checkout(scm) entry = checkout._latest_entry_for_changelog_at_revision("foo", "bar") @@ -137,8 +143,8 @@ class CheckoutTest(unittest.TestCase): checkout.changelog_entries_for_revision = lambda revision: [ChangeLogEntry(_changelog1entry1)] commitinfo = checkout.commit_info_for_revision(4) self.assertEqual(commitinfo.bug_id(), 36629) - self.assertEqual(commitinfo.author_name(), "Eric Seidel") - self.assertEqual(commitinfo.author_email(), "eric@webkit.org") + self.assertEqual(commitinfo.author_name(), u"Tor Arne Vestb\u00f8") + self.assertEqual(commitinfo.author_email(), "vestbo@webkit.org") self.assertEqual(commitinfo.reviewer_text(), None) self.assertEqual(commitinfo.reviewer(), None) self.assertEqual(commitinfo.committer_email(), "committer@example.com") @@ -157,13 +163,13 @@ class CheckoutTest(unittest.TestCase): def test_bug_id_for_this_commit(self): scm = Mock() checkout = Checkout(scm) - checkout.commit_message_for_this_commit = lambda: CommitMessage(ChangeLogEntry(_changelog1entry1).contents().splitlines()) - self.assertEqual(checkout.bug_id_for_this_commit(), 36629) + checkout.commit_message_for_this_commit = lambda git_commit, squash: CommitMessage(ChangeLogEntry(_changelog1entry1).contents().splitlines()) + self.assertEqual(checkout.bug_id_for_this_commit(git_commit=None, squash=False), 36629) def test_modified_changelogs(self): scm = Mock() scm.checkout_root = "/foo/bar" - scm.changed_files = lambda:["file1", "ChangeLog", "relative/path/ChangeLog"] + scm.changed_files = lambda git_commit, squash: ["file1", "ChangeLog", "relative/path/ChangeLog"] checkout = Checkout(scm) expected_changlogs = ["/foo/bar/ChangeLog", "/foo/bar/relative/path/ChangeLog"] - self.assertEqual(checkout.modified_changelogs(), expected_changlogs) + self.assertEqual(checkout.modified_changelogs(git_commit=None, squash=False), expected_changlogs) diff --git a/WebKitTools/Scripts/webkitpy/common/checkout/changelog.py b/WebKitTools/Scripts/webkitpy/common/checkout/changelog.py index e93896f..6220fbd 100644 --- a/WebKitTools/Scripts/webkitpy/common/checkout/changelog.py +++ b/WebKitTools/Scripts/webkitpy/common/checkout/changelog.py @@ -99,10 +99,14 @@ class ChangeLog(object): @staticmethod def parse_latest_entry_from_file(changelog_file): + """changelog_file must be a file-like object which returns + unicode strings. Use codecs.open or StringIO(unicode()) + to pass file objects to this class.""" date_line_regexp = re.compile(ChangeLogEntry.date_line_regexp) entry_lines = [] # The first line should be a date line. first_line = changelog_file.readline() + assert(isinstance(first_line, unicode)) if not date_line_regexp.match(first_line): return None entry_lines.append(first_line) diff --git a/WebKitTools/Scripts/webkitpy/common/checkout/changelog_unittest.py b/WebKitTools/Scripts/webkitpy/common/checkout/changelog_unittest.py index 9210c9c..864428a 100644 --- a/WebKitTools/Scripts/webkitpy/common/checkout/changelog_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/checkout/changelog_unittest.py @@ -26,9 +26,12 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import unittest +from __future__ import with_statement + +import codecs import os import tempfile +import unittest from StringIO import StringIO @@ -52,7 +55,7 @@ class ChangeLogsTest(unittest.TestCase): ''' # More example text than we need. Eventually we need to support parsing this all and write tests for the parsing. - _example_changelog = '''2009-08-17 David Kilzer <ddkilzer@apple.com> + _example_changelog = u"""2009-08-17 Tor Arne Vestb\xf8 <vestbo@webkit.org> <http://webkit.org/b/28393> check-webkit-style: add check for use of std::max()/std::min() instead of MAX()/MIN() @@ -84,10 +87,10 @@ class ChangeLogsTest(unittest.TestCase): so we can't assert here. == Rolled over to ChangeLog-2009-06-16 == -''' +""" def test_latest_entry_parse(self): - changelog_contents = "%s\n%s" % (self._example_entry, self._example_changelog) + changelog_contents = u"%s\n%s" % (self._example_entry, self._example_changelog) changelog_file = StringIO(changelog_contents) latest_entry = ChangeLog.parse_latest_entry_from_file(changelog_file) self.assertEquals(latest_entry.contents(), self._example_entry) @@ -97,19 +100,17 @@ class ChangeLogsTest(unittest.TestCase): self.assertTrue(latest_entry.reviewer()) # Make sure that our UTF8-based lookup of Tor works. @staticmethod - def _write_tmp_file_with_contents(contents): + def _write_tmp_file_with_contents(byte_array): + assert(isinstance(byte_array, str)) (file_descriptor, file_path) = tempfile.mkstemp() # NamedTemporaryFile always deletes the file on close in python < 2.6 - file = os.fdopen(file_descriptor, 'w') - file.write(contents) - file.close() + with os.fdopen(file_descriptor, "w") as file: + file.write(byte_array) return file_path @staticmethod - def _read_file_contents(file_path): - file = open(file_path) - contents = file.read() - file.close() - return contents + def _read_file_contents(file_path, encoding): + with codecs.open(file_path, "r", encoding) as file: + return file.read() _new_entry_boilerplate = '''2009-08-19 Eric Seidel <eric@webkit.org> @@ -121,11 +122,11 @@ class ChangeLogsTest(unittest.TestCase): ''' def test_set_reviewer(self): - changelog_contents = "%s\n%s" % (self._new_entry_boilerplate, self._example_changelog) - changelog_path = self._write_tmp_file_with_contents(changelog_contents) + changelog_contents = u"%s\n%s" % (self._new_entry_boilerplate, self._example_changelog) + changelog_path = self._write_tmp_file_with_contents(changelog_contents.encode("utf-8")) reviewer_name = 'Test Reviewer' ChangeLog(changelog_path).set_reviewer(reviewer_name) - actual_contents = self._read_file_contents(changelog_path) + actual_contents = self._read_file_contents(changelog_path, "utf-8") expected_contents = changelog_contents.replace('NOBODY (OOPS!)', reviewer_name) os.remove(changelog_path) self.assertEquals(actual_contents, expected_contents) @@ -169,8 +170,8 @@ class ChangeLogsTest(unittest.TestCase): ''' def _assert_update_for_revert_output(self, args, expected_entry): - changelog_contents = "%s\n%s" % (self._new_entry_boilerplate, self._example_changelog) - changelog_path = self._write_tmp_file_with_contents(changelog_contents) + changelog_contents = u"%s\n%s" % (self._new_entry_boilerplate, self._example_changelog) + changelog_path = self._write_tmp_file_with_contents(changelog_contents.encode("utf-8")) changelog = ChangeLog(changelog_path) changelog.update_for_revert(*args) actual_entry = changelog.latest_entry() diff --git a/WebKitTools/Scripts/webkitpy/common/checkout/commitinfo.py b/WebKitTools/Scripts/webkitpy/common/checkout/commitinfo.py index 7c3315f..448d530 100644 --- a/WebKitTools/Scripts/webkitpy/common/checkout/commitinfo.py +++ b/WebKitTools/Scripts/webkitpy/common/checkout/commitinfo.py @@ -28,8 +28,6 @@ # # WebKit's python module for holding information on a commit -import StringIO - from webkitpy.common.checkout.changelog import view_source_url from webkitpy.common.config.committers import CommitterList diff --git a/WebKitTools/Scripts/webkitpy/common/checkout/scm.py b/WebKitTools/Scripts/webkitpy/common/checkout/scm.py index 2704f07..02e114a 100644 --- a/WebKitTools/Scripts/webkitpy/common/checkout/scm.py +++ b/WebKitTools/Scripts/webkitpy/common/checkout/scm.py @@ -41,11 +41,13 @@ from webkitpy.common.system.deprecated_logging import error, log def detect_scm_system(path): - if SVN.in_working_directory(path): - return SVN(cwd=path) + absolute_path = os.path.abspath(path) + + if SVN.in_working_directory(absolute_path): + return SVN(cwd=absolute_path) - if Git.in_working_directory(path): - return Git(cwd=path) + if Git.in_working_directory(absolute_path): + return Git(cwd=absolute_path) return None @@ -145,7 +147,7 @@ class SCM: return filenames def strip_r_from_svn_revision(self, svn_revision): - match = re.match("^r(?P<svn_revision>\d+)", svn_revision) + match = re.match("^r(?P<svn_revision>\d+)", unicode(svn_revision)) if (match): return match.group('svn_revision') return svn_revision @@ -178,7 +180,7 @@ class SCM: def add(self, path): raise NotImplementedError, "subclasses must implement" - def changed_files(self): + def changed_files(self, git_commit=None, squash=None): raise NotImplementedError, "subclasses must implement" def changed_files_for_revision(self): @@ -193,7 +195,7 @@ class SCM: def display_name(self): raise NotImplementedError, "subclasses must implement" - def create_patch(self): + def create_patch(self, git_commit=None, squash=None): raise NotImplementedError, "subclasses must implement" def committer_email_for_revision(self, revision): @@ -211,7 +213,10 @@ class SCM: def revert_files(self, file_paths): raise NotImplementedError, "subclasses must implement" - def commit_with_message(self, message, username=None): + def should_squash(self, squash): + raise NotImplementedError, "subclasses must implement" + + def commit_with_message(self, message, username=None, git_commit=None, squash=None): raise NotImplementedError, "subclasses must implement" def svn_commit_log(self, svn_revision): @@ -229,12 +234,6 @@ class SCM: def svn_merge_base(): raise NotImplementedError, "subclasses must implement" - def create_patch_from_local_commit(self, commit_id): - error("Your source control manager does not support creating a patch from a local commit.") - - def create_patch_since_local_commit(self, commit_id): - error("Your source control manager does not support creating a patch from a local commit.") - def commit_locally_with_message(self, message): error("Your source control manager does not support local commits.") @@ -308,7 +307,7 @@ class SVN(SCM): return self.cached_version def working_directory_is_clean(self): - return run_command(["svn", "diff"], cwd=self.checkout_root) == "" + return run_command(["svn", "diff"], cwd=self.checkout_root, decode_output=False) == "" def clean_working_directory(self): # svn revert -R is not as awesome as git reset --hard. @@ -339,12 +338,13 @@ class SVN(SCM): # path is assumed to be cwd relative? run_command(["svn", "add", path]) - def changed_files(self): + def changed_files(self, git_commit=None, squash=None): return self.run_status_and_extract_filenames(self.status_command(), self._status_regexp("ACDMR")) def changed_files_for_revision(self, revision): # As far as I can tell svn diff --summarize output looks just like svn status output. - status_command = ["svn", "diff", "--summarize", "-c", str(revision)] + # No file contents printed, thus utf-8 auto-decoding in run_command is fine. + status_command = ["svn", "diff", "--summarize", "-c", revision] return self.run_status_and_extract_filenames(status_command, self._status_regexp("ACDMR")) def conflicted_files(self): @@ -360,19 +360,26 @@ class SVN(SCM): def display_name(self): return "svn" - def create_patch(self): - return run_command(self.script_path("svn-create-patch"), cwd=self.checkout_root, return_stderr=False) + def create_patch(self, git_commit=None, squash=None): + """Returns a byte array (str()) representing the patch file. + Patch files are effectively binary since they may contain + files of multiple different encodings.""" + return run_command([self.script_path("svn-create-patch")], + cwd=self.checkout_root, return_stderr=False, + decode_output=False) def committer_email_for_revision(self, revision): - return run_command(["svn", "propget", "svn:author", "--revprop", "-r", str(revision)]).rstrip() + return run_command(["svn", "propget", "svn:author", "--revprop", "-r", revision]).rstrip() def contents_at_revision(self, path, revision): + """Returns a byte array (str()) containing the contents + of path @ revision in the repository.""" remote_path = "%s/%s" % (self._repository_url(), path) - return run_command(["svn", "cat", "-r", str(revision), remote_path]) + return run_command(["svn", "cat", "-r", revision, remote_path], decode_output=False) def diff_for_revision(self, revision): # FIXME: This should probably use cwd=self.checkout_root - return run_command(['svn', 'diff', '-c', str(revision)]) + return run_command(['svn', 'diff', '-c', revision]) def _repository_url(self): return self.value_from_svn_info(self.checkout_root, 'URL') @@ -389,7 +396,12 @@ class SVN(SCM): # FIXME: This should probably use cwd=self.checkout_root. run_command(['svn', 'revert'] + file_paths) - def commit_with_message(self, message, username=None): + def should_squash(self, squash): + # SVN doesn't support the concept of squashing. + return False + + def commit_with_message(self, message, username=None, git_commit=None, squash=None): + # squash and git-commit are not used by SVN. if self.dryrun: # Return a string which looks like a commit so that things which parse this output will succeed. return "Dry run, no commit.\nCommitted revision 0." @@ -405,7 +417,7 @@ class SVN(SCM): return run_command(svn_commit_args, error_handler=commit_error_handler) def svn_commit_log(self, svn_revision): - svn_revision = self.strip_r_from_svn_revision(str(svn_revision)) + svn_revision = self.strip_r_from_svn_revision(svn_revision) return run_command(['svn', 'log', '--non-interactive', '--revision', svn_revision]); def last_svn_commit_log(self): @@ -466,6 +478,7 @@ class Git(SCM): def status_command(self): # git status returns non-zero when there are changes, so we use git diff name --name-status HEAD instead. + # No file contents printed, thus utf-8 autodecoding in run_command is fine. return ["git", "diff", "--name-status", "HEAD"] def _status_regexp(self, expected_types): @@ -475,8 +488,24 @@ class Git(SCM): # path is assumed to be cwd relative? run_command(["git", "add", path]) - def changed_files(self): - status_command = ['git', 'diff', '-r', '--name-status', '-C', '-M', 'HEAD'] + def _merge_base(self, git_commit, squash): + if git_commit: + # FIXME: Calling code should turn commit ranges into a list of commit IDs + # and then treat each commit separately. + if '..' not in git_commit: + git_commit = git_commit + "^.." + git_commit + return git_commit + + if self.should_squash(squash): + return self.svn_merge_base() + + # FIXME: Non-squash behavior should match commit_with_message. It raises an error + # if there are working copy changes and --squash or --no-squash wasn't passed in. + # If --no-squash, then it should proceed with each local commit as a separate patch. + return 'HEAD' + + def changed_files(self, git_commit=None, squash=None): + status_command = ['git', 'diff', '-r', '--name-status', '-C', '-M', "--no-ext-diff", "--full-index", self._merge_base(git_commit, squash)] return self.run_status_and_extract_filenames(status_command, self._status_regexp("ADM")) def _changes_files_for_commit(self, git_commit): @@ -490,6 +519,8 @@ class Git(SCM): return self._changes_files_for_commit(commit_id) def conflicted_files(self): + # We do not need to pass decode_output for this diff command + # as we're passing --name-status which does not output any data. status_command = ['git', 'diff', '--name-status', '-C', '-M', '--diff-filter=U'] return self.run_status_and_extract_filenames(status_command, self._status_regexp("U")) @@ -503,9 +534,12 @@ class Git(SCM): def display_name(self): return "git" - def create_patch(self): + def create_patch(self, git_commit=None, squash=None): + """Returns a byte array (str()) representing the patch file. + Patch files are effectively binary since they may contain + files of multiple different encodings.""" # FIXME: This should probably use cwd=self.checkout_root - return run_command(['git', 'diff', '--binary', 'HEAD']) + return run_command(['git', 'diff', '--binary', "--no-ext-diff", "--full-index", "-M", self._merge_base(git_commit, squash)], decode_output=False) @classmethod def git_commit_from_svn_revision(cls, revision): @@ -517,11 +551,13 @@ class Git(SCM): return git_commit def contents_at_revision(self, path, revision): - return run_command(["git", "show", "%s:%s" % (self.git_commit_from_svn_revision(revision), path)]) + """Returns a byte array (str()) containing the contents + of path @ revision in the repository.""" + return run_command(["git", "show", "%s:%s" % (self.git_commit_from_svn_revision(revision), path)], decode_output=False) def diff_for_revision(self, revision): git_commit = self.git_commit_from_svn_revision(revision) - return self.create_patch_from_local_commit(git_commit) + return self.create_patch(git_commit) def committer_email_for_revision(self, revision): git_commit = self.git_commit_from_svn_revision(revision) @@ -538,11 +574,100 @@ class Git(SCM): def revert_files(self, file_paths): run_command(['git', 'checkout', 'HEAD'] + file_paths) - def commit_with_message(self, message, username=None): + def should_squash(self, squash): + if squash is not None: + # Squash is specified on the command-line. + return squash + + config_squash = Git.read_git_config('webkit-patch.squash') + if (config_squash and config_squash is not ""): + return config_squash.lower() == "true" + + # Only raise an error if there are actually multiple commits to squash. + num_local_commits = len(self.local_commits()) + if num_local_commits > 1 or num_local_commits > 0 and not self.working_directory_is_clean(): + working_directory_message = "" if self.working_directory_is_clean() else " and working copy changes" + raise ScriptError(message="""There are %s local commits%s. Do one of the following: +1) Use --squash or --no-squash +2) git config webkit-patch.squash true/false +""" % (num_local_commits, working_directory_message)) + + return None + + def commit_with_message(self, message, username=None, git_commit=None, squash=None): # Username is ignored during Git commits. - self.commit_locally_with_message(message) + if git_commit: + # Need working directory changes to be committed so we can checkout the merge branch. + if not self.working_directory_is_clean(): + # FIXME: webkit-patch land will modify the ChangeLogs to correct the reviewer. + # That will modify the working-copy and cause us to hit this error. + # The ChangeLog modification could be made to modify the existing local commit? + raise ScriptError(message="Working copy is modified. Cannot commit individual git_commits.") + return self._commit_on_branch(message, git_commit) + + squash = self.should_squash(squash) + if squash: + run_command(['git', 'reset', '--soft', self.svn_branch_name()]) + self.commit_locally_with_message(message) + elif not self.working_directory_is_clean(): + if not len(self.local_commits()): + # There are only working copy changes. Assume they should be committed. + self.commit_locally_with_message(message) + elif squash is None: + # The user didn't explicitly say to squash or not squash. There are local commits + # and working copy changes. Not clear what the user wants. + raise ScriptError(message="""There are local commits and working copy changes. Do one of the following: +1) Commit/revert working copy changes. +2) Use --squash or --no-squash +3) git config webkit-patch.squash true/false +""") + + # FIXME: This will commit all local commits, each with it's own message. We should restructure + # so that each local commit has the appropriate commit message based off it's ChangeLogs. return self.push_local_commits_to_server() + def _commit_on_branch(self, message, git_commit): + branch_ref = run_command(['git', 'symbolic-ref', 'HEAD']).strip() + branch_name = branch_ref.replace('refs/heads/', '') + commit_ids = self.commit_ids_from_commitish_arguments([git_commit]) + + # We want to squash all this branch's commits into one commit with the proper description. + # We do this by doing a "merge --squash" into a new commit branch, then dcommitting that. + MERGE_BRANCH = 'webkit-patch-land' + self.delete_branch(MERGE_BRANCH) + + # We might be in a directory that's present in this branch but not in the + # trunk. Move up to the top of the tree so that git commands that expect a + # valid CWD won't fail after we check out the merge branch. + os.chdir(self.checkout_root) + + # Stuff our change into the merge branch. + # We wrap in a try...finally block so if anything goes wrong, we clean up the branches. + commit_succeeded = True + try: + run_command(['git', 'checkout', '-q', '-b', MERGE_BRANCH, self.svn_branch_name()]) + + for commit in commit_ids: + # We're on a different branch now, so convert "head" to the branch name. + commit = re.sub(r'(?i)head', branch_name, commit) + # FIXME: Once changed_files and create_patch are modified to separately handle each + # commit in a commit range, commit each cherry pick so they'll get dcommitted separately. + run_command(['git', 'cherry-pick', '--no-commit', commit]) + + run_command(['git', 'commit', '-m', message]) + output = self.push_local_commits_to_server() + except Exception, e: + log("COMMIT FAILED: " + str(e)) + output = "Commit failed." + commit_succeeded = False + finally: + # And then swap back to the original branch and clean up. + self.clean_working_directory() + run_command(['git', 'checkout', '-q', branch_name]) + self.delete_branch(MERGE_BRANCH) + + return output + def svn_commit_log(self, svn_revision): svn_revision = self.strip_r_from_svn_revision(svn_revision) return run_command(['git', 'svn', 'log', '-r', svn_revision]) @@ -560,13 +685,9 @@ class Git(SCM): return run_command(['git', 'merge-base', self.svn_branch_name(), 'HEAD']).strip() def svn_branch_name(self): - return Git.read_git_config('svn-remote.svn.fetch').split(':')[1] - - def create_patch_from_local_commit(self, commit_id): - return run_command(['git', 'diff', '--binary', commit_id + "^.." + commit_id]) - - def create_patch_since_local_commit(self, commit_id): - return run_command(['git', 'diff', '--binary', commit_id]) + # FIXME: This should so something like: Git.read_git_config('svn-remote.svn.fetch').split(':')[1] + # but that doesn't work if the git repo is tracking multiple svn branches. + return 'trunk' def commit_locally_with_message(self, message): run_command(['git', 'commit', '--all', '-F', '-'], input=message) diff --git a/WebKitTools/Scripts/webkitpy/common/checkout/scm_unittest.py b/WebKitTools/Scripts/webkitpy/common/checkout/scm_unittest.py index c0a64d4..5a2c094 100644 --- a/WebKitTools/Scripts/webkitpy/common/checkout/scm_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/checkout/scm_unittest.py @@ -27,7 +27,10 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +from __future__ import with_statement + import base64 +import codecs import getpass import os import os.path @@ -49,23 +52,39 @@ from webkitpy.common.system.executive import Executive, run_command, ScriptError # Perhaps through some SCMTest base-class which both SVNTest and GitTest inherit from. # FIXME: This should be unified into one of the executive.py commands! +# Callers could use run_and_throw_if_fail(args, cwd=cwd, quiet=True) def run_silent(args, cwd=None): + # Note: Not thread safe: http://bugs.python.org/issue2320 process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd) process.communicate() # ignore output exit_code = process.wait() if exit_code: raise ScriptError('Failed to run "%s" exit_code: %d cwd: %s' % (args, exit_code, cwd)) -def write_into_file_at_path(file_path, contents): - file = open(file_path, 'w') - file.write(contents) - file.close() -def read_from_path(file_path): - file = open(file_path, 'r') - contents = file.read() - file.close() - return contents +def write_into_file_at_path(file_path, contents, encoding="utf-8"): + with codecs.open(file_path, "w", encoding) as file: + file.write(contents) + + +def read_from_path(file_path, encoding="utf-8"): + with codecs.open(file_path, "r", encoding) as file: + return file.read() + + +def _make_diff(command, *args): + # We use this wrapper to disable output decoding. diffs should be treated as + # binary files since they may include text files of multiple differnet encodings. + return run_command([command, "diff"] + list(args), decode_output=False) + + +def _svn_diff(*args): + return _make_diff("svn", *args) + + +def _git_diff(*args): + return _make_diff("git", *args) + # Exists to share svn repository creation code between the git and svn tests class SVNTestRepository: @@ -103,7 +122,11 @@ class SVNTestRepository: cls._svn_add("test_file2") cls._svn_commit("third commit") - write_into_file_at_path("test_file", "test1test2test3\ntest4\n") + # This 4th commit is used to make sure that our patch file handling + # code correctly treats patches as binary and does not attempt to + # decode them assuming they're utf-8. + write_into_file_at_path("test_file", u"latin1 test: \u00A0\n", "latin1") + write_into_file_at_path("test_file2", u"utf-8 test: \u00A0\n", "utf-8") cls._svn_commit("fourth commit") # svn does not seem to update after commit as I would expect. @@ -122,6 +145,19 @@ class SVNTestRepository: test_object.svn_checkout_path = tempfile.mkdtemp(suffix="svn_test_checkout") run_command(['svn', 'checkout', '--quiet', test_object.svn_repo_url, test_object.svn_checkout_path]) + # Create and checkout a trunk dir to match the standard svn configuration to match git-svn's expectations + os.chdir(test_object.svn_checkout_path) + os.mkdir('trunk') + cls._svn_add('trunk') + # We can add tags and branches as well if we ever need to test those. + cls._svn_commit('add trunk') + + # Change directory out of the svn checkout so we can delete the checkout directory. + # _setup_test_commits will CD back to the svn checkout directory. + os.chdir('/') + run_command(['rm', '-rf', test_object.svn_checkout_path]) + run_command(['svn', 'checkout', '--quiet', test_object.svn_repo_url + '/trunk', test_object.svn_checkout_path]) + cls._setup_test_commits(test_object) @classmethod @@ -181,15 +217,12 @@ svn: resource out of date; try updating # GitTest and SVNTest inherit from this so any test_ methods here will be run once for this class and then once for each subclass. class SCMTest(unittest.TestCase): def _create_patch(self, patch_contents): - patch_path = os.path.join(self.svn_checkout_path, 'patch.diff') - write_into_file_at_path(patch_path, patch_contents) - patch = {} - patch['bug_id'] = '12345' - patch['url'] = 'file://%s' % urllib.pathname2url(patch_path) + # FIXME: This code is brittle if the Attachment API changes. + attachment = Attachment({"bug_id": 12345}, None) + attachment.contents = lambda: patch_contents - attachment = Attachment(patch, None) # FIXME: This is a hack, scm.py shouldn't be fetching attachment data. joe_cool = Committer(name="Joe Cool", email_or_emails=None) - attachment._reviewer = joe_cool + attachment.reviewer = lambda: joe_cool return attachment @@ -202,15 +235,6 @@ class SCMTest(unittest.TestCase): # Tests which both GitTest and SVNTest should run. # FIXME: There must be a simpler way to add these w/o adding a wrapper method to both subclasses - def _shared_test_commit_with_message(self, username="dbates@webkit.org"): - write_into_file_at_path('test_file', 'more test content') - commit_text = self.scm.commit_with_message("another test commit", username) - self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '5') - - self.scm.dryrun = True - write_into_file_at_path('test_file', 'still more test content') - commit_text = self.scm.commit_with_message("yet another test commit", username) - self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '0') def _shared_test_changed_files(self): write_into_file_at_path("test_file", "changed content") @@ -248,19 +272,22 @@ class SCMTest(unittest.TestCase): def _shared_test_changed_files_for_revision(self): # SVN reports directory changes, Git does not. - changed_files = self.scm.changed_files_for_revision(2) + changed_files = self.scm.changed_files_for_revision(3) if "test_dir" in changed_files: changed_files.remove("test_dir") self.assertEqual(changed_files, ["test_dir/test_file3", "test_file"]) - self.assertEqual(sorted(self.scm.changed_files_for_revision(3)), sorted(["test_file", "test_file2"])) # Git and SVN return different orders. - self.assertEqual(self.scm.changed_files_for_revision(4), ["test_file"]) + self.assertEqual(sorted(self.scm.changed_files_for_revision(4)), sorted(["test_file", "test_file2"])) # Git and SVN return different orders. + self.assertEqual(self.scm.changed_files_for_revision(2), ["test_file"]) def _shared_test_contents_at_revision(self): - self.assertEqual(self.scm.contents_at_revision("test_file", 2), "test1test2") - self.assertEqual(self.scm.contents_at_revision("test_file", 3), "test1test2test3\n") - self.assertEqual(self.scm.contents_at_revision("test_file", 4), "test1test2test3\ntest4\n") + self.assertEqual(self.scm.contents_at_revision("test_file", 3), "test1test2") + self.assertEqual(self.scm.contents_at_revision("test_file", 4), "test1test2test3\n") + + # Verify that contents_at_revision returns a byte array, aka str(): + self.assertEqual(self.scm.contents_at_revision("test_file", 5), u"latin1 test: \u00A0\n".encode("latin1")) + self.assertEqual(self.scm.contents_at_revision("test_file2", 5), u"utf-8 test: \u00A0\n".encode("utf-8")) - self.assertEqual(self.scm.contents_at_revision("test_file2", 3), "second file") + self.assertEqual(self.scm.contents_at_revision("test_file2", 4), "second file") # Files which don't exist: # Currently we raise instead of returning None because detecting the difference between # "file not found" and any other error seems impossible with svn (git seems to expose such through the return code). @@ -268,21 +295,21 @@ class SCMTest(unittest.TestCase): self.assertRaises(ScriptError, self.scm.contents_at_revision, "does_not_exist", 2) def _shared_test_committer_email_for_revision(self): - self.assertEqual(self.scm.committer_email_for_revision(2), getpass.getuser()) # Committer "email" will be the current user + self.assertEqual(self.scm.committer_email_for_revision(3), getpass.getuser()) # Committer "email" will be the current user def _shared_test_reverse_diff(self): self._setup_webkittools_scripts_symlink(self.scm) # Git's apply_reverse_diff uses resolve-ChangeLogs # Only test the simple case, as any other will end up with conflict markers. - self.scm.apply_reverse_diff('4') + self.scm.apply_reverse_diff('5') self.assertEqual(read_from_path('test_file'), "test1test2test3\n") def _shared_test_diff_for_revision(self): # Patch formats are slightly different between svn and git, so just regexp for things we know should be there. - r3_patch = self.scm.diff_for_revision(3) + r3_patch = self.scm.diff_for_revision(4) self.assertTrue(re.search('test3', r3_patch)) self.assertFalse(re.search('test4', r3_patch)) self.assertTrue(re.search('test2', r3_patch)) - self.assertTrue(re.search('test2', self.scm.diff_for_revision(2))) + self.assertTrue(re.search('test2', self.scm.diff_for_revision(3))) def _shared_test_svn_apply_git_patch(self): self._setup_webkittools_scripts_symlink(self.scm) @@ -308,7 +335,7 @@ HcmV?d00001 """ self.checkout.apply_patch(self._create_patch(git_binary_addition)) - added = read_from_path('fizzbuzz7.gif') + added = read_from_path('fizzbuzz7.gif', encoding=None) self.assertEqual(512, len(added)) self.assertTrue(added.startswith('GIF89a')) self.assertTrue('fizzbuzz7.gif' in self.scm.changed_files()) @@ -336,7 +363,7 @@ ptUl-ZG<%a~#LwkIWv&q!KSCH7tQ8cJDiw+|GV?MN)RjY50RTb-xvT&H """ self.checkout.apply_patch(self._create_patch(git_binary_modification)) - modified = read_from_path('fizzbuzz7.gif') + modified = read_from_path('fizzbuzz7.gif', encoding=None) self.assertEqual('foobar\n', modified) self.assertTrue('fizzbuzz7.gif' in self.scm.changed_files()) @@ -473,6 +500,12 @@ class SVNTest(SCMTest): def tearDown(self): SVNTestRepository.tear_down(self) + def test_detect_scm_system_relative_url(self): + scm = detect_scm_system(".") + # I wanted to assert that we got the right path, but there was some + # crazy magic with temp folder names that I couldn't figure out. + self.assertTrue(scm.checkout_root) + def test_create_patch_is_full_patch(self): test_dir_path = os.path.join(self.svn_checkout_path, "test_dir2") os.mkdir(test_dir_path) @@ -518,25 +551,35 @@ Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA== self._setup_webkittools_scripts_symlink(self.scm) patch_file = self._create_patch(patch_contents) self.checkout.apply_patch(patch_file) - actual_contents = read_from_path("test_file.swf") + actual_contents = read_from_path("test_file.swf", encoding=None) self.assertEqual(actual_contents, expected_contents) def test_apply_svn_patch(self): scm = detect_scm_system(self.svn_checkout_path) - patch = self._create_patch(run_command(['svn', 'diff', '-r4:3'])) + patch = self._create_patch(_svn_diff("-r5:4")) self._setup_webkittools_scripts_symlink(scm) Checkout(scm).apply_patch(patch) def test_apply_svn_patch_force(self): scm = detect_scm_system(self.svn_checkout_path) - patch = self._create_patch(run_command(['svn', 'diff', '-r2:4'])) + patch = self._create_patch(_svn_diff("-r3:5")) self._setup_webkittools_scripts_symlink(scm) self.assertRaises(ScriptError, Checkout(scm).apply_patch, patch, force=True) def test_commit_logs(self): # Commits have dates and usernames in them, so we can't just direct compare. self.assertTrue(re.search('fourth commit', self.scm.last_svn_commit_log())) - self.assertTrue(re.search('second commit', self.scm.svn_commit_log(2))) + self.assertTrue(re.search('second commit', self.scm.svn_commit_log(3))) + + def _shared_test_commit_with_message(self, username=None): + write_into_file_at_path('test_file', 'more test content') + commit_text = self.scm.commit_with_message("another test commit", username) + self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '6') + + self.scm.dryrun = True + write_into_file_at_path('test_file', 'still more test content') + commit_text = self.scm.commit_with_message("yet another test commit", username) + self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '0') def test_commit_text_parsing(self): self._shared_test_commit_with_message() @@ -595,7 +638,7 @@ class GitTest(SCMTest): def _setup_git_clone_of_svn_repository(self): self.git_checkout_path = tempfile.mkdtemp(suffix="git_test_checkout") # --quiet doesn't make git svn silent, so we use run_silent to redirect output - run_silent(['git', 'svn', '--quiet', 'clone', self.svn_repo_url, self.git_checkout_path]) + run_silent(['git', 'svn', 'clone', '-T', 'trunk', self.svn_repo_url, self.git_checkout_path]) def _tear_down_git_clone_of_svn_repository(self): run_command(['rm', '-rf', self.git_checkout_path]) @@ -657,8 +700,8 @@ class GitTest(SCMTest): test_file = os.path.join(self.git_checkout_path, 'test_file') write_into_file_at_path(test_file, 'foo') - diff_to_common_base = run_command(['git', 'diff', self.scm.svn_branch_name() + '..']) - diff_to_merge_base = run_command(['git', 'diff', self.scm.svn_merge_base()]) + diff_to_common_base = _git_diff(self.scm.svn_branch_name() + '..') + diff_to_merge_base = _git_diff(self.scm.svn_merge_base()) self.assertFalse(re.search(r'foo', diff_to_common_base)) self.assertTrue(re.search(r'foo', diff_to_merge_base)) @@ -711,18 +754,126 @@ class GitTest(SCMTest): # We carefullly pick a diff which does not have a directory addition # as currently svn-apply will error out when trying to remove directories # in Git: https://bugs.webkit.org/show_bug.cgi?id=34871 - patch = self._create_patch(run_command(['git', 'diff', 'HEAD..HEAD^'])) + patch = self._create_patch(_git_diff('HEAD..HEAD^')) self._setup_webkittools_scripts_symlink(scm) Checkout(scm).apply_patch(patch) def test_apply_git_patch_force(self): scm = detect_scm_system(self.git_checkout_path) - patch = self._create_patch(run_command(['git', 'diff', 'HEAD~2..HEAD'])) + patch = self._create_patch(_git_diff('HEAD~2..HEAD')) self._setup_webkittools_scripts_symlink(scm) self.assertRaises(ScriptError, Checkout(scm).apply_patch, patch, force=True) def test_commit_text_parsing(self): - self._shared_test_commit_with_message() + write_into_file_at_path('test_file', 'more test content') + self.scm.commit_locally_with_message("another test commit") + commit_text = self.scm.commit_with_message("another test commit") + self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '6') + + self.scm.dryrun = True + write_into_file_at_path('test_file', 'still more test content') + self.scm.commit_locally_with_message("yet another test commit") + commit_text = self.scm.commit_with_message("yet another test commit") + self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '0') + + def _one_local_commit_plus_working_copy_changes(self): + write_into_file_at_path('test_file_commit1', 'more test content') + run_command(['git', 'add', 'test_file_commit1']) + self.scm.commit_locally_with_message("another test commit") + + write_into_file_at_path('test_file_commit2', 'still more test content') + run_command(['git', 'add', 'test_file_commit2']) + + def test_commit_with_message_working_copy_only(self): + write_into_file_at_path('test_file_commit1', 'more test content') + run_command(['git', 'add', 'test_file_commit1']) + scm = detect_scm_system(self.git_checkout_path) + commit_text = scm.commit_with_message("yet another test commit") + + self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') + svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) + self.assertTrue(re.search(r'test_file_commit1', svn_log)) + + def test_commit_with_message_squashed(self): + self._one_local_commit_plus_working_copy_changes() + scm = detect_scm_system(self.git_checkout_path) + commit_text = scm.commit_with_message("yet another test commit", squash=True) + + self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') + svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) + self.assertTrue(re.search(r'test_file_commit2', svn_log)) + self.assertTrue(re.search(r'test_file_commit1', svn_log)) + + def _two_local_commits(self): + write_into_file_at_path('test_file_commit1', 'more test content') + run_command(['git', 'add', 'test_file_commit1']) + self.scm.commit_locally_with_message("another test commit") + + write_into_file_at_path('test_file_commit2', 'still more test content') + run_command(['git', 'add', 'test_file_commit2']) + self.scm.commit_locally_with_message("yet another test commit") + + def test_commit_with_message_git_commit(self): + self._two_local_commits() + + scm = detect_scm_system(self.git_checkout_path) + commit_text = scm.commit_with_message("another test commit", git_commit="HEAD^") + self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') + + svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) + self.assertTrue(re.search(r'test_file_commit1', svn_log)) + self.assertFalse(re.search(r'test_file_commit2', svn_log)) + + def test_commit_with_message_git_commit_range(self): + self._two_local_commits() + + scm = detect_scm_system(self.git_checkout_path) + commit_text = scm.commit_with_message("another test commit", git_commit="HEAD~2..HEAD") + self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') + + svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) + self.assertTrue(re.search(r'test_file_commit1', svn_log)) + self.assertTrue(re.search(r'test_file_commit2', svn_log)) + + def test_commit_with_message_multiple_local_commits(self): + self._two_local_commits() + scm = detect_scm_system(self.git_checkout_path) + self.assertRaises(ScriptError, scm.commit_with_message, ["another test commit"]) + + def test_commit_with_message_multiple_local_commits_and_working_copy(self): + self._two_local_commits() + write_into_file_at_path('test_file_commit1', 'working copy change') + scm = detect_scm_system(self.git_checkout_path) + self.assertRaises(ScriptError, scm.commit_with_message, ["another test commit"]) + + def test_commit_with_message_git_commit_and_working_copy(self): + self._two_local_commits() + write_into_file_at_path('test_file_commit1', 'working copy change') + scm = detect_scm_system(self.git_checkout_path) + self.assertRaises(ScriptError, scm.commit_with_message, ["another test commit", 'git_commit="HEAD^"']) + + def test_commit_with_message_multiple_local_commits_no_squash(self): + self._two_local_commits() + scm = detect_scm_system(self.git_checkout_path) + commit_text = scm.commit_with_message("yet another test commit", squash=False) + self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') + + svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) + self.assertTrue(re.search(r'test_file_commit2', svn_log)) + self.assertFalse(re.search(r'test_file_commit1', svn_log)) + + svn_log = run_command(['git', 'svn', 'log', '--limit=2', '--verbose']) + self.assertTrue(re.search(r'test_file_commit1', svn_log)) + + def test_commit_with_message_multiple_local_commits_squash(self): + self._two_local_commits() + scm = detect_scm_system(self.git_checkout_path) + commit_text = scm.commit_with_message("yet another test commit", squash=True) + self.assertEqual(scm.svn_revision_from_commit_text(commit_text), '6') + + svn_log = run_command(['git', 'svn', 'log', '--limit=1', '--verbose']) + self.assertTrue(re.search(r'test_file_commit2', svn_log)) + self.assertTrue(re.search(r'test_file_commit1', svn_log)) def test_reverse_diff(self): self._shared_test_reverse_diff() @@ -733,13 +884,66 @@ class GitTest(SCMTest): def test_svn_apply_git_patch(self): self._shared_test_svn_apply_git_patch() + def test_create_patch_local_plus_working_copy(self): + self._one_local_commit_plus_working_copy_changes() + scm = detect_scm_system(self.git_checkout_path) + self.assertRaises(ScriptError, scm.create_patch) + + def test_create_patch_multiple_local_commits(self): + self._two_local_commits() + scm = detect_scm_system(self.git_checkout_path) + self.assertRaises(ScriptError, scm.create_patch) + + def test_create_patch_squashed(self): + self._one_local_commit_plus_working_copy_changes() + scm = detect_scm_system(self.git_checkout_path) + patch = scm.create_patch(squash=True) + self.assertTrue(re.search(r'test_file_commit2', patch)) + self.assertTrue(re.search(r'test_file_commit1', patch)) + + def test_create_patch_not_squashed(self): + self._one_local_commit_plus_working_copy_changes() + scm = detect_scm_system(self.git_checkout_path) + patch = scm.create_patch(squash=False) + self.assertTrue(re.search(r'test_file_commit2', patch)) + self.assertFalse(re.search(r'test_file_commit1', patch)) + + def test_create_patch_git_commit(self): + self._two_local_commits() + scm = detect_scm_system(self.git_checkout_path) + patch = scm.create_patch(git_commit="HEAD^") + self.assertTrue(re.search(r'test_file_commit1', patch)) + self.assertFalse(re.search(r'test_file_commit2', patch)) + + def test_create_patch_git_commit_range(self): + self._two_local_commits() + scm = detect_scm_system(self.git_checkout_path) + patch = scm.create_patch(git_commit="HEAD~2..HEAD") + self.assertTrue(re.search(r'test_file_commit2', patch)) + self.assertTrue(re.search(r'test_file_commit1', patch)) + + def test_create_patch_multiple_local_commits_no_squash(self): + self._two_local_commits() + scm = detect_scm_system(self.git_checkout_path) + patch = scm.create_patch(squash=False) + # FIXME: It's weird that with squash=False, create_patch/changed_files ignores local commits, + # but commit_with_message commits them. + self.assertTrue(patch == "") + + def test_create_patch_multiple_local_commits_squash(self): + self._two_local_commits() + scm = detect_scm_system(self.git_checkout_path) + patch = scm.create_patch(squash=True) + self.assertTrue(re.search(r'test_file_commit2', patch)) + self.assertTrue(re.search(r'test_file_commit1', patch)) + def test_create_binary_patch(self): # Create a git binary patch and check the contents. scm = detect_scm_system(self.git_checkout_path) test_file_name = 'binary_file' test_file_path = os.path.join(self.git_checkout_path, test_file_name) file_contents = ''.join(map(chr, range(256))) - write_into_file_at_path(test_file_path, file_contents) + write_into_file_at_path(test_file_path, file_contents, encoding=None) run_command(['git', 'add', test_file_name]) patch = scm.create_patch() self.assertTrue(re.search(r'\nliteral 0\n', patch)) @@ -749,19 +953,68 @@ class GitTest(SCMTest): run_command(['git', 'rm', '-f', test_file_name]) self._setup_webkittools_scripts_symlink(scm) self.checkout.apply_patch(self._create_patch(patch)) - self.assertEqual(file_contents, read_from_path(test_file_path)) + self.assertEqual(file_contents, read_from_path(test_file_path, encoding=None)) # Check if we can create a patch from a local commit. - write_into_file_at_path(test_file_path, file_contents) + write_into_file_at_path(test_file_path, file_contents, encoding=None) run_command(['git', 'add', test_file_name]) run_command(['git', 'commit', '-m', 'binary diff']) - patch_from_local_commit = scm.create_patch_from_local_commit('HEAD') + patch_from_local_commit = scm.create_patch('HEAD') self.assertTrue(re.search(r'\nliteral 0\n', patch_from_local_commit)) self.assertTrue(re.search(r'\nliteral 256\n', patch_from_local_commit)) - patch_since_local_commit = scm.create_patch_since_local_commit('HEAD^1') - self.assertTrue(re.search(r'\nliteral 0\n', patch_since_local_commit)) - self.assertTrue(re.search(r'\nliteral 256\n', patch_since_local_commit)) - self.assertEqual(patch_from_local_commit, patch_since_local_commit) + + def test_changed_files_local_plus_working_copy(self): + self._one_local_commit_plus_working_copy_changes() + scm = detect_scm_system(self.git_checkout_path) + self.assertRaises(ScriptError, scm.changed_files) + + def test_changed_files_multiple_local_commits(self): + self._two_local_commits() + scm = detect_scm_system(self.git_checkout_path) + self.assertRaises(ScriptError, scm.changed_files) + + def test_changed_files_squashed(self): + self._one_local_commit_plus_working_copy_changes() + scm = detect_scm_system(self.git_checkout_path) + files = scm.changed_files(squash=True) + self.assertTrue('test_file_commit2' in files) + self.assertTrue('test_file_commit1' in files) + + def test_changed_files_not_squashed(self): + self._one_local_commit_plus_working_copy_changes() + scm = detect_scm_system(self.git_checkout_path) + files = scm.changed_files(squash=False) + self.assertTrue('test_file_commit2' in files) + self.assertFalse('test_file_commit1' in files) + + def test_changed_files_git_commit(self): + self._two_local_commits() + scm = detect_scm_system(self.git_checkout_path) + files = scm.changed_files(git_commit="HEAD^") + self.assertTrue('test_file_commit1' in files) + self.assertFalse('test_file_commit2' in files) + + def test_changed_files_git_commit_range(self): + self._two_local_commits() + scm = detect_scm_system(self.git_checkout_path) + files = scm.changed_files(git_commit="HEAD~2..HEAD") + self.assertTrue('test_file_commit1' in files) + self.assertTrue('test_file_commit2' in files) + + def test_changed_files_multiple_local_commits_no_squash(self): + self._two_local_commits() + scm = detect_scm_system(self.git_checkout_path) + files = scm.changed_files(squash=False) + # FIXME: It's weird that with squash=False, create_patch/changed_files ignores local commits, + # but commit_with_message commits them. + self.assertTrue(len(files) == 0) + + def test_changed_files_multiple_local_commits_squash(self): + self._two_local_commits() + scm = detect_scm_system(self.git_checkout_path) + files = scm.changed_files(squash=True) + self.assertTrue('test_file_commit2' in files) + self.assertTrue('test_file_commit1' in files) def test_changed_files(self): self._shared_test_changed_files() diff --git a/WebKitTools/Scripts/webkitpy/common/config/committers.py b/WebKitTools/Scripts/webkitpy/common/config/committers.py index a92dbd3..56887ab 100644 --- a/WebKitTools/Scripts/webkitpy/common/config/committers.py +++ b/WebKitTools/Scripts/webkitpy/common/config/committers.py @@ -86,7 +86,6 @@ committers_unable_to_review = [ Committer("Carol Szabo", "carol.szabo@nokia.com"), Committer("Chang Shu", "Chang.Shu@nokia.com"), Committer("Chris Fleizach", "cfleizach@apple.com"), - Committer("Chris Jerdonek", "cjerdonek@webkit.org", "cjerdonek"), Committer("Chris Marrin", "cmarrin@apple.com", "cmarrin"), Committer("Chris Petersen", "cpetersen@apple.com", "cpetersen"), Committer("Christian Dywan", ["christian@twotoasts.de", "christian@webkit.org"]), @@ -94,6 +93,7 @@ committers_unable_to_review = [ Committer("Csaba Osztrogonac", "ossy@webkit.org", "ossy"), Committer("David Smith", ["catfish.man@gmail.com", "dsmith@webkit.org"], "catfishman"), Committer("Dean Jackson", "dino@apple.com", "dino"), + Committer("Diego Gonzalez", ["diegohcg@webkit.org", "diego.gonzalez@openbossa.org"], "diegohcg"), Committer("Dirk Pranke", "dpranke@chromium.org"), Committer("Drew Wilson", "atwilson@chromium.org", "atwilson"), Committer("Dumitru Daniliuc", "dumi@chromium.org", "dumi"), @@ -101,6 +101,8 @@ committers_unable_to_review = [ Committer("Enrica Casucci", "enrica@apple.com"), Committer("Erik Arvidsson", "arv@chromium.org", "arv"), Committer("Eric Roman", "eroman@chromium.org", "eroman"), + Committer("Evan Martin", "evan@chromium.org", "evmar"), + Committer("Evan Stade", "estade@chromium.org", "estade"), Committer("Feng Qian", "feng@chromium.org"), Committer("Fumitoshi Ukai", "ukai@chromium.org", "ukai"), Committer("Gabor Loki", "loki@webkit.org", "loki04"), @@ -153,13 +155,13 @@ committers_unable_to_review = [ Committer("Ryosuke Niwa", "rniwa@webkit.org", "rniwa"), Committer("Scott Violet", "sky@chromium.org", "sky"), Committer("Stephen White", "senorblanco@chromium.org", "senorblanco"), - Committer("Steve Block", "steveblock@google.com"), Committer("Tony Chang", "tony@chromium.org", "tony^work"), Committer("Trey Matteson", "trey@usa.net", "trey"), Committer("Tristan O'Tierney", ["tristan@otierney.net", "tristan@apple.com"]), Committer("Victor Wang", "victorw@chromium.org"), Committer("Vitaly Repeshko", "vitalyr@chromium.org"), Committer("William Siegrist", "wsiegrist@apple.com", "wms"), + Committer("Xiaomei Ji", "xji@chromium.org", "xji"), Committer("Yael Aharon", "yael.aharon@nokia.com"), Committer("Yaar Schnitman", ["yaar@chromium.org", "yaar@google.com"]), Committer("Yong Li", ["yong.li@torchmobile.com", "yong.li.webkit@gmail.com"], "yong"), @@ -191,6 +193,7 @@ reviewers_list = [ Reviewer("Brady Eidson", "beidson@apple.com", "bradee-oh"), Reviewer("Cameron Zwarich", ["zwarich@apple.com", "cwzwarich@apple.com", "cwzwarich@webkit.org"]), Reviewer("Chris Blumenberg", "cblu@apple.com", "cblu"), + Reviewer("Chris Jerdonek", "cjerdonek@webkit.org", "cjerdonek"), Reviewer("Dan Bernstein", ["mitz@webkit.org", "mitz@apple.com"], "mitzpettel"), Reviewer("Daniel Bates", "dbates@webkit.org", "dydz"), Reviewer("Darin Adler", "darin@apple.com", "darin"), @@ -237,10 +240,11 @@ reviewers_list = [ Reviewer("Simon Fraser", "simon.fraser@apple.com", "smfr"), Reviewer("Simon Hausmann", ["hausmann@webkit.org", "hausmann@kde.org", "simon.hausmann@nokia.com"], "tronical"), Reviewer("Stephanie Lewis", "slewis@apple.com", "sundiamonde"), + Reviewer("Steve Block", "steveblock@google.com", "steveblock"), Reviewer("Steve Falkenburg", "sfalken@apple.com", "sfalken"), Reviewer("Tim Omernick", "timo@apple.com"), Reviewer("Timothy Hatcher", ["timothy@hatcher.name", "timothy@apple.com"], "xenon"), - Reviewer(u'Tor Arne Vestb\xf8', "vestbo@webkit.org", "torarne"), + Reviewer(u"Tor Arne Vestb\u00f8", "vestbo@webkit.org", "torarne"), Reviewer("Vicki Murley", "vicki@apple.com"), Reviewer("Xan Lopez", ["xan.lopez@gmail.com", "xan@gnome.org", "xan@webkit.org"], "xan"), Reviewer("Yury Semikhatsky", "yurys@chromium.org", "yurys"), diff --git a/WebKitTools/Scripts/webkitpy/common/net/bugzilla.py b/WebKitTools/Scripts/webkitpy/common/net/bugzilla.py index 6920d67..4311a00 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/bugzilla.py +++ b/WebKitTools/Scripts/webkitpy/common/net/bugzilla.py @@ -32,7 +32,7 @@ import os.path import re -import subprocess +import StringIO from datetime import datetime # used in timestamp() @@ -116,6 +116,10 @@ class Attachment(object): # depends on the current behavior. return self._attachment_dictionary.get("url") + def contents(self): + # FIXME: We shouldn't be grabbing at _bugzilla. + return self._bug._bugzilla.fetch_attachment_contents(self.id()) + def _validate_flag_value(self, flag): email = self._attachment_dictionary.get("%s_email" % flag) if not email: @@ -427,7 +431,16 @@ class Bugzilla(object): if flag['status'] == '+': attachment[result_key] = flag['setter'] + def _string_contents(self, soup): + # WebKit's bugzilla instance uses UTF-8. + # BeautifulSoup always returns Unicode strings, however + # the .string method returns a (unicode) NavigableString. + # NavigableString can confuse other parts of the code, so we + # convert from NavigableString to a real unicode() object using unicode(). + return unicode(soup.string) + def _parse_attachment_element(self, element, bug_id): + attachment = {} attachment['bug_id'] = bug_id attachment['is_obsolete'] = (element.has_key('isobsolete') and element['isobsolete'] == "1") @@ -435,9 +448,9 @@ class Bugzilla(object): attachment['id'] = int(element.find('attachid').string) # FIXME: No need to parse out the url here. attachment['url'] = self.attachment_url_for_id(attachment['id']) - attachment['name'] = unicode(element.find('desc').string) - attachment['attacher_email'] = str(element.find('attacher').string) - attachment['type'] = str(element.find('type').string) + attachment['name'] = self._string_contents(element.find('desc')) + attachment['attacher_email'] = self._string_contents(element.find('attacher')) + attachment['type'] = self._string_contents(element.find('type')) self._parse_attachment_flag( element, 'review', attachment, 'reviewer_email') self._parse_attachment_flag( @@ -448,10 +461,10 @@ class Bugzilla(object): soup = BeautifulSoup(page) bug = {} bug["id"] = int(soup.find("bug_id").string) - bug["title"] = unicode(soup.find("short_desc").string) - bug["reporter_email"] = str(soup.find("reporter").string) - bug["assigned_to_email"] = str(soup.find("assigned_to").string) - bug["cc_emails"] = [str(element.string) + bug["title"] = self._string_contents(soup.find("short_desc")) + bug["reporter_email"] = self._string_contents(soup.find("reporter")) + bug["assigned_to_email"] = self._string_contents(soup.find("assigned_to")) + bug["cc_emails"] = [self._string_contents(element) for element in soup.findAll('cc')] bug["attachments"] = [self._parse_attachment_element(element, bug["id"]) for element in soup.findAll('attachment')] return bug @@ -476,6 +489,12 @@ class Bugzilla(object): def fetch_bug(self, bug_id): return Bug(self.fetch_bug_dictionary(bug_id), self) + def fetch_attachment_contents(self, attachment_id): + attachment_url = self.attachment_url_for_id(attachment_id) + # We need to authenticate to download patches from security bugs. + self.authenticate() + return self.browser.open(attachment_url).read() + def _parse_bug_id_from_attachment_page(self, page): # The "Up" relation happens to point to the bug. up_link = BeautifulSoup(page).find('link', rel='Up') @@ -568,6 +587,7 @@ class Bugzilla(object): patch_name = "bug-%s-%s.patch" % (bug_id, timestamp()) else: patch_name ="%s.patch" % timestamp() + self.browser.add_file(patch_file_object, "text/plain", patch_name, @@ -575,7 +595,7 @@ class Bugzilla(object): def add_patch_to_bug(self, bug_id, - patch_file_object, + diff, description, comment_text=None, mark_for_review=False, @@ -594,6 +614,11 @@ class Bugzilla(object): self.browser.open("%sattachment.cgi?action=enter&bugid=%s" % ( self.bug_server_url, bug_id)) self.browser.select_form(name="entryform") + + # _fill_attachment_form expects a file-like object + # Patch files are already binary, so no encoding needed. + assert(isinstance(diff, str)) + patch_file_object = StringIO.StringIO(diff) self._fill_attachment_form(description, patch_file_object, mark_for_review=mark_for_review, @@ -628,7 +653,7 @@ class Bugzilla(object): bug_title, bug_description, component=None, - patch_file_object=None, + diff=None, patch_description=None, cc=None, blocked=None, @@ -653,11 +678,15 @@ class Bugzilla(object): if cc: self.browser["cc"] = cc if blocked: - self.browser["blocked"] = str(blocked) + self.browser["blocked"] = unicode(blocked) self.browser["short_desc"] = bug_title self.browser["comment"] = bug_description - if patch_file_object: + if diff: + # _fill_attachment_form expects a file-like object + # Patch files are already binary, so no encoding needed. + assert(isinstance(diff, str)) + patch_file_object = StringIO.StringIO(diff) self._fill_attachment_form( patch_description, patch_file_object, diff --git a/WebKitTools/Scripts/webkitpy/common/net/buildbot.py b/WebKitTools/Scripts/webkitpy/common/net/buildbot.py index 753e909..6c6ed43 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/buildbot.py +++ b/WebKitTools/Scripts/webkitpy/common/net/buildbot.py @@ -44,7 +44,7 @@ _log = get_logger(__file__) class Builder(object): def __init__(self, name, buildbot): - self._name = unicode(name) + self._name = name self._buildbot = buildbot self._builds_cache = {} self._revision_to_build_number = None @@ -223,12 +223,12 @@ class LayoutTestResults(object): parsed_results = {} tables = BeautifulSoup(page).findAll("table") for table in tables: - table_title = table.findPreviousSibling("p").string + table_title = unicode(table.findPreviousSibling("p").string) if table_title not in cls.expected_keys: # This Exception should only ever be hit if run-webkit-tests changes its results.html format. - raise Exception("Unhandled title: %s" % str(table_title)) + raise Exception("Unhandled title: %s" % table_title) # We might want to translate table titles into identifiers before storing. - parsed_results[table_title] = [row.find("a").string for row in table.findAll("tr")] + parsed_results[table_title] = [unicode(row.find("a").string) for row in table.findAll("tr")] return parsed_results @@ -319,7 +319,6 @@ class BuildBot(object): "Leopard", "Tiger", "Windows.*Build", - "Windows.*Debug.*Test", "GTK", "Qt", "Chromium", @@ -361,7 +360,7 @@ class BuildBot(object): # First cell is the name name_link = status_cells[0].find('a') - builder["name"] = name_link.string + builder["name"] = unicode(name_link.string) self._parse_last_build_cell(builder, status_cells[1]) self._parse_current_build_cell(builder, status_cells[2]) @@ -410,13 +409,13 @@ class BuildBot(object): return urllib2.urlopen(build_status_url) def _parse_twisted_file_row(self, file_row): - string_or_empty = lambda string: str(string) if string else "" + string_or_empty = lambda soup: unicode(soup.string) if soup.string else u"" file_cells = file_row.findAll('td') return { - "filename" : string_or_empty(file_cells[0].find("a").string), - "size" : string_or_empty(file_cells[1].string), - "type" : string_or_empty(file_cells[2].string), - "encoding" : string_or_empty(file_cells[3].string), + "filename": string_or_empty(file_cells[0].find("a")), + "size": string_or_empty(file_cells[1]), + "type": string_or_empty(file_cells[2]), + "encoding": string_or_empty(file_cells[3]), } def _parse_twisted_directory_listing(self, page): diff --git a/WebKitTools/Scripts/webkitpy/common/net/buildbot_unittest.py b/WebKitTools/Scripts/webkitpy/common/net/buildbot_unittest.py index f765f6e..5e04745 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/buildbot_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/net/buildbot_unittest.py @@ -51,7 +51,7 @@ class BuilderTest(unittest.TestCase): def setUp(self): self.buildbot = BuildBot() - self.builder = Builder("Test Builder", self.buildbot) + self.builder = Builder(u"Test Builder \u2661", self.buildbot) self._install_fetch_build(lambda build_number: ["test1", "test2"]) def test_find_failure_transition(self): @@ -271,7 +271,6 @@ class BuildBotTest(unittest.TestCase): "Leopard", "Tiger", "Windows.*Build", - "Windows.*Debug.*Test", "GTK", "Qt", "Chromium", @@ -286,7 +285,6 @@ class BuildBotTest(unittest.TestCase): {'name': u'SnowLeopard Intel Release (Tests)', }, {'name': u'Windows Release (Build)', }, {'name': u'Windows Debug (Build)', }, - {'name': u'Windows Debug (Tests)', }, {'name': u'GTK Linux 32-bit Release', }, {'name': u'GTK Linux 32-bit Debug', }, {'name': u'GTK Linux 64-bit Debug', }, diff --git a/WebKitTools/Scripts/webkitpy/common/net/rietveld.py b/WebKitTools/Scripts/webkitpy/common/net/rietveld.py index a9e5b1a..9cc97f2 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/rietveld.py +++ b/WebKitTools/Scripts/webkitpy/common/net/rietveld.py @@ -26,6 +26,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import logging import os import re import stat @@ -50,23 +51,19 @@ class Rietveld(object): def __init__(self, executive, dryrun=False): self.dryrun = dryrun self._executive = executive - self._upload_py = upload.__file__ - # Chop off the last character so we modify permissions on the py file instead of the pyc. - if os.path.splitext(self._upload_py)[1] == ".pyc": - self._upload_py = self._upload_py[:-1] - os.chmod(self._upload_py, os.stat(self._upload_py).st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) def url_for_issue(self, codereview_issue): if not codereview_issue: return None return "%s%s" % (config.codereview_server_url, codereview_issue) - def post(self, message=None, codereview_issue=None, cc=None): + def post(self, diff, message=None, codereview_issue=None, cc=None): if not message: raise ScriptError("Rietveld requires a message.") args = [ - self._upload_py, + # First argument is empty string to mimic sys.argv. + "", "--assume_yes", "--server=%s" % config.codereview_server_host, "--message=%s" % message, @@ -80,10 +77,15 @@ class Rietveld(object): log("Would have run %s" % args) return - output = self._executive.run_and_throw_if_fail(args) - match = re.search("Issue created\. URL: " + - config.codereview_server_regex + - "(?P<codereview_issue>\d+)", - output) - if match: - return int(match.group('codereview_issue')) + # Set logging level to avoid rietveld's logging spew. + old_level_name = logging.getLogger().getEffectiveLevel() + logging.getLogger().setLevel(logging.ERROR) + + # Use RealMain instead of calling upload from the commandline so that + # we can pass in the diff ourselves. Otherwise, upload will just use + # git diff for git checkouts, which doesn't respect --squash and --git-commit. + issue, patchset = upload.RealMain(args[1:], data=diff) + + # Reset logging level to the original value. + logging.getLogger().setLevel(old_level_name) + return issue diff --git a/WebKitTools/Scripts/webkitpy/common/net/statusserver.py b/WebKitTools/Scripts/webkitpy/common/net/statusserver.py index e8987a9..d9b52a2 100644 --- a/WebKitTools/Scripts/webkitpy/common/net/statusserver.py +++ b/WebKitTools/Scripts/webkitpy/common/net/statusserver.py @@ -52,9 +52,9 @@ class StatusServer: if not patch: return if patch.bug_id(): - self.browser["bug_id"] = str(patch.bug_id()) + self.browser["bug_id"] = unicode(patch.bug_id()) if patch.id(): - self.browser["patch_id"] = str(patch.id()) + self.browser["patch_id"] = unicode(patch.id()) def _add_results_file(self, results_file): if not results_file: @@ -79,7 +79,7 @@ class StatusServer: update_svn_revision_url = "%s/update-svn-revision" % self.url self.browser.open(update_svn_revision_url) self.browser.select_form(name="update_svn_revision") - self.browser["number"] = str(svn_revision_number) + self.browser["number"] = unicode(svn_revision_number) self.browser["broken_bot"] = broken_bot return self.browser.submit().read() diff --git a/WebKitTools/Scripts/webkitpy/common/prettypatch.py b/WebKitTools/Scripts/webkitpy/common/prettypatch.py index 8157f9c..4e92a53 100644 --- a/WebKitTools/Scripts/webkitpy/common/prettypatch.py +++ b/WebKitTools/Scripts/webkitpy/common/prettypatch.py @@ -31,11 +31,15 @@ import tempfile class PrettyPatch(object): + # FIXME: PrettyPatch should not require checkout_root. def __init__(self, executive, checkout_root): self._executive = executive self._checkout_root = checkout_root def pretty_diff_file(self, diff): + # Diffs can contain multiple text files of different encodings + # so we always deal with them as byte arrays, not unicode strings. + assert(isinstance(diff, str)) pretty_diff = self.pretty_diff(diff) diff_file = tempfile.NamedTemporaryFile(suffix=".html") diff_file.write(pretty_diff) @@ -43,6 +47,11 @@ class PrettyPatch(object): return diff_file def pretty_diff(self, diff): + # pretify.rb will hang forever if given no input. + # Avoid the hang by returning an empty string. + if not diff: + return "" + pretty_patch_path = os.path.join(self._checkout_root, "BugsSite", "PrettyPatch") prettify_path = os.path.join(pretty_patch_path, "prettify.rb") @@ -52,4 +61,6 @@ class PrettyPatch(object): pretty_patch_path, prettify_path, ] - return self._executive.run_command(args, input=diff) + # PrettyPatch does not modify the encoding of the diff output + # so we can't expect it to be utf-8. + return self._executive.run_command(args, input=diff, decode_output=False) diff --git a/WebKitTools/Scripts/webkitpy/common/prettypatch_unittest.py b/WebKitTools/Scripts/webkitpy/common/prettypatch_unittest.py new file mode 100644 index 0000000..1307856 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/common/prettypatch_unittest.py @@ -0,0 +1,70 @@ +# Copyright (C) 2010 Google 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: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +# OWNER 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. + +import os.path +import unittest + +from webkitpy.common.system.executive import Executive +from webkitpy.common.prettypatch import PrettyPatch + + +class PrettyPatchTest(unittest.TestCase): + + _diff_with_multiple_encodings = """ +Index: utf8_test +=================================================================== +--- utf8_test\t(revision 0) ++++ utf8_test\t(revision 0) +@@ -0,0 +1 @@ ++utf-8 test: \xc2\xa0 +Index: latin1_test +=================================================================== +--- latin1_test\t(revision 0) ++++ latin1_test\t(revision 0) +@@ -0,0 +1 @@ ++latin1 test: \xa0 +""" + + def _webkit_root(self): + webkitpy_common = os.path.dirname(__file__) + webkitpy = os.path.dirname(webkitpy_common) + scripts = os.path.dirname(webkitpy) + webkit_tools = os.path.dirname(scripts) + webkit_root = os.path.dirname(webkit_tools) + return webkit_root + + def test_pretty_diff_encodings(self): + pretty_patch = PrettyPatch(Executive(), self._webkit_root()) + pretty = pretty_patch.pretty_diff(self._diff_with_multiple_encodings) + self.assertTrue(pretty) # We got some output + self.assertTrue(isinstance(pretty, str)) # It's a byte array, not unicode + + def test_pretty_print_empty_string(self): + # Make sure that an empty diff does not hang the process. + pretty_patch = PrettyPatch(Executive(), self._webkit_root()) + self.assertEqual(pretty_patch.pretty_diff(""), "") diff --git a/WebKitTools/Scripts/webkitpy/common/system/autoinstall.py b/WebKitTools/Scripts/webkitpy/common/system/autoinstall.py index 32fd2cf..9adab29 100755 --- a/WebKitTools/Scripts/webkitpy/common/system/autoinstall.py +++ b/WebKitTools/Scripts/webkitpy/common/system/autoinstall.py @@ -30,6 +30,10 @@ """Support for automatically downloading Python packages from an URL.""" + +from __future__ import with_statement + +import codecs import logging import new import os @@ -114,7 +118,7 @@ class AutoInstaller(object): os.makedirs(path) - def _write_file(self, path, text): + def _write_file(self, path, text, encoding): """Create a file at the given path with given text. This method overwrites any existing file. @@ -122,11 +126,8 @@ class AutoInstaller(object): """ _log.debug("Creating file...") _log.debug(' "%s"' % path) - file = open(path, "w") - try: + with codecs.open(path, "w", encoding) as file: file.write(text) - finally: - file.close() def _set_up_target_dir(self, target_dir, append_to_search_path, make_package): @@ -154,7 +155,7 @@ class AutoInstaller(object): if not os.path.exists(init_path): text = ("# This file is required for Python to search this " "directory for modules.\n") - self._write_file(init_path, text) + self._write_file(init_path, text, "ascii") def _create_scratch_directory_inner(self, prefix): """Create a scratch directory without exception handling. @@ -216,11 +217,8 @@ class AutoInstaller(object): _log.debug("No URL file found.") return False - file = open(version_path, "r") - try: + with codecs.open(version_path, "r", "utf-8") as file: version = file.read() - finally: - file.close() return version.strip() == url.strip() @@ -231,7 +229,7 @@ class AutoInstaller(object): _log.debug(' URL: "%s"' % url) _log.debug(' To: "%s"' % version_path) - self._write_file(version_path, url) + self._write_file(version_path, url, "utf-8") def _extract_targz(self, path, scratch_dir): # tarfile.extractall() extracts to a path without the @@ -284,6 +282,8 @@ class AutoInstaller(object): # Otherwise, it is a file. try: + # We open this file w/o encoding, as we're reading/writing + # the raw byte-stream from the zip file. outfile = open(path, 'wb') except IOError, err: # Not all zip files seem to list the directories explicitly, @@ -384,9 +384,8 @@ class AutoInstaller(object): self._log_transfer("Starting download...", url, target_path) - stream = file(target_path, "wb") - bytes = self._download_to_stream(url, stream) - stream.close() + with open(target_path, "wb") as stream: + bytes = self._download_to_stream(url, stream) _log.debug("Downloaded %s bytes." % bytes) diff --git a/WebKitTools/Scripts/webkitpy/common/system/deprecated_logging.py b/WebKitTools/Scripts/webkitpy/common/system/deprecated_logging.py index ba1c5eb..9e6b529 100644 --- a/WebKitTools/Scripts/webkitpy/common/system/deprecated_logging.py +++ b/WebKitTools/Scripts/webkitpy/common/system/deprecated_logging.py @@ -30,24 +30,30 @@ # WebKit's Python module for logging # This module is now deprecated in favor of python's built-in logging.py. +import codecs import os import sys + def log(string): print >> sys.stderr, string + def error(string): log("ERROR: %s" % string) exit(1) + # Simple class to split output between multiple destinations class tee: def __init__(self, *files): self.files = files - def write(self, string): + # Callers should pass an already encoded string for writing. + def write(self, bytes): for file in self.files: - file.write(string) + file.write(bytes) + class OutputTee: def __init__(self): @@ -71,7 +77,7 @@ class OutputTee: (log_directory, log_name) = os.path.split(log_path) if log_directory and not os.path.exists(log_directory): os.makedirs(log_directory) - return open(log_path, 'a+') + return codecs.open(log_path, "a+", "utf-8") def _tee_outputs_to_files(self, files): if not self._original_stdout: diff --git a/WebKitTools/Scripts/webkitpy/common/system/deprecated_logging_unittest.py b/WebKitTools/Scripts/webkitpy/common/system/deprecated_logging_unittest.py index 2b71803..3778162 100644 --- a/WebKitTools/Scripts/webkitpy/common/system/deprecated_logging_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/system/deprecated_logging_unittest.py @@ -27,7 +27,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os -import subprocess import StringIO import tempfile import unittest diff --git a/WebKitTools/Scripts/webkitpy/common/system/executive.py b/WebKitTools/Scripts/webkitpy/common/system/executive.py index b6126e4..11eb051 100644 --- a/WebKitTools/Scripts/webkitpy/common/system/executive.py +++ b/WebKitTools/Scripts/webkitpy/common/system/executive.py @@ -87,10 +87,20 @@ def run_command(*args, **kwargs): class Executive(object): + def _should_close_fds(self): + # We need to pass close_fds=True to work around Python bug #2320 + # (otherwise we can hang when we kill DumpRenderTree when we are running + # multiple threads). See http://bugs.python.org/issue2320 . + # Note that close_fds isn't supported on Windows, but this bug only + # shows up on Mac and Linux. + return sys.platform not in ('win32', 'cygwin') + def _run_command_with_teed_output(self, args, teed_output): + args = map(unicode, args) # Popen will throw an exception if args are non-strings (like int()) child_process = subprocess.Popen(args, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + stderr=subprocess.STDOUT, + close_fds=self._should_close_fds()) # Use our own custom wait loop because Popen ignores a tee'd # stderr/stdout. @@ -98,15 +108,24 @@ class Executive(object): while True: output_line = child_process.stdout.readline() if output_line == "" and child_process.poll() != None: + # poll() is not threadsafe and can throw OSError due to: + # http://bugs.python.org/issue1731717 return child_process.poll() + # We assume that the child process wrote to us in utf-8, + # so no re-encoding is necessary before writing here. teed_output.write(output_line) - def run_and_throw_if_fail(self, args, quiet=False): + # FIXME: Remove this deprecated method and move callers to run_command. + # FIXME: This method is a hack to allow running command which both + # capture their output and print out to stdin. Useful for things + # like "build-webkit" where we want to display to the user that we're building + # but still have the output to stuff into a log file. + def run_and_throw_if_fail(self, args, quiet=False, decode_output=True): # Cache the child's output locally so it can be used for error reports. child_out_file = StringIO.StringIO() tee_stdout = sys.stdout if quiet: - dev_null = open(os.devnull, "w") + dev_null = open(os.devnull, "w") # FIXME: Does this need an encoding? tee_stdout = dev_null child_stdout = tee(child_out_file, tee_stdout) exit_code = self._run_command_with_teed_output(args, child_stdout) @@ -116,6 +135,10 @@ class Executive(object): child_output = child_out_file.getvalue() child_out_file.close() + # We assume the child process output utf-8 + if decode_output: + child_output = child_output.decode("utf-8") + if exit_code: raise ScriptError(script_args=args, exit_code=exit_code, @@ -140,17 +163,39 @@ class Executive(object): return 2 def kill_process(self, pid): + """Attempts to kill the given pid. + Will fail silently if pid does not exist or insufficient permisssions.""" if platform.system() == "Windows": # According to http://docs.python.org/library/os.html # os.kill isn't available on Windows. However, when I tried it # using Cygwin, it worked fine. We should investigate whether # we need this platform specific code here. - subprocess.call(('taskkill.exe', '/f', '/pid', str(pid)), - stdin=open(os.devnull, 'r'), - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + command = ["taskkill.exe", "/f", "/pid", str(pid)] + # taskkill will exit 128 if the process is not found. + self.run_command(command, error_handler=self.ignore_error) return - os.kill(pid, signal.SIGKILL) + try: + os.kill(pid, signal.SIGKILL) + except OSError, e: + # FIXME: We should make non-silent failure an option. + pass + + def kill_all(self, process_name): + """Attempts to kill processes matching process_name. + Will fail silently if no process are found.""" + if platform.system() == "Windows": + # We might want to automatically append .exe? + command = ["taskkill.exe", "/f", "/im", process_name] + # taskkill will exit 128 if the process is not found. + self.run_command(command, error_handler=self.ignore_error) + return + + # FIXME: This is inconsistent that kill_all uses TERM and kill_process + # uses KILL. Windows is always using /f (which seems like -KILL). + # We should pick one mode, or add support for switching between them. + # Note: Mac OS X 10.6 requires -SIGNALNAME before -u USER + command = ["killall", "-TERM", "-u", os.getenv("USER"), process_name] + self.run_command(command, error_handler=self.ignore_error) # Error handlers do not need to be static methods once all callers are # updated to use an Executive object. @@ -163,38 +208,51 @@ class Executive(object): def ignore_error(error): pass - # FIXME: This should be merged with run_and_throw_if_fail + def _compute_stdin(self, input): + """Returns (stdin, string_to_communicate)""" + # FIXME: We should be returning /dev/null for stdin + # or closing stdin after process creation to prevent + # child processes from getting input from the user. + if not input: + return (None, None) + if hasattr(input, "read"): # Check if the input is a file. + return (input, None) # Assume the file is in the right encoding. + + # Popen in Python 2.5 and before does not automatically encode unicode objects. + # http://bugs.python.org/issue5290 + # See https://bugs.webkit.org/show_bug.cgi?id=37528 + # for an example of a regresion caused by passing a unicode string directly. + # FIXME: We may need to encode differently on different platforms. + if isinstance(input, unicode): + input = input.encode("utf-8") + return (subprocess.PIPE, input) + # FIXME: run_and_throw_if_fail should be merged into this method. def run_command(self, args, cwd=None, input=None, error_handler=None, return_exit_code=False, - return_stderr=True): - if hasattr(input, 'read'): # Check if the input is a file. - stdin = input - string_to_communicate = None - else: - stdin = None - if input: - stdin = subprocess.PIPE - # string_to_communicate seems to need to be a str for proper - # communication with shell commands. - # See https://bugs.webkit.org/show_bug.cgi?id=37528 - # For an example of a regresion caused by passing a unicode string through. - string_to_communicate = str(input) - if return_stderr: - stderr = subprocess.STDOUT - else: - stderr = None + return_stderr=True, + decode_output=True): + """Popen wrapper for convenience and to work around python bugs.""" + args = map(unicode, args) # Popen will throw an exception if args are non-strings (like int()) + stdin, string_to_communicate = self._compute_stdin(input) + stderr = subprocess.STDOUT if return_stderr else None process = subprocess.Popen(args, stdin=stdin, stdout=subprocess.PIPE, stderr=stderr, - cwd=cwd) + cwd=cwd, + close_fds=self._should_close_fds()) output = process.communicate(string_to_communicate)[0] + # run_command automatically decodes to unicode() unless explicitly told not to. + if decode_output: + output = output.decode("utf-8") + # wait() is not threadsafe and can throw OSError due to: + # http://bugs.python.org/issue1731717 exit_code = process.wait() if return_exit_code: diff --git a/WebKitTools/Scripts/webkitpy/common/system/executive_unittest.py b/WebKitTools/Scripts/webkitpy/common/system/executive_unittest.py index ac380f8..ce91269 100644 --- a/WebKitTools/Scripts/webkitpy/common/system/executive_unittest.py +++ b/WebKitTools/Scripts/webkitpy/common/system/executive_unittest.py @@ -1,4 +1,4 @@ -# Copyright (C) 2009 Google Inc. All rights reserved. +# Copyright (C) 2010 Google Inc. All rights reserved. # Copyright (C) 2009 Daniel Bates (dbates@intudata.com). All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -27,10 +27,14 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import signal +import subprocess +import sys import unittest from webkitpy.common.system.executive import Executive, run_command + class ExecutiveTest(unittest.TestCase): def test_run_command_with_bad_command(self): @@ -38,5 +42,52 @@ class ExecutiveTest(unittest.TestCase): run_command(["foo_bar_command_blah"], error_handler=Executive.ignore_error, return_exit_code=True) self.failUnlessRaises(OSError, run_bad_command) -if __name__ == '__main__': - unittest.main() + def test_run_command_with_unicode(self): + """Validate that it is safe to pass unicode() objects + to Executive.run* methods, and they will return unicode() + objects by default unless decode_output=False""" + executive = Executive() + unicode_tor = u"WebKit \u2661 Tor Arne Vestb\u00F8!" + utf8_tor = unicode_tor.encode("utf-8") + + output = executive.run_command(["cat"], input=unicode_tor) + self.assertEquals(output, unicode_tor) + + output = executive.run_command(["echo", "-n", unicode_tor]) + self.assertEquals(output, unicode_tor) + + output = executive.run_command(["echo", "-n", unicode_tor], decode_output=False) + self.assertEquals(output, utf8_tor) + + # Make sure that str() input also works. + output = executive.run_command(["cat"], input=utf8_tor, decode_output=False) + self.assertEquals(output, utf8_tor) + + # FIXME: We should only have one run* method to test + output = executive.run_and_throw_if_fail(["echo", "-n", unicode_tor], quiet=True) + self.assertEquals(output, unicode_tor) + + output = executive.run_and_throw_if_fail(["echo", "-n", unicode_tor], quiet=True, decode_output=False) + self.assertEquals(output, utf8_tor) + + def test_kill_process(self): + executive = Executive() + # FIXME: This may need edits to work right on windows. + # We use "yes" because it loops forever. + process = subprocess.Popen(["yes"], stdout=subprocess.PIPE) + self.assertEqual(process.poll(), None) # Process is running + executive.kill_process(process.pid) + self.assertEqual(process.wait(), -signal.SIGKILL) + # Killing again should fail silently. + executive.kill_process(process.pid) + + def test_kill_all(self): + executive = Executive() + # FIXME: This may need edits to work right on windows. + # We use "yes" because it loops forever. + process = subprocess.Popen(["yes"], stdout=subprocess.PIPE) + self.assertEqual(process.poll(), None) # Process is running + executive.kill_all("yes") + self.assertEqual(process.wait(), -signal.SIGTERM) + # Killing again should fail silently. + executive.kill_all("yes") diff --git a/WebKitTools/Scripts/webkitpy/common/system/user.py b/WebKitTools/Scripts/webkitpy/common/system/user.py index 076f965..64995bb 100644 --- a/WebKitTools/Scripts/webkitpy/common/system/user.py +++ b/WebKitTools/Scripts/webkitpy/common/system/user.py @@ -62,11 +62,13 @@ class User(object): def edit(self, files): editor = os.environ.get("EDITOR") or "vi" args = shlex.split(editor) + # Note: Not thread safe: http://bugs.python.org/issue2320 subprocess.call(args + files) def page(self, message): pager = os.environ.get("PAGER") or "less" try: + # Note: Not thread safe: http://bugs.python.org/issue2320 child_process = subprocess.Popen([pager], stdin=subprocess.PIPE) child_process.communicate(input=message) except IOError, e: diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/driver_test.py b/WebKitTools/Scripts/webkitpy/layout_tests/driver_test.py index 231ed70..633dfe8 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/driver_test.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/driver_test.py @@ -42,7 +42,8 @@ import port def run_tests(port, options, tests): # |image_path| is a path to the image capture from the driver. image_path = 'image_result.png' - driver = port.start_driver(image_path, None) + driver = port.create_driver(image_path, None) + driver.start() for t in tests: uri = port.filename_to_uri(os.path.join(port.layout_tests_dir(), t)) print "uri: " + uri @@ -58,6 +59,7 @@ def run_tests(port, options, tests): print ''.join(err) print '"""' print + driver.stop() if __name__ == '__main__': diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py index e61d11f..6957fcd 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py @@ -35,6 +35,9 @@ the output. When there are no more URLs to process in the shared queue, the thread exits. """ +from __future__ import with_statement + +import codecs import copy import logging import os @@ -89,10 +92,10 @@ def process_output(port, test_info, test_types, test_args, configuration, test_info.filename)) filename = os.path.splitext(filename)[0] + "-stack.txt" port.maybe_make_directory(os.path.split(filename)[0]) - open(filename, "wb").write(error) # FIXME: This leaks a file handle. + with codecs.open(filename, "wb", "utf-8") as file: + file.write(error) elif error: - _log.debug("Previous test output extra lines after dump:\n%s" % - error) + _log.debug("Previous test output stderr lines:\n%s" % error) # Check the output and save the results. start_time = time.time() @@ -152,7 +155,8 @@ class SingleTestThread(threading.Thread): def run(self): test_info = self._test_info - driver = self._port.start_driver(self._image_path, self._shell_args) + driver = self._port.create_driver(self._image_path, self._shell_args) + driver.start() start = time.time() crash, timeout, actual_checksum, output, error = \ driver.run_test(test_info.uri.strip(), test_info.timeout, @@ -290,7 +294,7 @@ class TestShellThread(threading.Thread): # This is created in run_webkit_tests.py:_PrepareListsAndPrintOutput. tests_run_filename = os.path.join(self._options.results_directory, "tests_run.txt") - tests_run_file = open(tests_run_filename, "a") + tests_run_file = codecs.open(tests_run_filename, "a", "utf-8") while True: if self._canceled: @@ -443,9 +447,11 @@ class TestShellThread(threading.Thread): a separate DumpRenderTree in their own thread. """ + # poll() is not threadsafe and can throw OSError due to: + # http://bugs.python.org/issue1731717 if (not self._driver or self._driver.poll() is not None): - self._driver = self._port.start_driver( - self._image_path, self._shell_args) + self._driver = self._port.create_driver(self._image_path, self._shell_args) + self._driver.start() def _kill_dump_render_tree(self): """Kill the DumpRenderTree process if it's running.""" diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py index 6263540..0993cbd 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/json_results_generator.py @@ -27,6 +27,9 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +from __future__ import with_statement + +import codecs import logging import os import subprocess @@ -118,10 +121,11 @@ class JSONResultsGenerator(object): """Generates the JSON output file.""" json = self._get_json() if json: - results_file = open(self._results_file_path, "w") + results_file = codecs.open(self._results_file_path, "w", "utf-8") results_file.write(json) results_file.close() + # FIXME: Callers should use scm.py instead. def _get_svn_revision(self, in_directory): """Returns the svn revision for the given directory. @@ -129,6 +133,7 @@ class JSONResultsGenerator(object): in_directory: The directory where svn is to be run. """ if os.path.exists(os.path.join(in_directory, '.svn')): + # Note: Not thread safe: http://bugs.python.org/issue2320 output = subprocess.Popen(["svn", "info", "--xml"], cwd=in_directory, shell=(sys.platform == 'win32'), @@ -151,8 +156,8 @@ class JSONResultsGenerator(object): error = None if os.path.exists(self._results_file_path): - old_results_file = open(self._results_file_path, "r") - old_results = old_results_file.read() + with codecs.open(self._results_file_path, "r", "utf-8") as file: + old_results = file.read() elif self._builder_base_url: # Check if we have the archived JSON file on the buildbot server. results_file_url = (self._builder_base_url + diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream.py index 930b9e4..9c42d73 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream.py @@ -32,6 +32,9 @@ Package that implements a stream wrapper that has 'meters' as well as regular output. A 'meter' is a single line of text that can be erased and rewritten repeatedly, without producing multiple lines of output. It can be used to produce effects like progress bars. + +This package should only be called by the printing module in the layout_tests +package. """ import logging @@ -41,18 +44,38 @@ _log = logging.getLogger("webkitpy.layout_tests.metered_stream") class MeteredStream: """This class is a wrapper around a stream that allows you to implement - meters. - - It can be used like a stream, but calling update() will print - the string followed by only a carriage return (instead of a carriage - return and a line feed). This can be used to implement progress bars and - other sorts of meters. Note that anything written by update() will be - erased by a subsequent update(), write(), or flush().""" + meters (progress bars, etc.). + + It can be used directly as a stream, by calling write(), but provides + two other methods for output, update(), and progress(). + + In normal usage, update() will overwrite the output of the immediately + preceding update() (write() also will overwrite update()). So, calling + multiple update()s in a row can provide an updating status bar (note that + if an update string contains newlines, only the text following the last + newline will be overwritten/erased). + + If the MeteredStream is constructed in "verbose" mode (i.e., by passing + verbose=true), then update() no longer overwrite a previous update(), and + instead the call is equivalent to write(), although the text is + actually sent to the logger rather than to the stream passed + to the constructor. + + progress() is just like update(), except that if you are in verbose mode, + progress messages are not output at all (they are dropped). This is + used for things like progress bars which are presumed to be unwanted in + verbose mode. + + Note that the usual usage for this class is as a destination for + a logger that can also be written to directly (i.e., some messages go + through the logger, some don't). We thus have to dance around a + layering inversion in update() for things to work correctly. + """ def __init__(self, verbose, stream): """ Args: - verbose: whether update is a no-op + verbose: whether progress is a no-op and updates() aren't overwritten stream: output stream to write to """ self._dirty = False @@ -63,9 +86,11 @@ class MeteredStream: def write(self, txt): """Write to the stream, overwriting and resetting the meter.""" if self._dirty: - self.update("") + self._write(txt) self._dirty = False - self._stream.write(txt) + self._last_update = '' + else: + self._stream.write(txt) def flush(self): """Flush any buffered output.""" @@ -111,10 +136,13 @@ class MeteredStream: # Print the necessary number of backspaces to erase the previous # message. - self._stream.write("\b" * len(self._last_update)) - self._stream.write(str) + if len(self._last_update): + self._stream.write("\b" * len(self._last_update)) + if len(str): + self._stream.write(str) num_remaining = len(self._last_update) - len(str) if num_remaining > 0: self._stream.write(" " * num_remaining + "\b" * num_remaining) - self._last_update = str + last_newline = str.rfind("\n") + self._last_update = str[(last_newline + 1):] self._dirty = True diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream_unittest.py new file mode 100644 index 0000000..926f9b3 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/metered_stream_unittest.py @@ -0,0 +1,106 @@ +#!/usr/bin/python +# Copyright (C) 2010 Google 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: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +# OWNER 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. + +"""Unit tests for metered_stream.py.""" + +import os +import optparse +import pdb +import sys +import unittest +import logging + +from webkitpy.common.array_stream import ArrayStream +from webkitpy.layout_tests.layout_package import metered_stream + + +class TestMeteredStream(unittest.TestCase): + def test_regular(self): + a = ArrayStream() + m = metered_stream.MeteredStream(verbose=False, stream=a) + self.assertTrue(a.empty()) + + # basic test - note that the flush() is a no-op, but we include it + # for coverage. + m.write("foo") + m.flush() + self.assertEquals(a.get(), ['foo']) + + # now check that a second write() does not overwrite the first. + m.write("bar") + self.assertEquals(a.get(), ['foo', 'bar']) + + m.update("batter") + self.assertEquals(a.get(), ['foo', 'bar', 'batter']) + + # The next update() should overwrite the laste update() but not the + # other text. Note that the cursor is effectively positioned at the + # end of 'foo', even though we had to erase three more characters. + m.update("foo") + self.assertEquals(a.get(), ['foo', 'bar', 'batter', '\b\b\b\b\b\b', + 'foo', ' \b\b\b']) + + m.progress("progress") + self.assertEquals(a.get(), ['foo', 'bar', 'batter', '\b\b\b\b\b\b', + 'foo', ' \b\b\b', '\b\b\b', 'progress']) + + # now check that a write() does overwrite the progress bar + m.write("foo") + self.assertEquals(a.get(), ['foo', 'bar', 'batter', '\b\b\b\b\b\b', + 'foo', ' \b\b\b', '\b\b\b', 'progress', + '\b\b\b\b\b\b\b\b', + 'foo', ' \b\b\b\b\b']) + + # Now test that we only back up to the most recent newline. + + # Note also that we do not back up to erase the most recent write(), + # i.e., write()s do not get erased. + a.reset() + m.update("foo\nbar") + m.update("baz") + self.assertEquals(a.get(), ['foo\nbar', '\b\b\b', 'baz']) + + def test_verbose(self): + a = ArrayStream() + m = metered_stream.MeteredStream(verbose=True, stream=a) + self.assertTrue(a.empty()) + m.write("foo") + self.assertEquals(a.get(), ['foo']) + + m.update("bar") + # FIXME: figure out how to test that this went to the logger. Is this + # good enough? + self.assertEquals(a.get(), ['foo']) + + m.progress("dropped") + self.assertEquals(a.get(), ['foo']) + + +if __name__ == '__main__': + unittest.main() diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing.py new file mode 100644 index 0000000..91d49c6 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing.py @@ -0,0 +1,500 @@ +#!/usr/bin/env python +# Copyright (C) 2010 Google 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: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +# OWNER 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. + +"""Package that handles non-debug, non-file output for run-webkit-tests.""" + +import logging +import optparse +import os +import pdb + +from webkitpy.layout_tests.layout_package import metered_stream +from webkitpy.layout_tests.layout_package import test_expectations + +_log = logging.getLogger("webkitpy.layout_tests.printer") + +TestExpectationsFile = test_expectations.TestExpectationsFile + +NUM_SLOW_TESTS_TO_LOG = 10 + +PRINT_DEFAULT = ("misc,one-line-progress,one-line-summary,unexpected," + "unexpected-results,updates") +PRINT_EVERYTHING = ("actual,config,expected,misc,one-line-progress," + "one-line-summary,slowest,timing,unexpected," + "unexpected-results,updates") + +HELP_PRINTING = """ +Output for run-webkit-tests is controlled by a comma-separated list of +values passed to --print. Values either influence the overall output, or +the output at the beginning of the run, during the run, or at the end: + +Overall options: + nothing don't print anything. This overrides every other option + everything print everything (except the trace-* options and the + detailed-progress option, see below for the full list ) + misc print miscellaneous things like blank lines + +At the beginning of the run: + config print the test run configuration + expected print a summary of what is expected to happen + (# passes, # failures, etc.) + +During the run: + detailed-progress print one dot per test completed + one-line-progress print a one-line progress bar + unexpected print any unexpected results as they occur + updates print updates on which stage is executing + trace-everything print detailed info on every test's results + (baselines, expectation, time it took to run). If + this is specified it will override the '*-progress' + options, the 'trace-unexpected' option, and the + 'unexpected' option. + trace-unexpected like 'trace-everything', but only for tests with + unexpected results. If this option is specified, + it will override the 'unexpected' option. + +At the end of the run: + actual print a summary of the actual results + slowest print %(slowest)d slowest tests and the time they took + timing print timing statistics + unexpected-results print a list of the tests with unexpected results + one-line-summary print a one-line summary of the run + +Notes: + - 'detailed-progress' can only be used if running in a single thread + (using --child-processes=1) or a single queue of tests (using + --experimental-fully-parallel). If these conditions aren't true, + 'one-line-progress' will be used instead. + - If both 'detailed-progress' and 'one-line-progress' are specified (and + both are possible), 'detailed-progress' will be used. + - If 'nothing' is specified, it overrides all of the other options. + - Specifying --verbose is equivalent to --print everything plus it + changes the format of the log messages to add timestamps and other + information. If you specify --verbose and --print X, then X overrides + the --print everything implied by --verbose. + +--print 'everything' is equivalent to --print '%(everything)s'. + +The default is to --print '%(default)s'. +""" % {'slowest': NUM_SLOW_TESTS_TO_LOG, 'everything': PRINT_EVERYTHING, + 'default': PRINT_DEFAULT} + + +def print_options(): + return [ + # Note: we use print_options rather than just 'print' because print + # is a reserved word. + optparse.make_option("--print", dest="print_options", + help=("controls print output of test run. " + "Use --help-printing for more.")), + optparse.make_option("--help-printing", action="store_true", + help="show detailed help on controlling print output"), + optparse.make_option("-v", "--verbose", action="store_true", + default=False, help="include debug-level logging"), + + # FIXME: we should remove this; it's pretty much obsolete with the + # --print trace-everything option. + optparse.make_option("--sources", action="store_true", + help=("show expected result file path for each test " + "(implies --verbose)")), + ] + + +def configure_logging(options, meter): + """Configures the logging system.""" + log_fmt = '%(message)s' + log_datefmt = '%y%m%d %H:%M:%S' + log_level = logging.INFO + if options.verbose: + log_fmt = ('%(asctime)s %(filename)s:%(lineno)-4d %(levelname)s ' + '%(message)s') + log_level = logging.DEBUG + + logging.basicConfig(level=log_level, format=log_fmt, + datefmt=log_datefmt, stream=meter) + + +def parse_print_options(print_options, verbose, child_processes, + is_fully_parallel): + """Parse the options provided to --print and dedup and rank them. + + Returns + a set() of switches that govern how logging is done + + """ + if print_options: + switches = set(print_options.split(',')) + elif verbose: + switches = set(PRINT_EVERYTHING.split(',')) + else: + switches = set(PRINT_DEFAULT.split(',')) + + if 'nothing' in switches: + return set() + + if (child_processes != 1 and not is_fully_parallel and + 'detailed-progress' in switches): + _log.warn("Can only print 'detailed-progress' if running " + "with --child-processes=1 or " + "with --experimental-fully-parallel. " + "Using 'one-line-progress' instead.") + switches.discard('detailed-progress') + switches.add('one-line-progress') + + if 'everything' in switches: + switches.discard('everything') + switches.update(set(PRINT_EVERYTHING.split(','))) + + if 'detailed-progress' in switches: + switches.discard('one-line-progress') + + if 'trace-everything' in switches: + switches.discard('detailed-progress') + switches.discard('one-line-progress') + switches.discard('trace-unexpected') + switches.discard('unexpected') + + if 'trace-unexpected' in switches: + switches.discard('unexpected') + + return switches + + +class Printer(object): + """Class handling all non-debug-logging printing done by run-webkit-tests. + + Printing from run-webkit-tests falls into two buckets: general or + regular output that is read only by humans and can be changed at any + time, and output that is parsed by buildbots (and humans) and hence + must be changed more carefully and in coordination with the buildbot + parsing code (in chromium.org's buildbot/master.chromium/scripts/master/ + log_parser/webkit_test_command.py script). + + By default the buildbot-parsed code gets logged to stdout, and regular + output gets logged to stderr.""" + def __init__(self, port, options, regular_output, buildbot_output, + child_processes, is_fully_parallel): + """ + Args + port interface to port-specific routines + options OptionParser object with command line settings + regular_output stream to which output intended only for humans + should be written + buildbot_output stream to which output intended to be read by + the buildbots (and humans) should be written + child_processes number of parallel threads running (usually + controlled by --child-processes) + is_fully_parallel are the tests running in a single queue, or + in shards (usually controlled by + --experimental-fully-parallel) + + Note that the last two args are separate rather than bundled into + the options structure so that this object does not assume any flags + set in options that weren't returned from logging_options(), above. + The two are used to determine whether or not we can sensibly use + the 'detailed-progress' option, or can only use 'one-line-progress'. + """ + self._buildbot_stream = buildbot_output + self._options = options + self._port = port + self._stream = regular_output + + # These are used for --print detailed-progress to track status by + # directory. + self._current_dir = None + self._current_progress_str = "" + self._current_test_number = 0 + + self._meter = metered_stream.MeteredStream(options.verbose, + regular_output) + configure_logging(self._options, self._meter) + + self.switches = parse_print_options(options.print_options, + options.verbose, child_processes, is_fully_parallel) + + # These two routines just hide the implmentation of the switches. + def disabled(self, option): + return not option in self.switches + + def enabled(self, option): + return option in self.switches + + def help_printing(self): + self._write(HELP_PRINTING) + + def print_actual(self, msg): + if self.disabled('actual'): + return + self._buildbot_stream.write("%s\n" % msg) + + def print_config(self, msg): + self.write(msg, 'config') + + def print_expected(self, msg): + self.write(msg, 'expected') + + def print_timing(self, msg): + self.write(msg, 'timing') + + def print_one_line_summary(self, total, expected): + """Print a one-line summary of the test run to stdout. + + Args: + total: total number of tests run + expected: number of expected results + """ + if self.disabled('one-line-summary'): + return + + unexpected = total - expected + if unexpected == 0: + self._write("All %d tests ran as expected." % expected) + elif expected == 1: + self._write("1 test ran as expected, %d didn't:" % unexpected) + else: + self._write("%d tests ran as expected, %d didn't:" % + (expected, unexpected)) + self._write("") + + def print_test_result(self, result, expected, exp_str, got_str): + """Print the result of the test as determined by --print.""" + if (self.enabled('trace-everything') or + self.enabled('trace-unexpected') and not expected): + self._print_test_trace(result, exp_str, got_str) + elif (not expected and self.enabled('unexpected') and + self.disabled('detailed-progress')): + # Note: 'detailed-progress' handles unexpected results internally, + # so we skip it here. + self._print_unexpected_test_result(result) + + def _print_test_trace(self, result, exp_str, got_str): + """Print detailed results of a test (triggered by --print trace-*). + For each test, print: + - location of the expected baselines + - expected results + - actual result + - timing info + """ + filename = result.filename + test_name = self._port.relative_test_filename(filename) + self._write('trace: %s' % test_name) + self._write(' txt: %s' % + self._port.relative_test_filename( + self._port.expected_filename(filename, '.txt'))) + png_file = self._port.expected_filename(filename, '.png') + if os.path.exists(png_file): + self._write(' png: %s' % + self._port.relative_test_filename(filename)) + else: + self._write(' png: <none>') + self._write(' exp: %s' % exp_str) + self._write(' got: %s' % got_str) + self._write(' took: %-.3f' % result.test_run_time) + self._write('') + + def _print_unexpected_test_result(self, result): + """Prints one unexpected test result line.""" + desc = TestExpectationsFile.EXPECTATION_DESCRIPTIONS[result.type][0] + self.write(" %s -> unexpected %s" % + (self._port.relative_test_filename(result.filename), + desc), "unexpected") + + def print_progress(self, result_summary, retrying, test_list): + """Print progress through the tests as determined by --print.""" + if self.enabled('detailed-progress'): + self._print_detailed_progress(result_summary, test_list) + elif self.enabled('one-line-progress'): + self._print_one_line_progress(result_summary, retrying) + else: + return + + if result_summary.remaining == 0: + self._meter.update('') + + def _print_one_line_progress(self, result_summary, retrying): + """Displays the progress through the test run.""" + percent_complete = 100 * (result_summary.expected + + result_summary.unexpected) / result_summary.total + action = "Testing" + if retrying: + action = "Retrying" + self._meter.progress("%s (%d%%): %d ran as expected, %d didn't," + " %d left" % (action, percent_complete, result_summary.expected, + result_summary.unexpected, result_summary.remaining)) + + def _print_detailed_progress(self, result_summary, test_list): + """Display detailed progress output where we print the directory name + and one dot for each completed test. This is triggered by + "--log detailed-progress".""" + if self._current_test_number == len(test_list): + return + + next_test = test_list[self._current_test_number] + next_dir = os.path.dirname( + self._port.relative_test_filename(next_test)) + if self._current_progress_str == "": + self._current_progress_str = "%s: " % (next_dir) + self._current_dir = next_dir + + while next_test in result_summary.results: + if next_dir != self._current_dir: + self._meter.write("%s\n" % (self._current_progress_str)) + self._current_progress_str = "%s: ." % (next_dir) + self._current_dir = next_dir + else: + self._current_progress_str += "." + + if (next_test in result_summary.unexpected_results and + self.enabled('unexpected')): + self._meter.write("%s\n" % self._current_progress_str) + test_result = result_summary.results[next_test] + self._print_unexpected_test_result(test_result) + self._current_progress_str = "%s: " % self._current_dir + + self._current_test_number += 1 + if self._current_test_number == len(test_list): + break + + next_test = test_list[self._current_test_number] + next_dir = os.path.dirname( + self._port.relative_test_filename(next_test)) + + if result_summary.remaining: + remain_str = " (%d)" % (result_summary.remaining) + self._meter.progress("%s%s" % (self._current_progress_str, + remain_str)) + else: + self._meter.progress("%s" % (self._current_progress_str)) + + def print_unexpected_results(self, unexpected_results): + """Prints a list of the unexpected results to the buildbot stream.""" + if self.disabled('unexpected-results'): + return + + passes = {} + flaky = {} + regressions = {} + + for test, results in unexpected_results['tests'].iteritems(): + actual = results['actual'].split(" ") + expected = results['expected'].split(" ") + if actual == ['PASS']: + if 'CRASH' in expected: + _add_to_dict_of_lists(passes, + 'Expected to crash, but passed', + test) + elif 'TIMEOUT' in expected: + _add_to_dict_of_lists(passes, + 'Expected to timeout, but passed', + test) + else: + _add_to_dict_of_lists(passes, + 'Expected to fail, but passed', + test) + elif len(actual) > 1: + # We group flaky tests by the first actual result we got. + _add_to_dict_of_lists(flaky, actual[0], test) + else: + _add_to_dict_of_lists(regressions, results['actual'], test) + + if len(passes) or len(flaky) or len(regressions): + self._buildbot_stream.write("\n") + + if len(passes): + for key, tests in passes.iteritems(): + self._buildbot_stream.write("%s: (%d)\n" % (key, len(tests))) + tests.sort() + for test in tests: + self._buildbot_stream.write(" %s\n" % test) + self._buildbot_stream.write("\n") + self._buildbot_stream.write("\n") + + if len(flaky): + descriptions = TestExpectationsFile.EXPECTATION_DESCRIPTIONS + for key, tests in flaky.iteritems(): + result = TestExpectationsFile.EXPECTATIONS[key.lower()] + self._buildbot_stream.write("Unexpected flakiness: %s (%d)\n" + % (descriptions[result][1], len(tests))) + tests.sort() + + for test in tests: + result = unexpected_results['tests'][test] + actual = result['actual'].split(" ") + expected = result['expected'].split(" ") + result = TestExpectationsFile.EXPECTATIONS[key.lower()] + new_expectations_list = list(set(actual) | set(expected)) + self._buildbot_stream.write(" %s = %s\n" % + (test, " ".join(new_expectations_list))) + self._buildbot_stream.write("\n") + self._buildbot_stream.write("\n") + + if len(regressions): + descriptions = TestExpectationsFile.EXPECTATION_DESCRIPTIONS + for key, tests in regressions.iteritems(): + result = TestExpectationsFile.EXPECTATIONS[key.lower()] + self._buildbot_stream.write( + "Regressions: Unexpected %s : (%d)\n" % ( + descriptions[result][1], len(tests))) + tests.sort() + for test in tests: + self._buildbot_stream.write(" %s = %s\n" % (test, key)) + self._buildbot_stream.write("\n") + self._buildbot_stream.write("\n") + + if len(unexpected_results['tests']) and self._options.verbose: + self._buildbot_stream.write("%s\n" % ("-" * 78)) + + def print_update(self, msg): + if self.disabled('updates'): + return + self._meter.update(msg) + + def write(self, msg, option="misc"): + if self.disabled(option): + return + self._write(msg) + + def _write(self, msg): + # FIXME: we could probably get away with calling _log.info() all of + # the time, but there doesn't seem to be a good way to test the output + # from the logger :(. + if self._options.verbose: + _log.info(msg) + elif msg == "": + self._meter.write("\n") + else: + self._meter.write(msg) + +# +# Utility routines used by the Controller class +# + + +def _add_to_dict_of_lists(dict, key, value): + dict.setdefault(key, []).append(value) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py new file mode 100644 index 0000000..8e6aa8f --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/printing_unittest.py @@ -0,0 +1,463 @@ +#!/usr/bin/python +# Copyright (C) 2010 Google 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: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +# OWNER 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. + +"""Unit tests for printing.py.""" + +import os +import optparse +import pdb +import sys +import unittest +import logging + +from webkitpy.common import array_stream +from webkitpy.layout_tests import port +from webkitpy.layout_tests.layout_package import printing +from webkitpy.layout_tests.layout_package import dump_render_tree_thread +from webkitpy.layout_tests.layout_package import test_expectations +from webkitpy.layout_tests.layout_package import test_failures +from webkitpy.layout_tests import run_webkit_tests + + +def get_options(args): + print_options = printing.print_options() + option_parser = optparse.OptionParser(option_list=print_options) + return option_parser.parse_args(args) + + +def get_result(filename, result_type=test_expectations.PASS, run_time=0): + failures = [] + if result_type == test_expectations.TIMEOUT: + failures = [test_failures.FailureTimeout()] + elif result_type == test_expectations.CRASH: + failures = [test_failures.FailureCrash()] + return dump_render_tree_thread.TestResult(filename, failures, run_time, + total_time_for_all_diffs=0, + time_for_diffs=0) + + +def get_result_summary(port_obj, test_files, expectations_str): + expectations = test_expectations.TestExpectations( + port_obj, test_files, expectations_str, + port_obj.test_platform_name(), is_debug_mode=False, + is_lint_mode=False, tests_are_present=False) + + rs = run_webkit_tests.ResultSummary(expectations, test_files) + return rs, expectations + + +class TestUtilityFunctions(unittest.TestCase): + def test_configure_logging(self): + # FIXME: We need to figure out how to reset the basic logger. + # FIXME: If other testing classes call logging.basicConfig() then + # FIXME: these calls become no-ops and we can't control the + # FIXME: configuration to test things properly. + options, args = get_options([]) + stream = array_stream.ArrayStream() + printing.configure_logging(options, stream) + logging.info("this should be logged") + # self.assertFalse(stream.empty()) + + stream.reset() + logging.debug("this should not be logged") + # self.assertTrue(stream.empty()) + + stream.reset() + options, args = get_options(['--verbose']) + printing.configure_logging(options, stream) + logging.debug("this should be logged") + # self.assertFalse(stream.empty()) + + def test_print_options(self): + options, args = get_options([]) + self.assertTrue(options is not None) + + +class Testprinter(unittest.TestCase): + def get_printer(self, args=None, single_threaded=False, + is_fully_parallel=False): + printing_options = printing.print_options() + option_parser = optparse.OptionParser(option_list=printing_options) + options, args = option_parser.parse_args(args) + self._port = port.get('test', options) + nproc = 2 + if single_threaded: + nproc = 1 + + regular_output = array_stream.ArrayStream() + buildbot_output = array_stream.ArrayStream() + printer = printing.Printer(self._port, options, regular_output, + buildbot_output, single_threaded, + is_fully_parallel) + return printer, regular_output, buildbot_output + + def test_help_printer(self): + # Here and below we'll call the "regular" printer err and the + # buildbot printer out; this corresponds to how things run on the + # bots with stderr and stdout. + printer, err, out = self.get_printer() + + # This routine should print something to stdout. testing what it is + # is kind of pointless. + printer.help_printing() + self.assertFalse(err.empty()) + self.assertTrue(out.empty()) + + def do_switch_tests(self, method_name, switch, to_buildbot, + message='hello', exp_err=None, exp_bot=None): + def do_helper(method_name, switch, message, exp_err, exp_bot): + printer, err, bot = self.get_printer(['--print', switch]) + getattr(printer, method_name)(message) + self.assertEqual(err.get(), exp_err) + self.assertEqual(bot.get(), exp_bot) + + if to_buildbot: + if exp_err is None: + exp_err = [] + if exp_bot is None: + exp_bot = [message + "\n"] + else: + if exp_err is None: + exp_err = [message] + if exp_bot is None: + exp_bot = [] + do_helper(method_name, 'nothing', 'hello', [], []) + do_helper(method_name, switch, 'hello', exp_err, exp_bot) + do_helper(method_name, 'everything', 'hello', exp_err, exp_bot) + + def test_print_actual(self): + # Actual results need to be logged to the buildbot's stream. + self.do_switch_tests('print_actual', 'actual', to_buildbot=True) + + def test_print_actual_buildbot(self): + # FIXME: Test that the format of the actual results matches what the + # buildbot is expecting. + pass + + def test_print_config(self): + self.do_switch_tests('print_config', 'config', to_buildbot=False) + + def test_print_expected(self): + self.do_switch_tests('print_expected', 'expected', to_buildbot=False) + + def test_print_timing(self): + self.do_switch_tests('print_timing', 'timing', to_buildbot=False) + + def test_print_update(self): + # Note that there shouldn't be a carriage return here; updates() + # are meant to be overwritten. + self.do_switch_tests('print_update', 'updates', to_buildbot=False, + message='hello', exp_err=['hello']) + + def test_print_one_line_summary(self): + printer, err, out = self.get_printer(['--print', 'nothing']) + printer.print_one_line_summary(1, 1) + self.assertTrue(err.empty()) + + printer, err, out = self.get_printer(['--print', 'one-line-summary']) + printer.print_one_line_summary(1, 1) + self.assertEquals(err.get(), ["All 1 tests ran as expected.", "\n"]) + + printer, err, out = self.get_printer(['--print', 'everything']) + printer.print_one_line_summary(1, 1) + self.assertEquals(err.get(), ["All 1 tests ran as expected.", "\n"]) + + err.reset() + printer.print_one_line_summary(2, 1) + self.assertEquals(err.get(), + ["1 test ran as expected, 1 didn't:", "\n"]) + + err.reset() + printer.print_one_line_summary(3, 2) + self.assertEquals(err.get(), + ["2 tests ran as expected, 1 didn't:", "\n"]) + + def test_print_test_result(self): + result = get_result('foo.html') + printer, err, out = self.get_printer(['--print', 'nothing']) + printer.print_test_result(result, expected=False, exp_str='', + got_str='') + self.assertTrue(err.empty()) + + printer, err, out = self.get_printer(['--print', 'unexpected']) + printer.print_test_result(result, expected=True, exp_str='', + got_str='') + self.assertTrue(err.empty()) + printer.print_test_result(result, expected=False, exp_str='', + got_str='') + self.assertEquals(err.get(), + [' foo.html -> unexpected pass']) + + printer, err, out = self.get_printer(['--print', 'everything']) + printer.print_test_result(result, expected=True, exp_str='', + got_str='') + self.assertTrue(err.empty()) + + printer.print_test_result(result, expected=False, exp_str='', + got_str='') + self.assertEquals(err.get(), + [' foo.html -> unexpected pass']) + + printer, err, out = self.get_printer(['--print', 'nothing']) + printer.print_test_result(result, expected=False, exp_str='', + got_str='') + self.assertTrue(err.empty()) + + printer, err, out = self.get_printer(['--print', + 'trace-unexpected']) + printer.print_test_result(result, expected=True, exp_str='', + got_str='') + self.assertTrue(err.empty()) + + err.reset() + printer.print_test_result(result, expected=False, exp_str='', + got_str='') + self.assertFalse(err.empty()) + + printer, err, out = self.get_printer(['--print', 'trace-everything']) + printer.print_test_result(result, expected=True, exp_str='', + got_str='') + self.assertFalse(err.empty()) + + err.reset() + printer.print_test_result(result, expected=False, exp_str='', + got_str='') + + def test_print_progress(self): + test_files = ['foo.html', 'bar.html'] + expectations = '' + + # test that we print nothing + printer, err, out = self.get_printer(['--print', 'nothing']) + rs, exp = get_result_summary(self._port, test_files, expectations) + + printer.print_progress(rs, False, test_files) + self.assertTrue(out.empty()) + self.assertTrue(err.empty()) + + printer.print_progress(rs, True, test_files) + self.assertTrue(out.empty()) + self.assertTrue(err.empty()) + + # test regular functionality + printer, err, out = self.get_printer(['--print', + 'one-line-progress']) + printer.print_progress(rs, False, test_files) + self.assertTrue(out.empty()) + self.assertFalse(err.empty()) + + err.reset() + out.reset() + printer.print_progress(rs, True, test_files) + self.assertFalse(err.empty()) + self.assertTrue(out.empty()) + + def test_print_progress__detailed(self): + test_files = ['pass/pass.html', 'pass/timeout.html', 'fail/crash.html'] + expectations = 'pass/timeout.html = TIMEOUT' + + # first, test that it is disabled properly + # should still print one-line-progress + printer, err, out = self.get_printer( + ['--print', 'detailed-progress'], single_threaded=False) + rs, exp = get_result_summary(self._port, test_files, expectations) + printer.print_progress(rs, False, test_files) + self.assertFalse(err.empty()) + self.assertTrue(out.empty()) + + # now test the enabled paths + printer, err, out = self.get_printer( + ['--print', 'detailed-progress'], single_threaded=True) + rs, exp = get_result_summary(self._port, test_files, expectations) + printer.print_progress(rs, False, test_files) + self.assertFalse(err.empty()) + self.assertTrue(out.empty()) + + err.reset() + out.reset() + printer.print_progress(rs, True, test_files) + self.assertFalse(err.empty()) + self.assertTrue(out.empty()) + + rs.add(get_result('pass/pass.html', test_expectations.TIMEOUT), False) + rs.add(get_result('pass/timeout.html'), True) + rs.add(get_result('fail/crash.html', test_expectations.CRASH), True) + err.reset() + out.reset() + printer.print_progress(rs, False, test_files) + self.assertFalse(err.empty()) + self.assertTrue(out.empty()) + + # We only clear the meter when retrying w/ detailed-progress. + err.reset() + out.reset() + printer.print_progress(rs, True, test_files) + self.assertEqual(err.get(), []) + self.assertTrue(out.empty()) + + printer, err, out = self.get_printer( + ['--print', 'detailed-progress,unexpected'], single_threaded=True) + rs, exp = get_result_summary(self._port, test_files, expectations) + printer.print_progress(rs, False, test_files) + self.assertFalse(err.empty()) + self.assertTrue(out.empty()) + + err.reset() + out.reset() + printer.print_progress(rs, True, test_files) + self.assertFalse(err.empty()) + self.assertTrue(out.empty()) + + rs.add(get_result('pass/pass.html', test_expectations.TIMEOUT), False) + rs.add(get_result('pass/timeout.html'), True) + rs.add(get_result('fail/crash.html', test_expectations.CRASH), True) + err.reset() + out.reset() + printer.print_progress(rs, False, test_files) + self.assertFalse(err.empty()) + self.assertTrue(out.empty()) + + # We only clear the meter when retrying w/ detailed-progress. + err.reset() + out.reset() + printer.print_progress(rs, True, test_files) + self.assertEqual(err.get(), []) + self.assertTrue(out.empty()) + + def test_write(self): + printer, err, out = self.get_printer(['--print', 'nothing']) + printer.write("foo") + self.assertTrue(err.empty()) + + printer, err, out = self.get_printer(['--print', 'misc']) + printer.write("foo") + self.assertFalse(err.empty()) + err.reset() + printer.write("foo", "config") + self.assertTrue(err.empty()) + + printer, err, out = self.get_printer(['--print', 'everything']) + printer.write("foo") + self.assertFalse(err.empty()) + err.reset() + printer.write("foo", "config") + self.assertFalse(err.empty()) + + def test_print_unexpected_results(self): + # This routine is the only one that prints stuff that the bots + # care about. + def get_unexpected_results(expected, passing, flaky): + rs, exp = get_result_summary(self._port, test_files, expectations) + if expected: + rs.add(get_result('pass/pass.html', test_expectations.PASS), + expected) + rs.add(get_result('pass/timeout.html', + test_expectations.TIMEOUT), expected) + rs.add(get_result('fail/crash.html', test_expectations.CRASH), + expected) + elif passing: + rs.add(get_result('pass/pass.html'), expected) + rs.add(get_result('pass/timeout.html'), expected) + rs.add(get_result('fail/crash.html'), expected) + else: + rs.add(get_result('pass/pass.html', test_expectations.TIMEOUT), + expected) + rs.add(get_result('pass/timeout.html', + test_expectations.CRASH), expected) + rs.add(get_result('fail/crash.html', + test_expectations.TIMEOUT), + expected) + retry = rs + if flaky: + retry, exp = get_result_summary(self._port, test_files, + expectations) + retry.add(get_result('pass/pass.html'), True) + retry.add(get_result('pass/timeout.html'), True) + retry.add(get_result('fail/crash.html'), True) + unexpected_results = run_webkit_tests.summarize_unexpected_results( + self._port, exp, rs, retry) + return unexpected_results + + test_files = ['pass/pass.html', 'pass/timeout.html', 'fail/crash.html'] + expectations = '' + + printer, err, out = self.get_printer(['--print', 'nothing']) + ur = get_unexpected_results(expected=False, passing=False, flaky=False) + printer.print_unexpected_results(ur) + self.assertTrue(err.empty()) + self.assertTrue(out.empty()) + + printer, err, out = self.get_printer(['--print', + 'unexpected-results']) + + # test everything running as expected + ur = get_unexpected_results(expected=True, passing=False, flaky=False) + printer.print_unexpected_results(ur) + self.assertTrue(err.empty()) + self.assertTrue(out.empty()) + + # test failures + err.reset() + out.reset() + ur = get_unexpected_results(expected=False, passing=False, flaky=False) + printer.print_unexpected_results(ur) + self.assertTrue(err.empty()) + self.assertFalse(out.empty()) + + # test unexpected flaky results + err.reset() + out.reset() + ur = get_unexpected_results(expected=False, passing=True, flaky=False) + printer.print_unexpected_results(ur) + self.assertTrue(err.empty()) + self.assertFalse(out.empty()) + + # test unexpected passes + err.reset() + out.reset() + ur = get_unexpected_results(expected=False, passing=False, flaky=True) + printer.print_unexpected_results(ur) + self.assertTrue(err.empty()) + self.assertFalse(out.empty()) + + err.reset() + out.reset() + printer, err, out = self.get_printer(['--print', 'everything']) + ur = get_unexpected_results(expected=False, passing=False, flaky=False) + printer.print_unexpected_results(ur) + self.assertTrue(err.empty()) + self.assertFalse(out.empty()) + + def test_print_unexpected_results_buildbot(self): + # FIXME: Test that print_unexpected_results() produces the printer the + # buildbot is expecting. + pass + +if __name__ == '__main__': + unittest.main() diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_files.py b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_files.py index 6754fa6..8f79505 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_files.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/test_files.py @@ -62,6 +62,7 @@ def gather_test_files(port, paths): paths_to_walk = set() # if paths is empty, provide a pre-defined list. if paths: + _log.debug("Gathering tests from: %s relative to %s" % (paths, port.layout_tests_dir())) for path in paths: # If there's an * in the name, assume it's a glob pattern. path = os.path.join(port.layout_tests_dir(), path) @@ -71,6 +72,7 @@ def gather_test_files(port, paths): else: paths_to_walk.add(path) else: + _log.debug("Gathering tests from: %s" % port.layout_tests_dir()) paths_to_walk.add(port.layout_tests_dir()) # Now walk all the paths passed in on the command line and get filenames diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/apache_http_server.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/apache_http_server.py index 1dd5b93..46617f6 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/apache_http_server.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/apache_http_server.py @@ -29,6 +29,10 @@ """A class to start/stop the apache http server used by layout tests.""" + +from __future__ import with_statement + +import codecs import logging import optparse import os @@ -151,7 +155,9 @@ class LayoutTestApacheHttpd(http_server_base.HttpServerBase): """ httpd_config = self._port_obj._path_to_apache_config_file() httpd_config_copy = os.path.join(output_dir, "httpd.conf") - httpd_conf = open(httpd_config).read() + # httpd.conf is always utf-8 according to http://archive.apache.org/gnats/10125 + with codecs.open(httpd_config, "r", "utf-8") as httpd_config_file: + httpd_conf = httpd_config_file.read() if self._is_cygwin(): # This is a gross hack, but it lets us use the upstream .conf file # and our checked in cygwin. This tells the server the root @@ -164,9 +170,8 @@ class LayoutTestApacheHttpd(http_server_base.HttpServerBase): httpd_conf = httpd_conf.replace('ServerRoot "/usr"', 'ServerRoot "%s"' % self._get_cygwin_path(cygusr)) - f = open(httpd_config_copy, 'wb') - f.write(httpd_conf) - f.close() + with codecs.open(httpd_config_copy, "w", "utf-8") as file: + file.write(httpd_conf) if self._is_cygwin(): return self._get_cygwin_path(httpd_config_copy) @@ -186,6 +191,9 @@ class LayoutTestApacheHttpd(http_server_base.HttpServerBase): # Use shell=True because we join the arguments into a string for # the sake of Window/Cygwin and it needs quoting that breaks # shell=False. + # FIXME: We should not need to be joining shell arguments into strings. + # shell=True is a trail of tears. + # Note: Not thread safe: http://bugs.python.org/issue2320 self._httpd_proc = subprocess.Popen(self._start_cmd, stderr=subprocess.PIPE, shell=True) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py index fb6fddf..25946af 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py @@ -34,7 +34,7 @@ import cgi import difflib import errno import os -import subprocess +import shlex import sys import time @@ -49,7 +49,19 @@ from webkitpy.common.system.executive import Executive, ScriptError _log = logutils.get_logger(__file__) -# Python bug workaround. See Port.wdiff_text() for an explanation. +# Python's Popen has a bug that causes any pipes opened to a +# process that can't be executed to be leaked. Since this +# code is specifically designed to tolerate exec failures +# to gracefully handle cases where wdiff is not installed, +# the bug results in a massive file descriptor leak. As a +# workaround, if an exec failure is ever experienced for +# wdiff, assume it's not available. This will leak one +# file descriptor but that's better than leaking each time +# wdiff would be run. +# +# http://mail.python.org/pipermail/python-list/ +# 2008-August/505753.html +# http://bugs.python.org/issue3210 _wdiff_available = True _pretty_patch_available = True @@ -135,17 +147,13 @@ class Port(object): result = True try: - if subprocess.call(cmd) == 0: + if self._executive.run_command(cmd, return_exit_code=True) == 0: return False except OSError, e: if e.errno == errno.ENOENT or e.errno == errno.EACCES: _compare_available = False else: raise e - except ValueError: - # work around a race condition in Python 2.4's implementation - # of subprocess.Popen. See http://bugs.python.org/issue1199282 . - pass return result def diff_text(self, expected_text, actual_text, @@ -313,6 +321,8 @@ class Port(object): if not self._webkit_base_dir: abspath = os.path.abspath(__file__) self._webkit_base_dir = abspath[0:abspath.find('WebKitTools')] + _log.debug("Using WebKit root: %s" % self._webkit_base_dir) + return os.path.join(self._webkit_base_dir, *comps) # FIXME: Callers should eventually move to scm.script_path. @@ -413,9 +423,10 @@ class Port(object): results_filename in a users' browser.""" raise NotImplementedError('Port.show_html_results_file') - def start_driver(self, png_path, options): - """Starts a new test Driver and returns a handle to the object.""" - raise NotImplementedError('Port.start_driver') + def create_driver(self, png_path, options): + """Return a newly created base.Driver subclass for starting/stopping + the test driver.""" + raise NotImplementedError('Port.create_driver') def start_helper(self): """If a port needs to reconfigure graphics settings or do other @@ -519,66 +530,68 @@ class Port(object): expectations, determining search paths, and logging information.""" raise NotImplementedError('Port.version') + _WDIFF_DEL = '##WDIFF_DEL##' + _WDIFF_ADD = '##WDIFF_ADD##' + _WDIFF_END = '##WDIFF_END##' + + def _format_wdiff_output_as_html(self, wdiff): + wdiff = cgi.escape(wdiff) + wdiff = wdiff.replace(self._WDIFF_DEL, "<span class=del>") + wdiff = wdiff.replace(self._WDIFF_ADD, "<span class=add>") + wdiff = wdiff.replace(self._WDIFF_END, "</span>") + html = "<head><style>.del { background: #faa; } " + html += ".add { background: #afa; }</style></head>" + html += "<pre>%s</pre>" % wdiff + return html + + def _wdiff_command(self, actual_filename, expected_filename): + executable = self._path_to_wdiff() + return [executable, + "--start-delete=%s" % self._WDIFF_DEL, + "--end-delete=%s" % self._WDIFF_END, + "--start-insert=%s" % self._WDIFF_ADD, + "--end-insert=%s" % self._WDIFF_END, + actual_filename, + expected_filename] + + @staticmethod + def _handle_wdiff_error(script_error): + # Exit 1 means the files differed, any other exit code is an error. + if script_error.exit_code != 1: + raise script_error + + def _run_wdiff(self, actual_filename, expected_filename): + """Runs wdiff and may throw exceptions. + This is mostly a hook for unit testing.""" + # Diffs are treated as binary as they may include multiple files + # with conflicting encodings. Thus we do not decode the output. + command = self._wdiff_command(actual_filename, expected_filename) + wdiff = self._executive.run_command(command, decode_output=False, + error_handler=self._handle_wdiff_error) + return self._format_wdiff_output_as_html(wdiff) + def wdiff_text(self, actual_filename, expected_filename): """Returns a string of HTML indicating the word-level diff of the contents of the two filenames. Returns an empty string if word-level diffing isn't available.""" - executable = self._path_to_wdiff() - cmd = [executable, - '--start-delete=##WDIFF_DEL##', - '--end-delete=##WDIFF_END##', - '--start-insert=##WDIFF_ADD##', - '--end-insert=##WDIFF_END##', - actual_filename, - expected_filename] - # FIXME: Why not just check os.exists(executable) once? - global _wdiff_available - result = '' + global _wdiff_available # See explaination at top of file. + if not _wdiff_available: + return "" try: - # Python's Popen has a bug that causes any pipes opened to a - # process that can't be executed to be leaked. Since this - # code is specifically designed to tolerate exec failures - # to gracefully handle cases where wdiff is not installed, - # the bug results in a massive file descriptor leak. As a - # workaround, if an exec failure is ever experienced for - # wdiff, assume it's not available. This will leak one - # file descriptor but that's better than leaking each time - # wdiff would be run. - # - # http://mail.python.org/pipermail/python-list/ - # 2008-August/505753.html - # http://bugs.python.org/issue3210 - # - # It also has a threading bug, so we don't output wdiff if - # the Popen raises a ValueError. - # http://bugs.python.org/issue1236 - if _wdiff_available: - try: - # FIXME: Use Executive() here. - wdiff = subprocess.Popen(cmd, - stdout=subprocess.PIPE).communicate()[0] - except ValueError, e: - # Working around a race in Python 2.4's implementation - # of Popen(). - wdiff = '' - wdiff = cgi.escape(wdiff) - wdiff = wdiff.replace('##WDIFF_DEL##', '<span class=del>') - wdiff = wdiff.replace('##WDIFF_ADD##', '<span class=add>') - wdiff = wdiff.replace('##WDIFF_END##', '</span>') - result = '<head><style>.del { background: #faa; } ' - result += '.add { background: #afa; }</style></head>' - result += '<pre>' + wdiff + '</pre>' + # It's possible to raise a ScriptError we pass wdiff invalid paths. + return self._run_wdiff(actual_filename, expected_filename) except OSError, e: - if (e.errno == errno.ENOENT or e.errno == errno.EACCES or - e.errno == errno.ECHILD): + if e.errno in [errno.ENOENT, errno.EACCES, errno.ECHILD]: + # Silently ignore cases where wdiff is missing. _wdiff_available = False - else: - raise e - return result + return "" + raise + assert(False) # Should never be reached. _pretty_patch_error_html = "Failed to run PrettyPatch, see error console." def pretty_patch_text(self, diff_path): + # FIXME: Much of this function could move to prettypatch.rb global _pretty_patch_available if not _pretty_patch_available: return self._pretty_patch_error_html @@ -586,7 +599,9 @@ class Port(object): prettify_path = os.path.join(pretty_patch_path, "prettify.rb") command = ["ruby", "-I", pretty_patch_path, prettify_path, diff_path] try: - return self._executive.run_command(command) + # Diffs are treated as binary (we pass decode_output=False) as they + # may contain multiple files of conflicting encodings. + return self._executive.run_command(command, decode_output=False) except OSError, e: # If the system is missing ruby log the error and stop trying. _pretty_patch_available = False @@ -718,6 +733,24 @@ class Driver: specified in the __init__() call.""" raise NotImplementedError('Driver.run_test') + # FIXME: This is static so we can test it w/o creating a Base instance. + @classmethod + def _command_wrapper(cls, wrapper_option): + # Hook for injecting valgrind or other runtime instrumentation, + # used by e.g. tools/valgrind/valgrind_tests.py. + wrapper = [] + browser_wrapper = os.environ.get("BROWSER_WRAPPER", None) + if browser_wrapper: + # FIXME: There seems to be no reason to use BROWSER_WRAPPER over --wrapper. + # Remove this code any time after the date listed below. + _log.error("BROWSER_WRAPPER is deprecated, please use --wrapper instead.") + _log.error("BROWSER_WRAPPER will be removed any time after June 1st 2010 and your scripts will break.") + wrapper += [browser_wrapper] + + if wrapper_option: + wrapper += shlex.split(wrapper_option) + return wrapper + def poll(self): """Returns None if the Driver is still running. Returns the returncode if it has exited.""" diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py new file mode 100644 index 0000000..f821353 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/base_unittest.py @@ -0,0 +1,126 @@ +# Copyright (C) 2010 Google 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: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +# OWNER 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. + +import base +import unittest +import tempfile + +from webkitpy.common.system.executive import Executive, ScriptError +from webkitpy.thirdparty.mock import Mock + + +class PortTest(unittest.TestCase): + + def test_format_wdiff_output_as_html(self): + output = "OUTPUT %s %s %s" % (base.Port._WDIFF_DEL, base.Port._WDIFF_ADD, base.Port._WDIFF_END) + html = base.Port()._format_wdiff_output_as_html(output) + expected_html = "<head><style>.del { background: #faa; } .add { background: #afa; }</style></head><pre>OUTPUT <span class=del> <span class=add> </span></pre>" + self.assertEqual(html, expected_html) + + def test_wdiff_command(self): + port = base.Port() + port._path_to_wdiff = lambda: "/path/to/wdiff" + command = port._wdiff_command("/actual/path", "/expected/path") + expected_command = [ + "/path/to/wdiff", + "--start-delete=##WDIFF_DEL##", + "--end-delete=##WDIFF_END##", + "--start-insert=##WDIFF_ADD##", + "--end-insert=##WDIFF_END##", + "/actual/path", + "/expected/path", + ] + self.assertEqual(command, expected_command) + + def _file_with_contents(self, contents, encoding="utf-8"): + new_file = tempfile.NamedTemporaryFile() + new_file.write(contents.encode(encoding)) + new_file.flush() + return new_file + + def test_run_wdiff(self): + executive = Executive() + # This may fail on some systems. We could ask the port + # object for the wdiff path, but since we don't know what + # port object to use, this is sufficient for now. + try: + wdiff_path = executive.run_command(["which", "wdiff"]).rstrip() + except Exception, e: + wdiff_path = None + + port = base.Port() + port._path_to_wdiff = lambda: wdiff_path + + if wdiff_path: + # "with tempfile.NamedTemporaryFile() as actual" does not seem to work in Python 2.5 + actual = self._file_with_contents(u"foo") + expected = self._file_with_contents(u"bar") + wdiff = port._run_wdiff(actual.name, expected.name) + expected_wdiff = "<head><style>.del { background: #faa; } .add { background: #afa; }</style></head><pre><span class=del>foo</span><span class=add>bar</span></pre>" + self.assertEqual(wdiff, expected_wdiff) + # Running the full wdiff_text method should give the same result. + base._wdiff_available = True # In case it's somehow already disabled. + wdiff = port.wdiff_text(actual.name, expected.name) + self.assertEqual(wdiff, expected_wdiff) + # wdiff should still be available after running wdiff_text with a valid diff. + self.assertTrue(base._wdiff_available) + actual.close() + expected.close() + + # Bogus paths should raise a script error. + self.assertRaises(ScriptError, port._run_wdiff, "/does/not/exist", "/does/not/exist2") + self.assertRaises(ScriptError, port.wdiff_text, "/does/not/exist", "/does/not/exist2") + # wdiff will still be available after running wdiff_text with invalid paths. + self.assertTrue(base._wdiff_available) + base._wdiff_available = True + + # If wdiff does not exist _run_wdiff should throw an OSError. + port._path_to_wdiff = lambda: "/invalid/path/to/wdiff" + self.assertRaises(OSError, port._run_wdiff, "foo", "bar") + + # wdiff_text should not throw an error if wdiff does not exist. + self.assertEqual(port.wdiff_text("foo", "bar"), "") + # However wdiff should not be available after running wdiff_text if wdiff is missing. + self.assertFalse(base._wdiff_available) + base._wdiff_available = True + + +class DriverTest(unittest.TestCase): + + def _assert_wrapper(self, wrapper_string, expected_wrapper): + wrapper = base.Driver._command_wrapper(wrapper_string) + self.assertEqual(wrapper, expected_wrapper) + + def test_command_wrapper(self): + self._assert_wrapper(None, []) + self._assert_wrapper("valgrind", ["valgrind"]) + + # Validate that shlex works as expected. + command_with_spaces = "valgrind --smc-check=\"check with spaces!\" --foo" + expected_parse = ["valgrind", "--smc-check=check with spaces!", "--foo"] + self._assert_wrapper(command_with_spaces, expected_parse) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py index 8bae2a9..bcbd498 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py @@ -29,6 +29,9 @@ """Chromium implementations of the Port interface.""" +from __future__ import with_statement + +import codecs import logging import os import shutil @@ -41,6 +44,8 @@ import webbrowser import base import http_server +from webkitpy.common.system.executive import Executive + # FIXME: To use the DRT-based version of this file, we need to be able to # run the webkit code, which uses server_process, which requires UNIX-style # non-blocking I/O with selects(), which requires fcntl() which doesn't exist @@ -77,8 +82,8 @@ def check_file_exists(path_to_file, file_description, override_step=None, class ChromiumPort(base.Port): """Abstract base class for Chromium implementations of the Port class.""" - def __init__(self, port_name=None, options=None): - base.Port.__init__(self, port_name, options) + def __init__(self, port_name=None, options=None, **kwargs): + base.Port.__init__(self, port_name, options, **kwargs) self._chromium_base_dir = None def baseline_path(self): @@ -115,10 +120,8 @@ class ChromiumPort(base.Port): return result def check_sys_deps(self, needs_http): - dump_render_tree_binary_path = self._path_to_driver() - proc = subprocess.Popen([dump_render_tree_binary_path, - '--check-layout-test-sys-deps']) - if proc.wait(): + cmd = [self._path_to_driver(), '--check-layout-test-sys-deps'] + if self._executive.run_command(cmd, return_exit_code=True): _log.error('System dependencies check failed.') _log.error('To override, invoke with --nocheck-sys-deps') _log.error('') @@ -140,6 +143,7 @@ class ChromiumPort(base.Port): abspath = os.path.abspath(__file__) offset = abspath.find('third_party') if offset == -1: + # FIXME: This seems like the wrong error to throw. raise AssertionError('could not find Chromium base dir from ' + abspath) self._chromium_base_dir = abspath[0:offset] @@ -169,20 +173,23 @@ class ChromiumPort(base.Port): def show_results_html_file(self, results_filename): uri = self.filename_to_uri(results_filename) if self._options.use_drt: + # FIXME: This should use User.open_url webbrowser.open(uri, new=1) else: + # Note: Not thread safe: http://bugs.python.org/issue2320 subprocess.Popen([self._path_to_driver(), uri]) - def start_driver(self, image_path, options): + def create_driver(self, image_path, options): """Starts a new Driver and returns a handle to it.""" if self._options.use_drt: - return webkit.WebKitDriver(self, image_path, options) - return ChromiumDriver(self, image_path, options) + return webkit.WebKitDriver(self, image_path, options, executive=self._executive) + return ChromiumDriver(self, image_path, options, executive=self._executive) def start_helper(self): helper_path = self._path_to_helper() if helper_path: _log.debug("Starting layout helper %s" % helper_path) + # Note: Not thread safe: http://bugs.python.org/issue2320 self._helper = subprocess.Popen([helper_path], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None) is_ready = self._helper.stdout.readline() @@ -194,6 +201,8 @@ class ChromiumPort(base.Port): _log.debug("Stopping layout test helper") self._helper.stdin.write("x\n") self._helper.stdin.close() + # wait() is not threadsafe and can throw OSError due to: + # http://bugs.python.org/issue1731717 self._helper.wait() def test_base_platform_names(self): @@ -204,19 +213,20 @@ class ChromiumPort(base.Port): Basically this string should contain the equivalent of a test_expectations file. See test_expectations.py for more details.""" - expectations_file = self.path_to_test_expectations_file() - return file(expectations_file, "r").read() + expectations_path = self.path_to_test_expectations_file() + with codecs.open(expectations_path, "r", "utf-8") as file: + return file.read() def test_expectations_overrides(self): try: - overrides_file = self.path_from_chromium_base('webkit', 'tools', + overrides_path = self.path_from_chromium_base('webkit', 'tools', 'layout_tests', 'test_expectations.txt') except AssertionError: return None - if os.path.exists(overrides_file): - return file(overrides_file, "r").read() - else: + if not os.path.exists(overrides_path): return None + with codecs.open(overrides_path, "r", "utf-8") as file: + return file.read() def test_platform_names(self): return self.test_base_platform_names() + ('win-xp', @@ -265,29 +275,26 @@ class ChromiumPort(base.Port): class ChromiumDriver(base.Driver): - """Abstract interface for the DumpRenderTree interface.""" + """Abstract interface for test_shell.""" - def __init__(self, port, image_path, options): + def __init__(self, port, image_path, options, executive=Executive()): self._port = port - self._options = options self._configuration = port._options.configuration + # FIXME: _options is very confusing, because it's not an Options() element. + # FIXME: These don't need to be passed into the constructor, but could rather + # be passed into .start() + self._options = options self._image_path = image_path + self._executive = executive + def start(self): + # FIXME: Should be an error to call this method twice. cmd = [] - # Hook for injecting valgrind or other runtime instrumentation, - # used by e.g. tools/valgrind/valgrind_tests.py. - wrapper = os.environ.get("BROWSER_WRAPPER", None) - if wrapper != None: - cmd += [wrapper] - if self._port._options.wrapper: - # This split() isn't really what we want -- it incorrectly will - # split quoted strings within the wrapper argument -- but in - # practice it shouldn't come up and the --help output warns - # about it anyway. - cmd += self._options.wrapper.split() - cmd += [port._path_to_driver(), '--layout-tests'] - if options: - cmd += options + # FIXME: We should not be grabbing at self._port._options.wrapper directly. + cmd += self._command_wrapper(self._port._options.wrapper) + cmd += [self._port._path_to_driver(), '--layout-tests'] + if self._options: + cmd += self._options # We need to pass close_fds=True to work around Python bug #2320 # (otherwise we can hang when we kill DumpRenderTree when we are running @@ -299,12 +306,42 @@ class ChromiumDriver(base.Driver): stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=close_flag) + def poll(self): + # poll() is not threadsafe and can throw OSError due to: + # http://bugs.python.org/issue1731717 return self._proc.poll() def returncode(self): return self._proc.returncode + def _write_command_and_read_line(self, input=None): + """Returns a tuple: (line, did_crash)""" + try: + if input: + if isinstance(input, unicode): + # TestShell expects utf-8 + input = input.encode("utf-8") + self._proc.stdin.write(input) + # DumpRenderTree text output is always UTF-8. However some tests + # (e.g. webarchive) may spit out binary data instead of text so we + # don't bother to decode the output (for either DRT or test_shell). + line = self._proc.stdout.readline() + # We could assert() here that line correctly decodes as UTF-8. + return (line, False) + except IOError, e: + _log.error("IOError communicating w/ test_shell: " + str(e)) + return (None, True) + + def _test_shell_command(self, uri, timeoutms, checksum): + cmd = uri + if timeoutms: + cmd += ' ' + str(timeoutms) + if checksum: + cmd += ' ' + checksum + cmd += "\n" + return cmd + def run_test(self, uri, timeoutms, checksum): output = [] error = [] @@ -314,26 +351,16 @@ class ChromiumDriver(base.Driver): actual_checksum = None start_time = time.time() - cmd = uri - if timeoutms: - cmd += ' ' + str(timeoutms) - if checksum: - cmd += ' ' + checksum - cmd += "\n" - try: - self._proc.stdin.write(cmd) - line = self._proc.stdout.readline() - except IOError, e: - _log.error("IOError communicating w/ test_shell: " + str(e)) - crash = True + cmd = self._test_shell_command(uri, timeoutms, checksum) + (line, crash) = self._write_command_and_read_line(input=cmd) while not crash and line.rstrip() != "#EOF": # Make sure we haven't crashed. if line == '' and self.poll() is not None: # This is hex code 0xc000001d, which is used for abrupt # termination. This happens if we hit ctrl+c from the prompt - # and we happen to be waiting on the DumpRenderTree. + # and we happen to be waiting on test_shell. # sdoyon: Not sure for which OS and in what circumstances the # above code is valid. What works for me under Linux to detect # ctrl+c is for the subprocess returncode to be negative @@ -361,11 +388,7 @@ class ChromiumDriver(base.Driver): else: error.append(line) - try: - line = self._proc.stdout.readline() - except IOError, e: - _log.error("IOError while reading: " + str(e)) - crash = True + (line, crash) = self._write_command_and_read_line(input=None) return (crash, timeout, actual_checksum, ''.join(output), ''.join(error)) @@ -379,17 +402,18 @@ class ChromiumDriver(base.Driver): if sys.platform not in ('win32', 'cygwin'): # Closing stdin/stdout/stderr hangs sometimes on OS X, # (see __init__(), above), and anyway we don't want to hang - # the harness if DumpRenderTree is buggy, so we wait a couple - # seconds to give DumpRenderTree a chance to clean up, but then + # the harness if test_shell is buggy, so we wait a couple + # seconds to give test_shell a chance to clean up, but then # force-kill the process if necessary. KILL_TIMEOUT = 3.0 timeout = time.time() + KILL_TIMEOUT + # poll() is not threadsafe and can throw OSError due to: + # http://bugs.python.org/issue1731717 while self._proc.poll() is None and time.time() < timeout: time.sleep(0.1) + # poll() is not threadsafe and can throw OSError due to: + # http://bugs.python.org/issue1731717 if self._proc.poll() is None: _log.warning('stopping test driver timed out, ' 'killing it') - null = open(os.devnull, "w") - subprocess.Popen(["kill", "-9", - str(self._proc.pid)], stderr=null) - null.close() + self._executive.kill_process(self._proc.pid) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py index 9a595f2..a01bd14 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_linux.py @@ -31,9 +31,7 @@ import logging import os -import platform import signal -import subprocess import chromium @@ -122,15 +120,9 @@ class ChromiumLinuxPort(chromium.ChromiumPort): _log.error(' Please install using: "sudo apt-get install ' 'wdiff"') _log.error('') + # FIXME: The ChromiumMac port always returns True. return result - - def _kill_all_process(self, process_name): - null = open(os.devnull) - subprocess.call(['killall', '-TERM', '-u', os.getenv('USER'), - process_name], stderr=null) - null.close() - def _path_to_apache(self): if self._is_redhat_based(): return '/usr/sbin/httpd' @@ -187,8 +179,8 @@ class ChromiumLinuxPort(chromium.ChromiumPort): # TODO(mmoss) This isn't ideal, since it could conflict with # lighttpd processes not started by http_server.py, # but good enough for now. - self._kill_all_process('lighttpd') - self._kill_all_process('apache2') + self._executive.kill_all("lighttpd") + self._executive.kill_all("apache2") else: try: os.kill(server_pid, signal.SIGTERM) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py index d5e1757..4ead26f 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac.py @@ -33,10 +33,11 @@ import logging import os import platform import signal -import subprocess import chromium +from webkitpy.common.system.executive import Executive + _log = logging.getLogger("webkitpy.layout_tests.port.chromium_mac") @@ -66,6 +67,15 @@ class ChromiumMacPort(chromium.ChromiumPort): 'MacBuildInstructions') return result + def default_child_processes(self): + # FIXME: we need to run single-threaded for now. See + # https://bugs.webkit.org/show_bug.cgi?id=38553. Unfortunately this + # routine is called right before the logger is configured, so if we + # try to _log.warning(), it gets thrown away. + import sys + sys.stderr.write("Defaulting to one child - see https://bugs.webkit.org/show_bug.cgi?id=38553\n") + return 1 + def driver_name(self): """name for this port's equivalent of DumpRenderTree.""" if self._options.use_drt: @@ -99,33 +109,18 @@ class ChromiumMacPort(chromium.ChromiumPort): return self.path_from_chromium_base('xcodebuild', *comps) def _check_wdiff_install(self): - f = open(os.devnull, 'w') - rcode = 0 try: - rcode = subprocess.call(['wdiff'], stderr=f) + # We're ignoring the return and always returning True + self._executive.run_command([self._path_to_wdiff()], error_handler=Executive.ignore_error) except OSError: _log.warning('wdiff not found. Install using MacPorts or some ' 'other means') - pass - f.close() return True def _lighttpd_path(self, *comps): return self.path_from_chromium_base('third_party', 'lighttpd', 'mac', *comps) - def _kill_all_process(self, process_name): - """Kill any processes running under this name.""" - # On Mac OS X 10.6, killall has a new constraint: -SIGNALNAME or - # -SIGNALNUMBER must come first. Example problem: - # $ killall -u $USER -TERM lighttpd - # killall: illegal option -- T - # Use of the earlier -TERM placement is just fine on 10.5. - null = open(os.devnull) - subprocess.call(['killall', '-TERM', '-u', os.getenv('USER'), - process_name], stderr=null) - null.close() - def _path_to_apache(self): return '/usr/sbin/httpd' @@ -177,8 +172,8 @@ class ChromiumMacPort(chromium.ChromiumPort): # TODO(mmoss) This isn't ideal, since it could conflict with # lighttpd processes not started by http_server.py, # but good enough for now. - self._kill_all_process('lighttpd') - self._kill_all_process('httpd') + self._executive.kill_all('lighttpd') + self._executive.kill_all('httpd') else: try: os.kill(server_pid, signal.SIGTERM) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac_unittest.py new file mode 100644 index 0000000..d63faa0 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_mac_unittest.py @@ -0,0 +1,40 @@ +# Copyright (C) 2010 Google 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: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +# OWNER 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. + +import chromium_mac +import unittest + +from webkitpy.thirdparty.mock import Mock + + +class ChromiumMacPortTest(unittest.TestCase): + + def test_check_wdiff_install(self): + port = chromium_mac.ChromiumMacPort() + # Currently is always true, just logs if missing. + self.assertTrue(port._check_wdiff_install()) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py new file mode 100644 index 0000000..95d6378 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_unittest.py @@ -0,0 +1,80 @@ +# Copyright (C) 2010 Google 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: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +# OWNER 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. + +import chromium +import unittest +import StringIO + +from webkitpy.thirdparty.mock import Mock + + +class ChromiumDriverTest(unittest.TestCase): + + def setUp(self): + mock_port = Mock() + # FIXME: The Driver should not be grabbing at port._options! + mock_port._options = Mock() + mock_port._options.wrapper = "" + self.driver = chromium.ChromiumDriver(mock_port, image_path=None, options=None) + + def test_test_shell_command(self): + expected_command = "test.html 2 checksum\n" + self.assertEqual(self.driver._test_shell_command("test.html", 2, "checksum"), expected_command) + + def _assert_write_command_and_read_line(self, input=None, expected_line=None, expected_stdin=None, expected_crash=False): + if not expected_stdin: + if input: + expected_stdin = input + else: + # We reset stdin, so we should expect stdin.getValue = "" + expected_stdin = "" + self.driver._proc.stdin = StringIO.StringIO() + line, did_crash = self.driver._write_command_and_read_line(input) + self.assertEqual(self.driver._proc.stdin.getvalue(), expected_stdin) + self.assertEqual(line, expected_line) + self.assertEqual(did_crash, expected_crash) + + def test_write_command_and_read_line(self): + self.driver._proc = Mock() + # Set up to read 3 lines before we get an IOError + self.driver._proc.stdout = StringIO.StringIO("first\nsecond\nthird\n") + + unicode_input = u"I \u2661 Unicode" + utf8_input = unicode_input.encode("utf-8") + # Test unicode input conversion to utf-8 + self._assert_write_command_and_read_line(input=unicode_input, expected_stdin=utf8_input, expected_line="first\n") + # Test str() input. + self._assert_write_command_and_read_line(input="foo", expected_line="second\n") + # Test input=None + self._assert_write_command_and_read_line(expected_line="third\n") + # Test reading from a closed/empty stream. + # reading from a StringIO does not raise IOError like a real file would, so raise IOError manually. + def mock_readline(): + raise IOError + self.driver._proc.stdout.readline = mock_readline + self._assert_write_command_and_read_line(expected_crash=True) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py index 2e3de85..302af86 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium_win.py @@ -31,9 +31,6 @@ import logging import os -import platform -import signal -import subprocess import sys import chromium @@ -151,11 +148,7 @@ class ChromiumWinPort(chromium.ChromiumPort): Args: server_pid: The process ID of the running server. """ - subprocess.Popen(('taskkill.exe', '/f', '/im', 'LightTPD.exe'), - stdin=open(os.devnull, 'r'), - stdout=subprocess.PIPE, - stderr=subprocess.PIPE).wait() - subprocess.Popen(('taskkill.exe', '/f', '/im', 'httpd.exe'), - stdin=open(os.devnull, 'r'), - stdout=subprocess.PIPE, - stderr=subprocess.PIPE).wait() + # FIXME: Why are we ignoring server_pid and calling + # _kill_all instead of Executive.kill_process(pid)? + self._executive.kill_all("LightTPD.exe") + self._executive.kill_all("httpd.exe") diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py index 7a6717f..2cbb1b9 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py @@ -116,7 +116,7 @@ class DryRunPort(object): def stop_websocket_server(self): pass - def start_driver(self, image_path, options): + def create_driver(self, image_path, options): return DryrunDriver(self, image_path, options) @@ -153,6 +153,9 @@ class DryrunDriver(base.Driver): hash = None return (False, False, hash, text_output, None) + def start(self): + pass + def stop(self): pass diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/gtk.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/gtk.py index de5e28a..59dc1d9 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/gtk.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/gtk.py @@ -30,7 +30,6 @@ import logging import os -import subprocess from webkitpy.layout_tests.port.webkit import WebKitPort @@ -61,12 +60,6 @@ class GtkPort(WebKitPort): return os.path.join(self.layout_tests_dir(), 'http', 'conf', 'apache2-debian-httpd.conf') - def _kill_all_process(self, process_name): - null = open(os.devnull) - subprocess.call(['killall', '-TERM', '-u', os.getenv('USER'), - process_name], stderr=null) - null.close() - def _shut_down_http_server(self, server_pid): """Shut down the httpd web server. Blocks until it's fully shut down. @@ -79,7 +72,7 @@ class GtkPort(WebKitPort): # FIXME: This isn't ideal, since it could conflict with # lighttpd processes not started by http_server.py, # but good enough for now. - self._kill_all_process('apache2') + self._executive.kill_all('apache2') else: try: os.kill(server_pid, signal.SIGTERM) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/http_server.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/http_server.py index cc434bc..fbe47e3 100755 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/http_server.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/http_server.py @@ -29,7 +29,9 @@ """A class to help start/stop the lighttpd server used by layout tests.""" +from __future__ import with_statement +import codecs import logging import optparse import os @@ -114,11 +116,14 @@ class Lighttpd(http_server_base.HttpServerBase): self.remove_log_files(self._output_dir, "error.log-") # Write out the config - f = file(base_conf_file, 'rb') - base_conf = f.read() - f.close() - - f = file(out_conf_file, 'wb') + with codecs.open(base_conf_file, "r", "utf-8") as file: + base_conf = file.read() + + # FIXME: This should be re-worked so that this block can + # use with open() instead of a manual file.close() call. + # lighttpd.conf files seem to be UTF-8 without BOM: + # http://redmine.lighttpd.net/issues/992 + f = codecs.open(out_conf_file, "w", "utf-8") f.write(base_conf) # Write out our cgi handlers. Run perl through env so that it @@ -205,9 +210,11 @@ class Lighttpd(http_server_base.HttpServerBase): if sys.platform == 'win32' and self._register_cygwin: setup_mount = self._port_obj.path_from_chromium_base('third_party', 'cygwin', 'setup_mount.bat') + # FIXME: Should use Executive.run_command subprocess.Popen(setup_mount).wait() _log.debug('Starting http server') + # FIXME: Should use Executive.run_command self._process = subprocess.Popen(start_cmd, env=env) # Wait for server to start. @@ -234,5 +241,7 @@ class Lighttpd(http_server_base.HttpServerBase): self._port_obj._shut_down_http_server(httpd_pid) if self._process: + # wait() is not threadsafe and can throw OSError due to: + # http://bugs.python.org/issue1731717 self._process.wait() self._process = None diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py index cf4daa8..350b088 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/mac.py @@ -30,15 +30,8 @@ import logging import os -import pdb import platform -import re -import shutil import signal -import subprocess -import sys -import time -import webbrowser import webkitpy.common.system.ospath as ospath import webkitpy.layout_tests.port.server_process as server_process @@ -131,18 +124,6 @@ class MacPort(WebKitPort): "platform/win", ] - # FIXME: This doesn't have anything to do with WebKit. - def _kill_all_process(self, process_name): - # On Mac OS X 10.6, killall has a new constraint: -SIGNALNAME or - # -SIGNALNUMBER must come first. Example problem: - # $ killall -u $USER -TERM lighttpd - # killall: illegal option -- T - # Use of the earlier -TERM placement is just fine on 10.5. - null = open(os.devnull) - subprocess.call(['killall', '-TERM', '-u', os.getenv('USER'), - process_name], stderr=null) - null.close() - def _path_to_apache_config_file(self): return os.path.join(self.layout_tests_dir(), 'http', 'conf', 'apache2-httpd.conf') @@ -160,7 +141,7 @@ class MacPort(WebKitPort): # FIXME: This isn't ideal, since it could conflict with # lighttpd processes not started by http_server.py, # but good enough for now. - self._kill_all_process('httpd') + self._executive.kill_all('httpd') else: try: os.kill(server_pid, signal.SIGTERM) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py index e47a4a4..ae7d40c 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/mac_unittest.py @@ -40,7 +40,7 @@ class MacTest(unittest.TestCase): relative_paths = [path[len(port.path_from_webkit_base()):] for path in skipped_paths] self.assertEqual(relative_paths, ['LayoutTests/platform/mac-leopard/Skipped', 'LayoutTests/platform/mac/Skipped']) - example_skipped_file = """ + example_skipped_file = u""" # <rdar://problem/5647952> fast/events/mouseout-on-window.html needs mac DRT to issue mouse out events fast/events/mouseout-on-window.html diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/qt.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/qt.py index 67cdefe..9032a24 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/qt.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/qt.py @@ -30,7 +30,6 @@ import logging import os -import subprocess import signal from webkitpy.layout_tests.port.webkit import WebKitPort @@ -62,12 +61,6 @@ class QtPort(WebKitPort): return os.path.join(self.layout_tests_dir(), 'http', 'conf', 'apache2-debian-httpd.conf') - def _kill_all_process(self, process_name): - null = open(os.devnull) - subprocess.call(['killall', '-TERM', '-u', os.getenv('USER'), - process_name], stderr=null) - null.close() - def _shut_down_http_server(self, server_pid): """Shut down the httpd web server. Blocks until it's fully shut down. @@ -80,7 +73,7 @@ class QtPort(WebKitPort): # FIXME: This isn't ideal, since it could conflict with # lighttpd processes not started by http_server.py, # but good enough for now. - self._kill_all_process('apache2') + self._executive.kill_all('apache2') else: try: os.kill(server_pid, signal.SIGTERM) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/server_process.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/server_process.py index f1c6d73..62ca693 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/server_process.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/server_process.py @@ -38,6 +38,8 @@ import subprocess import sys import time +from webkitpy.common.system.executive import Executive + _log = logging.getLogger("webkitpy.layout_tests.port.server_process") @@ -48,12 +50,13 @@ class ServerProcess: indefinitely. The class also handles transparently restarting processes as necessary to keep issuing commands.""" - def __init__(self, port_obj, name, cmd, env=None): + def __init__(self, port_obj, name, cmd, env=None, executive=Executive()): self._port = port_obj self._name = name self._cmd = cmd self._env = env self._reset() + self._executive = executive def _reset(self): self._proc = None @@ -66,6 +69,7 @@ class ServerProcess: if self._proc: raise ValueError("%s already running" % self._name) self._reset() + # close_fds is a workaround for http://bugs.python.org/issue2320 close_fds = sys.platform not in ('win32', 'cygwin') self._proc = subprocess.Popen(self._cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, @@ -100,6 +104,8 @@ class ServerProcess: """Check to see if the underlying process is running; returns None if it still is (wrapper around subprocess.poll).""" if self._proc: + # poll() is not threadsafe and can throw OSError due to: + # http://bugs.python.org/issue1731717 return self._proc.poll() return None @@ -164,6 +170,8 @@ class ServerProcess: select_fds = (out_fd, err_fd) deadline = time.time() + timeout while not self.timed_out and not self.crashed: + # poll() is not threadsafe and can throw OSError due to: + # http://bugs.python.org/issue1731717 if self._proc.poll() != None: self.crashed = True self.handle_interrupt() @@ -210,14 +218,15 @@ class ServerProcess: # force-kill the process if necessary. KILL_TIMEOUT = 3.0 timeout = time.time() + KILL_TIMEOUT + # poll() is not threadsafe and can throw OSError due to: + # http://bugs.python.org/issue1731717 while self._proc.poll() is None and time.time() < timeout: time.sleep(0.1) + # poll() is not threadsafe and can throw OSError due to: + # http://bugs.python.org/issue1731717 if self._proc.poll() is None: _log.warning('stopping %s timed out, killing it' % self._name) - null = open(os.devnull, "w") - subprocess.Popen(["kill", "-9", - str(self._proc.pid)], stderr=null) - null.close() + self._executive.kill_process(self._proc.pid) _log.warning('killed') self._reset() diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py index edef485..5d563cd 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py @@ -66,6 +66,13 @@ class TestPort(base.Port): expected_filename, actual_filename): return '' + def relative_test_filename(self, filename): + return filename + + def expected_filename(self, filename, suffix): + (basename, ext) = os.path.splitext(filename) + return basename + '.' + suffix + def name(self): return self._name @@ -81,7 +88,7 @@ class TestPort(base.Port): def show_results_html_file(self, filename): pass - def start_driver(self, image_path, options): + def create_driver(self, image_path, options): return TestDriver(image_path, options, self) def start_http_server(self): @@ -132,5 +139,8 @@ class TestDriver(base.Driver): def run_test(self, uri, timeoutms, image_hash): return (False, False, image_hash, '', None) + def start(self): + pass + def stop(self): pass diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py index f2f5237..ada83ce 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py @@ -29,18 +29,21 @@ """WebKit implementations of the Port interface.""" + +from __future__ import with_statement + +import codecs import logging import os -import pdb -import platform import re import shutil import signal -import subprocess import sys import time import webbrowser +from webkitpy.common.system.executive import Executive + import webkitpy.common.system.ospath as ospath import webkitpy.layout_tests.port.base as base import webkitpy.layout_tests.port.server_process as server_process @@ -51,8 +54,8 @@ _log = logging.getLogger("webkitpy.layout_tests.port.webkit") class WebKitPort(base.Port): """WebKit implementation of the Port class.""" - def __init__(self, port_name=None, options=None): - base.Port.__init__(self, port_name, options) + def __init__(self, port_name=None, options=None, **kwargs): + base.Port.__init__(self, port_name, options, **kwargs) self._cached_build_root = None self._cached_apache_path = None @@ -134,9 +137,11 @@ class WebKitPort(base.Port): sp = server_process.ServerProcess(self, 'ImageDiff', command) actual_length = os.stat(actual_filename).st_size - actual_file = open(actual_filename).read() + with open(actual_filename) as file: + actual_file = file.read() expected_length = os.stat(expected_filename).st_size - expected_file = open(expected_filename).read() + with open(expected_filename) as file: + expected_file = file.read() sp.write('Content-Length: %d\n%sContent-Length: %d\n%s' % (actual_length, actual_file, expected_length, expected_file)) @@ -165,7 +170,8 @@ class WebKitPort(base.Port): if m.group(2) == 'passed': result = False elif output and diff_filename: - open(diff_filename, 'w').write(output) # FIXME: This leaks a file handle. + with open(diff_filename, 'w') as file: + file.write(output) elif sp.timed_out: _log.error("ImageDiff timed out on %s" % expected_filename) elif sp.crashed: @@ -187,8 +193,8 @@ class WebKitPort(base.Port): # FIXME: We should open results in the version of WebKit we built. webbrowser.open(uri, new=1) - def start_driver(self, image_path, options): - return WebKitDriver(self, image_path, options) + def create_driver(self, image_path, options): + return WebKitDriver(self, image_path, options, executive=self._executive) def test_base_platform_names(self): # At the moment we don't use test platform names, but we have @@ -252,17 +258,16 @@ class WebKitPort(base.Port): if not os.path.exists(filename): _log.warn("Failed to open Skipped file: %s" % filename) continue - skipped_file = file(filename) - tests_to_skip.extend(self._tests_from_skipped_file(skipped_file)) - skipped_file.close() + with codecs.open(filename, "r", "utf-8") as skipped_file: + tests_to_skip.extend(self._tests_from_skipped_file(skipped_file)) return tests_to_skip def test_expectations(self): # The WebKit mac port uses a combination of a test_expectations file # and 'Skipped' files. - expectations_file = self.path_to_test_expectations_file() - expectations = file(expectations_file, "r").read() - return expectations + self._skips() + expectations_path = self.path_to_test_expectations_file() + with codecs.open(expectations_path, "r", "utf-8") as file: + return file.read() + self._skips() def _skips(self): # Each Skipped file contains a list of files @@ -341,28 +346,17 @@ class WebKitPort(base.Port): class WebKitDriver(base.Driver): """WebKit implementation of the DumpRenderTree interface.""" - def __init__(self, port, image_path, driver_options): + def __init__(self, port, image_path, driver_options, executive=Executive()): self._port = port - self._driver_options = driver_options + # FIXME: driver_options is never used. self._image_path = image_path + def start(self): command = [] - # Hook for injecting valgrind or other runtime instrumentation, - # used by e.g. tools/valgrind/valgrind_tests.py. - wrapper = os.environ.get("BROWSER_WRAPPER", None) - if wrapper != None: - command += [wrapper] - if self._port._options.wrapper: - # This split() isn't really what we want -- it incorrectly will - # split quoted strings within the wrapper argument -- but in - # practice it shouldn't come up and the --help output warns - # about it anyway. - # FIXME: Use a real shell parser. - command += self._options.wrapper.split() - - command += [port._path_to_driver(), '-'] - - if image_path: + # FIXME: We should not be grabbing at self._port._options.wrapper directly. + command += self._command_wrapper(self._port._options.wrapper) + command += [self._port._path_to_driver(), '-'] + if self._image_path: command.append('--pixel-tests') environment = os.environ environment['DYLD_FRAMEWORK_PATH'] = self._port._build_path() @@ -391,13 +385,12 @@ class WebKitDriver(base.Driver): command += "'" + image_hash command += "\n" - # pdb.set_trace() self._server_process.write(command) have_seen_content_type = False actual_image_hash = None - output = '' - image = '' + output = str() # Use a byte array for output, even though it should be UTF-8. + image = str() timeout = int(timeoutms) / 1000.0 deadline = time.time() + timeout @@ -409,6 +402,10 @@ class WebKitDriver(base.Driver): have_seen_content_type): have_seen_content_type = True else: + # Note: Text output from DumpRenderTree is always UTF-8. + # However, some tests (e.g. webarchives) spit out binary + # data instead of text. So to make things simple, we + # always treat the output as binary. output += line line = self._server_process.read_line(timeout) timeout = deadline - time.time() @@ -433,14 +430,24 @@ class WebKitDriver(base.Driver): line = self._server_process.read_line(timeout) if self._image_path and len(self._image_path): - image_file = file(self._image_path, "wb") - image_file.write(image) - image_file.close() + with open(self._image_path, "wb") as image_file: + image_file.write(image) + + error_lines = self._server_process.error.splitlines() + # FIXME: This is a hack. It is unclear why sometimes + # we do not get any error lines from the server_process + # probably we are not flushing stderr. + if error_lines and error_lines[-1] == "#EOF": + error_lines.pop() # Remove the expected "#EOF" + error = "\n".join(error_lines) + # FIXME: This seems like the wrong section of code to be doing + # this reset in. + self._server_process.error = "" return (self._server_process.crashed, self._server_process.timed_out, actual_image_hash, output, - self._server_process.error) + error) def stop(self): if self._server_process: diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py index a9ba160..ad557bd 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/websocket_server.py @@ -30,6 +30,9 @@ """A class to help start/stop the PyWebSocket server used by layout tests.""" +from __future__ import with_statement + +import codecs import logging import optparse import os @@ -151,7 +154,7 @@ class PyWebSocket(http_server.Lighttpd): error_log = os.path.join(self._output_dir, log_file_name + "-err.txt") output_log = os.path.join(self._output_dir, log_file_name + "-out.txt") - self._wsout = open(output_log, "w") + self._wsout = codecs.open(output_log, "w", "utf-8") python_interp = sys.executable pywebsocket_base = os.path.join( @@ -204,6 +207,7 @@ class PyWebSocket(http_server.Lighttpd): self._server_name, self._port)) _log.debug('cmdline: %s' % ' '.join(start_cmd)) # FIXME: We should direct this call through Executive for testing. + # Note: Not thread safe: http://bugs.python.org/issue2320 self._process = subprocess.Popen(start_cmd, stdin=open(os.devnull, 'r'), stdout=self._wsout, @@ -216,7 +220,7 @@ class PyWebSocket(http_server.Lighttpd): url = 'http' url = url + '://127.0.0.1:%d/' % self._port if not url_is_alive(url): - fp = open(output_log) + fp = codecs.open(output_log, "utf-8") try: for line in fp: _log.error(line) @@ -231,9 +235,8 @@ class PyWebSocket(http_server.Lighttpd): raise PyWebSocketNotStarted( 'Failed to start %s server.' % self._server_name) if self._pidfile: - f = open(self._pidfile, 'w') - f.write("%d" % self._process.pid) - f.close() + with codecs.open(self._pidfile, "w", "ascii") as file: + file.write("%d" % self._process.pid) def stop(self, force=False): if not force and not self.is_running(): @@ -243,9 +246,8 @@ class PyWebSocket(http_server.Lighttpd): if self._process: pid = self._process.pid elif self._pidfile: - f = open(self._pidfile) - pid = int(f.read().strip()) - f.close() + with codecs.open(self._pidfile, "r", "ascii") as file: + pid = int(file.read().strip()) if not pid: raise PyWebSocketNotFound( @@ -256,6 +258,8 @@ class PyWebSocket(http_server.Lighttpd): Executive().kill_process(pid) if self._process: + # wait() is not threadsafe and can throw OSError due to: + # http://bugs.python.org/issue1731717 self._process.wait() self._process = None diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/port/win.py b/WebKitTools/Scripts/webkitpy/layout_tests/port/win.py index 2bf692b..3b7a817 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/port/win.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/port/win.py @@ -30,7 +30,6 @@ import logging import os -import subprocess from webkitpy.layout_tests.port.webkit import WebKitPort @@ -69,7 +68,4 @@ class WinPort(WebKitPort): """ # Looks like we ignore server_pid. # Copy/pasted from chromium-win. - subprocess.Popen(('taskkill.exe', '/f', '/im', 'httpd.exe'), - stdin=open(os.devnull, 'r'), - stdout=subprocess.PIPE, - stderr=subprocess.PIPE).wait() + self._executive.kill_all("httpd.exe") diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py index b972154..211ce93 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/rebaseline_chromium_webkit_tests.py @@ -41,6 +41,9 @@ The script does the following for each platform specified: At the end, the script generates a html that compares old and new baselines. """ +from __future__ import with_statement + +import codecs import copy import logging import optparse @@ -55,6 +58,8 @@ import urllib import webbrowser import zipfile +from webkitpy.common.system.executive import run_command + import port from layout_package import test_expectations from test_types import image_diff @@ -93,7 +98,9 @@ def run_shell_with_return_code(command, print_output=False): """ # Use a shell for subcommands on Windows to get a PATH search. + # FIXME: shell=True is a trail of tears, and should be removed. use_shell = sys.platform.startswith('win') + # Note: Not thread safe: http://bugs.python.org/issue2320 p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=use_shell) if print_output: @@ -278,10 +285,10 @@ class Rebaseliner(object): def get_rebaselining_tests(self): return self._rebaselining_tests + # FIXME: Callers should use scm.py instead. def _get_repo_type(self): """Get the repository type that client is using.""" - output, return_code = run_shell_with_return_code(['svn', 'info'], - False) + return_code = run_command(['svn', 'info'], return_exit_code=True) if return_code == 0: return REPO_SVN @@ -598,12 +605,14 @@ class Rebaseliner(object): os.remove(backup_file) _log.info('Saving original file to "%s"', backup_file) os.rename(path, backup_file) - f = open(path, "w") - f.write(new_expectations) - f.close() + # FIXME: What encoding are these files? + # Or is new_expectations always a byte array? + with open(path, "w") as file: + file.write(new_expectations) else: _log.info('No test was rebaselined so nothing to remove.') + # FIXME: Callers should move to SCM.add instead. def _svn_add(self, filename): """Add the file to SVN repository. @@ -715,9 +724,10 @@ class Rebaseliner(object): base_file = get_result_file_fullpath(self._options.html_directory, baseline_filename, self._platform, 'old') - f = open(base_file, 'wb') - f.write(output) - f.close() + # FIXME: This assumes run_shell returns a byte array. + # We should be using an explicit encoding here. + with open(base_file, "wb") as file: + file.write(output) _log.info(' Html: created old baseline file: "%s".', base_file) @@ -748,9 +758,9 @@ class Rebaseliner(object): diff_file = get_result_file_fullpath( self._options.html_directory, baseline_filename, self._platform, 'diff') - f = open(diff_file, 'wb') - f.write(output) - f.close() + # FIXME: This assumes run_shell returns a byte array, not unicode() + with open(diff_file, 'wb') as file: + file.write(output) _log.info(' Html: created baseline diff file: "%s".', diff_file) @@ -835,9 +845,8 @@ class HtmlGenerator(object): 'body': html_body}) _log.debug(html) - f = open(self._html_file, 'w') - f.write(html) - f.close() + with codecs.open(self._html_file, "w", "utf-8") as file: + file.write(html) _log.info('Baseline comparison html generated at "%s"', self._html_file) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py index 73195b3..456c6f3 100755 --- a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py @@ -64,7 +64,7 @@ import traceback from layout_package import test_expectations from layout_package import json_layout_results_generator -from layout_package import metered_stream +from layout_package import printing from layout_package import test_failures from layout_package import dump_render_tree_thread from layout_package import test_files @@ -80,33 +80,6 @@ import port _log = logging.getLogger("webkitpy.layout_tests.run_webkit_tests") -# dummy value used for command-line explicitness to disable defaults -LOG_NOTHING = 'nothing' - -# Display the one-line progress bar (% completed) while testing -LOG_PROGRESS = 'progress' - -# Indicates that we want detailed progress updates in the output (prints -# directory-by-directory feedback). -LOG_DETAILED_PROGRESS = 'detailed-progress' - -# Log the one-line summary at the end of the run -LOG_SUMMARY = 'summary' - -# "Trace" the test - log the expected result, the actual result, and the -# baselines used -LOG_TRACE = 'trace' - -# Log any unexpected results while running (instead of just at the end). -LOG_UNEXPECTED = 'unexpected' -LOG_UNEXPECTED_RESULTS = 'unexpected-results' - -LOG_VALUES = ",".join(("actual", "config", LOG_DETAILED_PROGRESS, "expected", - LOG_NOTHING, LOG_PROGRESS, LOG_SUMMARY, "timing", - LOG_UNEXPECTED, LOG_UNEXPECTED_RESULTS)) -LOG_DEFAULT_VALUE = ",".join((LOG_DETAILED_PROGRESS, LOG_SUMMARY, - LOG_UNEXPECTED, LOG_UNEXPECTED_RESULTS)) - # Builder base URL where we have the archived test results. BUILDER_BASE_URL = "http://build.chromium.org/buildbot/layout_test_results/" @@ -181,7 +154,7 @@ class ResultSummary(object): """ self.tests_by_expectation[result.type].add(result.filename) - self.results[result.filename] = result.type + self.results[result.filename] = result self.remaining -= 1 if len(result.failures): self.failures[result.filename] = result.failures @@ -192,6 +165,83 @@ class ResultSummary(object): self.unexpected += 1 +def summarize_unexpected_results(port_obj, expectations, result_summary, + retry_summary): + """Summarize any unexpected results as a dict. + + FIXME: split this data structure into a separate class? + + Args: + port_obj: interface to port-specific hooks + expectations: test_expectations.TestExpectations object + result_summary: summary object from initial test runs + retry_summary: summary object from final test run of retried tests + Returns: + A dictionary containing a summary of the unexpected results from the + run, with the following fields: + 'version': a version indicator (1 in this version) + 'fixable': # of fixable tests (NOW - PASS) + 'skipped': # of skipped tests (NOW & SKIPPED) + 'num_regressions': # of non-flaky failures + 'num_flaky': # of flaky failures + 'num_passes': # of unexpected passes + 'tests': a dict of tests -> {'expected': '...', 'actual': '...'} + """ + results = {} + results['version'] = 1 + + tbe = result_summary.tests_by_expectation + tbt = result_summary.tests_by_timeline + results['fixable'] = len(tbt[test_expectations.NOW] - + tbe[test_expectations.PASS]) + results['skipped'] = len(tbt[test_expectations.NOW] & + tbe[test_expectations.SKIP]) + + num_passes = 0 + num_flaky = 0 + num_regressions = 0 + keywords = {} + for k, v in TestExpectationsFile.EXPECTATIONS.iteritems(): + keywords[v] = k.upper() + + tests = {} + for filename, result in result_summary.unexpected_results.iteritems(): + # Note that if a test crashed in the original run, we ignore + # whether or not it crashed when we retried it (if we retried it), + # and always consider the result not flaky. + test = port_obj.relative_test_filename(filename) + expected = expectations.get_expectations_string(filename) + actual = [keywords[result]] + + if result == test_expectations.PASS: + num_passes += 1 + elif result == test_expectations.CRASH: + num_regressions += 1 + else: + if filename not in retry_summary.unexpected_results: + actual.extend(expectations.get_expectations_string( + filename).split(" ")) + num_flaky += 1 + else: + retry_result = retry_summary.unexpected_results[filename] + if result != retry_result: + actual.append(keywords[retry_result]) + num_flaky += 1 + else: + num_regressions += 1 + + tests[test] = {} + tests[test]['expected'] = expected + tests[test]['actual'] = " ".join(actual) + + results['tests'] = tests + results['num_passes'] = num_passes + results['num_flaky'] = num_flaky + results['num_regressions'] = num_regressions + + return results + + class TestRunner: """A class for managing running a series of tests on a series of layout test files.""" @@ -204,19 +254,17 @@ class TestRunner: # in DumpRenderTree. DEFAULT_TEST_TIMEOUT_MS = 6 * 1000 - NUM_RETRY_ON_UNEXPECTED_FAILURE = 1 - - def __init__(self, port, options, meter): + def __init__(self, port, options, printer): """Initialize test runner data structures. Args: port: an object implementing port-specific options: a dictionary of command line options - meter: a MeteredStream object to record updates to. + printer: a Printer object to record updates to. """ self._port = port self._options = options - self._meter = meter + self._printer = printer # disable wss server. need to install pyOpenSSL on buildbots. # self._websocket_secure_server = websocket_server.PyWebSocket( @@ -230,13 +278,10 @@ class TestRunner: self._test_files_list = None self._result_queue = Queue.Queue() - # These are used for --log detailed-progress to track status by - # directory. - self._current_dir = None - self._current_progress_str = "" - self._current_test_number = 0 + self._retrying = False - self._retries = 0 + # Hack for dumping threads on the bots + self._last_thread_dump = None def __del__(self): _log.debug("flushing stdout") @@ -278,19 +323,20 @@ class TestRunner: else: raise err - def prepare_lists_and_print_output(self, write): + def prepare_lists_and_print_output(self): """Create appropriate subsets of test lists and returns a ResultSummary object. Also prints expected test counts. - - Args: - write: A callback to write info to (e.g., a LoggingWriter) or - sys.stdout.write. """ # Remove skipped - both fixable and ignored - files from the # top-level list of files to test. num_all_test_files = len(self._test_files) - write("Found: %d tests" % (len(self._test_files))) + self._printer.print_expected("Found: %d tests" % + (len(self._test_files))) + if not num_all_test_files: + _log.critical("No tests to run.") + sys.exit(1) + skipped = set() if num_all_test_files > 1 and not self._options.force: skipped = self._expectations.get_tests_with_result_type( @@ -353,7 +399,7 @@ class TestRunner: tests_run_msg = 'Running: %d tests (chunk slice [%d:%d] of %d)' % ( (slice_end - slice_start), slice_start, slice_end, num_tests) - write(tests_run_msg) + self._printer.print_expected(tests_run_msg) # If we reached the end and we don't have enough tests, we run some # from the beginning. @@ -362,14 +408,13 @@ class TestRunner: extra = 1 + chunk_len - (slice_end - slice_start) extra_msg = (' last chunk is partial, appending [0:%d]' % extra) - write(extra_msg) + self._printer.print_expected(extra_msg) tests_run_msg += "\n" + extra_msg files.extend(test_files[0:extra]) tests_run_filename = os.path.join(self._options.results_directory, "tests_run.txt") - tests_run_file = open(tests_run_filename, "w") - tests_run_file.write(tests_run_msg + "\n") - tests_run_file.close() + with codecs.open(tests_run_filename, "w", "utf-8") as file: + file.write(tests_run_msg + "\n") len_skip_chunk = int(len(files) * len(skipped) / float(len(self._test_files))) @@ -395,17 +440,18 @@ class TestRunner: result_summary = ResultSummary(self._expectations, self._test_files | skip_chunk) - self._print_expected_results_of_type(write, result_summary, + self._print_expected_results_of_type(result_summary, test_expectations.PASS, "passes") - self._print_expected_results_of_type(write, result_summary, + self._print_expected_results_of_type(result_summary, test_expectations.FAIL, "failures") - self._print_expected_results_of_type(write, result_summary, + self._print_expected_results_of_type(result_summary, test_expectations.FLAKY, "flaky") - self._print_expected_results_of_type(write, result_summary, + self._print_expected_results_of_type(result_summary, test_expectations.SKIP, "skipped") if self._options.force: - write('Running all tests, including skips (--force)') + self._printer.print_expected('Running all tests, including ' + 'skips (--force)') else: # Note that we don't actually run the skipped tests (they were # subtracted out of self._test_files, above), but we stub out the @@ -416,7 +462,7 @@ class TestRunner: time_for_diffs=0) result.type = test_expectations.SKIP result_summary.add(result, expected=True) - write("") + self._printer.print_expected('') return result_summary @@ -580,6 +626,29 @@ class TestRunner: """Returns whether we should run all the tests in the main thread.""" return int(self._options.child_processes) == 1 + def _dump_thread_states(self): + for thread_id, stack in sys._current_frames().items(): + # FIXME: Python 2.6 has thread.ident which we could + # use to map from thread_id back to thread.name + print "\n# Thread: %d" % thread_id + for filename, lineno, name, line in traceback.extract_stack(stack): + print 'File: "%s", line %d, in %s' % (filename, lineno, name) + if line: + print " %s" % (line.strip()) + + def _dump_thread_states_if_necessary(self): + # HACK: Dump thread states every minute to figure out what's + # hanging on the bots. + if not self._options.verbose: + return + dump_threads_every = 60 # Dump every minute + if not self._last_thread_dump: + self._last_thread_dump = time.time() + time_since_last_dump = time.time() - self._last_thread_dump + if time_since_last_dump > dump_threads_every: + self._dump_thread_states() + self._last_thread_dump = time.time() + def _run_tests(self, file_list, result_summary): """Runs the tests in the file_list. @@ -594,14 +663,15 @@ class TestRunner: in the form {filename:filename, test_run_time:test_run_time} result_summary: summary object to populate with the results """ + # FIXME: We should use webkitpy.tool.grammar.pluralize here. plural = "" if self._options.child_processes > 1: plural = "s" - self._meter.update('Starting %s%s ...' % - (self._port.driver_name(), plural)) + self._printer.print_update('Starting %s%s ...' % + (self._port.driver_name(), plural)) threads = self._instantiate_dump_render_tree_threads(file_list, result_summary) - self._meter.update("Starting testing ...") + self._printer.print_update("Starting testing ...") # Wait for the threads to finish and collect test failures. failures = {} @@ -609,21 +679,28 @@ class TestRunner: individual_test_timings = [] thread_timings = [] try: + # Loop through all the threads waiting for them to finish. for thread in threads: + # FIXME: We'll end up waiting on the first thread the whole + # time. That means we won't notice exceptions on other + # threads until the first one exits. + # We should instead while True: in the outer loop + # and then loop through threads joining and checking + # isAlive and get_exception_info. Exiting on any exception. while thread.isAlive(): - # Let it timeout occasionally so it can notice a - # KeyboardInterrupt. Actually, the timeout doesn't - # really matter: apparently it suffices to not use - # an indefinite blocking join for it to - # be interruptible by KeyboardInterrupt. + # Wake the main thread every 0.1 seconds so we + # can call update_summary in a timely fashion. thread.join(0.1) + # HACK: Used for debugging threads on the bots. + self._dump_thread_states_if_necessary() self.update_summary(result_summary) + + # This thread is done, save off the timing information. thread_timings.append({'name': thread.getName(), 'num_tests': thread.get_num_tests(), 'total_time': thread.get_total_time()}) test_timings.update(thread.get_directory_timing_stats()) - individual_test_timings.extend( - thread.get_test_results()) + individual_test_timings.extend(thread.get_test_results()) except KeyboardInterrupt: for thread in threads: thread.cancel() @@ -637,7 +714,9 @@ class TestRunner: # would be assumed to have passed. raise exception_info[0], exception_info[1], exception_info[2] - # Make sure we pick up any remaining tests. + # FIXME: This update_summary call seems unecessary. + # Calls are already made right after join() above, + # as well as from the individual threads themselves. self.update_summary(result_summary) return (thread_timings, test_timings, individual_test_timings) @@ -645,7 +724,7 @@ class TestRunner: """Returns whether the test runner needs an HTTP server.""" return self._contains_tests(self.HTTP_SUBDIR) - def run(self, result_summary, print_results): + def run(self, result_summary): """Run all our tests on all our test files. For each test file, we run each test type. If there are any failures, @@ -653,7 +732,6 @@ class TestRunner: Args: result_summary: a summary object tracking the test results. - print_results: whether or not to print the summary at the end Return: The number of unexpected results (0 == success) @@ -663,11 +741,12 @@ class TestRunner: start_time = time.time() if self.needs_http(): - self._meter.update('Starting HTTP server ...') + self._printer.print_update('Starting HTTP server ...') + self._port.start_http_server() if self._contains_tests(self.WEBSOCKET_SUBDIR): - self._meter.update('Starting WebSocket server ...') + self._printer.print_update('Starting WebSocket server ...') self._port.start_websocket_server() # self._websocket_secure_server.Start() @@ -678,53 +757,34 @@ class TestRunner: # we want to treat even a potentially flaky crash as an error. failures = self._get_failures(result_summary, include_crashes=False) retry_summary = result_summary - while (self._retries < self.NUM_RETRY_ON_UNEXPECTED_FAILURE and - len(failures)): + while (len(failures) and self._options.retry_failures and + not self._retrying): _log.info('') - _log.info("Retrying %d unexpected failure(s)" % len(failures)) + _log.info("Retrying %d unexpected failure(s) ..." % len(failures)) _log.info('') - self._retries += 1 + self._retrying = True retry_summary = ResultSummary(self._expectations, failures.keys()) self._run_tests(failures.keys(), retry_summary) failures = self._get_failures(retry_summary, include_crashes=True) end_time = time.time() - write = create_logging_writer(self._options, 'timing') - self._print_timing_statistics(write, end_time - start_time, - thread_timings, test_timings, - individual_test_timings, - result_summary) + self._print_timing_statistics(end_time - start_time, + thread_timings, test_timings, + individual_test_timings, + result_summary) - self._meter.update("") - - if self._options.verbose: - # We write this block to stdout for compatibility with the - # buildbot log parser, which only looks at stdout, not stderr :( - write = lambda s: sys.stdout.write("%s\n" % s) - else: - write = create_logging_writer(self._options, 'actual') - - self._print_result_summary(write, result_summary) + self._print_result_summary(result_summary) sys.stdout.flush() sys.stderr.flush() - # This summary data gets written to stdout regardless of log level - # (unless of course we're printing nothing). - if print_results: - if (LOG_DETAILED_PROGRESS in self._options.log or - (LOG_UNEXPECTED in self._options.log and - result_summary.total != result_summary.expected)): - print - if LOG_SUMMARY in self._options.log: - self._print_one_line_summary(result_summary.total, + self._printer.print_one_line_summary(result_summary.total, result_summary.expected) - unexpected_results = self._summarize_unexpected_results(result_summary, - retry_summary) - if LOG_UNEXPECTED_RESULTS in self._options.log: - self._print_unexpected_results(unexpected_results) + unexpected_results = summarize_unexpected_results(self._port, + self._expectations, result_summary, retry_summary) + self._printer.print_unexpected_results(unexpected_results) # Write the same data to log files. self._write_json_files(unexpected_results, result_summary, @@ -746,112 +806,16 @@ class TestRunner: result = self._result_queue.get_nowait() except Queue.Empty: return + expected = self._expectations.matches_an_expected_result( result.filename, result.type, self._options.pixel_tests) result_summary.add(result, expected) - self._print_test_results(result, expected, result_summary) - - def _print_test_results(self, result, expected, result_summary): - "Print the result of the test as determined by the --log switches." - if LOG_TRACE in self._options.log: - self._print_test_trace(result) - elif (LOG_DETAILED_PROGRESS in self._options.log and - (self._options.experimental_fully_parallel or - self._is_single_threaded())): - self._print_detailed_progress(result_summary) - else: - if (not expected and LOG_UNEXPECTED in self._options.log): - self._print_unexpected_test_result(result) - self._print_one_line_progress(result_summary) - - def _print_test_trace(self, result): - """Print detailed results of a test (triggered by --log trace). - For each test, print: - - location of the expected baselines - - expected results - - actual result - - timing info - """ - filename = result.filename - test_name = self._port.relative_test_filename(filename) - _log.info('trace: %s' % test_name) - _log.info(' txt: %s' % - self._port.relative_test_filename( - self._port.expected_filename(filename, '.txt'))) - png_file = self._port.expected_filename(filename, '.png') - if os.path.exists(png_file): - _log.info(' png: %s' % - self._port.relative_test_filename(filename)) - else: - _log.info(' png: <none>') - _log.info(' exp: %s' % - self._expectations.get_expectations_string(filename)) - _log.info(' got: %s' % - self._expectations.expectation_to_string(result.type)) - _log.info(' took: %-.3f' % result.test_run_time) - _log.info('') - - def _print_one_line_progress(self, result_summary): - """Displays the progress through the test run.""" - percent_complete = 100 * (result_summary.expected + - result_summary.unexpected) / result_summary.total - action = "Testing" - if self._retries > 0: - action = "Retrying" - self._meter.progress("%s (%d%%): %d ran as expected, %d didn't," - " %d left" % (action, percent_complete, result_summary.expected, - result_summary.unexpected, result_summary.remaining)) - - def _print_detailed_progress(self, result_summary): - """Display detailed progress output where we print the directory name - and one dot for each completed test. This is triggered by - "--log detailed-progress".""" - if self._current_test_number == len(self._test_files_list): - return - - next_test = self._test_files_list[self._current_test_number] - next_dir = os.path.dirname( - self._port.relative_test_filename(next_test)) - if self._current_progress_str == "": - self._current_progress_str = "%s: " % (next_dir) - self._current_dir = next_dir - - while next_test in result_summary.results: - if next_dir != self._current_dir: - self._meter.write("%s\n" % (self._current_progress_str)) - self._current_progress_str = "%s: ." % (next_dir) - self._current_dir = next_dir - else: - self._current_progress_str += "." - - if (next_test in result_summary.unexpected_results and - LOG_UNEXPECTED in self._options.log): - result = result_summary.unexpected_results[next_test] - self._meter.write("%s\n" % self._current_progress_str) - self._print_unexpected_test_result(next_test, result) - self._current_progress_str = "%s: " % self._current_dir - - self._current_test_number += 1 - if self._current_test_number == len(self._test_files_list): - break - - next_test = self._test_files_list[self._current_test_number] - next_dir = os.path.dirname( - self._port.relative_test_filename(next_test)) - - if result_summary.remaining: - remain_str = " (%d)" % (result_summary.remaining) - self._meter.progress("%s%s" % - (self._current_progress_str, remain_str)) - else: - self._meter.progress("%s\n" % (self._current_progress_str)) - - def _print_unexpected_test_result(self, result): - """Prints one unexpected test result line.""" - desc = TestExpectationsFile.EXPECTATION_DESCRIPTIONS[result.type][0] - self._meter.write(" %s -> unexpected %s\n" % - (self._port.relative_test_filename(result.filename), - desc)) + exp_str = self._expectations.get_expectations_string( + result.filename) + got_str = self._expectations.expectation_to_string(result.type) + self._printer.print_test_result(result, expected, exp_str, got_str) + self._printer.print_progress(result_summary, self._retrying, + self._test_files_list) def _get_failures(self, result_summary, include_crashes): """Filters a dict of results and returns only the failures. @@ -874,80 +838,6 @@ class TestRunner: return failed_results - def _summarize_unexpected_results(self, result_summary, retry_summary): - """Summarize any unexpected results as a dict. - - TODO(dpranke): split this data structure into a separate class? - - Args: - result_summary: summary object from initial test runs - retry_summary: summary object from final test run of retried tests - Returns: - A dictionary containing a summary of the unexpected results from the - run, with the following fields: - 'version': a version indicator (1 in this version) - 'fixable': # of fixable tests (NOW - PASS) - 'skipped': # of skipped tests (NOW & SKIPPED) - 'num_regressions': # of non-flaky failures - 'num_flaky': # of flaky failures - 'num_passes': # of unexpected passes - 'tests': a dict of tests -> {'expected': '...', 'actual': '...'} - """ - results = {} - results['version'] = 1 - - tbe = result_summary.tests_by_expectation - tbt = result_summary.tests_by_timeline - results['fixable'] = len(tbt[test_expectations.NOW] - - tbe[test_expectations.PASS]) - results['skipped'] = len(tbt[test_expectations.NOW] & - tbe[test_expectations.SKIP]) - - num_passes = 0 - num_flaky = 0 - num_regressions = 0 - keywords = {} - for k, v in TestExpectationsFile.EXPECTATIONS.iteritems(): - keywords[v] = k.upper() - - tests = {} - for filename, result in result_summary.unexpected_results.iteritems(): - # Note that if a test crashed in the original run, we ignore - # whether or not it crashed when we retried it (if we retried it), - # and always consider the result not flaky. - test = self._port.relative_test_filename(filename) - expected = self._expectations.get_expectations_string(filename) - actual = [keywords[result]] - - if result == test_expectations.PASS: - num_passes += 1 - elif result == test_expectations.CRASH: - num_regressions += 1 - else: - if filename not in retry_summary.unexpected_results: - actual.extend( - self._expectations.get_expectations_string( - filename).split(" ")) - num_flaky += 1 - else: - retry_result = retry_summary.unexpected_results[filename] - if result != retry_result: - actual.append(keywords[retry_result]) - num_flaky += 1 - else: - num_regressions += 1 - - tests[test] = {} - tests[test]['expected'] = expected - tests[test]['actual'] = " ".join(actual) - - results['tests'] = tests - results['num_passes'] = num_passes - results['num_flaky'] = num_flaky - results['num_regressions'] = num_regressions - - return results - def _write_json_files(self, unexpected_results, result_summary, individual_test_timings): """Writes the results of the test run as JSON files into the results @@ -966,22 +856,19 @@ class TestRunner: individual_test_timings: list of test times (used by the flakiness dashboard). """ - _log.debug("Writing JSON files in %s." % - self._options.results_directory) - unexpected_file = open(os.path.join(self._options.results_directory, - "unexpected_results.json"), "w") - unexpected_file.write(simplejson.dumps(unexpected_results, - sort_keys=True, indent=2)) - unexpected_file.close() + results_directory = self._options.results_directory + _log.debug("Writing JSON files in %s." % results_directory) + unexpected_json_path = os.path.join(results_directory, "unexpected_results.json") + with codecs.open(unexpected_json_path, "w", "utf-8") as file: + simplejson.dump(unexpected_results, file, sort_keys=True, indent=2) # Write a json file of the test_expectations.txt file for the layout # tests dashboard. - expectations_file = open(os.path.join(self._options.results_directory, - "expectations.json"), "w") + expectations_path = os.path.join(results_directory, "expectations.json") expectations_json = \ self._expectations.get_expectations_json_for_all_platforms() - expectations_file.write("ADD_EXPECTATIONS(" + expectations_json + ");") - expectations_file.close() + with codecs.open(expectations_path, "w", "utf-8") as file: + file.write(u"ADD_EXPECTATIONS(%s);" % expectations_json) json_layout_results_generator.JSONLayoutResultsGenerator( self._port, self._options.builder_name, self._options.build_name, @@ -991,13 +878,11 @@ class TestRunner: _log.debug("Finished writing JSON files.") - def _print_expected_results_of_type(self, write, result_summary, + def _print_expected_results_of_type(self, result_summary, result_type, result_type_str): """Print the number of the tests in a given result class. Args: - write: A callback to write info to (e.g., a LoggingWriter) or - sys.stdout.write. result_summary - the object containing all the results to report on result_type - the particular result type to report in the summary. result_type_str - a string description of the result_type. @@ -1012,8 +897,9 @@ class TestRunner: fmtstr = ("Expect: %%5d %%-8s (%%%dd now, %%%dd defer, %%%dd wontfix)" % (self._num_digits(now), self._num_digits(defer), self._num_digits(wontfix))) - write(fmtstr % (len(tests), result_type_str, len(tests & now), - len(tests & defer), len(tests & wontfix))) + self._printer.print_expected(fmtstr % + (len(tests), result_type_str, len(tests & now), + len(tests & defer), len(tests & wontfix))) def _num_digits(self, num): """Returns the number of digits needed to represent the length of a @@ -1023,43 +909,39 @@ class TestRunner: ndigits = int(math.log10(len(num))) + 1 return ndigits - def _print_timing_statistics(self, write, total_time, thread_timings, + def _print_timing_statistics(self, total_time, thread_timings, directory_test_timings, individual_test_timings, result_summary): """Record timing-specific information for the test run. Args: - write: A callback to write info to (e.g., a LoggingWriter) or - sys.stdout.write. total_time: total elapsed time (in seconds) for the test run thread_timings: wall clock time each thread ran for directory_test_timings: timing by directory individual_test_timings: timing by file result_summary: summary object for the test run """ - write("Test timing:") - write(" %6.2f total testing time" % total_time) - write("") - write("Thread timing:") + self._printer.print_timing("Test timing:") + self._printer.print_timing(" %6.2f total testing time" % total_time) + self._printer.print_timing("") + self._printer.print_timing("Thread timing:") cuml_time = 0 for t in thread_timings: - write(" %10s: %5d tests, %6.2f secs" % + self._printer.print_timing(" %10s: %5d tests, %6.2f secs" % (t['name'], t['num_tests'], t['total_time'])) cuml_time += t['total_time'] - write(" %6.2f cumulative, %6.2f optimal" % + self._printer.print_timing(" %6.2f cumulative, %6.2f optimal" % (cuml_time, cuml_time / int(self._options.child_processes))) - write("") + self._printer.print_timing("") - self._print_aggregate_test_statistics(write, individual_test_timings) - self._print_individual_test_times(write, individual_test_timings, + self._print_aggregate_test_statistics(individual_test_timings) + self._print_individual_test_times(individual_test_timings, result_summary) - self._print_directory_timings(write, directory_test_timings) + self._print_directory_timings(directory_test_timings) - def _print_aggregate_test_statistics(self, write, individual_test_timings): + def _print_aggregate_test_statistics(self, individual_test_timings): """Prints aggregate statistics (e.g. median, mean, etc.) for all tests. Args: - write: A callback to write info to (e.g., a LoggingWriter) or - sys.stdout.write. individual_test_timings: List of dump_render_tree_thread.TestStats for all tests. """ @@ -1081,23 +963,21 @@ class TestRunner: times_per_test_type[test_type].append( time_for_diffs[test_type]) - self._print_statistics_for_test_timings(write, + self._print_statistics_for_test_timings( "PER TEST TIME IN TESTSHELL (seconds):", times_for_dump_render_tree) - self._print_statistics_for_test_timings(write, + self._print_statistics_for_test_timings( "PER TEST DIFF PROCESSING TIMES (seconds):", times_for_diff_processing) for test_type in test_types: - self._print_statistics_for_test_timings(write, + self._print_statistics_for_test_timings( "PER TEST TIMES BY TEST TYPE: %s" % test_type, times_per_test_type[test_type]) - def _print_individual_test_times(self, write, individual_test_timings, + def _print_individual_test_times(self, individual_test_timings, result_summary): """Prints the run times for slow, timeout and crash tests. Args: - write: A callback to write info to (e.g., a LoggingWriter) or - sys.stdout.write. individual_test_timings: List of dump_render_tree_thread.TestStats for all tests. result_summary: summary object for test run @@ -1119,53 +999,52 @@ class TestRunner: slow_tests.append(test_tuple) if filename in result_summary.failures: - result = result_summary.results[filename] + result = result_summary.results[filename].type if (result == test_expectations.TIMEOUT or result == test_expectations.CRASH): is_timeout_crash_or_slow = True timeout_or_crash_tests.append(test_tuple) if (not is_timeout_crash_or_slow and - num_printed < self._options.num_slow_tests_to_log): + num_printed < printing.NUM_SLOW_TESTS_TO_LOG): num_printed = num_printed + 1 unexpected_slow_tests.append(test_tuple) - write("") - self._print_test_list_timing(write, "%s slowest tests that are not " + self._printer.print_timing("") + self._print_test_list_timing("%s slowest tests that are not " "marked as SLOW and did not timeout/crash:" % - self._options.num_slow_tests_to_log, unexpected_slow_tests) - write("") - self._print_test_list_timing(write, "Tests marked as SLOW:", - slow_tests) - write("") - self._print_test_list_timing(write, "Tests that timed out or crashed:", + printing.NUM_SLOW_TESTS_TO_LOG, unexpected_slow_tests) + self._printer.print_timing("") + self._print_test_list_timing("Tests marked as SLOW:", slow_tests) + self._printer.print_timing("") + self._print_test_list_timing("Tests that timed out or crashed:", timeout_or_crash_tests) - write("") + self._printer.print_timing("") - def _print_test_list_timing(self, write, title, test_list): + def _print_test_list_timing(self, title, test_list): """Print timing info for each test. Args: - write: A callback to write info to (e.g., a LoggingWriter) or - sys.stdout.write. title: section heading test_list: tests that fall in this section """ - write(title) + if self._printer.disabled('slowest'): + return + + self._printer.print_timing(title) for test_tuple in test_list: filename = test_tuple.filename[len( self._port.layout_tests_dir()) + 1:] filename = filename.replace('\\', '/') test_run_time = round(test_tuple.test_run_time, 1) - write(" %s took %s seconds" % (filename, test_run_time)) + self._printer.print_timing(" %s took %s seconds" % + (filename, test_run_time)) - def _print_directory_timings(self, write, directory_test_timings): + def _print_directory_timings(self, directory_test_timings): """Print timing info by directory for any directories that take > 10 seconds to run. Args: - write: A callback to write info to (e.g., a LoggingWriter) or - sys.stdout.write. directory_test_timing: time info for each directory """ timings = [] @@ -1175,25 +1054,24 @@ class TestRunner: num_tests)) timings.sort() - write("Time to process slowest subdirectories:") + self._printer.print_timing("Time to process slowest subdirectories:") min_seconds_to_print = 10 for timing in timings: if timing[0] > min_seconds_to_print: - write(" %s took %s seconds to run %s tests." % (timing[1], - timing[0], timing[2])) - write("") + self._printer.print_timing( + " %s took %s seconds to run %s tests." % (timing[1], + timing[0], timing[2])) + self._printer.print_timing("") - def _print_statistics_for_test_timings(self, write, title, timings): + def _print_statistics_for_test_timings(self, title, timings): """Prints the median, mean and standard deviation of the values in timings. Args: - write: A callback to write info to (e.g., a LoggingWriter) or - sys.stdout.write. title: Title for these timings. timings: A list of floats representing times. """ - write(title) + self._printer.print_timing(title) timings.sort() num_tests = len(timings) @@ -1215,19 +1093,17 @@ class TestRunner: sum_of_deviations = math.pow(time - mean, 2) std_deviation = math.sqrt(sum_of_deviations / num_tests) - write(" Median: %6.3f" % median) - write(" Mean: %6.3f" % mean) - write(" 90th percentile: %6.3f" % percentile90) - write(" 99th percentile: %6.3f" % percentile99) - write(" Standard dev: %6.3f" % std_deviation) - write("") - - def _print_result_summary(self, write, result_summary): + self._printer.print_timing(" Median: %6.3f" % median) + self._printer.print_timing(" Mean: %6.3f" % mean) + self._printer.print_timing(" 90th percentile: %6.3f" % percentile90) + self._printer.print_timing(" 99th percentile: %6.3f" % percentile99) + self._printer.print_timing(" Standard dev: %6.3f" % std_deviation) + self._printer.print_timing("") + + def _print_result_summary(self, result_summary): """Print a short summary about how many tests passed. Args: - write: A callback to write info to (e.g., a LoggingWriter) or - sys.stdout.write. result_summary: information to log """ failed = len(result_summary.failures) @@ -1239,30 +1115,29 @@ class TestRunner: if total > 0: pct_passed = float(passed) * 100 / total - write("") - write("=> Results: %d/%d tests passed (%.1f%%)" % + self._printer.print_actual("") + self._printer.print_actual("=> Results: %d/%d tests passed (%.1f%%)" % (passed, total, pct_passed)) - write("") - self._print_result_summary_entry(write, result_summary, + self._printer.print_actual("") + self._print_result_summary_entry(result_summary, test_expectations.NOW, "Tests to be fixed for the current release") - write("") - self._print_result_summary_entry(write, result_summary, + self._printer.print_actual("") + self._print_result_summary_entry(result_summary, test_expectations.DEFER, "Tests we'll fix in the future if they fail (DEFER)") - write("") - self._print_result_summary_entry(write, result_summary, + self._printer.print_actual("") + self._print_result_summary_entry(result_summary, test_expectations.WONTFIX, "Tests that will only be fixed if they crash (WONTFIX)") + self._printer.print_actual("") - def _print_result_summary_entry(self, write, result_summary, timeline, + def _print_result_summary_entry(self, result_summary, timeline, heading): """Print a summary block of results for a particular timeline of test. Args: - write: A callback to write info to (e.g., a LoggingWriter) or - sys.stdout.write. result_summary: summary to print results for timeline: the timeline to print results for (NOT, WONTFIX, etc.) heading: a textual description of the timeline @@ -1271,7 +1146,7 @@ class TestRunner: not_passing = (total - len(result_summary.tests_by_expectation[test_expectations.PASS] & result_summary.tests_by_timeline[timeline])) - write("=> %s (%d):" % (heading, not_passing)) + self._printer.print_actual("=> %s (%d):" % (heading, not_passing)) for result in TestExpectationsFile.EXPECTATION_ORDER: if result == test_expectations.PASS: @@ -1281,94 +1156,34 @@ class TestRunner: desc = TestExpectationsFile.EXPECTATION_DESCRIPTIONS[result] if not_passing and len(results): pct = len(results) * 100.0 / not_passing - write(" %5d %-24s (%4.1f%%)" % (len(results), - desc[len(results) != 1], pct)) - - def _print_one_line_summary(self, total, expected): - """Print a one-line summary of the test run to stdout. + self._printer.print_actual(" %5d %-24s (%4.1f%%)" % + (len(results), desc[len(results) != 1], pct)) - Args: - total: total number of tests run - expected: number of expected results + def _results_html(self, test_files, failures, title="Test Failures", override_time=None): """ - unexpected = total - expected - if unexpected == 0: - print "All %d tests ran as expected." % expected - elif expected == 1: - print "1 test ran as expected, %d didn't:" % unexpected - else: - print "%d tests ran as expected, %d didn't:" % (expected, - unexpected) - - def _print_unexpected_results(self, unexpected_results): - """Prints any unexpected results in a human-readable form to stdout.""" - passes = {} - flaky = {} - regressions = {} - - if len(unexpected_results['tests']): - print "" - - for test, results in unexpected_results['tests'].iteritems(): - actual = results['actual'].split(" ") - expected = results['expected'].split(" ") - if actual == ['PASS']: - if 'CRASH' in expected: - _add_to_dict_of_lists(passes, - 'Expected to crash, but passed', - test) - elif 'TIMEOUT' in expected: - _add_to_dict_of_lists(passes, - 'Expected to timeout, but passed', - test) - else: - _add_to_dict_of_lists(passes, - 'Expected to fail, but passed', - test) - elif len(actual) > 1: - # We group flaky tests by the first actual result we got. - _add_to_dict_of_lists(flaky, actual[0], test) - else: - _add_to_dict_of_lists(regressions, results['actual'], test) - - if len(passes): - for key, tests in passes.iteritems(): - print "%s: (%d)" % (key, len(tests)) - tests.sort() - for test in tests: - print " %s" % test - print - - if len(flaky): - descriptions = TestExpectationsFile.EXPECTATION_DESCRIPTIONS - for key, tests in flaky.iteritems(): - result = TestExpectationsFile.EXPECTATIONS[key.lower()] - print "Unexpected flakiness: %s (%d)" % ( - descriptions[result][1], len(tests)) - tests.sort() - - for test in tests: - result = unexpected_results['tests'][test] - actual = result['actual'].split(" ") - expected = result['expected'].split(" ") - result = TestExpectationsFile.EXPECTATIONS[key.lower()] - new_expectations_list = list(set(actual) | set(expected)) - print " %s = %s" % (test, " ".join(new_expectations_list)) - print - - if len(regressions): - descriptions = TestExpectationsFile.EXPECTATION_DESCRIPTIONS - for key, tests in regressions.iteritems(): - result = TestExpectationsFile.EXPECTATIONS[key.lower()] - print "Regressions: Unexpected %s : (%d)" % ( - descriptions[result][1], len(tests)) - tests.sort() - for test in tests: - print " %s = %s" % (test, key) - print - - if len(unexpected_results['tests']) and self._options.verbose: - print "-" * 78 + test_files = a list of file paths + failures = dictionary mapping test paths to failure objects + title = title printed at top of test + override_time = current time (used by unit tests) + """ + page = """<html> + <head> + <title>Layout Test Results (%(time)s)</title> + </head> + <body> + <h2>%(title)s (%(time)s)</h2> + """ % {'title': title, 'time': override_time or time.asctime()} + + for test_file in sorted(test_files): + test_name = self._port.relative_test_filename(test_file) + test_url = self._port.filename_to_uri(test_file) + page += u"<p><a href='%s'>%s</a><br />\n" % (test_url, test_name) + test_failures = failures.get(test_file, []) + for failure in test_failures: + page += u" %s<br/>" % failure.result_html_output(test_name) + page += "</p>\n" + page += "</body></html>\n" + return page def _write_results_html_file(self, result_summary): """Write results.html which is a summary of tests that failed. @@ -1382,8 +1197,10 @@ class TestRunner: """ # test failures if self._options.full_results_html: + results_title = "Test Failures" test_files = result_summary.failures.keys() else: + results_title = "Unexpected Test Failures" unexpected_failures = self._get_failures(result_summary, include_crashes=True) test_files = unexpected_failures.keys() @@ -1392,30 +1209,10 @@ class TestRunner: out_filename = os.path.join(self._options.results_directory, "results.html") - out_file = open(out_filename, 'w') - # header - if self._options.full_results_html: - h2 = "Test Failures" - else: - h2 = "Unexpected Test Failures" - out_file.write("<html><head><title>Layout Test Results (%(time)s)" - "</title></head><body><h2>%(h2)s (%(time)s)</h2>\n" - % {'h2': h2, 'time': time.asctime()}) + with codecs.open(out_filename, "w", "utf-8") as results_file: + html = self._results_html(test_files, result_summary.failures, results_title) + results_file.write(html) - test_files.sort() - for test_file in test_files: - test_failures = result_summary.failures.get(test_file, []) - out_file.write("<p><a href='%s'>%s</a><br />\n" - % (self._port.filename_to_uri(test_file), - self._port.relative_test_filename(test_file))) - for failure in test_failures: - out_file.write(" %s<br/>" - % failure.result_html_output( - self._port.relative_test_filename(test_file))) - out_file.write("</p>\n") - - # footer - out_file.write("</body></html>\n") return True def _show_results_html_file(self): @@ -1425,64 +1222,49 @@ class TestRunner: self._port.show_results_html_file(results_filename) -def _add_to_dict_of_lists(dict, key, value): - dict.setdefault(key, []).append(value) - - def read_test_files(files): tests = [] for file in files: - for line in open(file): + # FIXME: This could be cleaner using a list comprehension. + for line in codecs.open(file, "r", "utf-8"): line = test_expectations.strip_comments(line) if line: tests.append(line) return tests -def create_logging_writer(options, log_option): - """Returns a write() function that will write the string to _log.info() - if comp was specified in --log or if --verbose is true. Otherwise the - message is dropped. - - Args: - options: list of command line options from optparse - log_option: option to match in options.log in order for the messages - to be logged (e.g., 'actual' or 'expected') - """ - if options.verbose or log_option in options.log.split(","): - return _log.info - return lambda str: 1 - - -def main(options, args, print_results=True): +def run(port_obj, options, args, regular_output=sys.stderr, + buildbot_output=sys.stdout): """Run the tests. Args: + port_obj: Port object for port-specific behavior options: a dictionary of command line options args: a list of sub directories or files to test - print_results: whether or not to log anything to stdout. - Set to false by the unit tests + regular_output: a stream-like object that we can send logging/debug + output to + buildbot_output: a stream-like object that we can write all output that + is intended to be parsed by the buildbot to Returns: the number of unexpected results that occurred, or -1 if there is an error. """ - if options.sources: - options.verbose = True + # Configure the printing subsystem for printing output, logging debug + # info, and tracing tests. - # Set up our logging format. - meter = metered_stream.MeteredStream(options.verbose, sys.stderr) - log_fmt = '%(message)s' - log_datefmt = '%y%m%d %H:%M:%S' - log_level = logging.INFO - if options.verbose: - log_fmt = ('%(asctime)s %(filename)s:%(lineno)-4d %(levelname)s ' - '%(message)s') - log_level = logging.DEBUG - logging.basicConfig(level=log_level, format=log_fmt, datefmt=log_datefmt, - stream=meter) + if not options.child_processes: + # FIXME: Investigate perf/flakiness impact of using cpu_count + 1. + options.child_processes = port_obj.default_child_processes() + + printer = printing.Printer(port_obj, options, regular_output=regular_output, + buildbot_output=buildbot_output, + child_processes=int(options.child_processes), + is_fully_parallel=options.experimental_fully_parallel) + if options.help_printing: + printer.help_printing() + return 0 - port_obj = port.get(options.platform, options) executive = Executive() if not options.configuration: @@ -1504,14 +1286,13 @@ def main(options, args, print_results=True): options.results_directory = port_obj.results_directory() last_unexpected_results = [] - if options.print_unexpected_results or options.retry_unexpected_results: + if options.print_last_failures or options.retest_last_failures: unexpected_results_filename = os.path.join( options.results_directory, "unexpected_results.json") - f = file(unexpected_results_filename) - results = simplejson.load(f) - f.close() + with open(unexpected_results_filename, "r", "utf-8") as file: + results = simplejson.load(file) last_unexpected_results = results['tests'].keys() - if options.print_unexpected_results: + if options.print_last_failures: print "\n".join(last_unexpected_results) + "\n" return 0 @@ -1519,8 +1300,8 @@ def main(options, args, print_results=True): # Just clobber the actual test results directories since the other # files in the results directory are explicitly used for cross-run # tracking. - meter.update("Clobbering old results in %s" % - options.results_directory) + printer.print_update("Clobbering old results in %s" % + options.results_directory) layout_tests_dir = port_obj.layout_tests_dir() possible_dirs = os.listdir(layout_tests_dir) for dirname in possible_dirs: @@ -1528,17 +1309,6 @@ def main(options, args, print_results=True): shutil.rmtree(os.path.join(options.results_directory, dirname), ignore_errors=True) - if not options.child_processes: - # FIXME: Investigate perf/flakiness impact of using cpu_count + 1. - options.child_processes = port_obj.default_child_processes() - - write = create_logging_writer(options, 'config') - if options.child_processes == 1: - write("Running one %s" % port_obj.driver_name) - else: - write("Running %s %ss in parallel" % ( - options.child_processes, port_obj.driver_name())) - if not options.time_out_ms: if options.configuration == "Debug": options.time_out_ms = str(2 * TestRunner.DEFAULT_TEST_TIMEOUT_MS) @@ -1546,8 +1316,14 @@ def main(options, args, print_results=True): options.time_out_ms = str(TestRunner.DEFAULT_TEST_TIMEOUT_MS) options.slow_time_out_ms = str(5 * int(options.time_out_ms)) - write("Regular timeout: %s, slow test timeout: %s" % - (options.time_out_ms, options.slow_time_out_ms)) + printer.print_config("Regular timeout: %s, slow test timeout: %s" % + (options.time_out_ms, options.slow_time_out_ms)) + + if int(options.child_processes) == 1: + printer.print_config("Running one %s" % port_obj.driver_name()) + else: + printer.print_config("Running %s %ss in parallel" % ( + options.child_processes, port_obj.driver_name())) # Include all tests if none are specified. new_args = [] @@ -1564,9 +1340,9 @@ def main(options, args, print_results=True): # Create the output directory if it doesn't already exist. port_obj.maybe_make_directory(options.results_directory) - meter.update("Collecting tests ...") + printer.print_update("Collecting tests ...") - test_runner = TestRunner(port_obj, options, meter) + test_runner = TestRunner(port_obj, options, printer) test_runner.gather_file_paths(paths) if options.lint_test_files: @@ -1576,43 +1352,43 @@ def main(options, args, print_results=True): for platform_name in port_obj.test_platform_names(): test_runner.parse_expectations(platform_name, is_debug_mode=True) test_runner.parse_expectations(platform_name, is_debug_mode=False) - meter.update("") - print ("If there are no fail messages, errors or exceptions, then the " - "lint succeeded.") + printer.write("") + _log.info("If there are no fail messages, errors or exceptions, " + "then the lint succeeded.") return 0 - write = create_logging_writer(options, "config") - write("Using port '%s'" % port_obj.name()) - write("Placing test results in %s" % options.results_directory) + printer.print_config("Using port '%s'" % port_obj.name()) + printer.print_config("Placing test results in %s" % + options.results_directory) if options.new_baseline: - write("Placing new baselines in %s" % port_obj.baseline_path()) - write("Using %s build" % options.configuration) + printer.print_config("Placing new baselines in %s" % + port_obj.baseline_path()) + printer.print_config("Using %s build" % options.configuration) if options.pixel_tests: - write("Pixel tests enabled") + printer.print_config("Pixel tests enabled") else: - write("Pixel tests disabled") - write("") + printer.print_config("Pixel tests disabled") + printer.print_config("") - meter.update("Parsing expectations ...") + printer.print_update("Parsing expectations ...") test_runner.parse_expectations(port_obj.test_platform_name(), options.configuration == 'Debug') - meter.update("Checking build ...") + printer.print_update("Checking build ...") if not port_obj.check_build(test_runner.needs_http()): return -1 - meter.update("Starting helper ...") + printer.print_update("Starting helper ...") port_obj.start_helper() # Check that the system dependencies (themes, fonts, ...) are correct. if not options.nocheck_sys_deps: - meter.update("Checking system dependencies ...") + printer.print_update("Checking system dependencies ...") if not port_obj.check_sys_deps(test_runner.needs_http()): return -1 - meter.update("Preparing tests ...") - write = create_logging_writer(options, "expected") - result_summary = test_runner.prepare_lists_and_print_output(write) + printer.print_update("Preparing tests ...") + result_summary = test_runner.prepare_lists_and_print_output() port_obj.setup_test_run() @@ -1622,7 +1398,7 @@ def main(options, args, print_results=True): if options.fuzzy_pixel_tests: test_runner.add_test_type(fuzzy_image_diff.FuzzyImageDiff) - num_unexpected_results = test_runner.run(result_summary, print_results) + num_unexpected_results = test_runner.run(result_summary) port_obj.stop_helper() @@ -1634,8 +1410,10 @@ def _compat_shim_callback(option, opt_str, value, parser): print "Ignoring unsupported option: %s" % opt_str -def _compat_shim_option(option_name, nargs=0): - return optparse.make_option(option_name, action="callback", callback=_compat_shim_callback, nargs=nargs, help="Ignored, for old-run-webkit-tests compat only.") +def _compat_shim_option(option_name, **kwargs): + return optparse.make_option(option_name, action="callback", + callback=_compat_shim_callback, + help="Ignored, for old-run-webkit-tests compat only.", **kwargs) def parse_args(args=None): @@ -1659,22 +1437,7 @@ def parse_args(args=None): # old-run-webkit-tests also accepts -c, --configuration CONFIGURATION. ] - logging_options = [ - optparse.make_option("--log", action="store", - default=LOG_DEFAULT_VALUE, - help=("log various types of data. The argument value should be a " - "comma-separated list of values from: %s (defaults to " - "--log %s)" % (LOG_VALUES, LOG_DEFAULT_VALUE))), - optparse.make_option("-v", "--verbose", action="store_true", - default=False, help="include debug-level logging"), - optparse.make_option("--sources", action="store_true", - help="show expected result file path for each test " + - "(implies --verbose)"), - # old-run-webkit-tests has a --slowest option which just prints - # the slowest 10. - optparse.make_option("--num-slow-tests-to-log", default=50, - help="Number of slow tests whose timings to print."), - ] + print_options = printing.print_options() # FIXME: These options should move onto the ChromiumPort. chromium_options = [ @@ -1706,7 +1469,7 @@ def parse_args(args=None): _compat_shim_option("--use-remote-links-to-tests"), # FIXME: NRWT doesn't need this option as much since failures are # designed to be cheap. We eventually plan to add this support. - _compat_shim_option("--exit-after-n-failures", nargs=1), + _compat_shim_option("--exit-after-n-failures", nargs=1, type="int"), ] results_options = [ @@ -1815,12 +1578,18 @@ def parse_args(args=None): # Exit after the first N failures instead of running all tests # FIXME: consider: --iterations n # Number of times to run the set of tests (e.g. ABCABCABC) - optparse.make_option("--print-unexpected-results", action="store_true", - default=False, help="print the tests in the last run that " - "had unexpected results."), - optparse.make_option("--retry-unexpected-results", action="store_true", - default=False, help="re-try the tests in the last run that " - "had unexpected results."), + optparse.make_option("--print-last-failures", action="store_true", + default=False, help="Print the tests in the last run that " + "had unexpected failures (or passes)."), + optparse.make_option("--retest-last-failures", action="store_true", + default=False, help="re-test the tests in the last run that " + "had unexpected failures (or passes)."), + optparse.make_option("--retry-failures", action="store_true", + default=True, + help="Re-try any tests that produce unexpected results (default)"), + optparse.make_option("--no-retry-failures", action="store_false", + dest="retry_failures", + help="Don't re-try any tests that produce unexpected results."), ] misc_options = [ @@ -1841,13 +1610,23 @@ def parse_args(args=None): help=("The build number of the builder running this script.")), ] - option_list = (configuration_options + logging_options + + option_list = (configuration_options + print_options + chromium_options + results_options + test_options + misc_options + results_json_options + old_run_webkit_tests_compat) option_parser = optparse.OptionParser(option_list=option_list) - return option_parser.parse_args(args) -if '__main__' == __name__: + options, args = option_parser.parse_args(args) + if options.sources: + options.verbose = True + + return options, args + + +def main(): options, args = parse_args() - sys.exit(main(options, args)) + port_obj = port.get(options.platform, options) + return run(port_obj, options, args) + +if '__main__' == __name__: + sys.exit(main()) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py index 9fe0e74..cd72fa3 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py @@ -33,14 +33,32 @@ import os import sys import unittest -import webkitpy.layout_tests.run_webkit_tests as run_webkit_tests +from webkitpy.common import array_stream +from webkitpy.layout_tests import port +from webkitpy.layout_tests import run_webkit_tests +from webkitpy.thirdparty.mock import Mock -def passing_run(args): + +def passing_run(args, port_obj=None, logging_included=False): + if not logging_included: + args.extend(['--print', 'nothing']) options, args = run_webkit_tests.parse_args(args) - res = run_webkit_tests.main(options, args, False) + if port_obj is None: + port_obj = port.get(options.platform, options) + res = run_webkit_tests.run(port_obj, options, args) return res == 0 +def logging_run(args): + options, args = run_webkit_tests.parse_args(args) + port_obj = port.get(options.platform, options) + buildbot_output = array_stream.ArrayStream() + regular_output = array_stream.ArrayStream() + res = run_webkit_tests.run(port_obj, options, args, + buildbot_output=buildbot_output, + regular_output=regular_output) + return (res, buildbot_output, regular_output) + class MainTest(unittest.TestCase): def test_fast(self): @@ -53,9 +71,44 @@ class MainTest(unittest.TestCase): 'fast/html/article-element.html'])) self.assertTrue(passing_run(['--platform', 'test', '--child-processes', '1', - '--log', 'unexpected', + '--print', 'unexpected', 'fast/html'])) + def test_child_processes(self): + (res, buildbot_output, regular_output) = logging_run( + ['--platform', 'test', '--print', 'config', '--child-processes', + '1', 'fast/html']) + self.assertTrue('Running one DumpRenderTree' + in regular_output.get()) + + (res, buildbot_output, regular_output) = logging_run( + ['--platform', 'test', '--print', 'config', '--child-processes', + '2', 'fast/html']) + self.assertTrue('Running 2 DumpRenderTrees in parallel' + in regular_output.get()) + + + +class TestRunnerTest(unittest.TestCase): + def test_results_html(self): + mock_port = Mock() + mock_port.relative_test_filename = lambda name: name + mock_port.filename_to_uri = lambda name: name + + runner = run_webkit_tests.TestRunner(port=mock_port, options=Mock(), printer=Mock()) + expected_html = u"""<html> + <head> + <title>Layout Test Results (time)</title> + </head> + <body> + <h2>Title (time)</h2> + <p><a href='test_path'>test_path</a><br /> +</p> +</body></html> +""" + html = runner._results_html(["test_path"], {}, "Title", override_time="time") + self.assertEqual(html, expected_html) + class DryrunTest(unittest.TestCase): def test_basics(self): diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py index b414358..b37f4b3 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py @@ -34,6 +34,9 @@ match, returns FailureImageHashMismatch and outputs both hashes into the layout test results directory. """ +from __future__ import with_statement + +import codecs import errno import logging import os @@ -78,11 +81,10 @@ class ImageDiff(test_type_base.TestTypeBase): png_path: path to the actual PNG result file checksum: value of the actual checksum result """ - png_file = open(png_path, "rb") - png_data = png_file.read() - png_file.close() - self._save_baseline_data(filename, png_data, ".png") - self._save_baseline_data(filename, checksum, ".checksum") + with open(png_path, "rb") as png_file: + png_data = png_file.read() + self._save_baseline_data(filename, png_data, ".png", encoding=None) + self._save_baseline_data(filename, checksum, ".checksum", encoding="ascii") def _create_image_diff(self, port, filename, configuration): """Creates the visual diff of the expected/actual PNGs. @@ -140,8 +142,10 @@ class ImageDiff(test_type_base.TestTypeBase): _log.debug('Using %s' % expected_hash_file) _log.debug('Using %s' % expected_png_file) + # FIXME: We repeat this pattern often, we should share code. try: - expected_hash = open(expected_hash_file, "r").read() + with codecs.open(expected_hash_file, "r", "ascii") as file: + expected_hash = file.read() except IOError, e: if errno.ENOENT != e.errno: raise @@ -152,6 +156,7 @@ class ImageDiff(test_type_base.TestTypeBase): # Report a missing expected PNG file. self.write_output_files(port, filename, '.checksum', test_args.hash, expected_hash, + encoding="ascii", print_text_diffs=False) self._copy_output_png(filename, test_args.png_path, '-actual.png') failures.append(test_failures.FailureMissingImage(self)) @@ -162,6 +167,7 @@ class ImageDiff(test_type_base.TestTypeBase): self.write_output_files(port, filename, '.checksum', test_args.hash, expected_hash, + encoding="ascii", print_text_diffs=False) self._copy_output_png(filename, test_args.png_path, '-actual.png') self._copy_output_png(filename, expected_png_file, '-expected.png') diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py index 4c99be0..cf0b9ec 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py @@ -32,6 +32,9 @@ Also defines the TestArguments "struct" to pass them additional arguments. """ +from __future__ import with_statement + +import codecs import cgi import errno import logging @@ -90,7 +93,7 @@ class TestTypeBase(object): self._port.relative_test_filename(filename)) self._port.maybe_make_directory(os.path.split(output_filename)[0]) - def _save_baseline_data(self, filename, data, modifier): + def _save_baseline_data(self, filename, data, modifier, encoding): """Saves a new baseline file into the port's baseline directory. The file will be named simply "<test>-expected<modifier>", suitable for @@ -112,7 +115,7 @@ class TestTypeBase(object): self._port.maybe_make_directory(output_dir) output_path = os.path.join(output_dir, output_file) _log.debug('writing new baseline to "%s"' % (output_path)) - self._write_into_file_at_path(output_path, data) + self._write_into_file_at_path(output_path, data, encoding) def output_filename(self, filename, modifier): """Returns a filename inside the output dir that contains modifier. @@ -150,13 +153,15 @@ class TestTypeBase(object): """ raise NotImplemented - def _write_into_file_at_path(self, file_path, contents): - file = open(file_path, "wb") - file.write(contents) - file.close() + def _write_into_file_at_path(self, file_path, contents, encoding): + """This method assumes that byte_array is already encoded + into the right format.""" + with codecs.open(file_path, "w", encoding=encoding) as file: + file.write(contents) def write_output_files(self, port, filename, file_type, - output, expected, print_text_diffs=False): + output, expected, encoding, + print_text_diffs=False): """Writes the test output, the expected output and optionally the diff between the two to files in the results directory. @@ -175,10 +180,12 @@ class TestTypeBase(object): self._make_output_directory(filename) actual_filename = self.output_filename(filename, self.FILENAME_SUFFIX_ACTUAL + file_type) expected_filename = self.output_filename(filename, self.FILENAME_SUFFIX_EXPECTED + file_type) + # FIXME: This function is poorly designed. We should be passing in some sort of + # encoding information from the callers. if output: - self._write_into_file_at_path(actual_filename, output) + self._write_into_file_at_path(actual_filename, output, encoding) if expected: - self._write_into_file_at_path(expected_filename, expected) + self._write_into_file_at_path(expected_filename, expected, encoding) if not output or not expected: return @@ -186,16 +193,19 @@ class TestTypeBase(object): if not print_text_diffs: return + # Note: We pass encoding=None for all diff writes, as we treat diff + # output as binary. Diff output may contain multiple files in + # conflicting encodings. diff = port.diff_text(expected, output, expected_filename, actual_filename) diff_filename = self.output_filename(filename, self.FILENAME_SUFFIX_DIFF + file_type) - self._write_into_file_at_path(diff_filename, diff) + self._write_into_file_at_path(diff_filename, diff, encoding=None) # Shell out to wdiff to get colored inline diffs. wdiff = port.wdiff_text(expected_filename, actual_filename) wdiff_filename = self.output_filename(filename, self.FILENAME_SUFFIX_WDIFF) - self._write_into_file_at_path(wdiff_filename, wdiff) + self._write_into_file_at_path(wdiff_filename, wdiff, encoding=None) # Use WebKit's PrettyPatch.rb to get an HTML diff. pretty_patch = port.pretty_patch_text(diff_filename) pretty_patch_filename = self.output_filename(filename, self.FILENAME_SUFFIX_PRETTY_PATCH) - self._write_into_file_at_path(pretty_patch_filename, pretty_patch) + self._write_into_file_at_path(pretty_patch_filename, pretty_patch, encoding=None) diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/text_diff.py b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/text_diff.py index 8f7907c..9fed474 100644 --- a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/text_diff.py +++ b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/text_diff.py @@ -33,6 +33,9 @@ If the output doesn't match, returns FailureTextMismatch and outputs the diff files into the layout test results directory. """ +from __future__ import with_statement + +import codecs import errno import logging import os.path @@ -43,12 +46,6 @@ from webkitpy.layout_tests.test_types import test_type_base _log = logging.getLogger("webkitpy.layout_tests.test_types.text_diff") -def is_render_tree_dump(data): - """Returns true if data appears to be a render tree dump as opposed to a - plain text dump.""" - return data.find("RenderView at (0,0)") != -1 - - class TestTextDiff(test_type_base.TestTypeBase): def get_normalized_output_text(self, output): @@ -70,8 +67,14 @@ class TestTextDiff(test_type_base.TestTypeBase): return self.get_normalized_text(expected_filename) def get_normalized_text(self, filename): + # FIXME: We repeat this pattern often, we should share code. try: - text = open(filename).read() + # NOTE: -expected.txt files are ALWAYS utf-8. However, + # we do not decode the output from DRT, so we should not + # decode the -expected.txt values either to allow comparisons. + with codecs.open(filename, "r", encoding=None) as file: + text = file.read() + # We could assert that the text is valid utf-8. except IOError, e: if errno.ENOENT != e.errno: raise @@ -87,7 +90,10 @@ class TestTextDiff(test_type_base.TestTypeBase): # If we're generating a new baseline, we pass. if test_args.new_baseline: - self._save_baseline_data(filename, output, ".txt") + # Although all test_shell/DumpRenderTree output should be utf-8, + # we do not ever decode it inside run-webkit-tests. For some tests + # DumpRenderTree may not output utf-8 text (e.g. webarchives). + self._save_baseline_data(filename, output, ".txt", encoding=None) return failures # Normalize text to diff @@ -99,7 +105,8 @@ class TestTextDiff(test_type_base.TestTypeBase): if port.compare_text(output, expected): # Text doesn't match, write output files. self.write_output_files(port, filename, ".txt", output, - expected, print_text_diffs=True) + expected, encoding=None, + print_text_diffs=True) if expected == '': failures.append(test_failures.FailureMissingResult(self)) diff --git a/WebKitTools/Scripts/webkitpy/style/checker.py b/WebKitTools/Scripts/webkitpy/style/checker.py index 84ae3da..59a3d39 100644 --- a/WebKitTools/Scripts/webkitpy/style/checker.py +++ b/WebKitTools/Scripts/webkitpy/style/checker.py @@ -30,20 +30,19 @@ """Front end of some style-checker modules.""" -import codecs import logging import os.path import sys +from checkers.common import categories as CommonCategories +from checkers.common import CarriageReturnChecker +from checkers.cpp import CppChecker +from checkers.python import PythonChecker +from checkers.text import TextChecker from error_handlers import DefaultStyleErrorHandler from filter import FilterConfiguration from optparser import ArgumentParser from optparser import DefaultCommandOptionValues -from processors.common import categories as CommonCategories -from processors.common import CarriageReturnProcessor -from processors.cpp import CppProcessor -from processors.python import PythonProcessor -from processors.text import TextProcessor from webkitpy.style_references import parse_patch from webkitpy.style_references import configure_logging as _configure_logging @@ -158,11 +157,51 @@ _PATH_RULES_SPECIFIER = [ ] +_CPP_FILE_EXTENSIONS = [ + 'c', + 'cpp', + 'h', + ] + +_PYTHON_FILE_EXTENSION = 'py' + +# FIXME: Include 'vcproj' files as text files after creating a mechanism +# for exempting them from the carriage-return checker (since they +# are Windows-only files). +_TEXT_FILE_EXTENSIONS = [ + 'ac', + 'cc', + 'cgi', + 'css', + 'exp', + 'flex', + 'gyp', + 'gypi', + 'html', + 'idl', + 'in', + 'js', + 'mm', + 'php', + 'pl', + 'pm', + 'pri', + 'pro', + 'rb', + 'sh', + 'txt', +# 'vcproj', # See FIXME above. + 'wm', + 'xhtml', + 'y', + ] + + +# Files to skip that are less obvious. +# # Some files should be skipped when checking style. For example, # WebKit maintains some files in Mozilla style on purpose to ease # future merges. -# -# Include a warning for skipped files that are less obvious. _SKIPPED_FILES_WITH_WARNING = [ # The Qt API and tests do not follow WebKit style. # They follow Qt style. :) @@ -175,11 +214,12 @@ _SKIPPED_FILES_WITH_WARNING = [ ] -# Don't include a warning for skipped files that are more common -# and more obvious. +# Files to skip that are more common or obvious. +# +# This list should be in addition to files with FileType.NONE. Files +# with FileType.NONE are automatically skipped without warning. _SKIPPED_FILES_WITHOUT_WARNING = [ "LayoutTests/", - ".pyc", ] @@ -192,8 +232,8 @@ _MAX_REPORTS_PER_CATEGORY = { def _all_categories(): """Return the set of all categories used by check-webkit-style.""" - # Take the union across all processors. - categories = CommonCategories.union(CppProcessor.categories) + # Take the union across all checkers. + categories = CommonCategories.union(CppChecker.categories) # FIXME: Consider adding all of the pep8 categories. Since they # are not too meaningful for documentation purposes, for @@ -221,7 +261,7 @@ def check_webkit_style_parser(): def check_webkit_style_configuration(options): - """Return a StyleCheckerConfiguration instance for check-webkit-style. + """Return a StyleProcessorConfiguration instance for check-webkit-style. Args: options: A CommandOptionValues instance. @@ -232,7 +272,7 @@ def check_webkit_style_configuration(options): path_specific=_PATH_RULES_SPECIFIER, user_rules=options.filter_rules) - return StyleCheckerConfiguration(filter_configuration=filter_configuration, + return StyleProcessorConfiguration(filter_configuration=filter_configuration, max_reports_per_category=_MAX_REPORTS_PER_CATEGORY, min_confidence=options.min_confidence, output_format=options.output_format, @@ -330,34 +370,17 @@ def configure_logging(stream, logger=None, is_verbose=False): # Enum-like idiom class FileType: - NONE = 1 + NONE = 0 # FileType.NONE evaluates to False. # Alphabetize remaining types - CPP = 2 - PYTHON = 3 - TEXT = 4 + CPP = 1 + PYTHON = 2 + TEXT = 3 -class ProcessorDispatcher(object): +class CheckerDispatcher(object): """Supports determining whether and how to check style, based on path.""" - cpp_file_extensions = ( - 'c', - 'cpp', - 'h', - ) - - text_file_extensions = ( - 'css', - 'html', - 'idl', - 'js', - 'mm', - 'php', - 'pm', - 'txt', - ) - def _file_extension(self, file_path): """Return the file extension without the leading dot.""" return os.path.splitext(file_path)[1].lstrip(".") @@ -371,6 +394,16 @@ class ProcessorDispatcher(object): def should_skip_without_warning(self, file_path): """Return whether the given file should be skipped without a warning.""" + if not self._file_type(file_path): # FileType.NONE. + return True + # Since "LayoutTests" is in _SKIPPED_FILES_WITHOUT_WARNING, make + # an exception to prevent files like "LayoutTests/ChangeLog" and + # "LayoutTests/ChangeLog-2009-06-16" from being skipped. + # + # FIXME: Figure out a good way to avoid having to add special logic + # for this special case. + if os.path.basename(file_path).startswith('ChangeLog'): + return False for skipped_file in _SKIPPED_FILES_WITHOUT_WARNING: if file_path.find(skipped_file) >= 0: return True @@ -380,7 +413,7 @@ class ProcessorDispatcher(object): """Return the file type corresponding to the given file.""" file_extension = self._file_extension(file_path) - if (file_extension in self.cpp_file_extensions) or (file_path == '-'): + if (file_extension in _CPP_FILE_EXTENSIONS) or (file_path == '-'): # FIXME: Do something about the comment below and the issue it # raises since cpp_style already relies on the extension. # @@ -388,28 +421,28 @@ class ProcessorDispatcher(object): # reading from stdin, cpp_style tests should not rely on # the extension. return FileType.CPP - elif file_extension == "py": + elif file_extension == _PYTHON_FILE_EXTENSION: return FileType.PYTHON - elif ("ChangeLog" in file_path or + elif (os.path.basename(file_path).startswith('ChangeLog') or (not file_extension and "WebKitTools/Scripts/" in file_path) or - file_extension in self.text_file_extensions): + file_extension in _TEXT_FILE_EXTENSIONS): return FileType.TEXT else: return FileType.NONE - def _create_processor(self, file_type, file_path, handle_style_error, - min_confidence): - """Instantiate and return a style processor based on file type.""" + def _create_checker(self, file_type, file_path, handle_style_error, + min_confidence): + """Instantiate and return a style checker based on file type.""" if file_type == FileType.NONE: - processor = None + checker = None elif file_type == FileType.CPP: file_extension = self._file_extension(file_path) - processor = CppProcessor(file_path, file_extension, - handle_style_error, min_confidence) + checker = CppChecker(file_path, file_extension, + handle_style_error, min_confidence) elif file_type == FileType.PYTHON: - processor = PythonProcessor(file_path, handle_style_error) + checker = PythonChecker(file_path, handle_style_error) elif file_type == FileType.TEXT: - processor = TextProcessor(file_path, handle_style_error) + checker = TextChecker(file_path, handle_style_error) else: raise ValueError('Invalid file type "%(file_type)s": the only valid file types ' "are %(NONE)s, %(CPP)s, and %(TEXT)s." @@ -418,24 +451,24 @@ class ProcessorDispatcher(object): "CPP": FileType.CPP, "TEXT": FileType.TEXT}) - return processor + return checker - def dispatch_processor(self, file_path, handle_style_error, min_confidence): - """Instantiate and return a style processor based on file path.""" + def dispatch(self, file_path, handle_style_error, min_confidence): + """Instantiate and return a style checker based on file path.""" file_type = self._file_type(file_path) - processor = self._create_processor(file_type, - file_path, - handle_style_error, - min_confidence) - return processor + checker = self._create_checker(file_type, + file_path, + handle_style_error, + min_confidence) + return checker # FIXME: Remove the stderr_write attribute from this class and replace # its use with calls to a logging module logger. -class StyleCheckerConfiguration(object): +class StyleProcessorConfiguration(object): - """Stores configuration values for the StyleChecker class. + """Stores configuration values for the StyleProcessor class. Attributes: min_confidence: An integer between 1 and 5 inclusive that is the @@ -455,7 +488,7 @@ class StyleCheckerConfiguration(object): min_confidence, output_format, stderr_write): - """Create a StyleCheckerConfiguration instance. + """Create a StyleProcessorConfiguration instance. Args: filter_configuration: A FilterConfiguration instance. The default @@ -528,7 +561,13 @@ class ProcessorBase(object): """The base class for processors of lists of lines.""" def should_process(self, file_path): - """Return whether the file at file_path should be processed.""" + """Return whether the file at file_path should be processed. + + The TextFileReader class calls this method prior to reading in + the lines of a file. Use this method, for example, to prevent + the style checker from reading binary files into memory. + + """ raise NotImplementedError('Subclasses should implement.') def process(self, lines, file_path, **kwargs): @@ -540,7 +579,7 @@ class ProcessorBase(object): **kwargs: This argument signifies that the process() method of subclasses of ProcessorBase may support additional keyword arguments. - For example, a style processor's process() method + For example, a style checker's check() method may support a "reportable_lines" parameter that represents the line numbers of the lines for which style errors should be reported. @@ -549,209 +588,129 @@ class ProcessorBase(object): raise NotImplementedError('Subclasses should implement.') -# FIXME: Modify this class to start using the TextFileReader class in -# webkitpy/style/filereader.py. This probably means creating -# a StyleProcessor class that inherits from ProcessorBase. -class StyleChecker(object): +class StyleProcessor(ProcessorBase): - """Supports checking style in files and patches. + """A ProcessorBase for checking style. - Attributes: - error_count: An integer that is the total number of reported - errors for the lifetime of this StyleChecker - instance. - file_count: An integer that is the total number of processed - files. Note that the number of skipped files is - included in this value. + Attributes: + error_count: An integer that is the total number of reported + errors for the lifetime of this instance. """ - def __init__(self, configuration): - """Create a StyleChecker instance. + def __init__(self, configuration, mock_dispatcher=None, + mock_increment_error_count=None, + mock_carriage_checker_class=None): + """Create an instance. Args: - configuration: A StyleCheckerConfiguration instance that controls - the behavior of style checking. + configuration: A StyleProcessorConfiguration instance. + mock_dispatcher: A mock CheckerDispatcher instance. This + parameter is for unit testing. Defaults to a + CheckerDispatcher instance. + mock_increment_error_count: A mock error-count incrementer. + mock_carriage_checker_class: A mock class for checking and + transforming carriage returns. + This parameter is for unit testing. + Defaults to CarriageReturnChecker. """ - self._configuration = configuration - self.error_count = 0 - self.file_count = 0 - - def _increment_error_count(self): - """Increment the total count of reported errors.""" - self.error_count += 1 - - def _read_lines(self, file_path): - """Read the file at a path, and return its lines. - - Raises: - IOError: if the file does not exist or cannot be read. - - """ - # Support the UNIX convention of using "-" for stdin. - if file_path == '-': - file = codecs.StreamReaderWriter(sys.stdin, - codecs.getreader('utf8'), - codecs.getwriter('utf8'), - 'replace') + if mock_dispatcher is None: + dispatcher = CheckerDispatcher() else: - # We do not open the file with universal newline support - # (codecs does not support it anyway), so the resulting - # lines contain trailing "\r" characters if we are reading - # a file with CRLF endings. - file = codecs.open(file_path, 'r', 'utf8', 'replace') - - contents = file.read() - - lines = contents.split("\n") - return lines - - def _process_file(self, processor, file_path, handle_style_error): - """Process the file using the given style processor.""" - try: - lines = self._read_lines(file_path) - except IOError: - message = 'Could not read file. Skipping: "%s"' % file_path - _log.warn(message) - return - - # Check for and remove trailing carriage returns ("\r"). - # - # FIXME: We should probably use the SVN "eol-style" property - # or a white list to decide whether or not to do - # the carriage-return check. Originally, we did the - # check only if (os.linesep != '\r\n'). - carriage_return_processor = CarriageReturnProcessor(handle_style_error) - lines = carriage_return_processor.process(lines) - - processor.process(lines) + dispatcher = mock_dispatcher - def check_paths(self, paths, mock_check_file=None, mock_os=None): - """Check style in the given files or directories. + if mock_increment_error_count is None: + # The following blank line is present to avoid flagging by pep8.py. - Args: - paths: A list of file paths and directory paths. - mock_check_file: A mock of self.check_file for unit testing. - mock_os: A mock os for unit testing. - - """ - check_file = self.check_file if mock_check_file is None else \ - mock_check_file - os_module = os if mock_os is None else mock_os - - for path in paths: - if os_module.path.isdir(path): - self._check_directory(directory=path, - check_file=check_file, - mock_os_walk=os_module.walk) - else: - check_file(path) + def increment_error_count(): + """Increment the total count of reported errors.""" + self.error_count += 1 + else: + increment_error_count = mock_increment_error_count - def _check_directory(self, directory, check_file, mock_os_walk=None): - """Check style in all files in a directory, recursively. + if mock_carriage_checker_class is None: + # This needs to be a class rather than an instance since the + # process() method instantiates one using parameters. + carriage_checker_class = CarriageReturnChecker + else: + carriage_checker_class = mock_carriage_checker_class - Args: - directory: A path to a directory. - check_file: The function to use in place of self.check_file(). - mock_os_walk: A mock os.walk for unit testing. + self.error_count = 0 - """ - os_walk = os.walk if mock_os_walk is None else mock_os_walk + self._carriage_checker_class = carriage_checker_class + self._configuration = configuration + self._dispatcher = dispatcher + self._increment_error_count = increment_error_count - for dir_path, dir_names, file_names in os_walk(directory): - for file_name in file_names: - file_path = os.path.join(dir_path, file_name) - check_file(file_path) + def should_process(self, file_path): + """Return whether the file should be checked for style.""" + if self._dispatcher.should_skip_without_warning(file_path): + return False + if self._dispatcher.should_skip_with_warning(file_path): + _log.warn('File exempt from style guide. Skipping: "%s"' + % file_path) + return False + return True - def check_file(self, file_path, line_numbers=None, - mock_handle_style_error=None, - mock_os_path_exists=None, - mock_process_file=None): - """Check style in the given file. + def process(self, lines, file_path, line_numbers=None): + """Check the given lines for style. - Args: + Arguments: + lines: A list of all lines in the file to check. file_path: The path of the file to process. If possible, the path should be relative to the source root. Otherwise, path-specific logic may not behave as expected. - line_numbers: An array of line numbers of the lines for which + line_numbers: A list of line numbers of the lines for which style errors should be reported, or None if errors - for all lines should be reported. Normally, this - array contains the line numbers corresponding to the - modified lines of a patch. - mock_handle_style_error: A unit-testing replacement for the function - to call when a style error occurs. Defaults - to a DefaultStyleErrorHandler instance. - mock_os_path_exists: A unit-test replacement for os.path.exists. - This parameter should only be used for unit - tests. - mock_process_file: The function to call to process the file. This - parameter should be used only for unit tests. - Defaults to the file processing method of this - class. - - Raises: - SystemExit: if the file does not exist. + for all lines should be reported. When not None, this + list normally contains the line numbers corresponding + to the modified lines of a patch. """ - if mock_handle_style_error is None: - increment = self._increment_error_count - handle_style_error = DefaultStyleErrorHandler( - configuration=self._configuration, - file_path=file_path, - increment_error_count=increment, - line_numbers=line_numbers) - else: - handle_style_error = mock_handle_style_error - - os_path_exists = (os.path.exists if mock_os_path_exists is None else - mock_os_path_exists) - process_file = (self._process_file if mock_process_file is None else - mock_process_file) - - if not os_path_exists(file_path) and file_path != "-": - _log.error("File does not exist: %s" % file_path) - sys.exit(1) + _log.debug("Checking style: " + file_path) - _log.debug("Checking: " + file_path) + style_error_handler = DefaultStyleErrorHandler( + configuration=self._configuration, + file_path=file_path, + increment_error_count=self._increment_error_count, + line_numbers=line_numbers) - self.file_count += 1 + carriage_checker = self._carriage_checker_class(style_error_handler) - dispatcher = ProcessorDispatcher() - - if dispatcher.should_skip_without_warning(file_path): - return - if dispatcher.should_skip_with_warning(file_path): - _log.warn('File exempt from style guide. Skipping: "%s"' - % file_path) - return + # FIXME: We should probably use the SVN "eol-style" property + # or a white list to decide whether or not to do + # the carriage-return check. Originally, we did the + # check only if (os.linesep != '\r\n'). + # + # Check for and remove trailing carriage returns ("\r"). + lines = carriage_checker.check(lines) min_confidence = self._configuration.min_confidence - processor = dispatcher.dispatch_processor(file_path, - handle_style_error, - min_confidence) - if processor is None: - _log.debug('File not a recognized type to check. Skipping: "%s"' - % file_path) - return + checker = self._dispatcher.dispatch(file_path, + style_error_handler, + min_confidence) + + if checker is None: + raise AssertionError("File should not be checked: '%s'" % file_path) - _log.debug("Using class: " + processor.__class__.__name__) + _log.debug("Using class: " + checker.__class__.__name__) - process_file(processor, file_path, handle_style_error) + checker.check(lines) -class PatchChecker(object): +class PatchReader(object): """Supports checking style in patches.""" - def __init__(self, style_checker): - """Create a PatchChecker instance. + def __init__(self, text_file_reader): + """Create a PatchReader instance. Args: - style_checker: A StyleChecker instance. + text_file_reader: A TextFileReader instance. """ - self._file_checker = style_checker + self._text_file_reader = text_file_reader def check(self, patch_string): """Check style in the given patch.""" @@ -775,5 +734,5 @@ class PatchChecker(object): # This optimization also prevents the program from exiting # due to a deleted file. if line_numbers: - self._file_checker.check_file(file_path=path, - line_numbers=line_numbers) + self._text_file_reader.process_file(file_path=path, + line_numbers=line_numbers) diff --git a/WebKitTools/Scripts/webkitpy/style/checker_unittest.py b/WebKitTools/Scripts/webkitpy/style/checker_unittest.py index 401a7b3..6e1eaa2 100755 --- a/WebKitTools/Scripts/webkitpy/style/checker_unittest.py +++ b/WebKitTools/Scripts/webkitpy/style/checker_unittest.py @@ -49,18 +49,21 @@ from checker import _all_categories from checker import check_webkit_style_configuration from checker import check_webkit_style_parser from checker import configure_logging -from checker import ProcessorDispatcher -from checker import PatchChecker -from checker import StyleChecker -from checker import StyleCheckerConfiguration +from checker import CheckerDispatcher +from checker import PatchReader +from checker import ProcessorBase +from checker import StyleProcessor +from checker import StyleProcessorConfiguration +from checkers.cpp import CppChecker +from checkers.python import PythonChecker +from checkers.text import TextChecker +from error_handlers import DefaultStyleErrorHandler from filter import validate_filter_rules from filter import FilterConfiguration from optparser import ArgumentParser from optparser import CommandOptionValues -from processors.cpp import CppProcessor -from processors.python import PythonProcessor -from processors.text import TextProcessor from webkitpy.common.system.logtesting import LoggingTestCase +from webkitpy.style.filereader import TextFileReader class ConfigureLoggingTestBase(unittest.TestCase): @@ -265,16 +268,17 @@ class CheckWebKitStyleFunctionTest(unittest.TestCase): parser = check_webkit_style_parser() -class ProcessorDispatcherSkipTest(unittest.TestCase): +class CheckerDispatcherSkipTest(unittest.TestCase): - """Tests the "should skip" methods of the ProcessorDispatcher class.""" + """Tests the "should skip" methods of the CheckerDispatcher class.""" + + def setUp(self): + self._dispatcher = CheckerDispatcher() def test_should_skip_with_warning(self): """Test should_skip_with_warning().""" - dispatcher = ProcessorDispatcher() - # Check a non-skipped file. - self.assertFalse(dispatcher.should_skip_with_warning("foo.txt")) + self.assertFalse(self._dispatcher.should_skip_with_warning("foo.txt")) # Check skipped files. paths_to_skip = [ @@ -289,51 +293,72 @@ class ProcessorDispatcherSkipTest(unittest.TestCase): ] for path in paths_to_skip: - self.assertTrue(dispatcher.should_skip_with_warning(path), + self.assertTrue(self._dispatcher.should_skip_with_warning(path), "Checking: " + path) - def test_should_skip_without_warning(self): - """Test should_skip_without_warning().""" - dispatcher = ProcessorDispatcher() - - # Check a non-skipped file. - self.assertFalse(dispatcher.should_skip_without_warning("foo.txt")) - - # Check skipped files. - paths_to_skip = [ - # LayoutTests folder - "LayoutTests/foo.txt", - ] + def _assert_should_skip_without_warning(self, path, is_checker_none, + expected): + # Check the file type before asserting the return value. + checker = self._dispatcher.dispatch(file_path=path, + handle_style_error=None, + min_confidence=3) + message = 'while checking: %s' % path + self.assertEquals(checker is None, is_checker_none, message) + self.assertEquals(self._dispatcher.should_skip_without_warning(path), + expected, message) + + def test_should_skip_without_warning__true(self): + """Test should_skip_without_warning() for True return values.""" + # Check a file with NONE file type. + path = 'foo.asdf' # Non-sensical file extension. + self._assert_should_skip_without_warning(path, + is_checker_none=True, + expected=True) + + # Check files with non-NONE file type. These examples must be + # drawn from the _SKIPPED_FILES_WITHOUT_WARNING configuration + # variable. + path = os.path.join('LayoutTests', 'foo.txt') + self._assert_should_skip_without_warning(path, + is_checker_none=False, + expected=True) + + def test_should_skip_without_warning__false(self): + """Test should_skip_without_warning() for False return values.""" + paths = ['foo.txt', + os.path.join('LayoutTests', 'ChangeLog'), + ] - for path in paths_to_skip: - self.assertTrue(dispatcher.should_skip_without_warning(path), - "Checking: " + path) + for path in paths: + self._assert_should_skip_without_warning(path, + is_checker_none=False, + expected=False) -class ProcessorDispatcherDispatchTest(unittest.TestCase): +class CheckerDispatcherDispatchTest(unittest.TestCase): - """Tests dispatch_processor() method of ProcessorDispatcher class.""" + """Tests dispatch() method of CheckerDispatcher class.""" def mock_handle_style_error(self): pass - def dispatch_processor(self, file_path): - """Call dispatch_processor() with the given file path.""" - dispatcher = ProcessorDispatcher() - processor = dispatcher.dispatch_processor(file_path, - self.mock_handle_style_error, - min_confidence=3) - return processor - - def assert_processor_none(self, file_path): - """Assert that the dispatched processor is None.""" - processor = self.dispatch_processor(file_path) - self.assertTrue(processor is None, 'Checking: "%s"' % file_path) - - def assert_processor(self, file_path, expected_class): - """Assert the type of the dispatched processor.""" - processor = self.dispatch_processor(file_path) - got_class = processor.__class__ + def dispatch(self, file_path): + """Call dispatch() with the given file path.""" + dispatcher = CheckerDispatcher() + checker = dispatcher.dispatch(file_path, + self.mock_handle_style_error, + min_confidence=3) + return checker + + def assert_checker_none(self, file_path): + """Assert that the dispatched checker is None.""" + checker = self.dispatch(file_path) + self.assertTrue(checker is None, 'Checking: "%s"' % file_path) + + def assert_checker(self, file_path, expected_class): + """Assert the type of the dispatched checker.""" + checker = self.dispatch(file_path) + got_class = checker.__class__ self.assertEquals(got_class, expected_class, 'For path "%(file_path)s" got %(got_class)s when ' "expecting %(expected_class)s." @@ -341,17 +366,17 @@ class ProcessorDispatcherDispatchTest(unittest.TestCase): "got_class": got_class, "expected_class": expected_class}) - def assert_processor_cpp(self, file_path): - """Assert that the dispatched processor is a CppProcessor.""" - self.assert_processor(file_path, CppProcessor) + def assert_checker_cpp(self, file_path): + """Assert that the dispatched checker is a CppChecker.""" + self.assert_checker(file_path, CppChecker) - def assert_processor_python(self, file_path): - """Assert that the dispatched processor is a PythonProcessor.""" - self.assert_processor(file_path, PythonProcessor) + def assert_checker_python(self, file_path): + """Assert that the dispatched checker is a PythonChecker.""" + self.assert_checker(file_path, PythonChecker) - def assert_processor_text(self, file_path): - """Assert that the dispatched processor is a TextProcessor.""" - self.assert_processor(file_path, TextProcessor) + def assert_checker_text(self, file_path): + """Assert that the dispatched checker is a TextChecker.""" + self.assert_checker(file_path, TextChecker) def test_cpp_paths(self): """Test paths that should be checked as C++.""" @@ -363,26 +388,26 @@ class ProcessorDispatcherDispatchTest(unittest.TestCase): ] for path in paths: - self.assert_processor_cpp(path) + self.assert_checker_cpp(path) - # Check processor attributes on a typical input. + # Check checker attributes on a typical input. file_base = "foo" file_extension = "c" file_path = file_base + "." + file_extension - self.assert_processor_cpp(file_path) - processor = self.dispatch_processor(file_path) - self.assertEquals(processor.file_extension, file_extension) - self.assertEquals(processor.file_path, file_path) - self.assertEquals(processor.handle_style_error, self.mock_handle_style_error) - self.assertEquals(processor.min_confidence, 3) + self.assert_checker_cpp(file_path) + checker = self.dispatch(file_path) + self.assertEquals(checker.file_extension, file_extension) + self.assertEquals(checker.file_path, file_path) + self.assertEquals(checker.handle_style_error, self.mock_handle_style_error) + self.assertEquals(checker.min_confidence, 3) # Check "-" for good measure. file_base = "-" file_extension = "" file_path = file_base - self.assert_processor_cpp(file_path) - processor = self.dispatch_processor(file_path) - self.assertEquals(processor.file_extension, file_extension) - self.assertEquals(processor.file_path, file_path) + self.assert_checker_cpp(file_path) + checker = self.dispatch(file_path) + self.assertEquals(checker.file_extension, file_extension) + self.assertEquals(checker.file_path, file_path) def test_python_paths(self): """Test paths that should be checked as Python.""" @@ -392,63 +417,81 @@ class ProcessorDispatcherDispatchTest(unittest.TestCase): ] for path in paths: - self.assert_processor_python(path) + self.assert_checker_python(path) - # Check processor attributes on a typical input. + # Check checker attributes on a typical input. file_base = "foo" file_extension = "css" file_path = file_base + "." + file_extension - self.assert_processor_text(file_path) - processor = self.dispatch_processor(file_path) - self.assertEquals(processor.file_path, file_path) - self.assertEquals(processor.handle_style_error, + self.assert_checker_text(file_path) + checker = self.dispatch(file_path) + self.assertEquals(checker.file_path, file_path) + self.assertEquals(checker.handle_style_error, self.mock_handle_style_error) def test_text_paths(self): """Test paths that should be checked as text.""" paths = [ "ChangeLog", + "ChangeLog-2009-06-16", + "foo.ac", + "foo.cc", + "foo.cgi", "foo.css", + "foo.exp", + "foo.flex", + "foo.gyp", + "foo.gypi", "foo.html", "foo.idl", + "foo.in", "foo.js", "foo.mm", "foo.php", + "foo.pl", "foo.pm", + "foo.pri", + "foo.pro", + "foo.rb", + "foo.sh", "foo.txt", - "FooChangeLog.bak", - "WebCore/ChangeLog", - "WebCore/inspector/front-end/inspector.js", - "WebKitTools/Scripts/check-webkit-style", + "foo.wm", + "foo.xhtml", + "foo.y", + os.path.join("WebCore", "ChangeLog"), + os.path.join("WebCore", "inspector", "front-end", "inspector.js"), + os.path.join("WebKitTools", "Scripts", "check-webkit-style"), ] for path in paths: - self.assert_processor_text(path) + self.assert_checker_text(path) - # Check processor attributes on a typical input. + # Check checker attributes on a typical input. file_base = "foo" file_extension = "css" file_path = file_base + "." + file_extension - self.assert_processor_text(file_path) - processor = self.dispatch_processor(file_path) - self.assertEquals(processor.file_path, file_path) - self.assertEquals(processor.handle_style_error, self.mock_handle_style_error) + self.assert_checker_text(file_path) + checker = self.dispatch(file_path) + self.assertEquals(checker.file_path, file_path) + self.assertEquals(checker.handle_style_error, self.mock_handle_style_error) def test_none_paths(self): """Test paths that have no file type..""" paths = [ "Makefile", + "foo.asdf", # Non-sensical file extension. "foo.png", "foo.exe", + "foo.vcproj", ] for path in paths: - self.assert_processor_none(path) + self.assert_checker_none(path) -class StyleCheckerConfigurationTest(unittest.TestCase): +class StyleProcessorConfigurationTest(unittest.TestCase): - """Tests the StyleCheckerConfiguration class.""" + """Tests the StyleProcessorConfiguration class.""" def setUp(self): self._error_messages = [] @@ -458,11 +501,11 @@ class StyleCheckerConfigurationTest(unittest.TestCase): self._error_messages.append(message) def _style_checker_configuration(self, output_format="vs7"): - """Return a StyleCheckerConfiguration instance for testing.""" + """Return a StyleProcessorConfiguration instance for testing.""" base_rules = ["-whitespace", "+whitespace/tab"] filter_configuration = FilterConfiguration(base_rules=base_rules) - return StyleCheckerConfiguration( + return StyleProcessorConfiguration( filter_configuration=filter_configuration, max_reports_per_category={"whitespace/newline": 1}, min_confidence=3, @@ -512,277 +555,246 @@ class StyleCheckerConfigurationTest(unittest.TestCase): ["foo.h(100): message [whitespace/tab] [5]\n"]) -class StyleCheckerTest(unittest.TestCase): +class StyleProcessor_EndToEndTest(LoggingTestCase): - """Test the StyleChecker class.""" + """Test the StyleProcessor class with an emphasis on end-to-end tests.""" - def _mock_stderr_write(self, message): - pass + def setUp(self): + LoggingTestCase.setUp(self) + self._messages = [] - def _style_checker(self, configuration): - return StyleChecker(configuration) + def _mock_stderr_write(self, message): + """Save a message so it can later be asserted.""" + self._messages.append(message) def test_init(self): """Test __init__ constructor.""" - configuration = StyleCheckerConfiguration( + configuration = StyleProcessorConfiguration( filter_configuration=FilterConfiguration(), max_reports_per_category={}, min_confidence=3, output_format="vs7", stderr_write=self._mock_stderr_write) + processor = StyleProcessor(configuration) - style_checker = self._style_checker(configuration) - - self.assertEquals(style_checker._configuration, configuration) - self.assertEquals(style_checker.error_count, 0) - self.assertEquals(style_checker.file_count, 0) - - -class StyleCheckerCheckFileBase(LoggingTestCase): - - def setUp(self): - LoggingTestCase.setUp(self) - self.warning_messages = "" - - def mock_stderr_write(self, warning_message): - self.warning_messages += warning_message - - def _style_checker_configuration(self): - return StyleCheckerConfiguration( - filter_configuration=FilterConfiguration(), - max_reports_per_category={"whitespace/newline": 1}, - min_confidence=3, - output_format="vs7", - stderr_write=self.mock_stderr_write) + self.assertEquals(processor.error_count, 0) + self.assertEquals(self._messages, []) + def test_process(self): + configuration = StyleProcessorConfiguration( + filter_configuration=FilterConfiguration(), + max_reports_per_category={}, + min_confidence=3, + output_format="vs7", + stderr_write=self._mock_stderr_write) + processor = StyleProcessor(configuration) -class StyleCheckerCheckFileTest(StyleCheckerCheckFileBase): + processor.process(lines=['line1', 'Line with tab:\t'], + file_path='foo.txt') + self.assertEquals(processor.error_count, 1) + expected_messages = ['foo.txt(2): Line contains tab character. ' + '[whitespace/tab] [5]\n'] + self.assertEquals(self._messages, expected_messages) - """Test the check_file() method of the StyleChecker class. - The check_file() method calls its process_file parameter when - given a file that should not be skipped. +class StyleProcessor_CodeCoverageTest(LoggingTestCase): - The "got_*" attributes of this class are the parameters passed - to process_file by calls to check_file() made by this test - class. These attributes allow us to check the parameter values - passed internally to the process_file function. + """Test the StyleProcessor class with an emphasis on code coverage. - Attributes: - got_file_path: The file_path parameter passed by check_file() - to its process_file parameter. - got_handle_style_error: The handle_style_error parameter passed - by check_file() to its process_file - parameter. - got_processor: The processor parameter passed by check_file() to - its process_file parameter. - warning_messages: A string containing all of the warning messages - written to the mock_stderr_write method of - this class. + This class makes heavy use of mock objects. """ - def setUp(self): - StyleCheckerCheckFileBase.setUp(self) - self.got_file_path = None - self.got_handle_style_error = None - self.got_processor = None - def mock_handle_style_error(self): - pass - - def mock_os_path_exists(self, path): - # We deliberately make it so that this method returns False unless - # the caller has made an effort to put "does_exist" in the path. - return path.find("does_exist") > -1 - - def mock_process_file(self, processor, file_path, handle_style_error): - """A mock _process_file(). + class MockDispatchedChecker(object): - See the documentation for this class for more information - on this function. + """A mock checker dispatched by the MockDispatcher.""" - """ - self.got_file_path = file_path - self.got_handle_style_error = handle_style_error - self.got_processor = processor - - def assert_attributes(self, - expected_file_path, - expected_handle_style_error, - expected_processor, - expected_warning_messages): - """Assert that the attributes of this class equal the given values.""" - self.assertEquals(self.got_file_path, expected_file_path) - self.assertEquals(self.got_handle_style_error, expected_handle_style_error) - self.assertEquals(self.got_processor, expected_processor) - self.assertEquals(self.warning_messages, expected_warning_messages) - - def call_check_file(self, file_path): - """Call the check_file() method of a test StyleChecker instance.""" - # Confirm that the attributes are reset. - self.assert_attributes(None, None, None, "") - - configuration = self._style_checker_configuration() + def __init__(self, file_path, min_confidence, style_error_handler): + self.file_path = file_path + self.min_confidence = min_confidence + self.style_error_handler = style_error_handler - style_checker = StyleChecker(configuration) + def check(self, lines): + self.lines = lines - style_checker.check_file(file_path=file_path, - mock_handle_style_error=self.mock_handle_style_error, - mock_os_path_exists=self.mock_os_path_exists, - mock_process_file=self.mock_process_file) + class MockDispatcher(object): - self.assertEquals(style_checker.file_count, 1) + """A mock CheckerDispatcher class.""" - def test_check_file_does_not_exist(self): - file_path = "file_does_not_exist.txt" - - # Confirm that the file does not exist. - self.assertFalse(self.mock_os_path_exists(file_path)) + def __init__(self): + self.dispatched_checker = None - # Check the outcome. - self.assertRaises(SystemExit, self.call_check_file, file_path) - self.assertLog(["ERROR: File does not exist: " - "file_does_not_exist.txt\n"]) + def should_skip_with_warning(self, file_path): + return file_path.endswith('skip_with_warning.txt') - def test_check_file_stdin(self): - file_path = "-" + def should_skip_without_warning(self, file_path): + return file_path.endswith('skip_without_warning.txt') - # Confirm that the file does not exist. - self.assertFalse(self.mock_os_path_exists(file_path)) + def dispatch(self, file_path, style_error_handler, min_confidence): + if file_path.endswith('do_not_process.txt'): + return None - # Check the outcome. - self.call_check_file(file_path) - expected_processor = CppProcessor(file_path, - "", - self.mock_handle_style_error, 3) - self.assert_attributes(file_path, - self.mock_handle_style_error, - expected_processor, - "") + checker = StyleProcessor_CodeCoverageTest.MockDispatchedChecker( + file_path, + min_confidence, + style_error_handler) - def test_check_file_on_skip_without_warning(self): - """Test check_file() for a skipped-without-warning file.""" + # Save the dispatched checker so the current test case has a + # way to access and check it. + self.dispatched_checker = checker - file_path = "LayoutTests/does_exist/foo.txt" + return checker - dispatcher = ProcessorDispatcher() - # Confirm that the input file is truly a skipped-without-warning file. - self.assertTrue(dispatcher.should_skip_without_warning(file_path)) + def setUp(self): + LoggingTestCase.setUp(self) + # We can pass an error-message swallower here because error message + # output is tested instead in the end-to-end test case above. + configuration = StyleProcessorConfiguration( + filter_configuration=FilterConfiguration(), + max_reports_per_category={"whitespace/newline": 1}, + min_confidence=3, + output_format="vs7", + stderr_write=self._swallow_stderr_message) + + mock_carriage_checker_class = self._create_carriage_checker_class() + mock_dispatcher = self.MockDispatcher() + # We do not need to use a real incrementer here because error-count + # incrementing is tested instead in the end-to-end test case above. + mock_increment_error_count = self._do_nothing + + processor = StyleProcessor(configuration=configuration, + mock_carriage_checker_class=mock_carriage_checker_class, + mock_dispatcher=mock_dispatcher, + mock_increment_error_count=mock_increment_error_count) + + self._configuration = configuration + self._mock_dispatcher = mock_dispatcher + self._processor = processor + + def _do_nothing(self): + # We provide this function so the caller can pass it to the + # StyleProcessor constructor. This lets us assert the equality of + # the DefaultStyleErrorHandler instance generated by the process() + # method with an expected instance. + pass - # Check the outcome. - self.call_check_file(file_path) - self.assert_attributes(None, None, None, "") + def _swallow_stderr_message(self, message): + """Swallow a message passed to stderr.write().""" + # This is a mock stderr.write() for passing to the constructor + # of the StyleProcessorConfiguration class. + pass - def test_check_file_on_skip_with_warning(self): - """Test check_file() for a skipped-with-warning file.""" + def _create_carriage_checker_class(self): - file_path = "does_exist/gtk2drawing.c" + # Create a reference to self with a new name so its name does not + # conflict with the self introduced below. + test_case = self - dispatcher = ProcessorDispatcher() - # Check that the input file is truly a skipped-with-warning file. - self.assertTrue(dispatcher.should_skip_with_warning(file_path)) + class MockCarriageChecker(object): - # Check the outcome. - self.call_check_file(file_path) - self.assert_attributes(None, None, None, "") - self.assertLog(["WARNING: File exempt from style guide. " - 'Skipping: "does_exist/gtk2drawing.c"\n']) + """A mock carriage-return checker.""" - def test_check_file_on_non_skipped(self): + def __init__(self, style_error_handler): + self.style_error_handler = style_error_handler - # We use a C++ file since by using a CppProcessor, we can check - # that all of the possible information is getting passed to - # process_file (in particular, the min_confidence parameter). - file_base = "foo_does_exist" - file_extension = "cpp" - file_path = file_base + "." + file_extension + # This gives the current test case access to the + # instantiated carriage checker. + test_case.carriage_checker = self - dispatcher = ProcessorDispatcher() - # Check that the input file is truly a C++ file. - self.assertEquals(dispatcher._file_type(file_path), style.FileType.CPP) + def check(self, lines): + # Save the lines so the current test case has a way to access + # and check them. + self.lines = lines - # Check the outcome. - self.call_check_file(file_path) + return lines - expected_processor = CppProcessor(file_path, file_extension, self.mock_handle_style_error, 3) + return MockCarriageChecker - self.assert_attributes(file_path, - self.mock_handle_style_error, - expected_processor, - "") + def test_should_process__skip_without_warning(self): + """Test should_process() for a skip-without-warning file.""" + file_path = "foo/skip_without_warning.txt" + self.assertFalse(self._processor.should_process(file_path)) -class StyleCheckerCheckPathsTest(unittest.TestCase): + def test_should_process__skip_with_warning(self): + """Test should_process() for a skip-with-warning file.""" + file_path = "foo/skip_with_warning.txt" - """Test the check_paths() method of the StyleChecker class.""" + self.assertFalse(self._processor.should_process(file_path)) - class MockOs(object): + self.assertLog(['WARNING: File exempt from style guide. ' + 'Skipping: "foo/skip_with_warning.txt"\n']) - class MockPath(object): + def test_should_process__true_result(self): + """Test should_process() for a file that should be processed.""" + file_path = "foo/skip_process.txt" - """A mock os.path.""" + self.assertTrue(self._processor.should_process(file_path)) - def isdir(self, path): - return path == "directory" + def test_process__checker_dispatched(self): + """Test the process() method for a path with a dispatched checker.""" + file_path = 'foo.txt' + lines = ['line1', 'line2'] + line_numbers = [100] - def __init__(self): - self.path = self.MockPath() + expected_error_handler = DefaultStyleErrorHandler( + configuration=self._configuration, + file_path=file_path, + increment_error_count=self._do_nothing, + line_numbers=line_numbers) - def walk(self, directory): - """A mock of os.walk.""" - if directory == "directory": - dirs = [("dir_path1", [], ["file1", "file2"]), - ("dir_path2", [], ["file3"])] - return dirs - return None + self._processor.process(lines=lines, + file_path=file_path, + line_numbers=line_numbers) - def setUp(self): - self._checked_files = [] + # Check that the carriage-return checker was instantiated correctly + # and was passed lines correctly. + carriage_checker = self.carriage_checker + self.assertEquals(carriage_checker.style_error_handler, + expected_error_handler) + self.assertEquals(carriage_checker.lines, ['line1', 'line2']) - def _mock_check_file(self, file): - self._checked_files.append(file) + # Check that the style checker was dispatched correctly and was + # passed lines correctly. + checker = self._mock_dispatcher.dispatched_checker + self.assertEquals(checker.file_path, 'foo.txt') + self.assertEquals(checker.min_confidence, 3) + self.assertEquals(checker.style_error_handler, expected_error_handler) - def test_check_paths(self): - """Test StyleChecker.check_paths().""" - checker = StyleChecker(configuration=None) - mock_check_file = self._mock_check_file - mock_os = self.MockOs() + self.assertEquals(checker.lines, ['line1', 'line2']) - # Confirm that checked files is empty at the outset. - self.assertEquals(self._checked_files, []) - checker.check_paths(["path1", "directory"], - mock_check_file=mock_check_file, - mock_os=mock_os) - self.assertEquals(self._checked_files, - ["path1", - os.path.join("dir_path1", "file1"), - os.path.join("dir_path1", "file2"), - os.path.join("dir_path2", "file3")]) + def test_process__no_checker_dispatched(self): + """Test the process() method for a path with no dispatched checker.""" + path = os.path.join('foo', 'do_not_process.txt') + self.assertRaises(AssertionError, self._processor.process, + lines=['line1', 'line2'], file_path=path, + line_numbers=[100]) -class PatchCheckerTest(unittest.TestCase): +class PatchReaderTest(unittest.TestCase): - """Test the PatchChecker class.""" + """Test the PatchReader class.""" - class MockStyleChecker(object): + class MockTextFileReader(object): def __init__(self): - self.checked_files = [] + self.passed_to_process_file = [] """A list of (file_path, line_numbers) pairs.""" - def check_file(self, file_path, line_numbers): - self.checked_files.append((file_path, line_numbers)) + def process_file(self, file_path, line_numbers): + self.passed_to_process_file.append((file_path, line_numbers)) def setUp(self): - style_checker = self.MockStyleChecker() - self._style_checker = style_checker - self._patch_checker = PatchChecker(style_checker) + file_reader = self.MockTextFileReader() + self._file_reader = file_reader + self._patch_checker = PatchReader(file_reader) def _call_check_patch(self, patch_string): self._patch_checker.check(patch_string) - def _assert_checked(self, checked_files): - self.assertEquals(self._style_checker.checked_files, checked_files) + def _assert_checked(self, passed_to_process_file): + self.assertEquals(self._file_reader.passed_to_process_file, + passed_to_process_file) def test_check_patch(self): # The modified line_numbers array for this patch is: [2]. diff --git a/WebKitTools/Scripts/webkitpy/style/processors/__init__.py b/WebKitTools/Scripts/webkitpy/style/checkers/__init__.py index ef65bee..ef65bee 100644 --- a/WebKitTools/Scripts/webkitpy/style/processors/__init__.py +++ b/WebKitTools/Scripts/webkitpy/style/checkers/__init__.py diff --git a/WebKitTools/Scripts/webkitpy/style/processors/common.py b/WebKitTools/Scripts/webkitpy/style/checkers/common.py index 30b8fed..a2d933f 100644 --- a/WebKitTools/Scripts/webkitpy/style/processors/common.py +++ b/WebKitTools/Scripts/webkitpy/style/checkers/common.py @@ -23,7 +23,7 @@ """Supports style checking not specific to any one file type.""" -# FIXME: Test this list in the same way that the list of CppProcessor +# FIXME: Test this list in the same way that the list of CppChecker # categories is tested, for example by checking that all of its # elements appear in the unit tests. This should probably be done # after moving the relevant cpp_unittest.ErrorCollector code @@ -33,14 +33,14 @@ categories = set([ ]) -class CarriageReturnProcessor(object): +class CarriageReturnChecker(object): """Supports checking for and handling carriage returns.""" def __init__(self, handle_style_error): self._handle_style_error = handle_style_error - def process(self, lines): + def check(self, lines): """Check for and strip trailing carriage returns from lines.""" for line_number in range(len(lines)): if not lines[line_number].endswith("\r"): diff --git a/WebKitTools/Scripts/webkitpy/style/processors/common_unittest.py b/WebKitTools/Scripts/webkitpy/style/checkers/common_unittest.py index 3dde7b9..b67b7b0 100644 --- a/WebKitTools/Scripts/webkitpy/style/processors/common_unittest.py +++ b/WebKitTools/Scripts/webkitpy/style/checkers/common_unittest.py @@ -24,16 +24,16 @@ import unittest -from common import CarriageReturnProcessor +from common import CarriageReturnChecker -# FIXME: The unit tests for the cpp, text, and common processors should +# FIXME: The unit tests for the cpp, text, and common checkers should # share supporting test code. This can include, for example, the # mock style error handling code and the code to check that all -# of a processor's categories are covered by the unit tests. +# of a checker's categories are covered by the unit tests. # Such shared code can be located in a shared test file, perhaps # even this file. -class CarriageReturnProcessorTest(unittest.TestCase): +class CarriageReturnCheckerTest(unittest.TestCase): """Tests check_no_carriage_return().""" @@ -55,8 +55,8 @@ class CarriageReturnProcessorTest(unittest.TestCase): """Process the given line and assert that the result is correct.""" handle_style_error = self._mock_style_error_handler - processor = CarriageReturnProcessor(handle_style_error) - output_lines = processor.process(input_lines) + checker = CarriageReturnChecker(handle_style_error) + output_lines = checker.check(input_lines) # Check both the return value and error messages. self.assertEquals(output_lines, expected_lines) @@ -82,7 +82,7 @@ class CarriageReturnProcessorTest(unittest.TestCase): []) def test_carriage_in_middle(self): - # The CarriageReturnProcessor checks only the final character + # The CarriageReturnChecker checks only the final character # of each line. self.assert_carriage_return(["carriage\r in a string"], ["carriage\r in a string"], diff --git a/WebKitTools/Scripts/webkitpy/style/processors/cpp.py b/WebKitTools/Scripts/webkitpy/style/checkers/cpp.py index 23be9f9..3e787d6 100644 --- a/WebKitTools/Scripts/webkitpy/style/processors/cpp.py +++ b/WebKitTools/Scripts/webkitpy/style/checkers/cpp.py @@ -2499,6 +2499,10 @@ def check_identifier_name_in_declaration(filename, line_number, line, error): and not modified_identifier == "const_iterator"): error(line_number, 'readability/naming', 4, identifier + " is incorrectly named. Don't use underscores in your identifier names.") + # Check for variables named 'l', these are too easy to confuse with '1' in some fonts + if modified_identifier == 'l': + error(line_number, 'readability/naming', 4, identifier + " is incorrectly named. Don't use the single letter 'l' as an identifier name.") + # There can be only one declaration in non-for-control statements. if control_statement: return @@ -2511,7 +2515,6 @@ def check_identifier_name_in_declaration(filename, line_number, line, error): number_of_identifiers += 1 line = line[matched.end():] - def check_c_style_cast(line_number, line, raw_line, cast_type, pattern, error): """Checks for a C-style cast by looking for the pattern. @@ -2877,7 +2880,7 @@ def _process_lines(filename, file_extension, lines, error, min_confidence): check_for_new_line_at_eof(lines, error) -class CppProcessor(object): +class CppChecker(object): """Processes C++ lines for checking style.""" @@ -2952,7 +2955,7 @@ class CppProcessor(object): def __init__(self, file_path, file_extension, handle_style_error, min_confidence): - """Create a CppProcessor instance. + """Create a CppChecker instance. Args: file_extension: A string that is the file extension, without @@ -2966,7 +2969,7 @@ class CppProcessor(object): # Useful for unit testing. def __eq__(self, other): - """Return whether this CppProcessor instance is equal to another.""" + """Return whether this CppChecker instance is equal to another.""" if self.file_extension != other.file_extension: return False if self.file_path != other.file_path: @@ -2983,12 +2986,12 @@ class CppProcessor(object): # Python does not automatically deduce __ne__() from __eq__(). return not self.__eq__(other) - def process(self, lines): + def check(self, lines): _process_lines(self.file_path, self.file_extension, lines, self.handle_style_error, self.min_confidence) # FIXME: Remove this function (requires refactoring unit tests). def process_file_data(filename, file_extension, lines, error, min_confidence): - processor = CppProcessor(filename, file_extension, error, min_confidence) - processor.process(lines) + checker = CppChecker(filename, file_extension, error, min_confidence) + checker.check(lines) diff --git a/WebKitTools/Scripts/webkitpy/style/processors/cpp_unittest.py b/WebKitTools/Scripts/webkitpy/style/checkers/cpp_unittest.py index 0a3fe08..5a5aabd 100644 --- a/WebKitTools/Scripts/webkitpy/style/processors/cpp_unittest.py +++ b/WebKitTools/Scripts/webkitpy/style/checkers/cpp_unittest.py @@ -42,13 +42,13 @@ import random import re import unittest import cpp as cpp_style -from cpp import CppProcessor +from cpp import CppChecker # This class works as an error collector and replaces cpp_style.Error # function for the unit tests. We also verify each category we see # is in STYLE_CATEGORIES, to help keep that list up to date. class ErrorCollector: - _all_style_categories = CppProcessor.categories + _all_style_categories = CppChecker.categories # This is a list including all categories seen in any unit test. _seen_style_categories = {} @@ -3538,7 +3538,8 @@ class WebKitStyleTest(CppStyleTestBase): 'foo.h') def test_names(self): - name_error_message = " is incorrectly named. Don't use underscores in your identifier names. [readability/naming] [4]" + name_underscore_error_message = " is incorrectly named. Don't use underscores in your identifier names. [readability/naming] [4]" + name_tooshort_error_message = " is incorrectly named. Don't use the single letter 'l' as an identifier name. [readability/naming] [4]" # Basic cases from WebKit style guide. self.assert_lint('struct Data;', '') @@ -3546,60 +3547,65 @@ class WebKitStyleTest(CppStyleTestBase): self.assert_lint('class HTMLDocument;', '') self.assert_lint('String mimeType();', '') self.assert_lint('size_t buffer_size;', - 'buffer_size' + name_error_message) + 'buffer_size' + name_underscore_error_message) self.assert_lint('short m_length;', '') self.assert_lint('short _length;', - '_length' + name_error_message) + '_length' + name_underscore_error_message) self.assert_lint('short length_;', - 'length_' + name_error_message) + 'length_' + name_underscore_error_message) self.assert_lint('unsigned _length;', - '_length' + name_error_message) + '_length' + name_underscore_error_message) self.assert_lint('unsigned int _length;', - '_length' + name_error_message) + '_length' + name_underscore_error_message) self.assert_lint('unsigned long long _length;', - '_length' + name_error_message) + '_length' + name_underscore_error_message) + + # Variable name 'l' is easy to confuse with '1' + self.assert_lint('int l;', 'l' + name_tooshort_error_message) + self.assert_lint('size_t l;', 'l' + name_tooshort_error_message) + self.assert_lint('long long l;', 'l' + name_tooshort_error_message) # Pointers, references, functions, templates, and adjectives. self.assert_lint('char* under_score;', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('const int UNDER_SCORE;', - 'UNDER_SCORE' + name_error_message) + 'UNDER_SCORE' + name_underscore_error_message) self.assert_lint('static inline const char const& const under_score;', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('WebCore::RenderObject* under_score;', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('int func_name();', - 'func_name' + name_error_message) + 'func_name' + name_underscore_error_message) self.assert_lint('RefPtr<RenderObject*> under_score;', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('WTF::Vector<WTF::RefPtr<const RenderObject* const> > under_score;', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('int under_score[];', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('struct dirent* under_score;', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('long under_score;', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('long long under_score;', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('long double under_score;', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('long long int under_score;', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) # Declarations in control statement. self.assert_lint('if (int under_score = 42) {', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('else if (int under_score = 42) {', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('for (int under_score = 42; cond; i++) {', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('while (foo & under_score = bar) {', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('for (foo * under_score = p; cond; i++) {', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('for (foo * under_score; cond; i++) {', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('while (foo & value_in_thirdparty_library) {', '') self.assert_lint('while (foo * value_in_thirdparty_library) {', '') self.assert_lint('if (mli && S_OK == mli->foo()) {', '') @@ -3607,38 +3613,38 @@ class WebKitStyleTest(CppStyleTestBase): # More member variables and functions. self.assert_lint('int SomeClass::s_validName', '') self.assert_lint('int m_under_score;', - 'm_under_score' + name_error_message) + 'm_under_score' + name_underscore_error_message) self.assert_lint('int SomeClass::s_under_score = 0;', - 'SomeClass::s_under_score' + name_error_message) + 'SomeClass::s_under_score' + name_underscore_error_message) self.assert_lint('int SomeClass::under_score = 0;', - 'SomeClass::under_score' + name_error_message) + 'SomeClass::under_score' + name_underscore_error_message) # Other statements. self.assert_lint('return INT_MAX;', '') self.assert_lint('return_t under_score;', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('goto under_score;', - 'under_score' + name_error_message) + 'under_score' + name_underscore_error_message) self.assert_lint('delete static_cast<Foo*>(p);', '') # Multiple variables in one line. self.assert_lint('void myFunction(int variable1, int another_variable);', - 'another_variable' + name_error_message) + 'another_variable' + name_underscore_error_message) self.assert_lint('int variable1, another_variable;', - 'another_variable' + name_error_message) + 'another_variable' + name_underscore_error_message) self.assert_lint('int first_variable, secondVariable;', - 'first_variable' + name_error_message) + 'first_variable' + name_underscore_error_message) self.assert_lint('void my_function(int variable_1, int variable_2);', - ['my_function' + name_error_message, - 'variable_1' + name_error_message, - 'variable_2' + name_error_message]) + ['my_function' + name_underscore_error_message, + 'variable_1' + name_underscore_error_message, + 'variable_2' + name_underscore_error_message]) self.assert_lint('for (int variable_1, variable_2;;) {', - ['variable_1' + name_error_message, - 'variable_2' + name_error_message]) + ['variable_1' + name_underscore_error_message, + 'variable_2' + name_underscore_error_message]) # There is an exception for op code functions but only in the JavaScriptCore directory. self.assert_lint('void this_op_code(int var1, int var2)', '', 'JavaScriptCore/foo.cpp') - self.assert_lint('void this_op_code(int var1, int var2)', 'this_op_code' + name_error_message) + self.assert_lint('void this_op_code(int var1, int var2)', 'this_op_code' + name_underscore_error_message) # GObject requires certain magical names in class declarations. self.assert_lint('void webkit_dom_object_init();', '') @@ -3656,7 +3662,7 @@ class WebKitStyleTest(CppStyleTestBase): # Bitfields. self.assert_lint('unsigned _fillRule : 1;', - '_fillRule' + name_error_message) + '_fillRule' + name_underscore_error_message) def test_comments(self): @@ -3673,52 +3679,52 @@ class WebKitStyleTest(CppStyleTestBase): pass -class CppProcessorTest(unittest.TestCase): +class CppCheckerTest(unittest.TestCase): - """Tests CppProcessor class.""" + """Tests CppChecker class.""" def mock_handle_style_error(self): pass - def _processor(self): - return CppProcessor("foo", "h", self.mock_handle_style_error, 3) + def _checker(self): + return CppChecker("foo", "h", self.mock_handle_style_error, 3) def test_init(self): """Test __init__ constructor.""" - processor = self._processor() - self.assertEquals(processor.file_extension, "h") - self.assertEquals(processor.file_path, "foo") - self.assertEquals(processor.handle_style_error, self.mock_handle_style_error) - self.assertEquals(processor.min_confidence, 3) + checker = self._checker() + self.assertEquals(checker.file_extension, "h") + self.assertEquals(checker.file_path, "foo") + self.assertEquals(checker.handle_style_error, self.mock_handle_style_error) + self.assertEquals(checker.min_confidence, 3) def test_eq(self): """Test __eq__ equality function.""" - processor1 = self._processor() - processor2 = self._processor() + checker1 = self._checker() + checker2 = self._checker() # == calls __eq__. - self.assertTrue(processor1 == processor2) + self.assertTrue(checker1 == checker2) def mock_handle_style_error2(self): pass # Verify that a difference in any argument cause equality to fail. - processor = CppProcessor("foo", "h", self.mock_handle_style_error, 3) - self.assertFalse(processor == CppProcessor("bar", "h", self.mock_handle_style_error, 3)) - self.assertFalse(processor == CppProcessor("foo", "c", self.mock_handle_style_error, 3)) - self.assertFalse(processor == CppProcessor("foo", "h", mock_handle_style_error2, 3)) - self.assertFalse(processor == CppProcessor("foo", "h", self.mock_handle_style_error, 4)) + checker = CppChecker("foo", "h", self.mock_handle_style_error, 3) + self.assertFalse(checker == CppChecker("bar", "h", self.mock_handle_style_error, 3)) + self.assertFalse(checker == CppChecker("foo", "c", self.mock_handle_style_error, 3)) + self.assertFalse(checker == CppChecker("foo", "h", mock_handle_style_error2, 3)) + self.assertFalse(checker == CppChecker("foo", "h", self.mock_handle_style_error, 4)) def test_ne(self): """Test __ne__ inequality function.""" - processor1 = self._processor() - processor2 = self._processor() + checker1 = self._checker() + checker2 = self._checker() # != calls __ne__. # By default, __ne__ always returns true on different objects. # Thus, just check the distinguishing case to verify that the # code defines __ne__. - self.assertFalse(processor1 != processor2) + self.assertFalse(checker1 != checker2) def tearDown(): diff --git a/WebKitTools/Scripts/webkitpy/style/processors/python.py b/WebKitTools/Scripts/webkitpy/style/checkers/python.py index 8ab936d..70d4450 100644 --- a/WebKitTools/Scripts/webkitpy/style/processors/python.py +++ b/WebKitTools/Scripts/webkitpy/style/checkers/python.py @@ -25,7 +25,7 @@ from ...style_references import pep8 -class PythonProcessor(object): +class PythonChecker(object): """Processes text lines for checking style.""" @@ -33,7 +33,7 @@ class PythonProcessor(object): self._file_path = file_path self._handle_style_error = handle_style_error - def process(self, lines): + def check(self, lines): # Initialize pep8.options, which is necessary for # Checker.check_all() to execute. pep8.process_options(arglist=[self._file_path]) diff --git a/WebKitTools/Scripts/webkitpy/style/processors/python_unittest.py b/WebKitTools/Scripts/webkitpy/style/checkers/python_unittest.py index 3ce3311..e003eb8 100644 --- a/WebKitTools/Scripts/webkitpy/style/processors/python_unittest.py +++ b/WebKitTools/Scripts/webkitpy/style/checkers/python_unittest.py @@ -25,25 +25,25 @@ import os import unittest -from python import PythonProcessor +from python import PythonChecker -class PythonProcessorTest(unittest.TestCase): +class PythonCheckerTest(unittest.TestCase): - """Tests the PythonProcessor class.""" + """Tests the PythonChecker class.""" def test_init(self): """Test __init__() method.""" def _mock_handle_style_error(self): pass - processor = PythonProcessor("foo.txt", _mock_handle_style_error) - self.assertEquals(processor._file_path, "foo.txt") - self.assertEquals(processor._handle_style_error, + checker = PythonChecker("foo.txt", _mock_handle_style_error) + self.assertEquals(checker._file_path, "foo.txt") + self.assertEquals(checker._handle_style_error, _mock_handle_style_error) - def test_process(self): - """Test process() method.""" + def test_check(self): + """Test check() method.""" errors = [] def _mock_handle_style_error(line_number, category, confidence, @@ -54,8 +54,8 @@ class PythonProcessorTest(unittest.TestCase): current_dir = os.path.dirname(__file__) file_path = os.path.join(current_dir, "python_unittest_input.py") - processor = PythonProcessor(file_path, _mock_handle_style_error) - processor.process(lines=[]) + checker = PythonChecker(file_path, _mock_handle_style_error) + checker.check(lines=[]) self.assertEquals(len(errors), 1) self.assertEquals(errors[0], diff --git a/WebKitTools/Scripts/webkitpy/style/processors/python_unittest_input.py b/WebKitTools/Scripts/webkitpy/style/checkers/python_unittest_input.py index 9f1d118..9f1d118 100644 --- a/WebKitTools/Scripts/webkitpy/style/processors/python_unittest_input.py +++ b/WebKitTools/Scripts/webkitpy/style/checkers/python_unittest_input.py diff --git a/WebKitTools/Scripts/webkitpy/style/processors/text.py b/WebKitTools/Scripts/webkitpy/style/checkers/text.py index 307e5b8..0d03938 100644 --- a/WebKitTools/Scripts/webkitpy/style/processors/text.py +++ b/WebKitTools/Scripts/webkitpy/style/checkers/text.py @@ -30,7 +30,7 @@ """Checks WebKit style for text files.""" -class TextProcessor(object): +class TextChecker(object): """Processes text lines for checking style.""" @@ -38,7 +38,7 @@ class TextProcessor(object): self.file_path = file_path self.handle_style_error = handle_style_error - def process(self, lines): + def check(self, lines): lines = (["// adjust line numbers to make the first line 1."] + lines) # FIXME: share with cpp_style. @@ -51,6 +51,6 @@ class TextProcessor(object): # FIXME: Remove this function (requires refactoring unit tests). def process_file_data(filename, lines, error): - processor = TextProcessor(filename, error) - processor.process(lines) + checker = TextChecker(filename, error) + checker.check(lines) diff --git a/WebKitTools/Scripts/webkitpy/style/processors/text_unittest.py b/WebKitTools/Scripts/webkitpy/style/checkers/text_unittest.py index 62f825b..ced49a9 100644 --- a/WebKitTools/Scripts/webkitpy/style/processors/text_unittest.py +++ b/WebKitTools/Scripts/webkitpy/style/checkers/text_unittest.py @@ -32,7 +32,7 @@ import unittest import text as text_style -from text import TextProcessor +from text import TextChecker class TextStyleTestCase(unittest.TestCase): """TestCase for text_style.py""" @@ -76,18 +76,18 @@ class TextStyleTestCase(unittest.TestCase): '\tReviewed by NOBODY.'], 3) -class TextProcessorTest(unittest.TestCase): +class TextCheckerTest(unittest.TestCase): - """Tests TextProcessor class.""" + """Tests TextChecker class.""" def mock_handle_style_error(self): pass def test_init(self): """Test __init__ constructor.""" - processor = TextProcessor("foo.txt", self.mock_handle_style_error) - self.assertEquals(processor.file_path, "foo.txt") - self.assertEquals(processor.handle_style_error, self.mock_handle_style_error) + checker = TextChecker("foo.txt", self.mock_handle_style_error) + self.assertEquals(checker.file_path, "foo.txt") + self.assertEquals(checker.handle_style_error, self.mock_handle_style_error) if __name__ == '__main__': diff --git a/WebKitTools/Scripts/webkitpy/style/error_handlers.py b/WebKitTools/Scripts/webkitpy/style/error_handlers.py index 5666bfb..0bede24 100644 --- a/WebKitTools/Scripts/webkitpy/style/error_handlers.py +++ b/WebKitTools/Scripts/webkitpy/style/error_handlers.py @@ -63,7 +63,7 @@ class DefaultStyleErrorHandler(object): Args: file_path: The path to the file containing the error. This is used for reporting to the user. - configuration: A StyleCheckerConfiguration instance. + configuration: A StyleProcessorConfiguration instance. increment_error_count: A function that takes no arguments and increments the total count of reportable errors. diff --git a/WebKitTools/Scripts/webkitpy/style/error_handlers_unittest.py b/WebKitTools/Scripts/webkitpy/style/error_handlers_unittest.py index 05e725a..23619cc 100644 --- a/WebKitTools/Scripts/webkitpy/style/error_handlers_unittest.py +++ b/WebKitTools/Scripts/webkitpy/style/error_handlers_unittest.py @@ -25,7 +25,7 @@ import unittest -from checker import StyleCheckerConfiguration +from checker import StyleProcessorConfiguration from error_handlers import DefaultStyleErrorHandler from filter import FilterConfiguration @@ -51,11 +51,11 @@ class DefaultStyleErrorHandlerTest(unittest.TestCase): self._error_messages.append(message) def _style_checker_configuration(self): - """Return a StyleCheckerConfiguration instance for testing.""" + """Return a StyleProcessorConfiguration instance for testing.""" base_rules = ["-whitespace", "+whitespace/tab"] filter_configuration = FilterConfiguration(base_rules=base_rules) - return StyleCheckerConfiguration( + return StyleProcessorConfiguration( filter_configuration=filter_configuration, max_reports_per_category={"whitespace/tab": 2}, min_confidence=3, diff --git a/WebKitTools/Scripts/webkitpy/style/filereader.py b/WebKitTools/Scripts/webkitpy/style/filereader.py index 081e6dc..48455b3 100644 --- a/WebKitTools/Scripts/webkitpy/style/filereader.py +++ b/WebKitTools/Scripts/webkitpy/style/filereader.py @@ -103,6 +103,10 @@ class TextFileReader(object): """ self.file_count += 1 + if not os.path.exists(file_path) and file_path != "-": + _log.error("File does not exist: '%s'" % file_path) + sys.exit(1) + if not self._processor.should_process(file_path): _log.debug("Skipping file: '%s'" % file_path) return @@ -111,10 +115,6 @@ class TextFileReader(object): try: lines = self._read_lines(file_path) except IOError, err: - if not os.path.exists(file_path): - _log.error("File does not exist: '%s'" % file_path) - sys.exit(1) - message = ("Could not read file. Skipping: '%s'\n %s" % (file_path, err)) _log.warn(message) diff --git a/WebKitTools/Scripts/webkitpy/style/filereader_unittest.py b/WebKitTools/Scripts/webkitpy/style/filereader_unittest.py index 8d1a159..558ec5a 100644 --- a/WebKitTools/Scripts/webkitpy/style/filereader_unittest.py +++ b/WebKitTools/Scripts/webkitpy/style/filereader_unittest.py @@ -22,6 +22,9 @@ """Contains unit tests for filereader.py.""" +from __future__ import with_statement + +import codecs import os import shutil import tempfile @@ -67,14 +70,12 @@ class TextFileReaderTest(LoggingTestCase): LoggingTestCase.tearDown(self) shutil.rmtree(self._temp_dir) - def _create_file(self, rel_path, text): + def _create_file(self, rel_path, text, encoding="utf-8"): """Create a file with given text and return the path to the file.""" + # FIXME: There are better/more secure APIs for creatin tmp file paths. file_path = os.path.join(self._temp_dir, rel_path) - - file = open(file_path, 'w') - file.write(text) - file.close() - + with codecs.open(file_path, "w", encoding) as file: + file.write(text) return file_path def _passed_to_processor(self): @@ -86,10 +87,6 @@ class TextFileReaderTest(LoggingTestCase): self.assertEquals(passed_to_processor, self._passed_to_processor()) self.assertEquals(file_count, self._file_reader.file_count) - def test_process_file__should_not_process(self): - self._file_reader.process_file('should_not_process.txt') - self._assert_file_reader([], 1) - def test_process_file__does_not_exist(self): try: self._file_reader.process_file('does_not_exist.txt') @@ -121,6 +118,12 @@ class TextFileReaderTest(LoggingTestCase): self._assert_file_reader([], 1) + def test_process_file__should_not_process(self): + file_path = self._create_file('should_not_process.txt', 'contents') + + self._file_reader.process_file(file_path) + self._assert_file_reader([], 1) + def test_process_file__multiple_lines(self): file_path = self._create_file('foo.txt', 'line one\r\nline two\n') @@ -128,6 +131,13 @@ class TextFileReaderTest(LoggingTestCase): processed = [(['line one\r', 'line two', ''], file_path, None)] self._assert_file_reader(processed, 1) + def test_process_file__file_stdin(self): + file_path = self._create_file('-', 'file contents') + + self._file_reader.process_file(file_path=file_path, test_kwarg='foo') + processed = [(['file contents'], file_path, 'foo')] + self._assert_file_reader(processed, 1) + def test_process_file__with_kwarg(self): file_path = self._create_file('foo.txt', 'file contents') diff --git a/WebKitTools/Scripts/webkitpy/style/optparser.py b/WebKitTools/Scripts/webkitpy/style/optparser.py index 576c16a..bb4788a 100644 --- a/WebKitTools/Scripts/webkitpy/style/optparser.py +++ b/WebKitTools/Scripts/webkitpy/style/optparser.py @@ -147,7 +147,8 @@ class CommandOptionValues(object): git_commit=None, is_verbose=False, min_confidence=1, - output_format="emacs"): + output_format="emacs", + squash=False): if filter_rules is None: filter_rules = [] @@ -166,6 +167,7 @@ class CommandOptionValues(object): self.is_verbose = is_verbose self.min_confidence = min_confidence self.output_format = output_format + self.squash = squash # Useful for unit testing. def __eq__(self, other): @@ -180,6 +182,8 @@ class CommandOptionValues(object): return False if self.output_format != other.output_format: return False + if self.squash != other.squash: + return False return True @@ -214,6 +218,8 @@ class ArgumentPrinter(object): flags['filter'] = ",".join(filter_rules) if options.git_commit: flags['git-commit'] = options.git_commit + if options.squash: + flags['squash'] = options.squash flag_string = '' # Alphabetizing lets us unit test this method. @@ -303,9 +309,10 @@ class ArgumentParser(object): parser.add_option("-f", "--filter-rules", metavar="RULES", dest="filter_value", help=filter_help) - git_help = "check all changes after the given git commit." - parser.add_option("-g", "--git-commit", "--git-diff", "--git-since", - metavar="COMMIT", dest="git_since", help=git_help,) + git_commit_help = ("check all changes in the given git commit. " + "Use 'commit_id..' to check all changes after commmit_id") + parser.add_option("-g", "--git-diff", "--git-commit", + metavar="COMMIT", dest="git_commit", help=git_commit_help,) min_confidence_help = ("set the minimum confidence of style errors " "to report. Can be an integer 1-5, with 1 " @@ -323,6 +330,14 @@ class ArgumentParser(object): dest="output_format", default=default_output_format, help=output_format_help) + squash_help = ("All diffs from the remote branch are checked." + "If excluded, prompts whether to squash when there are multiple commits.") + parser.add_option("-s", "--squash", action="store_true", dest="squash", help=squash_help) + + squash_help = ("Only working copy diffs are checked." + "If excluded, prompts whether to squash when there are multiple commits.") + parser.add_option("--no-squash", action="store_false", dest="squash", help=squash_help) + verbose_help = "enable verbose logging." parser.add_option("-v", "--verbose", dest="is_verbose", default=False, action="store_true", help=verbose_help) @@ -407,7 +422,7 @@ class ArgumentParser(object): (options, paths) = self._parser.parse_args(args=args) filter_value = options.filter_value - git_commit = options.git_since + git_commit = options.git_commit is_verbose = options.is_verbose min_confidence = options.min_confidence output_format = options.output_format @@ -423,14 +438,6 @@ class ArgumentParser(object): self._parse_error('You cannot provide both paths and a git ' 'commit at the same time.') - # FIXME: Add unit tests. - if git_commit and '..' in git_commit: - # FIXME: If the range is a "...", the code should find the common - # ancestor and start there. See git diff --help for how - # "..." usually works. - self._parse_error('invalid --git-commit option: option does ' - 'not support ranges "..": %s' % git_commit) - min_confidence = int(min_confidence) if (min_confidence < 1) or (min_confidence > 5): self._parse_error('option --min-confidence: invalid integer: ' @@ -451,7 +458,8 @@ class ArgumentParser(object): git_commit=git_commit, is_verbose=is_verbose, min_confidence=min_confidence, - output_format=output_format) + output_format=output_format, + squash=options.squash) return (paths, options) diff --git a/WebKitTools/Scripts/webkitpy/style/optparser_unittest.py b/WebKitTools/Scripts/webkitpy/style/optparser_unittest.py index 1c525c6..b7e3eda 100644 --- a/WebKitTools/Scripts/webkitpy/style/optparser_unittest.py +++ b/WebKitTools/Scripts/webkitpy/style/optparser_unittest.py @@ -114,10 +114,6 @@ class ArgumentParserTest(LoggingTestCase): self.assertRaises(SystemExit, parse, ['--bad']) self.assertLog(['ERROR: no such option: --bad\n']) - self.assertRaises(SystemExit, parse, ['--git-diff=aa..bb']) - self.assertLog(['ERROR: invalid --git-commit option: ' - 'option does not support ranges "..": aa..bb\n']) - self.assertRaises(SystemExit, parse, ['--min-confidence=bad']) self.assertLog(['ERROR: option --min-confidence: ' "invalid integer value: 'bad'\n"]) @@ -173,8 +169,6 @@ class ArgumentParserTest(LoggingTestCase): self.assertEquals(options.git_commit, 'commit') (files, options) = parse(['--git-diff=commit']) self.assertEquals(options.git_commit, 'commit') - (files, options) = parse(['--git-since=commit']) - self.assertEquals(options.git_commit, 'commit') (files, options) = parse(['--verbose']) self.assertEquals(options.is_verbose, True) diff --git a/WebKitTools/Scripts/webkitpy/style_references.py b/WebKitTools/Scripts/webkitpy/style_references.py index ba2806e..1bf087d 100644 --- a/WebKitTools/Scripts/webkitpy/style_references.py +++ b/WebKitTools/Scripts/webkitpy/style_references.py @@ -75,9 +75,6 @@ class WebKitCheckout(object): """Return the checkout root as an absolute path.""" return self._scm.checkout_root - def create_patch(self): - return self._scm.create_patch() - - def create_patch_since_local_commit(self, commit): - return self._scm.create_patch_since_local_commit(commit) + def create_patch(self, git_commit, squash): + return self._scm.create_patch(git_commit, squash) diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/__init__.py b/WebKitTools/Scripts/webkitpy/thirdparty/__init__.py index f1e5334..c052f00 100644 --- a/WebKitTools/Scripts/webkitpy/thirdparty/__init__.py +++ b/WebKitTools/Scripts/webkitpy/thirdparty/__init__.py @@ -24,6 +24,9 @@ """Autoinstalls third-party code required by WebKit.""" +from __future__ import with_statement + +import codecs import os from webkitpy.common.system.autoinstall import AutoInstaller @@ -88,10 +91,7 @@ installer.install(url="http://iweb.dl.sourceforge.net/project/python-irclib/pyth readme_path = os.path.join(autoinstalled_dir, "README") if not os.path.exists(readme_path): - file = open(readme_path, "w") - try: + with codecs.open(readme_path, "w", "ascii") as file: file.write("This directory is auto-generated by WebKit and is " "safe to delete.\nIt contains needed third-party Python " "packages automatically downloaded from the web.") - finally: - file.close() diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/.mechanize.url b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/.mechanize.url new file mode 100644 index 0000000..4186aee --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/.mechanize.url @@ -0,0 +1 @@ +http://pypi.python.org/packages/source/m/mechanize/mechanize-0.1.11.zip
\ No newline at end of file diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/.pep8.py.url b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/.pep8.py.url new file mode 100644 index 0000000..0fb1ef6 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/.pep8.py.url @@ -0,0 +1 @@ +http://pypi.python.org/packages/source/p/pep8/pep8-0.5.0.tar.gz#md5=512a818af9979290cd619cce8e9c2e2b
\ No newline at end of file diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/README b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/README new file mode 100644 index 0000000..1d68cf3 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/README @@ -0,0 +1,2 @@ +This directory is auto-generated by WebKit and is safe to delete. +It contains needed third-party Python packages automatically downloaded from the web.
\ No newline at end of file diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/__init__.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/__init__.py new file mode 100644 index 0000000..c1e4c6d --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/__init__.py @@ -0,0 +1 @@ +# This file is required for Python to search this directory for modules. diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/clientform/.ClientForm.py.url b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/clientform/.ClientForm.py.url new file mode 100644 index 0000000..c723abf --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/clientform/.ClientForm.py.url @@ -0,0 +1 @@ +http://pypi.python.org/packages/source/C/ClientForm/ClientForm-0.2.10.zip
\ No newline at end of file diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/clientform/ClientForm.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/clientform/ClientForm.py new file mode 100644 index 0000000..a622de7 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/clientform/ClientForm.py @@ -0,0 +1,3401 @@ +"""HTML form handling for web clients. + +ClientForm is a Python module for handling HTML forms on the client +side, useful for parsing HTML forms, filling them in and returning the +completed forms to the server. It has developed from a port of Gisle +Aas' Perl module HTML::Form, from the libwww-perl library, but the +interface is not the same. + +The most useful docstring is the one for HTMLForm. + +RFC 1866: HTML 2.0 +RFC 1867: Form-based File Upload in HTML +RFC 2388: Returning Values from Forms: multipart/form-data +HTML 3.2 Specification, W3C Recommendation 14 January 1997 (for ISINDEX) +HTML 4.01 Specification, W3C Recommendation 24 December 1999 + + +Copyright 2002-2007 John J. Lee <jjl@pobox.com> +Copyright 2005 Gary Poster +Copyright 2005 Zope Corporation +Copyright 1998-2000 Gisle Aas. + +This code is free software; you can redistribute it and/or modify it +under the terms of the BSD or ZPL 2.1 licenses (see the file +COPYING.txt included with the distribution). + +""" + +# XXX +# Remove parser testing hack +# safeUrl()-ize action +# Switch to unicode throughout (would be 0.3.x) +# See Wichert Akkerman's 2004-01-22 message to c.l.py. +# Add charset parameter to Content-type headers? How to find value?? +# Add some more functional tests +# Especially single and multiple file upload on the internet. +# Does file upload work when name is missing? Sourceforge tracker form +# doesn't like it. Check standards, and test with Apache. Test +# binary upload with Apache. +# mailto submission & enctype text/plain +# I'm not going to fix this unless somebody tells me what real servers +# that want this encoding actually expect: If enctype is +# application/x-www-form-urlencoded and there's a FILE control present. +# Strictly, it should be 'name=data' (see HTML 4.01 spec., section +# 17.13.2), but I send "name=" ATM. What about multiple file upload?? + +# Would be nice, but I'm not going to do it myself: +# ------------------------------------------------- +# Maybe a 0.4.x? +# Replace by_label etc. with moniker / selector concept. Allows, eg., +# a choice between selection by value / id / label / element +# contents. Or choice between matching labels exactly or by +# substring. Etc. +# Remove deprecated methods. +# ...what else? +# Work on DOMForm. +# XForms? Don't know if there's a need here. + +__all__ = ['AmbiguityError', 'CheckboxControl', 'Control', + 'ControlNotFoundError', 'FileControl', 'FormParser', 'HTMLForm', + 'HiddenControl', 'IgnoreControl', 'ImageControl', 'IsindexControl', + 'Item', 'ItemCountError', 'ItemNotFoundError', 'Label', + 'ListControl', 'LocateError', 'Missing', 'ParseError', 'ParseFile', + 'ParseFileEx', 'ParseResponse', 'ParseResponseEx','PasswordControl', + 'RadioControl', 'ScalarControl', 'SelectControl', + 'SubmitButtonControl', 'SubmitControl', 'TextControl', + 'TextareaControl', 'XHTMLCompatibleFormParser'] + +try: True +except NameError: + True = 1 + False = 0 + +try: bool +except NameError: + def bool(expr): + if expr: return True + else: return False + +try: + import logging + import inspect +except ImportError: + def debug(msg, *args, **kwds): + pass +else: + _logger = logging.getLogger("ClientForm") + OPTIMIZATION_HACK = True + + def debug(msg, *args, **kwds): + if OPTIMIZATION_HACK: + return + + caller_name = inspect.stack()[1][3] + extended_msg = '%%s %s' % msg + extended_args = (caller_name,)+args + debug = _logger.debug(extended_msg, *extended_args, **kwds) + + def _show_debug_messages(): + global OPTIMIZATION_HACK + OPTIMIZATION_HACK = False + _logger.setLevel(logging.DEBUG) + handler = logging.StreamHandler(sys.stdout) + handler.setLevel(logging.DEBUG) + _logger.addHandler(handler) + +import sys, urllib, urllib2, types, mimetools, copy, urlparse, \ + htmlentitydefs, re, random +from cStringIO import StringIO + +import sgmllib +# monkeypatch to fix http://www.python.org/sf/803422 :-( +sgmllib.charref = re.compile("&#(x?[0-9a-fA-F]+)[^0-9a-fA-F]") + +# HTMLParser.HTMLParser is recent, so live without it if it's not available +# (also, sgmllib.SGMLParser is much more tolerant of bad HTML) +try: + import HTMLParser +except ImportError: + HAVE_MODULE_HTMLPARSER = False +else: + HAVE_MODULE_HTMLPARSER = True + +try: + import warnings +except ImportError: + def deprecation(message, stack_offset=0): + pass +else: + def deprecation(message, stack_offset=0): + warnings.warn(message, DeprecationWarning, stacklevel=3+stack_offset) + +VERSION = "0.2.10" + +CHUNK = 1024 # size of chunks fed to parser, in bytes + +DEFAULT_ENCODING = "latin-1" + +class Missing: pass + +_compress_re = re.compile(r"\s+") +def compress_text(text): return _compress_re.sub(" ", text.strip()) + +def normalize_line_endings(text): + return re.sub(r"(?:(?<!\r)\n)|(?:\r(?!\n))", "\r\n", text) + + +# This version of urlencode is from my Python 1.5.2 back-port of the +# Python 2.1 CVS maintenance branch of urllib. It will accept a sequence +# of pairs instead of a mapping -- the 2.0 version only accepts a mapping. +def urlencode(query,doseq=False,): + """Encode a sequence of two-element tuples or dictionary into a URL query \ +string. + + If any values in the query arg are sequences and doseq is true, each + sequence element is converted to a separate parameter. + + If the query arg is a sequence of two-element tuples, the order of the + parameters in the output will match the order of parameters in the + input. + """ + + if hasattr(query,"items"): + # mapping objects + query = query.items() + else: + # it's a bother at times that strings and string-like objects are + # sequences... + try: + # non-sequence items should not work with len() + x = len(query) + # non-empty strings will fail this + if len(query) and type(query[0]) != types.TupleType: + raise TypeError() + # zero-length sequences of all types will get here and succeed, + # but that's a minor nit - since the original implementation + # allowed empty dicts that type of behavior probably should be + # preserved for consistency + except TypeError: + ty,va,tb = sys.exc_info() + raise TypeError("not a valid non-string sequence or mapping " + "object", tb) + + l = [] + if not doseq: + # preserve old behavior + for k, v in query: + k = urllib.quote_plus(str(k)) + v = urllib.quote_plus(str(v)) + l.append(k + '=' + v) + else: + for k, v in query: + k = urllib.quote_plus(str(k)) + if type(v) == types.StringType: + v = urllib.quote_plus(v) + l.append(k + '=' + v) + elif type(v) == types.UnicodeType: + # is there a reasonable way to convert to ASCII? + # encode generates a string, but "replace" or "ignore" + # lose information and "strict" can raise UnicodeError + v = urllib.quote_plus(v.encode("ASCII","replace")) + l.append(k + '=' + v) + else: + try: + # is this a sufficient test for sequence-ness? + x = len(v) + except TypeError: + # not a sequence + v = urllib.quote_plus(str(v)) + l.append(k + '=' + v) + else: + # loop over the sequence + for elt in v: + l.append(k + '=' + urllib.quote_plus(str(elt))) + return '&'.join(l) + +def unescape(data, entities, encoding=DEFAULT_ENCODING): + if data is None or "&" not in data: + return data + + def replace_entities(match, entities=entities, encoding=encoding): + ent = match.group() + if ent[1] == "#": + return unescape_charref(ent[2:-1], encoding) + + repl = entities.get(ent) + if repl is not None: + if type(repl) != type(""): + try: + repl = repl.encode(encoding) + except UnicodeError: + repl = ent + else: + repl = ent + + return repl + + return re.sub(r"&#?[A-Za-z0-9]+?;", replace_entities, data) + +def unescape_charref(data, encoding): + name, base = data, 10 + if name.startswith("x"): + name, base= name[1:], 16 + uc = unichr(int(name, base)) + if encoding is None: + return uc + else: + try: + repl = uc.encode(encoding) + except UnicodeError: + repl = "&#%s;" % data + return repl + +def get_entitydefs(): + import htmlentitydefs + from codecs import latin_1_decode + entitydefs = {} + try: + htmlentitydefs.name2codepoint + except AttributeError: + entitydefs = {} + for name, char in htmlentitydefs.entitydefs.items(): + uc = latin_1_decode(char)[0] + if uc.startswith("&#") and uc.endswith(";"): + uc = unescape_charref(uc[2:-1], None) + entitydefs["&%s;" % name] = uc + else: + for name, codepoint in htmlentitydefs.name2codepoint.items(): + entitydefs["&%s;" % name] = unichr(codepoint) + return entitydefs + + +def issequence(x): + try: + x[0] + except (TypeError, KeyError): + return False + except IndexError: + pass + return True + +def isstringlike(x): + try: x+"" + except: return False + else: return True + + +def choose_boundary(): + """Return a string usable as a multipart boundary.""" + # follow IE and firefox + nonce = "".join([str(random.randint(0, sys.maxint-1)) for i in 0,1,2]) + return "-"*27 + nonce + +# This cut-n-pasted MimeWriter from standard library is here so can add +# to HTTP headers rather than message body when appropriate. It also uses +# \r\n in place of \n. This is a bit nasty. +class MimeWriter: + + """Generic MIME writer. + + Methods: + + __init__() + addheader() + flushheaders() + startbody() + startmultipartbody() + nextpart() + lastpart() + + A MIME writer is much more primitive than a MIME parser. It + doesn't seek around on the output file, and it doesn't use large + amounts of buffer space, so you have to write the parts in the + order they should occur on the output file. It does buffer the + headers you add, allowing you to rearrange their order. + + General usage is: + + f = <open the output file> + w = MimeWriter(f) + ...call w.addheader(key, value) 0 or more times... + + followed by either: + + f = w.startbody(content_type) + ...call f.write(data) for body data... + + or: + + w.startmultipartbody(subtype) + for each part: + subwriter = w.nextpart() + ...use the subwriter's methods to create the subpart... + w.lastpart() + + The subwriter is another MimeWriter instance, and should be + treated in the same way as the toplevel MimeWriter. This way, + writing recursive body parts is easy. + + Warning: don't forget to call lastpart()! + + XXX There should be more state so calls made in the wrong order + are detected. + + Some special cases: + + - startbody() just returns the file passed to the constructor; + but don't use this knowledge, as it may be changed. + + - startmultipartbody() actually returns a file as well; + this can be used to write the initial 'if you can read this your + mailer is not MIME-aware' message. + + - If you call flushheaders(), the headers accumulated so far are + written out (and forgotten); this is useful if you don't need a + body part at all, e.g. for a subpart of type message/rfc822 + that's (mis)used to store some header-like information. + + - Passing a keyword argument 'prefix=<flag>' to addheader(), + start*body() affects where the header is inserted; 0 means + append at the end, 1 means insert at the start; default is + append for addheader(), but insert for start*body(), which use + it to determine where the Content-type header goes. + + """ + + def __init__(self, fp, http_hdrs=None): + self._http_hdrs = http_hdrs + self._fp = fp + self._headers = [] + self._boundary = [] + self._first_part = True + + def addheader(self, key, value, prefix=0, + add_to_http_hdrs=0): + """ + prefix is ignored if add_to_http_hdrs is true. + """ + lines = value.split("\r\n") + while lines and not lines[-1]: del lines[-1] + while lines and not lines[0]: del lines[0] + if add_to_http_hdrs: + value = "".join(lines) + # 2.2 urllib2 doesn't normalize header case + self._http_hdrs.append((key.capitalize(), value)) + else: + for i in range(1, len(lines)): + lines[i] = " " + lines[i].strip() + value = "\r\n".join(lines) + "\r\n" + line = key.title() + ": " + value + if prefix: + self._headers.insert(0, line) + else: + self._headers.append(line) + + def flushheaders(self): + self._fp.writelines(self._headers) + self._headers = [] + + def startbody(self, ctype=None, plist=[], prefix=1, + add_to_http_hdrs=0, content_type=1): + """ + prefix is ignored if add_to_http_hdrs is true. + """ + if content_type and ctype: + for name, value in plist: + ctype = ctype + ';\r\n %s=%s' % (name, value) + self.addheader("Content-Type", ctype, prefix=prefix, + add_to_http_hdrs=add_to_http_hdrs) + self.flushheaders() + if not add_to_http_hdrs: self._fp.write("\r\n") + self._first_part = True + return self._fp + + def startmultipartbody(self, subtype, boundary=None, plist=[], prefix=1, + add_to_http_hdrs=0, content_type=1): + boundary = boundary or choose_boundary() + self._boundary.append(boundary) + return self.startbody("multipart/" + subtype, + [("boundary", boundary)] + plist, + prefix=prefix, + add_to_http_hdrs=add_to_http_hdrs, + content_type=content_type) + + def nextpart(self): + boundary = self._boundary[-1] + if self._first_part: + self._first_part = False + else: + self._fp.write("\r\n") + self._fp.write("--" + boundary + "\r\n") + return self.__class__(self._fp) + + def lastpart(self): + if self._first_part: + self.nextpart() + boundary = self._boundary.pop() + self._fp.write("\r\n--" + boundary + "--\r\n") + + +class LocateError(ValueError): pass +class AmbiguityError(LocateError): pass +class ControlNotFoundError(LocateError): pass +class ItemNotFoundError(LocateError): pass + +class ItemCountError(ValueError): pass + +# for backwards compatibility, ParseError derives from exceptions that were +# raised by versions of ClientForm <= 0.2.5 +if HAVE_MODULE_HTMLPARSER: + SGMLLIB_PARSEERROR = sgmllib.SGMLParseError + class ParseError(sgmllib.SGMLParseError, + HTMLParser.HTMLParseError, + ): + pass +else: + if hasattr(sgmllib, "SGMLParseError"): + SGMLLIB_PARSEERROR = sgmllib.SGMLParseError + class ParseError(sgmllib.SGMLParseError): + pass + else: + SGMLLIB_PARSEERROR = RuntimeError + class ParseError(RuntimeError): + pass + + +class _AbstractFormParser: + """forms attribute contains HTMLForm instances on completion.""" + # thanks to Moshe Zadka for an example of sgmllib/htmllib usage + def __init__(self, entitydefs=None, encoding=DEFAULT_ENCODING): + if entitydefs is None: + entitydefs = get_entitydefs() + self._entitydefs = entitydefs + self._encoding = encoding + + self.base = None + self.forms = [] + self.labels = [] + self._current_label = None + self._current_form = None + self._select = None + self._optgroup = None + self._option = None + self._textarea = None + + # forms[0] will contain all controls that are outside of any form + # self._global_form is an alias for self.forms[0] + self._global_form = None + self.start_form([]) + self.end_form() + self._current_form = self._global_form = self.forms[0] + + def do_base(self, attrs): + debug("%s", attrs) + for key, value in attrs: + if key == "href": + self.base = self.unescape_attr_if_required(value) + + def end_body(self): + debug("") + if self._current_label is not None: + self.end_label() + if self._current_form is not self._global_form: + self.end_form() + + def start_form(self, attrs): + debug("%s", attrs) + if self._current_form is not self._global_form: + raise ParseError("nested FORMs") + name = None + action = None + enctype = "application/x-www-form-urlencoded" + method = "GET" + d = {} + for key, value in attrs: + if key == "name": + name = self.unescape_attr_if_required(value) + elif key == "action": + action = self.unescape_attr_if_required(value) + elif key == "method": + method = self.unescape_attr_if_required(value.upper()) + elif key == "enctype": + enctype = self.unescape_attr_if_required(value.lower()) + d[key] = self.unescape_attr_if_required(value) + controls = [] + self._current_form = (name, action, method, enctype), d, controls + + def end_form(self): + debug("") + if self._current_label is not None: + self.end_label() + if self._current_form is self._global_form: + raise ParseError("end of FORM before start") + self.forms.append(self._current_form) + self._current_form = self._global_form + + def start_select(self, attrs): + debug("%s", attrs) + if self._select is not None: + raise ParseError("nested SELECTs") + if self._textarea is not None: + raise ParseError("SELECT inside TEXTAREA") + d = {} + for key, val in attrs: + d[key] = self.unescape_attr_if_required(val) + + self._select = d + self._add_label(d) + + self._append_select_control({"__select": d}) + + def end_select(self): + debug("") + if self._select is None: + raise ParseError("end of SELECT before start") + + if self._option is not None: + self._end_option() + + self._select = None + + def start_optgroup(self, attrs): + debug("%s", attrs) + if self._select is None: + raise ParseError("OPTGROUP outside of SELECT") + d = {} + for key, val in attrs: + d[key] = self.unescape_attr_if_required(val) + + self._optgroup = d + + def end_optgroup(self): + debug("") + if self._optgroup is None: + raise ParseError("end of OPTGROUP before start") + self._optgroup = None + + def _start_option(self, attrs): + debug("%s", attrs) + if self._select is None: + raise ParseError("OPTION outside of SELECT") + if self._option is not None: + self._end_option() + + d = {} + for key, val in attrs: + d[key] = self.unescape_attr_if_required(val) + + self._option = {} + self._option.update(d) + if (self._optgroup and self._optgroup.has_key("disabled") and + not self._option.has_key("disabled")): + self._option["disabled"] = None + + def _end_option(self): + debug("") + if self._option is None: + raise ParseError("end of OPTION before start") + + contents = self._option.get("contents", "").strip() + self._option["contents"] = contents + if not self._option.has_key("value"): + self._option["value"] = contents + if not self._option.has_key("label"): + self._option["label"] = contents + # stuff dict of SELECT HTML attrs into a special private key + # (gets deleted again later) + self._option["__select"] = self._select + self._append_select_control(self._option) + self._option = None + + def _append_select_control(self, attrs): + debug("%s", attrs) + controls = self._current_form[2] + name = self._select.get("name") + controls.append(("select", name, attrs)) + + def start_textarea(self, attrs): + debug("%s", attrs) + if self._textarea is not None: + raise ParseError("nested TEXTAREAs") + if self._select is not None: + raise ParseError("TEXTAREA inside SELECT") + d = {} + for key, val in attrs: + d[key] = self.unescape_attr_if_required(val) + self._add_label(d) + + self._textarea = d + + def end_textarea(self): + debug("") + if self._textarea is None: + raise ParseError("end of TEXTAREA before start") + controls = self._current_form[2] + name = self._textarea.get("name") + controls.append(("textarea", name, self._textarea)) + self._textarea = None + + def start_label(self, attrs): + debug("%s", attrs) + if self._current_label: + self.end_label() + d = {} + for key, val in attrs: + d[key] = self.unescape_attr_if_required(val) + taken = bool(d.get("for")) # empty id is invalid + d["__text"] = "" + d["__taken"] = taken + if taken: + self.labels.append(d) + self._current_label = d + + def end_label(self): + debug("") + label = self._current_label + if label is None: + # something is ugly in the HTML, but we're ignoring it + return + self._current_label = None + # if it is staying around, it is True in all cases + del label["__taken"] + + def _add_label(self, d): + #debug("%s", d) + if self._current_label is not None: + if not self._current_label["__taken"]: + self._current_label["__taken"] = True + d["__label"] = self._current_label + + def handle_data(self, data): + debug("%s", data) + + if self._option is not None: + # self._option is a dictionary of the OPTION element's HTML + # attributes, but it has two special keys, one of which is the + # special "contents" key contains text between OPTION tags (the + # other is the "__select" key: see the end_option method) + map = self._option + key = "contents" + elif self._textarea is not None: + map = self._textarea + key = "value" + data = normalize_line_endings(data) + # not if within option or textarea + elif self._current_label is not None: + map = self._current_label + key = "__text" + else: + return + + if data and not map.has_key(key): + # according to + # http://www.w3.org/TR/html4/appendix/notes.html#h-B.3.1 line break + # immediately after start tags or immediately before end tags must + # be ignored, but real browsers only ignore a line break after a + # start tag, so we'll do that. + if data[0:2] == "\r\n": + data = data[2:] + elif data[0:1] in ["\n", "\r"]: + data = data[1:] + map[key] = data + else: + map[key] = map[key] + data + + def do_button(self, attrs): + debug("%s", attrs) + d = {} + d["type"] = "submit" # default + for key, val in attrs: + d[key] = self.unescape_attr_if_required(val) + controls = self._current_form[2] + + type = d["type"] + name = d.get("name") + # we don't want to lose information, so use a type string that + # doesn't clash with INPUT TYPE={SUBMIT,RESET,BUTTON} + # e.g. type for BUTTON/RESET is "resetbutton" + # (type for INPUT/RESET is "reset") + type = type+"button" + self._add_label(d) + controls.append((type, name, d)) + + def do_input(self, attrs): + debug("%s", attrs) + d = {} + d["type"] = "text" # default + for key, val in attrs: + d[key] = self.unescape_attr_if_required(val) + controls = self._current_form[2] + + type = d["type"] + name = d.get("name") + self._add_label(d) + controls.append((type, name, d)) + + def do_isindex(self, attrs): + debug("%s", attrs) + d = {} + for key, val in attrs: + d[key] = self.unescape_attr_if_required(val) + controls = self._current_form[2] + + self._add_label(d) + # isindex doesn't have type or name HTML attributes + controls.append(("isindex", None, d)) + + def handle_entityref(self, name): + #debug("%s", name) + self.handle_data(unescape( + '&%s;' % name, self._entitydefs, self._encoding)) + + def handle_charref(self, name): + #debug("%s", name) + self.handle_data(unescape_charref(name, self._encoding)) + + def unescape_attr(self, name): + #debug("%s", name) + return unescape(name, self._entitydefs, self._encoding) + + def unescape_attrs(self, attrs): + #debug("%s", attrs) + escaped_attrs = {} + for key, val in attrs.items(): + try: + val.items + except AttributeError: + escaped_attrs[key] = self.unescape_attr(val) + else: + # e.g. "__select" -- yuck! + escaped_attrs[key] = self.unescape_attrs(val) + return escaped_attrs + + def unknown_entityref(self, ref): self.handle_data("&%s;" % ref) + def unknown_charref(self, ref): self.handle_data("&#%s;" % ref) + + +if not HAVE_MODULE_HTMLPARSER: + class XHTMLCompatibleFormParser: + def __init__(self, entitydefs=None, encoding=DEFAULT_ENCODING): + raise ValueError("HTMLParser could not be imported") +else: + class XHTMLCompatibleFormParser(_AbstractFormParser, HTMLParser.HTMLParser): + """Good for XHTML, bad for tolerance of incorrect HTML.""" + # thanks to Michael Howitz for this! + def __init__(self, entitydefs=None, encoding=DEFAULT_ENCODING): + HTMLParser.HTMLParser.__init__(self) + _AbstractFormParser.__init__(self, entitydefs, encoding) + + def feed(self, data): + try: + HTMLParser.HTMLParser.feed(self, data) + except HTMLParser.HTMLParseError, exc: + raise ParseError(exc) + + def start_option(self, attrs): + _AbstractFormParser._start_option(self, attrs) + + def end_option(self): + _AbstractFormParser._end_option(self) + + def handle_starttag(self, tag, attrs): + try: + method = getattr(self, "start_" + tag) + except AttributeError: + try: + method = getattr(self, "do_" + tag) + except AttributeError: + pass # unknown tag + else: + method(attrs) + else: + method(attrs) + + def handle_endtag(self, tag): + try: + method = getattr(self, "end_" + tag) + except AttributeError: + pass # unknown tag + else: + method() + + def unescape(self, name): + # Use the entitydefs passed into constructor, not + # HTMLParser.HTMLParser's entitydefs. + return self.unescape_attr(name) + + def unescape_attr_if_required(self, name): + return name # HTMLParser.HTMLParser already did it + def unescape_attrs_if_required(self, attrs): + return attrs # ditto + + def close(self): + HTMLParser.HTMLParser.close(self) + self.end_body() + + +class _AbstractSgmllibParser(_AbstractFormParser): + + def do_option(self, attrs): + _AbstractFormParser._start_option(self, attrs) + + if sys.version_info[:2] >= (2,5): + # we override this attr to decode hex charrefs + entity_or_charref = re.compile( + '&(?:([a-zA-Z][-.a-zA-Z0-9]*)|#(x?[0-9a-fA-F]+))(;?)') + def convert_entityref(self, name): + return unescape("&%s;" % name, self._entitydefs, self._encoding) + def convert_charref(self, name): + return unescape_charref("%s" % name, self._encoding) + def unescape_attr_if_required(self, name): + return name # sgmllib already did it + def unescape_attrs_if_required(self, attrs): + return attrs # ditto + else: + def unescape_attr_if_required(self, name): + return self.unescape_attr(name) + def unescape_attrs_if_required(self, attrs): + return self.unescape_attrs(attrs) + + +class FormParser(_AbstractSgmllibParser, sgmllib.SGMLParser): + """Good for tolerance of incorrect HTML, bad for XHTML.""" + def __init__(self, entitydefs=None, encoding=DEFAULT_ENCODING): + sgmllib.SGMLParser.__init__(self) + _AbstractFormParser.__init__(self, entitydefs, encoding) + + def feed(self, data): + try: + sgmllib.SGMLParser.feed(self, data) + except SGMLLIB_PARSEERROR, exc: + raise ParseError(exc) + + def close(self): + sgmllib.SGMLParser.close(self) + self.end_body() + + +# sigh, must support mechanize by allowing dynamic creation of classes based on +# its bundled copy of BeautifulSoup (which was necessary because of dependency +# problems) + +def _create_bs_classes(bs, + icbinbs, + ): + class _AbstractBSFormParser(_AbstractSgmllibParser): + bs_base_class = None + def __init__(self, entitydefs=None, encoding=DEFAULT_ENCODING): + _AbstractFormParser.__init__(self, entitydefs, encoding) + self.bs_base_class.__init__(self) + def handle_data(self, data): + _AbstractFormParser.handle_data(self, data) + self.bs_base_class.handle_data(self, data) + def feed(self, data): + try: + self.bs_base_class.feed(self, data) + except SGMLLIB_PARSEERROR, exc: + raise ParseError(exc) + def close(self): + self.bs_base_class.close(self) + self.end_body() + + class RobustFormParser(_AbstractBSFormParser, bs): + """Tries to be highly tolerant of incorrect HTML.""" + pass + RobustFormParser.bs_base_class = bs + class NestingRobustFormParser(_AbstractBSFormParser, icbinbs): + """Tries to be highly tolerant of incorrect HTML. + + Different from RobustFormParser in that it more often guesses nesting + above missing end tags (see BeautifulSoup docs). + + """ + pass + NestingRobustFormParser.bs_base_class = icbinbs + + return RobustFormParser, NestingRobustFormParser + +try: + if sys.version_info[:2] < (2, 2): + raise ImportError # BeautifulSoup uses generators + import BeautifulSoup +except ImportError: + pass +else: + RobustFormParser, NestingRobustFormParser = _create_bs_classes( + BeautifulSoup.BeautifulSoup, BeautifulSoup.ICantBelieveItsBeautifulSoup + ) + __all__ += ['RobustFormParser', 'NestingRobustFormParser'] + + +#FormParser = XHTMLCompatibleFormParser # testing hack +#FormParser = RobustFormParser # testing hack + + +def ParseResponseEx(response, + select_default=False, + form_parser_class=FormParser, + request_class=urllib2.Request, + entitydefs=None, + encoding=DEFAULT_ENCODING, + + # private + _urljoin=urlparse.urljoin, + _urlparse=urlparse.urlparse, + _urlunparse=urlparse.urlunparse, + ): + """Identical to ParseResponse, except that: + + 1. The returned list contains an extra item. The first form in the list + contains all controls not contained in any FORM element. + + 2. The arguments ignore_errors and backwards_compat have been removed. + + 3. Backwards-compatibility mode (backwards_compat=True) is not available. + """ + return _ParseFileEx(response, response.geturl(), + select_default, + False, + form_parser_class, + request_class, + entitydefs, + False, + encoding, + _urljoin=_urljoin, + _urlparse=_urlparse, + _urlunparse=_urlunparse, + ) + +def ParseFileEx(file, base_uri, + select_default=False, + form_parser_class=FormParser, + request_class=urllib2.Request, + entitydefs=None, + encoding=DEFAULT_ENCODING, + + # private + _urljoin=urlparse.urljoin, + _urlparse=urlparse.urlparse, + _urlunparse=urlparse.urlunparse, + ): + """Identical to ParseFile, except that: + + 1. The returned list contains an extra item. The first form in the list + contains all controls not contained in any FORM element. + + 2. The arguments ignore_errors and backwards_compat have been removed. + + 3. Backwards-compatibility mode (backwards_compat=True) is not available. + """ + return _ParseFileEx(file, base_uri, + select_default, + False, + form_parser_class, + request_class, + entitydefs, + False, + encoding, + _urljoin=_urljoin, + _urlparse=_urlparse, + _urlunparse=_urlunparse, + ) + +def ParseResponse(response, *args, **kwds): + """Parse HTTP response and return a list of HTMLForm instances. + + The return value of urllib2.urlopen can be conveniently passed to this + function as the response parameter. + + ClientForm.ParseError is raised on parse errors. + + response: file-like object (supporting read() method) with a method + geturl(), returning the URI of the HTTP response + select_default: for multiple-selection SELECT controls and RADIO controls, + pick the first item as the default if none are selected in the HTML + form_parser_class: class to instantiate and use to pass + request_class: class to return from .click() method (default is + urllib2.Request) + entitydefs: mapping like {"&": "&", ...} containing HTML entity + definitions (a sensible default is used) + encoding: character encoding used for encoding numeric character references + when matching link text. ClientForm does not attempt to find the encoding + in a META HTTP-EQUIV attribute in the document itself (mechanize, for + example, does do that and will pass the correct value to ClientForm using + this parameter). + + backwards_compat: boolean that determines whether the returned HTMLForm + objects are backwards-compatible with old code. If backwards_compat is + true: + + - ClientForm 0.1 code will continue to work as before. + + - Label searches that do not specify a nr (number or count) will always + get the first match, even if other controls match. If + backwards_compat is False, label searches that have ambiguous results + will raise an AmbiguityError. + + - Item label matching is done by strict string comparison rather than + substring matching. + + - De-selecting individual list items is allowed even if the Item is + disabled. + + The backwards_compat argument will be deprecated in a future release. + + Pass a true value for select_default if you want the behaviour specified by + RFC 1866 (the HTML 2.0 standard), which is to select the first item in a + RADIO or multiple-selection SELECT control if none were selected in the + HTML. Most browsers (including Microsoft Internet Explorer (IE) and + Netscape Navigator) instead leave all items unselected in these cases. The + W3C HTML 4.0 standard leaves this behaviour undefined in the case of + multiple-selection SELECT controls, but insists that at least one RADIO + button should be checked at all times, in contradiction to browser + behaviour. + + There is a choice of parsers. ClientForm.XHTMLCompatibleFormParser (uses + HTMLParser.HTMLParser) works best for XHTML, ClientForm.FormParser (uses + sgmllib.SGMLParser) (the default) works better for ordinary grubby HTML. + Note that HTMLParser is only available in Python 2.2 and later. You can + pass your own class in here as a hack to work around bad HTML, but at your + own risk: there is no well-defined interface. + + """ + return _ParseFileEx(response, response.geturl(), *args, **kwds)[1:] + +def ParseFile(file, base_uri, *args, **kwds): + """Parse HTML and return a list of HTMLForm instances. + + ClientForm.ParseError is raised on parse errors. + + file: file-like object (supporting read() method) containing HTML with zero + or more forms to be parsed + base_uri: the URI of the document (note that the base URI used to submit + the form will be that given in the BASE element if present, not that of + the document) + + For the other arguments and further details, see ParseResponse.__doc__. + + """ + return _ParseFileEx(file, base_uri, *args, **kwds)[1:] + +def _ParseFileEx(file, base_uri, + select_default=False, + ignore_errors=False, + form_parser_class=FormParser, + request_class=urllib2.Request, + entitydefs=None, + backwards_compat=True, + encoding=DEFAULT_ENCODING, + _urljoin=urlparse.urljoin, + _urlparse=urlparse.urlparse, + _urlunparse=urlparse.urlunparse, + ): + if backwards_compat: + deprecation("operating in backwards-compatibility mode", 1) + fp = form_parser_class(entitydefs, encoding) + while 1: + data = file.read(CHUNK) + try: + fp.feed(data) + except ParseError, e: + e.base_uri = base_uri + raise + if len(data) != CHUNK: break + fp.close() + if fp.base is not None: + # HTML BASE element takes precedence over document URI + base_uri = fp.base + labels = [] # Label(label) for label in fp.labels] + id_to_labels = {} + for l in fp.labels: + label = Label(l) + labels.append(label) + for_id = l["for"] + coll = id_to_labels.get(for_id) + if coll is None: + id_to_labels[for_id] = [label] + else: + coll.append(label) + forms = [] + for (name, action, method, enctype), attrs, controls in fp.forms: + if action is None: + action = base_uri + else: + action = _urljoin(base_uri, action) + # would be nice to make HTMLForm class (form builder) pluggable + form = HTMLForm( + action, method, enctype, name, attrs, request_class, + forms, labels, id_to_labels, backwards_compat) + form._urlparse = _urlparse + form._urlunparse = _urlunparse + for ii in range(len(controls)): + type, name, attrs = controls[ii] + # index=ii*10 allows ImageControl to return multiple ordered pairs + form.new_control( + type, name, attrs, select_default=select_default, index=ii*10) + forms.append(form) + for form in forms: + form.fixup() + return forms + + +class Label: + def __init__(self, attrs): + self.id = attrs.get("for") + self._text = attrs.get("__text").strip() + self._ctext = compress_text(self._text) + self.attrs = attrs + self._backwards_compat = False # maintained by HTMLForm + + def __getattr__(self, name): + if name == "text": + if self._backwards_compat: + return self._text + else: + return self._ctext + return getattr(Label, name) + + def __setattr__(self, name, value): + if name == "text": + # don't see any need for this, so make it read-only + raise AttributeError("text attribute is read-only") + self.__dict__[name] = value + + def __str__(self): + return "<Label(id=%r, text=%r)>" % (self.id, self.text) + + +def _get_label(attrs): + text = attrs.get("__label") + if text is not None: + return Label(text) + else: + return None + +class Control: + """An HTML form control. + + An HTMLForm contains a sequence of Controls. The Controls in an HTMLForm + are accessed using the HTMLForm.find_control method or the + HTMLForm.controls attribute. + + Control instances are usually constructed using the ParseFile / + ParseResponse functions. If you use those functions, you can ignore the + rest of this paragraph. A Control is only properly initialised after the + fixup method has been called. In fact, this is only strictly necessary for + ListControl instances. This is necessary because ListControls are built up + from ListControls each containing only a single item, and their initial + value(s) can only be known after the sequence is complete. + + The types and values that are acceptable for assignment to the value + attribute are defined by subclasses. + + If the disabled attribute is true, this represents the state typically + represented by browsers by 'greying out' a control. If the disabled + attribute is true, the Control will raise AttributeError if an attempt is + made to change its value. In addition, the control will not be considered + 'successful' as defined by the W3C HTML 4 standard -- ie. it will + contribute no data to the return value of the HTMLForm.click* methods. To + enable a control, set the disabled attribute to a false value. + + If the readonly attribute is true, the Control will raise AttributeError if + an attempt is made to change its value. To make a control writable, set + the readonly attribute to a false value. + + All controls have the disabled and readonly attributes, not only those that + may have the HTML attributes of the same names. + + On assignment to the value attribute, the following exceptions are raised: + TypeError, AttributeError (if the value attribute should not be assigned + to, because the control is disabled, for example) and ValueError. + + If the name or value attributes are None, or the value is an empty list, or + if the control is disabled, the control is not successful. + + Public attributes: + + type: string describing type of control (see the keys of the + HTMLForm.type2class dictionary for the allowable values) (readonly) + name: name of control (readonly) + value: current value of control (subclasses may allow a single value, a + sequence of values, or either) + disabled: disabled state + readonly: readonly state + id: value of id HTML attribute + + """ + def __init__(self, type, name, attrs, index=None): + """ + type: string describing type of control (see the keys of the + HTMLForm.type2class dictionary for the allowable values) + name: control name + attrs: HTML attributes of control's HTML element + + """ + raise NotImplementedError() + + def add_to_form(self, form): + self._form = form + form.controls.append(self) + + def fixup(self): + pass + + def is_of_kind(self, kind): + raise NotImplementedError() + + def clear(self): + raise NotImplementedError() + + def __getattr__(self, name): raise NotImplementedError() + def __setattr__(self, name, value): raise NotImplementedError() + + def pairs(self): + """Return list of (key, value) pairs suitable for passing to urlencode. + """ + return [(k, v) for (i, k, v) in self._totally_ordered_pairs()] + + def _totally_ordered_pairs(self): + """Return list of (key, value, index) tuples. + + Like pairs, but allows preserving correct ordering even where several + controls are involved. + + """ + raise NotImplementedError() + + def _write_mime_data(self, mw, name, value): + """Write data for a subitem of this control to a MimeWriter.""" + # called by HTMLForm + mw2 = mw.nextpart() + mw2.addheader("Content-Disposition", + 'form-data; name="%s"' % name, 1) + f = mw2.startbody(prefix=0) + f.write(value) + + def __str__(self): + raise NotImplementedError() + + def get_labels(self): + """Return all labels (Label instances) for this control. + + If the control was surrounded by a <label> tag, that will be the first + label; all other labels, connected by 'for' and 'id', are in the order + that appear in the HTML. + + """ + res = [] + if self._label: + res.append(self._label) + if self.id: + res.extend(self._form._id_to_labels.get(self.id, ())) + return res + + +#--------------------------------------------------- +class ScalarControl(Control): + """Control whose value is not restricted to one of a prescribed set. + + Some ScalarControls don't accept any value attribute. Otherwise, takes a + single value, which must be string-like. + + Additional read-only public attribute: + + attrs: dictionary mapping the names of original HTML attributes of the + control to their values + + """ + def __init__(self, type, name, attrs, index=None): + self._index = index + self._label = _get_label(attrs) + self.__dict__["type"] = type.lower() + self.__dict__["name"] = name + self._value = attrs.get("value") + self.disabled = attrs.has_key("disabled") + self.readonly = attrs.has_key("readonly") + self.id = attrs.get("id") + + self.attrs = attrs.copy() + + self._clicked = False + + self._urlparse = urlparse.urlparse + self._urlunparse = urlparse.urlunparse + + def __getattr__(self, name): + if name == "value": + return self.__dict__["_value"] + else: + raise AttributeError("%s instance has no attribute '%s'" % + (self.__class__.__name__, name)) + + def __setattr__(self, name, value): + if name == "value": + if not isstringlike(value): + raise TypeError("must assign a string") + elif self.readonly: + raise AttributeError("control '%s' is readonly" % self.name) + elif self.disabled: + raise AttributeError("control '%s' is disabled" % self.name) + self.__dict__["_value"] = value + elif name in ("name", "type"): + raise AttributeError("%s attribute is readonly" % name) + else: + self.__dict__[name] = value + + def _totally_ordered_pairs(self): + name = self.name + value = self.value + if name is None or value is None or self.disabled: + return [] + return [(self._index, name, value)] + + def clear(self): + if self.readonly: + raise AttributeError("control '%s' is readonly" % self.name) + self.__dict__["_value"] = None + + def __str__(self): + name = self.name + value = self.value + if name is None: name = "<None>" + if value is None: value = "<None>" + + infos = [] + if self.disabled: infos.append("disabled") + if self.readonly: infos.append("readonly") + info = ", ".join(infos) + if info: info = " (%s)" % info + + return "<%s(%s=%s)%s>" % (self.__class__.__name__, name, value, info) + + +#--------------------------------------------------- +class TextControl(ScalarControl): + """Textual input control. + + Covers: + + INPUT/TEXT + INPUT/PASSWORD + INPUT/HIDDEN + TEXTAREA + + """ + def __init__(self, type, name, attrs, index=None): + ScalarControl.__init__(self, type, name, attrs, index) + if self.type == "hidden": self.readonly = True + if self._value is None: + self._value = "" + + def is_of_kind(self, kind): return kind == "text" + +#--------------------------------------------------- +class FileControl(ScalarControl): + """File upload with INPUT TYPE=FILE. + + The value attribute of a FileControl is always None. Use add_file instead. + + Additional public method: add_file + + """ + + def __init__(self, type, name, attrs, index=None): + ScalarControl.__init__(self, type, name, attrs, index) + self._value = None + self._upload_data = [] + + def is_of_kind(self, kind): return kind == "file" + + def clear(self): + if self.readonly: + raise AttributeError("control '%s' is readonly" % self.name) + self._upload_data = [] + + def __setattr__(self, name, value): + if name in ("value", "name", "type"): + raise AttributeError("%s attribute is readonly" % name) + else: + self.__dict__[name] = value + + def add_file(self, file_object, content_type=None, filename=None): + if not hasattr(file_object, "read"): + raise TypeError("file-like object must have read method") + if content_type is not None and not isstringlike(content_type): + raise TypeError("content type must be None or string-like") + if filename is not None and not isstringlike(filename): + raise TypeError("filename must be None or string-like") + if content_type is None: + content_type = "application/octet-stream" + self._upload_data.append((file_object, content_type, filename)) + + def _totally_ordered_pairs(self): + # XXX should it be successful even if unnamed? + if self.name is None or self.disabled: + return [] + return [(self._index, self.name, "")] + + def _write_mime_data(self, mw, _name, _value): + # called by HTMLForm + # assert _name == self.name and _value == '' + if len(self._upload_data) < 2: + if len(self._upload_data) == 0: + file_object = StringIO() + content_type = "application/octet-stream" + filename = "" + else: + file_object, content_type, filename = self._upload_data[0] + if filename is None: + filename = "" + mw2 = mw.nextpart() + fn_part = '; filename="%s"' % filename + disp = 'form-data; name="%s"%s' % (self.name, fn_part) + mw2.addheader("Content-Disposition", disp, prefix=1) + fh = mw2.startbody(content_type, prefix=0) + fh.write(file_object.read()) + else: + # multiple files + mw2 = mw.nextpart() + disp = 'form-data; name="%s"' % self.name + mw2.addheader("Content-Disposition", disp, prefix=1) + fh = mw2.startmultipartbody("mixed", prefix=0) + for file_object, content_type, filename in self._upload_data: + mw3 = mw2.nextpart() + if filename is None: + filename = "" + fn_part = '; filename="%s"' % filename + disp = "file%s" % fn_part + mw3.addheader("Content-Disposition", disp, prefix=1) + fh2 = mw3.startbody(content_type, prefix=0) + fh2.write(file_object.read()) + mw2.lastpart() + + def __str__(self): + name = self.name + if name is None: name = "<None>" + + if not self._upload_data: + value = "<No files added>" + else: + value = [] + for file, ctype, filename in self._upload_data: + if filename is None: + value.append("<Unnamed file>") + else: + value.append(filename) + value = ", ".join(value) + + info = [] + if self.disabled: info.append("disabled") + if self.readonly: info.append("readonly") + info = ", ".join(info) + if info: info = " (%s)" % info + + return "<%s(%s=%s)%s>" % (self.__class__.__name__, name, value, info) + + +#--------------------------------------------------- +class IsindexControl(ScalarControl): + """ISINDEX control. + + ISINDEX is the odd-one-out of HTML form controls. In fact, it isn't really + part of regular HTML forms at all, and predates it. You're only allowed + one ISINDEX per HTML document. ISINDEX and regular form submission are + mutually exclusive -- either submit a form, or the ISINDEX. + + Having said this, since ISINDEX controls may appear in forms (which is + probably bad HTML), ParseFile / ParseResponse will include them in the + HTMLForm instances it returns. You can set the ISINDEX's value, as with + any other control (but note that ISINDEX controls have no name, so you'll + need to use the type argument of set_value!). When you submit the form, + the ISINDEX will not be successful (ie., no data will get returned to the + server as a result of its presence), unless you click on the ISINDEX + control, in which case the ISINDEX gets submitted instead of the form: + + form.set_value("my isindex value", type="isindex") + urllib2.urlopen(form.click(type="isindex")) + + ISINDEX elements outside of FORMs are ignored. If you want to submit one + by hand, do it like so: + + url = urlparse.urljoin(page_uri, "?"+urllib.quote_plus("my isindex value")) + result = urllib2.urlopen(url) + + """ + def __init__(self, type, name, attrs, index=None): + ScalarControl.__init__(self, type, name, attrs, index) + if self._value is None: + self._value = "" + + def is_of_kind(self, kind): return kind in ["text", "clickable"] + + def _totally_ordered_pairs(self): + return [] + + def _click(self, form, coord, return_type, request_class=urllib2.Request): + # Relative URL for ISINDEX submission: instead of "foo=bar+baz", + # want "bar+baz". + # This doesn't seem to be specified in HTML 4.01 spec. (ISINDEX is + # deprecated in 4.01, but it should still say how to submit it). + # Submission of ISINDEX is explained in the HTML 3.2 spec, though. + parts = self._urlparse(form.action) + rest, (query, frag) = parts[:-2], parts[-2:] + parts = rest + (urllib.quote_plus(self.value), None) + url = self._urlunparse(parts) + req_data = url, None, [] + + if return_type == "pairs": + return [] + elif return_type == "request_data": + return req_data + else: + return request_class(url) + + def __str__(self): + value = self.value + if value is None: value = "<None>" + + infos = [] + if self.disabled: infos.append("disabled") + if self.readonly: infos.append("readonly") + info = ", ".join(infos) + if info: info = " (%s)" % info + + return "<%s(%s)%s>" % (self.__class__.__name__, value, info) + + +#--------------------------------------------------- +class IgnoreControl(ScalarControl): + """Control that we're not interested in. + + Covers: + + INPUT/RESET + BUTTON/RESET + INPUT/BUTTON + BUTTON/BUTTON + + These controls are always unsuccessful, in the terminology of HTML 4 (ie. + they never require any information to be returned to the server). + + BUTTON/BUTTON is used to generate events for script embedded in HTML. + + The value attribute of IgnoreControl is always None. + + """ + def __init__(self, type, name, attrs, index=None): + ScalarControl.__init__(self, type, name, attrs, index) + self._value = None + + def is_of_kind(self, kind): return False + + def __setattr__(self, name, value): + if name == "value": + raise AttributeError( + "control '%s' is ignored, hence read-only" % self.name) + elif name in ("name", "type"): + raise AttributeError("%s attribute is readonly" % name) + else: + self.__dict__[name] = value + + +#--------------------------------------------------- +# ListControls + +# helpers and subsidiary classes + +class Item: + def __init__(self, control, attrs, index=None): + label = _get_label(attrs) + self.__dict__.update({ + "name": attrs["value"], + "_labels": label and [label] or [], + "attrs": attrs, + "_control": control, + "disabled": attrs.has_key("disabled"), + "_selected": False, + "id": attrs.get("id"), + "_index": index, + }) + control.items.append(self) + + def get_labels(self): + """Return all labels (Label instances) for this item. + + For items that represent radio buttons or checkboxes, if the item was + surrounded by a <label> tag, that will be the first label; all other + labels, connected by 'for' and 'id', are in the order that appear in + the HTML. + + For items that represent select options, if the option had a label + attribute, that will be the first label. If the option has contents + (text within the option tags) and it is not the same as the label + attribute (if any), that will be a label. There is nothing in the + spec to my knowledge that makes an option with an id unable to be the + target of a label's for attribute, so those are included, if any, for + the sake of consistency and completeness. + + """ + res = [] + res.extend(self._labels) + if self.id: + res.extend(self._control._form._id_to_labels.get(self.id, ())) + return res + + def __getattr__(self, name): + if name=="selected": + return self._selected + raise AttributeError(name) + + def __setattr__(self, name, value): + if name == "selected": + self._control._set_selected_state(self, value) + elif name == "disabled": + self.__dict__["disabled"] = bool(value) + else: + raise AttributeError(name) + + def __str__(self): + res = self.name + if self.selected: + res = "*" + res + if self.disabled: + res = "(%s)" % res + return res + + def __repr__(self): + # XXX appending the attrs without distinguishing them from name and id + # is silly + attrs = [("name", self.name), ("id", self.id)]+self.attrs.items() + return "<%s %s>" % ( + self.__class__.__name__, + " ".join(["%s=%r" % (k, v) for k, v in attrs]) + ) + +def disambiguate(items, nr, **kwds): + msgs = [] + for key, value in kwds.items(): + msgs.append("%s=%r" % (key, value)) + msg = " ".join(msgs) + if not items: + raise ItemNotFoundError(msg) + if nr is None: + if len(items) > 1: + raise AmbiguityError(msg) + nr = 0 + if len(items) <= nr: + raise ItemNotFoundError(msg) + return items[nr] + +class ListControl(Control): + """Control representing a sequence of items. + + The value attribute of a ListControl represents the successful list items + in the control. The successful list items are those that are selected and + not disabled. + + ListControl implements both list controls that take a length-1 value + (single-selection) and those that take length >1 values + (multiple-selection). + + ListControls accept sequence values only. Some controls only accept + sequences of length 0 or 1 (RADIO, and single-selection SELECT). + In those cases, ItemCountError is raised if len(sequence) > 1. CHECKBOXes + and multiple-selection SELECTs (those having the "multiple" HTML attribute) + accept sequences of any length. + + Note the following mistake: + + control.value = some_value + assert control.value == some_value # not necessarily true + + The reason for this is that the value attribute always gives the list items + in the order they were listed in the HTML. + + ListControl items can also be referred to by their labels instead of names. + Use the label argument to .get(), and the .set_value_by_label(), + .get_value_by_label() methods. + + Note that, rather confusingly, though SELECT controls are represented in + HTML by SELECT elements (which contain OPTION elements, representing + individual list items), CHECKBOXes and RADIOs are not represented by *any* + element. Instead, those controls are represented by a collection of INPUT + elements. For example, this is a SELECT control, named "control1": + + <select name="control1"> + <option>foo</option> + <option value="1">bar</option> + </select> + + and this is a CHECKBOX control, named "control2": + + <input type="checkbox" name="control2" value="foo" id="cbe1"> + <input type="checkbox" name="control2" value="bar" id="cbe2"> + + The id attribute of a CHECKBOX or RADIO ListControl is always that of its + first element (for example, "cbe1" above). + + + Additional read-only public attribute: multiple. + + """ + + # ListControls are built up by the parser from their component items by + # creating one ListControl per item, consolidating them into a single + # master ListControl held by the HTMLForm: + + # -User calls form.new_control(...) + # -Form creates Control, and calls control.add_to_form(self). + # -Control looks for a Control with the same name and type in the form, + # and if it finds one, merges itself with that control by calling + # control.merge_control(self). The first Control added to the form, of + # a particular name and type, is the only one that survives in the + # form. + # -Form calls control.fixup for all its controls. ListControls in the + # form know they can now safely pick their default values. + + # To create a ListControl without an HTMLForm, use: + + # control.merge_control(new_control) + + # (actually, it's much easier just to use ParseFile) + + _label = None + + def __init__(self, type, name, attrs={}, select_default=False, + called_as_base_class=False, index=None): + """ + select_default: for RADIO and multiple-selection SELECT controls, pick + the first item as the default if no 'selected' HTML attribute is + present + + """ + if not called_as_base_class: + raise NotImplementedError() + + self.__dict__["type"] = type.lower() + self.__dict__["name"] = name + self._value = attrs.get("value") + self.disabled = False + self.readonly = False + self.id = attrs.get("id") + self._closed = False + + # As Controls are merged in with .merge_control(), self.attrs will + # refer to each Control in turn -- always the most recently merged + # control. Each merged-in Control instance corresponds to a single + # list item: see ListControl.__doc__. + self.items = [] + self._form = None + + self._select_default = select_default + self._clicked = False + + def clear(self): + self.value = [] + + def is_of_kind(self, kind): + if kind == "list": + return True + elif kind == "multilist": + return bool(self.multiple) + elif kind == "singlelist": + return not self.multiple + else: + return False + + def get_items(self, name=None, label=None, id=None, + exclude_disabled=False): + """Return matching items by name or label. + + For argument docs, see the docstring for .get() + + """ + if name is not None and not isstringlike(name): + raise TypeError("item name must be string-like") + if label is not None and not isstringlike(label): + raise TypeError("item label must be string-like") + if id is not None and not isstringlike(id): + raise TypeError("item id must be string-like") + items = [] # order is important + compat = self._form.backwards_compat + for o in self.items: + if exclude_disabled and o.disabled: + continue + if name is not None and o.name != name: + continue + if label is not None: + for l in o.get_labels(): + if ((compat and l.text == label) or + (not compat and l.text.find(label) > -1)): + break + else: + continue + if id is not None and o.id != id: + continue + items.append(o) + return items + + def get(self, name=None, label=None, id=None, nr=None, + exclude_disabled=False): + """Return item by name or label, disambiguating if necessary with nr. + + All arguments must be passed by name, with the exception of 'name', + which may be used as a positional argument. + + If name is specified, then the item must have the indicated name. + + If label is specified, then the item must have a label whose + whitespace-compressed, stripped, text substring-matches the indicated + label string (eg. label="please choose" will match + " Do please choose an item "). + + If id is specified, then the item must have the indicated id. + + nr is an optional 0-based index of the items matching the query. + + If nr is the default None value and more than item is found, raises + AmbiguityError (unless the HTMLForm instance's backwards_compat + attribute is true). + + If no item is found, or if items are found but nr is specified and not + found, raises ItemNotFoundError. + + Optionally excludes disabled items. + + """ + if nr is None and self._form.backwards_compat: + nr = 0 # :-/ + items = self.get_items(name, label, id, exclude_disabled) + return disambiguate(items, nr, name=name, label=label, id=id) + + def _get(self, name, by_label=False, nr=None, exclude_disabled=False): + # strictly for use by deprecated methods + if by_label: + name, label = None, name + else: + name, label = name, None + return self.get(name, label, nr, exclude_disabled) + + def toggle(self, name, by_label=False, nr=None): + """Deprecated: given a name or label and optional disambiguating index + nr, toggle the matching item's selection. + + Selecting items follows the behavior described in the docstring of the + 'get' method. + + if the item is disabled, or this control is disabled or readonly, + raise AttributeError. + + """ + deprecation( + "item = control.get(...); item.selected = not item.selected") + o = self._get(name, by_label, nr) + self._set_selected_state(o, not o.selected) + + def set(self, selected, name, by_label=False, nr=None): + """Deprecated: given a name or label and optional disambiguating index + nr, set the matching item's selection to the bool value of selected. + + Selecting items follows the behavior described in the docstring of the + 'get' method. + + if the item is disabled, or this control is disabled or readonly, + raise AttributeError. + + """ + deprecation( + "control.get(...).selected = <boolean>") + self._set_selected_state(self._get(name, by_label, nr), selected) + + def _set_selected_state(self, item, action): + # action: + # bool False: off + # bool True: on + if self.disabled: + raise AttributeError("control '%s' is disabled" % self.name) + if self.readonly: + raise AttributeError("control '%s' is readonly" % self.name) + action == bool(action) + compat = self._form.backwards_compat + if not compat and item.disabled: + raise AttributeError("item is disabled") + else: + if compat and item.disabled and action: + raise AttributeError("item is disabled") + if self.multiple: + item.__dict__["_selected"] = action + else: + if not action: + item.__dict__["_selected"] = False + else: + for o in self.items: + o.__dict__["_selected"] = False + item.__dict__["_selected"] = True + + def toggle_single(self, by_label=None): + """Deprecated: toggle the selection of the single item in this control. + + Raises ItemCountError if the control does not contain only one item. + + by_label argument is ignored, and included only for backwards + compatibility. + + """ + deprecation( + "control.items[0].selected = not control.items[0].selected") + if len(self.items) != 1: + raise ItemCountError( + "'%s' is not a single-item control" % self.name) + item = self.items[0] + self._set_selected_state(item, not item.selected) + + def set_single(self, selected, by_label=None): + """Deprecated: set the selection of the single item in this control. + + Raises ItemCountError if the control does not contain only one item. + + by_label argument is ignored, and included only for backwards + compatibility. + + """ + deprecation( + "control.items[0].selected = <boolean>") + if len(self.items) != 1: + raise ItemCountError( + "'%s' is not a single-item control" % self.name) + self._set_selected_state(self.items[0], selected) + + def get_item_disabled(self, name, by_label=False, nr=None): + """Get disabled state of named list item in a ListControl.""" + deprecation( + "control.get(...).disabled") + return self._get(name, by_label, nr).disabled + + def set_item_disabled(self, disabled, name, by_label=False, nr=None): + """Set disabled state of named list item in a ListControl. + + disabled: boolean disabled state + + """ + deprecation( + "control.get(...).disabled = <boolean>") + self._get(name, by_label, nr).disabled = disabled + + def set_all_items_disabled(self, disabled): + """Set disabled state of all list items in a ListControl. + + disabled: boolean disabled state + + """ + for o in self.items: + o.disabled = disabled + + def get_item_attrs(self, name, by_label=False, nr=None): + """Return dictionary of HTML attributes for a single ListControl item. + + The HTML element types that describe list items are: OPTION for SELECT + controls, INPUT for the rest. These elements have HTML attributes that + you may occasionally want to know about -- for example, the "alt" HTML + attribute gives a text string describing the item (graphical browsers + usually display this as a tooltip). + + The returned dictionary maps HTML attribute names to values. The names + and values are taken from the original HTML. + + """ + deprecation( + "control.get(...).attrs") + return self._get(name, by_label, nr).attrs + + def close_control(self): + self._closed = True + + def add_to_form(self, form): + assert self._form is None or form == self._form, ( + "can't add control to more than one form") + self._form = form + if self.name is None: + # always count nameless elements as separate controls + Control.add_to_form(self, form) + else: + for ii in range(len(form.controls)-1, -1, -1): + control = form.controls[ii] + if control.name == self.name and control.type == self.type: + if control._closed: + Control.add_to_form(self, form) + else: + control.merge_control(self) + break + else: + Control.add_to_form(self, form) + + def merge_control(self, control): + assert bool(control.multiple) == bool(self.multiple) + # usually, isinstance(control, self.__class__) + self.items.extend(control.items) + + def fixup(self): + """ + ListControls are built up from component list items (which are also + ListControls) during parsing. This method should be called after all + items have been added. See ListControl.__doc__ for the reason this is + required. + + """ + # Need to set default selection where no item was indicated as being + # selected by the HTML: + + # CHECKBOX: + # Nothing should be selected. + # SELECT/single, SELECT/multiple and RADIO: + # RFC 1866 (HTML 2.0): says first item should be selected. + # W3C HTML 4.01 Specification: says that client behaviour is + # undefined in this case. For RADIO, exactly one must be selected, + # though which one is undefined. + # Both Netscape and Microsoft Internet Explorer (IE) choose first + # item for SELECT/single. However, both IE5 and Mozilla (both 1.0 + # and Firebird 0.6) leave all items unselected for RADIO and + # SELECT/multiple. + + # Since both Netscape and IE all choose the first item for + # SELECT/single, we do the same. OTOH, both Netscape and IE + # leave SELECT/multiple with nothing selected, in violation of RFC 1866 + # (but not in violation of the W3C HTML 4 standard); the same is true + # of RADIO (which *is* in violation of the HTML 4 standard). We follow + # RFC 1866 if the _select_default attribute is set, and Netscape and IE + # otherwise. RFC 1866 and HTML 4 are always violated insofar as you + # can deselect all items in a RadioControl. + + for o in self.items: + # set items' controls to self, now that we've merged + o.__dict__["_control"] = self + + def __getattr__(self, name): + if name == "value": + compat = self._form.backwards_compat + if self.name is None: + return [] + return [o.name for o in self.items if o.selected and + (not o.disabled or compat)] + else: + raise AttributeError("%s instance has no attribute '%s'" % + (self.__class__.__name__, name)) + + def __setattr__(self, name, value): + if name == "value": + if self.disabled: + raise AttributeError("control '%s' is disabled" % self.name) + if self.readonly: + raise AttributeError("control '%s' is readonly" % self.name) + self._set_value(value) + elif name in ("name", "type", "multiple"): + raise AttributeError("%s attribute is readonly" % name) + else: + self.__dict__[name] = value + + def _set_value(self, value): + if value is None or isstringlike(value): + raise TypeError("ListControl, must set a sequence") + if not value: + compat = self._form.backwards_compat + for o in self.items: + if not o.disabled or compat: + o.selected = False + elif self.multiple: + self._multiple_set_value(value) + elif len(value) > 1: + raise ItemCountError( + "single selection list, must set sequence of " + "length 0 or 1") + else: + self._single_set_value(value) + + def _get_items(self, name, target=1): + all_items = self.get_items(name) + items = [o for o in all_items if not o.disabled] + if len(items) < target: + if len(all_items) < target: + raise ItemNotFoundError( + "insufficient items with name %r" % name) + else: + raise AttributeError( + "insufficient non-disabled items with name %s" % name) + on = [] + off = [] + for o in items: + if o.selected: + on.append(o) + else: + off.append(o) + return on, off + + def _single_set_value(self, value): + assert len(value) == 1 + on, off = self._get_items(value[0]) + assert len(on) <= 1 + if not on: + off[0].selected = True + + def _multiple_set_value(self, value): + compat = self._form.backwards_compat + turn_on = [] # transactional-ish + turn_off = [item for item in self.items if + item.selected and (not item.disabled or compat)] + names = {} + for nn in value: + if nn in names.keys(): + names[nn] += 1 + else: + names[nn] = 1 + for name, count in names.items(): + on, off = self._get_items(name, count) + for i in range(count): + if on: + item = on[0] + del on[0] + del turn_off[turn_off.index(item)] + else: + item = off[0] + del off[0] + turn_on.append(item) + for item in turn_off: + item.selected = False + for item in turn_on: + item.selected = True + + def set_value_by_label(self, value): + """Set the value of control by item labels. + + value is expected to be an iterable of strings that are substrings of + the item labels that should be selected. Before substring matching is + performed, the original label text is whitespace-compressed + (consecutive whitespace characters are converted to a single space + character) and leading and trailing whitespace is stripped. Ambiguous + labels are accepted without complaint if the form's backwards_compat is + True; otherwise, it will not complain as long as all ambiguous labels + share the same item name (e.g. OPTION value). + + """ + if isstringlike(value): + raise TypeError(value) + if not self.multiple and len(value) > 1: + raise ItemCountError( + "single selection list, must set sequence of " + "length 0 or 1") + items = [] + for nn in value: + found = self.get_items(label=nn) + if len(found) > 1: + if not self._form.backwards_compat: + # ambiguous labels are fine as long as item names (e.g. + # OPTION values) are same + opt_name = found[0].name + if [o for o in found[1:] if o.name != opt_name]: + raise AmbiguityError(nn) + else: + # OK, we'll guess :-( Assume first available item. + found = found[:1] + for o in found: + # For the multiple-item case, we could try to be smarter, + # saving them up and trying to resolve, but that's too much. + if self._form.backwards_compat or o not in items: + items.append(o) + break + else: # all of them are used + raise ItemNotFoundError(nn) + # now we have all the items that should be on + # let's just turn everything off and then back on. + self.value = [] + for o in items: + o.selected = True + + def get_value_by_label(self): + """Return the value of the control as given by normalized labels.""" + res = [] + compat = self._form.backwards_compat + for o in self.items: + if (not o.disabled or compat) and o.selected: + for l in o.get_labels(): + if l.text: + res.append(l.text) + break + else: + res.append(None) + return res + + def possible_items(self, by_label=False): + """Deprecated: return the names or labels of all possible items. + + Includes disabled items, which may be misleading for some use cases. + + """ + deprecation( + "[item.name for item in self.items]") + if by_label: + res = [] + for o in self.items: + for l in o.get_labels(): + if l.text: + res.append(l.text) + break + else: + res.append(None) + return res + return [o.name for o in self.items] + + def _totally_ordered_pairs(self): + if self.disabled or self.name is None: + return [] + else: + return [(o._index, self.name, o.name) for o in self.items + if o.selected and not o.disabled] + + def __str__(self): + name = self.name + if name is None: name = "<None>" + + display = [str(o) for o in self.items] + + infos = [] + if self.disabled: infos.append("disabled") + if self.readonly: infos.append("readonly") + info = ", ".join(infos) + if info: info = " (%s)" % info + + return "<%s(%s=[%s])%s>" % (self.__class__.__name__, + name, ", ".join(display), info) + + +class RadioControl(ListControl): + """ + Covers: + + INPUT/RADIO + + """ + def __init__(self, type, name, attrs, select_default=False, index=None): + attrs.setdefault("value", "on") + ListControl.__init__(self, type, name, attrs, select_default, + called_as_base_class=True, index=index) + self.__dict__["multiple"] = False + o = Item(self, attrs, index) + o.__dict__["_selected"] = attrs.has_key("checked") + + def fixup(self): + ListControl.fixup(self) + found = [o for o in self.items if o.selected and not o.disabled] + if not found: + if self._select_default: + for o in self.items: + if not o.disabled: + o.selected = True + break + else: + # Ensure only one item selected. Choose the last one, + # following IE and Firefox. + for o in found[:-1]: + o.selected = False + + def get_labels(self): + return [] + +class CheckboxControl(ListControl): + """ + Covers: + + INPUT/CHECKBOX + + """ + def __init__(self, type, name, attrs, select_default=False, index=None): + attrs.setdefault("value", "on") + ListControl.__init__(self, type, name, attrs, select_default, + called_as_base_class=True, index=index) + self.__dict__["multiple"] = True + o = Item(self, attrs, index) + o.__dict__["_selected"] = attrs.has_key("checked") + + def get_labels(self): + return [] + + +class SelectControl(ListControl): + """ + Covers: + + SELECT (and OPTION) + + + OPTION 'values', in HTML parlance, are Item 'names' in ClientForm parlance. + + SELECT control values and labels are subject to some messy defaulting + rules. For example, if the HTML representation of the control is: + + <SELECT name=year> + <OPTION value=0 label="2002">current year</OPTION> + <OPTION value=1>2001</OPTION> + <OPTION>2000</OPTION> + </SELECT> + + The items, in order, have labels "2002", "2001" and "2000", whereas their + names (the OPTION values) are "0", "1" and "2000" respectively. Note that + the value of the last OPTION in this example defaults to its contents, as + specified by RFC 1866, as do the labels of the second and third OPTIONs. + + The OPTION labels are sometimes more meaningful than the OPTION values, + which can make for more maintainable code. + + Additional read-only public attribute: attrs + + The attrs attribute is a dictionary of the original HTML attributes of the + SELECT element. Other ListControls do not have this attribute, because in + other cases the control as a whole does not correspond to any single HTML + element. control.get(...).attrs may be used as usual to get at the HTML + attributes of the HTML elements corresponding to individual list items (for + SELECT controls, these are OPTION elements). + + Another special case is that the Item.attrs dictionaries have a special key + "contents" which does not correspond to any real HTML attribute, but rather + contains the contents of the OPTION element: + + <OPTION>this bit</OPTION> + + """ + # HTML attributes here are treated slightly differently from other list + # controls: + # -The SELECT HTML attributes dictionary is stuffed into the OPTION + # HTML attributes dictionary under the "__select" key. + # -The content of each OPTION element is stored under the special + # "contents" key of the dictionary. + # After all this, the dictionary is passed to the SelectControl constructor + # as the attrs argument, as usual. However: + # -The first SelectControl constructed when building up a SELECT control + # has a constructor attrs argument containing only the __select key -- so + # this SelectControl represents an empty SELECT control. + # -Subsequent SelectControls have both OPTION HTML-attribute in attrs and + # the __select dictionary containing the SELECT HTML-attributes. + + def __init__(self, type, name, attrs, select_default=False, index=None): + # fish out the SELECT HTML attributes from the OPTION HTML attributes + # dictionary + self.attrs = attrs["__select"].copy() + self.__dict__["_label"] = _get_label(self.attrs) + self.__dict__["id"] = self.attrs.get("id") + self.__dict__["multiple"] = self.attrs.has_key("multiple") + # the majority of the contents, label, and value dance already happened + contents = attrs.get("contents") + attrs = attrs.copy() + del attrs["__select"] + + ListControl.__init__(self, type, name, self.attrs, select_default, + called_as_base_class=True, index=index) + self.disabled = self.attrs.has_key("disabled") + self.readonly = self.attrs.has_key("readonly") + if attrs.has_key("value"): + # otherwise it is a marker 'select started' token + o = Item(self, attrs, index) + o.__dict__["_selected"] = attrs.has_key("selected") + # add 'label' label and contents label, if different. If both are + # provided, the 'label' label is used for display in HTML + # 4.0-compliant browsers (and any lower spec? not sure) while the + # contents are used for display in older or less-compliant + # browsers. We make label objects for both, if the values are + # different. + label = attrs.get("label") + if label: + o._labels.append(Label({"__text": label})) + if contents and contents != label: + o._labels.append(Label({"__text": contents})) + elif contents: + o._labels.append(Label({"__text": contents})) + + def fixup(self): + ListControl.fixup(self) + # Firefox doesn't exclude disabled items from those considered here + # (i.e. from 'found', for both branches of the if below). Note that + # IE6 doesn't support the disabled attribute on OPTIONs at all. + found = [o for o in self.items if o.selected] + if not found: + if not self.multiple or self._select_default: + for o in self.items: + if not o.disabled: + was_disabled = self.disabled + self.disabled = False + try: + o.selected = True + finally: + o.disabled = was_disabled + break + elif not self.multiple: + # Ensure only one item selected. Choose the last one, + # following IE and Firefox. + for o in found[:-1]: + o.selected = False + + +#--------------------------------------------------- +class SubmitControl(ScalarControl): + """ + Covers: + + INPUT/SUBMIT + BUTTON/SUBMIT + + """ + def __init__(self, type, name, attrs, index=None): + ScalarControl.__init__(self, type, name, attrs, index) + # IE5 defaults SUBMIT value to "Submit Query"; Firebird 0.6 leaves it + # blank, Konqueror 3.1 defaults to "Submit". HTML spec. doesn't seem + # to define this. + if self.value is None: self.value = "" + self.readonly = True + + def get_labels(self): + res = [] + if self.value: + res.append(Label({"__text": self.value})) + res.extend(ScalarControl.get_labels(self)) + return res + + def is_of_kind(self, kind): return kind == "clickable" + + def _click(self, form, coord, return_type, request_class=urllib2.Request): + self._clicked = coord + r = form._switch_click(return_type, request_class) + self._clicked = False + return r + + def _totally_ordered_pairs(self): + if not self._clicked: + return [] + return ScalarControl._totally_ordered_pairs(self) + + +#--------------------------------------------------- +class ImageControl(SubmitControl): + """ + Covers: + + INPUT/IMAGE + + Coordinates are specified using one of the HTMLForm.click* methods. + + """ + def __init__(self, type, name, attrs, index=None): + SubmitControl.__init__(self, type, name, attrs, index) + self.readonly = False + + def _totally_ordered_pairs(self): + clicked = self._clicked + if self.disabled or not clicked: + return [] + name = self.name + if name is None: return [] + pairs = [ + (self._index, "%s.x" % name, str(clicked[0])), + (self._index+1, "%s.y" % name, str(clicked[1])), + ] + value = self._value + if value: + pairs.append((self._index+2, name, value)) + return pairs + + get_labels = ScalarControl.get_labels + +# aliases, just to make str(control) and str(form) clearer +class PasswordControl(TextControl): pass +class HiddenControl(TextControl): pass +class TextareaControl(TextControl): pass +class SubmitButtonControl(SubmitControl): pass + + +def is_listcontrol(control): return control.is_of_kind("list") + + +class HTMLForm: + """Represents a single HTML <form> ... </form> element. + + A form consists of a sequence of controls that usually have names, and + which can take on various values. The values of the various types of + controls represent variously: text, zero-or-one-of-many or many-of-many + choices, and files to be uploaded. Some controls can be clicked on to + submit the form, and clickable controls' values sometimes include the + coordinates of the click. + + Forms can be filled in with data to be returned to the server, and then + submitted, using the click method to generate a request object suitable for + passing to urllib2.urlopen (or the click_request_data or click_pairs + methods if you're not using urllib2). + + import ClientForm + forms = ClientForm.ParseFile(html, base_uri) + form = forms[0] + + form["query"] = "Python" + form.find_control("nr_results").get("lots").selected = True + + response = urllib2.urlopen(form.click()) + + Usually, HTMLForm instances are not created directly. Instead, the + ParseFile or ParseResponse factory functions are used. If you do construct + HTMLForm objects yourself, however, note that an HTMLForm instance is only + properly initialised after the fixup method has been called (ParseFile and + ParseResponse do this for you). See ListControl.__doc__ for the reason + this is required. + + Indexing a form (form["control_name"]) returns the named Control's value + attribute. Assignment to a form index (form["control_name"] = something) + is equivalent to assignment to the named Control's value attribute. If you + need to be more specific than just supplying the control's name, use the + set_value and get_value methods. + + ListControl values are lists of item names (specifically, the names of the + items that are selected and not disabled, and hence are "successful" -- ie. + cause data to be returned to the server). The list item's name is the + value of the corresponding HTML element's"value" attribute. + + Example: + + <INPUT type="CHECKBOX" name="cheeses" value="leicester"></INPUT> + <INPUT type="CHECKBOX" name="cheeses" value="cheddar"></INPUT> + + defines a CHECKBOX control with name "cheeses" which has two items, named + "leicester" and "cheddar". + + Another example: + + <SELECT name="more_cheeses"> + <OPTION>1</OPTION> + <OPTION value="2" label="CHEDDAR">cheddar</OPTION> + </SELECT> + + defines a SELECT control with name "more_cheeses" which has two items, + named "1" and "2" (because the OPTION element's value HTML attribute + defaults to the element contents -- see SelectControl.__doc__ for more on + these defaulting rules). + + To select, deselect or otherwise manipulate individual list items, use the + HTMLForm.find_control() and ListControl.get() methods. To set the whole + value, do as for any other control: use indexing or the set_/get_value + methods. + + Example: + + # select *only* the item named "cheddar" + form["cheeses"] = ["cheddar"] + # select "cheddar", leave other items unaffected + form.find_control("cheeses").get("cheddar").selected = True + + Some controls (RADIO and SELECT without the multiple attribute) can only + have zero or one items selected at a time. Some controls (CHECKBOX and + SELECT with the multiple attribute) can have multiple items selected at a + time. To set the whole value of a ListControl, assign a sequence to a form + index: + + form["cheeses"] = ["cheddar", "leicester"] + + If the ListControl is not multiple-selection, the assigned list must be of + length one. + + To check if a control has an item, if an item is selected, or if an item is + successful (selected and not disabled), respectively: + + "cheddar" in [item.name for item in form.find_control("cheeses").items] + "cheddar" in [item.name for item in form.find_control("cheeses").items and + item.selected] + "cheddar" in form["cheeses"] # (or "cheddar" in form.get_value("cheeses")) + + Note that some list items may be disabled (see below). + + Note the following mistake: + + form[control_name] = control_value + assert form[control_name] == control_value # not necessarily true + + The reason for this is that form[control_name] always gives the list items + in the order they were listed in the HTML. + + List items (hence list values, too) can be referred to in terms of list + item labels rather than list item names using the appropriate label + arguments. Note that each item may have several labels. + + The question of default values of OPTION contents, labels and values is + somewhat complicated: see SelectControl.__doc__ and + ListControl.get_item_attrs.__doc__ if you think you need to know. + + Controls can be disabled or readonly. In either case, the control's value + cannot be changed until you clear those flags (see example below). + Disabled is the state typically represented by browsers by 'greying out' a + control. Disabled controls are not 'successful' -- they don't cause data + to get returned to the server. Readonly controls usually appear in + browsers as read-only text boxes. Readonly controls are successful. List + items can also be disabled. Attempts to select or deselect disabled items + fail with AttributeError. + + If a lot of controls are readonly, it can be useful to do this: + + form.set_all_readonly(False) + + To clear a control's value attribute, so that it is not successful (until a + value is subsequently set): + + form.clear("cheeses") + + More examples: + + control = form.find_control("cheeses") + control.disabled = False + control.readonly = False + control.get("gruyere").disabled = True + control.items[0].selected = True + + See the various Control classes for further documentation. Many methods + take name, type, kind, id, label and nr arguments to specify the control to + be operated on: see HTMLForm.find_control.__doc__. + + ControlNotFoundError (subclass of ValueError) is raised if the specified + control can't be found. This includes occasions where a non-ListControl + is found, but the method (set, for example) requires a ListControl. + ItemNotFoundError (subclass of ValueError) is raised if a list item can't + be found. ItemCountError (subclass of ValueError) is raised if an attempt + is made to select more than one item and the control doesn't allow that, or + set/get_single are called and the control contains more than one item. + AttributeError is raised if a control or item is readonly or disabled and + an attempt is made to alter its value. + + Security note: Remember that any passwords you store in HTMLForm instances + will be saved to disk in the clear if you pickle them (directly or + indirectly). The simplest solution to this is to avoid pickling HTMLForm + objects. You could also pickle before filling in any password, or just set + the password to "" before pickling. + + + Public attributes: + + action: full (absolute URI) form action + method: "GET" or "POST" + enctype: form transfer encoding MIME type + name: name of form (None if no name was specified) + attrs: dictionary mapping original HTML form attributes to their values + + controls: list of Control instances; do not alter this list + (instead, call form.new_control to make a Control and add it to the + form, or control.add_to_form if you already have a Control instance) + + + + Methods for form filling: + ------------------------- + + Most of the these methods have very similar arguments. See + HTMLForm.find_control.__doc__ for details of the name, type, kind, label + and nr arguments. + + def find_control(self, + name=None, type=None, kind=None, id=None, predicate=None, + nr=None, label=None) + + get_value(name=None, type=None, kind=None, id=None, nr=None, + by_label=False, # by_label is deprecated + label=None) + set_value(value, + name=None, type=None, kind=None, id=None, nr=None, + by_label=False, # by_label is deprecated + label=None) + + clear_all() + clear(name=None, type=None, kind=None, id=None, nr=None, label=None) + + set_all_readonly(readonly) + + + Method applying only to FileControls: + + add_file(file_object, + content_type="application/octet-stream", filename=None, + name=None, id=None, nr=None, label=None) + + + Methods applying only to clickable controls: + + click(name=None, type=None, id=None, nr=0, coord=(1,1), label=None) + click_request_data(name=None, type=None, id=None, nr=0, coord=(1,1), + label=None) + click_pairs(name=None, type=None, id=None, nr=0, coord=(1,1), label=None) + + """ + + type2class = { + "text": TextControl, + "password": PasswordControl, + "hidden": HiddenControl, + "textarea": TextareaControl, + + "isindex": IsindexControl, + + "file": FileControl, + + "button": IgnoreControl, + "buttonbutton": IgnoreControl, + "reset": IgnoreControl, + "resetbutton": IgnoreControl, + + "submit": SubmitControl, + "submitbutton": SubmitButtonControl, + "image": ImageControl, + + "radio": RadioControl, + "checkbox": CheckboxControl, + "select": SelectControl, + } + +#--------------------------------------------------- +# Initialisation. Use ParseResponse / ParseFile instead. + + def __init__(self, action, method="GET", + enctype="application/x-www-form-urlencoded", + name=None, attrs=None, + request_class=urllib2.Request, + forms=None, labels=None, id_to_labels=None, + backwards_compat=True): + """ + In the usual case, use ParseResponse (or ParseFile) to create new + HTMLForm objects. + + action: full (absolute URI) form action + method: "GET" or "POST" + enctype: form transfer encoding MIME type + name: name of form + attrs: dictionary mapping original HTML form attributes to their values + + """ + self.action = action + self.method = method + self.enctype = enctype + self.name = name + if attrs is not None: + self.attrs = attrs.copy() + else: + self.attrs = {} + self.controls = [] + self._request_class = request_class + + # these attributes are used by zope.testbrowser + self._forms = forms # this is a semi-public API! + self._labels = labels # this is a semi-public API! + self._id_to_labels = id_to_labels # this is a semi-public API! + + self.backwards_compat = backwards_compat # note __setattr__ + + self._urlunparse = urlparse.urlunparse + self._urlparse = urlparse.urlparse + + def __getattr__(self, name): + if name == "backwards_compat": + return self._backwards_compat + return getattr(HTMLForm, name) + + def __setattr__(self, name, value): + # yuck + if name == "backwards_compat": + name = "_backwards_compat" + value = bool(value) + for cc in self.controls: + try: + items = cc.items + except AttributeError: + continue + else: + for ii in items: + for ll in ii.get_labels(): + ll._backwards_compat = value + self.__dict__[name] = value + + def new_control(self, type, name, attrs, + ignore_unknown=False, select_default=False, index=None): + """Adds a new control to the form. + + This is usually called by ParseFile and ParseResponse. Don't call it + youself unless you're building your own Control instances. + + Note that controls representing lists of items are built up from + controls holding only a single list item. See ListControl.__doc__ for + further information. + + type: type of control (see Control.__doc__ for a list) + attrs: HTML attributes of control + ignore_unknown: if true, use a dummy Control instance for controls of + unknown type; otherwise, use a TextControl + select_default: for RADIO and multiple-selection SELECT controls, pick + the first item as the default if no 'selected' HTML attribute is + present (this defaulting happens when the HTMLForm.fixup method is + called) + index: index of corresponding element in HTML (see + MoreFormTests.test_interspersed_controls for motivation) + + """ + type = type.lower() + klass = self.type2class.get(type) + if klass is None: + if ignore_unknown: + klass = IgnoreControl + else: + klass = TextControl + + a = attrs.copy() + if issubclass(klass, ListControl): + control = klass(type, name, a, select_default, index) + else: + control = klass(type, name, a, index) + + if type == "select" and len(attrs) == 1: + for ii in range(len(self.controls)-1, -1, -1): + ctl = self.controls[ii] + if ctl.type == "select": + ctl.close_control() + break + + control.add_to_form(self) + control._urlparse = self._urlparse + control._urlunparse = self._urlunparse + + def fixup(self): + """Normalise form after all controls have been added. + + This is usually called by ParseFile and ParseResponse. Don't call it + youself unless you're building your own Control instances. + + This method should only be called once, after all controls have been + added to the form. + + """ + for control in self.controls: + control.fixup() + self.backwards_compat = self._backwards_compat + +#--------------------------------------------------- + def __str__(self): + header = "%s%s %s %s" % ( + (self.name and self.name+" " or ""), + self.method, self.action, self.enctype) + rep = [header] + for control in self.controls: + rep.append(" %s" % str(control)) + return "<%s>" % "\n".join(rep) + +#--------------------------------------------------- +# Form-filling methods. + + def __getitem__(self, name): + return self.find_control(name).value + def __contains__(self, name): + return bool(self.find_control(name)) + def __setitem__(self, name, value): + control = self.find_control(name) + try: + control.value = value + except AttributeError, e: + raise ValueError(str(e)) + + def get_value(self, + name=None, type=None, kind=None, id=None, nr=None, + by_label=False, # by_label is deprecated + label=None): + """Return value of control. + + If only name and value arguments are supplied, equivalent to + + form[name] + + """ + if by_label: + deprecation("form.get_value_by_label(...)") + c = self.find_control(name, type, kind, id, label=label, nr=nr) + if by_label: + try: + meth = c.get_value_by_label + except AttributeError: + raise NotImplementedError( + "control '%s' does not yet support by_label" % c.name) + else: + return meth() + else: + return c.value + def set_value(self, value, + name=None, type=None, kind=None, id=None, nr=None, + by_label=False, # by_label is deprecated + label=None): + """Set value of control. + + If only name and value arguments are supplied, equivalent to + + form[name] = value + + """ + if by_label: + deprecation("form.get_value_by_label(...)") + c = self.find_control(name, type, kind, id, label=label, nr=nr) + if by_label: + try: + meth = c.set_value_by_label + except AttributeError: + raise NotImplementedError( + "control '%s' does not yet support by_label" % c.name) + else: + meth(value) + else: + c.value = value + def get_value_by_label( + self, name=None, type=None, kind=None, id=None, label=None, nr=None): + """ + + All arguments should be passed by name. + + """ + c = self.find_control(name, type, kind, id, label=label, nr=nr) + return c.get_value_by_label() + + def set_value_by_label( + self, value, + name=None, type=None, kind=None, id=None, label=None, nr=None): + """ + + All arguments should be passed by name. + + """ + c = self.find_control(name, type, kind, id, label=label, nr=nr) + c.set_value_by_label(value) + + def set_all_readonly(self, readonly): + for control in self.controls: + control.readonly = bool(readonly) + + def clear_all(self): + """Clear the value attributes of all controls in the form. + + See HTMLForm.clear.__doc__. + + """ + for control in self.controls: + control.clear() + + def clear(self, + name=None, type=None, kind=None, id=None, nr=None, label=None): + """Clear the value attribute of a control. + + As a result, the affected control will not be successful until a value + is subsequently set. AttributeError is raised on readonly controls. + + """ + c = self.find_control(name, type, kind, id, label=label, nr=nr) + c.clear() + + +#--------------------------------------------------- +# Form-filling methods applying only to ListControls. + + def possible_items(self, # deprecated + name=None, type=None, kind=None, id=None, + nr=None, by_label=False, label=None): + """Return a list of all values that the specified control can take.""" + c = self._find_list_control(name, type, kind, id, label, nr) + return c.possible_items(by_label) + + def set(self, selected, item_name, # deprecated + name=None, type=None, kind=None, id=None, nr=None, + by_label=False, label=None): + """Select / deselect named list item. + + selected: boolean selected state + + """ + self._find_list_control(name, type, kind, id, label, nr).set( + selected, item_name, by_label) + def toggle(self, item_name, # deprecated + name=None, type=None, kind=None, id=None, nr=None, + by_label=False, label=None): + """Toggle selected state of named list item.""" + self._find_list_control(name, type, kind, id, label, nr).toggle( + item_name, by_label) + + def set_single(self, selected, # deprecated + name=None, type=None, kind=None, id=None, + nr=None, by_label=None, label=None): + """Select / deselect list item in a control having only one item. + + If the control has multiple list items, ItemCountError is raised. + + This is just a convenience method, so you don't need to know the item's + name -- the item name in these single-item controls is usually + something meaningless like "1" or "on". + + For example, if a checkbox has a single item named "on", the following + two calls are equivalent: + + control.toggle("on") + control.toggle_single() + + """ # by_label ignored and deprecated + self._find_list_control( + name, type, kind, id, label, nr).set_single(selected) + def toggle_single(self, name=None, type=None, kind=None, id=None, + nr=None, by_label=None, label=None): # deprecated + """Toggle selected state of list item in control having only one item. + + The rest is as for HTMLForm.set_single.__doc__. + + """ # by_label ignored and deprecated + self._find_list_control(name, type, kind, id, label, nr).toggle_single() + +#--------------------------------------------------- +# Form-filling method applying only to FileControls. + + def add_file(self, file_object, content_type=None, filename=None, + name=None, id=None, nr=None, label=None): + """Add a file to be uploaded. + + file_object: file-like object (with read method) from which to read + data to upload + content_type: MIME content type of data to upload + filename: filename to pass to server + + If filename is None, no filename is sent to the server. + + If content_type is None, the content type is guessed based on the + filename and the data from read from the file object. + + XXX + At the moment, guessed content type is always application/octet-stream. + Use sndhdr, imghdr modules. Should also try to guess HTML, XML, and + plain text. + + Note the following useful HTML attributes of file upload controls (see + HTML 4.01 spec, section 17): + + accept: comma-separated list of content types that the server will + handle correctly; you can use this to filter out non-conforming files + size: XXX IIRC, this is indicative of whether form wants multiple or + single files + maxlength: XXX hint of max content length in bytes? + + """ + self.find_control(name, "file", id=id, label=label, nr=nr).add_file( + file_object, content_type, filename) + +#--------------------------------------------------- +# Form submission methods, applying only to clickable controls. + + def click(self, name=None, type=None, id=None, nr=0, coord=(1,1), + request_class=urllib2.Request, + label=None): + """Return request that would result from clicking on a control. + + The request object is a urllib2.Request instance, which you can pass to + urllib2.urlopen (or ClientCookie.urlopen). + + Only some control types (INPUT/SUBMIT & BUTTON/SUBMIT buttons and + IMAGEs) can be clicked. + + Will click on the first clickable control, subject to the name, type + and nr arguments (as for find_control). If no name, type, id or number + is specified and there are no clickable controls, a request will be + returned for the form in its current, un-clicked, state. + + IndexError is raised if any of name, type, id or nr is specified but no + matching control is found. ValueError is raised if the HTMLForm has an + enctype attribute that is not recognised. + + You can optionally specify a coordinate to click at, which only makes a + difference if you clicked on an image. + + """ + return self._click(name, type, id, label, nr, coord, "request", + self._request_class) + + def click_request_data(self, + name=None, type=None, id=None, + nr=0, coord=(1,1), + request_class=urllib2.Request, + label=None): + """As for click method, but return a tuple (url, data, headers). + + You can use this data to send a request to the server. This is useful + if you're using httplib or urllib rather than urllib2. Otherwise, use + the click method. + + # Untested. Have to subclass to add headers, I think -- so use urllib2 + # instead! + import urllib + url, data, hdrs = form.click_request_data() + r = urllib.urlopen(url, data) + + # Untested. I don't know of any reason to use httplib -- you can get + # just as much control with urllib2. + import httplib, urlparse + url, data, hdrs = form.click_request_data() + tup = urlparse(url) + host, path = tup[1], urlparse.urlunparse((None, None)+tup[2:]) + conn = httplib.HTTPConnection(host) + if data: + httplib.request("POST", path, data, hdrs) + else: + httplib.request("GET", path, headers=hdrs) + r = conn.getresponse() + + """ + return self._click(name, type, id, label, nr, coord, "request_data", + self._request_class) + + def click_pairs(self, name=None, type=None, id=None, + nr=0, coord=(1,1), + label=None): + """As for click_request_data, but returns a list of (key, value) pairs. + + You can use this list as an argument to ClientForm.urlencode. This is + usually only useful if you're using httplib or urllib rather than + urllib2 or ClientCookie. It may also be useful if you want to manually + tweak the keys and/or values, but this should not be necessary. + Otherwise, use the click method. + + Note that this method is only useful for forms of MIME type + x-www-form-urlencoded. In particular, it does not return the + information required for file upload. If you need file upload and are + not using urllib2, use click_request_data. + + Also note that Python 2.0's urllib.urlencode is slightly broken: it + only accepts a mapping, not a sequence of pairs, as an argument. This + messes up any ordering in the argument. Use ClientForm.urlencode + instead. + + """ + return self._click(name, type, id, label, nr, coord, "pairs", + self._request_class) + +#--------------------------------------------------- + + def find_control(self, + name=None, type=None, kind=None, id=None, + predicate=None, nr=None, + label=None): + """Locate and return some specific control within the form. + + At least one of the name, type, kind, predicate and nr arguments must + be supplied. If no matching control is found, ControlNotFoundError is + raised. + + If name is specified, then the control must have the indicated name. + + If type is specified then the control must have the specified type (in + addition to the types possible for <input> HTML tags: "text", + "password", "hidden", "submit", "image", "button", "radio", "checkbox", + "file" we also have "reset", "buttonbutton", "submitbutton", + "resetbutton", "textarea", "select" and "isindex"). + + If kind is specified, then the control must fall into the specified + group, each of which satisfies a particular interface. The types are + "text", "list", "multilist", "singlelist", "clickable" and "file". + + If id is specified, then the control must have the indicated id. + + If predicate is specified, then the control must match that function. + The predicate function is passed the control as its single argument, + and should return a boolean value indicating whether the control + matched. + + nr, if supplied, is the sequence number of the control (where 0 is the + first). Note that control 0 is the first control matching all the + other arguments (if supplied); it is not necessarily the first control + in the form. If no nr is supplied, AmbiguityError is raised if + multiple controls match the other arguments (unless the + .backwards-compat attribute is true). + + If label is specified, then the control must have this label. Note + that radio controls and checkboxes never have labels: their items do. + + """ + if ((name is None) and (type is None) and (kind is None) and + (id is None) and (label is None) and (predicate is None) and + (nr is None)): + raise ValueError( + "at least one argument must be supplied to specify control") + return self._find_control(name, type, kind, id, label, predicate, nr) + +#--------------------------------------------------- +# Private methods. + + def _find_list_control(self, + name=None, type=None, kind=None, id=None, + label=None, nr=None): + if ((name is None) and (type is None) and (kind is None) and + (id is None) and (label is None) and (nr is None)): + raise ValueError( + "at least one argument must be supplied to specify control") + + return self._find_control(name, type, kind, id, label, + is_listcontrol, nr) + + def _find_control(self, name, type, kind, id, label, predicate, nr): + if ((name is not None) and (name is not Missing) and + not isstringlike(name)): + raise TypeError("control name must be string-like") + if (type is not None) and not isstringlike(type): + raise TypeError("control type must be string-like") + if (kind is not None) and not isstringlike(kind): + raise TypeError("control kind must be string-like") + if (id is not None) and not isstringlike(id): + raise TypeError("control id must be string-like") + if (label is not None) and not isstringlike(label): + raise TypeError("control label must be string-like") + if (predicate is not None) and not callable(predicate): + raise TypeError("control predicate must be callable") + if (nr is not None) and nr < 0: + raise ValueError("control number must be a positive integer") + + orig_nr = nr + found = None + ambiguous = False + if nr is None and self.backwards_compat: + nr = 0 + + for control in self.controls: + if ((name is not None and name != control.name) and + (name is not Missing or control.name is not None)): + continue + if type is not None and type != control.type: + continue + if kind is not None and not control.is_of_kind(kind): + continue + if id is not None and id != control.id: + continue + if predicate and not predicate(control): + continue + if label: + for l in control.get_labels(): + if l.text.find(label) > -1: + break + else: + continue + if nr is not None: + if nr == 0: + return control # early exit: unambiguous due to nr + nr -= 1 + continue + if found: + ambiguous = True + break + found = control + + if found and not ambiguous: + return found + + description = [] + if name is not None: description.append("name %s" % repr(name)) + if type is not None: description.append("type '%s'" % type) + if kind is not None: description.append("kind '%s'" % kind) + if id is not None: description.append("id '%s'" % id) + if label is not None: description.append("label '%s'" % label) + if predicate is not None: + description.append("predicate %s" % predicate) + if orig_nr: description.append("nr %d" % orig_nr) + description = ", ".join(description) + + if ambiguous: + raise AmbiguityError("more than one control matching "+description) + elif not found: + raise ControlNotFoundError("no control matching "+description) + assert False + + def _click(self, name, type, id, label, nr, coord, return_type, + request_class=urllib2.Request): + try: + control = self._find_control( + name, type, "clickable", id, label, None, nr) + except ControlNotFoundError: + if ((name is not None) or (type is not None) or (id is not None) or + (nr != 0)): + raise + # no clickable controls, but no control was explicitly requested, + # so return state without clicking any control + return self._switch_click(return_type, request_class) + else: + return control._click(self, coord, return_type, request_class) + + def _pairs(self): + """Return sequence of (key, value) pairs suitable for urlencoding.""" + return [(k, v) for (i, k, v, c_i) in self._pairs_and_controls()] + + + def _pairs_and_controls(self): + """Return sequence of (index, key, value, control_index) + of totally ordered pairs suitable for urlencoding. + + control_index is the index of the control in self.controls + """ + pairs = [] + for control_index in range(len(self.controls)): + control = self.controls[control_index] + for ii, key, val in control._totally_ordered_pairs(): + pairs.append((ii, key, val, control_index)) + + # stable sort by ONLY first item in tuple + pairs.sort() + + return pairs + + def _request_data(self): + """Return a tuple (url, data, headers).""" + method = self.method.upper() + #scheme, netloc, path, parameters, query, frag = urlparse.urlparse(self.action) + parts = self._urlparse(self.action) + rest, (query, frag) = parts[:-2], parts[-2:] + + if method == "GET": + if self.enctype != "application/x-www-form-urlencoded": + raise ValueError( + "unknown GET form encoding type '%s'" % self.enctype) + parts = rest + (urlencode(self._pairs()), None) + uri = self._urlunparse(parts) + return uri, None, [] + elif method == "POST": + parts = rest + (query, None) + uri = self._urlunparse(parts) + if self.enctype == "application/x-www-form-urlencoded": + return (uri, urlencode(self._pairs()), + [("Content-Type", self.enctype)]) + elif self.enctype == "multipart/form-data": + data = StringIO() + http_hdrs = [] + mw = MimeWriter(data, http_hdrs) + f = mw.startmultipartbody("form-data", add_to_http_hdrs=True, + prefix=0) + for ii, k, v, control_index in self._pairs_and_controls(): + self.controls[control_index]._write_mime_data(mw, k, v) + mw.lastpart() + return uri, data.getvalue(), http_hdrs + else: + raise ValueError( + "unknown POST form encoding type '%s'" % self.enctype) + else: + raise ValueError("Unknown method '%s'" % method) + + def _switch_click(self, return_type, request_class=urllib2.Request): + # This is called by HTMLForm and clickable Controls to hide switching + # on return_type. + if return_type == "pairs": + return self._pairs() + elif return_type == "request_data": + return self._request_data() + else: + req_data = self._request_data() + req = request_class(req_data[0], req_data[1]) + for key, val in req_data[2]: + add_hdr = req.add_header + if key.lower() == "content-type": + try: + add_hdr = req.add_unredirected_header + except AttributeError: + # pre-2.4 and not using ClientCookie + pass + add_hdr(key, val) + return req diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/clientform/__init__.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/clientform/__init__.py new file mode 100644 index 0000000..c1e4c6d --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/clientform/__init__.py @@ -0,0 +1 @@ +# This file is required for Python to search this directory for modules. diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/irc/.ircbot.py.url b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/irc/.ircbot.py.url new file mode 100644 index 0000000..f34e243 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/irc/.ircbot.py.url @@ -0,0 +1 @@ +http://iweb.dl.sourceforge.net/project/python-irclib/python-irclib/0.4.8/python-irclib-0.4.8.zip
\ No newline at end of file diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/irc/.irclib.py.url b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/irc/.irclib.py.url new file mode 100644 index 0000000..f34e243 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/irc/.irclib.py.url @@ -0,0 +1 @@ +http://iweb.dl.sourceforge.net/project/python-irclib/python-irclib/0.4.8/python-irclib-0.4.8.zip
\ No newline at end of file diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/irc/__init__.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/irc/__init__.py new file mode 100644 index 0000000..c1e4c6d --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/irc/__init__.py @@ -0,0 +1 @@ +# This file is required for Python to search this directory for modules. diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/irc/ircbot.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/irc/ircbot.py new file mode 100644 index 0000000..6f29a65 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/irc/ircbot.py @@ -0,0 +1,438 @@ +# Copyright (C) 1999--2002 Joel Rosdahl +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Joel Rosdahl <joel@rosdahl.net> +# +# $Id: ircbot.py,v 1.23 2008/09/11 07:38:30 keltus Exp $ + +"""ircbot -- Simple IRC bot library. + +This module contains a single-server IRC bot class that can be used to +write simpler bots. +""" + +import sys +from UserDict import UserDict + +from irclib import SimpleIRCClient +from irclib import nm_to_n, irc_lower, all_events +from irclib import parse_channel_modes, is_channel +from irclib import ServerConnectionError + +class SingleServerIRCBot(SimpleIRCClient): + """A single-server IRC bot class. + + The bot tries to reconnect if it is disconnected. + + The bot keeps track of the channels it has joined, the other + clients that are present in the channels and which of those that + have operator or voice modes. The "database" is kept in the + self.channels attribute, which is an IRCDict of Channels. + """ + def __init__(self, server_list, nickname, realname, reconnection_interval=60): + """Constructor for SingleServerIRCBot objects. + + Arguments: + + server_list -- A list of tuples (server, port) that + defines which servers the bot should try to + connect to. + + nickname -- The bot's nickname. + + realname -- The bot's realname. + + reconnection_interval -- How long the bot should wait + before trying to reconnect. + + dcc_connections -- A list of initiated/accepted DCC + connections. + """ + + SimpleIRCClient.__init__(self) + self.channels = IRCDict() + self.server_list = server_list + if not reconnection_interval or reconnection_interval < 0: + reconnection_interval = 2**31 + self.reconnection_interval = reconnection_interval + + self._nickname = nickname + self._realname = realname + for i in ["disconnect", "join", "kick", "mode", + "namreply", "nick", "part", "quit"]: + self.connection.add_global_handler(i, + getattr(self, "_on_" + i), + -10) + def _connected_checker(self): + """[Internal]""" + if not self.connection.is_connected(): + self.connection.execute_delayed(self.reconnection_interval, + self._connected_checker) + self.jump_server() + + def _connect(self): + """[Internal]""" + password = None + if len(self.server_list[0]) > 2: + password = self.server_list[0][2] + try: + self.connect(self.server_list[0][0], + self.server_list[0][1], + self._nickname, + password, + ircname=self._realname) + except ServerConnectionError: + pass + + def _on_disconnect(self, c, e): + """[Internal]""" + self.channels = IRCDict() + self.connection.execute_delayed(self.reconnection_interval, + self._connected_checker) + + def _on_join(self, c, e): + """[Internal]""" + ch = e.target() + nick = nm_to_n(e.source()) + if nick == c.get_nickname(): + self.channels[ch] = Channel() + self.channels[ch].add_user(nick) + + def _on_kick(self, c, e): + """[Internal]""" + nick = e.arguments()[0] + channel = e.target() + + if nick == c.get_nickname(): + del self.channels[channel] + else: + self.channels[channel].remove_user(nick) + + def _on_mode(self, c, e): + """[Internal]""" + modes = parse_channel_modes(" ".join(e.arguments())) + t = e.target() + if is_channel(t): + ch = self.channels[t] + for mode in modes: + if mode[0] == "+": + f = ch.set_mode + else: + f = ch.clear_mode + f(mode[1], mode[2]) + else: + # Mode on self... XXX + pass + + def _on_namreply(self, c, e): + """[Internal]""" + + # e.arguments()[0] == "@" for secret channels, + # "*" for private channels, + # "=" for others (public channels) + # e.arguments()[1] == channel + # e.arguments()[2] == nick list + + ch = e.arguments()[1] + for nick in e.arguments()[2].split(): + if nick[0] == "@": + nick = nick[1:] + self.channels[ch].set_mode("o", nick) + elif nick[0] == "+": + nick = nick[1:] + self.channels[ch].set_mode("v", nick) + self.channels[ch].add_user(nick) + + def _on_nick(self, c, e): + """[Internal]""" + before = nm_to_n(e.source()) + after = e.target() + for ch in self.channels.values(): + if ch.has_user(before): + ch.change_nick(before, after) + + def _on_part(self, c, e): + """[Internal]""" + nick = nm_to_n(e.source()) + channel = e.target() + + if nick == c.get_nickname(): + del self.channels[channel] + else: + self.channels[channel].remove_user(nick) + + def _on_quit(self, c, e): + """[Internal]""" + nick = nm_to_n(e.source()) + for ch in self.channels.values(): + if ch.has_user(nick): + ch.remove_user(nick) + + def die(self, msg="Bye, cruel world!"): + """Let the bot die. + + Arguments: + + msg -- Quit message. + """ + + self.connection.disconnect(msg) + sys.exit(0) + + def disconnect(self, msg="I'll be back!"): + """Disconnect the bot. + + The bot will try to reconnect after a while. + + Arguments: + + msg -- Quit message. + """ + self.connection.disconnect(msg) + + def get_version(self): + """Returns the bot version. + + Used when answering a CTCP VERSION request. + """ + return "ircbot.py by Joel Rosdahl <joel@rosdahl.net>" + + def jump_server(self, msg="Changing servers"): + """Connect to a new server, possibly disconnecting from the current. + + The bot will skip to next server in the server_list each time + jump_server is called. + """ + if self.connection.is_connected(): + self.connection.disconnect(msg) + + self.server_list.append(self.server_list.pop(0)) + self._connect() + + def on_ctcp(self, c, e): + """Default handler for ctcp events. + + Replies to VERSION and PING requests and relays DCC requests + to the on_dccchat method. + """ + if e.arguments()[0] == "VERSION": + c.ctcp_reply(nm_to_n(e.source()), + "VERSION " + self.get_version()) + elif e.arguments()[0] == "PING": + if len(e.arguments()) > 1: + c.ctcp_reply(nm_to_n(e.source()), + "PING " + e.arguments()[1]) + elif e.arguments()[0] == "DCC" and e.arguments()[1].split(" ", 1)[0] == "CHAT": + self.on_dccchat(c, e) + + def on_dccchat(self, c, e): + pass + + def start(self): + """Start the bot.""" + self._connect() + SimpleIRCClient.start(self) + + +class IRCDict: + """A dictionary suitable for storing IRC-related things. + + Dictionary keys a and b are considered equal if and only if + irc_lower(a) == irc_lower(b) + + Otherwise, it should behave exactly as a normal dictionary. + """ + + def __init__(self, dict=None): + self.data = {} + self.canon_keys = {} # Canonical keys + if dict is not None: + self.update(dict) + def __repr__(self): + return repr(self.data) + def __cmp__(self, dict): + if isinstance(dict, IRCDict): + return cmp(self.data, dict.data) + else: + return cmp(self.data, dict) + def __len__(self): + return len(self.data) + def __getitem__(self, key): + return self.data[self.canon_keys[irc_lower(key)]] + def __setitem__(self, key, item): + if key in self: + del self[key] + self.data[key] = item + self.canon_keys[irc_lower(key)] = key + def __delitem__(self, key): + ck = irc_lower(key) + del self.data[self.canon_keys[ck]] + del self.canon_keys[ck] + def __iter__(self): + return iter(self.data) + def __contains__(self, key): + return self.has_key(key) + def clear(self): + self.data.clear() + self.canon_keys.clear() + def copy(self): + if self.__class__ is UserDict: + return UserDict(self.data) + import copy + return copy.copy(self) + def keys(self): + return self.data.keys() + def items(self): + return self.data.items() + def values(self): + return self.data.values() + def has_key(self, key): + return irc_lower(key) in self.canon_keys + def update(self, dict): + for k, v in dict.items(): + self.data[k] = v + def get(self, key, failobj=None): + return self.data.get(key, failobj) + + +class Channel: + """A class for keeping information about an IRC channel. + + This class can be improved a lot. + """ + + def __init__(self): + self.userdict = IRCDict() + self.operdict = IRCDict() + self.voiceddict = IRCDict() + self.modes = {} + + def users(self): + """Returns an unsorted list of the channel's users.""" + return self.userdict.keys() + + def opers(self): + """Returns an unsorted list of the channel's operators.""" + return self.operdict.keys() + + def voiced(self): + """Returns an unsorted list of the persons that have voice + mode set in the channel.""" + return self.voiceddict.keys() + + def has_user(self, nick): + """Check whether the channel has a user.""" + return nick in self.userdict + + def is_oper(self, nick): + """Check whether a user has operator status in the channel.""" + return nick in self.operdict + + def is_voiced(self, nick): + """Check whether a user has voice mode set in the channel.""" + return nick in self.voiceddict + + def add_user(self, nick): + self.userdict[nick] = 1 + + def remove_user(self, nick): + for d in self.userdict, self.operdict, self.voiceddict: + if nick in d: + del d[nick] + + def change_nick(self, before, after): + self.userdict[after] = 1 + del self.userdict[before] + if before in self.operdict: + self.operdict[after] = 1 + del self.operdict[before] + if before in self.voiceddict: + self.voiceddict[after] = 1 + del self.voiceddict[before] + + def set_mode(self, mode, value=None): + """Set mode on the channel. + + Arguments: + + mode -- The mode (a single-character string). + + value -- Value + """ + if mode == "o": + self.operdict[value] = 1 + elif mode == "v": + self.voiceddict[value] = 1 + else: + self.modes[mode] = value + + def clear_mode(self, mode, value=None): + """Clear mode on the channel. + + Arguments: + + mode -- The mode (a single-character string). + + value -- Value + """ + try: + if mode == "o": + del self.operdict[value] + elif mode == "v": + del self.voiceddict[value] + else: + del self.modes[mode] + except KeyError: + pass + + def has_mode(self, mode): + return mode in self.modes + + def is_moderated(self): + return self.has_mode("m") + + def is_secret(self): + return self.has_mode("s") + + def is_protected(self): + return self.has_mode("p") + + def has_topic_lock(self): + return self.has_mode("t") + + def is_invite_only(self): + return self.has_mode("i") + + def has_allow_external_messages(self): + return self.has_mode("n") + + def has_limit(self): + return self.has_mode("l") + + def limit(self): + if self.has_limit(): + return self.modes[l] + else: + return None + + def has_key(self): + return self.has_mode("k") + + def key(self): + if self.has_key(): + return self.modes["k"] + else: + return None diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/irc/irclib.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/irc/irclib.py new file mode 100644 index 0000000..5f7141c --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/irc/irclib.py @@ -0,0 +1,1560 @@ +# Copyright (C) 1999--2002 Joel Rosdahl +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# keltus <keltus@users.sourceforge.net> +# +# $Id: irclib.py,v 1.47 2008/09/25 22:00:59 keltus Exp $ + +"""irclib -- Internet Relay Chat (IRC) protocol client library. + +This library is intended to encapsulate the IRC protocol at a quite +low level. It provides an event-driven IRC client framework. It has +a fairly thorough support for the basic IRC protocol, CTCP, DCC chat, +but DCC file transfers is not yet supported. + +In order to understand how to make an IRC client, I'm afraid you more +or less must understand the IRC specifications. They are available +here: [IRC specifications]. + +The main features of the IRC client framework are: + + * Abstraction of the IRC protocol. + * Handles multiple simultaneous IRC server connections. + * Handles server PONGing transparently. + * Messages to the IRC server are done by calling methods on an IRC + connection object. + * Messages from an IRC server triggers events, which can be caught + by event handlers. + * Reading from and writing to IRC server sockets are normally done + by an internal select() loop, but the select()ing may be done by + an external main loop. + * Functions can be registered to execute at specified times by the + event-loop. + * Decodes CTCP tagging correctly (hopefully); I haven't seen any + other IRC client implementation that handles the CTCP + specification subtilties. + * A kind of simple, single-server, object-oriented IRC client class + that dispatches events to instance methods is included. + +Current limitations: + + * The IRC protocol shines through the abstraction a bit too much. + * Data is not written asynchronously to the server, i.e. the write() + may block if the TCP buffers are stuffed. + * There are no support for DCC file transfers. + * The author haven't even read RFC 2810, 2811, 2812 and 2813. + * Like most projects, documentation is lacking... + +.. [IRC specifications] http://www.irchelp.org/irchelp/rfc/ +""" + +import bisect +import re +import select +import socket +import string +import sys +import time +import types + +VERSION = 0, 4, 8 +DEBUG = 0 + +# TODO +# ---- +# (maybe) thread safety +# (maybe) color parser convenience functions +# documentation (including all event types) +# (maybe) add awareness of different types of ircds +# send data asynchronously to the server (and DCC connections) +# (maybe) automatically close unused, passive DCC connections after a while + +# NOTES +# ----- +# connection.quit() only sends QUIT to the server. +# ERROR from the server triggers the error event and the disconnect event. +# dropping of the connection triggers the disconnect event. + +class IRCError(Exception): + """Represents an IRC exception.""" + pass + + +class IRC: + """Class that handles one or several IRC server connections. + + When an IRC object has been instantiated, it can be used to create + Connection objects that represent the IRC connections. The + responsibility of the IRC object is to provide an event-driven + framework for the connections and to keep the connections alive. + It runs a select loop to poll each connection's TCP socket and + hands over the sockets with incoming data for processing by the + corresponding connection. + + The methods of most interest for an IRC client writer are server, + add_global_handler, remove_global_handler, execute_at, + execute_delayed, process_once and process_forever. + + Here is an example: + + irc = irclib.IRC() + server = irc.server() + server.connect(\"irc.some.where\", 6667, \"my_nickname\") + server.privmsg(\"a_nickname\", \"Hi there!\") + irc.process_forever() + + This will connect to the IRC server irc.some.where on port 6667 + using the nickname my_nickname and send the message \"Hi there!\" + to the nickname a_nickname. + """ + + def __init__(self, fn_to_add_socket=None, + fn_to_remove_socket=None, + fn_to_add_timeout=None): + """Constructor for IRC objects. + + Optional arguments are fn_to_add_socket, fn_to_remove_socket + and fn_to_add_timeout. The first two specify functions that + will be called with a socket object as argument when the IRC + object wants to be notified (or stop being notified) of data + coming on a new socket. When new data arrives, the method + process_data should be called. Similarly, fn_to_add_timeout + is called with a number of seconds (a floating point number) + as first argument when the IRC object wants to receive a + notification (by calling the process_timeout method). So, if + e.g. the argument is 42.17, the object wants the + process_timeout method to be called after 42 seconds and 170 + milliseconds. + + The three arguments mainly exist to be able to use an external + main loop (for example Tkinter's or PyGTK's main app loop) + instead of calling the process_forever method. + + An alternative is to just call ServerConnection.process_once() + once in a while. + """ + + if fn_to_add_socket and fn_to_remove_socket: + self.fn_to_add_socket = fn_to_add_socket + self.fn_to_remove_socket = fn_to_remove_socket + else: + self.fn_to_add_socket = None + self.fn_to_remove_socket = None + + self.fn_to_add_timeout = fn_to_add_timeout + self.connections = [] + self.handlers = {} + self.delayed_commands = [] # list of tuples in the format (time, function, arguments) + + self.add_global_handler("ping", _ping_ponger, -42) + + def server(self): + """Creates and returns a ServerConnection object.""" + + c = ServerConnection(self) + self.connections.append(c) + return c + + def process_data(self, sockets): + """Called when there is more data to read on connection sockets. + + Arguments: + + sockets -- A list of socket objects. + + See documentation for IRC.__init__. + """ + for s in sockets: + for c in self.connections: + if s == c._get_socket(): + c.process_data() + + def process_timeout(self): + """Called when a timeout notification is due. + + See documentation for IRC.__init__. + """ + t = time.time() + while self.delayed_commands: + if t >= self.delayed_commands[0][0]: + self.delayed_commands[0][1](*self.delayed_commands[0][2]) + del self.delayed_commands[0] + else: + break + + def process_once(self, timeout=0): + """Process data from connections once. + + Arguments: + + timeout -- How long the select() call should wait if no + data is available. + + This method should be called periodically to check and process + incoming data, if there are any. If that seems boring, look + at the process_forever method. + """ + sockets = map(lambda x: x._get_socket(), self.connections) + sockets = filter(lambda x: x != None, sockets) + if sockets: + (i, o, e) = select.select(sockets, [], [], timeout) + self.process_data(i) + else: + time.sleep(timeout) + self.process_timeout() + + def process_forever(self, timeout=0.2): + """Run an infinite loop, processing data from connections. + + This method repeatedly calls process_once. + + Arguments: + + timeout -- Parameter to pass to process_once. + """ + while 1: + self.process_once(timeout) + + def disconnect_all(self, message=""): + """Disconnects all connections.""" + for c in self.connections: + c.disconnect(message) + + def add_global_handler(self, event, handler, priority=0): + """Adds a global handler function for a specific event type. + + Arguments: + + event -- Event type (a string). Check the values of the + numeric_events dictionary in irclib.py for possible event + types. + + handler -- Callback function. + + priority -- A number (the lower number, the higher priority). + + The handler function is called whenever the specified event is + triggered in any of the connections. See documentation for + the Event class. + + The handler functions are called in priority order (lowest + number is highest priority). If a handler function returns + \"NO MORE\", no more handlers will be called. + """ + if not event in self.handlers: + self.handlers[event] = [] + bisect.insort(self.handlers[event], ((priority, handler))) + + def remove_global_handler(self, event, handler): + """Removes a global handler function. + + Arguments: + + event -- Event type (a string). + + handler -- Callback function. + + Returns 1 on success, otherwise 0. + """ + if not event in self.handlers: + return 0 + for h in self.handlers[event]: + if handler == h[1]: + self.handlers[event].remove(h) + return 1 + + def execute_at(self, at, function, arguments=()): + """Execute a function at a specified time. + + Arguments: + + at -- Execute at this time (standard \"time_t\" time). + + function -- Function to call. + + arguments -- Arguments to give the function. + """ + self.execute_delayed(at-time.time(), function, arguments) + + def execute_delayed(self, delay, function, arguments=()): + """Execute a function after a specified time. + + Arguments: + + delay -- How many seconds to wait. + + function -- Function to call. + + arguments -- Arguments to give the function. + """ + bisect.insort(self.delayed_commands, (delay+time.time(), function, arguments)) + if self.fn_to_add_timeout: + self.fn_to_add_timeout(delay) + + def dcc(self, dcctype="chat"): + """Creates and returns a DCCConnection object. + + Arguments: + + dcctype -- "chat" for DCC CHAT connections or "raw" for + DCC SEND (or other DCC types). If "chat", + incoming data will be split in newline-separated + chunks. If "raw", incoming data is not touched. + """ + c = DCCConnection(self, dcctype) + self.connections.append(c) + return c + + def _handle_event(self, connection, event): + """[Internal]""" + h = self.handlers + for handler in h.get("all_events", []) + h.get(event.eventtype(), []): + if handler[1](connection, event) == "NO MORE": + return + + def _remove_connection(self, connection): + """[Internal]""" + self.connections.remove(connection) + if self.fn_to_remove_socket: + self.fn_to_remove_socket(connection._get_socket()) + +_rfc_1459_command_regexp = re.compile("^(:(?P<prefix>[^ ]+) +)?(?P<command>[^ ]+)( *(?P<argument> .+))?") + +class Connection: + """Base class for IRC connections. + + Must be overridden. + """ + def __init__(self, irclibobj): + self.irclibobj = irclibobj + + def _get_socket(): + raise IRCError, "Not overridden" + + ############################## + ### Convenience wrappers. + + def execute_at(self, at, function, arguments=()): + self.irclibobj.execute_at(at, function, arguments) + + def execute_delayed(self, delay, function, arguments=()): + self.irclibobj.execute_delayed(delay, function, arguments) + + +class ServerConnectionError(IRCError): + pass + +class ServerNotConnectedError(ServerConnectionError): + pass + + +# Huh!? Crrrrazy EFNet doesn't follow the RFC: their ircd seems to +# use \n as message separator! :P +_linesep_regexp = re.compile("\r?\n") + +class ServerConnection(Connection): + """This class represents an IRC server connection. + + ServerConnection objects are instantiated by calling the server + method on an IRC object. + """ + + def __init__(self, irclibobj): + Connection.__init__(self, irclibobj) + self.connected = 0 # Not connected yet. + self.socket = None + self.ssl = None + + def connect(self, server, port, nickname, password=None, username=None, + ircname=None, localaddress="", localport=0, ssl=False, ipv6=False): + """Connect/reconnect to a server. + + Arguments: + + server -- Server name. + + port -- Port number. + + nickname -- The nickname. + + password -- Password (if any). + + username -- The username. + + ircname -- The IRC name ("realname"). + + localaddress -- Bind the connection to a specific local IP address. + + localport -- Bind the connection to a specific local port. + + ssl -- Enable support for ssl. + + ipv6 -- Enable support for ipv6. + + This function can be called to reconnect a closed connection. + + Returns the ServerConnection object. + """ + if self.connected: + self.disconnect("Changing servers") + + self.previous_buffer = "" + self.handlers = {} + self.real_server_name = "" + self.real_nickname = nickname + self.server = server + self.port = port + self.nickname = nickname + self.username = username or nickname + self.ircname = ircname or nickname + self.password = password + self.localaddress = localaddress + self.localport = localport + self.localhost = socket.gethostname() + if ipv6: + self.socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + else: + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + self.socket.bind((self.localaddress, self.localport)) + self.socket.connect((self.server, self.port)) + if ssl: + self.ssl = socket.ssl(self.socket) + except socket.error, x: + self.socket.close() + self.socket = None + raise ServerConnectionError, "Couldn't connect to socket: %s" % x + self.connected = 1 + if self.irclibobj.fn_to_add_socket: + self.irclibobj.fn_to_add_socket(self.socket) + + # Log on... + if self.password: + self.pass_(self.password) + self.nick(self.nickname) + self.user(self.username, self.ircname) + return self + + def close(self): + """Close the connection. + + This method closes the connection permanently; after it has + been called, the object is unusable. + """ + + self.disconnect("Closing object") + self.irclibobj._remove_connection(self) + + def _get_socket(self): + """[Internal]""" + return self.socket + + def get_server_name(self): + """Get the (real) server name. + + This method returns the (real) server name, or, more + specifically, what the server calls itself. + """ + + if self.real_server_name: + return self.real_server_name + else: + return "" + + def get_nickname(self): + """Get the (real) nick name. + + This method returns the (real) nickname. The library keeps + track of nick changes, so it might not be the nick name that + was passed to the connect() method. """ + + return self.real_nickname + + def process_data(self): + """[Internal]""" + + try: + if self.ssl: + new_data = self.ssl.read(2**14) + else: + new_data = self.socket.recv(2**14) + except socket.error, x: + # The server hung up. + self.disconnect("Connection reset by peer") + return + if not new_data: + # Read nothing: connection must be down. + self.disconnect("Connection reset by peer") + return + + lines = _linesep_regexp.split(self.previous_buffer + new_data) + + # Save the last, unfinished line. + self.previous_buffer = lines.pop() + + for line in lines: + if DEBUG: + print "FROM SERVER:", line + + if not line: + continue + + prefix = None + command = None + arguments = None + self._handle_event(Event("all_raw_messages", + self.get_server_name(), + None, + [line])) + + m = _rfc_1459_command_regexp.match(line) + if m.group("prefix"): + prefix = m.group("prefix") + if not self.real_server_name: + self.real_server_name = prefix + + if m.group("command"): + command = m.group("command").lower() + + if m.group("argument"): + a = m.group("argument").split(" :", 1) + arguments = a[0].split() + if len(a) == 2: + arguments.append(a[1]) + + # Translate numerics into more readable strings. + if command in numeric_events: + command = numeric_events[command] + + if command == "nick": + if nm_to_n(prefix) == self.real_nickname: + self.real_nickname = arguments[0] + elif command == "welcome": + # Record the nickname in case the client changed nick + # in a nicknameinuse callback. + self.real_nickname = arguments[0] + + if command in ["privmsg", "notice"]: + target, message = arguments[0], arguments[1] + messages = _ctcp_dequote(message) + + if command == "privmsg": + if is_channel(target): + command = "pubmsg" + else: + if is_channel(target): + command = "pubnotice" + else: + command = "privnotice" + + for m in messages: + if type(m) is types.TupleType: + if command in ["privmsg", "pubmsg"]: + command = "ctcp" + else: + command = "ctcpreply" + + m = list(m) + if DEBUG: + print "command: %s, source: %s, target: %s, arguments: %s" % ( + command, prefix, target, m) + self._handle_event(Event(command, prefix, target, m)) + if command == "ctcp" and m[0] == "ACTION": + self._handle_event(Event("action", prefix, target, m[1:])) + else: + if DEBUG: + print "command: %s, source: %s, target: %s, arguments: %s" % ( + command, prefix, target, [m]) + self._handle_event(Event(command, prefix, target, [m])) + else: + target = None + + if command == "quit": + arguments = [arguments[0]] + elif command == "ping": + target = arguments[0] + else: + target = arguments[0] + arguments = arguments[1:] + + if command == "mode": + if not is_channel(target): + command = "umode" + + if DEBUG: + print "command: %s, source: %s, target: %s, arguments: %s" % ( + command, prefix, target, arguments) + self._handle_event(Event(command, prefix, target, arguments)) + + def _handle_event(self, event): + """[Internal]""" + self.irclibobj._handle_event(self, event) + if event.eventtype() in self.handlers: + for fn in self.handlers[event.eventtype()]: + fn(self, event) + + def is_connected(self): + """Return connection status. + + Returns true if connected, otherwise false. + """ + return self.connected + + def add_global_handler(self, *args): + """Add global handler. + + See documentation for IRC.add_global_handler. + """ + self.irclibobj.add_global_handler(*args) + + def remove_global_handler(self, *args): + """Remove global handler. + + See documentation for IRC.remove_global_handler. + """ + self.irclibobj.remove_global_handler(*args) + + def action(self, target, action): + """Send a CTCP ACTION command.""" + self.ctcp("ACTION", target, action) + + def admin(self, server=""): + """Send an ADMIN command.""" + self.send_raw(" ".join(["ADMIN", server]).strip()) + + def ctcp(self, ctcptype, target, parameter=""): + """Send a CTCP command.""" + ctcptype = ctcptype.upper() + self.privmsg(target, "\001%s%s\001" % (ctcptype, parameter and (" " + parameter) or "")) + + def ctcp_reply(self, target, parameter): + """Send a CTCP REPLY command.""" + self.notice(target, "\001%s\001" % parameter) + + def disconnect(self, message=""): + """Hang up the connection. + + Arguments: + + message -- Quit message. + """ + if not self.connected: + return + + self.connected = 0 + + self.quit(message) + + try: + self.socket.close() + except socket.error, x: + pass + self.socket = None + self._handle_event(Event("disconnect", self.server, "", [message])) + + def globops(self, text): + """Send a GLOBOPS command.""" + self.send_raw("GLOBOPS :" + text) + + def info(self, server=""): + """Send an INFO command.""" + self.send_raw(" ".join(["INFO", server]).strip()) + + def invite(self, nick, channel): + """Send an INVITE command.""" + self.send_raw(" ".join(["INVITE", nick, channel]).strip()) + + def ison(self, nicks): + """Send an ISON command. + + Arguments: + + nicks -- List of nicks. + """ + self.send_raw("ISON " + " ".join(nicks)) + + def join(self, channel, key=""): + """Send a JOIN command.""" + self.send_raw("JOIN %s%s" % (channel, (key and (" " + key)))) + + def kick(self, channel, nick, comment=""): + """Send a KICK command.""" + self.send_raw("KICK %s %s%s" % (channel, nick, (comment and (" :" + comment)))) + + def links(self, remote_server="", server_mask=""): + """Send a LINKS command.""" + command = "LINKS" + if remote_server: + command = command + " " + remote_server + if server_mask: + command = command + " " + server_mask + self.send_raw(command) + + def list(self, channels=None, server=""): + """Send a LIST command.""" + command = "LIST" + if channels: + command = command + " " + ",".join(channels) + if server: + command = command + " " + server + self.send_raw(command) + + def lusers(self, server=""): + """Send a LUSERS command.""" + self.send_raw("LUSERS" + (server and (" " + server))) + + def mode(self, target, command): + """Send a MODE command.""" + self.send_raw("MODE %s %s" % (target, command)) + + def motd(self, server=""): + """Send an MOTD command.""" + self.send_raw("MOTD" + (server and (" " + server))) + + def names(self, channels=None): + """Send a NAMES command.""" + self.send_raw("NAMES" + (channels and (" " + ",".join(channels)) or "")) + + def nick(self, newnick): + """Send a NICK command.""" + self.send_raw("NICK " + newnick) + + def notice(self, target, text): + """Send a NOTICE command.""" + # Should limit len(text) here! + self.send_raw("NOTICE %s :%s" % (target, text)) + + def oper(self, nick, password): + """Send an OPER command.""" + self.send_raw("OPER %s %s" % (nick, password)) + + def part(self, channels, message=""): + """Send a PART command.""" + if type(channels) == types.StringType: + self.send_raw("PART " + channels + (message and (" " + message))) + else: + self.send_raw("PART " + ",".join(channels) + (message and (" " + message))) + + def pass_(self, password): + """Send a PASS command.""" + self.send_raw("PASS " + password) + + def ping(self, target, target2=""): + """Send a PING command.""" + self.send_raw("PING %s%s" % (target, target2 and (" " + target2))) + + def pong(self, target, target2=""): + """Send a PONG command.""" + self.send_raw("PONG %s%s" % (target, target2 and (" " + target2))) + + def privmsg(self, target, text): + """Send a PRIVMSG command.""" + # Should limit len(text) here! + self.send_raw("PRIVMSG %s :%s" % (target, text)) + + def privmsg_many(self, targets, text): + """Send a PRIVMSG command to multiple targets.""" + # Should limit len(text) here! + self.send_raw("PRIVMSG %s :%s" % (",".join(targets), text)) + + def quit(self, message=""): + """Send a QUIT command.""" + # Note that many IRC servers don't use your QUIT message + # unless you've been connected for at least 5 minutes! + self.send_raw("QUIT" + (message and (" :" + message))) + + def send_raw(self, string): + """Send raw string to the server. + + The string will be padded with appropriate CR LF. + """ + if self.socket is None: + raise ServerNotConnectedError, "Not connected." + try: + if self.ssl: + self.ssl.write(string + "\r\n") + else: + self.socket.send(string + "\r\n") + if DEBUG: + print "TO SERVER:", string + except socket.error, x: + # Ouch! + self.disconnect("Connection reset by peer.") + + def squit(self, server, comment=""): + """Send an SQUIT command.""" + self.send_raw("SQUIT %s%s" % (server, comment and (" :" + comment))) + + def stats(self, statstype, server=""): + """Send a STATS command.""" + self.send_raw("STATS %s%s" % (statstype, server and (" " + server))) + + def time(self, server=""): + """Send a TIME command.""" + self.send_raw("TIME" + (server and (" " + server))) + + def topic(self, channel, new_topic=None): + """Send a TOPIC command.""" + if new_topic is None: + self.send_raw("TOPIC " + channel) + else: + self.send_raw("TOPIC %s :%s" % (channel, new_topic)) + + def trace(self, target=""): + """Send a TRACE command.""" + self.send_raw("TRACE" + (target and (" " + target))) + + def user(self, username, realname): + """Send a USER command.""" + self.send_raw("USER %s 0 * :%s" % (username, realname)) + + def userhost(self, nicks): + """Send a USERHOST command.""" + self.send_raw("USERHOST " + ",".join(nicks)) + + def users(self, server=""): + """Send a USERS command.""" + self.send_raw("USERS" + (server and (" " + server))) + + def version(self, server=""): + """Send a VERSION command.""" + self.send_raw("VERSION" + (server and (" " + server))) + + def wallops(self, text): + """Send a WALLOPS command.""" + self.send_raw("WALLOPS :" + text) + + def who(self, target="", op=""): + """Send a WHO command.""" + self.send_raw("WHO%s%s" % (target and (" " + target), op and (" o"))) + + def whois(self, targets): + """Send a WHOIS command.""" + self.send_raw("WHOIS " + ",".join(targets)) + + def whowas(self, nick, max="", server=""): + """Send a WHOWAS command.""" + self.send_raw("WHOWAS %s%s%s" % (nick, + max and (" " + max), + server and (" " + server))) + +class DCCConnectionError(IRCError): + pass + + +class DCCConnection(Connection): + """This class represents a DCC connection. + + DCCConnection objects are instantiated by calling the dcc + method on an IRC object. + """ + def __init__(self, irclibobj, dcctype): + Connection.__init__(self, irclibobj) + self.connected = 0 + self.passive = 0 + self.dcctype = dcctype + self.peeraddress = None + self.peerport = None + + def connect(self, address, port): + """Connect/reconnect to a DCC peer. + + Arguments: + address -- Host/IP address of the peer. + + port -- The port number to connect to. + + Returns the DCCConnection object. + """ + self.peeraddress = socket.gethostbyname(address) + self.peerport = port + self.socket = None + self.previous_buffer = "" + self.handlers = {} + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.passive = 0 + try: + self.socket.connect((self.peeraddress, self.peerport)) + except socket.error, x: + raise DCCConnectionError, "Couldn't connect to socket: %s" % x + self.connected = 1 + if self.irclibobj.fn_to_add_socket: + self.irclibobj.fn_to_add_socket(self.socket) + return self + + def listen(self): + """Wait for a connection/reconnection from a DCC peer. + + Returns the DCCConnection object. + + The local IP address and port are available as + self.localaddress and self.localport. After connection from a + peer, the peer address and port are available as + self.peeraddress and self.peerport. + """ + self.previous_buffer = "" + self.handlers = {} + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.passive = 1 + try: + self.socket.bind((socket.gethostbyname(socket.gethostname()), 0)) + self.localaddress, self.localport = self.socket.getsockname() + self.socket.listen(10) + except socket.error, x: + raise DCCConnectionError, "Couldn't bind socket: %s" % x + return self + + def disconnect(self, message=""): + """Hang up the connection and close the object. + + Arguments: + + message -- Quit message. + """ + if not self.connected: + return + + self.connected = 0 + try: + self.socket.close() + except socket.error, x: + pass + self.socket = None + self.irclibobj._handle_event( + self, + Event("dcc_disconnect", self.peeraddress, "", [message])) + self.irclibobj._remove_connection(self) + + def process_data(self): + """[Internal]""" + + if self.passive and not self.connected: + conn, (self.peeraddress, self.peerport) = self.socket.accept() + self.socket.close() + self.socket = conn + self.connected = 1 + if DEBUG: + print "DCC connection from %s:%d" % ( + self.peeraddress, self.peerport) + self.irclibobj._handle_event( + self, + Event("dcc_connect", self.peeraddress, None, None)) + return + + try: + new_data = self.socket.recv(2**14) + except socket.error, x: + # The server hung up. + self.disconnect("Connection reset by peer") + return + if not new_data: + # Read nothing: connection must be down. + self.disconnect("Connection reset by peer") + return + + if self.dcctype == "chat": + # The specification says lines are terminated with LF, but + # it seems safer to handle CR LF terminations too. + chunks = _linesep_regexp.split(self.previous_buffer + new_data) + + # Save the last, unfinished line. + self.previous_buffer = chunks[-1] + if len(self.previous_buffer) > 2**14: + # Bad peer! Naughty peer! + self.disconnect() + return + chunks = chunks[:-1] + else: + chunks = [new_data] + + command = "dccmsg" + prefix = self.peeraddress + target = None + for chunk in chunks: + if DEBUG: + print "FROM PEER:", chunk + arguments = [chunk] + if DEBUG: + print "command: %s, source: %s, target: %s, arguments: %s" % ( + command, prefix, target, arguments) + self.irclibobj._handle_event( + self, + Event(command, prefix, target, arguments)) + + def _get_socket(self): + """[Internal]""" + return self.socket + + def privmsg(self, string): + """Send data to DCC peer. + + The string will be padded with appropriate LF if it's a DCC + CHAT session. + """ + try: + self.socket.send(string) + if self.dcctype == "chat": + self.socket.send("\n") + if DEBUG: + print "TO PEER: %s\n" % string + except socket.error, x: + # Ouch! + self.disconnect("Connection reset by peer.") + +class SimpleIRCClient: + """A simple single-server IRC client class. + + This is an example of an object-oriented wrapper of the IRC + framework. A real IRC client can be made by subclassing this + class and adding appropriate methods. + + The method on_join will be called when a "join" event is created + (which is done when the server sends a JOIN messsage/command), + on_privmsg will be called for "privmsg" events, and so on. The + handler methods get two arguments: the connection object (same as + self.connection) and the event object. + + Instance attributes that can be used by sub classes: + + ircobj -- The IRC instance. + + connection -- The ServerConnection instance. + + dcc_connections -- A list of DCCConnection instances. + """ + def __init__(self): + self.ircobj = IRC() + self.connection = self.ircobj.server() + self.dcc_connections = [] + self.ircobj.add_global_handler("all_events", self._dispatcher, -10) + self.ircobj.add_global_handler("dcc_disconnect", self._dcc_disconnect, -10) + + def _dispatcher(self, c, e): + """[Internal]""" + m = "on_" + e.eventtype() + if hasattr(self, m): + getattr(self, m)(c, e) + + def _dcc_disconnect(self, c, e): + self.dcc_connections.remove(c) + + def connect(self, server, port, nickname, password=None, username=None, + ircname=None, localaddress="", localport=0, ssl=False, ipv6=False): + """Connect/reconnect to a server. + + Arguments: + + server -- Server name. + + port -- Port number. + + nickname -- The nickname. + + password -- Password (if any). + + username -- The username. + + ircname -- The IRC name. + + localaddress -- Bind the connection to a specific local IP address. + + localport -- Bind the connection to a specific local port. + + ssl -- Enable support for ssl. + + ipv6 -- Enable support for ipv6. + + This function can be called to reconnect a closed connection. + """ + self.connection.connect(server, port, nickname, + password, username, ircname, + localaddress, localport, ssl, ipv6) + + def dcc_connect(self, address, port, dcctype="chat"): + """Connect to a DCC peer. + + Arguments: + + address -- IP address of the peer. + + port -- Port to connect to. + + Returns a DCCConnection instance. + """ + dcc = self.ircobj.dcc(dcctype) + self.dcc_connections.append(dcc) + dcc.connect(address, port) + return dcc + + def dcc_listen(self, dcctype="chat"): + """Listen for connections from a DCC peer. + + Returns a DCCConnection instance. + """ + dcc = self.ircobj.dcc(dcctype) + self.dcc_connections.append(dcc) + dcc.listen() + return dcc + + def start(self): + """Start the IRC client.""" + self.ircobj.process_forever() + + +class Event: + """Class representing an IRC event.""" + def __init__(self, eventtype, source, target, arguments=None): + """Constructor of Event objects. + + Arguments: + + eventtype -- A string describing the event. + + source -- The originator of the event (a nick mask or a server). + + target -- The target of the event (a nick or a channel). + + arguments -- Any event specific arguments. + """ + self._eventtype = eventtype + self._source = source + self._target = target + if arguments: + self._arguments = arguments + else: + self._arguments = [] + + def eventtype(self): + """Get the event type.""" + return self._eventtype + + def source(self): + """Get the event source.""" + return self._source + + def target(self): + """Get the event target.""" + return self._target + + def arguments(self): + """Get the event arguments.""" + return self._arguments + +_LOW_LEVEL_QUOTE = "\020" +_CTCP_LEVEL_QUOTE = "\134" +_CTCP_DELIMITER = "\001" + +_low_level_mapping = { + "0": "\000", + "n": "\n", + "r": "\r", + _LOW_LEVEL_QUOTE: _LOW_LEVEL_QUOTE +} + +_low_level_regexp = re.compile(_LOW_LEVEL_QUOTE + "(.)") + +def mask_matches(nick, mask): + """Check if a nick matches a mask. + + Returns true if the nick matches, otherwise false. + """ + nick = irc_lower(nick) + mask = irc_lower(mask) + mask = mask.replace("\\", "\\\\") + for ch in ".$|[](){}+": + mask = mask.replace(ch, "\\" + ch) + mask = mask.replace("?", ".") + mask = mask.replace("*", ".*") + r = re.compile(mask, re.IGNORECASE) + return r.match(nick) + +_special = "-[]\\`^{}" +nick_characters = string.ascii_letters + string.digits + _special +_ircstring_translation = string.maketrans(string.ascii_uppercase + "[]\\^", + string.ascii_lowercase + "{}|~") + +def irc_lower(s): + """Returns a lowercased string. + + The definition of lowercased comes from the IRC specification (RFC + 1459). + """ + return s.translate(_ircstring_translation) + +def _ctcp_dequote(message): + """[Internal] Dequote a message according to CTCP specifications. + + The function returns a list where each element can be either a + string (normal message) or a tuple of one or two strings (tagged + messages). If a tuple has only one element (ie is a singleton), + that element is the tag; otherwise the tuple has two elements: the + tag and the data. + + Arguments: + + message -- The message to be decoded. + """ + + def _low_level_replace(match_obj): + ch = match_obj.group(1) + + # If low_level_mapping doesn't have the character as key, we + # should just return the character. + return _low_level_mapping.get(ch, ch) + + if _LOW_LEVEL_QUOTE in message: + # Yup, there was a quote. Release the dequoter, man! + message = _low_level_regexp.sub(_low_level_replace, message) + + if _CTCP_DELIMITER not in message: + return [message] + else: + # Split it into parts. (Does any IRC client actually *use* + # CTCP stacking like this?) + chunks = message.split(_CTCP_DELIMITER) + + messages = [] + i = 0 + while i < len(chunks)-1: + # Add message if it's non-empty. + if len(chunks[i]) > 0: + messages.append(chunks[i]) + + if i < len(chunks)-2: + # Aye! CTCP tagged data ahead! + messages.append(tuple(chunks[i+1].split(" ", 1))) + + i = i + 2 + + if len(chunks) % 2 == 0: + # Hey, a lonely _CTCP_DELIMITER at the end! This means + # that the last chunk, including the delimiter, is a + # normal message! (This is according to the CTCP + # specification.) + messages.append(_CTCP_DELIMITER + chunks[-1]) + + return messages + +def is_channel(string): + """Check if a string is a channel name. + + Returns true if the argument is a channel name, otherwise false. + """ + return string and string[0] in "#&+!" + +def ip_numstr_to_quad(num): + """Convert an IP number as an integer given in ASCII + representation (e.g. '3232235521') to an IP address string + (e.g. '192.168.0.1').""" + n = long(num) + p = map(str, map(int, [n >> 24 & 0xFF, n >> 16 & 0xFF, + n >> 8 & 0xFF, n & 0xFF])) + return ".".join(p) + +def ip_quad_to_numstr(quad): + """Convert an IP address string (e.g. '192.168.0.1') to an IP + number as an integer given in ASCII representation + (e.g. '3232235521').""" + p = map(long, quad.split(".")) + s = str((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]) + if s[-1] == "L": + s = s[:-1] + return s + +def nm_to_n(s): + """Get the nick part of a nickmask. + + (The source of an Event is a nickmask.) + """ + return s.split("!")[0] + +def nm_to_uh(s): + """Get the userhost part of a nickmask. + + (The source of an Event is a nickmask.) + """ + return s.split("!")[1] + +def nm_to_h(s): + """Get the host part of a nickmask. + + (The source of an Event is a nickmask.) + """ + return s.split("@")[1] + +def nm_to_u(s): + """Get the user part of a nickmask. + + (The source of an Event is a nickmask.) + """ + s = s.split("!")[1] + return s.split("@")[0] + +def parse_nick_modes(mode_string): + """Parse a nick mode string. + + The function returns a list of lists with three members: sign, + mode and argument. The sign is \"+\" or \"-\". The argument is + always None. + + Example: + + >>> irclib.parse_nick_modes(\"+ab-c\") + [['+', 'a', None], ['+', 'b', None], ['-', 'c', None]] + """ + + return _parse_modes(mode_string, "") + +def parse_channel_modes(mode_string): + """Parse a channel mode string. + + The function returns a list of lists with three members: sign, + mode and argument. The sign is \"+\" or \"-\". The argument is + None if mode isn't one of \"b\", \"k\", \"l\", \"v\" or \"o\". + + Example: + + >>> irclib.parse_channel_modes(\"+ab-c foo\") + [['+', 'a', None], ['+', 'b', 'foo'], ['-', 'c', None]] + """ + + return _parse_modes(mode_string, "bklvo") + +def _parse_modes(mode_string, unary_modes=""): + """[Internal]""" + modes = [] + arg_count = 0 + + # State variable. + sign = "" + + a = mode_string.split() + if len(a) == 0: + return [] + else: + mode_part, args = a[0], a[1:] + + if mode_part[0] not in "+-": + return [] + for ch in mode_part: + if ch in "+-": + sign = ch + elif ch == " ": + collecting_arguments = 1 + elif ch in unary_modes: + if len(args) >= arg_count + 1: + modes.append([sign, ch, args[arg_count]]) + arg_count = arg_count + 1 + else: + modes.append([sign, ch, None]) + else: + modes.append([sign, ch, None]) + return modes + +def _ping_ponger(connection, event): + """[Internal]""" + connection.pong(event.target()) + +# Numeric table mostly stolen from the Perl IRC module (Net::IRC). +numeric_events = { + "001": "welcome", + "002": "yourhost", + "003": "created", + "004": "myinfo", + "005": "featurelist", # XXX + "200": "tracelink", + "201": "traceconnecting", + "202": "tracehandshake", + "203": "traceunknown", + "204": "traceoperator", + "205": "traceuser", + "206": "traceserver", + "207": "traceservice", + "208": "tracenewtype", + "209": "traceclass", + "210": "tracereconnect", + "211": "statslinkinfo", + "212": "statscommands", + "213": "statscline", + "214": "statsnline", + "215": "statsiline", + "216": "statskline", + "217": "statsqline", + "218": "statsyline", + "219": "endofstats", + "221": "umodeis", + "231": "serviceinfo", + "232": "endofservices", + "233": "service", + "234": "servlist", + "235": "servlistend", + "241": "statslline", + "242": "statsuptime", + "243": "statsoline", + "244": "statshline", + "250": "luserconns", + "251": "luserclient", + "252": "luserop", + "253": "luserunknown", + "254": "luserchannels", + "255": "luserme", + "256": "adminme", + "257": "adminloc1", + "258": "adminloc2", + "259": "adminemail", + "261": "tracelog", + "262": "endoftrace", + "263": "tryagain", + "265": "n_local", + "266": "n_global", + "300": "none", + "301": "away", + "302": "userhost", + "303": "ison", + "305": "unaway", + "306": "nowaway", + "311": "whoisuser", + "312": "whoisserver", + "313": "whoisoperator", + "314": "whowasuser", + "315": "endofwho", + "316": "whoischanop", + "317": "whoisidle", + "318": "endofwhois", + "319": "whoischannels", + "321": "liststart", + "322": "list", + "323": "listend", + "324": "channelmodeis", + "329": "channelcreate", + "331": "notopic", + "332": "currenttopic", + "333": "topicinfo", + "341": "inviting", + "342": "summoning", + "346": "invitelist", + "347": "endofinvitelist", + "348": "exceptlist", + "349": "endofexceptlist", + "351": "version", + "352": "whoreply", + "353": "namreply", + "361": "killdone", + "362": "closing", + "363": "closeend", + "364": "links", + "365": "endoflinks", + "366": "endofnames", + "367": "banlist", + "368": "endofbanlist", + "369": "endofwhowas", + "371": "info", + "372": "motd", + "373": "infostart", + "374": "endofinfo", + "375": "motdstart", + "376": "endofmotd", + "377": "motd2", # 1997-10-16 -- tkil + "381": "youreoper", + "382": "rehashing", + "384": "myportis", + "391": "time", + "392": "usersstart", + "393": "users", + "394": "endofusers", + "395": "nousers", + "401": "nosuchnick", + "402": "nosuchserver", + "403": "nosuchchannel", + "404": "cannotsendtochan", + "405": "toomanychannels", + "406": "wasnosuchnick", + "407": "toomanytargets", + "409": "noorigin", + "411": "norecipient", + "412": "notexttosend", + "413": "notoplevel", + "414": "wildtoplevel", + "421": "unknowncommand", + "422": "nomotd", + "423": "noadmininfo", + "424": "fileerror", + "431": "nonicknamegiven", + "432": "erroneusnickname", # Thiss iz how its speld in thee RFC. + "433": "nicknameinuse", + "436": "nickcollision", + "437": "unavailresource", # "Nick temporally unavailable" + "441": "usernotinchannel", + "442": "notonchannel", + "443": "useronchannel", + "444": "nologin", + "445": "summondisabled", + "446": "usersdisabled", + "451": "notregistered", + "461": "needmoreparams", + "462": "alreadyregistered", + "463": "nopermforhost", + "464": "passwdmismatch", + "465": "yourebannedcreep", # I love this one... + "466": "youwillbebanned", + "467": "keyset", + "471": "channelisfull", + "472": "unknownmode", + "473": "inviteonlychan", + "474": "bannedfromchan", + "475": "badchannelkey", + "476": "badchanmask", + "477": "nochanmodes", # "Channel doesn't support modes" + "478": "banlistfull", + "481": "noprivileges", + "482": "chanoprivsneeded", + "483": "cantkillserver", + "484": "restricted", # Connection is restricted + "485": "uniqopprivsneeded", + "491": "nooperhost", + "492": "noservicehost", + "501": "umodeunknownflag", + "502": "usersdontmatch", +} + +generated_events = [ + # Generated events + "dcc_connect", + "dcc_disconnect", + "dccmsg", + "disconnect", + "ctcp", + "ctcpreply", +] + +protocol_events = [ + # IRC protocol events + "error", + "join", + "kick", + "mode", + "part", + "ping", + "privmsg", + "privnotice", + "pubmsg", + "pubnotice", + "quit", + "invite", + "pong", +] + +all_events = generated_events + protocol_events + numeric_events.values() diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/__init__.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/__init__.py new file mode 100644 index 0000000..4bb20aa --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/__init__.py @@ -0,0 +1,140 @@ +__all__ = [ + 'AbstractBasicAuthHandler', + 'AbstractDigestAuthHandler', + 'BaseHandler', + 'Browser', + 'BrowserStateError', + 'CacheFTPHandler', + 'ContentTooShortError', + 'Cookie', + 'CookieJar', + 'CookiePolicy', + 'DefaultCookiePolicy', + 'DefaultFactory', + 'FTPHandler', + 'Factory', + 'FileCookieJar', + 'FileHandler', + 'FormNotFoundError', + 'FormsFactory', + 'HTTPBasicAuthHandler', + 'HTTPCookieProcessor', + 'HTTPDefaultErrorHandler', + 'HTTPDigestAuthHandler', + 'HTTPEquivProcessor', + 'HTTPError', + 'HTTPErrorProcessor', + 'HTTPHandler', + 'HTTPPasswordMgr', + 'HTTPPasswordMgrWithDefaultRealm', + 'HTTPProxyPasswordMgr', + 'HTTPRedirectDebugProcessor', + 'HTTPRedirectHandler', + 'HTTPRefererProcessor', + 'HTTPRefreshProcessor', + 'HTTPRequestUpgradeProcessor', + 'HTTPResponseDebugProcessor', + 'HTTPRobotRulesProcessor', + 'HTTPSClientCertMgr', + 'HTTPSHandler', + 'HeadParser', + 'History', + 'LWPCookieJar', + 'Link', + 'LinkNotFoundError', + 'LinksFactory', + 'LoadError', + 'MSIECookieJar', + 'MozillaCookieJar', + 'OpenerDirector', + 'OpenerFactory', + 'ParseError', + 'ProxyBasicAuthHandler', + 'ProxyDigestAuthHandler', + 'ProxyHandler', + 'Request', + 'ResponseUpgradeProcessor', + 'RobotExclusionError', + 'RobustFactory', + 'RobustFormsFactory', + 'RobustLinksFactory', + 'RobustTitleFactory', + 'SeekableProcessor', + 'SeekableResponseOpener', + 'TitleFactory', + 'URLError', + 'USE_BARE_EXCEPT', + 'UnknownHandler', + 'UserAgent', + 'UserAgentBase', + 'XHTMLCompatibleHeadParser', + '__version__', + 'build_opener', + 'install_opener', + 'lwp_cookie_str', + 'make_response', + 'request_host', + 'response_seek_wrapper', # XXX deprecate in public interface? + 'seek_wrapped_response' # XXX should probably use this internally in place of response_seek_wrapper() + 'str2time', + 'urlopen', + 'urlretrieve'] + +import logging +import sys + +from _mechanize import __version__ + +# high-level stateful browser-style interface +from _mechanize import \ + Browser, History, \ + BrowserStateError, LinkNotFoundError, FormNotFoundError + +# configurable URL-opener interface +from _useragent import UserAgentBase, UserAgent +from _html import \ + ParseError, \ + Link, \ + Factory, DefaultFactory, RobustFactory, \ + FormsFactory, LinksFactory, TitleFactory, \ + RobustFormsFactory, RobustLinksFactory, RobustTitleFactory + +# urllib2 work-alike interface (part from mechanize, part from urllib2) +# This is a superset of the urllib2 interface. +from _urllib2 import * + +# misc +from _opener import ContentTooShortError, OpenerFactory, urlretrieve +from _util import http2time as str2time +from _response import \ + response_seek_wrapper, seek_wrapped_response, make_response +from _http import HeadParser +try: + from _http import XHTMLCompatibleHeadParser +except ImportError: + pass + +# cookies +from _clientcookie import Cookie, CookiePolicy, DefaultCookiePolicy, \ + CookieJar, FileCookieJar, LoadError, request_host_lc as request_host, \ + effective_request_host +from _lwpcookiejar import LWPCookieJar, lwp_cookie_str +# 2.4 raises SyntaxError due to generator / try/finally use +if sys.version_info[:2] > (2,4): + try: + import sqlite3 + except ImportError: + pass + else: + from _firefox3cookiejar import Firefox3CookieJar +from _mozillacookiejar import MozillaCookieJar +from _msiecookiejar import MSIECookieJar + +# If you hate the idea of turning bugs into warnings, do: +# import mechanize; mechanize.USE_BARE_EXCEPT = False +USE_BARE_EXCEPT = True + +logger = logging.getLogger("mechanize") +if logger.level is logging.NOTSET: + logger.setLevel(logging.CRITICAL) +del logger diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_auth.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_auth.py new file mode 100644 index 0000000..232f7d8 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_auth.py @@ -0,0 +1,522 @@ +"""HTTP Authentication and Proxy support. + +All but HTTPProxyPasswordMgr come from Python 2.5. + + +Copyright 2006 John J. Lee <jjl@pobox.com> + +This code is free software; you can redistribute it and/or modify it under +the terms of the BSD or ZPL 2.1 licenses (see the file COPYING.txt +included with the distribution). + +""" + +import base64 +import copy +import os +import posixpath +import random +import re +import time +import urlparse + +try: + import hashlib +except ImportError: + import md5 + import sha + def sha1_digest(bytes): + return sha.new(bytes).hexdigest() + def md5_digest(bytes): + return md5.new(bytes).hexdigest() +else: + def sha1_digest(bytes): + return hashlib.sha1(bytes).hexdigest() + def md5_digest(bytes): + return hashlib.md5(bytes).hexdigest() + +from urllib2 import BaseHandler, HTTPError, parse_keqv_list, parse_http_list +from urllib import getproxies, unquote, splittype, splituser, splitpasswd, \ + splitport + + +def _parse_proxy(proxy): + """Return (scheme, user, password, host/port) given a URL or an authority. + + If a URL is supplied, it must have an authority (host:port) component. + According to RFC 3986, having an authority component means the URL must + have two slashes after the scheme: + + >>> _parse_proxy('file:/ftp.example.com/') + Traceback (most recent call last): + ValueError: proxy URL with no authority: 'file:/ftp.example.com/' + + The first three items of the returned tuple may be None. + + Examples of authority parsing: + + >>> _parse_proxy('proxy.example.com') + (None, None, None, 'proxy.example.com') + >>> _parse_proxy('proxy.example.com:3128') + (None, None, None, 'proxy.example.com:3128') + + The authority component may optionally include userinfo (assumed to be + username:password): + + >>> _parse_proxy('joe:password@proxy.example.com') + (None, 'joe', 'password', 'proxy.example.com') + >>> _parse_proxy('joe:password@proxy.example.com:3128') + (None, 'joe', 'password', 'proxy.example.com:3128') + + Same examples, but with URLs instead: + + >>> _parse_proxy('http://proxy.example.com/') + ('http', None, None, 'proxy.example.com') + >>> _parse_proxy('http://proxy.example.com:3128/') + ('http', None, None, 'proxy.example.com:3128') + >>> _parse_proxy('http://joe:password@proxy.example.com/') + ('http', 'joe', 'password', 'proxy.example.com') + >>> _parse_proxy('http://joe:password@proxy.example.com:3128') + ('http', 'joe', 'password', 'proxy.example.com:3128') + + Everything after the authority is ignored: + + >>> _parse_proxy('ftp://joe:password@proxy.example.com/rubbish:3128') + ('ftp', 'joe', 'password', 'proxy.example.com') + + Test for no trailing '/' case: + + >>> _parse_proxy('http://joe:password@proxy.example.com') + ('http', 'joe', 'password', 'proxy.example.com') + + """ + scheme, r_scheme = splittype(proxy) + if not r_scheme.startswith("/"): + # authority + scheme = None + authority = proxy + else: + # URL + if not r_scheme.startswith("//"): + raise ValueError("proxy URL with no authority: %r" % proxy) + # We have an authority, so for RFC 3986-compliant URLs (by ss 3. + # and 3.3.), path is empty or starts with '/' + end = r_scheme.find("/", 2) + if end == -1: + end = None + authority = r_scheme[2:end] + userinfo, hostport = splituser(authority) + if userinfo is not None: + user, password = splitpasswd(userinfo) + else: + user = password = None + return scheme, user, password, hostport + +class ProxyHandler(BaseHandler): + # Proxies must be in front + handler_order = 100 + + def __init__(self, proxies=None): + if proxies is None: + proxies = getproxies() + assert hasattr(proxies, 'has_key'), "proxies must be a mapping" + self.proxies = proxies + for type, url in proxies.items(): + setattr(self, '%s_open' % type, + lambda r, proxy=url, type=type, meth=self.proxy_open: \ + meth(r, proxy, type)) + + def proxy_open(self, req, proxy, type): + orig_type = req.get_type() + proxy_type, user, password, hostport = _parse_proxy(proxy) + if proxy_type is None: + proxy_type = orig_type + if user and password: + user_pass = '%s:%s' % (unquote(user), unquote(password)) + creds = base64.encodestring(user_pass).strip() + req.add_header('Proxy-authorization', 'Basic ' + creds) + hostport = unquote(hostport) + req.set_proxy(hostport, proxy_type) + if orig_type == proxy_type: + # let other handlers take care of it + return None + else: + # need to start over, because the other handlers don't + # grok the proxy's URL type + # e.g. if we have a constructor arg proxies like so: + # {'http': 'ftp://proxy.example.com'}, we may end up turning + # a request for http://acme.example.com/a into one for + # ftp://proxy.example.com/a + return self.parent.open(req) + +class HTTPPasswordMgr: + + def __init__(self): + self.passwd = {} + + def add_password(self, realm, uri, user, passwd): + # uri could be a single URI or a sequence + if isinstance(uri, basestring): + uri = [uri] + if not realm in self.passwd: + self.passwd[realm] = {} + for default_port in True, False: + reduced_uri = tuple( + [self.reduce_uri(u, default_port) for u in uri]) + self.passwd[realm][reduced_uri] = (user, passwd) + + def find_user_password(self, realm, authuri): + domains = self.passwd.get(realm, {}) + for default_port in True, False: + reduced_authuri = self.reduce_uri(authuri, default_port) + for uris, authinfo in domains.iteritems(): + for uri in uris: + if self.is_suburi(uri, reduced_authuri): + return authinfo + return None, None + + def reduce_uri(self, uri, default_port=True): + """Accept authority or URI and extract only the authority and path.""" + # note HTTP URLs do not have a userinfo component + parts = urlparse.urlsplit(uri) + if parts[1]: + # URI + scheme = parts[0] + authority = parts[1] + path = parts[2] or '/' + else: + # host or host:port + scheme = None + authority = uri + path = '/' + host, port = splitport(authority) + if default_port and port is None and scheme is not None: + dport = {"http": 80, + "https": 443, + }.get(scheme) + if dport is not None: + authority = "%s:%d" % (host, dport) + return authority, path + + def is_suburi(self, base, test): + """Check if test is below base in a URI tree + + Both args must be URIs in reduced form. + """ + if base == test: + return True + if base[0] != test[0]: + return False + common = posixpath.commonprefix((base[1], test[1])) + if len(common) == len(base[1]): + return True + return False + + +class HTTPPasswordMgrWithDefaultRealm(HTTPPasswordMgr): + + def find_user_password(self, realm, authuri): + user, password = HTTPPasswordMgr.find_user_password(self, realm, + authuri) + if user is not None: + return user, password + return HTTPPasswordMgr.find_user_password(self, None, authuri) + + +class AbstractBasicAuthHandler: + + rx = re.compile('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', re.I) + + # XXX there can actually be multiple auth-schemes in a + # www-authenticate header. should probably be a lot more careful + # in parsing them to extract multiple alternatives + + def __init__(self, password_mgr=None): + if password_mgr is None: + password_mgr = HTTPPasswordMgr() + self.passwd = password_mgr + self.add_password = self.passwd.add_password + + def http_error_auth_reqed(self, authreq, host, req, headers): + # host may be an authority (without userinfo) or a URL with an + # authority + # XXX could be multiple headers + authreq = headers.get(authreq, None) + if authreq: + mo = AbstractBasicAuthHandler.rx.search(authreq) + if mo: + scheme, realm = mo.groups() + if scheme.lower() == 'basic': + return self.retry_http_basic_auth(host, req, realm) + + def retry_http_basic_auth(self, host, req, realm): + user, pw = self.passwd.find_user_password(realm, host) + if pw is not None: + raw = "%s:%s" % (user, pw) + auth = 'Basic %s' % base64.encodestring(raw).strip() + if req.headers.get(self.auth_header, None) == auth: + return None + newreq = copy.copy(req) + newreq.add_header(self.auth_header, auth) + newreq.visit = False + return self.parent.open(newreq) + else: + return None + + +class HTTPBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler): + + auth_header = 'Authorization' + + def http_error_401(self, req, fp, code, msg, headers): + url = req.get_full_url() + return self.http_error_auth_reqed('www-authenticate', + url, req, headers) + + +class ProxyBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler): + + auth_header = 'Proxy-authorization' + + def http_error_407(self, req, fp, code, msg, headers): + # http_error_auth_reqed requires that there is no userinfo component in + # authority. Assume there isn't one, since urllib2 does not (and + # should not, RFC 3986 s. 3.2.1) support requests for URLs containing + # userinfo. + authority = req.get_host() + return self.http_error_auth_reqed('proxy-authenticate', + authority, req, headers) + + +def randombytes(n): + """Return n random bytes.""" + # Use /dev/urandom if it is available. Fall back to random module + # if not. It might be worthwhile to extend this function to use + # other platform-specific mechanisms for getting random bytes. + if os.path.exists("/dev/urandom"): + f = open("/dev/urandom") + s = f.read(n) + f.close() + return s + else: + L = [chr(random.randrange(0, 256)) for i in range(n)] + return "".join(L) + +class AbstractDigestAuthHandler: + # Digest authentication is specified in RFC 2617. + + # XXX The client does not inspect the Authentication-Info header + # in a successful response. + + # XXX It should be possible to test this implementation against + # a mock server that just generates a static set of challenges. + + # XXX qop="auth-int" supports is shaky + + def __init__(self, passwd=None): + if passwd is None: + passwd = HTTPPasswordMgr() + self.passwd = passwd + self.add_password = self.passwd.add_password + self.retried = 0 + self.nonce_count = 0 + + def reset_retry_count(self): + self.retried = 0 + + def http_error_auth_reqed(self, auth_header, host, req, headers): + authreq = headers.get(auth_header, None) + if self.retried > 5: + # Don't fail endlessly - if we failed once, we'll probably + # fail a second time. Hm. Unless the Password Manager is + # prompting for the information. Crap. This isn't great + # but it's better than the current 'repeat until recursion + # depth exceeded' approach <wink> + raise HTTPError(req.get_full_url(), 401, "digest auth failed", + headers, None) + else: + self.retried += 1 + if authreq: + scheme = authreq.split()[0] + if scheme.lower() == 'digest': + return self.retry_http_digest_auth(req, authreq) + + def retry_http_digest_auth(self, req, auth): + token, challenge = auth.split(' ', 1) + chal = parse_keqv_list(parse_http_list(challenge)) + auth = self.get_authorization(req, chal) + if auth: + auth_val = 'Digest %s' % auth + if req.headers.get(self.auth_header, None) == auth_val: + return None + newreq = copy.copy(req) + newreq.add_unredirected_header(self.auth_header, auth_val) + newreq.visit = False + return self.parent.open(newreq) + + def get_cnonce(self, nonce): + # The cnonce-value is an opaque + # quoted string value provided by the client and used by both client + # and server to avoid chosen plaintext attacks, to provide mutual + # authentication, and to provide some message integrity protection. + # This isn't a fabulous effort, but it's probably Good Enough. + dig = sha1_digest("%s:%s:%s:%s" % (self.nonce_count, nonce, + time.ctime(), randombytes(8))) + return dig[:16] + + def get_authorization(self, req, chal): + try: + realm = chal['realm'] + nonce = chal['nonce'] + qop = chal.get('qop') + algorithm = chal.get('algorithm', 'MD5') + # mod_digest doesn't send an opaque, even though it isn't + # supposed to be optional + opaque = chal.get('opaque', None) + except KeyError: + return None + + H, KD = self.get_algorithm_impls(algorithm) + if H is None: + return None + + user, pw = self.passwd.find_user_password(realm, req.get_full_url()) + if user is None: + return None + + # XXX not implemented yet + if req.has_data(): + entdig = self.get_entity_digest(req.get_data(), chal) + else: + entdig = None + + A1 = "%s:%s:%s" % (user, realm, pw) + A2 = "%s:%s" % (req.get_method(), + # XXX selector: what about proxies and full urls + req.get_selector()) + if qop == 'auth': + self.nonce_count += 1 + ncvalue = '%08x' % self.nonce_count + cnonce = self.get_cnonce(nonce) + noncebit = "%s:%s:%s:%s:%s" % (nonce, ncvalue, cnonce, qop, H(A2)) + respdig = KD(H(A1), noncebit) + elif qop is None: + respdig = KD(H(A1), "%s:%s" % (nonce, H(A2))) + else: + # XXX handle auth-int. + pass + + # XXX should the partial digests be encoded too? + + base = 'username="%s", realm="%s", nonce="%s", uri="%s", ' \ + 'response="%s"' % (user, realm, nonce, req.get_selector(), + respdig) + if opaque: + base += ', opaque="%s"' % opaque + if entdig: + base += ', digest="%s"' % entdig + base += ', algorithm="%s"' % algorithm + if qop: + base += ', qop=auth, nc=%s, cnonce="%s"' % (ncvalue, cnonce) + return base + + def get_algorithm_impls(self, algorithm): + # lambdas assume digest modules are imported at the top level + if algorithm == 'MD5': + H = md5_digest + elif algorithm == 'SHA': + H = sha1_digest + # XXX MD5-sess + KD = lambda s, d: H("%s:%s" % (s, d)) + return H, KD + + def get_entity_digest(self, data, chal): + # XXX not implemented yet + return None + + +class HTTPDigestAuthHandler(BaseHandler, AbstractDigestAuthHandler): + """An authentication protocol defined by RFC 2069 + + Digest authentication improves on basic authentication because it + does not transmit passwords in the clear. + """ + + auth_header = 'Authorization' + handler_order = 490 + + def http_error_401(self, req, fp, code, msg, headers): + host = urlparse.urlparse(req.get_full_url())[1] + retry = self.http_error_auth_reqed('www-authenticate', + host, req, headers) + self.reset_retry_count() + return retry + + +class ProxyDigestAuthHandler(BaseHandler, AbstractDigestAuthHandler): + + auth_header = 'Proxy-Authorization' + handler_order = 490 + + def http_error_407(self, req, fp, code, msg, headers): + host = req.get_host() + retry = self.http_error_auth_reqed('proxy-authenticate', + host, req, headers) + self.reset_retry_count() + return retry + + +# XXX ugly implementation, should probably not bother deriving +class HTTPProxyPasswordMgr(HTTPPasswordMgr): + # has default realm and host/port + def add_password(self, realm, uri, user, passwd): + # uri could be a single URI or a sequence + if uri is None or isinstance(uri, basestring): + uris = [uri] + else: + uris = uri + passwd_by_domain = self.passwd.setdefault(realm, {}) + for uri in uris: + for default_port in True, False: + reduced_uri = self.reduce_uri(uri, default_port) + passwd_by_domain[reduced_uri] = (user, passwd) + + def find_user_password(self, realm, authuri): + attempts = [(realm, authuri), (None, authuri)] + # bleh, want default realm to take precedence over default + # URI/authority, hence this outer loop + for default_uri in False, True: + for realm, authuri in attempts: + authinfo_by_domain = self.passwd.get(realm, {}) + for default_port in True, False: + reduced_authuri = self.reduce_uri(authuri, default_port) + for uri, authinfo in authinfo_by_domain.iteritems(): + if uri is None and not default_uri: + continue + if self.is_suburi(uri, reduced_authuri): + return authinfo + user, password = None, None + + if user is not None: + break + return user, password + + def reduce_uri(self, uri, default_port=True): + if uri is None: + return None + return HTTPPasswordMgr.reduce_uri(self, uri, default_port) + + def is_suburi(self, base, test): + if base is None: + # default to the proxy's host/port + hostport, path = test + base = (hostport, "/") + return HTTPPasswordMgr.is_suburi(self, base, test) + + +class HTTPSClientCertMgr(HTTPPasswordMgr): + # implementation inheritance: this is not a proper subclass + def add_key_cert(self, uri, key_file, cert_file): + self.add_password(None, uri, key_file, cert_file) + def find_key_cert(self, authuri): + return HTTPPasswordMgr.find_user_password(self, None, authuri) diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_beautifulsoup.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_beautifulsoup.py new file mode 100644 index 0000000..268b305 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_beautifulsoup.py @@ -0,0 +1,1080 @@ +"""Beautiful Soup +Elixir and Tonic +"The Screen-Scraper's Friend" +v2.1.1 +http://www.crummy.com/software/BeautifulSoup/ + +Beautiful Soup parses arbitrarily invalid XML- or HTML-like substance +into a tree representation. It provides methods and Pythonic idioms +that make it easy to search and modify the tree. + +A well-formed XML/HTML document will yield a well-formed data +structure. An ill-formed XML/HTML document will yield a +correspondingly ill-formed data structure. If your document is only +locally well-formed, you can use this library to find and process the +well-formed part of it. The BeautifulSoup class has heuristics for +obtaining a sensible parse tree in the face of common HTML errors. + +Beautiful Soup has no external dependencies. It works with Python 2.2 +and up. + +Beautiful Soup defines classes for four different parsing strategies: + + * BeautifulStoneSoup, for parsing XML, SGML, or your domain-specific + language that kind of looks like XML. + + * BeautifulSoup, for parsing run-of-the-mill HTML code, be it valid + or invalid. + + * ICantBelieveItsBeautifulSoup, for parsing valid but bizarre HTML + that trips up BeautifulSoup. + + * BeautifulSOAP, for making it easier to parse XML documents that use + lots of subelements containing a single string, where you'd prefer + they put that string into an attribute (such as SOAP messages). + +You can subclass BeautifulStoneSoup or BeautifulSoup to create a +parsing strategy specific to an XML schema or a particular bizarre +HTML document. Typically your subclass would just override +SELF_CLOSING_TAGS and/or NESTABLE_TAGS. +""" #" +from __future__ import generators + +__author__ = "Leonard Richardson (leonardr@segfault.org)" +__version__ = "2.1.1" +__date__ = "$Date: 2004/10/18 00:14:20 $" +__copyright__ = "Copyright (c) 2004-2005 Leonard Richardson" +__license__ = "PSF" + +from sgmllib import SGMLParser, SGMLParseError +import types +import re +import sgmllib + +#This code makes Beautiful Soup able to parse XML with namespaces +sgmllib.tagfind = re.compile('[a-zA-Z][-_.:a-zA-Z0-9]*') + +class NullType(object): + + """Similar to NoneType with a corresponding singleton instance + 'Null' that, unlike None, accepts any message and returns itself. + + Examples: + >>> Null("send", "a", "message")("and one more", + ... "and what you get still") is Null + True + """ + + def __new__(cls): return Null + def __call__(self, *args, **kwargs): return Null +## def __getstate__(self, *args): return Null + def __getattr__(self, attr): return Null + def __getitem__(self, item): return Null + def __setattr__(self, attr, value): pass + def __setitem__(self, item, value): pass + def __len__(self): return 0 + # FIXME: is this a python bug? otherwise ``for x in Null: pass`` + # never terminates... + def __iter__(self): return iter([]) + def __contains__(self, item): return False + def __repr__(self): return "Null" +Null = object.__new__(NullType) + +class PageElement: + """Contains the navigational information for some part of the page + (either a tag or a piece of text)""" + + def setup(self, parent=Null, previous=Null): + """Sets up the initial relations between this element and + other elements.""" + self.parent = parent + self.previous = previous + self.next = Null + self.previousSibling = Null + self.nextSibling = Null + if self.parent and self.parent.contents: + self.previousSibling = self.parent.contents[-1] + self.previousSibling.nextSibling = self + + def findNext(self, name=None, attrs={}, text=None): + """Returns the first item that matches the given criteria and + appears after this Tag in the document.""" + return self._first(self.fetchNext, name, attrs, text) + firstNext = findNext + + def fetchNext(self, name=None, attrs={}, text=None, limit=None): + """Returns all items that match the given criteria and appear + before after Tag in the document.""" + return self._fetch(name, attrs, text, limit, self.nextGenerator) + + def findNextSibling(self, name=None, attrs={}, text=None): + """Returns the closest sibling to this Tag that matches the + given criteria and appears after this Tag in the document.""" + return self._first(self.fetchNextSiblings, name, attrs, text) + firstNextSibling = findNextSibling + + def fetchNextSiblings(self, name=None, attrs={}, text=None, limit=None): + """Returns the siblings of this Tag that match the given + criteria and appear after this Tag in the document.""" + return self._fetch(name, attrs, text, limit, self.nextSiblingGenerator) + + def findPrevious(self, name=None, attrs={}, text=None): + """Returns the first item that matches the given criteria and + appears before this Tag in the document.""" + return self._first(self.fetchPrevious, name, attrs, text) + + def fetchPrevious(self, name=None, attrs={}, text=None, limit=None): + """Returns all items that match the given criteria and appear + before this Tag in the document.""" + return self._fetch(name, attrs, text, limit, self.previousGenerator) + firstPrevious = findPrevious + + def findPreviousSibling(self, name=None, attrs={}, text=None): + """Returns the closest sibling to this Tag that matches the + given criteria and appears before this Tag in the document.""" + return self._first(self.fetchPreviousSiblings, name, attrs, text) + firstPreviousSibling = findPreviousSibling + + def fetchPreviousSiblings(self, name=None, attrs={}, text=None, + limit=None): + """Returns the siblings of this Tag that match the given + criteria and appear before this Tag in the document.""" + return self._fetch(name, attrs, text, limit, + self.previousSiblingGenerator) + + def findParent(self, name=None, attrs={}): + """Returns the closest parent of this Tag that matches the given + criteria.""" + r = Null + l = self.fetchParents(name, attrs, 1) + if l: + r = l[0] + return r + firstParent = findParent + + def fetchParents(self, name=None, attrs={}, limit=None): + """Returns the parents of this Tag that match the given + criteria.""" + return self._fetch(name, attrs, None, limit, self.parentGenerator) + + #These methods do the real heavy lifting. + + def _first(self, method, name, attrs, text): + r = Null + l = method(name, attrs, text, 1) + if l: + r = l[0] + return r + + def _fetch(self, name, attrs, text, limit, generator): + "Iterates over a generator looking for things that match." + if not hasattr(attrs, 'items'): + attrs = {'class' : attrs} + + results = [] + g = generator() + while True: + try: + i = g.next() + except StopIteration: + break + found = None + if isinstance(i, Tag): + if not text: + if not name or self._matches(i, name): + match = True + for attr, matchAgainst in attrs.items(): + check = i.get(attr) + if not self._matches(check, matchAgainst): + match = False + break + if match: + found = i + elif text: + if self._matches(i, text): + found = i + if found: + results.append(found) + if limit and len(results) >= limit: + break + return results + + #Generators that can be used to navigate starting from both + #NavigableTexts and Tags. + def nextGenerator(self): + i = self + while i: + i = i.next + yield i + + def nextSiblingGenerator(self): + i = self + while i: + i = i.nextSibling + yield i + + def previousGenerator(self): + i = self + while i: + i = i.previous + yield i + + def previousSiblingGenerator(self): + i = self + while i: + i = i.previousSibling + yield i + + def parentGenerator(self): + i = self + while i: + i = i.parent + yield i + + def _matches(self, chunk, howToMatch): + #print 'looking for %s in %s' % (howToMatch, chunk) + # + # If given a list of items, return true if the list contains a + # text element that matches. + if isList(chunk) and not isinstance(chunk, Tag): + for tag in chunk: + if isinstance(tag, NavigableText) and self._matches(tag, howToMatch): + return True + return False + if callable(howToMatch): + return howToMatch(chunk) + if isinstance(chunk, Tag): + #Custom match methods take the tag as an argument, but all other + #ways of matching match the tag name as a string + chunk = chunk.name + #Now we know that chunk is a string + if not isinstance(chunk, basestring): + chunk = str(chunk) + if hasattr(howToMatch, 'match'): + # It's a regexp object. + return howToMatch.search(chunk) + if isList(howToMatch): + return chunk in howToMatch + if hasattr(howToMatch, 'items'): + return howToMatch.has_key(chunk) + #It's just a string + return str(howToMatch) == chunk + +class NavigableText(PageElement): + + def __getattr__(self, attr): + "For backwards compatibility, text.string gives you text" + if attr == 'string': + return self + else: + raise AttributeError, "'%s' object has no attribute '%s'" % (self.__class__.__name__, attr) + +class NavigableString(str, NavigableText): + pass + +class NavigableUnicodeString(unicode, NavigableText): + pass + +class Tag(PageElement): + + """Represents a found HTML tag with its attributes and contents.""" + + def __init__(self, name, attrs=None, parent=Null, previous=Null): + "Basic constructor." + self.name = name + if attrs == None: + attrs = [] + self.attrs = attrs + self.contents = [] + self.setup(parent, previous) + self.hidden = False + + def get(self, key, default=None): + """Returns the value of the 'key' attribute for the tag, or + the value given for 'default' if it doesn't have that + attribute.""" + return self._getAttrMap().get(key, default) + + def __getitem__(self, key): + """tag[key] returns the value of the 'key' attribute for the tag, + and throws an exception if it's not there.""" + return self._getAttrMap()[key] + + def __iter__(self): + "Iterating over a tag iterates over its contents." + return iter(self.contents) + + def __len__(self): + "The length of a tag is the length of its list of contents." + return len(self.contents) + + def __contains__(self, x): + return x in self.contents + + def __nonzero__(self): + "A tag is non-None even if it has no contents." + return True + + def __setitem__(self, key, value): + """Setting tag[key] sets the value of the 'key' attribute for the + tag.""" + self._getAttrMap() + self.attrMap[key] = value + found = False + for i in range(0, len(self.attrs)): + if self.attrs[i][0] == key: + self.attrs[i] = (key, value) + found = True + if not found: + self.attrs.append((key, value)) + self._getAttrMap()[key] = value + + def __delitem__(self, key): + "Deleting tag[key] deletes all 'key' attributes for the tag." + for item in self.attrs: + if item[0] == key: + self.attrs.remove(item) + #We don't break because bad HTML can define the same + #attribute multiple times. + self._getAttrMap() + if self.attrMap.has_key(key): + del self.attrMap[key] + + def __call__(self, *args, **kwargs): + """Calling a tag like a function is the same as calling its + fetch() method. Eg. tag('a') returns a list of all the A tags + found within this tag.""" + return apply(self.fetch, args, kwargs) + + def __getattr__(self, tag): + if len(tag) > 3 and tag.rfind('Tag') == len(tag)-3: + return self.first(tag[:-3]) + elif tag.find('__') != 0: + return self.first(tag) + + def __eq__(self, other): + """Returns true iff this tag has the same name, the same attributes, + and the same contents (recursively) as the given tag. + + NOTE: right now this will return false if two tags have the + same attributes in a different order. Should this be fixed?""" + if not hasattr(other, 'name') or not hasattr(other, 'attrs') or not hasattr(other, 'contents') or self.name != other.name or self.attrs != other.attrs or len(self) != len(other): + return False + for i in range(0, len(self.contents)): + if self.contents[i] != other.contents[i]: + return False + return True + + def __ne__(self, other): + """Returns true iff this tag is not identical to the other tag, + as defined in __eq__.""" + return not self == other + + def __repr__(self): + """Renders this tag as a string.""" + return str(self) + + def __unicode__(self): + return self.__str__(1) + + def __str__(self, needUnicode=None, showStructureIndent=None): + """Returns a string or Unicode representation of this tag and + its contents. + + NOTE: since Python's HTML parser consumes whitespace, this + method is not certain to reproduce the whitespace present in + the original string.""" + + attrs = [] + if self.attrs: + for key, val in self.attrs: + attrs.append('%s="%s"' % (key, val)) + close = '' + closeTag = '' + if self.isSelfClosing(): + close = ' /' + else: + closeTag = '</%s>' % self.name + indentIncrement = None + if showStructureIndent != None: + indentIncrement = showStructureIndent + if not self.hidden: + indentIncrement += 1 + contents = self.renderContents(indentIncrement, needUnicode=needUnicode) + if showStructureIndent: + space = '\n%s' % (' ' * showStructureIndent) + if self.hidden: + s = contents + else: + s = [] + attributeString = '' + if attrs: + attributeString = ' ' + ' '.join(attrs) + if showStructureIndent: + s.append(space) + s.append('<%s%s%s>' % (self.name, attributeString, close)) + s.append(contents) + if closeTag and showStructureIndent != None: + s.append(space) + s.append(closeTag) + s = ''.join(s) + isUnicode = type(s) == types.UnicodeType + if needUnicode and not isUnicode: + s = unicode(s) + elif isUnicode and needUnicode==False: + s = str(s) + return s + + def prettify(self, needUnicode=None): + return self.__str__(needUnicode, showStructureIndent=True) + + def renderContents(self, showStructureIndent=None, needUnicode=None): + """Renders the contents of this tag as a (possibly Unicode) + string.""" + s=[] + for c in self: + text = None + if isinstance(c, NavigableUnicodeString) or type(c) == types.UnicodeType: + text = unicode(c) + elif isinstance(c, Tag): + s.append(c.__str__(needUnicode, showStructureIndent)) + elif needUnicode: + text = unicode(c) + else: + text = str(c) + if text: + if showStructureIndent != None: + if text[-1] == '\n': + text = text[:-1] + s.append(text) + return ''.join(s) + + #Soup methods + + def firstText(self, text, recursive=True): + """Convenience method to retrieve the first piece of text matching the + given criteria. 'text' can be a string, a regular expression object, + a callable that takes a string and returns whether or not the + string 'matches', etc.""" + return self.first(recursive=recursive, text=text) + + def fetchText(self, text, recursive=True, limit=None): + """Convenience method to retrieve all pieces of text matching the + given criteria. 'text' can be a string, a regular expression object, + a callable that takes a string and returns whether or not the + string 'matches', etc.""" + return self.fetch(recursive=recursive, text=text, limit=limit) + + def first(self, name=None, attrs={}, recursive=True, text=None): + """Return only the first child of this + Tag matching the given criteria.""" + r = Null + l = self.fetch(name, attrs, recursive, text, 1) + if l: + r = l[0] + return r + findChild = first + + def fetch(self, name=None, attrs={}, recursive=True, text=None, + limit=None): + """Extracts a list of Tag objects that match the given + criteria. You can specify the name of the Tag and any + attributes you want the Tag to have. + + The value of a key-value pair in the 'attrs' map can be a + string, a list of strings, a regular expression object, or a + callable that takes a string and returns whether or not the + string matches for some custom definition of 'matches'. The + same is true of the tag name.""" + generator = self.recursiveChildGenerator + if not recursive: + generator = self.childGenerator + return self._fetch(name, attrs, text, limit, generator) + fetchChildren = fetch + + #Utility methods + + def isSelfClosing(self): + """Returns true iff this is a self-closing tag as defined in the HTML + standard. + + TODO: This is specific to BeautifulSoup and its subclasses, but it's + used by __str__""" + return self.name in BeautifulSoup.SELF_CLOSING_TAGS + + def append(self, tag): + """Appends the given tag to the contents of this tag.""" + self.contents.append(tag) + + #Private methods + + def _getAttrMap(self): + """Initializes a map representation of this tag's attributes, + if not already initialized.""" + if not getattr(self, 'attrMap'): + self.attrMap = {} + for (key, value) in self.attrs: + self.attrMap[key] = value + return self.attrMap + + #Generator methods + def childGenerator(self): + for i in range(0, len(self.contents)): + yield self.contents[i] + raise StopIteration + + def recursiveChildGenerator(self): + stack = [(self, 0)] + while stack: + tag, start = stack.pop() + if isinstance(tag, Tag): + for i in range(start, len(tag.contents)): + a = tag.contents[i] + yield a + if isinstance(a, Tag) and tag.contents: + if i < len(tag.contents) - 1: + stack.append((tag, i+1)) + stack.append((a, 0)) + break + raise StopIteration + + +def isList(l): + """Convenience method that works with all 2.x versions of Python + to determine whether or not something is listlike.""" + return hasattr(l, '__iter__') \ + or (type(l) in (types.ListType, types.TupleType)) + +def buildTagMap(default, *args): + """Turns a list of maps, lists, or scalars into a single map. + Used to build the SELF_CLOSING_TAGS and NESTABLE_TAGS maps out + of lists and partial maps.""" + built = {} + for portion in args: + if hasattr(portion, 'items'): + #It's a map. Merge it. + for k,v in portion.items(): + built[k] = v + elif isList(portion): + #It's a list. Map each item to the default. + for k in portion: + built[k] = default + else: + #It's a scalar. Map it to the default. + built[portion] = default + return built + +class BeautifulStoneSoup(Tag, SGMLParser): + + """This class contains the basic parser and fetch code. It defines + a parser that knows nothing about tag behavior except for the + following: + + You can't close a tag without closing all the tags it encloses. + That is, "<foo><bar></foo>" actually means + "<foo><bar></bar></foo>". + + [Another possible explanation is "<foo><bar /></foo>", but since + this class defines no SELF_CLOSING_TAGS, it will never use that + explanation.] + + This class is useful for parsing XML or made-up markup languages, + or when BeautifulSoup makes an assumption counter to what you were + expecting.""" + + SELF_CLOSING_TAGS = {} + NESTABLE_TAGS = {} + RESET_NESTING_TAGS = {} + QUOTE_TAGS = {} + + #As a public service we will by default silently replace MS smart quotes + #and similar characters with their HTML or ASCII equivalents. + MS_CHARS = { '\x80' : '€', + '\x81' : ' ', + '\x82' : '‚', + '\x83' : 'ƒ', + '\x84' : '„', + '\x85' : '…', + '\x86' : '†', + '\x87' : '‡', + '\x88' : '⁁', + '\x89' : '%', + '\x8A' : 'Š', + '\x8B' : '<', + '\x8C' : 'Œ', + '\x8D' : '?', + '\x8E' : 'Z', + '\x8F' : '?', + '\x90' : '?', + '\x91' : '‘', + '\x92' : '’', + '\x93' : '“', + '\x94' : '”', + '\x95' : '•', + '\x96' : '–', + '\x97' : '—', + '\x98' : '˜', + '\x99' : '™', + '\x9a' : 'š', + '\x9b' : '>', + '\x9c' : 'œ', + '\x9d' : '?', + '\x9e' : 'z', + '\x9f' : 'Ÿ',} + + PARSER_MASSAGE = [(re.compile('(<[^<>]*)/>'), + lambda(x):x.group(1) + ' />'), + (re.compile('<!\s+([^<>]*)>'), + lambda(x):'<!' + x.group(1) + '>'), + (re.compile("([\x80-\x9f])"), + lambda(x): BeautifulStoneSoup.MS_CHARS.get(x.group(1))) + ] + + ROOT_TAG_NAME = '[document]' + + def __init__(self, text=None, avoidParserProblems=True, + initialTextIsEverything=True): + """Initialize this as the 'root tag' and feed in any text to + the parser. + + NOTE about avoidParserProblems: sgmllib will process most bad + HTML, and BeautifulSoup has tricks for dealing with some HTML + that kills sgmllib, but Beautiful Soup can nonetheless choke + or lose data if your data uses self-closing tags or + declarations incorrectly. By default, Beautiful Soup sanitizes + its input to avoid the vast majority of these problems. The + problems are relatively rare, even in bad HTML, so feel free + to pass in False to avoidParserProblems if they don't apply to + you, and you'll get better performance. The only reason I have + this turned on by default is so I don't get so many tech + support questions. + + The two most common instances of invalid HTML that will choke + sgmllib are fixed by the default parser massage techniques: + + <br/> (No space between name of closing tag and tag close) + <! --Comment--> (Extraneous whitespace in declaration) + + You can pass in a custom list of (RE object, replace method) + tuples to get Beautiful Soup to scrub your input the way you + want.""" + Tag.__init__(self, self.ROOT_TAG_NAME) + if avoidParserProblems \ + and not isList(avoidParserProblems): + avoidParserProblems = self.PARSER_MASSAGE + self.avoidParserProblems = avoidParserProblems + SGMLParser.__init__(self) + self.quoteStack = [] + self.hidden = 1 + self.reset() + if hasattr(text, 'read'): + #It's a file-type object. + text = text.read() + if text: + self.feed(text) + if initialTextIsEverything: + self.done() + + def __getattr__(self, methodName): + """This method routes method call requests to either the SGMLParser + superclass or the Tag superclass, depending on the method name.""" + if methodName.find('start_') == 0 or methodName.find('end_') == 0 \ + or methodName.find('do_') == 0: + return SGMLParser.__getattr__(self, methodName) + elif methodName.find('__') != 0: + return Tag.__getattr__(self, methodName) + else: + raise AttributeError + + def feed(self, text): + if self.avoidParserProblems: + for fix, m in self.avoidParserProblems: + text = fix.sub(m, text) + SGMLParser.feed(self, text) + + def done(self): + """Called when you're done parsing, so that the unclosed tags can be + correctly processed.""" + self.endData() #NEW + while self.currentTag.name != self.ROOT_TAG_NAME: + self.popTag() + + def reset(self): + SGMLParser.reset(self) + self.currentData = [] + self.currentTag = None + self.tagStack = [] + self.pushTag(self) + + def popTag(self): + tag = self.tagStack.pop() + # Tags with just one string-owning child get the child as a + # 'string' property, so that soup.tag.string is shorthand for + # soup.tag.contents[0] + if len(self.currentTag.contents) == 1 and \ + isinstance(self.currentTag.contents[0], NavigableText): + self.currentTag.string = self.currentTag.contents[0] + + #print "Pop", tag.name + if self.tagStack: + self.currentTag = self.tagStack[-1] + return self.currentTag + + def pushTag(self, tag): + #print "Push", tag.name + if self.currentTag: + self.currentTag.append(tag) + self.tagStack.append(tag) + self.currentTag = self.tagStack[-1] + + def endData(self): + currentData = ''.join(self.currentData) + if currentData: + if not currentData.strip(): + if '\n' in currentData: + currentData = '\n' + else: + currentData = ' ' + c = NavigableString + if type(currentData) == types.UnicodeType: + c = NavigableUnicodeString + o = c(currentData) + o.setup(self.currentTag, self.previous) + if self.previous: + self.previous.next = o + self.previous = o + self.currentTag.contents.append(o) + self.currentData = [] + + def _popToTag(self, name, inclusivePop=True): + """Pops the tag stack up to and including the most recent + instance of the given tag. If inclusivePop is false, pops the tag + stack up to but *not* including the most recent instqance of + the given tag.""" + if name == self.ROOT_TAG_NAME: + return + + numPops = 0 + mostRecentTag = None + for i in range(len(self.tagStack)-1, 0, -1): + if name == self.tagStack[i].name: + numPops = len(self.tagStack)-i + break + if not inclusivePop: + numPops = numPops - 1 + + for i in range(0, numPops): + mostRecentTag = self.popTag() + return mostRecentTag + + def _smartPop(self, name): + + """We need to pop up to the previous tag of this type, unless + one of this tag's nesting reset triggers comes between this + tag and the previous tag of this type, OR unless this tag is a + generic nesting trigger and another generic nesting trigger + comes between this tag and the previous tag of this type. + + Examples: + <p>Foo<b>Bar<p> should pop to 'p', not 'b'. + <p>Foo<table>Bar<p> should pop to 'table', not 'p'. + <p>Foo<table><tr>Bar<p> should pop to 'tr', not 'p'. + <p>Foo<b>Bar<p> should pop to 'p', not 'b'. + + <li><ul><li> *<li>* should pop to 'ul', not the first 'li'. + <tr><table><tr> *<tr>* should pop to 'table', not the first 'tr' + <td><tr><td> *<td>* should pop to 'tr', not the first 'td' + """ + + nestingResetTriggers = self.NESTABLE_TAGS.get(name) + isNestable = nestingResetTriggers != None + isResetNesting = self.RESET_NESTING_TAGS.has_key(name) + popTo = None + inclusive = True + for i in range(len(self.tagStack)-1, 0, -1): + p = self.tagStack[i] + if (not p or p.name == name) and not isNestable: + #Non-nestable tags get popped to the top or to their + #last occurance. + popTo = name + break + if (nestingResetTriggers != None + and p.name in nestingResetTriggers) \ + or (nestingResetTriggers == None and isResetNesting + and self.RESET_NESTING_TAGS.has_key(p.name)): + + #If we encounter one of the nesting reset triggers + #peculiar to this tag, or we encounter another tag + #that causes nesting to reset, pop up to but not + #including that tag. + + popTo = p.name + inclusive = False + break + p = p.parent + if popTo: + self._popToTag(popTo, inclusive) + + def unknown_starttag(self, name, attrs, selfClosing=0): + #print "Start tag %s" % name + if self.quoteStack: + #This is not a real tag. + #print "<%s> is not real!" % name + attrs = ''.join(map(lambda(x, y): ' %s="%s"' % (x, y), attrs)) + self.handle_data('<%s%s>' % (name, attrs)) + return + self.endData() + if not name in self.SELF_CLOSING_TAGS and not selfClosing: + self._smartPop(name) + tag = Tag(name, attrs, self.currentTag, self.previous) + if self.previous: + self.previous.next = tag + self.previous = tag + self.pushTag(tag) + if selfClosing or name in self.SELF_CLOSING_TAGS: + self.popTag() + if name in self.QUOTE_TAGS: + #print "Beginning quote (%s)" % name + self.quoteStack.append(name) + self.literal = 1 + + def unknown_endtag(self, name): + if self.quoteStack and self.quoteStack[-1] != name: + #This is not a real end tag. + #print "</%s> is not real!" % name + self.handle_data('</%s>' % name) + return + self.endData() + self._popToTag(name) + if self.quoteStack and self.quoteStack[-1] == name: + self.quoteStack.pop() + self.literal = (len(self.quoteStack) > 0) + + def handle_data(self, data): + self.currentData.append(data) + + def handle_pi(self, text): + "Propagate processing instructions right through." + self.handle_data("<?%s>" % text) + + def handle_comment(self, text): + "Propagate comments right through." + self.handle_data("<!--%s-->" % text) + + def handle_charref(self, ref): + "Propagate char refs right through." + self.handle_data('&#%s;' % ref) + + def handle_entityref(self, ref): + "Propagate entity refs right through." + self.handle_data('&%s;' % ref) + + def handle_decl(self, data): + "Propagate DOCTYPEs and the like right through." + self.handle_data('<!%s>' % data) + + def parse_declaration(self, i): + """Treat a bogus SGML declaration as raw data. Treat a CDATA + declaration as regular data.""" + j = None + if self.rawdata[i:i+9] == '<![CDATA[': + k = self.rawdata.find(']]>', i) + if k == -1: + k = len(self.rawdata) + self.handle_data(self.rawdata[i+9:k]) + j = k+3 + else: + try: + j = SGMLParser.parse_declaration(self, i) + except SGMLParseError: + toHandle = self.rawdata[i:] + self.handle_data(toHandle) + j = i + len(toHandle) + return j + +class BeautifulSoup(BeautifulStoneSoup): + + """This parser knows the following facts about HTML: + + * Some tags have no closing tag and should be interpreted as being + closed as soon as they are encountered. + + * The text inside some tags (ie. 'script') may contain tags which + are not really part of the document and which should be parsed + as text, not tags. If you want to parse the text as tags, you can + always fetch it and parse it explicitly. + + * Tag nesting rules: + + Most tags can't be nested at all. For instance, the occurance of + a <p> tag should implicitly close the previous <p> tag. + + <p>Para1<p>Para2 + should be transformed into: + <p>Para1</p><p>Para2 + + Some tags can be nested arbitrarily. For instance, the occurance + of a <blockquote> tag should _not_ implicitly close the previous + <blockquote> tag. + + Alice said: <blockquote>Bob said: <blockquote>Blah + should NOT be transformed into: + Alice said: <blockquote>Bob said: </blockquote><blockquote>Blah + + Some tags can be nested, but the nesting is reset by the + interposition of other tags. For instance, a <tr> tag should + implicitly close the previous <tr> tag within the same <table>, + but not close a <tr> tag in another table. + + <table><tr>Blah<tr>Blah + should be transformed into: + <table><tr>Blah</tr><tr>Blah + but, + <tr>Blah<table><tr>Blah + should NOT be transformed into + <tr>Blah<table></tr><tr>Blah + + Differing assumptions about tag nesting rules are a major source + of problems with the BeautifulSoup class. If BeautifulSoup is not + treating as nestable a tag your page author treats as nestable, + try ICantBelieveItsBeautifulSoup before writing your own + subclass.""" + + SELF_CLOSING_TAGS = buildTagMap(None, ['br' , 'hr', 'input', 'img', 'meta', + 'spacer', 'link', 'frame', 'base']) + + QUOTE_TAGS = {'script': None} + + #According to the HTML standard, each of these inline tags can + #contain another tag of the same type. Furthermore, it's common + #to actually use these tags this way. + NESTABLE_INLINE_TAGS = ['span', 'font', 'q', 'object', 'bdo', 'sub', 'sup', + 'center'] + + #According to the HTML standard, these block tags can contain + #another tag of the same type. Furthermore, it's common + #to actually use these tags this way. + NESTABLE_BLOCK_TAGS = ['blockquote', 'div', 'fieldset', 'ins', 'del'] + + #Lists can contain other lists, but there are restrictions. + NESTABLE_LIST_TAGS = { 'ol' : [], + 'ul' : [], + 'li' : ['ul', 'ol'], + 'dl' : [], + 'dd' : ['dl'], + 'dt' : ['dl'] } + + #Tables can contain other tables, but there are restrictions. + NESTABLE_TABLE_TAGS = {'table' : [], + 'tr' : ['table', 'tbody', 'tfoot', 'thead'], + 'td' : ['tr'], + 'th' : ['tr'], + } + + NON_NESTABLE_BLOCK_TAGS = ['address', 'form', 'p', 'pre'] + + #If one of these tags is encountered, all tags up to the next tag of + #this type are popped. + RESET_NESTING_TAGS = buildTagMap(None, NESTABLE_BLOCK_TAGS, 'noscript', + NON_NESTABLE_BLOCK_TAGS, + NESTABLE_LIST_TAGS, + NESTABLE_TABLE_TAGS) + + NESTABLE_TAGS = buildTagMap([], NESTABLE_INLINE_TAGS, NESTABLE_BLOCK_TAGS, + NESTABLE_LIST_TAGS, NESTABLE_TABLE_TAGS) + +class ICantBelieveItsBeautifulSoup(BeautifulSoup): + + """The BeautifulSoup class is oriented towards skipping over + common HTML errors like unclosed tags. However, sometimes it makes + errors of its own. For instance, consider this fragment: + + <b>Foo<b>Bar</b></b> + + This is perfectly valid (if bizarre) HTML. However, the + BeautifulSoup class will implicitly close the first b tag when it + encounters the second 'b'. It will think the author wrote + "<b>Foo<b>Bar", and didn't close the first 'b' tag, because + there's no real-world reason to bold something that's already + bold. When it encounters '</b></b>' it will close two more 'b' + tags, for a grand total of three tags closed instead of two. This + can throw off the rest of your document structure. The same is + true of a number of other tags, listed below. + + It's much more common for someone to forget to close (eg.) a 'b' + tag than to actually use nested 'b' tags, and the BeautifulSoup + class handles the common case. This class handles the + not-co-common case: where you can't believe someone wrote what + they did, but it's valid HTML and BeautifulSoup screwed up by + assuming it wouldn't be. + + If this doesn't do what you need, try subclassing this class or + BeautifulSoup, and providing your own list of NESTABLE_TAGS.""" + + I_CANT_BELIEVE_THEYRE_NESTABLE_INLINE_TAGS = \ + ['em', 'big', 'i', 'small', 'tt', 'abbr', 'acronym', 'strong', + 'cite', 'code', 'dfn', 'kbd', 'samp', 'strong', 'var', 'b', + 'big'] + + I_CANT_BELIEVE_THEYRE_NESTABLE_BLOCK_TAGS = ['noscript'] + + NESTABLE_TAGS = buildTagMap([], BeautifulSoup.NESTABLE_TAGS, + I_CANT_BELIEVE_THEYRE_NESTABLE_BLOCK_TAGS, + I_CANT_BELIEVE_THEYRE_NESTABLE_INLINE_TAGS) + +class BeautifulSOAP(BeautifulStoneSoup): + """This class will push a tag with only a single string child into + the tag's parent as an attribute. The attribute's name is the tag + name, and the value is the string child. An example should give + the flavor of the change: + + <foo><bar>baz</bar></foo> + => + <foo bar="baz"><bar>baz</bar></foo> + + You can then access fooTag['bar'] instead of fooTag.barTag.string. + + This is, of course, useful for scraping structures that tend to + use subelements instead of attributes, such as SOAP messages. Note + that it modifies its input, so don't print the modified version + out. + + I'm not sure how many people really want to use this class; let me + know if you do. Mainly I like the name.""" + + def popTag(self): + if len(self.tagStack) > 1: + tag = self.tagStack[-1] + parent = self.tagStack[-2] + parent._getAttrMap() + if (isinstance(tag, Tag) and len(tag.contents) == 1 and + isinstance(tag.contents[0], NavigableText) and + not parent.attrMap.has_key(tag.name)): + parent[tag.name] = tag.contents[0] + BeautifulStoneSoup.popTag(self) + +#Enterprise class names! It has come to our attention that some people +#think the names of the Beautiful Soup parser classes are too silly +#and "unprofessional" for use in enterprise screen-scraping. We feel +#your pain! For such-minded folk, the Beautiful Soup Consortium And +#All-Night Kosher Bakery recommends renaming this file to +#"RobustParser.py" (or, in cases of extreme enterprisitude, +#"RobustParserBeanInterface.class") and using the following +#enterprise-friendly class aliases: +class RobustXMLParser(BeautifulStoneSoup): + pass +class RobustHTMLParser(BeautifulSoup): + pass +class RobustWackAssHTMLParser(ICantBelieveItsBeautifulSoup): + pass +class SimplifyingSOAPParser(BeautifulSOAP): + pass + +### + + +#By default, act as an HTML pretty-printer. +if __name__ == '__main__': + import sys + soup = BeautifulStoneSoup(sys.stdin.read()) + print soup.prettify() diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_clientcookie.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_clientcookie.py new file mode 100644 index 0000000..caeb82b --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_clientcookie.py @@ -0,0 +1,1707 @@ +"""HTTP cookie handling for web clients. + +This module originally developed from my port of Gisle Aas' Perl module +HTTP::Cookies, from the libwww-perl library. + +Docstrings, comments and debug strings in this code refer to the +attributes of the HTTP cookie system as cookie-attributes, to distinguish +them clearly from Python attributes. + + CookieJar____ + / \ \ + FileCookieJar \ \ + / | \ \ \ + MozillaCookieJar | LWPCookieJar \ \ + | | \ + | ---MSIEBase | \ + | / | | \ + | / MSIEDBCookieJar BSDDBCookieJar + |/ + MSIECookieJar + +Comments to John J Lee <jjl@pobox.com>. + + +Copyright 2002-2006 John J Lee <jjl@pobox.com> +Copyright 1997-1999 Gisle Aas (original libwww-perl code) +Copyright 2002-2003 Johnny Lee (original MSIE Perl code) + +This code is free software; you can redistribute it and/or modify it +under the terms of the BSD or ZPL 2.1 licenses (see the file +COPYING.txt included with the distribution). + +""" + +import sys, re, copy, time, urllib, types, logging +try: + import threading + _threading = threading; del threading +except ImportError: + import dummy_threading + _threading = dummy_threading; del dummy_threading + +MISSING_FILENAME_TEXT = ("a filename was not supplied (nor was the CookieJar " + "instance initialised with one)") +DEFAULT_HTTP_PORT = "80" + +from _headersutil import split_header_words, parse_ns_headers +from _util import isstringlike +import _rfc3986 + +debug = logging.getLogger("mechanize.cookies").debug + + +def reraise_unmasked_exceptions(unmasked=()): + # There are a few catch-all except: statements in this module, for + # catching input that's bad in unexpected ways. + # This function re-raises some exceptions we don't want to trap. + import mechanize, warnings + if not mechanize.USE_BARE_EXCEPT: + raise + unmasked = unmasked + (KeyboardInterrupt, SystemExit, MemoryError) + etype = sys.exc_info()[0] + if issubclass(etype, unmasked): + raise + # swallowed an exception + import traceback, StringIO + f = StringIO.StringIO() + traceback.print_exc(None, f) + msg = f.getvalue() + warnings.warn("mechanize bug!\n%s" % msg, stacklevel=2) + + +IPV4_RE = re.compile(r"\.\d+$") +def is_HDN(text): + """Return True if text is a host domain name.""" + # XXX + # This may well be wrong. Which RFC is HDN defined in, if any (for + # the purposes of RFC 2965)? + # For the current implementation, what about IPv6? Remember to look + # at other uses of IPV4_RE also, if change this. + return not (IPV4_RE.search(text) or + text == "" or + text[0] == "." or text[-1] == ".") + +def domain_match(A, B): + """Return True if domain A domain-matches domain B, according to RFC 2965. + + A and B may be host domain names or IP addresses. + + RFC 2965, section 1: + + Host names can be specified either as an IP address or a HDN string. + Sometimes we compare one host name with another. (Such comparisons SHALL + be case-insensitive.) Host A's name domain-matches host B's if + + * their host name strings string-compare equal; or + + * A is a HDN string and has the form NB, where N is a non-empty + name string, B has the form .B', and B' is a HDN string. (So, + x.y.com domain-matches .Y.com but not Y.com.) + + Note that domain-match is not a commutative operation: a.b.c.com + domain-matches .c.com, but not the reverse. + + """ + # Note that, if A or B are IP addresses, the only relevant part of the + # definition of the domain-match algorithm is the direct string-compare. + A = A.lower() + B = B.lower() + if A == B: + return True + if not is_HDN(A): + return False + i = A.rfind(B) + has_form_nb = not (i == -1 or i == 0) + return ( + has_form_nb and + B.startswith(".") and + is_HDN(B[1:]) + ) + +def liberal_is_HDN(text): + """Return True if text is a sort-of-like a host domain name. + + For accepting/blocking domains. + + """ + return not IPV4_RE.search(text) + +def user_domain_match(A, B): + """For blocking/accepting domains. + + A and B may be host domain names or IP addresses. + + """ + A = A.lower() + B = B.lower() + if not (liberal_is_HDN(A) and liberal_is_HDN(B)): + if A == B: + # equal IP addresses + return True + return False + initial_dot = B.startswith(".") + if initial_dot and A.endswith(B): + return True + if not initial_dot and A == B: + return True + return False + +cut_port_re = re.compile(r":\d+$") +def request_host(request): + """Return request-host, as defined by RFC 2965. + + Variation from RFC: returned value is lowercased, for convenient + comparison. + + """ + url = request.get_full_url() + host = _rfc3986.urlsplit(url)[1] + if host is None: + host = request.get_header("Host", "") + # remove port, if present + return cut_port_re.sub("", host, 1) + +def request_host_lc(request): + return request_host(request).lower() + +def eff_request_host(request): + """Return a tuple (request-host, effective request-host name).""" + erhn = req_host = request_host(request) + if req_host.find(".") == -1 and not IPV4_RE.search(req_host): + erhn = req_host + ".local" + return req_host, erhn + +def eff_request_host_lc(request): + req_host, erhn = eff_request_host(request) + return req_host.lower(), erhn.lower() + +def effective_request_host(request): + """Return the effective request-host, as defined by RFC 2965.""" + return eff_request_host(request)[1] + +def request_path(request): + """request-URI, as defined by RFC 2965.""" + url = request.get_full_url() + path, query, frag = _rfc3986.urlsplit(url)[2:] + path = escape_path(path) + req_path = _rfc3986.urlunsplit((None, None, path, query, frag)) + if not req_path.startswith("/"): + req_path = "/"+req_path + return req_path + +def request_port(request): + host = request.get_host() + i = host.find(':') + if i >= 0: + port = host[i+1:] + try: + int(port) + except ValueError: + debug("nonnumeric port: '%s'", port) + return None + else: + port = DEFAULT_HTTP_PORT + return port + +def request_is_unverifiable(request): + try: + return request.is_unverifiable() + except AttributeError: + if hasattr(request, "unverifiable"): + return request.unverifiable + else: + raise + +# Characters in addition to A-Z, a-z, 0-9, '_', '.', and '-' that don't +# need to be escaped to form a valid HTTP URL (RFCs 2396 and 1738). +HTTP_PATH_SAFE = "%/;:@&=+$,!~*'()" +ESCAPED_CHAR_RE = re.compile(r"%([0-9a-fA-F][0-9a-fA-F])") +def uppercase_escaped_char(match): + return "%%%s" % match.group(1).upper() +def escape_path(path): + """Escape any invalid characters in HTTP URL, and uppercase all escapes.""" + # There's no knowing what character encoding was used to create URLs + # containing %-escapes, but since we have to pick one to escape invalid + # path characters, we pick UTF-8, as recommended in the HTML 4.0 + # specification: + # http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.2.1 + # And here, kind of: draft-fielding-uri-rfc2396bis-03 + # (And in draft IRI specification: draft-duerst-iri-05) + # (And here, for new URI schemes: RFC 2718) + if isinstance(path, types.UnicodeType): + path = path.encode("utf-8") + path = urllib.quote(path, HTTP_PATH_SAFE) + path = ESCAPED_CHAR_RE.sub(uppercase_escaped_char, path) + return path + +def reach(h): + """Return reach of host h, as defined by RFC 2965, section 1. + + The reach R of a host name H is defined as follows: + + * If + + - H is the host domain name of a host; and, + + - H has the form A.B; and + + - A has no embedded (that is, interior) dots; and + + - B has at least one embedded dot, or B is the string "local". + then the reach of H is .B. + + * Otherwise, the reach of H is H. + + >>> reach("www.acme.com") + '.acme.com' + >>> reach("acme.com") + 'acme.com' + >>> reach("acme.local") + '.local' + + """ + i = h.find(".") + if i >= 0: + #a = h[:i] # this line is only here to show what a is + b = h[i+1:] + i = b.find(".") + if is_HDN(h) and (i >= 0 or b == "local"): + return "."+b + return h + +def is_third_party(request): + """ + + RFC 2965, section 3.3.6: + + An unverifiable transaction is to a third-party host if its request- + host U does not domain-match the reach R of the request-host O in the + origin transaction. + + """ + req_host = request_host_lc(request) + # the origin request's request-host was stuffed into request by + # _urllib2_support.AbstractHTTPHandler + return not domain_match(req_host, reach(request.origin_req_host)) + + +class Cookie: + """HTTP Cookie. + + This class represents both Netscape and RFC 2965 cookies. + + This is deliberately a very simple class. It just holds attributes. It's + possible to construct Cookie instances that don't comply with the cookie + standards. CookieJar.make_cookies is the factory function for Cookie + objects -- it deals with cookie parsing, supplying defaults, and + normalising to the representation used in this class. CookiePolicy is + responsible for checking them to see whether they should be accepted from + and returned to the server. + + version: integer; + name: string; + value: string (may be None); + port: string; None indicates no attribute was supplied (eg. "Port", rather + than eg. "Port=80"); otherwise, a port string (eg. "80") or a port list + string (eg. "80,8080") + port_specified: boolean; true if a value was supplied with the Port + cookie-attribute + domain: string; + domain_specified: boolean; true if Domain was explicitly set + domain_initial_dot: boolean; true if Domain as set in HTTP header by server + started with a dot (yes, this really is necessary!) + path: string; + path_specified: boolean; true if Path was explicitly set + secure: boolean; true if should only be returned over secure connection + expires: integer; seconds since epoch (RFC 2965 cookies should calculate + this value from the Max-Age attribute) + discard: boolean, true if this is a session cookie; (if no expires value, + this should be true) + comment: string; + comment_url: string; + rfc2109: boolean; true if cookie arrived in a Set-Cookie: (not + Set-Cookie2:) header, but had a version cookie-attribute of 1 + rest: mapping of other cookie-attributes + + Note that the port may be present in the headers, but unspecified ("Port" + rather than"Port=80", for example); if this is the case, port is None. + + """ + + def __init__(self, version, name, value, + port, port_specified, + domain, domain_specified, domain_initial_dot, + path, path_specified, + secure, + expires, + discard, + comment, + comment_url, + rest, + rfc2109=False, + ): + + if version is not None: version = int(version) + if expires is not None: expires = int(expires) + if port is None and port_specified is True: + raise ValueError("if port is None, port_specified must be false") + + self.version = version + self.name = name + self.value = value + self.port = port + self.port_specified = port_specified + # normalise case, as per RFC 2965 section 3.3.3 + self.domain = domain.lower() + self.domain_specified = domain_specified + # Sigh. We need to know whether the domain given in the + # cookie-attribute had an initial dot, in order to follow RFC 2965 + # (as clarified in draft errata). Needed for the returned $Domain + # value. + self.domain_initial_dot = domain_initial_dot + self.path = path + self.path_specified = path_specified + self.secure = secure + self.expires = expires + self.discard = discard + self.comment = comment + self.comment_url = comment_url + self.rfc2109 = rfc2109 + + self._rest = copy.copy(rest) + + def has_nonstandard_attr(self, name): + return self._rest.has_key(name) + def get_nonstandard_attr(self, name, default=None): + return self._rest.get(name, default) + def set_nonstandard_attr(self, name, value): + self._rest[name] = value + def nonstandard_attr_keys(self): + return self._rest.keys() + + def is_expired(self, now=None): + if now is None: now = time.time() + return (self.expires is not None) and (self.expires <= now) + + def __str__(self): + if self.port is None: p = "" + else: p = ":"+self.port + limit = self.domain + p + self.path + if self.value is not None: + namevalue = "%s=%s" % (self.name, self.value) + else: + namevalue = self.name + return "<Cookie %s for %s>" % (namevalue, limit) + + def __repr__(self): + args = [] + for name in ["version", "name", "value", + "port", "port_specified", + "domain", "domain_specified", "domain_initial_dot", + "path", "path_specified", + "secure", "expires", "discard", "comment", "comment_url", + ]: + attr = getattr(self, name) + args.append("%s=%s" % (name, repr(attr))) + args.append("rest=%s" % repr(self._rest)) + args.append("rfc2109=%s" % repr(self.rfc2109)) + return "Cookie(%s)" % ", ".join(args) + + +class CookiePolicy: + """Defines which cookies get accepted from and returned to server. + + May also modify cookies. + + The subclass DefaultCookiePolicy defines the standard rules for Netscape + and RFC 2965 cookies -- override that if you want a customised policy. + + As well as implementing set_ok and return_ok, implementations of this + interface must also supply the following attributes, indicating which + protocols should be used, and how. These can be read and set at any time, + though whether that makes complete sense from the protocol point of view is + doubtful. + + Public attributes: + + netscape: implement netscape protocol + rfc2965: implement RFC 2965 protocol + rfc2109_as_netscape: + WARNING: This argument will change or go away if is not accepted into + the Python standard library in this form! + If true, treat RFC 2109 cookies as though they were Netscape cookies. The + default is for this attribute to be None, which means treat 2109 cookies + as RFC 2965 cookies unless RFC 2965 handling is switched off (which it is, + by default), and as Netscape cookies otherwise. + hide_cookie2: don't add Cookie2 header to requests (the presence of + this header indicates to the server that we understand RFC 2965 + cookies) + + """ + def set_ok(self, cookie, request): + """Return true if (and only if) cookie should be accepted from server. + + Currently, pre-expired cookies never get this far -- the CookieJar + class deletes such cookies itself. + + cookie: mechanize.Cookie object + request: object implementing the interface defined by + CookieJar.extract_cookies.__doc__ + + """ + raise NotImplementedError() + + def return_ok(self, cookie, request): + """Return true if (and only if) cookie should be returned to server. + + cookie: mechanize.Cookie object + request: object implementing the interface defined by + CookieJar.add_cookie_header.__doc__ + + """ + raise NotImplementedError() + + def domain_return_ok(self, domain, request): + """Return false if cookies should not be returned, given cookie domain. + + This is here as an optimization, to remove the need for checking every + cookie with a particular domain (which may involve reading many files). + The default implementations of domain_return_ok and path_return_ok + (return True) leave all the work to return_ok. + + If domain_return_ok returns true for the cookie domain, path_return_ok + is called for the cookie path. Otherwise, path_return_ok and return_ok + are never called for that cookie domain. If path_return_ok returns + true, return_ok is called with the Cookie object itself for a full + check. Otherwise, return_ok is never called for that cookie path. + + Note that domain_return_ok is called for every *cookie* domain, not + just for the *request* domain. For example, the function might be + called with both ".acme.com" and "www.acme.com" if the request domain + is "www.acme.com". The same goes for path_return_ok. + + For argument documentation, see the docstring for return_ok. + + """ + return True + + def path_return_ok(self, path, request): + """Return false if cookies should not be returned, given cookie path. + + See the docstring for domain_return_ok. + + """ + return True + + +class DefaultCookiePolicy(CookiePolicy): + """Implements the standard rules for accepting and returning cookies. + + Both RFC 2965 and Netscape cookies are covered. RFC 2965 handling is + switched off by default. + + The easiest way to provide your own policy is to override this class and + call its methods in your overriden implementations before adding your own + additional checks. + + import mechanize + class MyCookiePolicy(mechanize.DefaultCookiePolicy): + def set_ok(self, cookie, request): + if not mechanize.DefaultCookiePolicy.set_ok( + self, cookie, request): + return False + if i_dont_want_to_store_this_cookie(): + return False + return True + + In addition to the features required to implement the CookiePolicy + interface, this class allows you to block and allow domains from setting + and receiving cookies. There are also some strictness switches that allow + you to tighten up the rather loose Netscape protocol rules a little bit (at + the cost of blocking some benign cookies). + + A domain blacklist and whitelist is provided (both off by default). Only + domains not in the blacklist and present in the whitelist (if the whitelist + is active) participate in cookie setting and returning. Use the + blocked_domains constructor argument, and blocked_domains and + set_blocked_domains methods (and the corresponding argument and methods for + allowed_domains). If you set a whitelist, you can turn it off again by + setting it to None. + + Domains in block or allow lists that do not start with a dot must + string-compare equal. For example, "acme.com" matches a blacklist entry of + "acme.com", but "www.acme.com" does not. Domains that do start with a dot + are matched by more specific domains too. For example, both "www.acme.com" + and "www.munitions.acme.com" match ".acme.com" (but "acme.com" itself does + not). IP addresses are an exception, and must match exactly. For example, + if blocked_domains contains "192.168.1.2" and ".168.1.2" 192.168.1.2 is + blocked, but 193.168.1.2 is not. + + Additional Public Attributes: + + General strictness switches + + strict_domain: don't allow sites to set two-component domains with + country-code top-level domains like .co.uk, .gov.uk, .co.nz. etc. + This is far from perfect and isn't guaranteed to work! + + RFC 2965 protocol strictness switches + + strict_rfc2965_unverifiable: follow RFC 2965 rules on unverifiable + transactions (usually, an unverifiable transaction is one resulting from + a redirect or an image hosted on another site); if this is false, cookies + are NEVER blocked on the basis of verifiability + + Netscape protocol strictness switches + + strict_ns_unverifiable: apply RFC 2965 rules on unverifiable transactions + even to Netscape cookies + strict_ns_domain: flags indicating how strict to be with domain-matching + rules for Netscape cookies: + DomainStrictNoDots: when setting cookies, host prefix must not contain a + dot (eg. www.foo.bar.com can't set a cookie for .bar.com, because + www.foo contains a dot) + DomainStrictNonDomain: cookies that did not explicitly specify a Domain + cookie-attribute can only be returned to a domain that string-compares + equal to the domain that set the cookie (eg. rockets.acme.com won't + be returned cookies from acme.com that had no Domain cookie-attribute) + DomainRFC2965Match: when setting cookies, require a full RFC 2965 + domain-match + DomainLiberal and DomainStrict are the most useful combinations of the + above flags, for convenience + strict_ns_set_initial_dollar: ignore cookies in Set-Cookie: headers that + have names starting with '$' + strict_ns_set_path: don't allow setting cookies whose path doesn't + path-match request URI + + """ + + DomainStrictNoDots = 1 + DomainStrictNonDomain = 2 + DomainRFC2965Match = 4 + + DomainLiberal = 0 + DomainStrict = DomainStrictNoDots|DomainStrictNonDomain + + def __init__(self, + blocked_domains=None, allowed_domains=None, + netscape=True, rfc2965=False, + # WARNING: this argument will change or go away if is not + # accepted into the Python standard library in this form! + # default, ie. treat 2109 as netscape iff not rfc2965 + rfc2109_as_netscape=None, + hide_cookie2=False, + strict_domain=False, + strict_rfc2965_unverifiable=True, + strict_ns_unverifiable=False, + strict_ns_domain=DomainLiberal, + strict_ns_set_initial_dollar=False, + strict_ns_set_path=False, + ): + """ + Constructor arguments should be used as keyword arguments only. + + blocked_domains: sequence of domain names that we never accept cookies + from, nor return cookies to + allowed_domains: if not None, this is a sequence of the only domains + for which we accept and return cookies + + For other arguments, see CookiePolicy.__doc__ and + DefaultCookiePolicy.__doc__.. + + """ + self.netscape = netscape + self.rfc2965 = rfc2965 + self.rfc2109_as_netscape = rfc2109_as_netscape + self.hide_cookie2 = hide_cookie2 + self.strict_domain = strict_domain + self.strict_rfc2965_unverifiable = strict_rfc2965_unverifiable + self.strict_ns_unverifiable = strict_ns_unverifiable + self.strict_ns_domain = strict_ns_domain + self.strict_ns_set_initial_dollar = strict_ns_set_initial_dollar + self.strict_ns_set_path = strict_ns_set_path + + if blocked_domains is not None: + self._blocked_domains = tuple(blocked_domains) + else: + self._blocked_domains = () + + if allowed_domains is not None: + allowed_domains = tuple(allowed_domains) + self._allowed_domains = allowed_domains + + def blocked_domains(self): + """Return the sequence of blocked domains (as a tuple).""" + return self._blocked_domains + def set_blocked_domains(self, blocked_domains): + """Set the sequence of blocked domains.""" + self._blocked_domains = tuple(blocked_domains) + + def is_blocked(self, domain): + for blocked_domain in self._blocked_domains: + if user_domain_match(domain, blocked_domain): + return True + return False + + def allowed_domains(self): + """Return None, or the sequence of allowed domains (as a tuple).""" + return self._allowed_domains + def set_allowed_domains(self, allowed_domains): + """Set the sequence of allowed domains, or None.""" + if allowed_domains is not None: + allowed_domains = tuple(allowed_domains) + self._allowed_domains = allowed_domains + + def is_not_allowed(self, domain): + if self._allowed_domains is None: + return False + for allowed_domain in self._allowed_domains: + if user_domain_match(domain, allowed_domain): + return False + return True + + def set_ok(self, cookie, request): + """ + If you override set_ok, be sure to call this method. If it returns + false, so should your subclass (assuming your subclass wants to be more + strict about which cookies to accept). + + """ + debug(" - checking cookie %s", cookie) + + assert cookie.name is not None + + for n in "version", "verifiability", "name", "path", "domain", "port": + fn_name = "set_ok_"+n + fn = getattr(self, fn_name) + if not fn(cookie, request): + return False + + return True + + def set_ok_version(self, cookie, request): + if cookie.version is None: + # Version is always set to 0 by parse_ns_headers if it's a Netscape + # cookie, so this must be an invalid RFC 2965 cookie. + debug(" Set-Cookie2 without version attribute (%s)", cookie) + return False + if cookie.version > 0 and not self.rfc2965: + debug(" RFC 2965 cookies are switched off") + return False + elif cookie.version == 0 and not self.netscape: + debug(" Netscape cookies are switched off") + return False + return True + + def set_ok_verifiability(self, cookie, request): + if request_is_unverifiable(request) and is_third_party(request): + if cookie.version > 0 and self.strict_rfc2965_unverifiable: + debug(" third-party RFC 2965 cookie during " + "unverifiable transaction") + return False + elif cookie.version == 0 and self.strict_ns_unverifiable: + debug(" third-party Netscape cookie during " + "unverifiable transaction") + return False + return True + + def set_ok_name(self, cookie, request): + # Try and stop servers setting V0 cookies designed to hack other + # servers that know both V0 and V1 protocols. + if (cookie.version == 0 and self.strict_ns_set_initial_dollar and + cookie.name.startswith("$")): + debug(" illegal name (starts with '$'): '%s'", cookie.name) + return False + return True + + def set_ok_path(self, cookie, request): + if cookie.path_specified: + req_path = request_path(request) + if ((cookie.version > 0 or + (cookie.version == 0 and self.strict_ns_set_path)) and + not req_path.startswith(cookie.path)): + debug(" path attribute %s is not a prefix of request " + "path %s", cookie.path, req_path) + return False + return True + + def set_ok_countrycode_domain(self, cookie, request): + """Return False if explicit cookie domain is not acceptable. + + Called by set_ok_domain, for convenience of overriding by + subclasses. + + """ + if cookie.domain_specified and self.strict_domain: + domain = cookie.domain + # since domain was specified, we know that: + assert domain.startswith(".") + if domain.count(".") == 2: + # domain like .foo.bar + i = domain.rfind(".") + tld = domain[i+1:] + sld = domain[1:i] + if (sld.lower() in [ + "co", "ac", + "com", "edu", "org", "net", "gov", "mil", "int", + "aero", "biz", "cat", "coop", "info", "jobs", "mobi", + "museum", "name", "pro", "travel", + ] and + len(tld) == 2): + # domain like .co.uk + return False + return True + + def set_ok_domain(self, cookie, request): + if self.is_blocked(cookie.domain): + debug(" domain %s is in user block-list", cookie.domain) + return False + if self.is_not_allowed(cookie.domain): + debug(" domain %s is not in user allow-list", cookie.domain) + return False + if not self.set_ok_countrycode_domain(cookie, request): + debug(" country-code second level domain %s", cookie.domain) + return False + if cookie.domain_specified: + req_host, erhn = eff_request_host_lc(request) + domain = cookie.domain + if domain.startswith("."): + undotted_domain = domain[1:] + else: + undotted_domain = domain + embedded_dots = (undotted_domain.find(".") >= 0) + if not embedded_dots and domain != ".local": + debug(" non-local domain %s contains no embedded dot", + domain) + return False + if cookie.version == 0: + if (not erhn.endswith(domain) and + (not erhn.startswith(".") and + not ("."+erhn).endswith(domain))): + debug(" effective request-host %s (even with added " + "initial dot) does not end end with %s", + erhn, domain) + return False + if (cookie.version > 0 or + (self.strict_ns_domain & self.DomainRFC2965Match)): + if not domain_match(erhn, domain): + debug(" effective request-host %s does not domain-match " + "%s", erhn, domain) + return False + if (cookie.version > 0 or + (self.strict_ns_domain & self.DomainStrictNoDots)): + host_prefix = req_host[:-len(domain)] + if (host_prefix.find(".") >= 0 and + not IPV4_RE.search(req_host)): + debug(" host prefix %s for domain %s contains a dot", + host_prefix, domain) + return False + return True + + def set_ok_port(self, cookie, request): + if cookie.port_specified: + req_port = request_port(request) + if req_port is None: + req_port = "80" + else: + req_port = str(req_port) + for p in cookie.port.split(","): + try: + int(p) + except ValueError: + debug(" bad port %s (not numeric)", p) + return False + if p == req_port: + break + else: + debug(" request port (%s) not found in %s", + req_port, cookie.port) + return False + return True + + def return_ok(self, cookie, request): + """ + If you override return_ok, be sure to call this method. If it returns + false, so should your subclass (assuming your subclass wants to be more + strict about which cookies to return). + + """ + # Path has already been checked by path_return_ok, and domain blocking + # done by domain_return_ok. + debug(" - checking cookie %s", cookie) + + for n in ("version", "verifiability", "secure", "expires", "port", + "domain"): + fn_name = "return_ok_"+n + fn = getattr(self, fn_name) + if not fn(cookie, request): + return False + return True + + def return_ok_version(self, cookie, request): + if cookie.version > 0 and not self.rfc2965: + debug(" RFC 2965 cookies are switched off") + return False + elif cookie.version == 0 and not self.netscape: + debug(" Netscape cookies are switched off") + return False + return True + + def return_ok_verifiability(self, cookie, request): + if request_is_unverifiable(request) and is_third_party(request): + if cookie.version > 0 and self.strict_rfc2965_unverifiable: + debug(" third-party RFC 2965 cookie during unverifiable " + "transaction") + return False + elif cookie.version == 0 and self.strict_ns_unverifiable: + debug(" third-party Netscape cookie during unverifiable " + "transaction") + return False + return True + + def return_ok_secure(self, cookie, request): + if cookie.secure and request.get_type() != "https": + debug(" secure cookie with non-secure request") + return False + return True + + def return_ok_expires(self, cookie, request): + if cookie.is_expired(self._now): + debug(" cookie expired") + return False + return True + + def return_ok_port(self, cookie, request): + if cookie.port: + req_port = request_port(request) + if req_port is None: + req_port = "80" + for p in cookie.port.split(","): + if p == req_port: + break + else: + debug(" request port %s does not match cookie port %s", + req_port, cookie.port) + return False + return True + + def return_ok_domain(self, cookie, request): + req_host, erhn = eff_request_host_lc(request) + domain = cookie.domain + + # strict check of non-domain cookies: Mozilla does this, MSIE5 doesn't + if (cookie.version == 0 and + (self.strict_ns_domain & self.DomainStrictNonDomain) and + not cookie.domain_specified and domain != erhn): + debug(" cookie with unspecified domain does not string-compare " + "equal to request domain") + return False + + if cookie.version > 0 and not domain_match(erhn, domain): + debug(" effective request-host name %s does not domain-match " + "RFC 2965 cookie domain %s", erhn, domain) + return False + if cookie.version == 0 and not ("."+erhn).endswith(domain): + debug(" request-host %s does not match Netscape cookie domain " + "%s", req_host, domain) + return False + return True + + def domain_return_ok(self, domain, request): + # Liberal check of domain. This is here as an optimization to avoid + # having to load lots of MSIE cookie files unless necessary. + + # Munge req_host and erhn to always start with a dot, so as to err on + # the side of letting cookies through. + dotted_req_host, dotted_erhn = eff_request_host_lc(request) + if not dotted_req_host.startswith("."): + dotted_req_host = "."+dotted_req_host + if not dotted_erhn.startswith("."): + dotted_erhn = "."+dotted_erhn + if not (dotted_req_host.endswith(domain) or + dotted_erhn.endswith(domain)): + #debug(" request domain %s does not match cookie domain %s", + # req_host, domain) + return False + + if self.is_blocked(domain): + debug(" domain %s is in user block-list", domain) + return False + if self.is_not_allowed(domain): + debug(" domain %s is not in user allow-list", domain) + return False + + return True + + def path_return_ok(self, path, request): + debug("- checking cookie path=%s", path) + req_path = request_path(request) + if not req_path.startswith(path): + debug(" %s does not path-match %s", req_path, path) + return False + return True + + +def vals_sorted_by_key(adict): + keys = adict.keys() + keys.sort() + return map(adict.get, keys) + +class MappingIterator: + """Iterates over nested mapping, depth-first, in sorted order by key.""" + def __init__(self, mapping): + self._s = [(vals_sorted_by_key(mapping), 0, None)] # LIFO stack + + def __iter__(self): return self + + def next(self): + # this is hairy because of lack of generators + while 1: + try: + vals, i, prev_item = self._s.pop() + except IndexError: + raise StopIteration() + if i < len(vals): + item = vals[i] + i = i + 1 + self._s.append((vals, i, prev_item)) + try: + item.items + except AttributeError: + # non-mapping + break + else: + # mapping + self._s.append((vals_sorted_by_key(item), 0, item)) + continue + return item + + +# Used as second parameter to dict.get method, to distinguish absent +# dict key from one with a None value. +class Absent: pass + +class CookieJar: + """Collection of HTTP cookies. + + You may not need to know about this class: try mechanize.urlopen(). + + The major methods are extract_cookies and add_cookie_header; these are all + you are likely to need. + + CookieJar supports the iterator protocol: + + for cookie in cookiejar: + # do something with cookie + + Methods: + + add_cookie_header(request) + extract_cookies(response, request) + get_policy() + set_policy(policy) + cookies_for_request(request) + make_cookies(response, request) + set_cookie_if_ok(cookie, request) + set_cookie(cookie) + clear_session_cookies() + clear_expired_cookies() + clear(domain=None, path=None, name=None) + + Public attributes + + policy: CookiePolicy object + + """ + + non_word_re = re.compile(r"\W") + quote_re = re.compile(r"([\"\\])") + strict_domain_re = re.compile(r"\.?[^.]*") + domain_re = re.compile(r"[^.]*") + dots_re = re.compile(r"^\.+") + + def __init__(self, policy=None): + """ + See CookieJar.__doc__ for argument documentation. + + """ + if policy is None: + policy = DefaultCookiePolicy() + self._policy = policy + + self._cookies = {} + + # for __getitem__ iteration in pre-2.2 Pythons + self._prev_getitem_index = 0 + + def get_policy(self): + return self._policy + + def set_policy(self, policy): + self._policy = policy + + def _cookies_for_domain(self, domain, request): + cookies = [] + if not self._policy.domain_return_ok(domain, request): + return [] + debug("Checking %s for cookies to return", domain) + cookies_by_path = self._cookies[domain] + for path in cookies_by_path.keys(): + if not self._policy.path_return_ok(path, request): + continue + cookies_by_name = cookies_by_path[path] + for cookie in cookies_by_name.values(): + if not self._policy.return_ok(cookie, request): + debug(" not returning cookie") + continue + debug(" it's a match") + cookies.append(cookie) + return cookies + + def cookies_for_request(self, request): + """Return a list of cookies to be returned to server. + + The returned list of cookie instances is sorted in the order they + should appear in the Cookie: header for return to the server. + + See add_cookie_header.__doc__ for the interface required of the + request argument. + + New in version 0.1.10 + + """ + self._policy._now = self._now = int(time.time()) + cookies = self._cookies_for_request(request) + # add cookies in order of most specific (i.e. longest) path first + def decreasing_size(a, b): return cmp(len(b.path), len(a.path)) + cookies.sort(decreasing_size) + return cookies + + def _cookies_for_request(self, request): + """Return a list of cookies to be returned to server.""" + # this method still exists (alongside cookies_for_request) because it + # is part of an implied protected interface for subclasses of cookiejar + # XXX document that implied interface, or provide another way of + # implementing cookiejars than subclassing + cookies = [] + for domain in self._cookies.keys(): + cookies.extend(self._cookies_for_domain(domain, request)) + return cookies + + def _cookie_attrs(self, cookies): + """Return a list of cookie-attributes to be returned to server. + + The $Version attribute is also added when appropriate (currently only + once per request). + + >>> jar = CookieJar() + >>> ns_cookie = Cookie(0, "foo", '"bar"', None, False, + ... "example.com", False, False, + ... "/", False, False, None, True, + ... None, None, {}) + >>> jar._cookie_attrs([ns_cookie]) + ['foo="bar"'] + >>> rfc2965_cookie = Cookie(1, "foo", "bar", None, False, + ... ".example.com", True, False, + ... "/", False, False, None, True, + ... None, None, {}) + >>> jar._cookie_attrs([rfc2965_cookie]) + ['$Version=1', 'foo=bar', '$Domain="example.com"'] + + """ + version_set = False + + attrs = [] + for cookie in cookies: + # set version of Cookie header + # XXX + # What should it be if multiple matching Set-Cookie headers have + # different versions themselves? + # Answer: there is no answer; was supposed to be settled by + # RFC 2965 errata, but that may never appear... + version = cookie.version + if not version_set: + version_set = True + if version > 0: + attrs.append("$Version=%s" % version) + + # quote cookie value if necessary + # (not for Netscape protocol, which already has any quotes + # intact, due to the poorly-specified Netscape Cookie: syntax) + if ((cookie.value is not None) and + self.non_word_re.search(cookie.value) and version > 0): + value = self.quote_re.sub(r"\\\1", cookie.value) + else: + value = cookie.value + + # add cookie-attributes to be returned in Cookie header + if cookie.value is None: + attrs.append(cookie.name) + else: + attrs.append("%s=%s" % (cookie.name, value)) + if version > 0: + if cookie.path_specified: + attrs.append('$Path="%s"' % cookie.path) + if cookie.domain.startswith("."): + domain = cookie.domain + if (not cookie.domain_initial_dot and + domain.startswith(".")): + domain = domain[1:] + attrs.append('$Domain="%s"' % domain) + if cookie.port is not None: + p = "$Port" + if cookie.port_specified: + p = p + ('="%s"' % cookie.port) + attrs.append(p) + + return attrs + + def add_cookie_header(self, request): + """Add correct Cookie: header to request (urllib2.Request object). + + The Cookie2 header is also added unless policy.hide_cookie2 is true. + + The request object (usually a urllib2.Request instance) must support + the methods get_full_url, get_host, is_unverifiable, get_type, + has_header, get_header, header_items and add_unredirected_header, as + documented by urllib2, and the port attribute (the port number). + Actually, RequestUpgradeProcessor will automatically upgrade your + Request object to one with has_header, get_header, header_items and + add_unredirected_header, if it lacks those methods, for compatibility + with pre-2.4 versions of urllib2. + + """ + debug("add_cookie_header") + cookies = self.cookies_for_request(request) + + attrs = self._cookie_attrs(cookies) + if attrs: + if not request.has_header("Cookie"): + request.add_unredirected_header("Cookie", "; ".join(attrs)) + + # if necessary, advertise that we know RFC 2965 + if self._policy.rfc2965 and not self._policy.hide_cookie2: + for cookie in cookies: + if cookie.version != 1 and not request.has_header("Cookie2"): + request.add_unredirected_header("Cookie2", '$Version="1"') + break + + self.clear_expired_cookies() + + def _normalized_cookie_tuples(self, attrs_set): + """Return list of tuples containing normalised cookie information. + + attrs_set is the list of lists of key,value pairs extracted from + the Set-Cookie or Set-Cookie2 headers. + + Tuples are name, value, standard, rest, where name and value are the + cookie name and value, standard is a dictionary containing the standard + cookie-attributes (discard, secure, version, expires or max-age, + domain, path and port) and rest is a dictionary containing the rest of + the cookie-attributes. + + """ + cookie_tuples = [] + + boolean_attrs = "discard", "secure" + value_attrs = ("version", + "expires", "max-age", + "domain", "path", "port", + "comment", "commenturl") + + for cookie_attrs in attrs_set: + name, value = cookie_attrs[0] + + # Build dictionary of standard cookie-attributes (standard) and + # dictionary of other cookie-attributes (rest). + + # Note: expiry time is normalised to seconds since epoch. V0 + # cookies should have the Expires cookie-attribute, and V1 cookies + # should have Max-Age, but since V1 includes RFC 2109 cookies (and + # since V0 cookies may be a mish-mash of Netscape and RFC 2109), we + # accept either (but prefer Max-Age). + max_age_set = False + + bad_cookie = False + + standard = {} + rest = {} + for k, v in cookie_attrs[1:]: + lc = k.lower() + # don't lose case distinction for unknown fields + if lc in value_attrs or lc in boolean_attrs: + k = lc + if k in boolean_attrs and v is None: + # boolean cookie-attribute is present, but has no value + # (like "discard", rather than "port=80") + v = True + if standard.has_key(k): + # only first value is significant + continue + if k == "domain": + if v is None: + debug(" missing value for domain attribute") + bad_cookie = True + break + # RFC 2965 section 3.3.3 + v = v.lower() + if k == "expires": + if max_age_set: + # Prefer max-age to expires (like Mozilla) + continue + if v is None: + debug(" missing or invalid value for expires " + "attribute: treating as session cookie") + continue + if k == "max-age": + max_age_set = True + if v is None: + debug(" missing value for max-age attribute") + bad_cookie = True + break + try: + v = int(v) + except ValueError: + debug(" missing or invalid (non-numeric) value for " + "max-age attribute") + bad_cookie = True + break + # convert RFC 2965 Max-Age to seconds since epoch + # XXX Strictly you're supposed to follow RFC 2616 + # age-calculation rules. Remember that zero Max-Age is a + # is a request to discard (old and new) cookie, though. + k = "expires" + v = self._now + v + if (k in value_attrs) or (k in boolean_attrs): + if (v is None and + k not in ["port", "comment", "commenturl"]): + debug(" missing value for %s attribute" % k) + bad_cookie = True + break + standard[k] = v + else: + rest[k] = v + + if bad_cookie: + continue + + cookie_tuples.append((name, value, standard, rest)) + + return cookie_tuples + + def _cookie_from_cookie_tuple(self, tup, request): + # standard is dict of standard cookie-attributes, rest is dict of the + # rest of them + name, value, standard, rest = tup + + domain = standard.get("domain", Absent) + path = standard.get("path", Absent) + port = standard.get("port", Absent) + expires = standard.get("expires", Absent) + + # set the easy defaults + version = standard.get("version", None) + if version is not None: + try: + version = int(version) + except ValueError: + return None # invalid version, ignore cookie + secure = standard.get("secure", False) + # (discard is also set if expires is Absent) + discard = standard.get("discard", False) + comment = standard.get("comment", None) + comment_url = standard.get("commenturl", None) + + # set default path + if path is not Absent and path != "": + path_specified = True + path = escape_path(path) + else: + path_specified = False + path = request_path(request) + i = path.rfind("/") + if i != -1: + if version == 0: + # Netscape spec parts company from reality here + path = path[:i] + else: + path = path[:i+1] + if len(path) == 0: path = "/" + + # set default domain + domain_specified = domain is not Absent + # but first we have to remember whether it starts with a dot + domain_initial_dot = False + if domain_specified: + domain_initial_dot = bool(domain.startswith(".")) + if domain is Absent: + req_host, erhn = eff_request_host_lc(request) + domain = erhn + elif not domain.startswith("."): + domain = "."+domain + + # set default port + port_specified = False + if port is not Absent: + if port is None: + # Port attr present, but has no value: default to request port. + # Cookie should then only be sent back on that port. + port = request_port(request) + else: + port_specified = True + port = re.sub(r"\s+", "", port) + else: + # No port attr present. Cookie can be sent back on any port. + port = None + + # set default expires and discard + if expires is Absent: + expires = None + discard = True + + return Cookie(version, + name, value, + port, port_specified, + domain, domain_specified, domain_initial_dot, + path, path_specified, + secure, + expires, + discard, + comment, + comment_url, + rest) + + def _cookies_from_attrs_set(self, attrs_set, request): + cookie_tuples = self._normalized_cookie_tuples(attrs_set) + + cookies = [] + for tup in cookie_tuples: + cookie = self._cookie_from_cookie_tuple(tup, request) + if cookie: cookies.append(cookie) + return cookies + + def _process_rfc2109_cookies(self, cookies): + if self._policy.rfc2109_as_netscape is None: + rfc2109_as_netscape = not self._policy.rfc2965 + else: + rfc2109_as_netscape = self._policy.rfc2109_as_netscape + for cookie in cookies: + if cookie.version == 1: + cookie.rfc2109 = True + if rfc2109_as_netscape: + # treat 2109 cookies as Netscape cookies rather than + # as RFC2965 cookies + cookie.version = 0 + + def _make_cookies(self, response, request): + # get cookie-attributes for RFC 2965 and Netscape protocols + headers = response.info() + rfc2965_hdrs = headers.getheaders("Set-Cookie2") + ns_hdrs = headers.getheaders("Set-Cookie") + + rfc2965 = self._policy.rfc2965 + netscape = self._policy.netscape + + if ((not rfc2965_hdrs and not ns_hdrs) or + (not ns_hdrs and not rfc2965) or + (not rfc2965_hdrs and not netscape) or + (not netscape and not rfc2965)): + return [] # no relevant cookie headers: quick exit + + try: + cookies = self._cookies_from_attrs_set( + split_header_words(rfc2965_hdrs), request) + except: + reraise_unmasked_exceptions() + cookies = [] + + if ns_hdrs and netscape: + try: + # RFC 2109 and Netscape cookies + ns_cookies = self._cookies_from_attrs_set( + parse_ns_headers(ns_hdrs), request) + except: + reraise_unmasked_exceptions() + ns_cookies = [] + self._process_rfc2109_cookies(ns_cookies) + + # Look for Netscape cookies (from Set-Cookie headers) that match + # corresponding RFC 2965 cookies (from Set-Cookie2 headers). + # For each match, keep the RFC 2965 cookie and ignore the Netscape + # cookie (RFC 2965 section 9.1). Actually, RFC 2109 cookies are + # bundled in with the Netscape cookies for this purpose, which is + # reasonable behaviour. + if rfc2965: + lookup = {} + for cookie in cookies: + lookup[(cookie.domain, cookie.path, cookie.name)] = None + + def no_matching_rfc2965(ns_cookie, lookup=lookup): + key = ns_cookie.domain, ns_cookie.path, ns_cookie.name + return not lookup.has_key(key) + ns_cookies = filter(no_matching_rfc2965, ns_cookies) + + if ns_cookies: + cookies.extend(ns_cookies) + + return cookies + + def make_cookies(self, response, request): + """Return sequence of Cookie objects extracted from response object. + + See extract_cookies.__doc__ for the interface required of the + response and request arguments. + + """ + self._policy._now = self._now = int(time.time()) + return [cookie for cookie in self._make_cookies(response, request) + if cookie.expires is None or not cookie.expires <= self._now] + + def set_cookie_if_ok(self, cookie, request): + """Set a cookie if policy says it's OK to do so. + + cookie: mechanize.Cookie instance + request: see extract_cookies.__doc__ for the required interface + + """ + self._policy._now = self._now = int(time.time()) + + if self._policy.set_ok(cookie, request): + self.set_cookie(cookie) + + def set_cookie(self, cookie): + """Set a cookie, without checking whether or not it should be set. + + cookie: mechanize.Cookie instance + """ + c = self._cookies + if not c.has_key(cookie.domain): c[cookie.domain] = {} + c2 = c[cookie.domain] + if not c2.has_key(cookie.path): c2[cookie.path] = {} + c3 = c2[cookie.path] + c3[cookie.name] = cookie + + def extract_cookies(self, response, request): + """Extract cookies from response, where allowable given the request. + + Look for allowable Set-Cookie: and Set-Cookie2: headers in the response + object passed as argument. Any of these headers that are found are + used to update the state of the object (subject to the policy.set_ok + method's approval). + + The response object (usually be the result of a call to + mechanize.urlopen, or similar) should support an info method, which + returns a mimetools.Message object (in fact, the 'mimetools.Message + object' may be any object that provides a getheaders method). + + The request object (usually a urllib2.Request instance) must support + the methods get_full_url, get_type, get_host, and is_unverifiable, as + documented by urllib2, and the port attribute (the port number). The + request is used to set default values for cookie-attributes as well as + for checking that the cookie is OK to be set. + + """ + debug("extract_cookies: %s", response.info()) + self._policy._now = self._now = int(time.time()) + + for cookie in self._make_cookies(response, request): + if cookie.expires is not None and cookie.expires <= self._now: + # Expiry date in past is request to delete cookie. This can't be + # in DefaultCookiePolicy, because can't delete cookies there. + try: + self.clear(cookie.domain, cookie.path, cookie.name) + except KeyError: + pass + debug("Expiring cookie, domain='%s', path='%s', name='%s'", + cookie.domain, cookie.path, cookie.name) + elif self._policy.set_ok(cookie, request): + debug(" setting cookie: %s", cookie) + self.set_cookie(cookie) + + def clear(self, domain=None, path=None, name=None): + """Clear some cookies. + + Invoking this method without arguments will clear all cookies. If + given a single argument, only cookies belonging to that domain will be + removed. If given two arguments, cookies belonging to the specified + path within that domain are removed. If given three arguments, then + the cookie with the specified name, path and domain is removed. + + Raises KeyError if no matching cookie exists. + + """ + if name is not None: + if (domain is None) or (path is None): + raise ValueError( + "domain and path must be given to remove a cookie by name") + del self._cookies[domain][path][name] + elif path is not None: + if domain is None: + raise ValueError( + "domain must be given to remove cookies by path") + del self._cookies[domain][path] + elif domain is not None: + del self._cookies[domain] + else: + self._cookies = {} + + def clear_session_cookies(self): + """Discard all session cookies. + + Discards all cookies held by object which had either no Max-Age or + Expires cookie-attribute or an explicit Discard cookie-attribute, or + which otherwise have ended up with a true discard attribute. For + interactive browsers, the end of a session usually corresponds to + closing the browser window. + + Note that the save method won't save session cookies anyway, unless you + ask otherwise by passing a true ignore_discard argument. + + """ + for cookie in self: + if cookie.discard: + self.clear(cookie.domain, cookie.path, cookie.name) + + def clear_expired_cookies(self): + """Discard all expired cookies. + + You probably don't need to call this method: expired cookies are never + sent back to the server (provided you're using DefaultCookiePolicy), + this method is called by CookieJar itself every so often, and the save + method won't save expired cookies anyway (unless you ask otherwise by + passing a true ignore_expires argument). + + """ + now = time.time() + for cookie in self: + if cookie.is_expired(now): + self.clear(cookie.domain, cookie.path, cookie.name) + + def __getitem__(self, i): + if i == 0: + self._getitem_iterator = self.__iter__() + elif self._prev_getitem_index != i-1: raise IndexError( + "CookieJar.__getitem__ only supports sequential iteration") + self._prev_getitem_index = i + try: + return self._getitem_iterator.next() + except StopIteration: + raise IndexError() + + def __iter__(self): + return MappingIterator(self._cookies) + + def __len__(self): + """Return number of contained cookies.""" + i = 0 + for cookie in self: i = i + 1 + return i + + def __repr__(self): + r = [] + for cookie in self: r.append(repr(cookie)) + return "<%s[%s]>" % (self.__class__, ", ".join(r)) + + def __str__(self): + r = [] + for cookie in self: r.append(str(cookie)) + return "<%s[%s]>" % (self.__class__, ", ".join(r)) + + +class LoadError(Exception): pass + +class FileCookieJar(CookieJar): + """CookieJar that can be loaded from and saved to a file. + + Additional methods + + save(filename=None, ignore_discard=False, ignore_expires=False) + load(filename=None, ignore_discard=False, ignore_expires=False) + revert(filename=None, ignore_discard=False, ignore_expires=False) + + Additional public attributes + + filename: filename for loading and saving cookies + + Additional public readable attributes + + delayload: request that cookies are lazily loaded from disk; this is only + a hint since this only affects performance, not behaviour (unless the + cookies on disk are changing); a CookieJar object may ignore it (in fact, + only MSIECookieJar lazily loads cookies at the moment) + + """ + + def __init__(self, filename=None, delayload=False, policy=None): + """ + See FileCookieJar.__doc__ for argument documentation. + + Cookies are NOT loaded from the named file until either the load or + revert method is called. + + """ + CookieJar.__init__(self, policy) + if filename is not None and not isstringlike(filename): + raise ValueError("filename must be string-like") + self.filename = filename + self.delayload = bool(delayload) + + def save(self, filename=None, ignore_discard=False, ignore_expires=False): + """Save cookies to a file. + + filename: name of file in which to save cookies + ignore_discard: save even cookies set to be discarded + ignore_expires: save even cookies that have expired + + The file is overwritten if it already exists, thus wiping all its + cookies. Saved cookies can be restored later using the load or revert + methods. If filename is not specified, self.filename is used; if + self.filename is None, ValueError is raised. + + """ + raise NotImplementedError() + + def load(self, filename=None, ignore_discard=False, ignore_expires=False): + """Load cookies from a file. + + Old cookies are kept unless overwritten by newly loaded ones. + + Arguments are as for .save(). + + If filename is not specified, self.filename is used; if self.filename + is None, ValueError is raised. The named file must be in the format + understood by the class, or LoadError will be raised. This format will + be identical to that written by the save method, unless the load format + is not sufficiently well understood (as is the case for MSIECookieJar). + + """ + if filename is None: + if self.filename is not None: filename = self.filename + else: raise ValueError(MISSING_FILENAME_TEXT) + + f = open(filename) + try: + self._really_load(f, filename, ignore_discard, ignore_expires) + finally: + f.close() + + def revert(self, filename=None, + ignore_discard=False, ignore_expires=False): + """Clear all cookies and reload cookies from a saved file. + + Raises LoadError (or IOError) if reversion is not successful; the + object's state will not be altered if this happens. + + """ + if filename is None: + if self.filename is not None: filename = self.filename + else: raise ValueError(MISSING_FILENAME_TEXT) + + old_state = copy.deepcopy(self._cookies) + self._cookies = {} + try: + self.load(filename, ignore_discard, ignore_expires) + except (LoadError, IOError): + self._cookies = old_state + raise diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_debug.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_debug.py new file mode 100644 index 0000000..596b114 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_debug.py @@ -0,0 +1,28 @@ +import logging + +from urllib2 import BaseHandler +from _response import response_seek_wrapper + + +class HTTPResponseDebugProcessor(BaseHandler): + handler_order = 900 # before redirections, after everything else + + def http_response(self, request, response): + if not hasattr(response, "seek"): + response = response_seek_wrapper(response) + info = logging.getLogger("mechanize.http_responses").info + try: + info(response.read()) + finally: + response.seek(0) + info("*****************************************************") + return response + + https_response = http_response + +class HTTPRedirectDebugProcessor(BaseHandler): + def http_request(self, request): + if hasattr(request, "redirect_dict"): + info = logging.getLogger("mechanize.http_redirects").info + info("redirecting to %s", request.get_full_url()) + return request diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_file.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_file.py new file mode 100644 index 0000000..db662a8 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_file.py @@ -0,0 +1,60 @@ +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO +import mimetools +import os +import socket +import urllib +from urllib2 import BaseHandler, URLError + + +class FileHandler(BaseHandler): + # Use local file or FTP depending on form of URL + def file_open(self, req): + url = req.get_selector() + if url[:2] == '//' and url[2:3] != '/': + req.type = 'ftp' + return self.parent.open(req) + else: + return self.open_local_file(req) + + # names for the localhost + names = None + def get_names(self): + if FileHandler.names is None: + try: + FileHandler.names = (socket.gethostbyname('localhost'), + socket.gethostbyname(socket.gethostname())) + except socket.gaierror: + FileHandler.names = (socket.gethostbyname('localhost'),) + return FileHandler.names + + # not entirely sure what the rules are here + def open_local_file(self, req): + try: + import email.utils as emailutils + except ImportError: + import email.Utils as emailutils + import mimetypes + host = req.get_host() + file = req.get_selector() + localfile = urllib.url2pathname(file) + try: + stats = os.stat(localfile) + size = stats.st_size + modified = emailutils.formatdate(stats.st_mtime, usegmt=True) + mtype = mimetypes.guess_type(file)[0] + headers = mimetools.Message(StringIO( + 'Content-type: %s\nContent-length: %d\nLast-modified: %s\n' % + (mtype or 'text/plain', size, modified))) + if host: + host, port = urllib.splitport(host) + if not host or \ + (not port and socket.gethostbyname(host) in self.get_names()): + return urllib.addinfourl(open(localfile, 'rb'), + headers, 'file:'+file) + except OSError, msg: + # urllib2 users shouldn't expect OSErrors coming from urlopen() + raise URLError(msg) + raise URLError('file not on local host') diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_firefox3cookiejar.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_firefox3cookiejar.py new file mode 100644 index 0000000..34fe979 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_firefox3cookiejar.py @@ -0,0 +1,249 @@ +"""Firefox 3 "cookies.sqlite" cookie persistence. + +Copyright 2008 John J Lee <jjl@pobox.com> + +This code is free software; you can redistribute it and/or modify it +under the terms of the BSD or ZPL 2.1 licenses (see the file +COPYING.txt included with the distribution). + +""" + +import logging +import time +import sqlite3 + +from _clientcookie import CookieJar, Cookie, MappingIterator +from _util import isstringlike, experimental +debug = logging.getLogger("mechanize.cookies").debug + + +class Firefox3CookieJar(CookieJar): + + """Firefox 3 cookie jar. + + The cookies are stored in Firefox 3's "cookies.sqlite" format. + + Constructor arguments: + + filename: filename of cookies.sqlite (typically found at the top level + of a firefox profile directory) + autoconnect: as a convenience, connect to the SQLite cookies database at + Firefox3CookieJar construction time (default True) + policy: an object satisfying the mechanize.CookiePolicy interface + + Note that this is NOT a FileCookieJar, and there are no .load(), + .save() or .restore() methods. The database is in sync with the + cookiejar object's state after each public method call. + + Following Firefox's own behaviour, session cookies are never saved to + the database. + + The file is created, and an sqlite database written to it, if it does + not already exist. The moz_cookies database table is created if it does + not already exist. + """ + + # XXX + # handle DatabaseError exceptions + # add a FileCookieJar (explicit .save() / .revert() / .load() methods) + + def __init__(self, filename, autoconnect=True, policy=None): + experimental("Firefox3CookieJar is experimental code") + CookieJar.__init__(self, policy) + if filename is not None and not isstringlike(filename): + raise ValueError("filename must be string-like") + self.filename = filename + self._conn = None + if autoconnect: + self.connect() + + def connect(self): + self._conn = sqlite3.connect(self.filename) + self._conn.isolation_level = "DEFERRED" + self._create_table_if_necessary() + + def close(self): + self._conn.close() + + def _transaction(self, func): + try: + cur = self._conn.cursor() + try: + result = func(cur) + finally: + cur.close() + except: + self._conn.rollback() + raise + else: + self._conn.commit() + return result + + def _execute(self, query, params=()): + return self._transaction(lambda cur: cur.execute(query, params)) + + def _query(self, query, params=()): + # XXX should we bother with a transaction? + cur = self._conn.cursor() + try: + cur.execute(query, params) + for row in cur.fetchall(): + yield row + finally: + cur.close() + + def _create_table_if_necessary(self): + self._execute("""\ +CREATE TABLE IF NOT EXISTS moz_cookies (id INTEGER PRIMARY KEY, name TEXT, + value TEXT, host TEXT, path TEXT,expiry INTEGER, + lastAccessed INTEGER, isSecure INTEGER, isHttpOnly INTEGER)""") + + def _cookie_from_row(self, row): + (pk, name, value, domain, path, expires, + last_accessed, secure, http_only) = row + + version = 0 + domain = domain.encode("ascii", "ignore") + path = path.encode("ascii", "ignore") + name = name.encode("ascii", "ignore") + value = value.encode("ascii", "ignore") + secure = bool(secure) + + # last_accessed isn't a cookie attribute, so isn't added to rest + rest = {} + if http_only: + rest["HttpOnly"] = None + + if name == "": + name = value + value = None + + initial_dot = domain.startswith(".") + domain_specified = initial_dot + + discard = False + if expires == "": + expires = None + discard = True + + return Cookie(version, name, value, + None, False, + domain, domain_specified, initial_dot, + path, False, + secure, + expires, + discard, + None, + None, + rest) + + def clear(self, domain=None, path=None, name=None): + CookieJar.clear(self, domain, path, name) + where_parts = [] + sql_params = [] + if domain is not None: + where_parts.append("host = ?") + sql_params.append(domain) + if path is not None: + where_parts.append("path = ?") + sql_params.append(path) + if name is not None: + where_parts.append("name = ?") + sql_params.append(name) + where = " AND ".join(where_parts) + if where: + where = " WHERE " + where + def clear(cur): + cur.execute("DELETE FROM moz_cookies%s" % where, + tuple(sql_params)) + self._transaction(clear) + + def _row_from_cookie(self, cookie, cur): + expires = cookie.expires + if cookie.discard: + expires = "" + + domain = unicode(cookie.domain) + path = unicode(cookie.path) + name = unicode(cookie.name) + value = unicode(cookie.value) + secure = bool(int(cookie.secure)) + + if value is None: + value = name + name = "" + + last_accessed = int(time.time()) + http_only = cookie.has_nonstandard_attr("HttpOnly") + + query = cur.execute("""SELECT MAX(id) + 1 from moz_cookies""") + pk = query.fetchone()[0] + if pk is None: + pk = 1 + + return (pk, name, value, domain, path, expires, + last_accessed, secure, http_only) + + def set_cookie(self, cookie): + if cookie.discard: + CookieJar.set_cookie(self, cookie) + return + + def set_cookie(cur): + # XXX + # is this RFC 2965-correct? + # could this do an UPDATE instead? + row = self._row_from_cookie(cookie, cur) + name, unused, domain, path = row[1:5] + cur.execute("""\ +DELETE FROM moz_cookies WHERE host = ? AND path = ? AND name = ?""", + (domain, path, name)) + cur.execute("""\ +INSERT INTO moz_cookies VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) +""", row) + self._transaction(set_cookie) + + def __iter__(self): + # session (non-persistent) cookies + for cookie in MappingIterator(self._cookies): + yield cookie + # persistent cookies + for row in self._query("""\ +SELECT * FROM moz_cookies ORDER BY name, path, host"""): + yield self._cookie_from_row(row) + + def _cookies_for_request(self, request): + session_cookies = CookieJar._cookies_for_request(self, request) + def get_cookies(cur): + query = cur.execute("SELECT host from moz_cookies") + domains = [row[0] for row in query.fetchmany()] + cookies = [] + for domain in domains: + cookies += self._persistent_cookies_for_domain(domain, + request, cur) + return cookies + persistent_coookies = self._transaction(get_cookies) + return session_cookies + persistent_coookies + + def _persistent_cookies_for_domain(self, domain, request, cur): + cookies = [] + if not self._policy.domain_return_ok(domain, request): + return [] + debug("Checking %s for cookies to return", domain) + query = cur.execute("""\ +SELECT * from moz_cookies WHERE host = ? ORDER BY path""", + (domain,)) + cookies = [self._cookie_from_row(row) for row in query.fetchmany()] + last_path = None + r = [] + for cookie in cookies: + if (cookie.path != last_path and + not self._policy.path_return_ok(cookie.path, request)): + last_path = cookie.path + continue + if not self._policy.return_ok(cookie, request): + debug(" not returning cookie") + continue + debug(" it's a match") + r.append(cookie) + return r diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_gzip.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_gzip.py new file mode 100644 index 0000000..26c2743 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_gzip.py @@ -0,0 +1,103 @@ +import urllib2 +from cStringIO import StringIO +import _response + +# GzipConsumer was taken from Fredrik Lundh's effbot.org-0.1-20041009 library +class GzipConsumer: + + def __init__(self, consumer): + self.__consumer = consumer + self.__decoder = None + self.__data = "" + + def __getattr__(self, key): + return getattr(self.__consumer, key) + + def feed(self, data): + if self.__decoder is None: + # check if we have a full gzip header + data = self.__data + data + try: + i = 10 + flag = ord(data[3]) + if flag & 4: # extra + x = ord(data[i]) + 256*ord(data[i+1]) + i = i + 2 + x + if flag & 8: # filename + while ord(data[i]): + i = i + 1 + i = i + 1 + if flag & 16: # comment + while ord(data[i]): + i = i + 1 + i = i + 1 + if flag & 2: # crc + i = i + 2 + if len(data) < i: + raise IndexError("not enough data") + if data[:3] != "\x1f\x8b\x08": + raise IOError("invalid gzip data") + data = data[i:] + except IndexError: + self.__data = data + return # need more data + import zlib + self.__data = "" + self.__decoder = zlib.decompressobj(-zlib.MAX_WBITS) + data = self.__decoder.decompress(data) + if data: + self.__consumer.feed(data) + + def close(self): + if self.__decoder: + data = self.__decoder.flush() + if data: + self.__consumer.feed(data) + self.__consumer.close() + + +# -------------------------------------------------------------------- + +# the rest of this module is John Lee's stupid code, not +# Fredrik's nice code :-) + +class stupid_gzip_consumer: + def __init__(self): self.data = [] + def feed(self, data): self.data.append(data) + +class stupid_gzip_wrapper(_response.closeable_response): + def __init__(self, response): + self._response = response + + c = stupid_gzip_consumer() + gzc = GzipConsumer(c) + gzc.feed(response.read()) + self.__data = StringIO("".join(c.data)) + + def read(self, size=-1): + return self.__data.read(size) + def readline(self, size=-1): + return self.__data.readline(size) + def readlines(self, sizehint=-1): + return self.__data.readlines(sizehint) + + def __getattr__(self, name): + # delegate unknown methods/attributes + return getattr(self._response, name) + +class HTTPGzipProcessor(urllib2.BaseHandler): + handler_order = 200 # response processing before HTTPEquivProcessor + + def http_request(self, request): + request.add_header("Accept-Encoding", "gzip") + return request + + def http_response(self, request, response): + # post-process response + enc_hdrs = response.info().getheaders("Content-encoding") + for enc_hdr in enc_hdrs: + if ("gzip" in enc_hdr) or ("compress" in enc_hdr): + return stupid_gzip_wrapper(response) + return response + + https_response = http_response diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_headersutil.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_headersutil.py new file mode 100644 index 0000000..49ba5de --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_headersutil.py @@ -0,0 +1,232 @@ +"""Utility functions for HTTP header value parsing and construction. + +Copyright 1997-1998, Gisle Aas +Copyright 2002-2006, John J. Lee + +This code is free software; you can redistribute it and/or modify it +under the terms of the BSD or ZPL 2.1 licenses (see the file +COPYING.txt included with the distribution). + +""" + +import os, re +from types import StringType +from types import UnicodeType +STRING_TYPES = StringType, UnicodeType + +from _util import http2time +import _rfc3986 + +def is_html(ct_headers, url, allow_xhtml=False): + """ + ct_headers: Sequence of Content-Type headers + url: Response URL + + """ + if not ct_headers: + # guess + ext = os.path.splitext(_rfc3986.urlsplit(url)[2])[1] + html_exts = [".htm", ".html"] + if allow_xhtml: + html_exts += [".xhtml"] + return ext in html_exts + # use first header + ct = split_header_words(ct_headers)[0][0][0] + html_types = ["text/html"] + if allow_xhtml: + html_types += [ + "text/xhtml", "text/xml", + "application/xml", "application/xhtml+xml", + ] + return ct in html_types + +def unmatched(match): + """Return unmatched part of re.Match object.""" + start, end = match.span(0) + return match.string[:start]+match.string[end:] + +token_re = re.compile(r"^\s*([^=\s;,]+)") +quoted_value_re = re.compile(r"^\s*=\s*\"([^\"\\]*(?:\\.[^\"\\]*)*)\"") +value_re = re.compile(r"^\s*=\s*([^\s;,]*)") +escape_re = re.compile(r"\\(.)") +def split_header_words(header_values): + r"""Parse header values into a list of lists containing key,value pairs. + + The function knows how to deal with ",", ";" and "=" as well as quoted + values after "=". A list of space separated tokens are parsed as if they + were separated by ";". + + If the header_values passed as argument contains multiple values, then they + are treated as if they were a single value separated by comma ",". + + This means that this function is useful for parsing header fields that + follow this syntax (BNF as from the HTTP/1.1 specification, but we relax + the requirement for tokens). + + headers = #header + header = (token | parameter) *( [";"] (token | parameter)) + + token = 1*<any CHAR except CTLs or separators> + separators = "(" | ")" | "<" | ">" | "@" + | "," | ";" | ":" | "\" | <"> + | "/" | "[" | "]" | "?" | "=" + | "{" | "}" | SP | HT + + quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) + qdtext = <any TEXT except <">> + quoted-pair = "\" CHAR + + parameter = attribute "=" value + attribute = token + value = token | quoted-string + + Each header is represented by a list of key/value pairs. The value for a + simple token (not part of a parameter) is None. Syntactically incorrect + headers will not necessarily be parsed as you would want. + + This is easier to describe with some examples: + + >>> split_header_words(['foo="bar"; port="80,81"; discard, bar=baz']) + [[('foo', 'bar'), ('port', '80,81'), ('discard', None)], [('bar', 'baz')]] + >>> split_header_words(['text/html; charset="iso-8859-1"']) + [[('text/html', None), ('charset', 'iso-8859-1')]] + >>> split_header_words([r'Basic realm="\"foo\bar\""']) + [[('Basic', None), ('realm', '"foobar"')]] + + """ + assert type(header_values) not in STRING_TYPES + result = [] + for text in header_values: + orig_text = text + pairs = [] + while text: + m = token_re.search(text) + if m: + text = unmatched(m) + name = m.group(1) + m = quoted_value_re.search(text) + if m: # quoted value + text = unmatched(m) + value = m.group(1) + value = escape_re.sub(r"\1", value) + else: + m = value_re.search(text) + if m: # unquoted value + text = unmatched(m) + value = m.group(1) + value = value.rstrip() + else: + # no value, a lone token + value = None + pairs.append((name, value)) + elif text.lstrip().startswith(","): + # concatenated headers, as per RFC 2616 section 4.2 + text = text.lstrip()[1:] + if pairs: result.append(pairs) + pairs = [] + else: + # skip junk + non_junk, nr_junk_chars = re.subn("^[=\s;]*", "", text) + assert nr_junk_chars > 0, ( + "split_header_words bug: '%s', '%s', %s" % + (orig_text, text, pairs)) + text = non_junk + if pairs: result.append(pairs) + return result + +join_escape_re = re.compile(r"([\"\\])") +def join_header_words(lists): + """Do the inverse of the conversion done by split_header_words. + + Takes a list of lists of (key, value) pairs and produces a single header + value. Attribute values are quoted if needed. + + >>> join_header_words([[("text/plain", None), ("charset", "iso-8859/1")]]) + 'text/plain; charset="iso-8859/1"' + >>> join_header_words([[("text/plain", None)], [("charset", "iso-8859/1")]]) + 'text/plain, charset="iso-8859/1"' + + """ + headers = [] + for pairs in lists: + attr = [] + for k, v in pairs: + if v is not None: + if not re.search(r"^\w+$", v): + v = join_escape_re.sub(r"\\\1", v) # escape " and \ + v = '"%s"' % v + if k is None: # Netscape cookies may have no name + k = v + else: + k = "%s=%s" % (k, v) + attr.append(k) + if attr: headers.append("; ".join(attr)) + return ", ".join(headers) + +def strip_quotes(text): + if text.startswith('"'): + text = text[1:] + if text.endswith('"'): + text = text[:-1] + return text + +def parse_ns_headers(ns_headers): + """Ad-hoc parser for Netscape protocol cookie-attributes. + + The old Netscape cookie format for Set-Cookie can for instance contain + an unquoted "," in the expires field, so we have to use this ad-hoc + parser instead of split_header_words. + + XXX This may not make the best possible effort to parse all the crap + that Netscape Cookie headers contain. Ronald Tschalar's HTTPClient + parser is probably better, so could do worse than following that if + this ever gives any trouble. + + Currently, this is also used for parsing RFC 2109 cookies. + + """ + known_attrs = ("expires", "domain", "path", "secure", + # RFC 2109 attrs (may turn up in Netscape cookies, too) + "version", "port", "max-age") + + result = [] + for ns_header in ns_headers: + pairs = [] + version_set = False + params = re.split(r";\s*", ns_header) + for ii in range(len(params)): + param = params[ii] + param = param.rstrip() + if param == "": continue + if "=" not in param: + k, v = param, None + else: + k, v = re.split(r"\s*=\s*", param, 1) + k = k.lstrip() + if ii != 0: + lc = k.lower() + if lc in known_attrs: + k = lc + if k == "version": + # This is an RFC 2109 cookie. + v = strip_quotes(v) + version_set = True + if k == "expires": + # convert expires date to seconds since epoch + v = http2time(strip_quotes(v)) # None if invalid + pairs.append((k, v)) + + if pairs: + if not version_set: + pairs.append(("version", "0")) + result.append(pairs) + + return result + + +def _test(): + import doctest, _headersutil + return doctest.testmod(_headersutil) + +if __name__ == "__main__": + _test() diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_html.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_html.py new file mode 100644 index 0000000..5da0815 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_html.py @@ -0,0 +1,631 @@ +"""HTML handling. + +Copyright 2003-2006 John J. Lee <jjl@pobox.com> + +This code is free software; you can redistribute it and/or modify it under +the terms of the BSD or ZPL 2.1 licenses (see the file COPYING.txt +included with the distribution). + +""" + +import re, copy, htmlentitydefs +import sgmllib, ClientForm + +import _request +from _headersutil import split_header_words, is_html as _is_html +import _rfc3986 + +DEFAULT_ENCODING = "latin-1" + +COMPRESS_RE = re.compile(r"\s+") + + +# the base classe is purely for backwards compatibility +class ParseError(ClientForm.ParseError): pass + + +class CachingGeneratorFunction(object): + """Caching wrapper around a no-arguments iterable.""" + + def __init__(self, iterable): + self._cache = [] + # wrap iterable to make it non-restartable (otherwise, repeated + # __call__ would give incorrect results) + self._iterator = iter(iterable) + + def __call__(self): + cache = self._cache + for item in cache: + yield item + for item in self._iterator: + cache.append(item) + yield item + + +class EncodingFinder: + def __init__(self, default_encoding): + self._default_encoding = default_encoding + def encoding(self, response): + # HTTPEquivProcessor may be in use, so both HTTP and HTTP-EQUIV + # headers may be in the response. HTTP-EQUIV headers come last, + # so try in order from first to last. + for ct in response.info().getheaders("content-type"): + for k, v in split_header_words([ct])[0]: + if k == "charset": + return v + return self._default_encoding + +class ResponseTypeFinder: + def __init__(self, allow_xhtml): + self._allow_xhtml = allow_xhtml + def is_html(self, response, encoding): + ct_hdrs = response.info().getheaders("content-type") + url = response.geturl() + # XXX encoding + return _is_html(ct_hdrs, url, self._allow_xhtml) + + +# idea for this argument-processing trick is from Peter Otten +class Args: + def __init__(self, args_map): + self.dictionary = dict(args_map) + def __getattr__(self, key): + try: + return self.dictionary[key] + except KeyError: + return getattr(self.__class__, key) + +def form_parser_args( + select_default=False, + form_parser_class=None, + request_class=None, + backwards_compat=False, + ): + return Args(locals()) + + +class Link: + def __init__(self, base_url, url, text, tag, attrs): + assert None not in [url, tag, attrs] + self.base_url = base_url + self.absolute_url = _rfc3986.urljoin(base_url, url) + self.url, self.text, self.tag, self.attrs = url, text, tag, attrs + def __cmp__(self, other): + try: + for name in "url", "text", "tag", "attrs": + if getattr(self, name) != getattr(other, name): + return -1 + except AttributeError: + return -1 + return 0 + def __repr__(self): + return "Link(base_url=%r, url=%r, text=%r, tag=%r, attrs=%r)" % ( + self.base_url, self.url, self.text, self.tag, self.attrs) + + +class LinksFactory: + + def __init__(self, + link_parser_class=None, + link_class=Link, + urltags=None, + ): + import _pullparser + if link_parser_class is None: + link_parser_class = _pullparser.TolerantPullParser + self.link_parser_class = link_parser_class + self.link_class = link_class + if urltags is None: + urltags = { + "a": "href", + "area": "href", + "frame": "src", + "iframe": "src", + } + self.urltags = urltags + self._response = None + self._encoding = None + + def set_response(self, response, base_url, encoding): + self._response = response + self._encoding = encoding + self._base_url = base_url + + def links(self): + """Return an iterator that provides links of the document.""" + response = self._response + encoding = self._encoding + base_url = self._base_url + p = self.link_parser_class(response, encoding=encoding) + + try: + for token in p.tags(*(self.urltags.keys()+["base"])): + if token.type == "endtag": + continue + if token.data == "base": + base_href = dict(token.attrs).get("href") + if base_href is not None: + base_url = base_href + continue + attrs = dict(token.attrs) + tag = token.data + name = attrs.get("name") + text = None + # XXX use attr_encoding for ref'd doc if that doc does not + # provide one by other means + #attr_encoding = attrs.get("charset") + url = attrs.get(self.urltags[tag]) # XXX is "" a valid URL? + if not url: + # Probably an <A NAME="blah"> link or <AREA NOHREF...>. + # For our purposes a link is something with a URL, so + # ignore this. + continue + + url = _rfc3986.clean_url(url, encoding) + if tag == "a": + if token.type != "startendtag": + # hmm, this'd break if end tag is missing + text = p.get_compressed_text(("endtag", tag)) + # but this doesn't work for eg. + # <a href="blah"><b>Andy</b></a> + #text = p.get_compressed_text() + + yield Link(base_url, url, text, tag, token.attrs) + except sgmllib.SGMLParseError, exc: + raise ParseError(exc) + +class FormsFactory: + + """Makes a sequence of objects satisfying ClientForm.HTMLForm interface. + + After calling .forms(), the .global_form attribute is a form object + containing all controls not a descendant of any FORM element. + + For constructor argument docs, see ClientForm.ParseResponse + argument docs. + + """ + + def __init__(self, + select_default=False, + form_parser_class=None, + request_class=None, + backwards_compat=False, + ): + import ClientForm + self.select_default = select_default + if form_parser_class is None: + form_parser_class = ClientForm.FormParser + self.form_parser_class = form_parser_class + if request_class is None: + request_class = _request.Request + self.request_class = request_class + self.backwards_compat = backwards_compat + self._response = None + self.encoding = None + self.global_form = None + + def set_response(self, response, encoding): + self._response = response + self.encoding = encoding + self.global_form = None + + def forms(self): + import ClientForm + encoding = self.encoding + try: + forms = ClientForm.ParseResponseEx( + self._response, + select_default=self.select_default, + form_parser_class=self.form_parser_class, + request_class=self.request_class, + encoding=encoding, + _urljoin=_rfc3986.urljoin, + _urlparse=_rfc3986.urlsplit, + _urlunparse=_rfc3986.urlunsplit, + ) + except ClientForm.ParseError, exc: + raise ParseError(exc) + self.global_form = forms[0] + return forms[1:] + +class TitleFactory: + def __init__(self): + self._response = self._encoding = None + + def set_response(self, response, encoding): + self._response = response + self._encoding = encoding + + def _get_title_text(self, parser): + import _pullparser + text = [] + tok = None + while 1: + try: + tok = parser.get_token() + except _pullparser.NoMoreTokensError: + break + if tok.type == "data": + text.append(str(tok)) + elif tok.type == "entityref": + t = unescape("&%s;" % tok.data, + parser._entitydefs, parser.encoding) + text.append(t) + elif tok.type == "charref": + t = unescape_charref(tok.data, parser.encoding) + text.append(t) + elif tok.type in ["starttag", "endtag", "startendtag"]: + tag_name = tok.data + if tok.type == "endtag" and tag_name == "title": + break + text.append(str(tok)) + return COMPRESS_RE.sub(" ", "".join(text).strip()) + + def title(self): + import _pullparser + p = _pullparser.TolerantPullParser( + self._response, encoding=self._encoding) + try: + try: + p.get_tag("title") + except _pullparser.NoMoreTokensError: + return None + else: + return self._get_title_text(p) + except sgmllib.SGMLParseError, exc: + raise ParseError(exc) + + +def unescape(data, entities, encoding): + if data is None or "&" not in data: + return data + + def replace_entities(match): + ent = match.group() + if ent[1] == "#": + return unescape_charref(ent[2:-1], encoding) + + repl = entities.get(ent[1:-1]) + if repl is not None: + repl = unichr(repl) + if type(repl) != type(""): + try: + repl = repl.encode(encoding) + except UnicodeError: + repl = ent + else: + repl = ent + return repl + + return re.sub(r"&#?[A-Za-z0-9]+?;", replace_entities, data) + +def unescape_charref(data, encoding): + name, base = data, 10 + if name.startswith("x"): + name, base= name[1:], 16 + uc = unichr(int(name, base)) + if encoding is None: + return uc + else: + try: + repl = uc.encode(encoding) + except UnicodeError: + repl = "&#%s;" % data + return repl + + +# bizarre import gymnastics for bundled BeautifulSoup +import _beautifulsoup +import ClientForm +RobustFormParser, NestingRobustFormParser = ClientForm._create_bs_classes( + _beautifulsoup.BeautifulSoup, _beautifulsoup.ICantBelieveItsBeautifulSoup + ) +# monkeypatch sgmllib to fix http://www.python.org/sf/803422 :-( +sgmllib.charref = re.compile("&#(x?[0-9a-fA-F]+)[^0-9a-fA-F]") + +class MechanizeBs(_beautifulsoup.BeautifulSoup): + _entitydefs = htmlentitydefs.name2codepoint + # don't want the magic Microsoft-char workaround + PARSER_MASSAGE = [(re.compile('(<[^<>]*)/>'), + lambda(x):x.group(1) + ' />'), + (re.compile('<!\s+([^<>]*)>'), + lambda(x):'<!' + x.group(1) + '>') + ] + + def __init__(self, encoding, text=None, avoidParserProblems=True, + initialTextIsEverything=True): + self._encoding = encoding + _beautifulsoup.BeautifulSoup.__init__( + self, text, avoidParserProblems, initialTextIsEverything) + + def handle_charref(self, ref): + t = unescape("&#%s;"%ref, self._entitydefs, self._encoding) + self.handle_data(t) + def handle_entityref(self, ref): + t = unescape("&%s;"%ref, self._entitydefs, self._encoding) + self.handle_data(t) + def unescape_attrs(self, attrs): + escaped_attrs = [] + for key, val in attrs: + val = unescape(val, self._entitydefs, self._encoding) + escaped_attrs.append((key, val)) + return escaped_attrs + +class RobustLinksFactory: + + compress_re = COMPRESS_RE + + def __init__(self, + link_parser_class=None, + link_class=Link, + urltags=None, + ): + if link_parser_class is None: + link_parser_class = MechanizeBs + self.link_parser_class = link_parser_class + self.link_class = link_class + if urltags is None: + urltags = { + "a": "href", + "area": "href", + "frame": "src", + "iframe": "src", + } + self.urltags = urltags + self._bs = None + self._encoding = None + self._base_url = None + + def set_soup(self, soup, base_url, encoding): + self._bs = soup + self._base_url = base_url + self._encoding = encoding + + def links(self): + import _beautifulsoup + bs = self._bs + base_url = self._base_url + encoding = self._encoding + gen = bs.recursiveChildGenerator() + for ch in bs.recursiveChildGenerator(): + if (isinstance(ch, _beautifulsoup.Tag) and + ch.name in self.urltags.keys()+["base"]): + link = ch + attrs = bs.unescape_attrs(link.attrs) + attrs_dict = dict(attrs) + if link.name == "base": + base_href = attrs_dict.get("href") + if base_href is not None: + base_url = base_href + continue + url_attr = self.urltags[link.name] + url = attrs_dict.get(url_attr) + if not url: + continue + url = _rfc3986.clean_url(url, encoding) + text = link.fetchText(lambda t: True) + if not text: + # follow _pullparser's weird behaviour rigidly + if link.name == "a": + text = "" + else: + text = None + else: + text = self.compress_re.sub(" ", " ".join(text).strip()) + yield Link(base_url, url, text, link.name, attrs) + + +class RobustFormsFactory(FormsFactory): + def __init__(self, *args, **kwds): + args = form_parser_args(*args, **kwds) + if args.form_parser_class is None: + args.form_parser_class = RobustFormParser + FormsFactory.__init__(self, **args.dictionary) + + def set_response(self, response, encoding): + self._response = response + self.encoding = encoding + + +class RobustTitleFactory: + def __init__(self): + self._bs = self._encoding = None + + def set_soup(self, soup, encoding): + self._bs = soup + self._encoding = encoding + + def title(self): + import _beautifulsoup + title = self._bs.first("title") + if title == _beautifulsoup.Null: + return None + else: + inner_html = "".join([str(node) for node in title.contents]) + return COMPRESS_RE.sub(" ", inner_html.strip()) + + +class Factory: + """Factory for forms, links, etc. + + This interface may expand in future. + + Public methods: + + set_request_class(request_class) + set_response(response) + forms() + links() + + Public attributes: + + Note that accessing these attributes may raise ParseError. + + encoding: string specifying the encoding of response if it contains a text + document (this value is left unspecified for documents that do not have + an encoding, e.g. an image file) + is_html: true if response contains an HTML document (XHTML may be + regarded as HTML too) + title: page title, or None if no title or not HTML + global_form: form object containing all controls that are not descendants + of any FORM element, or None if the forms_factory does not support + supplying a global form + + """ + + LAZY_ATTRS = ["encoding", "is_html", "title", "global_form"] + + def __init__(self, forms_factory, links_factory, title_factory, + encoding_finder=EncodingFinder(DEFAULT_ENCODING), + response_type_finder=ResponseTypeFinder(allow_xhtml=False), + ): + """ + + Pass keyword arguments only. + + default_encoding: character encoding to use if encoding cannot be + determined (or guessed) from the response. You should turn on + HTTP-EQUIV handling if you want the best chance of getting this right + without resorting to this default. The default value of this + parameter (currently latin-1) may change in future. + + """ + self._forms_factory = forms_factory + self._links_factory = links_factory + self._title_factory = title_factory + self._encoding_finder = encoding_finder + self._response_type_finder = response_type_finder + + self.set_response(None) + + def set_request_class(self, request_class): + """Set urllib2.Request class. + + ClientForm.HTMLForm instances returned by .forms() will return + instances of this class when .click()ed. + + """ + self._forms_factory.request_class = request_class + + def set_response(self, response): + """Set response. + + The response must either be None or implement the same interface as + objects returned by urllib2.urlopen(). + + """ + self._response = response + self._forms_genf = self._links_genf = None + self._get_title = None + for name in self.LAZY_ATTRS: + try: + delattr(self, name) + except AttributeError: + pass + + def __getattr__(self, name): + if name not in self.LAZY_ATTRS: + return getattr(self.__class__, name) + + if name == "encoding": + self.encoding = self._encoding_finder.encoding( + copy.copy(self._response)) + return self.encoding + elif name == "is_html": + self.is_html = self._response_type_finder.is_html( + copy.copy(self._response), self.encoding) + return self.is_html + elif name == "title": + if self.is_html: + self.title = self._title_factory.title() + else: + self.title = None + return self.title + elif name == "global_form": + self.forms() + return self.global_form + + def forms(self): + """Return iterable over ClientForm.HTMLForm-like objects. + + Raises mechanize.ParseError on failure. + """ + # this implementation sets .global_form as a side-effect, for benefit + # of __getattr__ impl + if self._forms_genf is None: + try: + self._forms_genf = CachingGeneratorFunction( + self._forms_factory.forms()) + except: # XXXX define exception! + self.set_response(self._response) + raise + self.global_form = getattr( + self._forms_factory, "global_form", None) + return self._forms_genf() + + def links(self): + """Return iterable over mechanize.Link-like objects. + + Raises mechanize.ParseError on failure. + """ + if self._links_genf is None: + try: + self._links_genf = CachingGeneratorFunction( + self._links_factory.links()) + except: # XXXX define exception! + self.set_response(self._response) + raise + return self._links_genf() + +class DefaultFactory(Factory): + """Based on sgmllib.""" + def __init__(self, i_want_broken_xhtml_support=False): + Factory.__init__( + self, + forms_factory=FormsFactory(), + links_factory=LinksFactory(), + title_factory=TitleFactory(), + response_type_finder=ResponseTypeFinder( + allow_xhtml=i_want_broken_xhtml_support), + ) + + def set_response(self, response): + Factory.set_response(self, response) + if response is not None: + self._forms_factory.set_response( + copy.copy(response), self.encoding) + self._links_factory.set_response( + copy.copy(response), response.geturl(), self.encoding) + self._title_factory.set_response( + copy.copy(response), self.encoding) + +class RobustFactory(Factory): + """Based on BeautifulSoup, hopefully a bit more robust to bad HTML than is + DefaultFactory. + + """ + def __init__(self, i_want_broken_xhtml_support=False, + soup_class=None): + Factory.__init__( + self, + forms_factory=RobustFormsFactory(), + links_factory=RobustLinksFactory(), + title_factory=RobustTitleFactory(), + response_type_finder=ResponseTypeFinder( + allow_xhtml=i_want_broken_xhtml_support), + ) + if soup_class is None: + soup_class = MechanizeBs + self._soup_class = soup_class + + def set_response(self, response): + Factory.set_response(self, response) + if response is not None: + data = response.read() + soup = self._soup_class(self.encoding, data) + self._forms_factory.set_response( + copy.copy(response), self.encoding) + self._links_factory.set_soup( + soup, response.geturl(), self.encoding) + self._title_factory.set_soup(soup, self.encoding) diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_http.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_http.py new file mode 100644 index 0000000..1b80e2b --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_http.py @@ -0,0 +1,758 @@ +"""HTTP related handlers. + +Note that some other HTTP handlers live in more specific modules: _auth.py, +_gzip.py, etc. + + +Copyright 2002-2006 John J Lee <jjl@pobox.com> + +This code is free software; you can redistribute it and/or modify it +under the terms of the BSD or ZPL 2.1 licenses (see the file +COPYING.txt included with the distribution). + +""" + +import time, htmlentitydefs, logging, socket, \ + urllib2, urllib, httplib, sgmllib +from urllib2 import URLError, HTTPError, BaseHandler +from cStringIO import StringIO + +from _clientcookie import CookieJar +from _headersutil import is_html +from _html import unescape, unescape_charref +from _request import Request +from _response import closeable_response, response_seek_wrapper +import _rfc3986 +import _sockettimeout + +debug = logging.getLogger("mechanize").debug +debug_robots = logging.getLogger("mechanize.robots").debug + +# monkeypatch urllib2.HTTPError to show URL +## def urllib2_str(self): +## return 'HTTP Error %s: %s (%s)' % ( +## self.code, self.msg, self.geturl()) +## urllib2.HTTPError.__str__ = urllib2_str + + +CHUNK = 1024 # size of chunks fed to HTML HEAD parser, in bytes +DEFAULT_ENCODING = 'latin-1' + + +try: + socket._fileobject("fake socket", close=True) +except TypeError: + # python <= 2.4 + create_readline_wrapper = socket._fileobject +else: + def create_readline_wrapper(fh): + return socket._fileobject(fh, close=True) + + +# This adds "refresh" to the list of redirectables and provides a redirection +# algorithm that doesn't go into a loop in the presence of cookies +# (Python 2.4 has this new algorithm, 2.3 doesn't). +class HTTPRedirectHandler(BaseHandler): + # maximum number of redirections to any single URL + # this is needed because of the state that cookies introduce + max_repeats = 4 + # maximum total number of redirections (regardless of URL) before + # assuming we're in a loop + max_redirections = 10 + + # Implementation notes: + + # To avoid the server sending us into an infinite loop, the request + # object needs to track what URLs we have already seen. Do this by + # adding a handler-specific attribute to the Request object. The value + # of the dict is used to count the number of times the same URL has + # been visited. This is needed because visiting the same URL twice + # does not necessarily imply a loop, thanks to state introduced by + # cookies. + + # Always unhandled redirection codes: + # 300 Multiple Choices: should not handle this here. + # 304 Not Modified: no need to handle here: only of interest to caches + # that do conditional GETs + # 305 Use Proxy: probably not worth dealing with here + # 306 Unused: what was this for in the previous versions of protocol?? + + def redirect_request(self, newurl, req, fp, code, msg, headers): + """Return a Request or None in response to a redirect. + + This is called by the http_error_30x methods when a redirection + response is received. If a redirection should take place, return a + new Request to allow http_error_30x to perform the redirect; + otherwise, return None to indicate that an HTTPError should be + raised. + + """ + if code in (301, 302, 303, "refresh") or \ + (code == 307 and not req.has_data()): + # Strictly (according to RFC 2616), 301 or 302 in response to + # a POST MUST NOT cause a redirection without confirmation + # from the user (of urllib2, in this case). In practice, + # essentially all clients do redirect in this case, so we do + # the same. + # XXX really refresh redirections should be visiting; tricky to + # fix, so this will wait until post-stable release + new = Request(newurl, + headers=req.headers, + origin_req_host=req.get_origin_req_host(), + unverifiable=True, + visit=False, + ) + new._origin_req = getattr(req, "_origin_req", req) + return new + else: + raise HTTPError(req.get_full_url(), code, msg, headers, fp) + + def http_error_302(self, req, fp, code, msg, headers): + # Some servers (incorrectly) return multiple Location headers + # (so probably same goes for URI). Use first header. + if headers.has_key('location'): + newurl = headers.getheaders('location')[0] + elif headers.has_key('uri'): + newurl = headers.getheaders('uri')[0] + else: + return + newurl = _rfc3986.clean_url(newurl, "latin-1") + newurl = _rfc3986.urljoin(req.get_full_url(), newurl) + + # XXX Probably want to forget about the state of the current + # request, although that might interact poorly with other + # handlers that also use handler-specific request attributes + new = self.redirect_request(newurl, req, fp, code, msg, headers) + if new is None: + return + + # loop detection + # .redirect_dict has a key url if url was previously visited. + if hasattr(req, 'redirect_dict'): + visited = new.redirect_dict = req.redirect_dict + if (visited.get(newurl, 0) >= self.max_repeats or + len(visited) >= self.max_redirections): + raise HTTPError(req.get_full_url(), code, + self.inf_msg + msg, headers, fp) + else: + visited = new.redirect_dict = req.redirect_dict = {} + visited[newurl] = visited.get(newurl, 0) + 1 + + # Don't close the fp until we are sure that we won't use it + # with HTTPError. + fp.read() + fp.close() + + return self.parent.open(new) + + http_error_301 = http_error_303 = http_error_307 = http_error_302 + http_error_refresh = http_error_302 + + inf_msg = "The HTTP server returned a redirect error that would " \ + "lead to an infinite loop.\n" \ + "The last 30x error message was:\n" + + +# XXX would self.reset() work, instead of raising this exception? +class EndOfHeadError(Exception): pass +class AbstractHeadParser: + # only these elements are allowed in or before HEAD of document + head_elems = ("html", "head", + "title", "base", + "script", "style", "meta", "link", "object") + _entitydefs = htmlentitydefs.name2codepoint + _encoding = DEFAULT_ENCODING + + def __init__(self): + self.http_equiv = [] + + def start_meta(self, attrs): + http_equiv = content = None + for key, value in attrs: + if key == "http-equiv": + http_equiv = self.unescape_attr_if_required(value) + elif key == "content": + content = self.unescape_attr_if_required(value) + if http_equiv is not None and content is not None: + self.http_equiv.append((http_equiv, content)) + + def end_head(self): + raise EndOfHeadError() + + def handle_entityref(self, name): + #debug("%s", name) + self.handle_data(unescape( + '&%s;' % name, self._entitydefs, self._encoding)) + + def handle_charref(self, name): + #debug("%s", name) + self.handle_data(unescape_charref(name, self._encoding)) + + def unescape_attr(self, name): + #debug("%s", name) + return unescape(name, self._entitydefs, self._encoding) + + def unescape_attrs(self, attrs): + #debug("%s", attrs) + escaped_attrs = {} + for key, val in attrs.items(): + escaped_attrs[key] = self.unescape_attr(val) + return escaped_attrs + + def unknown_entityref(self, ref): + self.handle_data("&%s;" % ref) + + def unknown_charref(self, ref): + self.handle_data("&#%s;" % ref) + + +try: + import HTMLParser +except ImportError: + pass +else: + class XHTMLCompatibleHeadParser(AbstractHeadParser, + HTMLParser.HTMLParser): + def __init__(self): + HTMLParser.HTMLParser.__init__(self) + AbstractHeadParser.__init__(self) + + def handle_starttag(self, tag, attrs): + if tag not in self.head_elems: + raise EndOfHeadError() + try: + method = getattr(self, 'start_' + tag) + except AttributeError: + try: + method = getattr(self, 'do_' + tag) + except AttributeError: + pass # unknown tag + else: + method(attrs) + else: + method(attrs) + + def handle_endtag(self, tag): + if tag not in self.head_elems: + raise EndOfHeadError() + try: + method = getattr(self, 'end_' + tag) + except AttributeError: + pass # unknown tag + else: + method() + + def unescape(self, name): + # Use the entitydefs passed into constructor, not + # HTMLParser.HTMLParser's entitydefs. + return self.unescape_attr(name) + + def unescape_attr_if_required(self, name): + return name # HTMLParser.HTMLParser already did it + +class HeadParser(AbstractHeadParser, sgmllib.SGMLParser): + + def _not_called(self): + assert False + + def __init__(self): + sgmllib.SGMLParser.__init__(self) + AbstractHeadParser.__init__(self) + + def handle_starttag(self, tag, method, attrs): + if tag not in self.head_elems: + raise EndOfHeadError() + if tag == "meta": + method(attrs) + + def unknown_starttag(self, tag, attrs): + self.handle_starttag(tag, self._not_called, attrs) + + def handle_endtag(self, tag, method): + if tag in self.head_elems: + method() + else: + raise EndOfHeadError() + + def unescape_attr_if_required(self, name): + return self.unescape_attr(name) + +def parse_head(fileobj, parser): + """Return a list of key, value pairs.""" + while 1: + data = fileobj.read(CHUNK) + try: + parser.feed(data) + except EndOfHeadError: + break + if len(data) != CHUNK: + # this should only happen if there is no HTML body, or if + # CHUNK is big + break + return parser.http_equiv + +class HTTPEquivProcessor(BaseHandler): + """Append META HTTP-EQUIV headers to regular HTTP headers.""" + + handler_order = 300 # before handlers that look at HTTP headers + + def __init__(self, head_parser_class=HeadParser, + i_want_broken_xhtml_support=False, + ): + self.head_parser_class = head_parser_class + self._allow_xhtml = i_want_broken_xhtml_support + + def http_response(self, request, response): + if not hasattr(response, "seek"): + response = response_seek_wrapper(response) + http_message = response.info() + url = response.geturl() + ct_hdrs = http_message.getheaders("content-type") + if is_html(ct_hdrs, url, self._allow_xhtml): + try: + try: + html_headers = parse_head(response, + self.head_parser_class()) + finally: + response.seek(0) + except (HTMLParser.HTMLParseError, + sgmllib.SGMLParseError): + pass + else: + for hdr, val in html_headers: + # add a header + http_message.dict[hdr.lower()] = val + text = hdr + ": " + val + for line in text.split("\n"): + http_message.headers.append(line + "\n") + return response + + https_response = http_response + +class HTTPCookieProcessor(BaseHandler): + """Handle HTTP cookies. + + Public attributes: + + cookiejar: CookieJar instance + + """ + def __init__(self, cookiejar=None): + if cookiejar is None: + cookiejar = CookieJar() + self.cookiejar = cookiejar + + def http_request(self, request): + self.cookiejar.add_cookie_header(request) + return request + + def http_response(self, request, response): + self.cookiejar.extract_cookies(response, request) + return response + + https_request = http_request + https_response = http_response + +try: + import robotparser +except ImportError: + pass +else: + class MechanizeRobotFileParser(robotparser.RobotFileParser): + + def __init__(self, url='', opener=None): + robotparser.RobotFileParser.__init__(self, url) + self._opener = opener + self._timeout = _sockettimeout._GLOBAL_DEFAULT_TIMEOUT + + def set_opener(self, opener=None): + import _opener + if opener is None: + opener = _opener.OpenerDirector() + self._opener = opener + + def set_timeout(self, timeout): + self._timeout = timeout + + def read(self): + """Reads the robots.txt URL and feeds it to the parser.""" + if self._opener is None: + self.set_opener() + req = Request(self.url, unverifiable=True, visit=False, + timeout=self._timeout) + try: + f = self._opener.open(req) + except HTTPError, f: + pass + except (IOError, socket.error, OSError), exc: + debug_robots("ignoring error opening %r: %s" % + (self.url, exc)) + return + lines = [] + line = f.readline() + while line: + lines.append(line.strip()) + line = f.readline() + status = f.code + if status == 401 or status == 403: + self.disallow_all = True + debug_robots("disallow all") + elif status >= 400: + self.allow_all = True + debug_robots("allow all") + elif status == 200 and lines: + debug_robots("parse lines") + self.parse(lines) + + class RobotExclusionError(urllib2.HTTPError): + def __init__(self, request, *args): + apply(urllib2.HTTPError.__init__, (self,)+args) + self.request = request + + class HTTPRobotRulesProcessor(BaseHandler): + # before redirections, after everything else + handler_order = 800 + + try: + from httplib import HTTPMessage + except: + from mimetools import Message + http_response_class = Message + else: + http_response_class = HTTPMessage + + def __init__(self, rfp_class=MechanizeRobotFileParser): + self.rfp_class = rfp_class + self.rfp = None + self._host = None + + def http_request(self, request): + scheme = request.get_type() + if scheme not in ["http", "https"]: + # robots exclusion only applies to HTTP + return request + + if request.get_selector() == "/robots.txt": + # /robots.txt is always OK to fetch + return request + + host = request.get_host() + + # robots.txt requests don't need to be allowed by robots.txt :-) + origin_req = getattr(request, "_origin_req", None) + if (origin_req is not None and + origin_req.get_selector() == "/robots.txt" and + origin_req.get_host() == host + ): + return request + + if host != self._host: + self.rfp = self.rfp_class() + try: + self.rfp.set_opener(self.parent) + except AttributeError: + debug("%r instance does not support set_opener" % + self.rfp.__class__) + self.rfp.set_url(scheme+"://"+host+"/robots.txt") + self.rfp.set_timeout(request.timeout) + self.rfp.read() + self._host = host + + ua = request.get_header("User-agent", "") + if self.rfp.can_fetch(ua, request.get_full_url()): + return request + else: + # XXX This should really have raised URLError. Too late now... + msg = "request disallowed by robots.txt" + raise RobotExclusionError( + request, + request.get_full_url(), + 403, msg, + self.http_response_class(StringIO()), StringIO(msg)) + + https_request = http_request + +class HTTPRefererProcessor(BaseHandler): + """Add Referer header to requests. + + This only makes sense if you use each RefererProcessor for a single + chain of requests only (so, for example, if you use a single + HTTPRefererProcessor to fetch a series of URLs extracted from a single + page, this will break). + + There's a proper implementation of this in mechanize.Browser. + + """ + def __init__(self): + self.referer = None + + def http_request(self, request): + if ((self.referer is not None) and + not request.has_header("Referer")): + request.add_unredirected_header("Referer", self.referer) + return request + + def http_response(self, request, response): + self.referer = response.geturl() + return response + + https_request = http_request + https_response = http_response + + +def clean_refresh_url(url): + # e.g. Firefox 1.5 does (something like) this + if ((url.startswith('"') and url.endswith('"')) or + (url.startswith("'") and url.endswith("'"))): + url = url[1:-1] + return _rfc3986.clean_url(url, "latin-1") # XXX encoding + +def parse_refresh_header(refresh): + """ + >>> parse_refresh_header("1; url=http://example.com/") + (1.0, 'http://example.com/') + >>> parse_refresh_header("1; url='http://example.com/'") + (1.0, 'http://example.com/') + >>> parse_refresh_header("1") + (1.0, None) + >>> parse_refresh_header("blah") + Traceback (most recent call last): + ValueError: invalid literal for float(): blah + + """ + + ii = refresh.find(";") + if ii != -1: + pause, newurl_spec = float(refresh[:ii]), refresh[ii+1:] + jj = newurl_spec.find("=") + key = None + if jj != -1: + key, newurl = newurl_spec[:jj], newurl_spec[jj+1:] + newurl = clean_refresh_url(newurl) + if key is None or key.strip().lower() != "url": + raise ValueError() + else: + pause, newurl = float(refresh), None + return pause, newurl + +class HTTPRefreshProcessor(BaseHandler): + """Perform HTTP Refresh redirections. + + Note that if a non-200 HTTP code has occurred (for example, a 30x + redirect), this processor will do nothing. + + By default, only zero-time Refresh headers are redirected. Use the + max_time attribute / constructor argument to allow Refresh with longer + pauses. Use the honor_time attribute / constructor argument to control + whether the requested pause is honoured (with a time.sleep()) or + skipped in favour of immediate redirection. + + Public attributes: + + max_time: see above + honor_time: see above + + """ + handler_order = 1000 + + def __init__(self, max_time=0, honor_time=True): + self.max_time = max_time + self.honor_time = honor_time + self._sleep = time.sleep + + def http_response(self, request, response): + code, msg, hdrs = response.code, response.msg, response.info() + + if code == 200 and hdrs.has_key("refresh"): + refresh = hdrs.getheaders("refresh")[0] + try: + pause, newurl = parse_refresh_header(refresh) + except ValueError: + debug("bad Refresh header: %r" % refresh) + return response + + if newurl is None: + newurl = response.geturl() + if (self.max_time is None) or (pause <= self.max_time): + if pause > 1E-3 and self.honor_time: + self._sleep(pause) + hdrs["location"] = newurl + # hardcoded http is NOT a bug + response = self.parent.error( + "http", request, response, + "refresh", msg, hdrs) + else: + debug("Refresh header ignored: %r" % refresh) + + return response + + https_response = http_response + +class HTTPErrorProcessor(BaseHandler): + """Process HTTP error responses. + + The purpose of this handler is to to allow other response processors a + look-in by removing the call to parent.error() from + AbstractHTTPHandler. + + For non-200 error codes, this just passes the job on to the + Handler.<proto>_error_<code> methods, via the OpenerDirector.error + method. Eventually, urllib2.HTTPDefaultErrorHandler will raise an + HTTPError if no other handler handles the error. + + """ + handler_order = 1000 # after all other processors + + def http_response(self, request, response): + code, msg, hdrs = response.code, response.msg, response.info() + + if code != 200: + # hardcoded http is NOT a bug + response = self.parent.error( + "http", request, response, code, msg, hdrs) + + return response + + https_response = http_response + + +class HTTPDefaultErrorHandler(BaseHandler): + def http_error_default(self, req, fp, code, msg, hdrs): + # why these error methods took the code, msg, headers args in the first + # place rather than a response object, I don't know, but to avoid + # multiple wrapping, we're discarding them + + if isinstance(fp, urllib2.HTTPError): + response = fp + else: + response = urllib2.HTTPError( + req.get_full_url(), code, msg, hdrs, fp) + assert code == response.code + assert msg == response.msg + assert hdrs == response.hdrs + raise response + + +class AbstractHTTPHandler(BaseHandler): + + def __init__(self, debuglevel=0): + self._debuglevel = debuglevel + + def set_http_debuglevel(self, level): + self._debuglevel = level + + def do_request_(self, request): + host = request.get_host() + if not host: + raise URLError('no host given') + + if request.has_data(): # POST + data = request.get_data() + if not request.has_header('Content-type'): + request.add_unredirected_header( + 'Content-type', + 'application/x-www-form-urlencoded') + if not request.has_header('Content-length'): + request.add_unredirected_header( + 'Content-length', '%d' % len(data)) + + scheme, sel = urllib.splittype(request.get_selector()) + sel_host, sel_path = urllib.splithost(sel) + if not request.has_header('Host'): + request.add_unredirected_header('Host', sel_host or host) + for name, value in self.parent.addheaders: + name = name.capitalize() + if not request.has_header(name): + request.add_unredirected_header(name, value) + + return request + + def do_open(self, http_class, req): + """Return an addinfourl object for the request, using http_class. + + http_class must implement the HTTPConnection API from httplib. + The addinfourl return value is a file-like object. It also + has methods and attributes including: + - info(): return a mimetools.Message object for the headers + - geturl(): return the original request URL + - code: HTTP status code + """ + host_port = req.get_host() + if not host_port: + raise URLError('no host given') + + try: + h = http_class(host_port, timeout=req.timeout) + except TypeError: + # Python < 2.6, no per-connection timeout support + h = http_class(host_port) + h.set_debuglevel(self._debuglevel) + + headers = dict(req.headers) + headers.update(req.unredirected_hdrs) + # We want to make an HTTP/1.1 request, but the addinfourl + # class isn't prepared to deal with a persistent connection. + # It will try to read all remaining data from the socket, + # which will block while the server waits for the next request. + # So make sure the connection gets closed after the (only) + # request. + headers["Connection"] = "close" + headers = dict( + [(name.title(), val) for name, val in headers.items()]) + try: + h.request(req.get_method(), req.get_selector(), req.data, headers) + r = h.getresponse() + except socket.error, err: # XXX what error? + raise URLError(err) + + # Pick apart the HTTPResponse object to get the addinfourl + # object initialized properly. + + # Wrap the HTTPResponse object in socket's file object adapter + # for Windows. That adapter calls recv(), so delegate recv() + # to read(). This weird wrapping allows the returned object to + # have readline() and readlines() methods. + + # XXX It might be better to extract the read buffering code + # out of socket._fileobject() and into a base class. + + r.recv = r.read + fp = create_readline_wrapper(r) + + resp = closeable_response(fp, r.msg, req.get_full_url(), + r.status, r.reason) + return resp + + +class HTTPHandler(AbstractHTTPHandler): + def http_open(self, req): + return self.do_open(httplib.HTTPConnection, req) + + http_request = AbstractHTTPHandler.do_request_ + +if hasattr(httplib, 'HTTPS'): + + class HTTPSConnectionFactory: + def __init__(self, key_file, cert_file): + self._key_file = key_file + self._cert_file = cert_file + def __call__(self, hostport): + return httplib.HTTPSConnection( + hostport, + key_file=self._key_file, cert_file=self._cert_file) + + class HTTPSHandler(AbstractHTTPHandler): + def __init__(self, client_cert_manager=None): + AbstractHTTPHandler.__init__(self) + self.client_cert_manager = client_cert_manager + + def https_open(self, req): + if self.client_cert_manager is not None: + key_file, cert_file = self.client_cert_manager.find_key_cert( + req.get_full_url()) + conn_factory = HTTPSConnectionFactory(key_file, cert_file) + else: + conn_factory = httplib.HTTPSConnection + return self.do_open(conn_factory, req) + + https_request = AbstractHTTPHandler.do_request_ diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_lwpcookiejar.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_lwpcookiejar.py new file mode 100644 index 0000000..f8d49cf --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_lwpcookiejar.py @@ -0,0 +1,185 @@ +"""Load / save to libwww-perl (LWP) format files. + +Actually, the format is slightly extended from that used by LWP's +(libwww-perl's) HTTP::Cookies, to avoid losing some RFC 2965 information +not recorded by LWP. + +It uses the version string "2.0", though really there isn't an LWP Cookies +2.0 format. This indicates that there is extra information in here +(domain_dot and port_spec) while still being compatible with libwww-perl, +I hope. + +Copyright 2002-2006 John J Lee <jjl@pobox.com> +Copyright 1997-1999 Gisle Aas (original libwww-perl code) + +This code is free software; you can redistribute it and/or modify it +under the terms of the BSD or ZPL 2.1 licenses (see the file +COPYING.txt included with the distribution). + +""" + +import time, re, logging + +from _clientcookie import reraise_unmasked_exceptions, FileCookieJar, Cookie, \ + MISSING_FILENAME_TEXT, LoadError +from _headersutil import join_header_words, split_header_words +from _util import iso2time, time2isoz + +debug = logging.getLogger("mechanize").debug + + +def lwp_cookie_str(cookie): + """Return string representation of Cookie in an the LWP cookie file format. + + Actually, the format is extended a bit -- see module docstring. + + """ + h = [(cookie.name, cookie.value), + ("path", cookie.path), + ("domain", cookie.domain)] + if cookie.port is not None: h.append(("port", cookie.port)) + if cookie.path_specified: h.append(("path_spec", None)) + if cookie.port_specified: h.append(("port_spec", None)) + if cookie.domain_initial_dot: h.append(("domain_dot", None)) + if cookie.secure: h.append(("secure", None)) + if cookie.expires: h.append(("expires", + time2isoz(float(cookie.expires)))) + if cookie.discard: h.append(("discard", None)) + if cookie.comment: h.append(("comment", cookie.comment)) + if cookie.comment_url: h.append(("commenturl", cookie.comment_url)) + if cookie.rfc2109: h.append(("rfc2109", None)) + + keys = cookie.nonstandard_attr_keys() + keys.sort() + for k in keys: + h.append((k, str(cookie.get_nonstandard_attr(k)))) + + h.append(("version", str(cookie.version))) + + return join_header_words([h]) + +class LWPCookieJar(FileCookieJar): + """ + The LWPCookieJar saves a sequence of"Set-Cookie3" lines. + "Set-Cookie3" is the format used by the libwww-perl libary, not known + to be compatible with any browser, but which is easy to read and + doesn't lose information about RFC 2965 cookies. + + Additional methods + + as_lwp_str(ignore_discard=True, ignore_expired=True) + + """ + + magic_re = r"^\#LWP-Cookies-(\d+\.\d+)" + + def as_lwp_str(self, ignore_discard=True, ignore_expires=True): + """Return cookies as a string of "\n"-separated "Set-Cookie3" headers. + + ignore_discard and ignore_expires: see docstring for FileCookieJar.save + + """ + now = time.time() + r = [] + for cookie in self: + if not ignore_discard and cookie.discard: + debug(" Not saving %s: marked for discard", cookie.name) + continue + if not ignore_expires and cookie.is_expired(now): + debug(" Not saving %s: expired", cookie.name) + continue + r.append("Set-Cookie3: %s" % lwp_cookie_str(cookie)) + return "\n".join(r+[""]) + + def save(self, filename=None, ignore_discard=False, ignore_expires=False): + if filename is None: + if self.filename is not None: filename = self.filename + else: raise ValueError(MISSING_FILENAME_TEXT) + + f = open(filename, "w") + try: + debug("Saving LWP cookies file") + # There really isn't an LWP Cookies 2.0 format, but this indicates + # that there is extra information in here (domain_dot and + # port_spec) while still being compatible with libwww-perl, I hope. + f.write("#LWP-Cookies-2.0\n") + f.write(self.as_lwp_str(ignore_discard, ignore_expires)) + finally: + f.close() + + def _really_load(self, f, filename, ignore_discard, ignore_expires): + magic = f.readline() + if not re.search(self.magic_re, magic): + msg = "%s does not seem to contain cookies" % filename + raise LoadError(msg) + + now = time.time() + + header = "Set-Cookie3:" + boolean_attrs = ("port_spec", "path_spec", "domain_dot", + "secure", "discard", "rfc2109") + value_attrs = ("version", + "port", "path", "domain", + "expires", + "comment", "commenturl") + + try: + while 1: + line = f.readline() + if line == "": break + if not line.startswith(header): + continue + line = line[len(header):].strip() + + for data in split_header_words([line]): + name, value = data[0] + standard = {} + rest = {} + for k in boolean_attrs: + standard[k] = False + for k, v in data[1:]: + if k is not None: + lc = k.lower() + else: + lc = None + # don't lose case distinction for unknown fields + if (lc in value_attrs) or (lc in boolean_attrs): + k = lc + if k in boolean_attrs: + if v is None: v = True + standard[k] = v + elif k in value_attrs: + standard[k] = v + else: + rest[k] = v + + h = standard.get + expires = h("expires") + discard = h("discard") + if expires is not None: + expires = iso2time(expires) + if expires is None: + discard = True + domain = h("domain") + domain_specified = domain.startswith(".") + c = Cookie(h("version"), name, value, + h("port"), h("port_spec"), + domain, domain_specified, h("domain_dot"), + h("path"), h("path_spec"), + h("secure"), + expires, + discard, + h("comment"), + h("commenturl"), + rest, + h("rfc2109"), + ) + if not ignore_discard and c.discard: + continue + if not ignore_expires and c.is_expired(now): + continue + self.set_cookie(c) + except: + reraise_unmasked_exceptions((IOError,)) + raise LoadError("invalid Set-Cookie3 format file %s" % filename) + diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_mechanize.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_mechanize.py new file mode 100644 index 0000000..ad729c9 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_mechanize.py @@ -0,0 +1,676 @@ +"""Stateful programmatic WWW navigation, after Perl's WWW::Mechanize. + +Copyright 2003-2006 John J. Lee <jjl@pobox.com> +Copyright 2003 Andy Lester (original Perl code) + +This code is free software; you can redistribute it and/or modify it +under the terms of the BSD or ZPL 2.1 licenses (see the file COPYING.txt +included with the distribution). + +""" + +import urllib2, copy, re, os, urllib + + +from _html import DefaultFactory +import _response +import _request +import _rfc3986 +import _sockettimeout +from _useragent import UserAgentBase + +__version__ = (0, 1, 11, None, None) # 0.1.11 + +class BrowserStateError(Exception): pass +class LinkNotFoundError(Exception): pass +class FormNotFoundError(Exception): pass + + +def sanepathname2url(path): + urlpath = urllib.pathname2url(path) + if os.name == "nt" and urlpath.startswith("///"): + urlpath = urlpath[2:] + # XXX don't ask me about the mac... + return urlpath + + +class History: + """ + + Though this will become public, the implied interface is not yet stable. + + """ + def __init__(self): + self._history = [] # LIFO + def add(self, request, response): + self._history.append((request, response)) + def back(self, n, _response): + response = _response # XXX move Browser._response into this class? + while n > 0 or response is None: + try: + request, response = self._history.pop() + except IndexError: + raise BrowserStateError("already at start of history") + n -= 1 + return request, response + def clear(self): + del self._history[:] + def close(self): + for request, response in self._history: + if response is not None: + response.close() + del self._history[:] + + +class HTTPRefererProcessor(urllib2.BaseHandler): + def http_request(self, request): + # See RFC 2616 14.36. The only times we know the source of the + # request URI has a URI associated with it are redirect, and + # Browser.click() / Browser.submit() / Browser.follow_link(). + # Otherwise, it's the user's job to add any Referer header before + # .open()ing. + if hasattr(request, "redirect_dict"): + request = self.parent._add_referer_header( + request, origin_request=False) + return request + + https_request = http_request + + +class Browser(UserAgentBase): + """Browser-like class with support for history, forms and links. + + BrowserStateError is raised whenever the browser is in the wrong state to + complete the requested operation - eg., when .back() is called when the + browser history is empty, or when .follow_link() is called when the current + response does not contain HTML data. + + Public attributes: + + request: current request (mechanize.Request or urllib2.Request) + form: currently selected form (see .select_form()) + + """ + + handler_classes = copy.copy(UserAgentBase.handler_classes) + handler_classes["_referer"] = HTTPRefererProcessor + default_features = copy.copy(UserAgentBase.default_features) + default_features.append("_referer") + + def __init__(self, + factory=None, + history=None, + request_class=None, + ): + """ + + Only named arguments should be passed to this constructor. + + factory: object implementing the mechanize.Factory interface. + history: object implementing the mechanize.History interface. Note + this interface is still experimental and may change in future. + request_class: Request class to use. Defaults to mechanize.Request + by default for Pythons older than 2.4, urllib2.Request otherwise. + + The Factory and History objects passed in are 'owned' by the Browser, + so they should not be shared across Browsers. In particular, + factory.set_response() should not be called except by the owning + Browser itself. + + Note that the supplied factory's request_class is overridden by this + constructor, to ensure only one Request class is used. + + """ + self._handle_referer = True + + if history is None: + history = History() + self._history = history + + if request_class is None: + if not hasattr(urllib2.Request, "add_unredirected_header"): + request_class = _request.Request + else: + request_class = urllib2.Request # Python >= 2.4 + + if factory is None: + factory = DefaultFactory() + factory.set_request_class(request_class) + self._factory = factory + self.request_class = request_class + + self.request = None + self._set_response(None, False) + + # do this last to avoid __getattr__ problems + UserAgentBase.__init__(self) + + def close(self): + UserAgentBase.close(self) + if self._response is not None: + self._response.close() + if self._history is not None: + self._history.close() + self._history = None + + # make use after .close easy to spot + self.form = None + self.request = self._response = None + self.request = self.response = self.set_response = None + self.geturl = self.reload = self.back = None + self.clear_history = self.set_cookie = self.links = self.forms = None + self.viewing_html = self.encoding = self.title = None + self.select_form = self.click = self.submit = self.click_link = None + self.follow_link = self.find_link = None + + def set_handle_referer(self, handle): + """Set whether to add Referer header to each request.""" + self._set_handler("_referer", handle) + self._handle_referer = bool(handle) + + def _add_referer_header(self, request, origin_request=True): + if self.request is None: + return request + scheme = request.get_type() + original_scheme = self.request.get_type() + if scheme not in ["http", "https"]: + return request + if not origin_request and not self.request.has_header("Referer"): + return request + + if (self._handle_referer and + original_scheme in ["http", "https"] and + not (original_scheme == "https" and scheme != "https")): + # strip URL fragment (RFC 2616 14.36) + parts = _rfc3986.urlsplit(self.request.get_full_url()) + parts = parts[:-1]+(None,) + referer = _rfc3986.urlunsplit(parts) + request.add_unredirected_header("Referer", referer) + return request + + def open_novisit(self, url, data=None, + timeout=_sockettimeout._GLOBAL_DEFAULT_TIMEOUT): + """Open a URL without visiting it. + + Browser state (including request, response, history, forms and links) + is left unchanged by calling this function. + + The interface is the same as for .open(). + + This is useful for things like fetching images. + + See also .retrieve(). + + """ + return self._mech_open(url, data, visit=False, timeout=timeout) + + def open(self, url, data=None, + timeout=_sockettimeout._GLOBAL_DEFAULT_TIMEOUT): + return self._mech_open(url, data, timeout=timeout) + + def _mech_open(self, url, data=None, update_history=True, visit=None, + timeout=_sockettimeout._GLOBAL_DEFAULT_TIMEOUT): + try: + url.get_full_url + except AttributeError: + # string URL -- convert to absolute URL if required + scheme, authority = _rfc3986.urlsplit(url)[:2] + if scheme is None: + # relative URL + if self._response is None: + raise BrowserStateError( + "can't fetch relative reference: " + "not viewing any document") + url = _rfc3986.urljoin(self._response.geturl(), url) + + request = self._request(url, data, visit, timeout) + visit = request.visit + if visit is None: + visit = True + + if visit: + self._visit_request(request, update_history) + + success = True + try: + response = UserAgentBase.open(self, request, data) + except urllib2.HTTPError, error: + success = False + if error.fp is None: # not a response + raise + response = error +## except (IOError, socket.error, OSError), error: +## # Yes, urllib2 really does raise all these :-(( +## # See test_urllib2.py for examples of socket.gaierror and OSError, +## # plus note that FTPHandler raises IOError. +## # XXX I don't seem to have an example of exactly socket.error being +## # raised, only socket.gaierror... +## # I don't want to start fixing these here, though, since this is a +## # subclass of OpenerDirector, and it would break old code. Even in +## # Python core, a fix would need some backwards-compat. hack to be +## # acceptable. +## raise + + if visit: + self._set_response(response, False) + response = copy.copy(self._response) + elif response is not None: + response = _response.upgrade_response(response) + + if not success: + raise response + return response + + def __str__(self): + text = [] + text.append("<%s " % self.__class__.__name__) + if self._response: + text.append("visiting %s" % self._response.geturl()) + else: + text.append("(not visiting a URL)") + if self.form: + text.append("\n selected form:\n %s\n" % str(self.form)) + text.append(">") + return "".join(text) + + def response(self): + """Return a copy of the current response. + + The returned object has the same interface as the object returned by + .open() (or urllib2.urlopen()). + + """ + return copy.copy(self._response) + + def open_local_file(self, filename): + path = sanepathname2url(os.path.abspath(filename)) + url = 'file://'+path + return self.open(url) + + def set_response(self, response): + """Replace current response with (a copy of) response. + + response may be None. + + This is intended mostly for HTML-preprocessing. + """ + self._set_response(response, True) + + def _set_response(self, response, close_current): + # sanity check, necessary but far from sufficient + if not (response is None or + (hasattr(response, "info") and hasattr(response, "geturl") and + hasattr(response, "read") + ) + ): + raise ValueError("not a response object") + + self.form = None + if response is not None: + response = _response.upgrade_response(response) + if close_current and self._response is not None: + self._response.close() + self._response = response + self._factory.set_response(response) + + def visit_response(self, response, request=None): + """Visit the response, as if it had been .open()ed. + + Unlike .set_response(), this updates history rather than replacing the + current response. + """ + if request is None: + request = _request.Request(response.geturl()) + self._visit_request(request, True) + self._set_response(response, False) + + def _visit_request(self, request, update_history): + if self._response is not None: + self._response.close() + if self.request is not None and update_history: + self._history.add(self.request, self._response) + self._response = None + # we want self.request to be assigned even if UserAgentBase.open + # fails + self.request = request + + def geturl(self): + """Get URL of current document.""" + if self._response is None: + raise BrowserStateError("not viewing any document") + return self._response.geturl() + + def reload(self): + """Reload current document, and return response object.""" + if self.request is None: + raise BrowserStateError("no URL has yet been .open()ed") + if self._response is not None: + self._response.close() + return self._mech_open(self.request, update_history=False) + + def back(self, n=1): + """Go back n steps in history, and return response object. + + n: go back this number of steps (default 1 step) + + """ + if self._response is not None: + self._response.close() + self.request, response = self._history.back(n, self._response) + self.set_response(response) + if not response.read_complete: + return self.reload() + return copy.copy(response) + + def clear_history(self): + self._history.clear() + + def set_cookie(self, cookie_string): + """Request to set a cookie. + + Note that it is NOT necessary to call this method under ordinary + circumstances: cookie handling is normally entirely automatic. The + intended use case is rather to simulate the setting of a cookie by + client script in a web page (e.g. JavaScript). In that case, use of + this method is necessary because mechanize currently does not support + JavaScript, VBScript, etc. + + The cookie is added in the same way as if it had arrived with the + current response, as a result of the current request. This means that, + for example, if it is not appropriate to set the cookie based on the + current request, no cookie will be set. + + The cookie will be returned automatically with subsequent responses + made by the Browser instance whenever that's appropriate. + + cookie_string should be a valid value of the Set-Cookie header. + + For example: + + browser.set_cookie( + "sid=abcdef; expires=Wednesday, 09-Nov-06 23:12:40 GMT") + + Currently, this method does not allow for adding RFC 2986 cookies. + This limitation will be lifted if anybody requests it. + + """ + if self._response is None: + raise BrowserStateError("not viewing any document") + if self.request.get_type() not in ["http", "https"]: + raise BrowserStateError("can't set cookie for non-HTTP/HTTPS " + "transactions") + cookiejar = self._ua_handlers["_cookies"].cookiejar + response = self.response() # copy + headers = response.info() + headers["Set-cookie"] = cookie_string + cookiejar.extract_cookies(response, self.request) + + def links(self, **kwds): + """Return iterable over links (mechanize.Link objects).""" + if not self.viewing_html(): + raise BrowserStateError("not viewing HTML") + links = self._factory.links() + if kwds: + return self._filter_links(links, **kwds) + else: + return links + + def forms(self): + """Return iterable over forms. + + The returned form objects implement the ClientForm.HTMLForm interface. + + """ + if not self.viewing_html(): + raise BrowserStateError("not viewing HTML") + return self._factory.forms() + + def global_form(self): + """Return the global form object, or None if the factory implementation + did not supply one. + + The "global" form object contains all controls that are not descendants + of any FORM element. + + The returned form object implements the ClientForm.HTMLForm interface. + + This is a separate method since the global form is not regarded as part + of the sequence of forms in the document -- mostly for + backwards-compatibility. + + """ + if not self.viewing_html(): + raise BrowserStateError("not viewing HTML") + return self._factory.global_form + + def viewing_html(self): + """Return whether the current response contains HTML data.""" + if self._response is None: + raise BrowserStateError("not viewing any document") + return self._factory.is_html + + def encoding(self): + if self._response is None: + raise BrowserStateError("not viewing any document") + return self._factory.encoding + + def title(self): + r"""Return title, or None if there is no title element in the document. + + Treatment of any tag children of attempts to follow Firefox and IE + (currently, tags are preserved). + + """ + if not self.viewing_html(): + raise BrowserStateError("not viewing HTML") + return self._factory.title + + def select_form(self, name=None, predicate=None, nr=None): + """Select an HTML form for input. + + This is a bit like giving a form the "input focus" in a browser. + + If a form is selected, the Browser object supports the HTMLForm + interface, so you can call methods like .set_value(), .set(), and + .click(). + + Another way to select a form is to assign to the .form attribute. The + form assigned should be one of the objects returned by the .forms() + method. + + At least one of the name, predicate and nr arguments must be supplied. + If no matching form is found, mechanize.FormNotFoundError is raised. + + If name is specified, then the form must have the indicated name. + + If predicate is specified, then the form must match that function. The + predicate function is passed the HTMLForm as its single argument, and + should return a boolean value indicating whether the form matched. + + nr, if supplied, is the sequence number of the form (where 0 is the + first). Note that control 0 is the first form matching all the other + arguments (if supplied); it is not necessarily the first control in the + form. The "global form" (consisting of all form controls not contained + in any FORM element) is considered not to be part of this sequence and + to have no name, so will not be matched unless both name and nr are + None. + + """ + if not self.viewing_html(): + raise BrowserStateError("not viewing HTML") + if (name is None) and (predicate is None) and (nr is None): + raise ValueError( + "at least one argument must be supplied to specify form") + + global_form = self._factory.global_form + if nr is None and name is None and \ + predicate is not None and predicate(global_form): + self.form = global_form + return + + orig_nr = nr + for form in self.forms(): + if name is not None and name != form.name: + continue + if predicate is not None and not predicate(form): + continue + if nr: + nr -= 1 + continue + self.form = form + break # success + else: + # failure + description = [] + if name is not None: description.append("name '%s'" % name) + if predicate is not None: + description.append("predicate %s" % predicate) + if orig_nr is not None: description.append("nr %d" % orig_nr) + description = ", ".join(description) + raise FormNotFoundError("no form matching "+description) + + def click(self, *args, **kwds): + """See ClientForm.HTMLForm.click for documentation.""" + if not self.viewing_html(): + raise BrowserStateError("not viewing HTML") + request = self.form.click(*args, **kwds) + return self._add_referer_header(request) + + def submit(self, *args, **kwds): + """Submit current form. + + Arguments are as for ClientForm.HTMLForm.click(). + + Return value is same as for Browser.open(). + + """ + return self.open(self.click(*args, **kwds)) + + def click_link(self, link=None, **kwds): + """Find a link and return a Request object for it. + + Arguments are as for .find_link(), except that a link may be supplied + as the first argument. + + """ + if not self.viewing_html(): + raise BrowserStateError("not viewing HTML") + if not link: + link = self.find_link(**kwds) + else: + if kwds: + raise ValueError( + "either pass a Link, or keyword arguments, not both") + request = self.request_class(link.absolute_url) + return self._add_referer_header(request) + + def follow_link(self, link=None, **kwds): + """Find a link and .open() it. + + Arguments are as for .click_link(). + + Return value is same as for Browser.open(). + + """ + return self.open(self.click_link(link, **kwds)) + + def find_link(self, **kwds): + """Find a link in current page. + + Links are returned as mechanize.Link objects. + + # Return third link that .search()-matches the regexp "python" + # (by ".search()-matches", I mean that the regular expression method + # .search() is used, rather than .match()). + find_link(text_regex=re.compile("python"), nr=2) + + # Return first http link in the current page that points to somewhere + # on python.org whose link text (after tags have been removed) is + # exactly "monty python". + find_link(text="monty python", + url_regex=re.compile("http.*python.org")) + + # Return first link with exactly three HTML attributes. + find_link(predicate=lambda link: len(link.attrs) == 3) + + Links include anchors (<a>), image maps (<area>), and frames (<frame>, + <iframe>). + + All arguments must be passed by keyword, not position. Zero or more + arguments may be supplied. In order to find a link, all arguments + supplied must match. + + If a matching link is not found, mechanize.LinkNotFoundError is raised. + + text: link text between link tags: eg. <a href="blah">this bit</a> (as + returned by pullparser.get_compressed_text(), ie. without tags but + with opening tags "textified" as per the pullparser docs) must compare + equal to this argument, if supplied + text_regex: link text between tag (as defined above) must match the + regular expression object or regular expression string passed as this + argument, if supplied + name, name_regex: as for text and text_regex, but matched against the + name HTML attribute of the link tag + url, url_regex: as for text and text_regex, but matched against the + URL of the link tag (note this matches against Link.url, which is a + relative or absolute URL according to how it was written in the HTML) + tag: element name of opening tag, eg. "a" + predicate: a function taking a Link object as its single argument, + returning a boolean result, indicating whether the links + nr: matches the nth link that matches all other criteria (default 0) + + """ + try: + return self._filter_links(self._factory.links(), **kwds).next() + except StopIteration: + raise LinkNotFoundError() + + def __getattr__(self, name): + # pass through ClientForm / DOMForm methods and attributes + form = self.__dict__.get("form") + if form is None: + raise AttributeError( + "%s instance has no attribute %s (perhaps you forgot to " + ".select_form()?)" % (self.__class__, name)) + return getattr(form, name) + + def _filter_links(self, links, + text=None, text_regex=None, + name=None, name_regex=None, + url=None, url_regex=None, + tag=None, + predicate=None, + nr=0 + ): + if not self.viewing_html(): + raise BrowserStateError("not viewing HTML") + + found_links = [] + orig_nr = nr + + for link in links: + if url is not None and url != link.url: + continue + if url_regex is not None and not re.search(url_regex, link.url): + continue + if (text is not None and + (link.text is None or text != link.text)): + continue + if (text_regex is not None and + (link.text is None or not re.search(text_regex, link.text))): + continue + if name is not None and name != dict(link.attrs).get("name"): + continue + if name_regex is not None: + link_name = dict(link.attrs).get("name") + if link_name is None or not re.search(name_regex, link_name): + continue + if tag is not None and tag != link.tag: + continue + if predicate is not None and not predicate(link): + continue + if nr: + nr -= 1 + continue + yield link + nr = orig_nr diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_mozillacookiejar.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_mozillacookiejar.py new file mode 100644 index 0000000..51e81bb --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_mozillacookiejar.py @@ -0,0 +1,161 @@ +"""Mozilla / Netscape cookie loading / saving. + +Copyright 2002-2006 John J Lee <jjl@pobox.com> +Copyright 1997-1999 Gisle Aas (original libwww-perl code) + +This code is free software; you can redistribute it and/or modify it +under the terms of the BSD or ZPL 2.1 licenses (see the file +COPYING.txt included with the distribution). + +""" + +import re, time, logging + +from _clientcookie import reraise_unmasked_exceptions, FileCookieJar, Cookie, \ + MISSING_FILENAME_TEXT, LoadError +debug = logging.getLogger("ClientCookie").debug + + +class MozillaCookieJar(FileCookieJar): + """ + + WARNING: you may want to backup your browser's cookies file if you use + this class to save cookies. I *think* it works, but there have been + bugs in the past! + + This class differs from CookieJar only in the format it uses to save and + load cookies to and from a file. This class uses the Mozilla/Netscape + `cookies.txt' format. lynx uses this file format, too. + + Don't expect cookies saved while the browser is running to be noticed by + the browser (in fact, Mozilla on unix will overwrite your saved cookies if + you change them on disk while it's running; on Windows, you probably can't + save at all while the browser is running). + + Note that the Mozilla/Netscape format will downgrade RFC2965 cookies to + Netscape cookies on saving. + + In particular, the cookie version and port number information is lost, + together with information about whether or not Path, Port and Discard were + specified by the Set-Cookie2 (or Set-Cookie) header, and whether or not the + domain as set in the HTTP header started with a dot (yes, I'm aware some + domains in Netscape files start with a dot and some don't -- trust me, you + really don't want to know any more about this). + + Note that though Mozilla and Netscape use the same format, they use + slightly different headers. The class saves cookies using the Netscape + header by default (Mozilla can cope with that). + + """ + magic_re = "#( Netscape)? HTTP Cookie File" + header = """\ + # Netscape HTTP Cookie File + # http://www.netscape.com/newsref/std/cookie_spec.html + # This is a generated file! Do not edit. + +""" + + def _really_load(self, f, filename, ignore_discard, ignore_expires): + now = time.time() + + magic = f.readline() + if not re.search(self.magic_re, magic): + f.close() + raise LoadError( + "%s does not look like a Netscape format cookies file" % + filename) + + try: + while 1: + line = f.readline() + if line == "": break + + # last field may be absent, so keep any trailing tab + if line.endswith("\n"): line = line[:-1] + + # skip comments and blank lines XXX what is $ for? + if (line.strip().startswith("#") or + line.strip().startswith("$") or + line.strip() == ""): + continue + + domain, domain_specified, path, secure, expires, name, value = \ + line.split("\t", 6) + secure = (secure == "TRUE") + domain_specified = (domain_specified == "TRUE") + if name == "": + name = value + value = None + + initial_dot = domain.startswith(".") + if domain_specified != initial_dot: + raise LoadError("domain and domain specified flag don't " + "match in %s: %s" % (filename, line)) + + discard = False + if expires == "": + expires = None + discard = True + + # assume path_specified is false + c = Cookie(0, name, value, + None, False, + domain, domain_specified, initial_dot, + path, False, + secure, + expires, + discard, + None, + None, + {}) + if not ignore_discard and c.discard: + continue + if not ignore_expires and c.is_expired(now): + continue + self.set_cookie(c) + + except: + reraise_unmasked_exceptions((IOError, LoadError)) + raise LoadError("invalid Netscape format file %s: %s" % + (filename, line)) + + def save(self, filename=None, ignore_discard=False, ignore_expires=False): + if filename is None: + if self.filename is not None: filename = self.filename + else: raise ValueError(MISSING_FILENAME_TEXT) + + f = open(filename, "w") + try: + debug("Saving Netscape cookies.txt file") + f.write(self.header) + now = time.time() + for cookie in self: + if not ignore_discard and cookie.discard: + debug(" Not saving %s: marked for discard", cookie.name) + continue + if not ignore_expires and cookie.is_expired(now): + debug(" Not saving %s: expired", cookie.name) + continue + if cookie.secure: secure = "TRUE" + else: secure = "FALSE" + if cookie.domain.startswith("."): initial_dot = "TRUE" + else: initial_dot = "FALSE" + if cookie.expires is not None: + expires = str(cookie.expires) + else: + expires = "" + if cookie.value is None: + # cookies.txt regards 'Set-Cookie: foo' as a cookie + # with no name, whereas cookielib regards it as a + # cookie with no value. + name = "" + value = cookie.name + else: + name = cookie.name + value = cookie.value + f.write( + "\t".join([cookie.domain, initial_dot, cookie.path, + secure, expires, name, value])+ + "\n") + finally: + f.close() diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_msiecookiejar.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_msiecookiejar.py new file mode 100644 index 0000000..1057811 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_msiecookiejar.py @@ -0,0 +1,388 @@ +"""Microsoft Internet Explorer cookie loading on Windows. + +Copyright 2002-2003 Johnny Lee <typo_pl@hotmail.com> (MSIE Perl code) +Copyright 2002-2006 John J Lee <jjl@pobox.com> (The Python port) + +This code is free software; you can redistribute it and/or modify it +under the terms of the BSD or ZPL 2.1 licenses (see the file +COPYING.txt included with the distribution). + +""" + +# XXX names and comments are not great here + +import os, re, time, struct, logging +if os.name == "nt": + import _winreg + +from _clientcookie import FileCookieJar, CookieJar, Cookie, \ + MISSING_FILENAME_TEXT, LoadError + +debug = logging.getLogger("mechanize").debug + + +def regload(path, leaf): + key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, path, 0, + _winreg.KEY_ALL_ACCESS) + try: + value = _winreg.QueryValueEx(key, leaf)[0] + except WindowsError: + value = None + return value + +WIN32_EPOCH = 0x019db1ded53e8000L # 1970 Jan 01 00:00:00 in Win32 FILETIME + +def epoch_time_offset_from_win32_filetime(filetime): + """Convert from win32 filetime to seconds-since-epoch value. + + MSIE stores create and expire times as Win32 FILETIME, which is 64 + bits of 100 nanosecond intervals since Jan 01 1601. + + mechanize expects time in 32-bit value expressed in seconds since the + epoch (Jan 01 1970). + + """ + if filetime < WIN32_EPOCH: + raise ValueError("filetime (%d) is before epoch (%d)" % + (filetime, WIN32_EPOCH)) + + return divmod((filetime - WIN32_EPOCH), 10000000L)[0] + +def binary_to_char(c): return "%02X" % ord(c) +def binary_to_str(d): return "".join(map(binary_to_char, list(d))) + +class MSIEBase: + magic_re = re.compile(r"Client UrlCache MMF Ver \d\.\d.*") + padding = "\x0d\xf0\xad\x0b" + + msie_domain_re = re.compile(r"^([^/]+)(/.*)$") + cookie_re = re.compile("Cookie\:.+\@([\x21-\xFF]+).*?" + "(.+\@[\x21-\xFF]+\.txt)") + + # path under HKEY_CURRENT_USER from which to get location of index.dat + reg_path = r"software\microsoft\windows" \ + r"\currentversion\explorer\shell folders" + reg_key = "Cookies" + + def __init__(self): + self._delayload_domains = {} + + def _delayload_domain(self, domain): + # if necessary, lazily load cookies for this domain + delayload_info = self._delayload_domains.get(domain) + if delayload_info is not None: + cookie_file, ignore_discard, ignore_expires = delayload_info + try: + self.load_cookie_data(cookie_file, + ignore_discard, ignore_expires) + except (LoadError, IOError): + debug("error reading cookie file, skipping: %s", cookie_file) + else: + del self._delayload_domains[domain] + + def _load_cookies_from_file(self, filename): + debug("Loading MSIE cookies file: %s", filename) + cookies = [] + + cookies_fh = open(filename) + + try: + while 1: + key = cookies_fh.readline() + if key == "": break + + rl = cookies_fh.readline + def getlong(rl=rl): return long(rl().rstrip()) + def getstr(rl=rl): return rl().rstrip() + + key = key.rstrip() + value = getstr() + domain_path = getstr() + flags = getlong() # 0x2000 bit is for secure I think + lo_expire = getlong() + hi_expire = getlong() + lo_create = getlong() + hi_create = getlong() + sep = getstr() + + if "" in (key, value, domain_path, flags, hi_expire, lo_expire, + hi_create, lo_create, sep) or (sep != "*"): + break + + m = self.msie_domain_re.search(domain_path) + if m: + domain = m.group(1) + path = m.group(2) + + cookies.append({"KEY": key, "VALUE": value, + "DOMAIN": domain, "PATH": path, + "FLAGS": flags, "HIXP": hi_expire, + "LOXP": lo_expire, "HICREATE": hi_create, + "LOCREATE": lo_create}) + finally: + cookies_fh.close() + + return cookies + + def load_cookie_data(self, filename, + ignore_discard=False, ignore_expires=False): + """Load cookies from file containing actual cookie data. + + Old cookies are kept unless overwritten by newly loaded ones. + + You should not call this method if the delayload attribute is set. + + I think each of these files contain all cookies for one user, domain, + and path. + + filename: file containing cookies -- usually found in a file like + C:\WINNT\Profiles\joe\Cookies\joe@blah[1].txt + + """ + now = int(time.time()) + + cookie_data = self._load_cookies_from_file(filename) + + for cookie in cookie_data: + flags = cookie["FLAGS"] + secure = ((flags & 0x2000) != 0) + filetime = (cookie["HIXP"] << 32) + cookie["LOXP"] + expires = epoch_time_offset_from_win32_filetime(filetime) + if expires < now: + discard = True + else: + discard = False + domain = cookie["DOMAIN"] + initial_dot = domain.startswith(".") + if initial_dot: + domain_specified = True + else: + # MSIE 5 does not record whether the domain cookie-attribute + # was specified. + # Assuming it wasn't is conservative, because with strict + # domain matching this will match less frequently; with regular + # Netscape tail-matching, this will match at exactly the same + # times that domain_specified = True would. It also means we + # don't have to prepend a dot to achieve consistency with our + # own & Mozilla's domain-munging scheme. + domain_specified = False + + # assume path_specified is false + # XXX is there other stuff in here? -- eg. comment, commentURL? + c = Cookie(0, + cookie["KEY"], cookie["VALUE"], + None, False, + domain, domain_specified, initial_dot, + cookie["PATH"], False, + secure, + expires, + discard, + None, + None, + {"flags": flags}) + if not ignore_discard and c.discard: + continue + if not ignore_expires and c.is_expired(now): + continue + CookieJar.set_cookie(self, c) + + def load_from_registry(self, ignore_discard=False, ignore_expires=False, + username=None): + """ + username: only required on win9x + + """ + cookies_dir = regload(self.reg_path, self.reg_key) + filename = os.path.normpath(os.path.join(cookies_dir, "INDEX.DAT")) + self.load(filename, ignore_discard, ignore_expires, username) + + def _really_load(self, index, filename, ignore_discard, ignore_expires, + username): + now = int(time.time()) + + if username is None: + username = os.environ['USERNAME'].lower() + + cookie_dir = os.path.dirname(filename) + + data = index.read(256) + if len(data) != 256: + raise LoadError("%s file is too short" % filename) + + # Cookies' index.dat file starts with 32 bytes of signature + # followed by an offset to the first record, stored as a little- + # endian DWORD. + sig, size, data = data[:32], data[32:36], data[36:] + size = struct.unpack("<L", size)[0] + + # check that sig is valid + if not self.magic_re.match(sig) or size != 0x4000: + raise LoadError("%s ['%s' %s] does not seem to contain cookies" % + (str(filename), sig, size)) + + # skip to start of first record + index.seek(size, 0) + + sector = 128 # size of sector in bytes + + while 1: + data = "" + + # Cookies are usually in two contiguous sectors, so read in two + # sectors and adjust if not a Cookie. + to_read = 2 * sector + d = index.read(to_read) + if len(d) != to_read: + break + data = data + d + + # Each record starts with a 4-byte signature and a count + # (little-endian DWORD) of sectors for the record. + sig, size, data = data[:4], data[4:8], data[8:] + size = struct.unpack("<L", size)[0] + + to_read = (size - 2) * sector + +## from urllib import quote +## print "data", quote(data) +## print "sig", quote(sig) +## print "size in sectors", size +## print "size in bytes", size*sector +## print "size in units of 16 bytes", (size*sector) / 16 +## print "size to read in bytes", to_read +## print + + if sig != "URL ": + assert sig in ("HASH", "LEAK", \ + self.padding, "\x00\x00\x00\x00"), \ + "unrecognized MSIE index.dat record: %s" % \ + binary_to_str(sig) + if sig == "\x00\x00\x00\x00": + # assume we've got all the cookies, and stop + break + if sig == self.padding: + continue + # skip the rest of this record + assert to_read >= 0 + if size != 2: + assert to_read != 0 + index.seek(to_read, 1) + continue + + # read in rest of record if necessary + if size > 2: + more_data = index.read(to_read) + if len(more_data) != to_read: break + data = data + more_data + + cookie_re = ("Cookie\:%s\@([\x21-\xFF]+).*?" % username + + "(%s\@[\x21-\xFF]+\.txt)" % username) + m = re.search(cookie_re, data, re.I) + if m: + cookie_file = os.path.join(cookie_dir, m.group(2)) + if not self.delayload: + try: + self.load_cookie_data(cookie_file, + ignore_discard, ignore_expires) + except (LoadError, IOError): + debug("error reading cookie file, skipping: %s", + cookie_file) + else: + domain = m.group(1) + i = domain.find("/") + if i != -1: + domain = domain[:i] + + self._delayload_domains[domain] = ( + cookie_file, ignore_discard, ignore_expires) + + +class MSIECookieJar(MSIEBase, FileCookieJar): + """FileCookieJar that reads from the Windows MSIE cookies database. + + MSIECookieJar can read the cookie files of Microsoft Internet Explorer + (MSIE) for Windows version 5 on Windows NT and version 6 on Windows XP and + Windows 98. Other configurations may also work, but are untested. Saving + cookies in MSIE format is NOT supported. If you save cookies, they'll be + in the usual Set-Cookie3 format, which you can read back in using an + instance of the plain old CookieJar class. Don't save using the same + filename that you loaded cookies from, because you may succeed in + clobbering your MSIE cookies index file! + + You should be able to have LWP share Internet Explorer's cookies like + this (note you need to supply a username to load_from_registry if you're on + Windows 9x or Windows ME): + + cj = MSIECookieJar(delayload=1) + # find cookies index file in registry and load cookies from it + cj.load_from_registry() + opener = mechanize.build_opener(mechanize.HTTPCookieProcessor(cj)) + response = opener.open("http://example.com/") + + Iterating over a delayloaded MSIECookieJar instance will not cause any + cookies to be read from disk. To force reading of all cookies from disk, + call read_all_cookies. Note that the following methods iterate over self: + clear_temporary_cookies, clear_expired_cookies, __len__, __repr__, __str__ + and as_string. + + Additional methods: + + load_from_registry(ignore_discard=False, ignore_expires=False, + username=None) + load_cookie_data(filename, ignore_discard=False, ignore_expires=False) + read_all_cookies() + + """ + def __init__(self, filename=None, delayload=False, policy=None): + MSIEBase.__init__(self) + FileCookieJar.__init__(self, filename, delayload, policy) + + def set_cookie(self, cookie): + if self.delayload: + self._delayload_domain(cookie.domain) + CookieJar.set_cookie(self, cookie) + + def _cookies_for_request(self, request): + """Return a list of cookies to be returned to server.""" + domains = self._cookies.copy() + domains.update(self._delayload_domains) + domains = domains.keys() + + cookies = [] + for domain in domains: + cookies.extend(self._cookies_for_domain(domain, request)) + return cookies + + def _cookies_for_domain(self, domain, request): + if not self._policy.domain_return_ok(domain, request): + return [] + debug("Checking %s for cookies to return", domain) + if self.delayload: + self._delayload_domain(domain) + return CookieJar._cookies_for_domain(self, domain, request) + + def read_all_cookies(self): + """Eagerly read in all cookies.""" + if self.delayload: + for domain in self._delayload_domains.keys(): + self._delayload_domain(domain) + + def load(self, filename, ignore_discard=False, ignore_expires=False, + username=None): + """Load cookies from an MSIE 'index.dat' cookies index file. + + filename: full path to cookie index file + username: only required on win9x + + """ + if filename is None: + if self.filename is not None: filename = self.filename + else: raise ValueError(MISSING_FILENAME_TEXT) + + index = open(filename, "rb") + + try: + self._really_load(index, filename, ignore_discard, ignore_expires, + username) + finally: + index.close() diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_opener.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_opener.py new file mode 100644 index 0000000..d94eacf --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_opener.py @@ -0,0 +1,436 @@ +"""Integration with Python standard library module urllib2: OpenerDirector +class. + +Copyright 2004-2006 John J Lee <jjl@pobox.com> + +This code is free software; you can redistribute it and/or modify it +under the terms of the BSD or ZPL 2.1 licenses (see the file +COPYING.txt included with the distribution). + +""" + +import os, urllib2, bisect, httplib, types, tempfile +try: + import threading as _threading +except ImportError: + import dummy_threading as _threading +try: + set +except NameError: + import sets + set = sets.Set + +import _file +import _http +from _request import Request +import _response +import _rfc3986 +import _sockettimeout +import _upgrade +from _util import isstringlike + + +class ContentTooShortError(urllib2.URLError): + def __init__(self, reason, result): + urllib2.URLError.__init__(self, reason) + self.result = result + + +def set_request_attr(req, name, value, default): + try: + getattr(req, name) + except AttributeError: + setattr(req, name, default) + if value is not default: + setattr(req, name, value) + + +class OpenerDirector(urllib2.OpenerDirector): + def __init__(self): + urllib2.OpenerDirector.__init__(self) + # really none of these are (sanely) public -- the lack of initial + # underscore on some is just due to following urllib2 + self.process_response = {} + self.process_request = {} + self._any_request = {} + self._any_response = {} + self._handler_index_valid = True + self._tempfiles = [] + + def add_handler(self, handler): + if handler in self.handlers: + return + # XXX why does self.handlers need to be sorted? + bisect.insort(self.handlers, handler) + handler.add_parent(self) + self._handler_index_valid = False + + def _maybe_reindex_handlers(self): + if self._handler_index_valid: + return + + handle_error = {} + handle_open = {} + process_request = {} + process_response = {} + any_request = set() + any_response = set() + unwanted = [] + + for handler in self.handlers: + added = False + for meth in dir(handler): + if meth in ["redirect_request", "do_open", "proxy_open"]: + # oops, coincidental match + continue + + if meth == "any_request": + any_request.add(handler) + added = True + continue + elif meth == "any_response": + any_response.add(handler) + added = True + continue + + ii = meth.find("_") + scheme = meth[:ii] + condition = meth[ii+1:] + + if condition.startswith("error"): + jj = meth[ii+1:].find("_") + ii + 1 + kind = meth[jj+1:] + try: + kind = int(kind) + except ValueError: + pass + lookup = handle_error.setdefault(scheme, {}) + elif condition == "open": + kind = scheme + lookup = handle_open + elif condition == "request": + kind = scheme + lookup = process_request + elif condition == "response": + kind = scheme + lookup = process_response + else: + continue + + lookup.setdefault(kind, set()).add(handler) + added = True + + if not added: + unwanted.append(handler) + + for handler in unwanted: + self.handlers.remove(handler) + + # sort indexed methods + # XXX could be cleaned up + for lookup in [process_request, process_response]: + for scheme, handlers in lookup.iteritems(): + lookup[scheme] = handlers + for scheme, lookup in handle_error.iteritems(): + for code, handlers in lookup.iteritems(): + handlers = list(handlers) + handlers.sort() + lookup[code] = handlers + for scheme, handlers in handle_open.iteritems(): + handlers = list(handlers) + handlers.sort() + handle_open[scheme] = handlers + + # cache the indexes + self.handle_error = handle_error + self.handle_open = handle_open + self.process_request = process_request + self.process_response = process_response + self._any_request = any_request + self._any_response = any_response + + def _request(self, url_or_req, data, visit, + timeout=_sockettimeout._GLOBAL_DEFAULT_TIMEOUT): + if isstringlike(url_or_req): + req = Request(url_or_req, data, visit=visit, timeout=timeout) + else: + # already a urllib2.Request or mechanize.Request instance + req = url_or_req + if data is not None: + req.add_data(data) + # XXX yuck + set_request_attr(req, "visit", visit, None) + set_request_attr(req, "timeout", timeout, + _sockettimeout._GLOBAL_DEFAULT_TIMEOUT) + return req + + def open(self, fullurl, data=None, + timeout=_sockettimeout._GLOBAL_DEFAULT_TIMEOUT): + req = self._request(fullurl, data, None, timeout) + req_scheme = req.get_type() + + self._maybe_reindex_handlers() + + # pre-process request + # XXX should we allow a Processor to change the URL scheme + # of the request? + request_processors = set(self.process_request.get(req_scheme, [])) + request_processors.update(self._any_request) + request_processors = list(request_processors) + request_processors.sort() + for processor in request_processors: + for meth_name in ["any_request", req_scheme+"_request"]: + meth = getattr(processor, meth_name, None) + if meth: + req = meth(req) + + # In Python >= 2.4, .open() supports processors already, so we must + # call ._open() instead. + urlopen = getattr(urllib2.OpenerDirector, "_open", + urllib2.OpenerDirector.open) + response = urlopen(self, req, data) + + # post-process response + response_processors = set(self.process_response.get(req_scheme, [])) + response_processors.update(self._any_response) + response_processors = list(response_processors) + response_processors.sort() + for processor in response_processors: + for meth_name in ["any_response", req_scheme+"_response"]: + meth = getattr(processor, meth_name, None) + if meth: + response = meth(req, response) + + return response + + def error(self, proto, *args): + if proto in ['http', 'https']: + # XXX http[s] protocols are special-cased + dict = self.handle_error['http'] # https is not different than http + proto = args[2] # YUCK! + meth_name = 'http_error_%s' % proto + http_err = 1 + orig_args = args + else: + dict = self.handle_error + meth_name = proto + '_error' + http_err = 0 + args = (dict, proto, meth_name) + args + result = apply(self._call_chain, args) + if result: + return result + + if http_err: + args = (dict, 'default', 'http_error_default') + orig_args + return apply(self._call_chain, args) + + BLOCK_SIZE = 1024*8 + def retrieve(self, fullurl, filename=None, reporthook=None, data=None, + timeout=_sockettimeout._GLOBAL_DEFAULT_TIMEOUT): + """Returns (filename, headers). + + For remote objects, the default filename will refer to a temporary + file. Temporary files are removed when the OpenerDirector.close() + method is called. + + For file: URLs, at present the returned filename is None. This may + change in future. + + If the actual number of bytes read is less than indicated by the + Content-Length header, raises ContentTooShortError (a URLError + subclass). The exception's .result attribute contains the (filename, + headers) that would have been returned. + + """ + req = self._request(fullurl, data, False, timeout) + scheme = req.get_type() + fp = self.open(req) + headers = fp.info() + if filename is None and scheme == 'file': + # XXX req.get_selector() seems broken here, return None, + # pending sanity :-/ + return None, headers + #return urllib.url2pathname(req.get_selector()), headers + if filename: + tfp = open(filename, 'wb') + else: + path = _rfc3986.urlsplit(req.get_full_url())[2] + suffix = os.path.splitext(path)[1] + fd, filename = tempfile.mkstemp(suffix) + self._tempfiles.append(filename) + tfp = os.fdopen(fd, 'wb') + + result = filename, headers + bs = self.BLOCK_SIZE + size = -1 + read = 0 + blocknum = 0 + if reporthook: + if "content-length" in headers: + size = int(headers["Content-Length"]) + reporthook(blocknum, bs, size) + while 1: + block = fp.read(bs) + if block == "": + break + read += len(block) + tfp.write(block) + blocknum += 1 + if reporthook: + reporthook(blocknum, bs, size) + fp.close() + tfp.close() + del fp + del tfp + + # raise exception if actual size does not match content-length header + if size >= 0 and read < size: + raise ContentTooShortError( + "retrieval incomplete: " + "got only %i out of %i bytes" % (read, size), + result + ) + + return result + + def close(self): + urllib2.OpenerDirector.close(self) + + # make it very obvious this object is no longer supposed to be used + self.open = self.error = self.retrieve = self.add_handler = None + + if self._tempfiles: + for filename in self._tempfiles: + try: + os.unlink(filename) + except OSError: + pass + del self._tempfiles[:] + + +def wrapped_open(urlopen, process_response_object, fullurl, data=None, + timeout=_sockettimeout._GLOBAL_DEFAULT_TIMEOUT): + success = True + try: + response = urlopen(fullurl, data, timeout) + except urllib2.HTTPError, error: + success = False + if error.fp is None: # not a response + raise + response = error + + if response is not None: + response = process_response_object(response) + + if not success: + raise response + return response + +class ResponseProcessingOpener(OpenerDirector): + + def open(self, fullurl, data=None, + timeout=_sockettimeout._GLOBAL_DEFAULT_TIMEOUT): + def bound_open(fullurl, data=None, + timeout=_sockettimeout._GLOBAL_DEFAULT_TIMEOUT): + return OpenerDirector.open(self, fullurl, data, timeout) + return wrapped_open( + bound_open, self.process_response_object, fullurl, data, timeout) + + def process_response_object(self, response): + return response + + +class SeekableResponseOpener(ResponseProcessingOpener): + def process_response_object(self, response): + return _response.seek_wrapped_response(response) + + +class OpenerFactory: + """This class's interface is quite likely to change.""" + + default_classes = [ + # handlers + urllib2.ProxyHandler, + urllib2.UnknownHandler, + _http.HTTPHandler, # derived from new AbstractHTTPHandler + _http.HTTPDefaultErrorHandler, + _http.HTTPRedirectHandler, # bugfixed + urllib2.FTPHandler, + _file.FileHandler, + # processors + _upgrade.HTTPRequestUpgradeProcessor, + _http.HTTPCookieProcessor, + _http.HTTPErrorProcessor, + ] + if hasattr(httplib, 'HTTPS'): + default_classes.append(_http.HTTPSHandler) + handlers = [] + replacement_handlers = [] + + def __init__(self, klass=OpenerDirector): + self.klass = klass + + def build_opener(self, *handlers): + """Create an opener object from a list of handlers and processors. + + The opener will use several default handlers and processors, including + support for HTTP and FTP. + + If any of the handlers passed as arguments are subclasses of the + default handlers, the default handlers will not be used. + + """ + opener = self.klass() + default_classes = list(self.default_classes) + skip = [] + for klass in default_classes: + for check in handlers: + if type(check) == types.ClassType: + if issubclass(check, klass): + skip.append(klass) + elif type(check) == types.InstanceType: + if isinstance(check, klass): + skip.append(klass) + for klass in skip: + default_classes.remove(klass) + + for klass in default_classes: + opener.add_handler(klass()) + for h in handlers: + if type(h) == types.ClassType: + h = h() + opener.add_handler(h) + + return opener + + +build_opener = OpenerFactory().build_opener + +_opener = None +urlopen_lock = _threading.Lock() +def urlopen(url, data=None, timeout=_sockettimeout._GLOBAL_DEFAULT_TIMEOUT): + global _opener + if _opener is None: + urlopen_lock.acquire() + try: + if _opener is None: + _opener = build_opener() + finally: + urlopen_lock.release() + return _opener.open(url, data, timeout) + +def urlretrieve(url, filename=None, reporthook=None, data=None, + timeout=_sockettimeout._GLOBAL_DEFAULT_TIMEOUT): + global _opener + if _opener is None: + urlopen_lock.acquire() + try: + if _opener is None: + _opener = build_opener() + finally: + urlopen_lock.release() + return _opener.retrieve(url, filename, reporthook, data, timeout) + +def install_opener(opener): + global _opener + _opener = opener diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_pullparser.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_pullparser.py new file mode 100644 index 0000000..4d8d9d3 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_pullparser.py @@ -0,0 +1,390 @@ +"""A simple "pull API" for HTML parsing, after Perl's HTML::TokeParser. + +Examples + +This program extracts all links from a document. It will print one +line for each link, containing the URL and the textual description +between the <A>...</A> tags: + +import pullparser, sys +f = file(sys.argv[1]) +p = pullparser.PullParser(f) +for token in p.tags("a"): + if token.type == "endtag": continue + url = dict(token.attrs).get("href", "-") + text = p.get_compressed_text(endat=("endtag", "a")) + print "%s\t%s" % (url, text) + +This program extracts the <TITLE> from the document: + +import pullparser, sys +f = file(sys.argv[1]) +p = pullparser.PullParser(f) +if p.get_tag("title"): + title = p.get_compressed_text() + print "Title: %s" % title + + +Copyright 2003-2006 John J. Lee <jjl@pobox.com> +Copyright 1998-2001 Gisle Aas (original libwww-perl code) + +This code is free software; you can redistribute it and/or modify it +under the terms of the BSD or ZPL 2.1 licenses. + +""" + +import re, htmlentitydefs +import sgmllib, HTMLParser +from xml.sax import saxutils + +from _html import unescape, unescape_charref + + +class NoMoreTokensError(Exception): pass + +class Token: + """Represents an HTML tag, declaration, processing instruction etc. + + Behaves as both a tuple-like object (ie. iterable) and has attributes + .type, .data and .attrs. + + >>> t = Token("starttag", "a", [("href", "http://www.python.org/")]) + >>> t == ("starttag", "a", [("href", "http://www.python.org/")]) + True + >>> (t.type, t.data) == ("starttag", "a") + True + >>> t.attrs == [("href", "http://www.python.org/")] + True + + Public attributes + + type: one of "starttag", "endtag", "startendtag", "charref", "entityref", + "data", "comment", "decl", "pi", after the corresponding methods of + HTMLParser.HTMLParser + data: For a tag, the tag name; otherwise, the relevant data carried by the + tag, as a string + attrs: list of (name, value) pairs representing HTML attributes + (or None if token does not represent an opening tag) + + """ + def __init__(self, type, data, attrs=None): + self.type = type + self.data = data + self.attrs = attrs + def __iter__(self): + return iter((self.type, self.data, self.attrs)) + def __eq__(self, other): + type, data, attrs = other + if (self.type == type and + self.data == data and + self.attrs == attrs): + return True + else: + return False + def __ne__(self, other): return not self.__eq__(other) + def __repr__(self): + args = ", ".join(map(repr, [self.type, self.data, self.attrs])) + return self.__class__.__name__+"(%s)" % args + + def __str__(self): + """ + >>> print Token("starttag", "br") + <br> + >>> print Token("starttag", "a", + ... [("href", "http://www.python.org/"), ("alt", '"foo"')]) + <a href="http://www.python.org/" alt='"foo"'> + >>> print Token("startendtag", "br") + <br /> + >>> print Token("startendtag", "br", [("spam", "eggs")]) + <br spam="eggs" /> + >>> print Token("endtag", "p") + </p> + >>> print Token("charref", "38") + & + >>> print Token("entityref", "amp") + & + >>> print Token("data", "foo\\nbar") + foo + bar + >>> print Token("comment", "Life is a bowl\\nof cherries.") + <!--Life is a bowl + of cherries.--> + >>> print Token("decl", "decl") + <!decl> + >>> print Token("pi", "pi") + <?pi> + """ + if self.attrs is not None: + attrs = "".join([" %s=%s" % (k, saxutils.quoteattr(v)) for + k, v in self.attrs]) + else: + attrs = "" + if self.type == "starttag": + return "<%s%s>" % (self.data, attrs) + elif self.type == "startendtag": + return "<%s%s />" % (self.data, attrs) + elif self.type == "endtag": + return "</%s>" % self.data + elif self.type == "charref": + return "&#%s;" % self.data + elif self.type == "entityref": + return "&%s;" % self.data + elif self.type == "data": + return self.data + elif self.type == "comment": + return "<!--%s-->" % self.data + elif self.type == "decl": + return "<!%s>" % self.data + elif self.type == "pi": + return "<?%s>" % self.data + assert False + + +def iter_until_exception(fn, exception, *args, **kwds): + while 1: + try: + yield fn(*args, **kwds) + except exception: + raise StopIteration + + +class _AbstractParser: + chunk = 1024 + compress_re = re.compile(r"\s+") + def __init__(self, fh, textify={"img": "alt", "applet": "alt"}, + encoding="ascii", entitydefs=None): + """ + fh: file-like object (only a .read() method is required) from which to + read HTML to be parsed + textify: mapping used by .get_text() and .get_compressed_text() methods + to represent opening tags as text + encoding: encoding used to encode numeric character references by + .get_text() and .get_compressed_text() ("ascii" by default) + + entitydefs: mapping like {"amp": "&", ...} containing HTML entity + definitions (a sensible default is used). This is used to unescape + entities in .get_text() (and .get_compressed_text()) and attribute + values. If the encoding can not represent the character, the entity + reference is left unescaped. Note that entity references (both + numeric - e.g. { or ઼ - and non-numeric - e.g. &) are + unescaped in attribute values and the return value of .get_text(), but + not in data outside of tags. Instead, entity references outside of + tags are represented as tokens. This is a bit odd, it's true :-/ + + If the element name of an opening tag matches a key in the textify + mapping then that tag is converted to text. The corresponding value is + used to specify which tag attribute to obtain the text from. textify + maps from element names to either: + + - an HTML attribute name, in which case the HTML attribute value is + used as its text value along with the element name in square + brackets (eg."alt text goes here[IMG]", or, if the alt attribute + were missing, just "[IMG]") + - a callable object (eg. a function) which takes a Token and returns + the string to be used as its text value + + If textify has no key for an element name, nothing is substituted for + the opening tag. + + Public attributes: + + encoding and textify: see above + + """ + self._fh = fh + self._tokenstack = [] # FIFO + self.textify = textify + self.encoding = encoding + if entitydefs is None: + entitydefs = htmlentitydefs.name2codepoint + self._entitydefs = entitydefs + + def __iter__(self): return self + + def tags(self, *names): + return iter_until_exception(self.get_tag, NoMoreTokensError, *names) + + def tokens(self, *tokentypes): + return iter_until_exception(self.get_token, NoMoreTokensError, + *tokentypes) + + def next(self): + try: + return self.get_token() + except NoMoreTokensError: + raise StopIteration() + + def get_token(self, *tokentypes): + """Pop the next Token object from the stack of parsed tokens. + + If arguments are given, they are taken to be token types in which the + caller is interested: tokens representing other elements will be + skipped. Element names must be given in lower case. + + Raises NoMoreTokensError. + + """ + while 1: + while self._tokenstack: + token = self._tokenstack.pop(0) + if tokentypes: + if token.type in tokentypes: + return token + else: + return token + data = self._fh.read(self.chunk) + if not data: + raise NoMoreTokensError() + self.feed(data) + + def unget_token(self, token): + """Push a Token back onto the stack.""" + self._tokenstack.insert(0, token) + + def get_tag(self, *names): + """Return the next Token that represents an opening or closing tag. + + If arguments are given, they are taken to be element names in which the + caller is interested: tags representing other elements will be skipped. + Element names must be given in lower case. + + Raises NoMoreTokensError. + + """ + while 1: + tok = self.get_token() + if tok.type not in ["starttag", "endtag", "startendtag"]: + continue + if names: + if tok.data in names: + return tok + else: + return tok + + def get_text(self, endat=None): + """Get some text. + + endat: stop reading text at this tag (the tag is included in the + returned text); endtag is a tuple (type, name) where type is + "starttag", "endtag" or "startendtag", and name is the element name of + the tag (element names must be given in lower case) + + If endat is not given, .get_text() will stop at the next opening or + closing tag, or when there are no more tokens (no exception is raised). + Note that .get_text() includes the text representation (if any) of the + opening tag, but pushes the opening tag back onto the stack. As a + result, if you want to call .get_text() again, you need to call + .get_tag() first (unless you want an empty string returned when you + next call .get_text()). + + Entity references are translated using the value of the entitydefs + constructor argument (a mapping from names to characters like that + provided by the standard module htmlentitydefs). Named entity + references that are not in this mapping are left unchanged. + + The textify attribute is used to translate opening tags into text: see + the class docstring. + + """ + text = [] + tok = None + while 1: + try: + tok = self.get_token() + except NoMoreTokensError: + # unget last token (not the one we just failed to get) + if tok: self.unget_token(tok) + break + if tok.type == "data": + text.append(tok.data) + elif tok.type == "entityref": + t = unescape("&%s;"%tok.data, self._entitydefs, self.encoding) + text.append(t) + elif tok.type == "charref": + t = unescape_charref(tok.data, self.encoding) + text.append(t) + elif tok.type in ["starttag", "endtag", "startendtag"]: + tag_name = tok.data + if tok.type in ["starttag", "startendtag"]: + alt = self.textify.get(tag_name) + if alt is not None: + if callable(alt): + text.append(alt(tok)) + elif tok.attrs is not None: + for k, v in tok.attrs: + if k == alt: + text.append(v) + text.append("[%s]" % tag_name.upper()) + if endat is None or endat == (tok.type, tag_name): + self.unget_token(tok) + break + return "".join(text) + + def get_compressed_text(self, *args, **kwds): + """ + As .get_text(), but collapses each group of contiguous whitespace to a + single space character, and removes all initial and trailing + whitespace. + + """ + text = self.get_text(*args, **kwds) + text = text.strip() + return self.compress_re.sub(" ", text) + + def handle_startendtag(self, tag, attrs): + self._tokenstack.append(Token("startendtag", tag, attrs)) + def handle_starttag(self, tag, attrs): + self._tokenstack.append(Token("starttag", tag, attrs)) + def handle_endtag(self, tag): + self._tokenstack.append(Token("endtag", tag)) + def handle_charref(self, name): + self._tokenstack.append(Token("charref", name)) + def handle_entityref(self, name): + self._tokenstack.append(Token("entityref", name)) + def handle_data(self, data): + self._tokenstack.append(Token("data", data)) + def handle_comment(self, data): + self._tokenstack.append(Token("comment", data)) + def handle_decl(self, decl): + self._tokenstack.append(Token("decl", decl)) + def unknown_decl(self, data): + # XXX should this call self.error instead? + #self.error("unknown declaration: " + `data`) + self._tokenstack.append(Token("decl", data)) + def handle_pi(self, data): + self._tokenstack.append(Token("pi", data)) + + def unescape_attr(self, name): + return unescape(name, self._entitydefs, self.encoding) + def unescape_attrs(self, attrs): + escaped_attrs = [] + for key, val in attrs: + escaped_attrs.append((key, self.unescape_attr(val))) + return escaped_attrs + +class PullParser(_AbstractParser, HTMLParser.HTMLParser): + def __init__(self, *args, **kwds): + HTMLParser.HTMLParser.__init__(self) + _AbstractParser.__init__(self, *args, **kwds) + def unescape(self, name): + # Use the entitydefs passed into constructor, not + # HTMLParser.HTMLParser's entitydefs. + return self.unescape_attr(name) + +class TolerantPullParser(_AbstractParser, sgmllib.SGMLParser): + def __init__(self, *args, **kwds): + sgmllib.SGMLParser.__init__(self) + _AbstractParser.__init__(self, *args, **kwds) + def unknown_starttag(self, tag, attrs): + attrs = self.unescape_attrs(attrs) + self._tokenstack.append(Token("starttag", tag, attrs)) + def unknown_endtag(self, tag): + self._tokenstack.append(Token("endtag", tag)) + + +def _test(): + import doctest, _pullparser + return doctest.testmod(_pullparser) + +if __name__ == "__main__": + _test() diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_request.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_request.py new file mode 100644 index 0000000..7824441 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_request.py @@ -0,0 +1,87 @@ +"""Integration with Python standard library module urllib2: Request class. + +Copyright 2004-2006 John J Lee <jjl@pobox.com> + +This code is free software; you can redistribute it and/or modify it +under the terms of the BSD or ZPL 2.1 licenses (see the file +COPYING.txt included with the distribution). + +""" + +import urllib2, urllib, logging + +from _clientcookie import request_host_lc +import _rfc3986 +import _sockettimeout + +warn = logging.getLogger("mechanize").warning + + +class Request(urllib2.Request): + def __init__(self, url, data=None, headers={}, + origin_req_host=None, unverifiable=False, visit=None, + timeout=_sockettimeout._GLOBAL_DEFAULT_TIMEOUT): + # In mechanize 0.2, the interpretation of a unicode url argument will + # change: A unicode url argument will be interpreted as an IRI, and a + # bytestring as a URI. For now, we accept unicode or bytestring. We + # don't insist that the value is always a URI (specifically, must only + # contain characters which are legal), because that might break working + # code (who knows what bytes some servers want to see, especially with + # browser plugins for internationalised URIs). + if not _rfc3986.is_clean_uri(url): + warn("url argument is not a URI " + "(contains illegal characters) %r" % url) + urllib2.Request.__init__(self, url, data, headers) + self.selector = None + self.unredirected_hdrs = {} + self.visit = visit + self.timeout = timeout + + # All the terminology below comes from RFC 2965. + self.unverifiable = unverifiable + # Set request-host of origin transaction. + # The origin request-host is needed in order to decide whether + # unverifiable sub-requests (automatic redirects, images embedded + # in HTML, etc.) are to third-party hosts. If they are, the + # resulting transactions might need to be conducted with cookies + # turned off. + if origin_req_host is None: + origin_req_host = request_host_lc(self) + self.origin_req_host = origin_req_host + + def get_selector(self): + return urllib.splittag(self.__r_host)[0] + + def get_origin_req_host(self): + return self.origin_req_host + + def is_unverifiable(self): + return self.unverifiable + + def add_unredirected_header(self, key, val): + """Add a header that will not be added to a redirected request.""" + self.unredirected_hdrs[key.capitalize()] = val + + def has_header(self, header_name): + """True iff request has named header (regular or unredirected).""" + return (header_name in self.headers or + header_name in self.unredirected_hdrs) + + def get_header(self, header_name, default=None): + return self.headers.get( + header_name, + self.unredirected_hdrs.get(header_name, default)) + + def header_items(self): + hdrs = self.unredirected_hdrs.copy() + hdrs.update(self.headers) + return hdrs.items() + + def __str__(self): + return "<Request for %s>" % self.get_full_url() + + def get_method(self): + if self.has_data(): + return "POST" + else: + return "GET" diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_response.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_response.py new file mode 100644 index 0000000..fad9b57 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_response.py @@ -0,0 +1,527 @@ +"""Response classes. + +The seek_wrapper code is not used if you're using UserAgent with +.set_seekable_responses(False), or if you're using the urllib2-level interface +without SeekableProcessor or HTTPEquivProcessor. Class closeable_response is +instantiated by some handlers (AbstractHTTPHandler), but the closeable_response +interface is only depended upon by Browser-level code. Function +upgrade_response is only used if you're using Browser or +ResponseUpgradeProcessor. + + +Copyright 2006 John J. Lee <jjl@pobox.com> + +This code is free software; you can redistribute it and/or modify it +under the terms of the BSD or ZPL 2.1 licenses (see the file COPYING.txt +included with the distribution). + +""" + +import copy, mimetools +from cStringIO import StringIO +import urllib2 + + +def len_of_seekable(file_): + # this function exists because evaluation of len(file_.getvalue()) on every + # .read() from seek_wrapper would be O(N**2) in number of .read()s + pos = file_.tell() + file_.seek(0, 2) # to end + try: + return file_.tell() + finally: + file_.seek(pos) + + +# XXX Andrew Dalke kindly sent me a similar class in response to my request on +# comp.lang.python, which I then proceeded to lose. I wrote this class +# instead, but I think he's released his code publicly since, could pinch the +# tests from it, at least... + +# For testing seek_wrapper invariant (note that +# test_urllib2.HandlerTest.test_seekable is expected to fail when this +# invariant checking is turned on). The invariant checking is done by module +# ipdc, which is available here: +# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/436834 +## from ipdbc import ContractBase +## class seek_wrapper(ContractBase): +class seek_wrapper: + """Adds a seek method to a file object. + + This is only designed for seeking on readonly file-like objects. + + Wrapped file-like object must have a read method. The readline method is + only supported if that method is present on the wrapped object. The + readlines method is always supported. xreadlines and iteration are + supported only for Python 2.2 and above. + + Public attributes: + + wrapped: the wrapped file object + is_closed: true iff .close() has been called + + WARNING: All other attributes of the wrapped object (ie. those that are not + one of wrapped, read, readline, readlines, xreadlines, __iter__ and next) + are passed through unaltered, which may or may not make sense for your + particular file object. + + """ + # General strategy is to check that cache is full enough, then delegate to + # the cache (self.__cache, which is a cStringIO.StringIO instance). A seek + # position (self.__pos) is maintained independently of the cache, in order + # that a single cache may be shared between multiple seek_wrapper objects. + # Copying using module copy shares the cache in this way. + + def __init__(self, wrapped): + self.wrapped = wrapped + self.__read_complete_state = [False] + self.__is_closed_state = [False] + self.__have_readline = hasattr(self.wrapped, "readline") + self.__cache = StringIO() + self.__pos = 0 # seek position + + def invariant(self): + # The end of the cache is always at the same place as the end of the + # wrapped file (though the .tell() method is not required to be present + # on wrapped file). + return self.wrapped.tell() == len(self.__cache.getvalue()) + + def close(self): + self.wrapped.close() + self.is_closed = True + + def __getattr__(self, name): + if name == "is_closed": + return self.__is_closed_state[0] + elif name == "read_complete": + return self.__read_complete_state[0] + + wrapped = self.__dict__.get("wrapped") + if wrapped: + return getattr(wrapped, name) + + return getattr(self.__class__, name) + + def __setattr__(self, name, value): + if name == "is_closed": + self.__is_closed_state[0] = bool(value) + elif name == "read_complete": + if not self.is_closed: + self.__read_complete_state[0] = bool(value) + else: + self.__dict__[name] = value + + def seek(self, offset, whence=0): + assert whence in [0,1,2] + + # how much data, if any, do we need to read? + if whence == 2: # 2: relative to end of *wrapped* file + if offset < 0: raise ValueError("negative seek offset") + # since we don't know yet where the end of that file is, we must + # read everything + to_read = None + else: + if whence == 0: # 0: absolute + if offset < 0: raise ValueError("negative seek offset") + dest = offset + else: # 1: relative to current position + pos = self.__pos + if pos < offset: + raise ValueError("seek to before start of file") + dest = pos + offset + end = len_of_seekable(self.__cache) + to_read = dest - end + if to_read < 0: + to_read = 0 + + if to_read != 0: + self.__cache.seek(0, 2) + if to_read is None: + assert whence == 2 + self.__cache.write(self.wrapped.read()) + self.read_complete = True + self.__pos = self.__cache.tell() - offset + else: + data = self.wrapped.read(to_read) + if not data: + self.read_complete = True + else: + self.__cache.write(data) + # Don't raise an exception even if we've seek()ed past the end + # of .wrapped, since fseek() doesn't complain in that case. + # Also like fseek(), pretend we have seek()ed past the end, + # i.e. not: + #self.__pos = self.__cache.tell() + # but rather: + self.__pos = dest + else: + self.__pos = dest + + def tell(self): + return self.__pos + + def __copy__(self): + cpy = self.__class__(self.wrapped) + cpy.__cache = self.__cache + cpy.__read_complete_state = self.__read_complete_state + cpy.__is_closed_state = self.__is_closed_state + return cpy + + def get_data(self): + pos = self.__pos + try: + self.seek(0) + return self.read(-1) + finally: + self.__pos = pos + + def read(self, size=-1): + pos = self.__pos + end = len_of_seekable(self.__cache) + available = end - pos + + # enough data already cached? + if size <= available and size != -1: + self.__cache.seek(pos) + self.__pos = pos+size + return self.__cache.read(size) + + # no, so read sufficient data from wrapped file and cache it + self.__cache.seek(0, 2) + if size == -1: + self.__cache.write(self.wrapped.read()) + self.read_complete = True + else: + to_read = size - available + assert to_read > 0 + data = self.wrapped.read(to_read) + if not data: + self.read_complete = True + else: + self.__cache.write(data) + self.__cache.seek(pos) + + data = self.__cache.read(size) + self.__pos = self.__cache.tell() + assert self.__pos == pos + len(data) + return data + + def readline(self, size=-1): + if not self.__have_readline: + raise NotImplementedError("no readline method on wrapped object") + + # line we're about to read might not be complete in the cache, so + # read another line first + pos = self.__pos + self.__cache.seek(0, 2) + data = self.wrapped.readline() + if not data: + self.read_complete = True + else: + self.__cache.write(data) + self.__cache.seek(pos) + + data = self.__cache.readline() + if size != -1: + r = data[:size] + self.__pos = pos+size + else: + r = data + self.__pos = pos+len(data) + return r + + def readlines(self, sizehint=-1): + pos = self.__pos + self.__cache.seek(0, 2) + self.__cache.write(self.wrapped.read()) + self.read_complete = True + self.__cache.seek(pos) + data = self.__cache.readlines(sizehint) + self.__pos = self.__cache.tell() + return data + + def __iter__(self): return self + def next(self): + line = self.readline() + if line == "": raise StopIteration + return line + + xreadlines = __iter__ + + def __repr__(self): + return ("<%s at %s whose wrapped object = %r>" % + (self.__class__.__name__, hex(abs(id(self))), self.wrapped)) + + +class response_seek_wrapper(seek_wrapper): + + """ + Supports copying response objects and setting response body data. + + """ + + def __init__(self, wrapped): + seek_wrapper.__init__(self, wrapped) + self._headers = self.wrapped.info() + + def __copy__(self): + cpy = seek_wrapper.__copy__(self) + # copy headers from delegate + cpy._headers = copy.copy(self.info()) + return cpy + + # Note that .info() and .geturl() (the only two urllib2 response methods + # that are not implemented by seek_wrapper) must be here explicitly rather + # than by seek_wrapper's __getattr__ delegation) so that the nasty + # dynamically-created HTTPError classes in get_seek_wrapper_class() get the + # wrapped object's implementation, and not HTTPError's. + + def info(self): + return self._headers + + def geturl(self): + return self.wrapped.geturl() + + def set_data(self, data): + self.seek(0) + self.read() + self.close() + cache = self._seek_wrapper__cache = StringIO() + cache.write(data) + self.seek(0) + + +class eoffile: + # file-like object that always claims to be at end-of-file... + def read(self, size=-1): return "" + def readline(self, size=-1): return "" + def __iter__(self): return self + def next(self): return "" + def close(self): pass + +class eofresponse(eoffile): + def __init__(self, url, headers, code, msg): + self._url = url + self._headers = headers + self.code = code + self.msg = msg + def geturl(self): return self._url + def info(self): return self._headers + + +class closeable_response: + """Avoids unnecessarily clobbering urllib.addinfourl methods on .close(). + + Only supports responses returned by mechanize.HTTPHandler. + + After .close(), the following methods are supported: + + .read() + .readline() + .info() + .geturl() + .__iter__() + .next() + .close() + + and the following attributes are supported: + + .code + .msg + + Also supports pickling (but the stdlib currently does something to prevent + it: http://python.org/sf/1144636). + + """ + # presence of this attr indicates is useable after .close() + closeable_response = None + + def __init__(self, fp, headers, url, code, msg): + self._set_fp(fp) + self._headers = headers + self._url = url + self.code = code + self.msg = msg + + def _set_fp(self, fp): + self.fp = fp + self.read = self.fp.read + self.readline = self.fp.readline + if hasattr(self.fp, "readlines"): self.readlines = self.fp.readlines + if hasattr(self.fp, "fileno"): + self.fileno = self.fp.fileno + else: + self.fileno = lambda: None + self.__iter__ = self.fp.__iter__ + self.next = self.fp.next + + def __repr__(self): + return '<%s at %s whose fp = %r>' % ( + self.__class__.__name__, hex(abs(id(self))), self.fp) + + def info(self): + return self._headers + + def geturl(self): + return self._url + + def close(self): + wrapped = self.fp + wrapped.close() + new_wrapped = eofresponse( + self._url, self._headers, self.code, self.msg) + self._set_fp(new_wrapped) + + def __getstate__(self): + # There are three obvious options here: + # 1. truncate + # 2. read to end + # 3. close socket, pickle state including read position, then open + # again on unpickle and use Range header + # XXXX um, 4. refuse to pickle unless .close()d. This is better, + # actually ("errors should never pass silently"). Pickling doesn't + # work anyway ATM, because of http://python.org/sf/1144636 so fix + # this later + + # 2 breaks pickle protocol, because one expects the original object + # to be left unscathed by pickling. 3 is too complicated and + # surprising (and too much work ;-) to happen in a sane __getstate__. + # So we do 1. + + state = self.__dict__.copy() + new_wrapped = eofresponse( + self._url, self._headers, self.code, self.msg) + state["wrapped"] = new_wrapped + return state + +def test_response(data='test data', headers=[], + url="http://example.com/", code=200, msg="OK"): + return make_response(data, headers, url, code, msg) + +def test_html_response(data='test data', headers=[], + url="http://example.com/", code=200, msg="OK"): + headers += [("Content-type", "text/html")] + return make_response(data, headers, url, code, msg) + +def make_response(data, headers, url, code, msg): + """Convenient factory for objects implementing response interface. + + data: string containing response body data + headers: sequence of (name, value) pairs + url: URL of response + code: integer response code (e.g. 200) + msg: string response code message (e.g. "OK") + + """ + mime_headers = make_headers(headers) + r = closeable_response(StringIO(data), mime_headers, url, code, msg) + return response_seek_wrapper(r) + + +def make_headers(headers): + """ + headers: sequence of (name, value) pairs + """ + hdr_text = [] + for name_value in headers: + hdr_text.append("%s: %s" % name_value) + return mimetools.Message(StringIO("\n".join(hdr_text))) + + +# Rest of this module is especially horrible, but needed, at least until fork +# urllib2. Even then, may want to preseve urllib2 compatibility. + +def get_seek_wrapper_class(response): + # in order to wrap response objects that are also exceptions, we must + # dynamically subclass the exception :-((( + if (isinstance(response, urllib2.HTTPError) and + not hasattr(response, "seek")): + if response.__class__.__module__ == "__builtin__": + exc_class_name = response.__class__.__name__ + else: + exc_class_name = "%s.%s" % ( + response.__class__.__module__, response.__class__.__name__) + + class httperror_seek_wrapper(response_seek_wrapper, response.__class__): + # this only derives from HTTPError in order to be a subclass -- + # the HTTPError behaviour comes from delegation + + _exc_class_name = exc_class_name + + def __init__(self, wrapped): + response_seek_wrapper.__init__(self, wrapped) + # be compatible with undocumented HTTPError attributes :-( + self.hdrs = wrapped.info() + self.filename = wrapped.geturl() + + def __repr__(self): + return ( + "<%s (%s instance) at %s " + "whose wrapped object = %r>" % ( + self.__class__.__name__, self._exc_class_name, + hex(abs(id(self))), self.wrapped) + ) + wrapper_class = httperror_seek_wrapper + else: + wrapper_class = response_seek_wrapper + return wrapper_class + +def seek_wrapped_response(response): + """Return a copy of response that supports seekable response interface. + + Accepts responses from both mechanize and urllib2 handlers. + + Copes with both oridinary response instances and HTTPError instances (which + can't be simply wrapped due to the requirement of preserving the exception + base class). + """ + if not hasattr(response, "seek"): + wrapper_class = get_seek_wrapper_class(response) + response = wrapper_class(response) + assert hasattr(response, "get_data") + return response + +def upgrade_response(response): + """Return a copy of response that supports Browser response interface. + + Browser response interface is that of "seekable responses" + (response_seek_wrapper), plus the requirement that responses must be + useable after .close() (closeable_response). + + Accepts responses from both mechanize and urllib2 handlers. + + Copes with both ordinary response instances and HTTPError instances (which + can't be simply wrapped due to the requirement of preserving the exception + base class). + """ + wrapper_class = get_seek_wrapper_class(response) + if hasattr(response, "closeable_response"): + if not hasattr(response, "seek"): + response = wrapper_class(response) + assert hasattr(response, "get_data") + return copy.copy(response) + + # a urllib2 handler constructed the response, i.e. the response is an + # urllib.addinfourl or a urllib2.HTTPError, instead of a + # _Util.closeable_response as returned by e.g. mechanize.HTTPHandler + try: + code = response.code + except AttributeError: + code = None + try: + msg = response.msg + except AttributeError: + msg = None + + # may have already-.read() data from .seek() cache + data = None + get_data = getattr(response, "get_data", None) + if get_data: + data = get_data() + + response = closeable_response( + response.fp, response.info(), response.geturl(), code, msg) + response = wrapper_class(response) + if data: + response.set_data(data) + return response diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_rfc3986.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_rfc3986.py new file mode 100644 index 0000000..1bb5021 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_rfc3986.py @@ -0,0 +1,241 @@ +"""RFC 3986 URI parsing and relative reference resolution / absolutization. + +(aka splitting and joining) + +Copyright 2006 John J. Lee <jjl@pobox.com> + +This code is free software; you can redistribute it and/or modify it under +the terms of the BSD or ZPL 2.1 licenses (see the file COPYING.txt +included with the distribution). + +""" + +# XXX Wow, this is ugly. Overly-direct translation of the RFC ATM. + +import re, urllib + +## def chr_range(a, b): +## return "".join(map(chr, range(ord(a), ord(b)+1))) + +## UNRESERVED_URI_CHARS = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" +## "abcdefghijklmnopqrstuvwxyz" +## "0123456789" +## "-_.~") +## RESERVED_URI_CHARS = "!*'();:@&=+$,/?#[]" +## URI_CHARS = RESERVED_URI_CHARS+UNRESERVED_URI_CHARS+'%' +# this re matches any character that's not in URI_CHARS +BAD_URI_CHARS_RE = re.compile("[^A-Za-z0-9\-_.~!*'();:@&=+$,/?%#[\]]") + + +def clean_url(url, encoding): + # percent-encode illegal URI characters + # Trying to come up with test cases for this gave me a headache, revisit + # when do switch to unicode. + # Somebody else's comments (lost the attribution): +## - IE will return you the url in the encoding you send it +## - Mozilla/Firefox will send you latin-1 if there's no non latin-1 +## characters in your link. It will send you utf-8 however if there are... + if type(url) == type(""): + url = url.decode(encoding, "replace") + url = url.strip() + # for second param to urllib.quote(), we want URI_CHARS, minus the + # 'always_safe' characters that urllib.quote() never percent-encodes + return urllib.quote(url.encode(encoding), "!*'();:@&=+$,/?%#[]~") + +def is_clean_uri(uri): + """ + >>> is_clean_uri("ABC!") + True + >>> is_clean_uri(u"ABC!") + True + >>> is_clean_uri("ABC|") + False + >>> is_clean_uri(u"ABC|") + False + >>> is_clean_uri("http://example.com/0") + True + >>> is_clean_uri(u"http://example.com/0") + True + """ + # note module re treats bytestrings as through they were decoded as latin-1 + # so this function accepts both unicode and bytestrings + return not bool(BAD_URI_CHARS_RE.search(uri)) + + +SPLIT_MATCH = re.compile( + r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?").match +def urlsplit(absolute_uri): + """Return scheme, authority, path, query, fragment.""" + match = SPLIT_MATCH(absolute_uri) + if match: + g = match.groups() + return g[1], g[3], g[4], g[6], g[8] + +def urlunsplit(parts): + scheme, authority, path, query, fragment = parts + r = [] + append = r.append + if scheme is not None: + append(scheme) + append(":") + if authority is not None: + append("//") + append(authority) + append(path) + if query is not None: + append("?") + append(query) + if fragment is not None: + append("#") + append(fragment) + return "".join(r) + +def urljoin(base_uri, uri_reference): + return urlunsplit(urljoin_parts(urlsplit(base_uri), + urlsplit(uri_reference))) + +# oops, this doesn't do the same thing as the literal translation +# from the RFC below +## import posixpath +## def urljoin_parts(base_parts, reference_parts): +## scheme, authority, path, query, fragment = base_parts +## rscheme, rauthority, rpath, rquery, rfragment = reference_parts + +## # compute target URI path +## if rpath == "": +## tpath = path +## else: +## tpath = rpath +## if not tpath.startswith("/"): +## tpath = merge(authority, path, tpath) +## tpath = posixpath.normpath(tpath) + +## if rscheme is not None: +## return (rscheme, rauthority, tpath, rquery, rfragment) +## elif rauthority is not None: +## return (scheme, rauthority, tpath, rquery, rfragment) +## elif rpath == "": +## if rquery is not None: +## tquery = rquery +## else: +## tquery = query +## return (scheme, authority, tpath, tquery, rfragment) +## else: +## return (scheme, authority, tpath, rquery, rfragment) + +def urljoin_parts(base_parts, reference_parts): + scheme, authority, path, query, fragment = base_parts + rscheme, rauthority, rpath, rquery, rfragment = reference_parts + + if rscheme == scheme: + rscheme = None + + if rscheme is not None: + tscheme, tauthority, tpath, tquery = ( + rscheme, rauthority, remove_dot_segments(rpath), rquery) + else: + if rauthority is not None: + tauthority, tpath, tquery = ( + rauthority, remove_dot_segments(rpath), rquery) + else: + if rpath == "": + tpath = path + if rquery is not None: + tquery = rquery + else: + tquery = query + else: + if rpath.startswith("/"): + tpath = remove_dot_segments(rpath) + else: + tpath = merge(authority, path, rpath) + tpath = remove_dot_segments(tpath) + tquery = rquery + tauthority = authority + tscheme = scheme + tfragment = rfragment + return (tscheme, tauthority, tpath, tquery, tfragment) + +# um, something *vaguely* like this is what I want, but I have to generate +# lots of test cases first, if only to understand what it is that +# remove_dot_segments really does... +## def remove_dot_segments(path): +## if path == '': +## return '' +## comps = path.split('/') +## new_comps = [] +## for comp in comps: +## if comp in ['.', '']: +## if not new_comps or new_comps[-1]: +## new_comps.append('') +## continue +## if comp != '..': +## new_comps.append(comp) +## elif new_comps: +## new_comps.pop() +## return '/'.join(new_comps) + + +def remove_dot_segments(path): + r = [] + while path: + # A + if path.startswith("../"): + path = path[3:] + continue + if path.startswith("./"): + path = path[2:] + continue + # B + if path.startswith("/./"): + path = path[2:] + continue + if path == "/.": + path = "/" + continue + # C + if path.startswith("/../"): + path = path[3:] + if r: + r.pop() + continue + if path == "/..": + path = "/" + if r: + r.pop() + continue + # D + if path == ".": + path = path[1:] + continue + if path == "..": + path = path[2:] + continue + # E + start = 0 + if path.startswith("/"): + start = 1 + ii = path.find("/", start) + if ii < 0: + ii = None + r.append(path[:ii]) + if ii is None: + break + path = path[ii:] + return "".join(r) + +def merge(base_authority, base_path, ref_path): + # XXXX Oddly, the sample Perl implementation of this by Roy Fielding + # doesn't even take base_authority as a parameter, despite the wording in + # the RFC suggesting otherwise. Perhaps I'm missing some obvious identity. + #if base_authority is not None and base_path == "": + if base_path == "": + return "/" + ref_path + ii = base_path.rfind("/") + if ii >= 0: + return base_path[:ii+1] + ref_path + return ref_path + +if __name__ == "__main__": + import doctest + doctest.testmod() diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_seek.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_seek.py new file mode 100644 index 0000000..4086d52 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_seek.py @@ -0,0 +1,16 @@ +from urllib2 import BaseHandler +from _util import deprecation +from _response import response_seek_wrapper + + +class SeekableProcessor(BaseHandler): + """Deprecated: Make responses seekable.""" + + def __init__(self): + deprecation( + "See http://wwwsearch.sourceforge.net/mechanize/doc.html#seekable") + + def any_response(self, request, response): + if not hasattr(response, "seek"): + return response_seek_wrapper(response) + return response diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_sockettimeout.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_sockettimeout.py new file mode 100644 index 0000000..c22b734 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_sockettimeout.py @@ -0,0 +1,6 @@ +import socket + +try: + _GLOBAL_DEFAULT_TIMEOUT = socket._GLOBAL_DEFAULT_TIMEOUT +except AttributeError: + _GLOBAL_DEFAULT_TIMEOUT = object() diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_testcase.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_testcase.py new file mode 100644 index 0000000..a13cca3 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_testcase.py @@ -0,0 +1,73 @@ +import shutil +import tempfile +import unittest + + +class SetupStack(object): + + def __init__(self): + self._on_teardown = [] + + def add_teardown(self, teardown): + self._on_teardown.append(teardown) + + def tear_down(self): + for func in reversed(self._on_teardown): + func() + + +class TearDownConvenience(object): + + def __init__(self, setup_stack=None): + self._own_setup_stack = setup_stack is None + if setup_stack is None: + setup_stack = SetupStack() + self._setup_stack = setup_stack + + # only call this convenience method if no setup_stack was supplied to c'tor + def tear_down(self): + assert self._own_setup_stack + self._setup_stack.tear_down() + + +class TempDirMaker(TearDownConvenience): + + def make_temp_dir(self): + temp_dir = tempfile.mkdtemp(prefix="tmp-%s-" % self.__class__.__name__) + def tear_down(): + shutil.rmtree(temp_dir) + self._setup_stack.add_teardown(tear_down) + return temp_dir + + +class MonkeyPatcher(TearDownConvenience): + + def monkey_patch(self, obj, name, value): + orig_value = getattr(obj, name) + setattr(obj, name, value) + def reverse_patch(): + setattr(obj, name, orig_value) + self._setup_stack.add_teardown(reverse_patch) + + +class TestCase(unittest.TestCase): + + def setUp(self): + self._setup_stack = SetupStack() + + def tearDown(self): + self._setup_stack.tear_down() + + def make_temp_dir(self, *args, **kwds): + return TempDirMaker(self._setup_stack).make_temp_dir(*args, **kwds) + + def monkey_patch(self, *args, **kwds): + return MonkeyPatcher(self._setup_stack).monkey_patch(*args, **kwds) + + def assert_contains(self, container, containee): + self.assertTrue(containee in container, "%r not in %r" % + (containee, container)) + + def assert_less_than(self, got, expected): + self.assertTrue(got < expected, "%r >= %r" % + (got, expected)) diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_upgrade.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_upgrade.py new file mode 100644 index 0000000..df59c01 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_upgrade.py @@ -0,0 +1,40 @@ +from urllib2 import BaseHandler + +from _request import Request +from _response import upgrade_response +from _util import deprecation + + +class HTTPRequestUpgradeProcessor(BaseHandler): + # upgrade urllib2.Request to this module's Request + # yuck! + handler_order = 0 # before anything else + + def http_request(self, request): + if not hasattr(request, "add_unredirected_header"): + newrequest = Request(request.get_full_url(), request.data, + request.headers) + try: newrequest.origin_req_host = request.origin_req_host + except AttributeError: pass + try: newrequest.unverifiable = request.unverifiable + except AttributeError: pass + try: newrequest.visit = request.visit + except AttributeError: pass + request = newrequest + return request + + https_request = http_request + + +class ResponseUpgradeProcessor(BaseHandler): + # upgrade responses to be .close()able without becoming unusable + handler_order = 0 # before anything else + + def __init__(self): + deprecation( + "See http://wwwsearch.sourceforge.net/mechanize/doc.html#seekable") + + def any_response(self, request, response): + if not hasattr(response, 'closeable_response'): + response = upgrade_response(response) + return response diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_urllib2.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_urllib2.py new file mode 100644 index 0000000..cbb761b --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_urllib2.py @@ -0,0 +1,55 @@ +# urllib2 work-alike interface +# ...from urllib2... +from urllib2 import \ + URLError, \ + HTTPError, \ + BaseHandler, \ + UnknownHandler, \ + FTPHandler, \ + CacheFTPHandler +# ...and from mechanize +from _auth import \ + HTTPPasswordMgr, \ + HTTPPasswordMgrWithDefaultRealm, \ + AbstractBasicAuthHandler, \ + AbstractDigestAuthHandler, \ + HTTPProxyPasswordMgr, \ + ProxyHandler, \ + ProxyBasicAuthHandler, \ + ProxyDigestAuthHandler, \ + HTTPBasicAuthHandler, \ + HTTPDigestAuthHandler, \ + HTTPSClientCertMgr +from _debug import \ + HTTPResponseDebugProcessor, \ + HTTPRedirectDebugProcessor +from _file import \ + FileHandler +# crap ATM +## from _gzip import \ +## HTTPGzipProcessor +from _http import \ + HTTPHandler, \ + HTTPDefaultErrorHandler, \ + HTTPRedirectHandler, \ + HTTPEquivProcessor, \ + HTTPCookieProcessor, \ + HTTPRefererProcessor, \ + HTTPRefreshProcessor, \ + HTTPErrorProcessor, \ + HTTPRobotRulesProcessor, \ + RobotExclusionError +import httplib +if hasattr(httplib, 'HTTPS'): + from _http import HTTPSHandler +del httplib +from _opener import OpenerDirector, \ + SeekableResponseOpener, \ + build_opener, install_opener, urlopen +from _request import \ + Request +from _seek import \ + SeekableProcessor +from _upgrade import \ + HTTPRequestUpgradeProcessor, \ + ResponseUpgradeProcessor diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_useragent.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_useragent.py new file mode 100644 index 0000000..723f87c --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_useragent.py @@ -0,0 +1,352 @@ +"""Convenient HTTP UserAgent class. + +This is a subclass of urllib2.OpenerDirector. + + +Copyright 2003-2006 John J. Lee <jjl@pobox.com> + +This code is free software; you can redistribute it and/or modify it under +the terms of the BSD or ZPL 2.1 licenses (see the file COPYING.txt +included with the distribution). + +""" + +import warnings + +import _auth +import _gzip +import _opener +import _response +import _sockettimeout +import _urllib2 + + +class UserAgentBase(_opener.OpenerDirector): + """Convenient user-agent class. + + Do not use .add_handler() to add a handler for something already dealt with + by this code. + + The only reason at present for the distinction between UserAgent and + UserAgentBase is so that classes that depend on .seek()able responses + (e.g. mechanize.Browser) can inherit from UserAgentBase. The subclass + UserAgent exposes a .set_seekable_responses() method that allows switching + off the adding of a .seek() method to responses. + + Public attributes: + + addheaders: list of (name, value) pairs specifying headers to send with + every request, unless they are overridden in the Request instance. + + >>> ua = UserAgentBase() + >>> ua.addheaders = [ + ... ("User-agent", "Mozilla/5.0 (compatible)"), + ... ("From", "responsible.person@example.com")] + + """ + + handler_classes = { + # scheme handlers + "http": _urllib2.HTTPHandler, + # CacheFTPHandler is buggy, at least in 2.3, so we don't use it + "ftp": _urllib2.FTPHandler, + "file": _urllib2.FileHandler, + + # other handlers + "_unknown": _urllib2.UnknownHandler, + # HTTP{S,}Handler depend on HTTPErrorProcessor too + "_http_error": _urllib2.HTTPErrorProcessor, + "_http_request_upgrade": _urllib2.HTTPRequestUpgradeProcessor, + "_http_default_error": _urllib2.HTTPDefaultErrorHandler, + + # feature handlers + "_basicauth": _urllib2.HTTPBasicAuthHandler, + "_digestauth": _urllib2.HTTPDigestAuthHandler, + "_redirect": _urllib2.HTTPRedirectHandler, + "_cookies": _urllib2.HTTPCookieProcessor, + "_refresh": _urllib2.HTTPRefreshProcessor, + "_equiv": _urllib2.HTTPEquivProcessor, + "_proxy": _urllib2.ProxyHandler, + "_proxy_basicauth": _urllib2.ProxyBasicAuthHandler, + "_proxy_digestauth": _urllib2.ProxyDigestAuthHandler, + "_robots": _urllib2.HTTPRobotRulesProcessor, + "_gzip": _gzip.HTTPGzipProcessor, # experimental! + + # debug handlers + "_debug_redirect": _urllib2.HTTPRedirectDebugProcessor, + "_debug_response_body": _urllib2.HTTPResponseDebugProcessor, + } + + default_schemes = ["http", "ftp", "file"] + default_others = ["_unknown", "_http_error", "_http_request_upgrade", + "_http_default_error", + ] + default_features = ["_redirect", "_cookies", + "_refresh", "_equiv", + "_basicauth", "_digestauth", + "_proxy", "_proxy_basicauth", "_proxy_digestauth", + "_robots", + ] + if hasattr(_urllib2, 'HTTPSHandler'): + handler_classes["https"] = _urllib2.HTTPSHandler + default_schemes.append("https") + + def __init__(self): + _opener.OpenerDirector.__init__(self) + + ua_handlers = self._ua_handlers = {} + for scheme in (self.default_schemes+ + self.default_others+ + self.default_features): + klass = self.handler_classes[scheme] + ua_handlers[scheme] = klass() + for handler in ua_handlers.itervalues(): + self.add_handler(handler) + + # Yuck. + # Ensure correct default constructor args were passed to + # HTTPRefreshProcessor and HTTPEquivProcessor. + if "_refresh" in ua_handlers: + self.set_handle_refresh(True) + if "_equiv" in ua_handlers: + self.set_handle_equiv(True) + # Ensure default password managers are installed. + pm = ppm = None + if "_basicauth" in ua_handlers or "_digestauth" in ua_handlers: + pm = _urllib2.HTTPPasswordMgrWithDefaultRealm() + if ("_proxy_basicauth" in ua_handlers or + "_proxy_digestauth" in ua_handlers): + ppm = _auth.HTTPProxyPasswordMgr() + self.set_password_manager(pm) + self.set_proxy_password_manager(ppm) + # set default certificate manager + if "https" in ua_handlers: + cm = _urllib2.HTTPSClientCertMgr() + self.set_client_cert_manager(cm) + + def close(self): + _opener.OpenerDirector.close(self) + self._ua_handlers = None + + # XXX +## def set_timeout(self, timeout): +## self._timeout = timeout +## def set_http_connection_cache(self, conn_cache): +## self._http_conn_cache = conn_cache +## def set_ftp_connection_cache(self, conn_cache): +## # XXX ATM, FTP has cache as part of handler; should it be separate? +## self._ftp_conn_cache = conn_cache + + def set_handled_schemes(self, schemes): + """Set sequence of URL scheme (protocol) strings. + + For example: ua.set_handled_schemes(["http", "ftp"]) + + If this fails (with ValueError) because you've passed an unknown + scheme, the set of handled schemes will not be changed. + + """ + want = {} + for scheme in schemes: + if scheme.startswith("_"): + raise ValueError("not a scheme '%s'" % scheme) + if scheme not in self.handler_classes: + raise ValueError("unknown scheme '%s'") + want[scheme] = None + + # get rid of scheme handlers we don't want + for scheme, oldhandler in self._ua_handlers.items(): + if scheme.startswith("_"): continue # not a scheme handler + if scheme not in want: + self._replace_handler(scheme, None) + else: + del want[scheme] # already got it + # add the scheme handlers that are missing + for scheme in want.keys(): + self._set_handler(scheme, True) + + def set_cookiejar(self, cookiejar): + """Set a mechanize.CookieJar, or None.""" + self._set_handler("_cookies", obj=cookiejar) + + # XXX could use Greg Stein's httpx for some of this instead? + # or httplib2?? + def set_proxies(self, proxies): + """Set a dictionary mapping URL scheme to proxy specification, or None. + + e.g. {"http": "joe:password@myproxy.example.com:3128", + "ftp": "proxy.example.com"} + + """ + self._set_handler("_proxy", obj=proxies) + + def add_password(self, url, user, password, realm=None): + self._password_manager.add_password(realm, url, user, password) + def add_proxy_password(self, user, password, hostport=None, realm=None): + self._proxy_password_manager.add_password( + realm, hostport, user, password) + + def add_client_certificate(self, url, key_file, cert_file): + """Add an SSL client certificate, for HTTPS client auth. + + key_file and cert_file must be filenames of the key and certificate + files, in PEM format. You can use e.g. OpenSSL to convert a p12 (PKCS + 12) file to PEM format: + + openssl pkcs12 -clcerts -nokeys -in cert.p12 -out cert.pem + openssl pkcs12 -nocerts -in cert.p12 -out key.pem + + + Note that client certificate password input is very inflexible ATM. At + the moment this seems to be console only, which is presumably the + default behaviour of libopenssl. In future mechanize may support + third-party libraries that (I assume) allow more options here. + + """ + self._client_cert_manager.add_key_cert(url, key_file, cert_file) + + # the following are rarely useful -- use add_password / add_proxy_password + # instead + def set_password_manager(self, password_manager): + """Set a mechanize.HTTPPasswordMgrWithDefaultRealm, or None.""" + self._password_manager = password_manager + self._set_handler("_basicauth", obj=password_manager) + self._set_handler("_digestauth", obj=password_manager) + def set_proxy_password_manager(self, password_manager): + """Set a mechanize.HTTPProxyPasswordMgr, or None.""" + self._proxy_password_manager = password_manager + self._set_handler("_proxy_basicauth", obj=password_manager) + self._set_handler("_proxy_digestauth", obj=password_manager) + def set_client_cert_manager(self, cert_manager): + """Set a mechanize.HTTPClientCertMgr, or None.""" + self._client_cert_manager = cert_manager + handler = self._ua_handlers["https"] + handler.client_cert_manager = cert_manager + + # these methods all take a boolean parameter + def set_handle_robots(self, handle): + """Set whether to observe rules from robots.txt.""" + self._set_handler("_robots", handle) + def set_handle_redirect(self, handle): + """Set whether to handle HTTP 30x redirections.""" + self._set_handler("_redirect", handle) + def set_handle_refresh(self, handle, max_time=None, honor_time=True): + """Set whether to handle HTTP Refresh headers.""" + self._set_handler("_refresh", handle, constructor_kwds= + {"max_time": max_time, "honor_time": honor_time}) + def set_handle_equiv(self, handle, head_parser_class=None): + """Set whether to treat HTML http-equiv headers like HTTP headers. + + Response objects may be .seek()able if this is set (currently returned + responses are, raised HTTPError exception responses are not). + + """ + if head_parser_class is not None: + constructor_kwds = {"head_parser_class": head_parser_class} + else: + constructor_kwds={} + self._set_handler("_equiv", handle, constructor_kwds=constructor_kwds) + def set_handle_gzip(self, handle): + """Handle gzip transfer encoding. + + """ + if handle: + warnings.warn( + "gzip transfer encoding is experimental!", stacklevel=2) + self._set_handler("_gzip", handle) + def set_debug_redirects(self, handle): + """Log information about HTTP redirects (including refreshes). + + Logging is performed using module logging. The logger name is + "mechanize.http_redirects". To actually print some debug output, + eg: + + import sys, logging + logger = logging.getLogger("mechanize.http_redirects") + logger.addHandler(logging.StreamHandler(sys.stdout)) + logger.setLevel(logging.INFO) + + Other logger names relevant to this module: + + "mechanize.http_responses" + "mechanize.cookies" (or "cookielib" if running Python 2.4) + + To turn on everything: + + import sys, logging + logger = logging.getLogger("mechanize") + logger.addHandler(logging.StreamHandler(sys.stdout)) + logger.setLevel(logging.INFO) + + """ + self._set_handler("_debug_redirect", handle) + def set_debug_responses(self, handle): + """Log HTTP response bodies. + + See docstring for .set_debug_redirects() for details of logging. + + Response objects may be .seek()able if this is set (currently returned + responses are, raised HTTPError exception responses are not). + + """ + self._set_handler("_debug_response_body", handle) + def set_debug_http(self, handle): + """Print HTTP headers to sys.stdout.""" + level = int(bool(handle)) + for scheme in "http", "https": + h = self._ua_handlers.get(scheme) + if h is not None: + h.set_http_debuglevel(level) + + def _set_handler(self, name, handle=None, obj=None, + constructor_args=(), constructor_kwds={}): + if handle is None: + handle = obj is not None + if handle: + handler_class = self.handler_classes[name] + if obj is not None: + newhandler = handler_class(obj) + else: + newhandler = handler_class( + *constructor_args, **constructor_kwds) + else: + newhandler = None + self._replace_handler(name, newhandler) + + def _replace_handler(self, name, newhandler=None): + # first, if handler was previously added, remove it + if name is not None: + handler = self._ua_handlers.get(name) + if handler: + try: + self.handlers.remove(handler) + except ValueError: + pass + # then add the replacement, if any + if newhandler is not None: + self.add_handler(newhandler) + self._ua_handlers[name] = newhandler + + +class UserAgent(UserAgentBase): + + def __init__(self): + UserAgentBase.__init__(self) + self._seekable = False + + def set_seekable_responses(self, handle): + """Make response objects .seek()able.""" + self._seekable = bool(handle) + + def open(self, fullurl, data=None, + timeout=_sockettimeout._GLOBAL_DEFAULT_TIMEOUT): + if self._seekable: + def bound_open(fullurl, data=None, + timeout=_sockettimeout._GLOBAL_DEFAULT_TIMEOUT): + return UserAgentBase.open(self, fullurl, data, timeout) + response = _opener.wrapped_open( + bound_open, _response.seek_wrapped_response, fullurl, data, + timeout) + else: + response = UserAgentBase.open(self, fullurl, data) + return response diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_util.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_util.py new file mode 100644 index 0000000..dcdefa9 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/mechanize/_util.py @@ -0,0 +1,291 @@ +"""Utility functions and date/time routines. + + Copyright 2002-2006 John J Lee <jjl@pobox.com> + +This code is free software; you can redistribute it and/or modify it +under the terms of the BSD or ZPL 2.1 licenses (see the file +COPYING.txt included with the distribution). + +""" + +import re, time, warnings + + +class ExperimentalWarning(UserWarning): + pass + +def experimental(message): + warnings.warn(message, ExperimentalWarning, stacklevel=3) +def hide_experimental_warnings(): + warnings.filterwarnings("ignore", category=ExperimentalWarning) +def reset_experimental_warnings(): + warnings.filterwarnings("default", category=ExperimentalWarning) + +def deprecation(message): + warnings.warn(message, DeprecationWarning, stacklevel=3) +def hide_deprecations(): + warnings.filterwarnings("ignore", category=DeprecationWarning) +def reset_deprecations(): + warnings.filterwarnings("default", category=DeprecationWarning) + + +def isstringlike(x): + try: x+"" + except: return False + else: return True + +## def caller(): +## try: +## raise SyntaxError +## except: +## import sys +## return sys.exc_traceback.tb_frame.f_back.f_back.f_code.co_name + + +from calendar import timegm + +# Date/time conversion routines for formats used by the HTTP protocol. + +EPOCH = 1970 +def my_timegm(tt): + year, month, mday, hour, min, sec = tt[:6] + if ((year >= EPOCH) and (1 <= month <= 12) and (1 <= mday <= 31) and + (0 <= hour <= 24) and (0 <= min <= 59) and (0 <= sec <= 61)): + return timegm(tt) + else: + return None + +days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] +months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] +months_lower = [] +for month in months: months_lower.append(month.lower()) + + +def time2isoz(t=None): + """Return a string representing time in seconds since epoch, t. + + If the function is called without an argument, it will use the current + time. + + The format of the returned string is like "YYYY-MM-DD hh:mm:ssZ", + representing Universal Time (UTC, aka GMT). An example of this format is: + + 1994-11-24 08:49:37Z + + """ + if t is None: t = time.time() + year, mon, mday, hour, min, sec = time.gmtime(t)[:6] + return "%04d-%02d-%02d %02d:%02d:%02dZ" % ( + year, mon, mday, hour, min, sec) + +def time2netscape(t=None): + """Return a string representing time in seconds since epoch, t. + + If the function is called without an argument, it will use the current + time. + + The format of the returned string is like this: + + Wed, DD-Mon-YYYY HH:MM:SS GMT + + """ + if t is None: t = time.time() + year, mon, mday, hour, min, sec, wday = time.gmtime(t)[:7] + return "%s %02d-%s-%04d %02d:%02d:%02d GMT" % ( + days[wday], mday, months[mon-1], year, hour, min, sec) + + +UTC_ZONES = {"GMT": None, "UTC": None, "UT": None, "Z": None} + +timezone_re = re.compile(r"^([-+])?(\d\d?):?(\d\d)?$") +def offset_from_tz_string(tz): + offset = None + if UTC_ZONES.has_key(tz): + offset = 0 + else: + m = timezone_re.search(tz) + if m: + offset = 3600 * int(m.group(2)) + if m.group(3): + offset = offset + 60 * int(m.group(3)) + if m.group(1) == '-': + offset = -offset + return offset + +def _str2time(day, mon, yr, hr, min, sec, tz): + # translate month name to number + # month numbers start with 1 (January) + try: + mon = months_lower.index(mon.lower())+1 + except ValueError: + # maybe it's already a number + try: + imon = int(mon) + except ValueError: + return None + if 1 <= imon <= 12: + mon = imon + else: + return None + + # make sure clock elements are defined + if hr is None: hr = 0 + if min is None: min = 0 + if sec is None: sec = 0 + + yr = int(yr) + day = int(day) + hr = int(hr) + min = int(min) + sec = int(sec) + + if yr < 1000: + # find "obvious" year + cur_yr = time.localtime(time.time())[0] + m = cur_yr % 100 + tmp = yr + yr = yr + cur_yr - m + m = m - tmp + if abs(m) > 50: + if m > 0: yr = yr + 100 + else: yr = yr - 100 + + # convert UTC time tuple to seconds since epoch (not timezone-adjusted) + t = my_timegm((yr, mon, day, hr, min, sec, tz)) + + if t is not None: + # adjust time using timezone string, to get absolute time since epoch + if tz is None: + tz = "UTC" + tz = tz.upper() + offset = offset_from_tz_string(tz) + if offset is None: + return None + t = t - offset + + return t + + +strict_re = re.compile(r"^[SMTWF][a-z][a-z], (\d\d) ([JFMASOND][a-z][a-z]) " + r"(\d\d\d\d) (\d\d):(\d\d):(\d\d) GMT$") +wkday_re = re.compile( + r"^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[a-z]*,?\s*", re.I) +loose_http_re = re.compile( + r"""^ + (\d\d?) # day + (?:\s+|[-\/]) + (\w+) # month + (?:\s+|[-\/]) + (\d+) # year + (?: + (?:\s+|:) # separator before clock + (\d\d?):(\d\d) # hour:min + (?::(\d\d))? # optional seconds + )? # optional clock + \s* + ([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+)? # timezone + \s* + (?:\(\w+\))? # ASCII representation of timezone in parens. + \s*$""", re.X) +def http2time(text): + """Returns time in seconds since epoch of time represented by a string. + + Return value is an integer. + + None is returned if the format of str is unrecognized, the time is outside + the representable range, or the timezone string is not recognized. If the + string contains no timezone, UTC is assumed. + + The timezone in the string may be numerical (like "-0800" or "+0100") or a + string timezone (like "UTC", "GMT", "BST" or "EST"). Currently, only the + timezone strings equivalent to UTC (zero offset) are known to the function. + + The function loosely parses the following formats: + + Wed, 09 Feb 1994 22:23:32 GMT -- HTTP format + Tuesday, 08-Feb-94 14:15:29 GMT -- old rfc850 HTTP format + Tuesday, 08-Feb-1994 14:15:29 GMT -- broken rfc850 HTTP format + 09 Feb 1994 22:23:32 GMT -- HTTP format (no weekday) + 08-Feb-94 14:15:29 GMT -- rfc850 format (no weekday) + 08-Feb-1994 14:15:29 GMT -- broken rfc850 format (no weekday) + + The parser ignores leading and trailing whitespace. The time may be + absent. + + If the year is given with only 2 digits, the function will select the + century that makes the year closest to the current date. + + """ + # fast exit for strictly conforming string + m = strict_re.search(text) + if m: + g = m.groups() + mon = months_lower.index(g[1].lower()) + 1 + tt = (int(g[2]), mon, int(g[0]), + int(g[3]), int(g[4]), float(g[5])) + return my_timegm(tt) + + # No, we need some messy parsing... + + # clean up + text = text.lstrip() + text = wkday_re.sub("", text, 1) # Useless weekday + + # tz is time zone specifier string + day, mon, yr, hr, min, sec, tz = [None]*7 + + # loose regexp parse + m = loose_http_re.search(text) + if m is not None: + day, mon, yr, hr, min, sec, tz = m.groups() + else: + return None # bad format + + return _str2time(day, mon, yr, hr, min, sec, tz) + + +iso_re = re.compile( + """^ + (\d{4}) # year + [-\/]? + (\d\d?) # numerical month + [-\/]? + (\d\d?) # day + (?: + (?:\s+|[-:Tt]) # separator before clock + (\d\d?):?(\d\d) # hour:min + (?::?(\d\d(?:\.\d*)?))? # optional seconds (and fractional) + )? # optional clock + \s* + ([-+]?\d\d?:?(:?\d\d)? + |Z|z)? # timezone (Z is "zero meridian", i.e. GMT) + \s*$""", re.X) +def iso2time(text): + """ + As for http2time, but parses the ISO 8601 formats: + + 1994-02-03 14:15:29 -0100 -- ISO 8601 format + 1994-02-03 14:15:29 -- zone is optional + 1994-02-03 -- only date + 1994-02-03T14:15:29 -- Use T as separator + 19940203T141529Z -- ISO 8601 compact format + 19940203 -- only date + + """ + # clean up + text = text.lstrip() + + # tz is time zone specifier string + day, mon, yr, hr, min, sec, tz = [None]*7 + + # loose regexp parse + m = iso_re.search(text) + if m is not None: + # XXX there's an extra bit of the timezone I'm ignoring here: is + # this the right thing to do? + yr, mon, day, hr, min, sec, tz, _ = m.groups() + else: + return None # bad format + + return _str2time(day, mon, yr, hr, min, sec, tz) diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/pep8.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/pep8.py new file mode 100755 index 0000000..c319370 --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/pep8.py @@ -0,0 +1,1254 @@ +#!/usr/bin/python +# pep8.py - Check Python source code formatting, according to PEP 8 +# Copyright (C) 2006 Johann C. Rocholl <johann@rocholl.net> +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +""" +Check Python source code formatting, according to PEP 8: +http://www.python.org/dev/peps/pep-0008/ + +For usage and a list of options, try this: +$ python pep8.py -h + +This program and its regression test suite live here: +http://github.com/jcrocholl/pep8 + +Groups of errors and warnings: +E errors +W warnings +100 indentation +200 whitespace +300 blank lines +400 imports +500 line length +600 deprecation +700 statements + +You can add checks to this program by writing plugins. Each plugin is +a simple function that is called for each line of source code, either +physical or logical. + +Physical line: +- Raw line of text from the input file. + +Logical line: +- Multi-line statements converted to a single line. +- Stripped left and right. +- Contents of strings replaced with 'xxx' of same length. +- Comments removed. + +The check function requests physical or logical lines by the name of +the first argument: + +def maximum_line_length(physical_line) +def extraneous_whitespace(logical_line) +def blank_lines(logical_line, blank_lines, indent_level, line_number) + +The last example above demonstrates how check plugins can request +additional information with extra arguments. All attributes of the +Checker object are available. Some examples: + +lines: a list of the raw lines from the input file +tokens: the tokens that contribute to this logical line +line_number: line number in the input file +blank_lines: blank lines before this one +indent_char: first indentation character in this file (' ' or '\t') +indent_level: indentation (with tabs expanded to multiples of 8) +previous_indent_level: indentation on previous line +previous_logical: previous logical line + +The docstring of each check function shall be the relevant part of +text from PEP 8. It is printed if the user enables --show-pep8. +Several docstrings contain examples directly from the PEP 8 document. + +Okay: spam(ham[1], {eggs: 2}) +E201: spam( ham[1], {eggs: 2}) + +These examples are verified automatically when pep8.py is run with the +--doctest option. You can add examples for your own check functions. +The format is simple: "Okay" or error/warning code followed by colon +and space, the rest of the line is example source code. If you put 'r' +before the docstring, you can use \n for newline, \t for tab and \s +for space. + +""" + +__version__ = '0.5.0' + +import os +import sys +import re +import time +import inspect +import tokenize +from optparse import OptionParser +from keyword import iskeyword +from fnmatch import fnmatch + +DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git' +DEFAULT_IGNORE = ['E24'] + +INDENT_REGEX = re.compile(r'([ \t]*)') +RAISE_COMMA_REGEX = re.compile(r'raise\s+\w+\s*(,)') +SELFTEST_REGEX = re.compile(r'(Okay|[EW]\d{3}):\s(.*)') +ERRORCODE_REGEX = re.compile(r'[EW]\d{3}') +E301NOT_REGEX = re.compile(r'class |def |u?r?["\']') + +WHITESPACE = ' \t' + +BINARY_OPERATORS = ['**=', '*=', '+=', '-=', '!=', '<>', + '%=', '^=', '&=', '|=', '==', '/=', '//=', '>=', '<=', '>>=', '<<=', + '%', '^', '&', '|', '=', '/', '//', '>', '<', '>>', '<<'] +UNARY_OPERATORS = ['**', '*', '+', '-'] +OPERATORS = BINARY_OPERATORS + UNARY_OPERATORS + +options = None +args = None + + +############################################################################## +# Plugins (check functions) for physical lines +############################################################################## + + +def tabs_or_spaces(physical_line, indent_char): + r""" + Never mix tabs and spaces. + + The most popular way of indenting Python is with spaces only. The + second-most popular way is with tabs only. Code indented with a mixture + of tabs and spaces should be converted to using spaces exclusively. When + invoking the Python command line interpreter with the -t option, it issues + warnings about code that illegally mixes tabs and spaces. When using -tt + these warnings become errors. These options are highly recommended! + + Okay: if a == 0:\n a = 1\n b = 1 + E101: if a == 0:\n a = 1\n\tb = 1 + """ + indent = INDENT_REGEX.match(physical_line).group(1) + for offset, char in enumerate(indent): + if char != indent_char: + return offset, "E101 indentation contains mixed spaces and tabs" + + +def tabs_obsolete(physical_line): + r""" + For new projects, spaces-only are strongly recommended over tabs. Most + editors have features that make this easy to do. + + Okay: if True:\n return + W191: if True:\n\treturn + """ + indent = INDENT_REGEX.match(physical_line).group(1) + if indent.count('\t'): + return indent.index('\t'), "W191 indentation contains tabs" + + +def trailing_whitespace(physical_line): + """ + JCR: Trailing whitespace is superfluous. + + Okay: spam(1) + W291: spam(1)\s + """ + physical_line = physical_line.rstrip('\n') # chr(10), newline + physical_line = physical_line.rstrip('\r') # chr(13), carriage return + physical_line = physical_line.rstrip('\x0c') # chr(12), form feed, ^L + stripped = physical_line.rstrip() + if physical_line != stripped: + return len(stripped), "W291 trailing whitespace" + + +def trailing_blank_lines(physical_line, lines, line_number): + r""" + JCR: Trailing blank lines are superfluous. + + Okay: spam(1) + W391: spam(1)\n + """ + if physical_line.strip() == '' and line_number == len(lines): + return 0, "W391 blank line at end of file" + + +def missing_newline(physical_line): + """ + JCR: The last line should have a newline. + """ + if physical_line.rstrip() == physical_line: + return len(physical_line), "W292 no newline at end of file" + + +def maximum_line_length(physical_line): + """ + Limit all lines to a maximum of 79 characters. + + There are still many devices around that are limited to 80 character + lines; plus, limiting windows to 80 characters makes it possible to have + several windows side-by-side. The default wrapping on such devices looks + ugly. Therefore, please limit all lines to a maximum of 79 characters. + For flowing long blocks of text (docstrings or comments), limiting the + length to 72 characters is recommended. + """ + length = len(physical_line.rstrip()) + if length > 79: + return 79, "E501 line too long (%d characters)" % length + + +############################################################################## +# Plugins (check functions) for logical lines +############################################################################## + + +def blank_lines(logical_line, blank_lines, indent_level, line_number, + previous_logical, blank_lines_before_comment): + r""" + Separate top-level function and class definitions with two blank lines. + + Method definitions inside a class are separated by a single blank line. + + Extra blank lines may be used (sparingly) to separate groups of related + functions. Blank lines may be omitted between a bunch of related + one-liners (e.g. a set of dummy implementations). + + Use blank lines in functions, sparingly, to indicate logical sections. + + Okay: def a():\n pass\n\n\ndef b():\n pass + Okay: def a():\n pass\n\n\n# Foo\n# Bar\n\ndef b():\n pass + + E301: class Foo:\n b = 0\n def bar():\n pass + E302: def a():\n pass\n\ndef b(n):\n pass + E303: def a():\n pass\n\n\n\ndef b(n):\n pass + E303: def a():\n\n\n\n pass + E304: @decorator\n\ndef a():\n pass + """ + if line_number == 1: + return # Don't expect blank lines before the first line + max_blank_lines = max(blank_lines, blank_lines_before_comment) + if previous_logical.startswith('@'): + if max_blank_lines: + return 0, "E304 blank lines found after function decorator" + elif max_blank_lines > 2 or (indent_level and max_blank_lines == 2): + return 0, "E303 too many blank lines (%d)" % max_blank_lines + elif (logical_line.startswith('def ') or + logical_line.startswith('class ') or + logical_line.startswith('@')): + if indent_level: + if not (max_blank_lines or E301NOT_REGEX.match(previous_logical)): + return 0, "E301 expected 1 blank line, found 0" + elif max_blank_lines != 2: + return 0, "E302 expected 2 blank lines, found %d" % max_blank_lines + + +def extraneous_whitespace(logical_line): + """ + Avoid extraneous whitespace in the following situations: + + - Immediately inside parentheses, brackets or braces. + + - Immediately before a comma, semicolon, or colon. + + Okay: spam(ham[1], {eggs: 2}) + E201: spam( ham[1], {eggs: 2}) + E201: spam(ham[ 1], {eggs: 2}) + E201: spam(ham[1], { eggs: 2}) + E202: spam(ham[1], {eggs: 2} ) + E202: spam(ham[1 ], {eggs: 2}) + E202: spam(ham[1], {eggs: 2 }) + + E203: if x == 4: print x, y; x, y = y , x + E203: if x == 4: print x, y ; x, y = y, x + E203: if x == 4 : print x, y; x, y = y, x + """ + line = logical_line + for char in '([{': + found = line.find(char + ' ') + if found > -1: + return found + 1, "E201 whitespace after '%s'" % char + for char in '}])': + found = line.find(' ' + char) + if found > -1 and line[found - 1] != ',': + return found, "E202 whitespace before '%s'" % char + for char in ',;:': + found = line.find(' ' + char) + if found > -1: + return found, "E203 whitespace before '%s'" % char + + +def missing_whitespace(logical_line): + """ + JCR: Each comma, semicolon or colon should be followed by whitespace. + + Okay: [a, b] + Okay: (3,) + Okay: a[1:4] + Okay: a[:4] + Okay: a[1:] + Okay: a[1:4:2] + E231: ['a','b'] + E231: foo(bar,baz) + """ + line = logical_line + for index in range(len(line) - 1): + char = line[index] + if char in ',;:' and line[index + 1] not in WHITESPACE: + before = line[:index] + if char == ':' and before.count('[') > before.count(']'): + continue # Slice syntax, no space required + if char == ',' and line[index + 1] == ')': + continue # Allow tuple with only one element: (3,) + return index, "E231 missing whitespace after '%s'" % char + + +def indentation(logical_line, previous_logical, indent_char, + indent_level, previous_indent_level): + r""" + Use 4 spaces per indentation level. + + For really old code that you don't want to mess up, you can continue to + use 8-space tabs. + + Okay: a = 1 + Okay: if a == 0:\n a = 1 + E111: a = 1 + + Okay: for item in items:\n pass + E112: for item in items:\npass + + Okay: a = 1\nb = 2 + E113: a = 1\n b = 2 + """ + if indent_char == ' ' and indent_level % 4: + return 0, "E111 indentation is not a multiple of four" + indent_expect = previous_logical.endswith(':') + if indent_expect and indent_level <= previous_indent_level: + return 0, "E112 expected an indented block" + if indent_level > previous_indent_level and not indent_expect: + return 0, "E113 unexpected indentation" + + +def whitespace_before_parameters(logical_line, tokens): + """ + Avoid extraneous whitespace in the following situations: + + - Immediately before the open parenthesis that starts the argument + list of a function call. + + - Immediately before the open parenthesis that starts an indexing or + slicing. + + Okay: spam(1) + E211: spam (1) + + Okay: dict['key'] = list[index] + E211: dict ['key'] = list[index] + E211: dict['key'] = list [index] + """ + prev_type = tokens[0][0] + prev_text = tokens[0][1] + prev_end = tokens[0][3] + for index in range(1, len(tokens)): + token_type, text, start, end, line = tokens[index] + if (token_type == tokenize.OP and + text in '([' and + start != prev_end and + prev_type == tokenize.NAME and + (index < 2 or tokens[index - 2][1] != 'class') and + (not iskeyword(prev_text))): + return prev_end, "E211 whitespace before '%s'" % text + prev_type = token_type + prev_text = text + prev_end = end + + +def whitespace_around_operator(logical_line): + """ + Avoid extraneous whitespace in the following situations: + + - More than one space around an assignment (or other) operator to + align it with another. + + Okay: a = 12 + 3 + E221: a = 4 + 5 + E222: a = 4 + 5 + E223: a = 4\t+ 5 + E224: a = 4 +\t5 + """ + line = logical_line + for operator in OPERATORS: + found = line.find(' ' + operator) + if found > -1: + return found, "E221 multiple spaces before operator" + found = line.find(operator + ' ') + if found > -1: + return found, "E222 multiple spaces after operator" + found = line.find('\t' + operator) + if found > -1: + return found, "E223 tab before operator" + found = line.find(operator + '\t') + if found > -1: + return found, "E224 tab after operator" + + +def missing_whitespace_around_operator(logical_line, tokens): + r""" + - Always surround these binary operators with a single space on + either side: assignment (=), augmented assignment (+=, -= etc.), + comparisons (==, <, >, !=, <>, <=, >=, in, not in, is, is not), + Booleans (and, or, not). + + - Use spaces around arithmetic operators. + + Okay: i = i + 1 + Okay: submitted += 1 + Okay: x = x * 2 - 1 + Okay: hypot2 = x * x + y * y + Okay: c = (a + b) * (a - b) + Okay: foo(bar, key='word', *args, **kwargs) + Okay: baz(**kwargs) + Okay: negative = -1 + Okay: spam(-1) + Okay: alpha[:-i] + Okay: if not -5 < x < +5:\n pass + Okay: lambda *args, **kw: (args, kw) + + E225: i=i+1 + E225: submitted +=1 + E225: x = x*2 - 1 + E225: hypot2 = x*x + y*y + E225: c = (a+b) * (a-b) + E225: c = alpha -4 + E225: z = x **y + """ + parens = 0 + need_space = False + prev_type = tokenize.OP + prev_text = prev_end = None + for token_type, text, start, end, line in tokens: + if token_type in (tokenize.NL, tokenize.NEWLINE, tokenize.ERRORTOKEN): + # ERRORTOKEN is triggered by backticks in Python 3000 + continue + if text in ('(', 'lambda'): + parens += 1 + elif text == ')': + parens -= 1 + if need_space: + if start == prev_end: + return prev_end, "E225 missing whitespace around operator" + need_space = False + elif token_type == tokenize.OP: + if text == '=' and parens: + # Allow keyword args or defaults: foo(bar=None). + pass + elif text in BINARY_OPERATORS: + need_space = True + elif text in UNARY_OPERATORS: + if ((prev_type != tokenize.OP or prev_text in '}])') and not + (prev_type == tokenize.NAME and iskeyword(prev_text))): + # Allow unary operators: -123, -x, +1. + # Allow argument unpacking: foo(*args, **kwargs). + need_space = True + if need_space and start == prev_end: + return prev_end, "E225 missing whitespace around operator" + prev_type = token_type + prev_text = text + prev_end = end + + +def whitespace_around_comma(logical_line): + """ + Avoid extraneous whitespace in the following situations: + + - More than one space around an assignment (or other) operator to + align it with another. + + JCR: This should also be applied around comma etc. + Note: these checks are disabled by default + + Okay: a = (1, 2) + E241: a = (1, 2) + E242: a = (1,\t2) + """ + line = logical_line + for separator in ',;:': + found = line.find(separator + ' ') + if found > -1: + return found + 1, "E241 multiple spaces after '%s'" % separator + found = line.find(separator + '\t') + if found > -1: + return found + 1, "E242 tab after '%s'" % separator + + +def whitespace_around_named_parameter_equals(logical_line): + """ + Don't use spaces around the '=' sign when used to indicate a + keyword argument or a default parameter value. + + Okay: def complex(real, imag=0.0): + Okay: return magic(r=real, i=imag) + Okay: boolean(a == b) + Okay: boolean(a != b) + Okay: boolean(a <= b) + Okay: boolean(a >= b) + + E251: def complex(real, imag = 0.0): + E251: return magic(r = real, i = imag) + """ + parens = 0 + window = ' ' + equal_ok = ['==', '!=', '<=', '>='] + + for pos, c in enumerate(logical_line): + window = window[1:] + c + if parens: + if window[0] in WHITESPACE and window[1] == '=': + if window[1:] not in equal_ok: + issue = "E251 no spaces around keyword / parameter equals" + return pos, issue + if window[2] in WHITESPACE and window[1] == '=': + if window[:2] not in equal_ok: + issue = "E251 no spaces around keyword / parameter equals" + return pos, issue + if c == '(': + parens += 1 + elif c == ')': + parens -= 1 + + +def whitespace_before_inline_comment(logical_line, tokens): + """ + Separate inline comments by at least two spaces. + + An inline comment is a comment on the same line as a statement. Inline + comments should be separated by at least two spaces from the statement. + They should start with a # and a single space. + + Okay: x = x + 1 # Increment x + Okay: x = x + 1 # Increment x + E261: x = x + 1 # Increment x + E262: x = x + 1 #Increment x + E262: x = x + 1 # Increment x + """ + prev_end = (0, 0) + for token_type, text, start, end, line in tokens: + if token_type == tokenize.NL: + continue + if token_type == tokenize.COMMENT: + if not line[:start[1]].strip(): + continue + if prev_end[0] == start[0] and start[1] < prev_end[1] + 2: + return (prev_end, + "E261 at least two spaces before inline comment") + if (len(text) > 1 and text.startswith('# ') + or not text.startswith('# ')): + return start, "E262 inline comment should start with '# '" + else: + prev_end = end + + +def imports_on_separate_lines(logical_line): + r""" + Imports should usually be on separate lines. + + Okay: import os\nimport sys + E401: import sys, os + + Okay: from subprocess import Popen, PIPE + Okay: from myclas import MyClass + Okay: from foo.bar.yourclass import YourClass + Okay: import myclass + Okay: import foo.bar.yourclass + """ + line = logical_line + if line.startswith('import '): + found = line.find(',') + if found > -1: + return found, "E401 multiple imports on one line" + + +def compound_statements(logical_line): + r""" + Compound statements (multiple statements on the same line) are + generally discouraged. + + While sometimes it's okay to put an if/for/while with a small body + on the same line, never do this for multi-clause statements. Also + avoid folding such long lines! + + Okay: if foo == 'blah':\n do_blah_thing() + Okay: do_one() + Okay: do_two() + Okay: do_three() + + E701: if foo == 'blah': do_blah_thing() + E701: for x in lst: total += x + E701: while t < 10: t = delay() + E701: if foo == 'blah': do_blah_thing() + E701: else: do_non_blah_thing() + E701: try: something() + E701: finally: cleanup() + E701: if foo == 'blah': one(); two(); three() + + E702: do_one(); do_two(); do_three() + """ + line = logical_line + found = line.find(':') + if -1 < found < len(line) - 1: + before = line[:found] + if (before.count('{') <= before.count('}') and # {'a': 1} (dict) + before.count('[') <= before.count(']') and # [1:2] (slice) + not re.search(r'\blambda\b', before)): # lambda x: x + return found, "E701 multiple statements on one line (colon)" + found = line.find(';') + if -1 < found: + return found, "E702 multiple statements on one line (semicolon)" + + +def python_3000_has_key(logical_line): + """ + The {}.has_key() method will be removed in the future version of + Python. Use the 'in' operation instead, like: + d = {"a": 1, "b": 2} + if "b" in d: + print d["b"] + """ + pos = logical_line.find('.has_key(') + if pos > -1: + return pos, "W601 .has_key() is deprecated, use 'in'" + + +def python_3000_raise_comma(logical_line): + """ + When raising an exception, use "raise ValueError('message')" + instead of the older form "raise ValueError, 'message'". + + The paren-using form is preferred because when the exception arguments + are long or include string formatting, you don't need to use line + continuation characters thanks to the containing parentheses. The older + form will be removed in Python 3000. + """ + match = RAISE_COMMA_REGEX.match(logical_line) + if match: + return match.start(1), "W602 deprecated form of raising exception" + + +def python_3000_not_equal(logical_line): + """ + != can also be written <>, but this is an obsolete usage kept for + backwards compatibility only. New code should always use !=. + The older syntax is removed in Python 3000. + """ + pos = logical_line.find('<>') + if pos > -1: + return pos, "W603 '<>' is deprecated, use '!='" + + +def python_3000_backticks(logical_line): + """ + Backticks are removed in Python 3000. + Use repr() instead. + """ + pos = logical_line.find('`') + if pos > -1: + return pos, "W604 backticks are deprecated, use 'repr()'" + + +############################################################################## +# Helper functions +############################################################################## + + +def expand_indent(line): + """ + Return the amount of indentation. + Tabs are expanded to the next multiple of 8. + + >>> expand_indent(' ') + 4 + >>> expand_indent('\\t') + 8 + >>> expand_indent(' \\t') + 8 + >>> expand_indent(' \\t') + 8 + >>> expand_indent(' \\t') + 16 + """ + result = 0 + for char in line: + if char == '\t': + result = result // 8 * 8 + 8 + elif char == ' ': + result += 1 + else: + break + return result + + +def mute_string(text): + """ + Replace contents with 'xxx' to prevent syntax matching. + + >>> mute_string('"abc"') + '"xxx"' + >>> mute_string("'''abc'''") + "'''xxx'''" + >>> mute_string("r'abc'") + "r'xxx'" + """ + start = 1 + end = len(text) - 1 + # String modifiers (e.g. u or r) + if text.endswith('"'): + start += text.index('"') + elif text.endswith("'"): + start += text.index("'") + # Triple quotes + if text.endswith('"""') or text.endswith("'''"): + start += 2 + end -= 2 + return text[:start] + 'x' * (end - start) + text[end:] + + +def message(text): + """Print a message.""" + # print >> sys.stderr, options.prog + ': ' + text + # print >> sys.stderr, text + print(text) + + +############################################################################## +# Framework to run all checks +############################################################################## + + +def find_checks(argument_name): + """ + Find all globally visible functions where the first argument name + starts with argument_name. + """ + checks = [] + for name, function in globals().items(): + if not inspect.isfunction(function): + continue + args = inspect.getargspec(function)[0] + if args and args[0].startswith(argument_name): + codes = ERRORCODE_REGEX.findall(inspect.getdoc(function) or '') + for code in codes or ['']: + if not code or not ignore_code(code): + checks.append((name, function, args)) + break + checks.sort() + return checks + + +class Checker(object): + """ + Load a Python source file, tokenize it, check coding style. + """ + + def __init__(self, filename): + if filename: + self.filename = filename + try: + self.lines = open(filename).readlines() + except UnicodeDecodeError: + # Errors may occur with non-UTF8 files in Python 3000 + self.lines = open(filename, errors='replace').readlines() + else: + self.filename = 'stdin' + self.lines = [] + options.counters['physical lines'] = \ + options.counters.get('physical lines', 0) + len(self.lines) + + def readline(self): + """ + Get the next line from the input buffer. + """ + self.line_number += 1 + if self.line_number > len(self.lines): + return '' + return self.lines[self.line_number - 1] + + def readline_check_physical(self): + """ + Check and return the next physical line. This method can be + used to feed tokenize.generate_tokens. + """ + line = self.readline() + if line: + self.check_physical(line) + return line + + def run_check(self, check, argument_names): + """ + Run a check plugin. + """ + arguments = [] + for name in argument_names: + arguments.append(getattr(self, name)) + return check(*arguments) + + def check_physical(self, line): + """ + Run all physical checks on a raw input line. + """ + self.physical_line = line + if self.indent_char is None and len(line) and line[0] in ' \t': + self.indent_char = line[0] + for name, check, argument_names in options.physical_checks: + result = self.run_check(check, argument_names) + if result is not None: + offset, text = result + self.report_error(self.line_number, offset, text, check) + + def build_tokens_line(self): + """ + Build a logical line from tokens. + """ + self.mapping = [] + logical = [] + length = 0 + previous = None + for token in self.tokens: + token_type, text = token[0:2] + if token_type in (tokenize.COMMENT, tokenize.NL, + tokenize.INDENT, tokenize.DEDENT, + tokenize.NEWLINE): + continue + if token_type == tokenize.STRING: + text = mute_string(text) + if previous: + end_line, end = previous[3] + start_line, start = token[2] + if end_line != start_line: # different row + if self.lines[end_line - 1][end - 1] not in '{[(': + logical.append(' ') + length += 1 + elif end != start: # different column + fill = self.lines[end_line - 1][end:start] + logical.append(fill) + length += len(fill) + self.mapping.append((length, token)) + logical.append(text) + length += len(text) + previous = token + self.logical_line = ''.join(logical) + assert self.logical_line.lstrip() == self.logical_line + assert self.logical_line.rstrip() == self.logical_line + + def check_logical(self): + """ + Build a line from tokens and run all logical checks on it. + """ + options.counters['logical lines'] = \ + options.counters.get('logical lines', 0) + 1 + self.build_tokens_line() + first_line = self.lines[self.mapping[0][1][2][0] - 1] + indent = first_line[:self.mapping[0][1][2][1]] + self.previous_indent_level = self.indent_level + self.indent_level = expand_indent(indent) + if options.verbose >= 2: + print(self.logical_line[:80].rstrip()) + for name, check, argument_names in options.logical_checks: + if options.verbose >= 3: + print(' ', name) + result = self.run_check(check, argument_names) + if result is not None: + offset, text = result + if isinstance(offset, tuple): + original_number, original_offset = offset + else: + for token_offset, token in self.mapping: + if offset >= token_offset: + original_number = token[2][0] + original_offset = (token[2][1] + + offset - token_offset) + self.report_error(original_number, original_offset, + text, check) + self.previous_logical = self.logical_line + + def check_all(self): + """ + Run all checks on the input file. + """ + self.file_errors = 0 + self.line_number = 0 + self.indent_char = None + self.indent_level = 0 + self.previous_logical = '' + self.blank_lines = 0 + self.blank_lines_before_comment = 0 + self.tokens = [] + parens = 0 + for token in tokenize.generate_tokens(self.readline_check_physical): + # print(tokenize.tok_name[token[0]], repr(token)) + self.tokens.append(token) + token_type, text = token[0:2] + if token_type == tokenize.OP and text in '([{': + parens += 1 + if token_type == tokenize.OP and text in '}])': + parens -= 1 + if token_type == tokenize.NEWLINE and not parens: + self.check_logical() + self.blank_lines = 0 + self.blank_lines_before_comment = 0 + self.tokens = [] + if token_type == tokenize.NL and not parens: + if len(self.tokens) <= 1: + # The physical line contains only this token. + self.blank_lines += 1 + self.tokens = [] + if token_type == tokenize.COMMENT: + source_line = token[4] + token_start = token[2][1] + if source_line[:token_start].strip() == '': + self.blank_lines_before_comment = max(self.blank_lines, + self.blank_lines_before_comment) + self.blank_lines = 0 + if text.endswith('\n') and not parens: + # The comment also ends a physical line. This works around + # Python < 2.6 behaviour, which does not generate NL after + # a comment which is on a line by itself. + self.tokens = [] + return self.file_errors + + def report_error(self, line_number, offset, text, check): + """ + Report an error, according to options. + """ + if options.quiet == 1 and not self.file_errors: + message(self.filename) + self.file_errors += 1 + code = text[:4] + options.counters[code] = options.counters.get(code, 0) + 1 + options.messages[code] = text[5:] + if options.quiet: + return + if options.testsuite: + basename = os.path.basename(self.filename) + if basename[:4] != code: + return # Don't care about other errors or warnings + if 'not' not in basename: + return # Don't print the expected error message + if ignore_code(code): + return + if options.counters[code] == 1 or options.repeat: + message("%s:%s:%d: %s" % + (self.filename, line_number, offset + 1, text)) + if options.show_source: + line = self.lines[line_number - 1] + message(line.rstrip()) + message(' ' * offset + '^') + if options.show_pep8: + message(check.__doc__.lstrip('\n').rstrip()) + + +def input_file(filename): + """ + Run all checks on a Python source file. + """ + if excluded(filename): + return {} + if options.verbose: + message('checking ' + filename) + files_counter_before = options.counters.get('files', 0) + if options.testsuite: # Keep showing errors for multiple tests + options.counters = {} + options.counters['files'] = files_counter_before + 1 + errors = Checker(filename).check_all() + if options.testsuite: # Check if the expected error was found + basename = os.path.basename(filename) + code = basename[:4] + count = options.counters.get(code, 0) + if count == 0 and 'not' not in basename: + message("%s: error %s not found" % (filename, code)) + + +def input_dir(dirname): + """ + Check all Python source files in this directory and all subdirectories. + """ + dirname = dirname.rstrip('/') + if excluded(dirname): + return + for root, dirs, files in os.walk(dirname): + if options.verbose: + message('directory ' + root) + options.counters['directories'] = \ + options.counters.get('directories', 0) + 1 + dirs.sort() + for subdir in dirs: + if excluded(subdir): + dirs.remove(subdir) + files.sort() + for filename in files: + if filename_match(filename): + input_file(os.path.join(root, filename)) + + +def excluded(filename): + """ + Check if options.exclude contains a pattern that matches filename. + """ + basename = os.path.basename(filename) + for pattern in options.exclude: + if fnmatch(basename, pattern): + # print basename, 'excluded because it matches', pattern + return True + + +def filename_match(filename): + """ + Check if options.filename contains a pattern that matches filename. + If options.filename is unspecified, this always returns True. + """ + if not options.filename: + return True + for pattern in options.filename: + if fnmatch(filename, pattern): + return True + + +def ignore_code(code): + """ + Check if options.ignore contains a prefix of the error code. + If options.select contains a prefix of the error code, do not ignore it. + """ + for select in options.select: + if code.startswith(select): + return False + for ignore in options.ignore: + if code.startswith(ignore): + return True + + +def get_error_statistics(): + """Get error statistics.""" + return get_statistics("E") + + +def get_warning_statistics(): + """Get warning statistics.""" + return get_statistics("W") + + +def get_statistics(prefix=''): + """ + Get statistics for message codes that start with the prefix. + + prefix='' matches all errors and warnings + prefix='E' matches all errors + prefix='W' matches all warnings + prefix='E4' matches all errors that have to do with imports + """ + stats = [] + keys = list(options.messages.keys()) + keys.sort() + for key in keys: + if key.startswith(prefix): + stats.append('%-7s %s %s' % + (options.counters[key], key, options.messages[key])) + return stats + + +def get_count(prefix=''): + """Return the total count of errors and warnings.""" + keys = list(options.messages.keys()) + count = 0 + for key in keys: + if key.startswith(prefix): + count += options.counters[key] + return count + + +def print_statistics(prefix=''): + """Print overall statistics (number of errors and warnings).""" + for line in get_statistics(prefix): + print(line) + + +def print_benchmark(elapsed): + """ + Print benchmark numbers. + """ + print('%-7.2f %s' % (elapsed, 'seconds elapsed')) + keys = ['directories', 'files', + 'logical lines', 'physical lines'] + for key in keys: + if key in options.counters: + print('%-7d %s per second (%d total)' % ( + options.counters[key] / elapsed, key, + options.counters[key])) + + +def selftest(): + """ + Test all check functions with test cases in docstrings. + """ + count_passed = 0 + count_failed = 0 + checks = options.physical_checks + options.logical_checks + for name, check, argument_names in checks: + for line in check.__doc__.splitlines(): + line = line.lstrip() + match = SELFTEST_REGEX.match(line) + if match is None: + continue + code, source = match.groups() + checker = Checker(None) + for part in source.split(r'\n'): + part = part.replace(r'\t', '\t') + part = part.replace(r'\s', ' ') + checker.lines.append(part + '\n') + options.quiet = 2 + options.counters = {} + checker.check_all() + error = None + if code == 'Okay': + if len(options.counters) > 1: + codes = [key for key in options.counters.keys() + if key != 'logical lines'] + error = "incorrectly found %s" % ', '.join(codes) + elif options.counters.get(code, 0) == 0: + error = "failed to find %s" % code + if not error: + count_passed += 1 + else: + count_failed += 1 + if len(checker.lines) == 1: + print("pep8.py: %s: %s" % + (error, checker.lines[0].rstrip())) + else: + print("pep8.py: %s:" % error) + for line in checker.lines: + print(line.rstrip()) + if options.verbose: + print("%d passed and %d failed." % (count_passed, count_failed)) + if count_failed: + print("Test failed.") + else: + print("Test passed.") + + +def process_options(arglist=None): + """ + Process options passed either via arglist or via command line args. + """ + global options, args + parser = OptionParser(version=__version__, + usage="%prog [options] input ...") + parser.add_option('-v', '--verbose', default=0, action='count', + help="print status messages, or debug with -vv") + parser.add_option('-q', '--quiet', default=0, action='count', + help="report only file names, or nothing with -qq") + parser.add_option('-r', '--repeat', action='store_true', + help="show all occurrences of the same error") + parser.add_option('--exclude', metavar='patterns', default=DEFAULT_EXCLUDE, + help="exclude files or directories which match these " + "comma separated patterns (default: %s)" % + DEFAULT_EXCLUDE) + parser.add_option('--filename', metavar='patterns', default='*.py', + help="when parsing directories, only check filenames " + "matching these comma separated patterns (default: " + "*.py)") + parser.add_option('--select', metavar='errors', default='', + help="select errors and warnings (e.g. E,W6)") + parser.add_option('--ignore', metavar='errors', default='', + help="skip errors and warnings (e.g. E4,W)") + parser.add_option('--show-source', action='store_true', + help="show source code for each error") + parser.add_option('--show-pep8', action='store_true', + help="show text of PEP 8 for each error") + parser.add_option('--statistics', action='store_true', + help="count errors and warnings") + parser.add_option('--count', action='store_true', + help="print total number of errors and warnings " + "to standard error and set exit code to 1 if " + "total is not null") + parser.add_option('--benchmark', action='store_true', + help="measure processing speed") + parser.add_option('--testsuite', metavar='dir', + help="run regression tests from dir") + parser.add_option('--doctest', action='store_true', + help="run doctest on myself") + options, args = parser.parse_args(arglist) + if options.testsuite: + args.append(options.testsuite) + if len(args) == 0 and not options.doctest: + parser.error('input not specified') + options.prog = os.path.basename(sys.argv[0]) + options.exclude = options.exclude.split(',') + for index in range(len(options.exclude)): + options.exclude[index] = options.exclude[index].rstrip('/') + if options.filename: + options.filename = options.filename.split(',') + if options.select: + options.select = options.select.split(',') + else: + options.select = [] + if options.ignore: + options.ignore = options.ignore.split(',') + elif options.select: + # Ignore all checks which are not explicitly selected + options.ignore = [''] + elif options.testsuite or options.doctest: + # For doctest and testsuite, all checks are required + options.ignore = [] + else: + # The default choice: ignore controversial checks + options.ignore = DEFAULT_IGNORE + options.physical_checks = find_checks('physical_line') + options.logical_checks = find_checks('logical_line') + options.counters = {} + options.messages = {} + return options, args + + +def _main(): + """ + Parse options and run checks on Python source. + """ + options, args = process_options() + if options.doctest: + import doctest + doctest.testmod(verbose=options.verbose) + selftest() + start_time = time.time() + for path in args: + if os.path.isdir(path): + input_dir(path) + else: + input_file(path) + elapsed = time.time() - start_time + if options.statistics: + print_statistics() + if options.benchmark: + print_benchmark(elapsed) + if options.count: + count = get_count() + if count: + sys.stderr.write(str(count) + '\n') + sys.exit(1) + + +if __name__ == '__main__': + _main() diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/rietveld/.upload.py.url b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/rietveld/.upload.py.url new file mode 100644 index 0000000..8098dbc --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/rietveld/.upload.py.url @@ -0,0 +1 @@ +http://webkit-rietveld.googlecode.com/svn/trunk/static/upload.py
\ No newline at end of file diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/rietveld/__init__.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/rietveld/__init__.py new file mode 100644 index 0000000..c1e4c6d --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/rietveld/__init__.py @@ -0,0 +1 @@ +# This file is required for Python to search this directory for modules. diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/rietveld/upload.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/rietveld/upload.py new file mode 100755 index 0000000..e91060f --- /dev/null +++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstalled/rietveld/upload.py @@ -0,0 +1,1702 @@ +#!/usr/bin/env python +# +# Copyright 2007 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tool for uploading diffs from a version control system to the codereview app. + +Usage summary: upload.py [options] [-- diff_options] + +Diff options are passed to the diff command of the underlying system. + +Supported version control systems: + Git + Mercurial + Subversion + +It is important for Git/Mercurial users to specify a tree/node/branch to diff +against by using the '--rev' option. +""" +# This code is derived from appcfg.py in the App Engine SDK (open source), +# and from ASPN recipe #146306. + +import ConfigParser +import cookielib +import fnmatch +import getpass +import logging +import mimetypes +import optparse +import os +import re +import socket +import subprocess +import sys +import urllib +import urllib2 +import urlparse + +# The md5 module was deprecated in Python 2.5. +try: + from hashlib import md5 +except ImportError: + from md5 import md5 + +try: + import readline +except ImportError: + pass + +# The logging verbosity: +# 0: Errors only. +# 1: Status messages. +# 2: Info logs. +# 3: Debug logs. +verbosity = 1 + +# Max size of patch or base file. +MAX_UPLOAD_SIZE = 900 * 1024 + +# Constants for version control names. Used by GuessVCSName. +VCS_GIT = "Git" +VCS_MERCURIAL = "Mercurial" +VCS_SUBVERSION = "Subversion" +VCS_UNKNOWN = "Unknown" + +# whitelist for non-binary filetypes which do not start with "text/" +# .mm (Objective-C) shows up as application/x-freemind on my Linux box. +TEXT_MIMETYPES = ['application/javascript', 'application/x-javascript', + 'application/xml', 'application/x-freemind'] + +VCS_ABBREVIATIONS = { + VCS_MERCURIAL.lower(): VCS_MERCURIAL, + "hg": VCS_MERCURIAL, + VCS_SUBVERSION.lower(): VCS_SUBVERSION, + "svn": VCS_SUBVERSION, + VCS_GIT.lower(): VCS_GIT, +} + +# The result of parsing Subversion's [auto-props] setting. +svn_auto_props_map = None + +def GetEmail(prompt): + """Prompts the user for their email address and returns it. + + The last used email address is saved to a file and offered up as a suggestion + to the user. If the user presses enter without typing in anything the last + used email address is used. If the user enters a new address, it is saved + for next time we prompt. + + """ + last_email_file_name = os.path.expanduser("~/.last_codereview_email_address") + last_email = "" + if os.path.exists(last_email_file_name): + try: + last_email_file = open(last_email_file_name, "r") + last_email = last_email_file.readline().strip("\n") + last_email_file.close() + prompt += " [%s]" % last_email + except IOError, e: + pass + email = raw_input(prompt + ": ").strip() + if email: + try: + last_email_file = open(last_email_file_name, "w") + last_email_file.write(email) + last_email_file.close() + except IOError, e: + pass + else: + email = last_email + return email + + +def StatusUpdate(msg): + """Print a status message to stdout. + + If 'verbosity' is greater than 0, print the message. + + Args: + msg: The string to print. + """ + if verbosity > 0: + print msg + + +def ErrorExit(msg): + """Print an error message to stderr and exit.""" + print >>sys.stderr, msg + sys.exit(1) + + +class ClientLoginError(urllib2.HTTPError): + """Raised to indicate there was an error authenticating with ClientLogin.""" + + def __init__(self, url, code, msg, headers, args): + urllib2.HTTPError.__init__(self, url, code, msg, headers, None) + self.args = args + self.reason = args["Error"] + + +class AbstractRpcServer(object): + """Provides a common interface for a simple RPC server.""" + + def __init__(self, host, auth_function, host_override=None, extra_headers={}, + save_cookies=False): + """Creates a new HttpRpcServer. + + Args: + host: The host to send requests to. + auth_function: A function that takes no arguments and returns an + (email, password) tuple when called. Will be called if authentication + is required. + host_override: The host header to send to the server (defaults to host). + extra_headers: A dict of extra headers to append to every request. + save_cookies: If True, save the authentication cookies to local disk. + If False, use an in-memory cookiejar instead. Subclasses must + implement this functionality. Defaults to False. + """ + self.host = host + self.host_override = host_override + self.auth_function = auth_function + self.authenticated = False + self.extra_headers = extra_headers + self.save_cookies = save_cookies + self.opener = self._GetOpener() + if self.host_override: + logging.info("Server: %s; Host: %s", self.host, self.host_override) + else: + logging.info("Server: %s", self.host) + + def _GetOpener(self): + """Returns an OpenerDirector for making HTTP requests. + + Returns: + A urllib2.OpenerDirector object. + """ + raise NotImplementedError() + + def _CreateRequest(self, url, data=None): + """Creates a new urllib request.""" + logging.debug("Creating request for: '%s' with payload:\n%s", url, data) + req = urllib2.Request(url, data=data) + if self.host_override: + req.add_header("Host", self.host_override) + for key, value in self.extra_headers.iteritems(): + req.add_header(key, value) + return req + + def _GetAuthToken(self, email, password): + """Uses ClientLogin to authenticate the user, returning an auth token. + + Args: + email: The user's email address + password: The user's password + + Raises: + ClientLoginError: If there was an error authenticating with ClientLogin. + HTTPError: If there was some other form of HTTP error. + + Returns: + The authentication token returned by ClientLogin. + """ + account_type = "GOOGLE" + if self.host.endswith(".google.com"): + # Needed for use inside Google. + account_type = "HOSTED" + req = self._CreateRequest( + url="https://www.google.com/accounts/ClientLogin", + data=urllib.urlencode({ + "Email": email, + "Passwd": password, + "service": "ah", + "source": "rietveld-codereview-upload", + "accountType": account_type, + }), + ) + try: + response = self.opener.open(req) + response_body = response.read() + response_dict = dict(x.split("=") + for x in response_body.split("\n") if x) + return response_dict["Auth"] + except urllib2.HTTPError, e: + if e.code == 403: + body = e.read() + response_dict = dict(x.split("=", 1) for x in body.split("\n") if x) + raise ClientLoginError(req.get_full_url(), e.code, e.msg, + e.headers, response_dict) + else: + raise + + def _GetAuthCookie(self, auth_token): + """Fetches authentication cookies for an authentication token. + + Args: + auth_token: The authentication token returned by ClientLogin. + + Raises: + HTTPError: If there was an error fetching the authentication cookies. + """ + # This is a dummy value to allow us to identify when we're successful. + continue_location = "http://localhost/" + args = {"continue": continue_location, "auth": auth_token} + req = self._CreateRequest("http://%s/_ah/login?%s" % + (self.host, urllib.urlencode(args))) + try: + response = self.opener.open(req) + except urllib2.HTTPError, e: + response = e + if (response.code != 302 or + response.info()["location"] != continue_location): + raise urllib2.HTTPError(req.get_full_url(), response.code, response.msg, + response.headers, response.fp) + self.authenticated = True + + def _Authenticate(self): + """Authenticates the user. + + The authentication process works as follows: + 1) We get a username and password from the user + 2) We use ClientLogin to obtain an AUTH token for the user + (see http://code.google.com/apis/accounts/AuthForInstalledApps.html). + 3) We pass the auth token to /_ah/login on the server to obtain an + authentication cookie. If login was successful, it tries to redirect + us to the URL we provided. + + If we attempt to access the upload API without first obtaining an + authentication cookie, it returns a 401 response (or a 302) and + directs us to authenticate ourselves with ClientLogin. + """ + for i in range(3): + credentials = self.auth_function() + try: + auth_token = self._GetAuthToken(credentials[0], credentials[1]) + except ClientLoginError, e: + if e.reason == "BadAuthentication": + print >>sys.stderr, "Invalid username or password." + continue + if e.reason == "CaptchaRequired": + print >>sys.stderr, ( + "Please go to\n" + "https://www.google.com/accounts/DisplayUnlockCaptcha\n" + "and verify you are a human. Then try again.") + break + if e.reason == "NotVerified": + print >>sys.stderr, "Account not verified." + break + if e.reason == "TermsNotAgreed": + print >>sys.stderr, "User has not agreed to TOS." + break + if e.reason == "AccountDeleted": + print >>sys.stderr, "The user account has been deleted." + break + if e.reason == "AccountDisabled": + print >>sys.stderr, "The user account has been disabled." + break + if e.reason == "ServiceDisabled": + print >>sys.stderr, ("The user's access to the service has been " + "disabled.") + break + if e.reason == "ServiceUnavailable": + print >>sys.stderr, "The service is not available; try again later." + break + raise + self._GetAuthCookie(auth_token) + return + + def Send(self, request_path, payload=None, + content_type="application/octet-stream", + timeout=None, + **kwargs): + """Sends an RPC and returns the response. + + Args: + request_path: The path to send the request to, eg /api/appversion/create. + payload: The body of the request, or None to send an empty request. + content_type: The Content-Type header to use. + timeout: timeout in seconds; default None i.e. no timeout. + (Note: for large requests on OS X, the timeout doesn't work right.) + kwargs: Any keyword arguments are converted into query string parameters. + + Returns: + The response body, as a string. + """ + # TODO: Don't require authentication. Let the server say + # whether it is necessary. + if not self.authenticated: + self._Authenticate() + + old_timeout = socket.getdefaulttimeout() + socket.setdefaulttimeout(timeout) + try: + tries = 0 + while True: + tries += 1 + args = dict(kwargs) + url = "http://%s%s" % (self.host, request_path) + if args: + url += "?" + urllib.urlencode(args) + req = self._CreateRequest(url=url, data=payload) + req.add_header("Content-Type", content_type) + try: + f = self.opener.open(req) + response = f.read() + f.close() + return response + except urllib2.HTTPError, e: + if tries > 3: + raise + elif e.code == 401 or e.code == 302: + self._Authenticate() +## elif e.code >= 500 and e.code < 600: +## # Server Error - try again. +## continue + else: + raise + finally: + socket.setdefaulttimeout(old_timeout) + + +class HttpRpcServer(AbstractRpcServer): + """Provides a simplified RPC-style interface for HTTP requests.""" + + def _Authenticate(self): + """Save the cookie jar after authentication.""" + super(HttpRpcServer, self)._Authenticate() + if self.save_cookies: + StatusUpdate("Saving authentication cookies to %s" % self.cookie_file) + self.cookie_jar.save() + + def _GetOpener(self): + """Returns an OpenerDirector that supports cookies and ignores redirects. + + Returns: + A urllib2.OpenerDirector object. + """ + opener = urllib2.OpenerDirector() + opener.add_handler(urllib2.ProxyHandler()) + opener.add_handler(urllib2.UnknownHandler()) + opener.add_handler(urllib2.HTTPHandler()) + opener.add_handler(urllib2.HTTPDefaultErrorHandler()) + opener.add_handler(urllib2.HTTPSHandler()) + opener.add_handler(urllib2.HTTPErrorProcessor()) + if self.save_cookies: + self.cookie_file = os.path.expanduser("~/.codereview_upload_cookies") + self.cookie_jar = cookielib.MozillaCookieJar(self.cookie_file) + if os.path.exists(self.cookie_file): + try: + self.cookie_jar.load() + self.authenticated = True + StatusUpdate("Loaded authentication cookies from %s" % + self.cookie_file) + except (cookielib.LoadError, IOError): + # Failed to load cookies - just ignore them. + pass + else: + # Create an empty cookie file with mode 600 + fd = os.open(self.cookie_file, os.O_CREAT, 0600) + os.close(fd) + # Always chmod the cookie file + os.chmod(self.cookie_file, 0600) + else: + # Don't save cookies across runs of update.py. + self.cookie_jar = cookielib.CookieJar() + opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar)) + return opener + + +parser = optparse.OptionParser(usage="%prog [options] [-- diff_options]") +parser.add_option("-y", "--assume_yes", action="store_true", + dest="assume_yes", default=False, + help="Assume that the answer to yes/no questions is 'yes'.") +# Logging +group = parser.add_option_group("Logging options") +group.add_option("-q", "--quiet", action="store_const", const=0, + dest="verbose", help="Print errors only.") +group.add_option("-v", "--verbose", action="store_const", const=2, + dest="verbose", default=1, + help="Print info level logs (default).") +group.add_option("--noisy", action="store_const", const=3, + dest="verbose", help="Print all logs.") +# Review server +group = parser.add_option_group("Review server options") +group.add_option("-s", "--server", action="store", dest="server", + default="codereview.appspot.com", + metavar="SERVER", + help=("The server to upload to. The format is host[:port]. " + "Defaults to '%default'.")) +group.add_option("-e", "--email", action="store", dest="email", + metavar="EMAIL", default=None, + help="The username to use. Will prompt if omitted.") +group.add_option("-H", "--host", action="store", dest="host", + metavar="HOST", default=None, + help="Overrides the Host header sent with all RPCs.") +group.add_option("--no_cookies", action="store_false", + dest="save_cookies", default=True, + help="Do not save authentication cookies to local disk.") +# Issue +group = parser.add_option_group("Issue options") +group.add_option("-d", "--description", action="store", dest="description", + metavar="DESCRIPTION", default=None, + help="Optional description when creating an issue.") +group.add_option("-f", "--description_file", action="store", + dest="description_file", metavar="DESCRIPTION_FILE", + default=None, + help="Optional path of a file that contains " + "the description when creating an issue.") +group.add_option("-r", "--reviewers", action="store", dest="reviewers", + metavar="REVIEWERS", default=None, + help="Add reviewers (comma separated email addresses).") +group.add_option("--cc", action="store", dest="cc", + metavar="CC", default=None, + help="Add CC (comma separated email addresses).") +group.add_option("--private", action="store_true", dest="private", + default=False, + help="Make the issue restricted to reviewers and those CCed") +# Upload options +group = parser.add_option_group("Patch options") +group.add_option("-m", "--message", action="store", dest="message", + metavar="MESSAGE", default=None, + help="A message to identify the patch. " + "Will prompt if omitted.") +group.add_option("-i", "--issue", type="int", action="store", + metavar="ISSUE", default=None, + help="Issue number to which to add. Defaults to new issue.") +group.add_option("--base_url", action="store", dest="base_url", default=None, + help="Base repository URL (listed as \"Base URL\" when " + "viewing issue). If omitted, will be guessed automatically " + "for SVN repos and left blank for others.") +group.add_option("--download_base", action="store_true", + dest="download_base", default=False, + help="Base files will be downloaded by the server " + "(side-by-side diffs may not work on files with CRs).") +group.add_option("--rev", action="store", dest="revision", + metavar="REV", default=None, + help="Base revision/branch/tree to diff against. Use " + "rev1:rev2 range to review already committed changeset.") +group.add_option("--send_mail", action="store_true", + dest="send_mail", default=False, + help="Send notification email to reviewers.") +group.add_option("--vcs", action="store", dest="vcs", + metavar="VCS", default=None, + help=("Version control system (optional, usually upload.py " + "already guesses the right VCS).")) +group.add_option("--emulate_svn_auto_props", action="store_true", + dest="emulate_svn_auto_props", default=False, + help=("Emulate Subversion's auto properties feature.")) + + +def GetRpcServer(server, email=None, host_override=None, save_cookies=True): + """Returns an instance of an AbstractRpcServer. + + Args: + server: String containing the review server URL. + email: String containing user's email address. + host_override: If not None, string containing an alternate hostname to use + in the host header. + save_cookies: Whether authentication cookies should be saved to disk. + + Returns: + A new AbstractRpcServer, on which RPC calls can be made. + """ + + rpc_server_class = HttpRpcServer + + def GetUserCredentials(): + """Prompts the user for a username and password.""" + if email is None: + email = GetEmail("Email (login for uploading to %s)" % server) + password = getpass.getpass("Password for %s: " % email) + return (email, password) + + # If this is the dev_appserver, use fake authentication. + host = (host_override or server).lower() + if host == "localhost" or host.startswith("localhost:"): + if email is None: + email = "test@example.com" + logging.info("Using debug user %s. Override with --email" % email) + server = rpc_server_class( + server, + lambda: (email, "password"), + host_override=host_override, + extra_headers={"Cookie": + 'dev_appserver_login="%s:False"' % email}, + save_cookies=save_cookies) + # Don't try to talk to ClientLogin. + server.authenticated = True + return server + + return rpc_server_class(server, + GetUserCredentials, + host_override=host_override, + save_cookies=save_cookies) + + +def EncodeMultipartFormData(fields, files): + """Encode form fields for multipart/form-data. + + Args: + fields: A sequence of (name, value) elements for regular form fields. + files: A sequence of (name, filename, value) elements for data to be + uploaded as files. + Returns: + (content_type, body) ready for httplib.HTTP instance. + + Source: + http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306 + """ + BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-' + CRLF = '\r\n' + lines = [] + for (key, value) in fields: + lines.append('--' + BOUNDARY) + lines.append('Content-Disposition: form-data; name="%s"' % key) + lines.append('') + lines.append(value) + for (key, filename, value) in files: + lines.append('--' + BOUNDARY) + lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' % + (key, filename)) + lines.append('Content-Type: %s' % GetContentType(filename)) + lines.append('') + lines.append(value) + lines.append('--' + BOUNDARY + '--') + lines.append('') + body = CRLF.join(lines) + content_type = 'multipart/form-data; boundary=%s' % BOUNDARY + return content_type, body + + +def GetContentType(filename): + """Helper to guess the content-type from the filename.""" + return mimetypes.guess_type(filename)[0] or 'application/octet-stream' + + +# Use a shell for subcommands on Windows to get a PATH search. +use_shell = sys.platform.startswith("win") + +def RunShellWithReturnCode(command, print_output=False, + universal_newlines=True, + env=os.environ): + """Executes a command and returns the output from stdout and the return code. + + Args: + command: Command to execute. + print_output: If True, the output is printed to stdout. + If False, both stdout and stderr are ignored. + universal_newlines: Use universal_newlines flag (default: True). + + Returns: + Tuple (output, return code) + """ + logging.info("Running %s", command) + p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + shell=use_shell, universal_newlines=universal_newlines, + env=env) + if print_output: + output_array = [] + while True: + line = p.stdout.readline() + if not line: + break + print line.strip("\n") + output_array.append(line) + output = "".join(output_array) + else: + output = p.stdout.read() + p.wait() + errout = p.stderr.read() + if print_output and errout: + print >>sys.stderr, errout + p.stdout.close() + p.stderr.close() + return output, p.returncode + + +def RunShell(command, silent_ok=False, universal_newlines=True, + print_output=False, env=os.environ): + data, retcode = RunShellWithReturnCode(command, print_output, + universal_newlines, env) + if retcode: + ErrorExit("Got error status from %s:\n%s" % (command, data)) + if not silent_ok and not data: + ErrorExit("No output from %s" % command) + return data + + +class VersionControlSystem(object): + """Abstract base class providing an interface to the VCS.""" + + def __init__(self, options): + """Constructor. + + Args: + options: Command line options. + """ + self.options = options + + def GenerateDiff(self, args): + """Return the current diff as a string. + + Args: + args: Extra arguments to pass to the diff command. + """ + raise NotImplementedError( + "abstract method -- subclass %s must override" % self.__class__) + + def GetUnknownFiles(self): + """Return a list of files unknown to the VCS.""" + raise NotImplementedError( + "abstract method -- subclass %s must override" % self.__class__) + + def CheckForUnknownFiles(self): + """Show an "are you sure?" prompt if there are unknown files.""" + unknown_files = self.GetUnknownFiles() + if unknown_files: + print "The following files are not added to version control:" + for line in unknown_files: + print line + prompt = "Are you sure to continue?(y/N) " + answer = raw_input(prompt).strip() + if answer != "y": + ErrorExit("User aborted") + + def GetBaseFile(self, filename): + """Get the content of the upstream version of a file. + + Returns: + A tuple (base_content, new_content, is_binary, status) + base_content: The contents of the base file. + new_content: For text files, this is empty. For binary files, this is + the contents of the new file, since the diff output won't contain + information to reconstruct the current file. + is_binary: True iff the file is binary. + status: The status of the file. + """ + + raise NotImplementedError( + "abstract method -- subclass %s must override" % self.__class__) + + + def GetBaseFiles(self, diff): + """Helper that calls GetBase file for each file in the patch. + + Returns: + A dictionary that maps from filename to GetBaseFile's tuple. Filenames + are retrieved based on lines that start with "Index:" or + "Property changes on:". + """ + files = {} + for line in diff.splitlines(True): + if line.startswith('Index:') or line.startswith('Property changes on:'): + unused, filename = line.split(':', 1) + # On Windows if a file has property changes its filename uses '\' + # instead of '/'. + filename = filename.strip().replace('\\', '/') + files[filename] = self.GetBaseFile(filename) + return files + + + def UploadBaseFiles(self, issue, rpc_server, patch_list, patchset, options, + files): + """Uploads the base files (and if necessary, the current ones as well).""" + + def UploadFile(filename, file_id, content, is_binary, status, is_base): + """Uploads a file to the server.""" + file_too_large = False + if is_base: + type = "base" + else: + type = "current" + if len(content) > MAX_UPLOAD_SIZE: + print ("Not uploading the %s file for %s because it's too large." % + (type, filename)) + file_too_large = True + content = "" + checksum = md5(content).hexdigest() + if options.verbose > 0 and not file_too_large: + print "Uploading %s file for %s" % (type, filename) + url = "/%d/upload_content/%d/%d" % (int(issue), int(patchset), file_id) + form_fields = [("filename", filename), + ("status", status), + ("checksum", checksum), + ("is_binary", str(is_binary)), + ("is_current", str(not is_base)), + ] + if file_too_large: + form_fields.append(("file_too_large", "1")) + if options.email: + form_fields.append(("user", options.email)) + ctype, body = EncodeMultipartFormData(form_fields, + [("data", filename, content)]) + response_body = rpc_server.Send(url, body, + content_type=ctype) + if not response_body.startswith("OK"): + StatusUpdate(" --> %s" % response_body) + sys.exit(1) + + patches = dict() + [patches.setdefault(v, k) for k, v in patch_list] + for filename in patches.keys(): + base_content, new_content, is_binary, status = files[filename] + file_id_str = patches.get(filename) + if file_id_str.find("nobase") != -1: + base_content = None + file_id_str = file_id_str[file_id_str.rfind("_") + 1:] + file_id = int(file_id_str) + if base_content != None: + UploadFile(filename, file_id, base_content, is_binary, status, True) + if new_content != None: + UploadFile(filename, file_id, new_content, is_binary, status, False) + + def IsImage(self, filename): + """Returns true if the filename has an image extension.""" + mimetype = mimetypes.guess_type(filename)[0] + if not mimetype: + return False + return mimetype.startswith("image/") + + def IsBinary(self, filename): + """Returns true if the guessed mimetyped isnt't in text group.""" + mimetype = mimetypes.guess_type(filename)[0] + if not mimetype: + return False # e.g. README, "real" binaries usually have an extension + # special case for text files which don't start with text/ + if mimetype in TEXT_MIMETYPES: + return False + return not mimetype.startswith("text/") + + +class SubversionVCS(VersionControlSystem): + """Implementation of the VersionControlSystem interface for Subversion.""" + + def __init__(self, options): + super(SubversionVCS, self).__init__(options) + if self.options.revision: + match = re.match(r"(\d+)(:(\d+))?", self.options.revision) + if not match: + ErrorExit("Invalid Subversion revision %s." % self.options.revision) + self.rev_start = match.group(1) + self.rev_end = match.group(3) + else: + self.rev_start = self.rev_end = None + # Cache output from "svn list -r REVNO dirname". + # Keys: dirname, Values: 2-tuple (ouput for start rev and end rev). + self.svnls_cache = {} + # Base URL is required to fetch files deleted in an older revision. + # Result is cached to not guess it over and over again in GetBaseFile(). + required = self.options.download_base or self.options.revision is not None + self.svn_base = self._GuessBase(required) + + def GuessBase(self, required): + """Wrapper for _GuessBase.""" + return self.svn_base + + def _GuessBase(self, required): + """Returns the SVN base URL. + + Args: + required: If true, exits if the url can't be guessed, otherwise None is + returned. + """ + info = RunShell(["svn", "info"]) + for line in info.splitlines(): + words = line.split() + if len(words) == 2 and words[0] == "URL:": + url = words[1] + scheme, netloc, path, params, query, fragment = urlparse.urlparse(url) + username, netloc = urllib.splituser(netloc) + if username: + logging.info("Removed username from base URL") + if netloc.endswith("svn.python.org"): + if netloc == "svn.python.org": + if path.startswith("/projects/"): + path = path[9:] + elif netloc != "pythondev@svn.python.org": + ErrorExit("Unrecognized Python URL: %s" % url) + base = "http://svn.python.org/view/*checkout*%s/" % path + logging.info("Guessed Python base = %s", base) + elif netloc.endswith("svn.collab.net"): + if path.startswith("/repos/"): + path = path[6:] + base = "http://svn.collab.net/viewvc/*checkout*%s/" % path + logging.info("Guessed CollabNet base = %s", base) + elif netloc.endswith(".googlecode.com"): + path = path + "/" + base = urlparse.urlunparse(("http", netloc, path, params, + query, fragment)) + logging.info("Guessed Google Code base = %s", base) + else: + path = path + "/" + base = urlparse.urlunparse((scheme, netloc, path, params, + query, fragment)) + logging.info("Guessed base = %s", base) + return base + if required: + ErrorExit("Can't find URL in output from svn info") + return None + + def GenerateDiff(self, args): + cmd = ["svn", "diff"] + if self.options.revision: + cmd += ["-r", self.options.revision] + cmd.extend(args) + data = RunShell(cmd) + count = 0 + for line in data.splitlines(): + if line.startswith("Index:") or line.startswith("Property changes on:"): + count += 1 + logging.info(line) + if not count: + ErrorExit("No valid patches found in output from svn diff") + return data + + def _CollapseKeywords(self, content, keyword_str): + """Collapses SVN keywords.""" + # svn cat translates keywords but svn diff doesn't. As a result of this + # behavior patching.PatchChunks() fails with a chunk mismatch error. + # This part was originally written by the Review Board development team + # who had the same problem (http://reviews.review-board.org/r/276/). + # Mapping of keywords to known aliases + svn_keywords = { + # Standard keywords + 'Date': ['Date', 'LastChangedDate'], + 'Revision': ['Revision', 'LastChangedRevision', 'Rev'], + 'Author': ['Author', 'LastChangedBy'], + 'HeadURL': ['HeadURL', 'URL'], + 'Id': ['Id'], + + # Aliases + 'LastChangedDate': ['LastChangedDate', 'Date'], + 'LastChangedRevision': ['LastChangedRevision', 'Rev', 'Revision'], + 'LastChangedBy': ['LastChangedBy', 'Author'], + 'URL': ['URL', 'HeadURL'], + } + + def repl(m): + if m.group(2): + return "$%s::%s$" % (m.group(1), " " * len(m.group(3))) + return "$%s$" % m.group(1) + keywords = [keyword + for name in keyword_str.split(" ") + for keyword in svn_keywords.get(name, [])] + return re.sub(r"\$(%s):(:?)([^\$]+)\$" % '|'.join(keywords), repl, content) + + def GetUnknownFiles(self): + status = RunShell(["svn", "status", "--ignore-externals"], silent_ok=True) + unknown_files = [] + for line in status.split("\n"): + if line and line[0] == "?": + unknown_files.append(line) + return unknown_files + + def ReadFile(self, filename): + """Returns the contents of a file.""" + file = open(filename, 'rb') + result = "" + try: + result = file.read() + finally: + file.close() + return result + + def GetStatus(self, filename): + """Returns the status of a file.""" + if not self.options.revision: + status = RunShell(["svn", "status", "--ignore-externals", filename]) + if not status: + ErrorExit("svn status returned no output for %s" % filename) + status_lines = status.splitlines() + # If file is in a cl, the output will begin with + # "\n--- Changelist 'cl_name':\n". See + # http://svn.collab.net/repos/svn/trunk/notes/changelist-design.txt + if (len(status_lines) == 3 and + not status_lines[0] and + status_lines[1].startswith("--- Changelist")): + status = status_lines[2] + else: + status = status_lines[0] + # If we have a revision to diff against we need to run "svn list" + # for the old and the new revision and compare the results to get + # the correct status for a file. + else: + dirname, relfilename = os.path.split(filename) + if dirname not in self.svnls_cache: + cmd = ["svn", "list", "-r", self.rev_start, dirname or "."] + out, returncode = RunShellWithReturnCode(cmd) + if returncode: + ErrorExit("Failed to get status for %s." % filename) + old_files = out.splitlines() + args = ["svn", "list"] + if self.rev_end: + args += ["-r", self.rev_end] + cmd = args + [dirname or "."] + out, returncode = RunShellWithReturnCode(cmd) + if returncode: + ErrorExit("Failed to run command %s" % cmd) + self.svnls_cache[dirname] = (old_files, out.splitlines()) + old_files, new_files = self.svnls_cache[dirname] + if relfilename in old_files and relfilename not in new_files: + status = "D " + elif relfilename in old_files and relfilename in new_files: + status = "M " + else: + status = "A " + return status + + def GetBaseFile(self, filename): + status = self.GetStatus(filename) + base_content = None + new_content = None + + # If a file is copied its status will be "A +", which signifies + # "addition-with-history". See "svn st" for more information. We need to + # upload the original file or else diff parsing will fail if the file was + # edited. + if status[0] == "A" and status[3] != "+": + # We'll need to upload the new content if we're adding a binary file + # since diff's output won't contain it. + mimetype = RunShell(["svn", "propget", "svn:mime-type", filename], + silent_ok=True) + base_content = "" + is_binary = bool(mimetype) and not mimetype.startswith("text/") + if is_binary and self.IsImage(filename): + new_content = self.ReadFile(filename) + elif (status[0] in ("M", "D", "R") or + (status[0] == "A" and status[3] == "+") or # Copied file. + (status[0] == " " and status[1] == "M")): # Property change. + args = [] + if self.options.revision: + url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start) + else: + # Don't change filename, it's needed later. + url = filename + args += ["-r", "BASE"] + cmd = ["svn"] + args + ["propget", "svn:mime-type", url] + mimetype, returncode = RunShellWithReturnCode(cmd) + if returncode: + # File does not exist in the requested revision. + # Reset mimetype, it contains an error message. + mimetype = "" + get_base = False + is_binary = bool(mimetype) and not mimetype.startswith("text/") + if status[0] == " ": + # Empty base content just to force an upload. + base_content = "" + elif is_binary: + if self.IsImage(filename): + get_base = True + if status[0] == "M": + if not self.rev_end: + new_content = self.ReadFile(filename) + else: + url = "%s/%s@%s" % (self.svn_base, filename, self.rev_end) + new_content = RunShell(["svn", "cat", url], + universal_newlines=True, silent_ok=True) + else: + base_content = "" + else: + get_base = True + + if get_base: + if is_binary: + universal_newlines = False + else: + universal_newlines = True + if self.rev_start: + # "svn cat -r REV delete_file.txt" doesn't work. cat requires + # the full URL with "@REV" appended instead of using "-r" option. + url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start) + base_content = RunShell(["svn", "cat", url], + universal_newlines=universal_newlines, + silent_ok=True) + else: + base_content = RunShell(["svn", "cat", filename], + universal_newlines=universal_newlines, + silent_ok=True) + if not is_binary: + args = [] + if self.rev_start: + url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start) + else: + url = filename + args += ["-r", "BASE"] + cmd = ["svn"] + args + ["propget", "svn:keywords", url] + keywords, returncode = RunShellWithReturnCode(cmd) + if keywords and not returncode: + base_content = self._CollapseKeywords(base_content, keywords) + else: + StatusUpdate("svn status returned unexpected output: %s" % status) + sys.exit(1) + return base_content, new_content, is_binary, status[0:5] + + +class GitVCS(VersionControlSystem): + """Implementation of the VersionControlSystem interface for Git.""" + + def __init__(self, options): + super(GitVCS, self).__init__(options) + # Map of filename -> (hash before, hash after) of base file. + # Hashes for "no such file" are represented as None. + self.hashes = {} + # Map of new filename -> old filename for renames. + self.renames = {} + + def GenerateDiff(self, extra_args): + # This is more complicated than svn's GenerateDiff because we must convert + # the diff output to include an svn-style "Index:" line as well as record + # the hashes of the files, so we can upload them along with our diff. + + # Special used by git to indicate "no such content". + NULL_HASH = "0"*40 + + extra_args = extra_args[:] + if self.options.revision: + extra_args = [self.options.revision] + extra_args + + # --no-ext-diff is broken in some versions of Git, so try to work around + # this by overriding the environment (but there is still a problem if the + # git config key "diff.external" is used). + env = os.environ.copy() + if 'GIT_EXTERNAL_DIFF' in env: del env['GIT_EXTERNAL_DIFF'] + gitdiff = RunShell(["git", "diff", "--no-ext-diff", "--full-index", "-M"] + + extra_args, env=env) + + def IsFileNew(filename): + return filename in self.hashes and self.hashes[filename][0] is None + + def AddSubversionPropertyChange(filename): + """Add svn's property change information into the patch if given file is + new file. + + We use Subversion's auto-props setting to retrieve its property. + See http://svnbook.red-bean.com/en/1.1/ch07.html#svn-ch-7-sect-1.3.2 for + Subversion's [auto-props] setting. + """ + if self.options.emulate_svn_auto_props and IsFileNew(filename): + svnprops = GetSubversionPropertyChanges(filename) + if svnprops: + svndiff.append("\n" + svnprops + "\n") + + svndiff = [] + filecount = 0 + filename = None + for line in gitdiff.splitlines(): + match = re.match(r"diff --git a/(.*) b/(.*)$", line) + if match: + # Add auto property here for previously seen file. + if filename is not None: + AddSubversionPropertyChange(filename) + filecount += 1 + # Intentionally use the "after" filename so we can show renames. + filename = match.group(2) + svndiff.append("Index: %s\n" % filename) + if match.group(1) != match.group(2): + self.renames[match.group(2)] = match.group(1) + else: + # The "index" line in a git diff looks like this (long hashes elided): + # index 82c0d44..b2cee3f 100755 + # We want to save the left hash, as that identifies the base file. + match = re.match(r"index (\w+)\.\.(\w+)", line) + if match: + before, after = (match.group(1), match.group(2)) + if before == NULL_HASH: + before = None + if after == NULL_HASH: + after = None + self.hashes[filename] = (before, after) + svndiff.append(line + "\n") + if not filecount: + ErrorExit("No valid patches found in output from git diff") + # Add auto property for the last seen file. + assert filename is not None + AddSubversionPropertyChange(filename) + return "".join(svndiff) + + def GetUnknownFiles(self): + status = RunShell(["git", "ls-files", "--exclude-standard", "--others"], + silent_ok=True) + return status.splitlines() + + def GetFileContent(self, file_hash, is_binary): + """Returns the content of a file identified by its git hash.""" + data, retcode = RunShellWithReturnCode(["git", "show", file_hash], + universal_newlines=not is_binary) + if retcode: + ErrorExit("Got error status from 'git show %s'" % file_hash) + return data + + def GetBaseFile(self, filename): + hash_before, hash_after = self.hashes.get(filename, (None,None)) + base_content = None + new_content = None + is_binary = self.IsBinary(filename) + status = None + + if filename in self.renames: + status = "A +" # Match svn attribute name for renames. + if filename not in self.hashes: + # If a rename doesn't change the content, we never get a hash. + base_content = RunShell(["git", "show", "HEAD:" + filename]) + elif not hash_before: + status = "A" + base_content = "" + elif not hash_after: + status = "D" + else: + status = "M" + + is_image = self.IsImage(filename) + + # Grab the before/after content if we need it. + # We should include file contents if it's text or it's an image. + if not is_binary or is_image: + # Grab the base content if we don't have it already. + if base_content is None and hash_before: + base_content = self.GetFileContent(hash_before, is_binary) + # Only include the "after" file if it's an image; otherwise it + # it is reconstructed from the diff. + if is_image and hash_after: + new_content = self.GetFileContent(hash_after, is_binary) + + return (base_content, new_content, is_binary, status) + + +class MercurialVCS(VersionControlSystem): + """Implementation of the VersionControlSystem interface for Mercurial.""" + + def __init__(self, options, repo_dir): + super(MercurialVCS, self).__init__(options) + # Absolute path to repository (we can be in a subdir) + self.repo_dir = os.path.normpath(repo_dir) + # Compute the subdir + cwd = os.path.normpath(os.getcwd()) + assert cwd.startswith(self.repo_dir) + self.subdir = cwd[len(self.repo_dir):].lstrip(r"\/") + if self.options.revision: + self.base_rev = self.options.revision + else: + self.base_rev = RunShell(["hg", "parent", "-q"]).split(':')[1].strip() + + def _GetRelPath(self, filename): + """Get relative path of a file according to the current directory, + given its logical path in the repo.""" + assert filename.startswith(self.subdir), (filename, self.subdir) + return filename[len(self.subdir):].lstrip(r"\/") + + def GenerateDiff(self, extra_args): + # If no file specified, restrict to the current subdir + extra_args = extra_args or ["."] + cmd = ["hg", "diff", "--git", "-r", self.base_rev] + extra_args + data = RunShell(cmd, silent_ok=True) + svndiff = [] + filecount = 0 + for line in data.splitlines(): + m = re.match("diff --git a/(\S+) b/(\S+)", line) + if m: + # Modify line to make it look like as it comes from svn diff. + # With this modification no changes on the server side are required + # to make upload.py work with Mercurial repos. + # NOTE: for proper handling of moved/copied files, we have to use + # the second filename. + filename = m.group(2) + svndiff.append("Index: %s" % filename) + svndiff.append("=" * 67) + filecount += 1 + logging.info(line) + else: + svndiff.append(line) + if not filecount: + ErrorExit("No valid patches found in output from hg diff") + return "\n".join(svndiff) + "\n" + + def GetUnknownFiles(self): + """Return a list of files unknown to the VCS.""" + args = [] + status = RunShell(["hg", "status", "--rev", self.base_rev, "-u", "."], + silent_ok=True) + unknown_files = [] + for line in status.splitlines(): + st, fn = line.split(" ", 1) + if st == "?": + unknown_files.append(fn) + return unknown_files + + def GetBaseFile(self, filename): + # "hg status" and "hg cat" both take a path relative to the current subdir + # rather than to the repo root, but "hg diff" has given us the full path + # to the repo root. + base_content = "" + new_content = None + is_binary = False + oldrelpath = relpath = self._GetRelPath(filename) + # "hg status -C" returns two lines for moved/copied files, one otherwise + out = RunShell(["hg", "status", "-C", "--rev", self.base_rev, relpath]) + out = out.splitlines() + # HACK: strip error message about missing file/directory if it isn't in + # the working copy + if out[0].startswith('%s: ' % relpath): + out = out[1:] + if len(out) > 1: + # Moved/copied => considered as modified, use old filename to + # retrieve base contents + oldrelpath = out[1].strip() + status = "M" + else: + status, _ = out[0].split(' ', 1) + if ":" in self.base_rev: + base_rev = self.base_rev.split(":", 1)[0] + else: + base_rev = self.base_rev + if status != "A": + base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath], + silent_ok=True) + is_binary = "\0" in base_content # Mercurial's heuristic + if status != "R": + new_content = open(relpath, "rb").read() + is_binary = is_binary or "\0" in new_content + if is_binary and base_content: + # Fetch again without converting newlines + base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath], + silent_ok=True, universal_newlines=False) + if not is_binary or not self.IsImage(relpath): + new_content = None + return base_content, new_content, is_binary, status + + +# NOTE: The SplitPatch function is duplicated in engine.py, keep them in sync. +def SplitPatch(data): + """Splits a patch into separate pieces for each file. + + Args: + data: A string containing the output of svn diff. + + Returns: + A list of 2-tuple (filename, text) where text is the svn diff output + pertaining to filename. + """ + patches = [] + filename = None + diff = [] + for line in data.splitlines(True): + new_filename = None + if line.startswith('Index:'): + unused, new_filename = line.split(':', 1) + new_filename = new_filename.strip() + elif line.startswith('Property changes on:'): + unused, temp_filename = line.split(':', 1) + # When a file is modified, paths use '/' between directories, however + # when a property is modified '\' is used on Windows. Make them the same + # otherwise the file shows up twice. + temp_filename = temp_filename.strip().replace('\\', '/') + if temp_filename != filename: + # File has property changes but no modifications, create a new diff. + new_filename = temp_filename + if new_filename: + if filename and diff: + patches.append((filename, ''.join(diff))) + filename = new_filename + diff = [line] + continue + if diff is not None: + diff.append(line) + if filename and diff: + patches.append((filename, ''.join(diff))) + return patches + + +def UploadSeparatePatches(issue, rpc_server, patchset, data, options): + """Uploads a separate patch for each file in the diff output. + + Returns a list of [patch_key, filename] for each file. + """ + patches = SplitPatch(data) + rv = [] + for patch in patches: + if len(patch[1]) > MAX_UPLOAD_SIZE: + print ("Not uploading the patch for " + patch[0] + + " because the file is too large.") + continue + form_fields = [("filename", patch[0])] + if not options.download_base: + form_fields.append(("content_upload", "1")) + files = [("data", "data.diff", patch[1])] + ctype, body = EncodeMultipartFormData(form_fields, files) + url = "/%d/upload_patch/%d" % (int(issue), int(patchset)) + print "Uploading patch for " + patch[0] + response_body = rpc_server.Send(url, body, content_type=ctype) + lines = response_body.splitlines() + if not lines or lines[0] != "OK": + StatusUpdate(" --> %s" % response_body) + sys.exit(1) + rv.append([lines[1], patch[0]]) + return rv + + +def GuessVCSName(): + """Helper to guess the version control system. + + This examines the current directory, guesses which VersionControlSystem + we're using, and returns an string indicating which VCS is detected. + + Returns: + A pair (vcs, output). vcs is a string indicating which VCS was detected + and is one of VCS_GIT, VCS_MERCURIAL, VCS_SUBVERSION, or VCS_UNKNOWN. + output is a string containing any interesting output from the vcs + detection routine, or None if there is nothing interesting. + """ + # Mercurial has a command to get the base directory of a repository + # Try running it, but don't die if we don't have hg installed. + # NOTE: we try Mercurial first as it can sit on top of an SVN working copy. + try: + out, returncode = RunShellWithReturnCode(["hg", "root"]) + if returncode == 0: + return (VCS_MERCURIAL, out.strip()) + except OSError, (errno, message): + if errno != 2: # ENOENT -- they don't have hg installed. + raise + + # Subversion has a .svn in all working directories. + if os.path.isdir('.svn'): + logging.info("Guessed VCS = Subversion") + return (VCS_SUBVERSION, None) + + # Git has a command to test if you're in a git tree. + # Try running it, but don't die if we don't have git installed. + try: + out, returncode = RunShellWithReturnCode(["git", "rev-parse", + "--is-inside-work-tree"]) + if returncode == 0: + return (VCS_GIT, None) + except OSError, (errno, message): + if errno != 2: # ENOENT -- they don't have git installed. + raise + + return (VCS_UNKNOWN, None) + + +def GuessVCS(options): + """Helper to guess the version control system. + + This verifies any user-specified VersionControlSystem (by command line + or environment variable). If the user didn't specify one, this examines + the current directory, guesses which VersionControlSystem we're using, + and returns an instance of the appropriate class. Exit with an error + if we can't figure it out. + + Returns: + A VersionControlSystem instance. Exits if the VCS can't be guessed. + """ + vcs = options.vcs + if not vcs: + vcs = os.environ.get("CODEREVIEW_VCS") + if vcs: + v = VCS_ABBREVIATIONS.get(vcs.lower()) + if v is None: + ErrorExit("Unknown version control system %r specified." % vcs) + (vcs, extra_output) = (v, None) + else: + (vcs, extra_output) = GuessVCSName() + + if vcs == VCS_MERCURIAL: + if extra_output is None: + extra_output = RunShell(["hg", "root"]).strip() + return MercurialVCS(options, extra_output) + elif vcs == VCS_SUBVERSION: + return SubversionVCS(options) + elif vcs == VCS_GIT: + return GitVCS(options) + + ErrorExit(("Could not guess version control system. " + "Are you in a working copy directory?")) + + +def CheckReviewer(reviewer): + """Validate a reviewer -- either a nickname or an email addres. + + Args: + reviewer: A nickname or an email address. + + Calls ErrorExit() if it is an invalid email address. + """ + if "@" not in reviewer: + return # Assume nickname + parts = reviewer.split("@") + if len(parts) > 2: + ErrorExit("Invalid email address: %r" % reviewer) + assert len(parts) == 2 + if "." not in parts[1]: + ErrorExit("Invalid email address: %r" % reviewer) + + +def LoadSubversionAutoProperties(): + """Returns the content of [auto-props] section of Subversion's config file as + a dictionary. + + Returns: + A dictionary whose key-value pair corresponds the [auto-props] section's + key-value pair. + In following cases, returns empty dictionary: + - config file doesn't exist, or + - 'enable-auto-props' is not set to 'true-like-value' in [miscellany]. + """ + # Todo(hayato): Windows users might use different path for configuration file. + subversion_config = os.path.expanduser("~/.subversion/config") + if not os.path.exists(subversion_config): + return {} + config = ConfigParser.ConfigParser() + config.read(subversion_config) + if (config.has_section("miscellany") and + config.has_option("miscellany", "enable-auto-props") and + config.getboolean("miscellany", "enable-auto-props") and + config.has_section("auto-props")): + props = {} + for file_pattern in config.options("auto-props"): + props[file_pattern] = ParseSubversionPropertyValues( + config.get("auto-props", file_pattern)) + return props + else: + return {} + +def ParseSubversionPropertyValues(props): + """Parse the given property value which comes from [auto-props] section and + returns a list whose element is a (svn_prop_key, svn_prop_value) pair. + + See the following doctest for example. + + >>> ParseSubversionPropertyValues('svn:eol-style=LF') + [('svn:eol-style', 'LF')] + >>> ParseSubversionPropertyValues('svn:mime-type=image/jpeg') + [('svn:mime-type', 'image/jpeg')] + >>> ParseSubversionPropertyValues('svn:eol-style=LF;svn:executable') + [('svn:eol-style', 'LF'), ('svn:executable', '*')] + """ + key_value_pairs = [] + for prop in props.split(";"): + key_value = prop.split("=") + assert len(key_value) <= 2 + if len(key_value) == 1: + # If value is not given, use '*' as a Subversion's convention. + key_value_pairs.append((key_value[0], "*")) + else: + key_value_pairs.append((key_value[0], key_value[1])) + return key_value_pairs + + +def GetSubversionPropertyChanges(filename): + """Return a Subversion's 'Property changes on ...' string, which is used in + the patch file. + + Args: + filename: filename whose property might be set by [auto-props] config. + + Returns: + A string like 'Property changes on |filename| ...' if given |filename| + matches any entries in [auto-props] section. None, otherwise. + """ + global svn_auto_props_map + if svn_auto_props_map is None: + svn_auto_props_map = LoadSubversionAutoProperties() + + all_props = [] + for file_pattern, props in svn_auto_props_map.items(): + if fnmatch.fnmatch(filename, file_pattern): + all_props.extend(props) + if all_props: + return FormatSubversionPropertyChanges(filename, all_props) + return None + + +def FormatSubversionPropertyChanges(filename, props): + """Returns Subversion's 'Property changes on ...' strings using given filename + and properties. + + Args: + filename: filename + props: A list whose element is a (svn_prop_key, svn_prop_value) pair. + + Returns: + A string which can be used in the patch file for Subversion. + + See the following doctest for example. + + >>> print FormatSubversionPropertyChanges('foo.cc', [('svn:eol-style', 'LF')]) + Property changes on: foo.cc + ___________________________________________________________________ + Added: svn:eol-style + + LF + <BLANKLINE> + """ + prop_changes_lines = [ + "Property changes on: %s" % filename, + "___________________________________________________________________"] + for key, value in props: + prop_changes_lines.append("Added: " + key) + prop_changes_lines.append(" + " + value) + return "\n".join(prop_changes_lines) + "\n" + + +def RealMain(argv, data=None): + """The real main function. + + Args: + argv: Command line arguments. + data: Diff contents. If None (default) the diff is generated by + the VersionControlSystem implementation returned by GuessVCS(). + + Returns: + A 2-tuple (issue id, patchset id). + The patchset id is None if the base files are not uploaded by this + script (applies only to SVN checkouts). + """ + logging.basicConfig(format=("%(asctime).19s %(levelname)s %(filename)s:" + "%(lineno)s %(message)s ")) + os.environ['LC_ALL'] = 'C' + options, args = parser.parse_args(argv[1:]) + global verbosity + verbosity = options.verbose + if verbosity >= 3: + logging.getLogger().setLevel(logging.DEBUG) + elif verbosity >= 2: + logging.getLogger().setLevel(logging.INFO) + + vcs = GuessVCS(options) + + base = options.base_url + if isinstance(vcs, SubversionVCS): + # Guessing the base field is only supported for Subversion. + # Note: Fetching base files may become deprecated in future releases. + guessed_base = vcs.GuessBase(options.download_base) + if base: + if guessed_base and base != guessed_base: + print "Using base URL \"%s\" from --base_url instead of \"%s\"" % \ + (base, guessed_base) + else: + base = guessed_base + + if not base and options.download_base: + options.download_base = True + logging.info("Enabled upload of base file") + if not options.assume_yes: + vcs.CheckForUnknownFiles() + if data is None: + data = vcs.GenerateDiff(args) + files = vcs.GetBaseFiles(data) + if verbosity >= 1: + print "Upload server:", options.server, "(change with -s/--server)" + if options.issue: + prompt = "Message describing this patch set: " + else: + prompt = "New issue subject: " + message = options.message or raw_input(prompt).strip() + if not message: + ErrorExit("A non-empty message is required") + rpc_server = GetRpcServer(options.server, + options.email, + options.host, + options.save_cookies) + form_fields = [("subject", message)] + if base: + form_fields.append(("base", base)) + if options.issue: + form_fields.append(("issue", str(options.issue))) + if options.email: + form_fields.append(("user", options.email)) + if options.reviewers: + for reviewer in options.reviewers.split(','): + CheckReviewer(reviewer) + form_fields.append(("reviewers", options.reviewers)) + if options.cc: + for cc in options.cc.split(','): + CheckReviewer(cc) + form_fields.append(("cc", options.cc)) + description = options.description + if options.description_file: + if options.description: + ErrorExit("Can't specify description and description_file") + file = open(options.description_file, 'r') + description = file.read() + file.close() + if description: + form_fields.append(("description", description)) + # Send a hash of all the base file so the server can determine if a copy + # already exists in an earlier patchset. + base_hashes = "" + for file, info in files.iteritems(): + if not info[0] is None: + checksum = md5(info[0]).hexdigest() + if base_hashes: + base_hashes += "|" + base_hashes += checksum + ":" + file + form_fields.append(("base_hashes", base_hashes)) + if options.private: + if options.issue: + print "Warning: Private flag ignored when updating an existing issue." + else: + form_fields.append(("private", "1")) + # If we're uploading base files, don't send the email before the uploads, so + # that it contains the file status. + if options.send_mail and options.download_base: + form_fields.append(("send_mail", "1")) + if not options.download_base: + form_fields.append(("content_upload", "1")) + if len(data) > MAX_UPLOAD_SIZE: + print "Patch is large, so uploading file patches separately." + uploaded_diff_file = [] + form_fields.append(("separate_patches", "1")) + else: + uploaded_diff_file = [("data", "data.diff", data)] + ctype, body = EncodeMultipartFormData(form_fields, uploaded_diff_file) + response_body = rpc_server.Send("/upload", body, content_type=ctype) + patchset = None + if not options.download_base or not uploaded_diff_file: + lines = response_body.splitlines() + if len(lines) >= 2: + msg = lines[0] + patchset = lines[1].strip() + patches = [x.split(" ", 1) for x in lines[2:]] + else: + msg = response_body + else: + msg = response_body + StatusUpdate(msg) + if not response_body.startswith("Issue created.") and \ + not response_body.startswith("Issue updated."): + sys.exit(0) + issue = msg[msg.rfind("/")+1:] + + if not uploaded_diff_file: + result = UploadSeparatePatches(issue, rpc_server, patchset, data, options) + if not options.download_base: + patches = result + + if not options.download_base: + vcs.UploadBaseFiles(issue, rpc_server, patches, patchset, options, files) + if options.send_mail: + rpc_server.Send("/" + issue + "/mail", payload="") + return issue, patchset + + +def main(): + try: + RealMain(sys.argv) + except KeyboardInterrupt: + print + StatusUpdate("Interrupted.") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/download.py b/WebKitTools/Scripts/webkitpy/tool/commands/download.py index d960bbe..c66b95c 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/download.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/download.py @@ -89,12 +89,12 @@ class Land(AbstractSequencedCommand): steps.CloseBugForLandDiff, ] long_help = """land commits the current working copy diff (just as svn or git commit would). -land will build and run the tests before committing. +land will NOT build and run the tests before committing, but you can use the --build option for that. If a bug id is provided, or one can be found in the ChangeLog land will update the bug after committing.""" def _prepare_state(self, options, args, tool): return { - "bug_id" : (args and args[0]) or tool.checkout().bug_id_for_this_commit() + "bug_id": (args and args[0]) or tool.checkout().bug_id_for_this_commit(options.git_commit, options.squash), } diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem.py b/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem.py index 9ea34c0..7505c62 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/earlywarningsystem.py @@ -26,8 +26,6 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from StringIO import StringIO - from webkitpy.tool.commands.queues import AbstractReviewQueue from webkitpy.common.config.committers import CommitterList from webkitpy.common.config.ports import WebKitPort diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/queues.py b/WebKitTools/Scripts/webkitpy/tool/commands/queues.py index f0da379..775aa44 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/queues.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/queues.py @@ -71,8 +71,11 @@ class AbstractQueue(Command, QueueEngineDelegate): def run_webkit_patch(self, args): webkit_patch_args = [self.tool.path()] # FIXME: This is a hack, we should have a more general way to pass global options. + # FIXME: We must always pass global options and their value in one argument + # because our global option code looks for the first argument which does + # not begin with "-" and assumes that is the command name. webkit_patch_args += ["--status-host=%s" % self.tool.status_server.host] - webkit_patch_args += map(str, args) + webkit_patch_args.extend(args) return self.tool.executive.run_and_throw_if_fail(webkit_patch_args) def _log_directory(self): @@ -123,7 +126,10 @@ class AbstractQueue(Command, QueueEngineDelegate): if is_error: message = "Error: %s" % message output = script_error.message_with_output(output_limit=1024*1024) # 1MB - return tool.status_server.update_status(cls.name, message, state["patch"], StringIO(output)) + # We pre-encode the string to a byte array before passing it + # to status_server, because ClientForm (part of mechanize) + # wants a file-like object with pre-encoded data. + return tool.status_server.update_status(cls.name, message, state["patch"], StringIO(output.encode("utf-8"))) class AbstractPatchQueue(AbstractQueue): diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py b/WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py index f0f7c86..16eb053 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/queues_unittest.py @@ -75,7 +75,7 @@ class AbstractQueueTest(CommandsTest): queue.bind_to_tool(tool) queue.run_webkit_patch(run_args) - expected_run_args = ["echo", "--status-host=example.com"] + map(str, run_args) + expected_run_args = ["echo", "--status-host=example.com"] + run_args tool.executive.run_and_throw_if_fail.assert_called_with(expected_run_args) def test_run_webkit_patch(self): @@ -150,7 +150,7 @@ Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.c Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) 1 patch in commit-queue [106] """, - "process_work_item": "MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'land-attachment', '--force-clean', '--build', '--test', '--non-interactive', '--ignore-builders', '--build-style=both', '--quiet', '76543']\n", + "process_work_item": "MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'land-attachment', '--force-clean', '--build', '--test', '--non-interactive', '--ignore-builders', '--build-style=both', '--quiet', 76543]\n", } self.assert_queue_outputs(CommitQueue(), tool=tool, work_item=rollout_patch, expected_stderr=expected_stderr) diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/upload.py b/WebKitTools/Scripts/webkitpy/tool/commands/upload.py index bdf060a..99d45a6 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/upload.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/upload.py @@ -30,7 +30,6 @@ import os import re -import StringIO import sys from optparse import make_option @@ -141,16 +140,16 @@ class ObsoleteAttachments(AbstractSequencedCommand): class AbstractPatchUploadingCommand(AbstractSequencedCommand): - def _bug_id(self, args, tool, state): + def _bug_id(self, options, args, tool, state): # Perfer a bug id passed as an argument over a bug url in the diff (i.e. ChangeLogs). bug_id = args and args[0] if not bug_id: - bug_id = tool.checkout().bug_id_for_this_commit() + bug_id = tool.checkout().bug_id_for_this_commit(options.git_commit, options.squash) return bug_id def _prepare_state(self, options, args, tool): state = {} - state["bug_id"] = self._bug_id(args, tool, state) + state["bug_id"] = self._bug_id(options, args, tool, state) if not state["bug_id"]: error("No bug id passed and no bug url found in ChangeLogs.") return state @@ -223,7 +222,7 @@ class Upload(AbstractPatchUploadingCommand): def _prepare_state(self, options, args, tool): state = {} - state["bug_id"] = self._bug_id(args, tool, state) + state["bug_id"] = self._bug_id(options, args, tool, state) return state @@ -260,10 +259,6 @@ class PostCommits(AbstractDeclarativeCommand): comment_text += tool.scm().files_changed_summary_for_commit(commit_id) return comment_text - def _diff_file_for_commit(self, tool, commit_id): - diff = tool.scm().create_patch_from_local_commit(commit_id) - return StringIO.StringIO(diff) # add_patch_to_bug expects a file-like object - def execute(self, options, args, tool): commit_ids = tool.scm().commit_ids_from_commitish_arguments(args) if len(commit_ids) > 10: # We could lower this limit, 10 is too many for one bug as-is. @@ -274,7 +269,7 @@ class PostCommits(AbstractDeclarativeCommand): commit_message = tool.scm().commit_message_for_local_commit(commit_id) # Prefer --bug-id=, then a bug url in the commit message, then a bug url in the entire commit diff (i.e. ChangeLogs). - bug_id = options.bug_id or parse_bug_id(commit_message.message()) or parse_bug_id(tool.scm().create_patch_from_local_commit(commit_id)) + bug_id = options.bug_id or parse_bug_id(commit_message.message()) or parse_bug_id(tool.scm().create_patch(git_commit=commit_id)) if not bug_id: log("Skipping %s: No bug id found in commit or specified with --bug-id." % commit_id) continue @@ -284,10 +279,10 @@ class PostCommits(AbstractDeclarativeCommand): steps.ObsoletePatches(tool, options).run(state) have_obsoleted_patches.add(bug_id) - diff_file = self._diff_file_for_commit(tool, commit_id) + diff = tool.scm().create_patch(git_commit=commit_id) description = options.description or commit_message.description(lstrip=True, strip_url=True) comment_text = self._comment_text_for_commit(options, commit_message, tool, commit_id) - tool.bugs.add_patch_to_bug(bug_id, diff_file, description, comment_text, mark_for_review=options.review, mark_for_commit_queue=options.request_commit) + tool.bugs.add_patch_to_bug(bug_id, diff, description, comment_text, mark_for_review=options.review, mark_for_commit_queue=options.request_commit) # FIXME: This command needs to be brought into the modern age with steps and CommitInfo. @@ -403,9 +398,8 @@ class CreateBug(AbstractDeclarativeCommand): comment_text += "---\n" comment_text += tool.scm().files_changed_summary_for_commit(commit_id) - diff = tool.scm().create_patch_from_local_commit(commit_id) - diff_file = StringIO.StringIO(diff) # create_bug expects a file-like object - bug_id = tool.bugs.create_bug(bug_title, comment_text, options.component, diff_file, "Patch", cc=options.cc, mark_for_review=options.review, mark_for_commit_queue=options.request_commit) + diff = tool.scm().create_patch(git_commit=commit_id) + bug_id = tool.bugs.create_bug(bug_title, comment_text, options.component, diff, "Patch", cc=options.cc, mark_for_review=options.review, mark_for_commit_queue=options.request_commit) if bug_id and len(commit_ids) > 1: options.bug_id = bug_id @@ -419,13 +413,12 @@ class CreateBug(AbstractDeclarativeCommand): if options.prompt: (bug_title, comment_text) = self.prompt_for_bug_title_and_comment() else: - commit_message = tool.checkout().commit_message_for_this_commit() + commit_message = tool.checkout().commit_message_for_this_commit(options.git_commit, options.squash) bug_title = commit_message.description(lstrip=True, strip_url=True) comment_text = commit_message.body(lstrip=True) - diff = tool.scm().create_patch() - diff_file = StringIO.StringIO(diff) # create_bug expects a file-like object - bug_id = tool.bugs.create_bug(bug_title, comment_text, options.component, diff_file, "Patch", cc=options.cc, mark_for_review=options.review, mark_for_commit_queue=options.request_commit) + diff = tool.scm().create_patch(options.git_commit, options.squash) + bug_id = tool.bugs.create_bug(bug_title, comment_text, options.component, diff, "Patch", cc=options.cc, mark_for_review=options.review, mark_for_commit_queue=options.request_commit) def prompt_for_bug_title_and_comment(self): bug_title = User.prompt("Bug title: ") diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/upload_unittest.py b/WebKitTools/Scripts/webkitpy/tool/commands/upload_unittest.py index 271df01..eec3751 100644 --- a/WebKitTools/Scripts/webkitpy/tool/commands/upload_unittest.py +++ b/WebKitTools/Scripts/webkitpy/tool/commands/upload_unittest.py @@ -58,6 +58,8 @@ class UploadCommandsTest(CommandsTest): options.description = "MOCK description" options.request_commit = False options.review = True + # Rietveld upload code requires a real SCM checkout. + options.fancy_review = False options.cc = None expected_stderr = """Running check-webkit-style MOCK: user.open_url: file://... @@ -86,6 +88,8 @@ MOCK: user.open_url: http://example.com/42 options.description = "MOCK description" options.request_commit = False options.review = True + # Rietveld upload code requires a real SCM checkout. + options.fancy_review = False options.cc = None expected_stderr = """Running check-webkit-style MOCK: user.open_url: file://... diff --git a/WebKitTools/Scripts/webkitpy/tool/main.py b/WebKitTools/Scripts/webkitpy/tool/main.py index 06cde74..2dc177d 100755 --- a/WebKitTools/Scripts/webkitpy/tool/main.py +++ b/WebKitTools/Scripts/webkitpy/tool/main.py @@ -123,6 +123,7 @@ class WebKitPatch(MultiCommandTool): # FIXME: This may be unnecessary since we pass global options to all commands during execute() as well. def handle_global_options(self, options): + self._options = options if options.dry_run: self.scm().dryrun = True self.bugs.dryrun = True diff --git a/WebKitTools/Scripts/webkitpy/tool/mocktool.py b/WebKitTools/Scripts/webkitpy/tool/mocktool.py index cc361ff..128362a 100644 --- a/WebKitTools/Scripts/webkitpy/tool/mocktool.py +++ b/WebKitTools/Scripts/webkitpy/tool/mocktool.py @@ -260,7 +260,7 @@ class MockBugzilla(Mock): bug_title, bug_description, component=None, - patch_file_object=None, + diff=None, patch_description=None, cc=None, blocked=None, @@ -302,7 +302,7 @@ class MockBugzilla(Mock): def add_patch_to_bug(self, bug_id, - patch_file_object, + diff, description, comment_text=None, mark_for_review=False, @@ -384,7 +384,7 @@ class MockSCM(Mock): # will actually be the root. Since getcwd() is wrong, use a globally fake root for now. self.checkout_root = self.fake_checkout_root - def create_patch(self): + def create_patch(self, git_commit, squash): return "Patch1" def commit_ids_from_commitish_arguments(self, args): @@ -399,13 +399,6 @@ class MockSCM(Mock): "https://bugs.example.org/show_bug.cgi?id=75\n") raise Exception("Bogus commit_id in commit_message_for_local_commit.") - def create_patch_from_local_commit(self, commit_id): - if commit_id == "Commitish1": - return "Patch1" - if commit_id == "Commitish2": - return "Patch2" - raise Exception("Bogus commit_id in commit_message_for_local_commit.") - def diff_for_revision(self, revision): return "DiffForRevision%s\n" \ "http://bugs.webkit.org/show_bug.cgi?id=12345" % revision @@ -431,12 +424,12 @@ class MockCheckout(object): def bug_id_for_revision(self, svn_revision): return 12345 - def modified_changelogs(self): + def modified_changelogs(self, git_commit, squash): # Ideally we'd return something more interesting here. The problem is # that LandDiff will try to actually read the patch from disk! return [] - def commit_message_for_this_commit(self): + def commit_message_for_this_commit(self, git_commit, squash): commit_message = Mock() commit_message.message = lambda:"This is a fake commit message that is at least 50 characters." return commit_message @@ -507,7 +500,8 @@ class MockExecute(Mock): input=None, error_handler=None, return_exit_code=False, - return_stderr=True): + return_stderr=True, + decode_output=False): return "MOCK output of child process" diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/abstractstep.py b/WebKitTools/Scripts/webkitpy/tool/steps/abstractstep.py index 1ad343d..abafe63 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/abstractstep.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/abstractstep.py @@ -28,6 +28,7 @@ from webkitpy.common.system.deprecated_logging import log from webkitpy.common.config.ports import WebKitPort +from webkitpy.tool.steps.options import Options class AbstractStep(object): @@ -36,10 +37,13 @@ class AbstractStep(object): self._options = options self._port = None - def _run_script(self, script_name, quiet=False, port=WebKitPort): + def _run_script(self, script_name, args=None, quiet=False, port=WebKitPort): log("Running %s" % script_name) + command = [port.script_path(script_name)] + if args: + command.extend(args) # FIXME: This should use self.port() - self._tool.executive.run_and_throw_if_fail(port.script_path(script_name), quiet) + self._tool.executive.run_and_throw_if_fail(command, quiet) # FIXME: The port should live on the tool. def port(self): @@ -49,8 +53,8 @@ class AbstractStep(object): return self._port _well_known_keys = { - "diff" : lambda self: self._tool.scm().create_patch(), - "changelogs" : lambda self: self._tool.checkout().modified_changelogs(), + "diff": lambda self: self._tool.scm().create_patch(self._options.git_commit, self._options.squash), + "changelogs": lambda self: self._tool.checkout().modified_changelogs(self._options.git_commit, self._options.squash), } def cached_lookup(self, state, key, promise=None): @@ -63,7 +67,12 @@ class AbstractStep(object): @classmethod def options(cls): - return [] + return [ + # We need these options here because cached_lookup uses them. :( + Options.git_commit, + Options.no_squash, + Options.squash, + ] def run(self, state): raise NotImplementedError, "subclasses must implement" diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/applypatch.py b/WebKitTools/Scripts/webkitpy/tool/steps/applypatch.py index 66d0a03..6cded27 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/applypatch.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/applypatch.py @@ -33,7 +33,7 @@ from webkitpy.common.system.deprecated_logging import log class ApplyPatch(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ Options.non_interactive, ] diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/applypatchwithlocalcommit.py b/WebKitTools/Scripts/webkitpy/tool/steps/applypatchwithlocalcommit.py index 70ddfe5..d6b026d 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/applypatchwithlocalcommit.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/applypatchwithlocalcommit.py @@ -32,12 +32,12 @@ from webkitpy.tool.steps.options import Options class ApplyPatchWithLocalCommit(ApplyPatch): @classmethod def options(cls): - return [ + return ApplyPatch.options() + [ Options.local_commit, - ] + ApplyPatch.options() + ] def run(self, state): ApplyPatch.run(self, state) if self._options.local_commit: - commit_message = self._tool.checkout().commit_message_for_this_commit() + commit_message = self._tool.checkout().commit_message_for_this_commit(git_commit=None, squash=False) self._tool.scm().commit_locally_with_message(commit_message.message() or state["patch"].name()) diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/build.py b/WebKitTools/Scripts/webkitpy/tool/steps/build.py index f0570f9..456db25 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/build.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/build.py @@ -34,7 +34,7 @@ from webkitpy.common.system.deprecated_logging import log class Build(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ Options.build, Options.quiet, Options.build_style, diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/checkstyle.py b/WebKitTools/Scripts/webkitpy/tool/steps/checkstyle.py index 63f0114..7b2be99 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/checkstyle.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/checkstyle.py @@ -36,9 +36,12 @@ from webkitpy.common.system.deprecated_logging import error class CheckStyle(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ Options.non_interactive, Options.check_style, + Options.git_commit, + Options.no_squash, + Options.squash, ] def run(self, state): @@ -46,7 +49,16 @@ class CheckStyle(AbstractStep): return os.chdir(self._tool.scm().checkout_root) try: - self._run_script("check-webkit-style") + args = [] + if self._options.git_commit: + args.append("--git-commit") + args.append(self._options.git_commit) + if self._tool.scm().should_squash(self._options.squash): + args.append("--squash") + else: + args.append("--no-squash") + + self._run_script("check-webkit-style", args) except ScriptError, e: if self._options.non_interactive: # We need to re-raise the exception here to have the diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/cleanworkingdirectory.py b/WebKitTools/Scripts/webkitpy/tool/steps/cleanworkingdirectory.py index 3768297..e13fbc2 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/cleanworkingdirectory.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/cleanworkingdirectory.py @@ -39,7 +39,7 @@ class CleanWorkingDirectory(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ Options.force_clean, Options.clean, ] diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/closebug.py b/WebKitTools/Scripts/webkitpy/tool/steps/closebug.py index d5059ea..e77bc24 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/closebug.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/closebug.py @@ -34,7 +34,7 @@ from webkitpy.common.system.deprecated_logging import log class CloseBug(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ Options.close_bug, ] diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/closebugforlanddiff.py b/WebKitTools/Scripts/webkitpy/tool/steps/closebugforlanddiff.py index 476d3af..e5a68db 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/closebugforlanddiff.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/closebugforlanddiff.py @@ -35,7 +35,7 @@ from webkitpy.common.system.deprecated_logging import log class CloseBugForLandDiff(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ Options.close_bug, ] diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/commit.py b/WebKitTools/Scripts/webkitpy/tool/steps/commit.py index 294b41e..7bf8b8a 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/commit.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/commit.py @@ -27,11 +27,21 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from webkitpy.tool.steps.abstractstep import AbstractStep +from webkitpy.tool.steps.options import Options class Commit(AbstractStep): + @classmethod + def options(cls): + return AbstractStep.options() + [ + Options.git_commit, + Options.no_squash, + Options.squash, + ] + def run(self, state): - commit_message = self._tool.checkout().commit_message_for_this_commit() + commit_message = self._tool.checkout().commit_message_for_this_commit(self._options.git_commit, self._options.squash) if len(commit_message.message()) < 50: raise Exception("Attempted to commit with a commit message shorter than 50 characters. Either your patch is missing a ChangeLog or webkit-patch may have a bug.") - state["commit_text"] = self._tool.scm().commit_with_message(commit_message.message()) + state["commit_text"] = self._tool.scm().commit_with_message(commit_message.message(), + git_commit=self._options.git_commit, squash=self._options.squash) diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/confirmdiff.py b/WebKitTools/Scripts/webkitpy/tool/steps/confirmdiff.py index d08e477..626fcf3 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/confirmdiff.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/confirmdiff.py @@ -41,7 +41,7 @@ _log = logutils.get_logger(__file__) class ConfirmDiff(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ Options.confirm, ] diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/createbug.py b/WebKitTools/Scripts/webkitpy/tool/steps/createbug.py index 2f3d42c..cd043d6 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/createbug.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/createbug.py @@ -33,7 +33,7 @@ from webkitpy.tool.steps.options import Options class CreateBug(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ Options.cc, Options.component, ] diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/ensurebuildersaregreen.py b/WebKitTools/Scripts/webkitpy/tool/steps/ensurebuildersaregreen.py index fd44564..40bc302 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/ensurebuildersaregreen.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/ensurebuildersaregreen.py @@ -34,7 +34,7 @@ from webkitpy.common.system.deprecated_logging import error class EnsureBuildersAreGreen(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ Options.check_builders, ] diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/ensurelocalcommitifneeded.py b/WebKitTools/Scripts/webkitpy/tool/steps/ensurelocalcommitifneeded.py index 4f799f2..d0cda46 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/ensurelocalcommitifneeded.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/ensurelocalcommitifneeded.py @@ -34,7 +34,7 @@ from webkitpy.common.system.deprecated_logging import error class EnsureLocalCommitIfNeeded(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ Options.local_commit, ] diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/obsoletepatches.py b/WebKitTools/Scripts/webkitpy/tool/steps/obsoletepatches.py index 9f65d41..de508c6 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/obsoletepatches.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/obsoletepatches.py @@ -35,7 +35,7 @@ from webkitpy.common.system.deprecated_logging import log class ObsoletePatches(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ Options.obsolete_patches, ] diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/options.py b/WebKitTools/Scripts/webkitpy/tool/steps/options.py index 7f76f55..524a252 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/options.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/options.py @@ -42,7 +42,10 @@ class Options(object): email = make_option("--email", action="store", type="string", dest="email", help="Email address to use in ChangeLogs.") fancy_review = make_option("--fancy-review", action="store_true", dest="fancy_review", default=False, help="(Experimental) Upload the patch to Rietveld code review tool.") force_clean = make_option("--force-clean", action="store_true", dest="force_clean", default=False, help="Clean working directory before applying patches (removes local changes and commits)") +# FIXME: Make commit ranges treat each commit separately instead of squashing them into one. + git_commit = make_option("--git-commit", action="store", dest="git_commit", help="Local git commit to upload/land. If a range, the commits are squashed into one.") local_commit = make_option("--local-commit", action="store_true", dest="local_commit", default=False, help="Make a local commit for each applied patch") + no_squash = make_option("--no-squash", action="store_false", dest="squash", help="Don't squash local commits into one on upload/land (git-only).") non_interactive = make_option("--non-interactive", action="store_true", dest="non_interactive", default=False, help="Never prompt the user, fail as fast as possible.") obsolete_patches = make_option("--no-obsolete", action="store_false", dest="obsolete_patches", default=True, help="Do not obsolete old patches before posting this one.") open_bug = make_option("--open-bug", action="store_true", dest="open_bug", default=False, help="Opens the associated bug in a browser.") @@ -52,5 +55,6 @@ class Options(object): request_commit = make_option("--request-commit", action="store_true", dest="request_commit", default=False, help="Mark the patch as needing auto-commit after review.") review = make_option("--no-review", action="store_false", dest="review", default=True, help="Do not mark the patch for review.") reviewer = make_option("-r", "--reviewer", action="store", type="string", dest="reviewer", help="Update ChangeLogs to say Reviewed by REVIEWER.") - test = make_option("--test", action="store_true", dest="test", default=False, help="Commit without running run-webkit-tests") + squash = make_option("-s", "--squash", action="store_true", dest="squash", help="Squash all local commits into one on upload/land (git-only).") + test = make_option("--test", action="store_true", dest="test", default=False, help="Run run-webkit-tests before committing.") update = make_option("--no-update", action="store_false", dest="update", default=True, help="Don't update the working directory.") diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/postcodereview.py b/WebKitTools/Scripts/webkitpy/tool/steps/postcodereview.py index 3e7ed76..198cfce 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/postcodereview.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/postcodereview.py @@ -33,11 +33,10 @@ from webkitpy.tool.steps.options import Options class PostCodeReview(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ Options.cc, Options.description, Options.fancy_review, - Options.review, ] def run(self, state): @@ -66,7 +65,8 @@ class PostCodeReview(AbstractStep): # Unreachable with our current commands, but we might hit # this case if we support bug-less code reviews. message = "Code review" - created_issue = self._tool.codereview.post(message=message, + created_issue = self._tool.codereview.post(diff=self.cached_lookup(state, "diff"), + message=message, codereview_issue=codereview_issue, cc=self._options.cc) if created_issue: diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/postdiff.py b/WebKitTools/Scripts/webkitpy/tool/steps/postdiff.py index 6a3dee4..a542dba 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/postdiff.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/postdiff.py @@ -26,8 +26,6 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import StringIO - from webkitpy.tool.steps.abstractstep import AbstractStep from webkitpy.tool.steps.options import Options @@ -35,7 +33,7 @@ from webkitpy.tool.steps.options import Options class PostDiff(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ Options.description, Options.review, Options.request_commit, @@ -44,7 +42,6 @@ class PostDiff(AbstractStep): def run(self, state): diff = self.cached_lookup(state, "diff") - diff_file = StringIO.StringIO(diff) # add_patch_to_bug expects a file-like object description = self._options.description or "Patch" comment_text = None codereview_issue = state.get("codereview_issue") @@ -52,6 +49,6 @@ class PostDiff(AbstractStep): # but it makes doing the rietveld integration a lot easier. if codereview_issue: description += "-%s" % state["codereview_issue"] - self._tool.bugs.add_patch_to_bug(state["bug_id"], diff_file, description, comment_text=comment_text, mark_for_review=self._options.review, mark_for_commit_queue=self._options.request_commit) + self._tool.bugs.add_patch_to_bug(state["bug_id"], diff, description, comment_text=comment_text, mark_for_review=self._options.review, mark_for_commit_queue=self._options.request_commit) if self._options.open_bug: self._tool.user.open_url(self._tool.bugs.bug_url_for_bug_id(state["bug_id"])) diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/postdiffforcommit.py b/WebKitTools/Scripts/webkitpy/tool/steps/postdiffforcommit.py index 03b9e78..13bc00c 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/postdiffforcommit.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/postdiffforcommit.py @@ -26,8 +26,6 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import StringIO - from webkitpy.tool.steps.abstractstep import AbstractStep @@ -35,7 +33,7 @@ class PostDiffForCommit(AbstractStep): def run(self, state): self._tool.bugs.add_patch_to_bug( state["bug_id"], - StringIO.StringIO(self.cached_lookup(state, "diff")), + self.cached_lookup(state, "diff"), "Patch for landing", mark_for_review=False, mark_for_landing=True) diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/postdiffforrevert.py b/WebKitTools/Scripts/webkitpy/tool/steps/postdiffforrevert.py index 3b9da04..bfa631f 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/postdiffforrevert.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/postdiffforrevert.py @@ -26,8 +26,6 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import StringIO - from webkitpy.common.net.bugzilla import Attachment from webkitpy.tool.steps.abstractstep import AbstractStep @@ -44,7 +42,7 @@ following command:\n\n\ where ATTACHMENT_ID is the ID of this attachment." self._tool.bugs.add_patch_to_bug( state["bug_id"], - StringIO.StringIO(self.cached_lookup(state, "diff")), + self.cached_lookup(state, "diff"), "%s%s" % (Attachment.rollout_preamble, state["revision"]), comment_text=comment_text, mark_for_review=False, diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/preparechangelog.py b/WebKitTools/Scripts/webkitpy/tool/steps/preparechangelog.py index fcb40be..3a5c013 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/preparechangelog.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/preparechangelog.py @@ -37,10 +37,13 @@ from webkitpy.common.system.deprecated_logging import error class PrepareChangeLog(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ Options.port, Options.quiet, Options.email, + Options.git_commit, + Options.no_squash, + Options.squash, ] def run(self, state): @@ -52,6 +55,11 @@ class PrepareChangeLog(AbstractStep): args.append("--bug=%s" % state["bug_id"]) if self._options.email: args.append("--email=%s" % self._options.email) + if self._tool.scm().should_squash(self._options.squash): + args.append("--merge-base=%s" % self._tool.scm().svn_merge_base()) + if self._options.git_commit: + args.append("--git-commit=%s" % self._options.git_commit) + try: self._tool.executive.run_and_throw_if_fail(args, self._options.quiet) except ScriptError, e: diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/preparechangelogforrevert.py b/WebKitTools/Scripts/webkitpy/tool/steps/preparechangelogforrevert.py index f7d9cd3..4d299fa 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/preparechangelogforrevert.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/preparechangelogforrevert.py @@ -36,7 +36,7 @@ class PrepareChangeLogForRevert(AbstractStep): def run(self, state): # This could move to prepare-ChangeLog by adding a --revert= option. self._run_script("prepare-ChangeLog") - changelog_paths = self._tool.checkout().modified_changelogs() + changelog_paths = self._tool.checkout().modified_changelogs(git_commit=None, squash=False) bug_url = self._tool.bugs.bug_url_for_bug_id(state["bug_id"]) if state["bug_id"] else None for changelog_path in changelog_paths: # FIXME: Seems we should prepare the message outside of changelogs.py and then just pass in diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/runtests.py b/WebKitTools/Scripts/webkitpy/tool/steps/runtests.py index 55d8c62..b1c2d3b 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/runtests.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/runtests.py @@ -33,7 +33,7 @@ from webkitpy.common.system.deprecated_logging import log class RunTests(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ Options.test, Options.non_interactive, Options.quiet, diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/steps_unittest.py b/WebKitTools/Scripts/webkitpy/tool/steps/steps_unittest.py index 40bee90..5abfc6d 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/steps_unittest.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/steps_unittest.py @@ -48,7 +48,8 @@ class StepsTest(unittest.TestCase): def test_update_step(self): options = Mock() options.update = True - self._run_step(Update, options) + expected_stderr = "Updating working directory\n" + OutputCapture().assert_outputs(self, self._run_step, [Update, options], expected_stderr=expected_stderr) def test_prompt_for_bug_or_title_step(self): tool = MockTool() diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/update.py b/WebKitTools/Scripts/webkitpy/tool/steps/update.py index c98eba7..0f450f3 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/update.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/update.py @@ -34,7 +34,7 @@ from webkitpy.common.system.deprecated_logging import log class Update(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ Options.update, Options.port, ] diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/updatechangelogswithreviewer.py b/WebKitTools/Scripts/webkitpy/tool/steps/updatechangelogswithreviewer.py index a35ed8c..9740013 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/updatechangelogswithreviewer.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/updatechangelogswithreviewer.py @@ -37,8 +37,11 @@ from webkitpy.common.system.deprecated_logging import log, error class UpdateChangeLogsWithReviewer(AbstractStep): @classmethod def options(cls): - return [ + return AbstractStep.options() + [ + Options.git_commit, Options.reviewer, + Options.no_squash, + Options.squash, ] def _guess_reviewer_from_bug(self, bug_id): @@ -67,5 +70,5 @@ class UpdateChangeLogsWithReviewer(AbstractStep): return os.chdir(self._tool.scm().checkout_root) - for changelog_path in self._tool.checkout().modified_changelogs(): + for changelog_path in self._tool.checkout().modified_changelogs(self._options.git_commit, self._options.squash): ChangeLog(changelog_path).set_reviewer(reviewer) diff --git a/WebKitTools/Scripts/webkitpy/tool/steps/validatereviewer.py b/WebKitTools/Scripts/webkitpy/tool/steps/validatereviewer.py index 80b2c5d..66ee5b7 100644 --- a/WebKitTools/Scripts/webkitpy/tool/steps/validatereviewer.py +++ b/WebKitTools/Scripts/webkitpy/tool/steps/validatereviewer.py @@ -31,11 +31,20 @@ import re from webkitpy.common.checkout.changelog import ChangeLog from webkitpy.tool.steps.abstractstep import AbstractStep +from webkitpy.tool.steps.options import Options from webkitpy.common.system.deprecated_logging import error, log # FIXME: Some of this logic should probably be unified with CommitterValidator? class ValidateReviewer(AbstractStep): + @classmethod + def options(cls): + return AbstractStep.options() + [ + Options.git_commit, + Options.no_squash, + Options.squash, + ] + # FIXME: This should probably move onto ChangeLogEntry def _has_valid_reviewer(self, changelog_entry): if changelog_entry.reviewer(): @@ -54,7 +63,7 @@ class ValidateReviewer(AbstractStep): # FIXME: We should figure out how to handle the current working # directory issue more globally. os.chdir(self._tool.scm().checkout_root) - for changelog_path in self._tool.checkout().modified_changelogs(): + for changelog_path in self._tool.checkout().modified_changelogs(self._options.git_commit, self._options.squash): changelog_entry = ChangeLog(changelog_path).latest_entry() if self._has_valid_reviewer(changelog_entry): continue diff --git a/WebKitTools/WinLauncher/WinLauncher.h b/WebKitTools/WinLauncher/WinLauncher.h index 6488285..a82d7b1 100644 --- a/WebKitTools/WinLauncher/WinLauncher.h +++ b/WebKitTools/WinLauncher/WinLauncher.h @@ -61,6 +61,10 @@ public: /* [in] */ BSTR title, /* [in] */ IWebFrame *frame) { return S_OK; } + virtual HRESULT STDMETHODCALLTYPE didChangeIcons( + /* [in] */ IWebView *webView, + /* [in] */ IWebFrame *frame) { return S_OK; } + virtual HRESULT STDMETHODCALLTYPE didReceiveIcon( /* [in] */ IWebView *webView, /* [in] */ OLE_HANDLE hBitmap, diff --git a/WebKitTools/wx/build/settings.py b/WebKitTools/wx/build/settings.py index baf9657..1498c3d 100644 --- a/WebKitTools/wx/build/settings.py +++ b/WebKitTools/wx/build/settings.py @@ -232,7 +232,11 @@ def common_configure(conf): global msvc_version global msvclibs_dir + libprefix = '' + if building_on_win32: + libprefix = 'lib' + found_versions = conf.get_msvc_versions() if found_versions[0][0] == 'msvc 9.0': msvc_version = 'msvc2008' @@ -268,6 +272,9 @@ def common_configure(conf): conf.env.append_value('CXXDEFINES', ['BUILDING_WX__=1', 'JS_NO_EXPORT']) + conf.env['LIB_WXWEBKIT'] = ['wxwebkit'] + conf.env['CXXDEFINES_WXWEBKIT'] = ['WXUSINGDLL_WEBKIT'] + if building_on_win32: conf.env.append_value('LIBPATH', os.path.join(msvclibs_dir, 'lib')) # wx settings @@ -279,6 +286,9 @@ def common_configure(conf): conf.env['LIB_WX'] = wxlibs conf.env['LIBPATH_WX'] = wxlibpaths + conf.env['LIB_JSCORE'] = [libprefix + 'jscore'] + conf.env['LIB_WEBCORE'] = [libprefix + 'webcore'] + if sys.platform.startswith('darwin'): conf.env['LIB_ICU'] = ['icucore'] # Apple does not ship the ICU headers with Mac OS X, so WebKit includes a copy of 3.2 headers @@ -306,7 +316,12 @@ def common_configure(conf): sdk_version = min_version if min_version == "10.4": sdk_version += "u" - conf.env.append_value('LIB', ['WebKitSystemInterfaceTiger']) + conf.env.append_value('LIB_WEBCORE', ['WebKitSystemInterfaceTiger']) + else: + # NOTE: There is a WebKitSystemInterfaceSnowLeopard, but when we use that + # on 10.6, we get a strange missing symbol error, and this library seems to + # work fine for wx's purposes. + conf.env.append_value('LIB_WEBCORE', ['WebKitSystemInterfaceLeopard']) sdkroot = '/Developer/SDKs/MacOSX%s.sdk' % sdk_version sdkflags = ['-arch', 'i386', '-isysroot', sdkroot] @@ -317,15 +332,6 @@ def common_configure(conf): conf.env.append_value('CPPPATH_SQLITE3', [os.path.join(wklibs_dir, 'WebCoreSQLite3')]) conf.env.append_value('LIB_SQLITE3', ['WebCoreSQLite3']) - libprefix = '' - if building_on_win32: - libprefix = 'lib' - - conf.env['LIB_JSCORE'] = [libprefix + 'jscore'] - conf.env['LIB_WEBCORE'] = [libprefix + 'webcore'] - conf.env['LIB_WXWEBKIT'] = ['wxwebkit'] - conf.env['CXXDEFINES_WXWEBKIT'] = ['WXUSINGDLL_WEBKIT'] - conf.env.append_value('CXXDEFINES', feature_defines) if config == 'Release': conf.env.append_value('CPPDEFINES', 'NDEBUG') |