diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-09-25 13:02:02 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-09-25 13:02:02 +0200 |
commit | 715be629d51174233403237bfc563cf150087dc8 (patch) | |
tree | 4cff72df808db977624338b0a38d8b6d1bd73c57 /Source | |
parent | dc6262b587c71c14e30d93e57ed812e36a79a33e (diff) | |
download | qtwebkit-715be629d51174233403237bfc563cf150087dc8.tar.gz |
Imported WebKit commit ce614b0924ba46f78d4435e28ff93c8525fbb7cc (http://svn.webkit.org/repository/webkit/trunk@129485)
New snapshot that includes MingW build fixes
Diffstat (limited to 'Source')
371 files changed, 14468 insertions, 7547 deletions
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index 5d81031ba..403a38c70 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,3 +1,263 @@ +2012-09-24 Gavin Barraclough <barraclough@apple.com> + + https://bugs.webkit.org/show_bug.cgi?id=97530 + Regression, freeze applied to numeric properties of non-array objects + + Reviewed by Filip Pizlo. + + Object.freeze has a fast implementation in JSObject, but this hasn't been updated to take into account numeric properties in butterflies. + For now, just fall back to the generic implementation if the object has numeric properties. + + * runtime/ObjectConstructor.cpp: + (JSC::objectConstructorFreeze): + - fallback if the object has a non-zero indexed property vector length. + +2012-09-24 Gavin Barraclough <barraclough@apple.com> + + Bug in numeric accessors on global environment + https://bugs.webkit.org/show_bug.cgi?id=97526 + + Reviewed by Geoff Garen. + + I've hit this assert in test262 in browser, but haven't yet worked out how to repro in a test case :-/ + The sparsemap is failing to map back from the global object to the window shell. + A test case would need to resolve a numeric property name against the global environment. + + (JSC::SparseArrayEntry::get): + (JSC::SparseArrayEntry::put): + - Add missing toThisObject calls. + +2012-09-24 Filip Pizlo <fpizlo@apple.com> + + SerializedScriptValue isn't aware of indexed storage, but should be + https://bugs.webkit.org/show_bug.cgi?id=97515 + <rdar://problem/12361874> + + Reviewed by Sam Weinig. + + Export a method that WebCore now uses. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * runtime/JSObject.h: + (JSObject): + +2012-09-24 Gavin Barraclough <barraclough@apple.com> + + Remove JSObject::unwrappedGlobalObject(), JSObject::unwrappedObject() + https://bugs.webkit.org/show_bug.cgi?id=97519 + + Reviewed by Geoff Garen. + + unwrappedGlobalObject() was only needed because globalObject() doesn't always return a helpful result - + specifically for WebCore's window shell the structure's globalObject is set to null. We can fix this by + simply keeping the structure up to date as the window navigates, obviating the need for this function. + + The only other use of unwrappedObject() came from globalFuncEval(), and this can be trivially removed + by flipping the way we perform this globalObject check (which we may also be able to remove!) - instead + of getting the globalObject from the provided this value & comparing to the expected globalObject, we + can get the this value from the expected globalObject, and compare to that provided. + + * runtime/JSGlobalObject.cpp: + - Call globalObject() instead of unwrappedGlobalObject(). + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::globalFuncEval): + - Changed to compare this object values, instead of globalObjects - + this means we only need to be able to map globalObject -> this, + and not vice versa. + * runtime/JSObject.cpp: + (JSC::JSObject::allowsAccessFrom): + (JSC::JSObject::createInheritorID): + - Call globalObject() instead of unwrappedGlobalObject(). + * runtime/JSObject.h: + (JSObject): + - Removed unwrappedGlobalObject(), unwrappedObject(). + +2012-09-24 Mark Lam <mark.lam@apple.com> + + Deleting the classic interpreter and cleaning up some build options. + https://bugs.webkit.org/show_bug.cgi?id=96969. + + Reviewed by Geoffrey Garen. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + (JSC::CodeBlock::finalizeUnconditionally): + (JSC::CodeBlock::stronglyVisitStrongReferences): + (JSC): + * bytecode/Instruction.h: + (JSC::Instruction::Instruction): + * interpreter/AbstractPC.cpp: + (JSC::AbstractPC::AbstractPC): + * interpreter/AbstractPC.h: + (AbstractPC): + * interpreter/CallFrame.h: + (ExecState): + * interpreter/Interpreter.cpp: + (JSC): + (JSC::Interpreter::Interpreter): + (JSC::Interpreter::~Interpreter): + (JSC::Interpreter::initialize): + (JSC::Interpreter::isOpcode): + (JSC::Interpreter::unwindCallFrame): + (JSC::getLineNumberForCallFrame): + (JSC::getCallerInfo): + (JSC::getSourceURLFromCallFrame): + (JSC::Interpreter::execute): + (JSC::Interpreter::executeCall): + (JSC::Interpreter::executeConstruct): + (JSC::Interpreter::retrieveArgumentsFromVMCode): + (JSC::Interpreter::retrieveCallerFromVMCode): + (JSC::Interpreter::retrieveLastCaller): + * interpreter/Interpreter.h: + (JSC::Interpreter::getOpcodeID): + (Interpreter): + * jit/ExecutableAllocatorFixedVMPool.cpp: + (JSC::FixedVMPoolExecutableAllocator::FixedVMPoolExecutableAllocator): + * offlineasm/asm.rb: + * offlineasm/offsets.rb: + * runtime/Executable.cpp: + (JSC::EvalExecutable::compileInternal): + (JSC::ProgramExecutable::compileInternal): + (JSC::FunctionExecutable::compileForCallInternal): + (JSC::FunctionExecutable::compileForConstructInternal): + * runtime/Executable.h: + (JSC::NativeExecutable::create): + (NativeExecutable): + (JSC::NativeExecutable::finishCreation): + * runtime/JSGlobalData.cpp: + (JSC): + (JSC::JSGlobalData::JSGlobalData): + (JSC::JSGlobalData::getHostFunction): + * runtime/JSGlobalData.h: + (JSGlobalData): + (JSC::JSGlobalData::canUseJIT): + (JSC::JSGlobalData::canUseRegExpJIT): + * runtime/Options.cpp: + (JSC::Options::initialize): + +2012-09-24 Filip Pizlo <fpizlo@apple.com> + + Nested try/finally should not confuse the finally unpopper in BytecodeGenerator::emitComplexJumpScopes + https://bugs.webkit.org/show_bug.cgi?id=97508 + <rdar://problem/12361132> + + Reviewed by Sam Weinig. + + We're reusing some vector for multiple iterations of a loop, but we were forgetting to clear its + contents from one iteration to the next. Hence if you did multiple iterations of finally unpopping + (like in a nested try/finally and a jump out of both of them) then you'd get a corrupted try + context stack afterwards. + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitComplexJumpScopes): + +2012-09-24 Filip Pizlo <fpizlo@apple.com> + + ValueToInt32 bool case does bad things to registers + https://bugs.webkit.org/show_bug.cgi?id=97505 + <rdar://problem/12356331> + + Reviewed by Mark Hahnenberg. + + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileValueToInt32): + +2012-09-24 Mark Lam <mark.lam@apple.com> + + Add cloopDo instruction for debugging the llint C++ backend. + https://bugs.webkit.org/show_bug.cgi?id=97502. + + Reviewed by Geoffrey Garen. + + * offlineasm/cloop.rb: + * offlineasm/instructions.rb: + * offlineasm/parser.rb: + +2012-09-24 Filip Pizlo <fpizlo@apple.com> + + JSArray::putByIndex asserts with readonly property on prototype + https://bugs.webkit.org/show_bug.cgi?id=97435 + <rdar://problem/12357084> + + Reviewed by Geoffrey Garen. + + Boy, there were some problems: + + - putDirectIndex() should know that it can set the index quickly even if it's a hole and we're + in SlowPut mode, since that's the whole point of PutDirect. + + - We should have a fast path for putByIndex(). + + - The LiteralParser should not use push(), since that may throw if we're having a bad time. + + * interpreter/Interpreter.cpp: + (JSC::eval): + * runtime/JSObject.h: + (JSC::JSObject::putByIndexInline): + (JSObject): + (JSC::JSObject::putDirectIndex): + * runtime/LiteralParser.cpp: + (JSC::::parse): + +2012-09-24 Mark Lam <mark.lam@apple.com> + + Added a missing "if VALUE_PROFILER" around an access to ArrayProfile record. + https://bugs.webkit.org/show_bug.cgi?id=97496. + + Reviewed by Filip Pizlo. + + * llint/LowLevelInterpreter32_64.asm: + * llint/LowLevelInterpreter64.asm: + +2012-09-24 Geoffrey Garen <ggaren@apple.com> + + Inlined activation tear-off in the DFG + https://bugs.webkit.org/show_bug.cgi?id=97487 + + Reviewed by Filip Pizlo. + + * dfg/DFGOperations.cpp: + * dfg/DFGOperations.h: Activation tear-off is always inlined now, so I + removed its out-of-line implementation. + + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): Inlined the variable copy and update + of JSVariableObject::m_registers. This usually turns into < 10 instructions, + which is close to pure win as compared to the operation function call. + + * runtime/JSActivation.h: + (JSActivation): + (JSC::JSActivation::registersOffset): + (JSC::JSActivation::tearOff): + (JSC::JSActivation::isTornOff): + (JSC): + (JSC::JSActivation::storageOffset): + (JSC::JSActivation::storage): Tiny bit of refactoring so the JIT can + share the pointer math helper functions we use internally. + +2012-09-24 Balazs Kilvady <kilvadyb@homejinni.com> + + MIPS: store8 functions added to MacroAssembler. + + MIPS store8 functions + https://bugs.webkit.org/show_bug.cgi?id=97243 + + Reviewed by Oliver Hunt. + + Add MIPS store8 functions. + + * assembler/MIPSAssembler.h: + (JSC::MIPSAssembler::lhu): New function. + (MIPSAssembler): + (JSC::MIPSAssembler::sb): New function. + (JSC::MIPSAssembler::sh): New function. + * assembler/MacroAssemblerMIPS.h: + (JSC::MacroAssemblerMIPS::store8): New function. + (MacroAssemblerMIPS): + (JSC::MacroAssemblerMIPS::store16): New function. + 2012-09-23 Geoffrey Garen <ggaren@apple.com> PutScopedVar should not be marked as clobbering the world diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def index f7c0457bf..eda306f3c 100755 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def @@ -277,6 +277,7 @@ EXPORTS ?put@JSObject@JSC@@SAXPAVJSCell@2@PAVExecState@2@VPropertyName@2@VJSValue@2@AAVPutPropertySlot@2@@Z ?putByIndex@JSObject@JSC@@SAXPAVJSCell@2@PAVExecState@2@IVJSValue@2@_N@Z ?putDirectIndexBeyondVectorLength@JSObject@JSC@@AAE_NPAVExecState@2@IVJSValue@2@IW4PutDirectIndexMode@2@@Z + ?putDirectMayBeIndex@JSObject@JSC@@QAEXPAVExecState@2@VPropertyName@2@VJSValue@2@@Z ?putDirectVirtual@JSGlobalObject@JSC@@SAXPAVJSObject@2@PAVExecState@2@VPropertyName@2@VJSValue@2@I@Z ?putDirectVirtual@JSObject@JSC@@SAXPAV12@PAVExecState@2@VPropertyName@2@VJSValue@2@I@Z ?randomNumber@WTF@@YANXZ diff --git a/Source/JavaScriptCore/assembler/MIPSAssembler.h b/Source/JavaScriptCore/assembler/MIPSAssembler.h index 65307d950..d3f8af996 100644 --- a/Source/JavaScriptCore/assembler/MIPSAssembler.h +++ b/Source/JavaScriptCore/assembler/MIPSAssembler.h @@ -405,6 +405,18 @@ public: loadDelayNop(); } + void sb(RegisterID rt, RegisterID rs, int offset) + { + emitInst(0xa0000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) + | (offset & 0xffff)); + } + + void sh(RegisterID rt, RegisterID rs, int offset) + { + emitInst(0xa4000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) + | (offset & 0xffff)); + } + void sw(RegisterID rt, RegisterID rs, int offset) { emitInst(0xac000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h index b3afae8df..22830a621 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h @@ -786,6 +786,81 @@ public: return dataLabel; } + void store8(RegisterID src, BaseIndex address) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + sb src, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.sb(src, addrTempRegister, address.offset); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + sb src, (address.offset & 0xffff)(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, + immTempRegister); + m_assembler.sb(src, addrTempRegister, address.offset); + } + } + + void store8(TrustedImm32 imm, void* address) + { + /* + li immTemp, imm + li addrTemp, address + sb src, 0(addrTemp) + */ + if (!imm.m_value && !m_fixedWidth) { + move(TrustedImmPtr(address), addrTempRegister); + m_assembler.sb(MIPSRegisters::zero, addrTempRegister, 0); + } else { + move(imm, immTempRegister); + move(TrustedImmPtr(address), addrTempRegister); + m_assembler.sb(immTempRegister, addrTempRegister, 0); + } + } + + void store16(RegisterID src, BaseIndex address) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + sh src, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.sh(src, addrTempRegister, address.offset); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + sh src, (address.offset & 0xffff)(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, + immTempRegister); + m_assembler.sh(src, addrTempRegister, address.offset); + } + } + void store32(RegisterID src, ImplicitAddress address) { if (address.offset >= -32768 && address.offset <= 32767 diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp index 54dccb9ed..bd8bfec0d 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp @@ -588,25 +588,6 @@ void CodeBlock::dump(ExecState* exec) } while (i < m_globalResolveInfos.size()); } #endif -#if ENABLE(CLASSIC_INTERPRETER) - if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty()) - dataLog("\nStructures:\n"); - - if (!m_globalResolveInstructions.isEmpty()) { - size_t i = 0; - do { - printStructures(&instructions()[m_globalResolveInstructions[i]]); - ++i; - } while (i < m_globalResolveInstructions.size()); - } - if (!m_propertyAccessInstructions.isEmpty()) { - size_t i = 0; - do { - printStructures(&instructions()[m_propertyAccessInstructions[i]]); - ++i; - } while (i < m_propertyAccessInstructions.size()); - } -#endif if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) { dataLog("\nException Handlers:\n"); @@ -2065,9 +2046,7 @@ void CodeBlock::finalizeUnconditionally() { #if ENABLE(LLINT) Interpreter* interpreter = m_globalData->interpreter; - // interpreter->classicEnabled() returns true if the old C++ interpreter is enabled. If that's enabled - // then we're not using LLInt. - if (!interpreter->classicEnabled() && !!numberOfInstructions()) { + if (!!numberOfInstructions()) { for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) { Instruction* curInstruction = &instructions()[m_propertyAccessInstructions[i]]; switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) { @@ -2260,14 +2239,6 @@ void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor) visitor.append(&m_functionExprs[i]); for (size_t i = 0; i < m_functionDecls.size(); ++i) visitor.append(&m_functionDecls[i]); -#if ENABLE(CLASSIC_INTERPRETER) - if (m_globalData->interpreter->classicEnabled() && !!numberOfInstructions()) { - for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) - visitStructures(visitor, &instructions()[m_propertyAccessInstructions[i]]); - for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i) - visitStructures(visitor, &instructions()[m_globalResolveInstructions[i]]); - } -#endif updateAllPredictions(Collection); } @@ -2444,27 +2415,6 @@ void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& d return; } -#if ENABLE(CLASSIC_INTERPRETER) -bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset) -{ - if (m_globalResolveInstructions.isEmpty()) - return false; - - int low = 0; - int high = m_globalResolveInstructions.size(); - while (low < high) { - int mid = low + (high - low) / 2; - if (m_globalResolveInstructions[mid] <= bytecodeOffset) - low = mid + 1; - else - high = mid; - } - - if (!low || m_globalResolveInstructions[low - 1] != bytecodeOffset) - return false; - return true; -} -#endif #if ENABLE(JIT) bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset) { diff --git a/Source/JavaScriptCore/bytecode/Instruction.h b/Source/JavaScriptCore/bytecode/Instruction.h index 6c1260abc..b276fd957 100644 --- a/Source/JavaScriptCore/bytecode/Instruction.h +++ b/Source/JavaScriptCore/bytecode/Instruction.h @@ -154,7 +154,7 @@ namespace JSC { Instruction(Opcode opcode) { -#if !ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) +#if !ENABLE(COMPUTED_GOTO_OPCODES) // We have to initialize one of the pointer members to ensure that // the entire struct is initialized, when opcode is not a pointer. u.jsCell.clear(); diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index 13a2defff..9e993ec65 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -2483,6 +2483,7 @@ PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, Contro context.start = afterFinally; m_tryContextStack.append(context); } + poppedTryContexts.clear(); } if (flipLabelScopes) m_labelScopes = savedLabelScopes; diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp index 3452b2f0d..eaa0f47f7 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.cpp +++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp @@ -1167,13 +1167,6 @@ JSCell* DFG_OPERATION operationCreateInlinedArguments( return result; } -void DFG_OPERATION operationTearOffActivation(ExecState* exec, JSCell* activationCell) -{ - JSGlobalData& globalData = exec->globalData(); - NativeCallFrameTracer tracer(&globalData, exec); - jsCast<JSActivation*>(activationCell)->tearOff(exec->globalData()); -} - void DFG_OPERATION operationTearOffArguments(ExecState* exec, JSCell* argumentsCell, JSCell* activationCell) { ASSERT(exec->codeBlock()->usesArguments()); diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h index f86f5cf1f..3b947ecbf 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.h +++ b/Source/JavaScriptCore/dfg/DFGOperations.h @@ -177,7 +177,6 @@ char* DFG_OPERATION operationLinkConstruct(ExecState*) WTF_INTERNAL; JSCell* DFG_OPERATION operationCreateActivation(ExecState*) WTF_INTERNAL; JSCell* DFG_OPERATION operationCreateArguments(ExecState*) WTF_INTERNAL; JSCell* DFG_OPERATION operationCreateInlinedArguments(ExecState*, InlineCallFrame*) WTF_INTERNAL; -void DFG_OPERATION operationTearOffActivation(ExecState*, JSCell*) WTF_INTERNAL; void DFG_OPERATION operationTearOffArguments(ExecState*, JSCell*, JSCell*) WTF_INTERNAL; void DFG_OPERATION operationTearOffInlinedArguments(ExecState*, JSCell*, JSCell*, InlineCallFrame*) WTF_INTERNAL; EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState*, int32_t) WTF_INTERNAL; diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp index e42752d8a..05b1e741e 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp @@ -1907,9 +1907,10 @@ void SpeculativeJIT::compileValueToInt32(Node& node) SpeculateBooleanOperand op1(this, node.child1()); GPRTemporary result(this, op1); - m_jit.and32(JITCompiler::TrustedImm32(1), op1.gpr()); + m_jit.move(op1.gpr(), result.gpr()); + m_jit.and32(JITCompiler::TrustedImm32(1), result.gpr()); - integerResult(op1.gpr(), m_compileIndex); + integerResult(result.gpr(), m_compileIndex); return; } diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp index 8039ad2ab..70709b52f 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp @@ -30,7 +30,7 @@ #if ENABLE(DFG_JIT) #include "DFGSlowPathGenerator.h" -#include "JSVariableObject.h" +#include "JSActivation.h" namespace JSC { namespace DFG { @@ -4070,16 +4070,38 @@ void SpeculativeJIT::compile(Node& node) case TearOffActivation: { JSValueOperand activationValue(this, node.child1()); + GPRTemporary scratch(this); GPRReg activationValueTagGPR = activationValue.tagGPR(); GPRReg activationValuePayloadGPR = activationValue.payloadGPR(); + GPRReg scratchGPR = scratch.gpr(); - JITCompiler::Jump created = m_jit.branch32(JITCompiler::NotEqual, activationValueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); - - addSlowPathGenerator( - slowPathCall( - created, this, operationTearOffActivation, NoResult, activationValuePayloadGPR)); + JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, activationValueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); + + SharedSymbolTable* symbolTable = m_jit.symbolTableFor(node.codeOrigin); + int registersOffset = JSActivation::registersOffset(symbolTable); + + int captureEnd = symbolTable->captureEnd(); + for (int i = symbolTable->captureStart(); i < captureEnd; ++i) { + m_jit.loadPtr( + JITCompiler::Address( + GPRInfo::callFrameRegister, i * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), + scratchGPR); + m_jit.storePtr( + scratchGPR, JITCompiler::Address( + activationValuePayloadGPR, registersOffset + i * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))); + m_jit.loadPtr( + JITCompiler::Address( + GPRInfo::callFrameRegister, i * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), + scratchGPR); + m_jit.storePtr( + scratchGPR, JITCompiler::Address( + activationValuePayloadGPR, registersOffset + i * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))); + } + m_jit.addPtr(TrustedImm32(registersOffset), activationValuePayloadGPR, scratchGPR); + m_jit.storePtr(scratchGPR, JITCompiler::Address(activationValuePayloadGPR, JSActivation::offsetOfRegisters())); + notCreated.link(&m_jit); noResult(m_compileIndex); break; } diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp index 8488d261d..d7cec27c1 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp @@ -4041,14 +4041,28 @@ void SpeculativeJIT::compile(Node& node) ASSERT(!node.codeOrigin.inlineCallFrame); JSValueOperand activationValue(this, node.child1()); + GPRTemporary scratch(this); GPRReg activationValueGPR = activationValue.gpr(); + GPRReg scratchGPR = scratch.gpr(); - JITCompiler::Jump created = m_jit.branchTestPtr(JITCompiler::NonZero, activationValueGPR); - - addSlowPathGenerator( - slowPathCall( - created, this, operationTearOffActivation, NoResult, activationValueGPR)); - + JITCompiler::Jump notCreated = m_jit.branchTestPtr(JITCompiler::Zero, activationValueGPR); + + SharedSymbolTable* symbolTable = m_jit.symbolTableFor(node.codeOrigin); + int registersOffset = JSActivation::registersOffset(symbolTable); + + int captureEnd = symbolTable->captureEnd(); + for (int i = symbolTable->captureStart(); i < captureEnd; ++i) { + m_jit.loadPtr( + JITCompiler::Address( + GPRInfo::callFrameRegister, i * sizeof(Register)), scratchGPR); + m_jit.storePtr( + scratchGPR, JITCompiler::Address( + activationValueGPR, registersOffset + i * sizeof(Register))); + } + m_jit.addPtr(TrustedImm32(registersOffset), activationValueGPR, scratchGPR); + m_jit.storePtr(scratchGPR, JITCompiler::Address(activationValueGPR, JSActivation::offsetOfRegisters())); + + notCreated.link(&m_jit); noResult(m_compileIndex); break; } diff --git a/Source/JavaScriptCore/interpreter/AbstractPC.cpp b/Source/JavaScriptCore/interpreter/AbstractPC.cpp index f986e8872..12bc3a768 100644 --- a/Source/JavaScriptCore/interpreter/AbstractPC.cpp +++ b/Source/JavaScriptCore/interpreter/AbstractPC.cpp @@ -45,12 +45,6 @@ AbstractPC::AbstractPC(JSGlobalData& globalData, ExecState* exec) return; } #endif - -#if ENABLE(CLASSIC_INTERPRETER) - UNUSED_PARAM(globalData); - m_pointer = exec->returnVPC(); - m_mode = Interpreter; -#endif } } // namespace JSC diff --git a/Source/JavaScriptCore/interpreter/AbstractPC.h b/Source/JavaScriptCore/interpreter/AbstractPC.h index 5ed74472e..09a6db8ea 100644 --- a/Source/JavaScriptCore/interpreter/AbstractPC.h +++ b/Source/JavaScriptCore/interpreter/AbstractPC.h @@ -60,21 +60,6 @@ public: } #endif -#if ENABLE(CLASSIC_INTERPRETER) - AbstractPC(Instruction* vPC) - : m_pointer(vPC) - , m_mode(Interpreter) - { - } - - bool hasInterpreterReturnAddress() const { return m_mode == Interpreter; } - Instruction* interpreterReturnAddress() const - { - ASSERT(hasInterpreterReturnAddress()); - return static_cast<Instruction*>(m_pointer); - } -#endif - bool isSet() const { return m_mode != None; } bool operator!() const { return !isSet(); } diff --git a/Source/JavaScriptCore/interpreter/CallFrame.h b/Source/JavaScriptCore/interpreter/CallFrame.h index da1222ac9..4758e5bd0 100644 --- a/Source/JavaScriptCore/interpreter/CallFrame.h +++ b/Source/JavaScriptCore/interpreter/CallFrame.h @@ -148,9 +148,6 @@ namespace JSC { return 0; } #endif -#if ENABLE(CLASSIC_INTERPRETER) - Instruction* returnVPC() const { return this[RegisterFile::ReturnPC].vPC(); } -#endif #if USE(JSVALUE32_64) Instruction* currentVPC() const { diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp index 3b3409bd6..3107a5dab 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.cpp +++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp @@ -72,7 +72,7 @@ #include "JIT.h" #endif -#define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND ((ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)) && !defined(__llvm__)) +#define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND (ENABLE(LLINT) && !defined(__llvm__)) using namespace std; @@ -88,14 +88,6 @@ static int depth(CodeBlock* codeBlock, JSScope* sc) return sc->localDepth(); } -#if ENABLE(CLASSIC_INTERPRETER) -static NEVER_INLINE JSValue concatenateStrings(ExecState* exec, Register* strings, unsigned count) -{ - return jsString(exec, strings, count); -} - -#endif // ENABLE(CLASSIC_INTERPRETER) - ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argumentCountIncludingThis) { // This ensures enough space for the worst case scenario of zero arguments passed by the caller. @@ -123,16 +115,6 @@ ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newC return newCallFrame; } -#if ENABLE(CLASSIC_INTERPRETER) -static NEVER_INLINE bool isInvalidParamForIn(CallFrame* callFrame, JSValue value, JSValue& exceptionData) -{ - if (value.isObject()) - return false; - exceptionData = createInvalidParamError(callFrame, "in" , value); - return true; -} -#endif - JSValue eval(CallFrame* callFrame) { if (!callFrame->argumentCount()) @@ -166,6 +148,9 @@ JSValue eval(CallFrame* callFrame) return parsedObject; } } + + // If the literal parser bailed, it should not have thrown exceptions. + ASSERT(!callFrame->globalData().exception); JSValue exceptionValue; eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock->ownerExecutable(), callerCodeBlock->isStrictMode(), programSource, callerScopeChain, exceptionValue); @@ -265,59 +250,22 @@ Interpreter::Interpreter() #if !ASSERT_DISABLED , m_initialized(false) #endif - , m_classicEnabled(false) { } Interpreter::~Interpreter() { -#if ENABLE(LLINT) && ENABLE(COMPUTED_GOTO_OPCODES) - if (m_classicEnabled) - delete[] m_opcodeTable; -#endif } void Interpreter::initialize(bool canUseJIT) { UNUSED_PARAM(canUseJIT); - // If we have LLInt, then we shouldn't be building any kind of classic interpreter. -#if ENABLE(LLINT) && ENABLE(CLASSIC_INTERPRETER) -#error "Building both LLInt and the Classic Interpreter is not supported because it doesn't make sense." -#endif - -#if ENABLE(COMPUTED_GOTO_OPCODES) -#if ENABLE(LLINT) +#if ENABLE(COMPUTED_GOTO_OPCODES) && ENABLE(LLINT) m_opcodeTable = LLInt::opcodeMap(); for (int i = 0; i < numOpcodeIDs; ++i) m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i)); - m_classicEnabled = false; - -#elif ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) - if (canUseJIT) { - // If the JIT is present, don't use jump destinations for opcodes. - for (int i = 0; i < numOpcodeIDs; ++i) { - Opcode opcode = bitwise_cast<void*>(static_cast<uintptr_t>(i)); - m_opcodeTable[i] = opcode; - } - m_classicEnabled = false; - } else { - privateExecute(InitializeAndReturn, 0, 0); - - for (int i = 0; i < numOpcodeIDs; ++i) - m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i)); - - m_classicEnabled = true; - } -#endif // ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) - -#else // !ENABLE(COMPUTED_GOTO_OPCODES) -#if ENABLE(CLASSIC_INTERPRETER) - m_classicEnabled = true; -#else - m_classicEnabled = false; #endif -#endif // !ENABLE(COMPUTED_GOTO_OPCODES) #if !ASSERT_DISABLED m_initialized = true; @@ -431,12 +379,12 @@ bool Interpreter::isOpcode(Opcode opcode) { #if ENABLE(COMPUTED_GOTO_OPCODES) #if !ENABLE(LLINT) - if (!m_classicEnabled) - return static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode)) <= op_end; -#endif + return static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode)) <= op_end; +#else return opcode != HashTraits<Opcode>::emptyValue() && !HashTraits<Opcode>::isDeletedValue(opcode) && m_opcodeIDTable.contains(opcode); +#endif #else return opcode >= 0 && opcode <= op_end; #endif @@ -481,19 +429,8 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex // Because of how the JIT records call site->bytecode offset // information the JIT reports the bytecodeOffset for the returnPC // to be at the beginning of the opcode that has caused the call. - // In the interpreter we have an actual return address, which is - // the beginning of next instruction to execute. To get an offset - // inside the call instruction that triggered the exception we - // have to subtract 1. -#if ENABLE(JIT) && ENABLE(CLASSIC_INTERPRETER) - if (callerFrame->globalData().canUseJIT()) - bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC()); - else - bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1; -#elif ENABLE(JIT) || ENABLE(LLINT) +#if ENABLE(JIT) || ENABLE(LLINT) bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC()); -#else - bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1; #endif callFrame = callerFrame; @@ -559,18 +496,12 @@ static int getLineNumberForCallFrame(JSGlobalData* globalData, CallFrame* callFr CodeBlock* codeBlock = callFrame->codeBlock(); if (!codeBlock) return -1; -#if ENABLE(CLASSIC_INTERPRETER) - if (!globalData->canUseJIT()) - return codeBlock->lineNumberForBytecodeOffset(callFrame->bytecodeOffsetForNonDFGCode() - 1); -#endif #if ENABLE(JIT) || ENABLE(LLINT) #if ENABLE(DFG_JIT) if (codeBlock->getJITType() == JITCode::DFGJIT) return codeBlock->lineNumberForBytecodeOffset(codeBlock->codeOrigin(callFrame->codeOriginIndexForDFG()).bytecodeIndex); #endif return codeBlock->lineNumberForBytecodeOffset(callFrame->bytecodeOffsetForNonDFGCode()); -#else - return -1; #endif } @@ -601,13 +532,6 @@ static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, if (callframeIsHost) { // Don't need to deal with inline callframes here as by definition we haven't // inlined a call with an intervening native call frame. -#if ENABLE(CLASSIC_INTERPRETER) - if (!globalData->canUseJIT()) { - bytecodeOffset = callerFrame->bytecodeOffsetForNonDFGCode(); - lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1); - return callerFrame; - } -#endif #if ENABLE(JIT) || ENABLE(LLINT) #if ENABLE(DFG_JIT) if (callerCodeBlock && callerCodeBlock->getJITType() == JITCode::DFGJIT) { @@ -618,13 +542,6 @@ static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, bytecodeOffset = callerFrame->bytecodeOffsetForNonDFGCode(); #endif } else { -#if ENABLE(CLASSIC_INTERPRETER) - if (!globalData->canUseJIT()) { - bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnVPC()); - lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1); - return callerFrame; - } -#endif #if ENABLE(JIT) || ENABLE(LLINT) #if ENABLE(DFG_JIT) if (callFrame->isInlineCallFrame()) { @@ -662,16 +579,7 @@ static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, static ALWAYS_INLINE const String getSourceURLFromCallFrame(CallFrame* callFrame) { ASSERT(!callFrame->hasHostCallFrameFlag()); -#if ENABLE(CLASSIC_INTERPRETER) -#if ENABLE(JIT) - if (callFrame->globalData().canUseJIT()) - return callFrame->codeBlock()->ownerExecutable()->sourceURL(); -#endif - return callFrame->codeBlock()->source()->url(); - -#else return callFrame->codeBlock()->ownerExecutable()->sourceURL(); -#endif } static StackFrameCodeType getStackFrameCodeType(CallFrame* callFrame) @@ -978,14 +886,9 @@ failedJSONP: m_reentryDepth++; #if ENABLE(LLINT_C_LOOP) result = LLInt::CLoop::execute(newCallFrame, llint_program_prologue); -#else // !ENABLE(LLINT_C_LOOP) -#if ENABLE(JIT) - if (!classicEnabled()) - result = program->generatedJITCode().execute(&m_registerFile, newCallFrame, scope->globalData()); - else +#elif ENABLE(JIT) + result = program->generatedJITCode().execute(&m_registerFile, newCallFrame, scope->globalData()); #endif // ENABLE(JIT) - result = privateExecute(Normal, &m_registerFile, newCallFrame); -#endif // !ENABLE(LLINT_C_LOOP) m_reentryDepth--; } @@ -1054,14 +957,9 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT m_reentryDepth++; #if ENABLE(LLINT_C_LOOP) result = LLInt::CLoop::execute(newCallFrame, llint_function_for_call_prologue); -#else // ENABLE(LLINT_C_LOOP) -#if ENABLE(JIT) - if (!classicEnabled()) - result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, newCallFrame, callDataScope->globalData()); - else +#elif ENABLE(JIT) + result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, newCallFrame, callDataScope->globalData()); #endif // ENABLE(JIT) - result = privateExecute(Normal, &m_registerFile, newCallFrame); -#endif // !ENABLE(LLINT_C_LOOP) m_reentryDepth--; } @@ -1153,14 +1051,9 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc m_reentryDepth++; #if ENABLE(LLINT_C_LOOP) result = LLInt::CLoop::execute(newCallFrame, llint_function_for_construct_prologue); -#else // !ENABLE(LLINT_C_LOOP) -#if ENABLE(JIT) - if (!classicEnabled()) - result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_registerFile, newCallFrame, constructDataScope->globalData()); - else +#elif ENABLE(JIT) + result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_registerFile, newCallFrame, constructDataScope->globalData()); #endif // ENABLE(JIT) - result = privateExecute(Normal, &m_registerFile, newCallFrame); -#endif // !ENABLE(LLINT_C_LOOP) m_reentryDepth--; } @@ -1260,21 +1153,9 @@ JSValue Interpreter::execute(CallFrameClosure& closure) m_reentryDepth++; #if ENABLE(LLINT_C_LOOP) result = LLInt::CLoop::execute(closure.newCallFrame, llint_function_for_call_prologue); -#else // !ENABLE(LLINT_C_LOOP) -#if ENABLE(JIT) -#if ENABLE(CLASSIC_INTERPRETER) - if (closure.newCallFrame->globalData().canUseJIT()) -#endif - result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, closure.newCallFrame, closure.globalData); -#if ENABLE(CLASSIC_INTERPRETER) - else -#endif +#elif ENABLE(JIT) + result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, closure.newCallFrame, closure.globalData); #endif // ENABLE(JIT) -#if ENABLE(CLASSIC_INTERPRETER) - result = privateExecute(Normal, &m_registerFile, closure.newCallFrame); -#endif -#endif // !ENABLE(LLINT_C_LOOP) - m_reentryDepth--; } @@ -1365,20 +1246,9 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue #if ENABLE(LLINT_C_LOOP) result = LLInt::CLoop::execute(newCallFrame, llint_eval_prologue); -#else // !ENABLE(LLINT_C_LOOP) -#if ENABLE(JIT) -#if ENABLE(CLASSIC_INTERPRETER) - if (callFrame->globalData().canUseJIT()) -#endif - result = eval->generatedJITCode().execute(&m_registerFile, newCallFrame, scope->globalData()); -#if ENABLE(CLASSIC_INTERPRETER) - else -#endif +#elif ENABLE(JIT) + result = eval->generatedJITCode().execute(&m_registerFile, newCallFrame, scope->globalData()); #endif // ENABLE(JIT) -#if ENABLE(CLASSIC_INTERPRETER) - result = privateExecute(Normal, &m_registerFile, newCallFrame); -#endif -#endif // !ENABLE(LLINT_C_LOOP) m_reentryDepth--; } @@ -1417,3693 +1287,6 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook } } -#if ENABLE(CLASSIC_INTERPRETER) -NEVER_INLINE JSScope* Interpreter::createNameScope(CallFrame* callFrame, const Instruction* vPC) -{ - CodeBlock* codeBlock = callFrame->codeBlock(); - Identifier& property = codeBlock->identifier(vPC[1].u.operand); - JSValue value = callFrame->r(vPC[2].u.operand).jsValue(); - unsigned attributes = vPC[3].u.operand; - JSNameScope* scope = JSNameScope::create(callFrame, property, value, attributes); - return scope; -} - -NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const PutPropertySlot& slot) -{ - // Recursive invocation may already have specialized this instruction. - if (vPC[0].u.opcode != getOpcode(op_put_by_id)) - return; - - if (!baseValue.isCell()) - return; - - // Uncacheable: give up. - if (!slot.isCacheable()) { - vPC[0] = getOpcode(op_put_by_id_generic); - return; - } - - JSCell* baseCell = baseValue.asCell(); - Structure* structure = baseCell->structure(); - - if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) { - vPC[0] = getOpcode(op_put_by_id_generic); - return; - } - - // Cache miss: record Structure to compare against next time. - Structure* lastStructure = vPC[4].u.structure.get(); - if (structure != lastStructure) { - // First miss: record Structure to compare against next time. - if (!lastStructure) { - vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure); - return; - } - - // Second miss: give up. - vPC[0] = getOpcode(op_put_by_id_generic); - return; - } - - // Cache hit: Specialize instruction and ref Structures. - - // If baseCell != slot.base(), then baseCell must be a proxy for another object. - if (baseCell != slot.base()) { - vPC[0] = getOpcode(op_put_by_id_generic); - return; - } - - // Structure transition, cache transition info - if (slot.type() == PutPropertySlot::NewProperty) { - if (structure->isDictionary()) { - vPC[0] = getOpcode(op_put_by_id_generic); - return; - } - - // put_by_id_transition checks the prototype chain for setters. - normalizePrototypeChain(callFrame, baseCell); - JSCell* owner = codeBlock->ownerExecutable(); - JSGlobalData& globalData = callFrame->globalData(); - // Get the prototype here because the call to prototypeChain could cause a - // GC allocation, which we don't want to happen while we're in the middle of - // initializing the union. - StructureChain* prototypeChain = structure->prototypeChain(callFrame); - vPC[0] = getOpcode(op_put_by_id_transition); - vPC[4].u.structure.set(globalData, owner, structure->previousID()); - vPC[5].u.structure.set(globalData, owner, structure); - vPC[6].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), prototypeChain); - ASSERT(vPC[6].u.structureChain); - vPC[7] = slot.cachedOffset(); - return; - } - - vPC[0] = getOpcode(op_put_by_id_replace); - vPC[5] = slot.cachedOffset(); -} - -NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock*, Instruction* vPC) -{ - vPC[0] = getOpcode(op_put_by_id); - vPC[4] = 0; -} - -NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot) -{ - // Recursive invocation may already have specialized this instruction. - if (vPC[0].u.opcode != getOpcode(op_get_by_id)) - return; - - // FIXME: Cache property access for immediates. - if (!baseValue.isCell()) { - vPC[0] = getOpcode(op_get_by_id_generic); - return; - } - - if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) { - vPC[0] = getOpcode(op_get_array_length); - return; - } - - if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) { - vPC[0] = getOpcode(op_get_string_length); - return; - } - - // Uncacheable: give up. - if (!slot.isCacheable()) { - vPC[0] = getOpcode(op_get_by_id_generic); - return; - } - - Structure* structure = baseValue.asCell()->structure(); - - if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) { - vPC[0] = getOpcode(op_get_by_id_generic); - return; - } - - // Cache miss - Structure* lastStructure = vPC[4].u.structure.get(); - if (structure != lastStructure) { - // First miss: record Structure to compare against next time. - if (!lastStructure) { - vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure); - return; - } - - // Second miss: give up. - vPC[0] = getOpcode(op_get_by_id_generic); - return; - } - - // Cache hit: Specialize instruction and ref Structures. - - if (slot.slotBase() == baseValue) { - switch (slot.cachedPropertyType()) { - case PropertySlot::Getter: - vPC[0] = getOpcode(op_get_by_id_getter_self); - vPC[5] = slot.cachedOffset(); - break; - case PropertySlot::Custom: - vPC[0] = getOpcode(op_get_by_id_custom_self); - vPC[5] = slot.customGetter(); - break; - default: - vPC[0] = getOpcode(op_get_by_id_self); - vPC[5] = slot.cachedOffset(); - break; - } - return; - } - - if (structure->isDictionary()) { - vPC[0] = getOpcode(op_get_by_id_generic); - return; - } - - if (slot.slotBase() == structure->prototypeForLookup(callFrame)) { - ASSERT(slot.slotBase().isObject()); - - JSObject* baseObject = asObject(slot.slotBase()); - PropertyOffset offset = slot.cachedOffset(); - - // Since we're accessing a prototype in a loop, it's a good bet that it - // should not be treated as a dictionary. - if (baseObject->structure()->isDictionary()) { - baseObject->flattenDictionaryObject(callFrame->globalData()); - offset = baseObject->structure()->get(callFrame->globalData(), propertyName); - } - - ASSERT(!baseObject->structure()->isUncacheableDictionary()); - - switch (slot.cachedPropertyType()) { - case PropertySlot::Getter: - vPC[0] = getOpcode(op_get_by_id_getter_proto); - vPC[6] = offset; - break; - case PropertySlot::Custom: - vPC[0] = getOpcode(op_get_by_id_custom_proto); - vPC[6] = slot.customGetter(); - break; - default: - vPC[0] = getOpcode(op_get_by_id_proto); - vPC[6] = offset; - break; - } - vPC[5].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), baseObject->structure()); - return; - } - - PropertyOffset offset = slot.cachedOffset(); - size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset); - if (!count) { - vPC[0] = getOpcode(op_get_by_id_generic); - return; - } - - - StructureChain* prototypeChain = structure->prototypeChain(callFrame); - switch (slot.cachedPropertyType()) { - case PropertySlot::Getter: - vPC[0] = getOpcode(op_get_by_id_getter_chain); - vPC[7] = offset; - break; - case PropertySlot::Custom: - vPC[0] = getOpcode(op_get_by_id_custom_chain); - vPC[7] = slot.customGetter(); - break; - default: - vPC[0] = getOpcode(op_get_by_id_chain); - vPC[7] = offset; - break; - } - vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure); - vPC[5].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), prototypeChain); - vPC[6] = count; -} - -NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock*, Instruction* vPC) -{ - vPC[0] = getOpcode(op_get_by_id); - vPC[4] = 0; -} - -#endif // ENABLE(CLASSIC_INTERPRETER) - -#if !ENABLE(LLINT_C_LOOP) - -JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame) -{ - // One-time initialization of our address tables. We have to put this code - // here because our labels are only in scope inside this function. - if (UNLIKELY(flag == InitializeAndReturn)) { - #if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) - #define LIST_OPCODE_LABEL(id, length) &&id, - static Opcode labels[] = { FOR_EACH_OPCODE_ID(LIST_OPCODE_LABEL) }; - for (size_t i = 0; i < WTF_ARRAY_LENGTH(labels); ++i) - m_opcodeTable[i] = labels[i]; - #undef LIST_OPCODE_LABEL - #endif // ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) - return JSValue(); - } - - ASSERT(m_initialized); - ASSERT(m_classicEnabled); - -#if ENABLE(JIT) -#if ENABLE(CLASSIC_INTERPRETER) - // Mixing Interpreter + JIT is not supported. - if (callFrame->globalData().canUseJIT()) -#endif - ASSERT_NOT_REACHED(); -#endif - -#if !ENABLE(CLASSIC_INTERPRETER) - UNUSED_PARAM(registerFile); - UNUSED_PARAM(callFrame); - return JSValue(); -#else - - ASSERT(callFrame->globalData().topCallFrame == callFrame); - - JSGlobalData* globalData = &callFrame->globalData(); - JSValue exceptionValue; - HandlerInfo* handler = 0; - CallFrame** topCallFrameSlot = &globalData->topCallFrame; - - CodeBlock* codeBlock = callFrame->codeBlock(); - Instruction* vPC = codeBlock->instructions().begin(); - unsigned tickCount = globalData->timeoutChecker.ticksUntilNextCheck(); - JSValue functionReturnValue; - -#define CHECK_FOR_EXCEPTION() \ - do { \ - if (UNLIKELY(globalData->exception != JSValue())) { \ - exceptionValue = globalData->exception; \ - goto vm_throw; \ - } \ - } while (0) - -#if ENABLE(OPCODE_STATS) - OpcodeStats::resetLastInstruction(); -#endif - -#define CHECK_FOR_TIMEOUT() \ - if (!--tickCount) { \ - if (globalData->terminator.shouldTerminate() || globalData->timeoutChecker.didTimeOut(callFrame)) { \ - exceptionValue = jsNull(); \ - goto vm_throw; \ - } \ - tickCount = globalData->timeoutChecker.ticksUntilNextCheck(); \ - } - -#if ENABLE(OPCODE_SAMPLING) - #define SAMPLE(codeBlock, vPC) m_sampler->sample(codeBlock, vPC) -#else - #define SAMPLE(codeBlock, vPC) -#endif - -#define UPDATE_BYTECODE_OFFSET() \ - do {\ - callFrame->setBytecodeOffsetForNonDFGCode(vPC - codeBlock->instructions().data() + 1);\ - } while (0) - -#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) - #define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto *vPC->u.opcode -#if ENABLE(OPCODE_STATS) - #define DEFINE_OPCODE(opcode) \ - opcode:\ - OpcodeStats::recordInstruction(opcode);\ - UPDATE_BYTECODE_OFFSET(); -#else - #define DEFINE_OPCODE(opcode) opcode: UPDATE_BYTECODE_OFFSET(); -#endif // !ENABLE(OPCODE_STATS) - NEXT_INSTRUCTION(); -#else // !ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) - #define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto interpreterLoopStart -#if ENABLE(OPCODE_STATS) - #define DEFINE_OPCODE(opcode) \ - case opcode:\ - OpcodeStats::recordInstruction(opcode);\ - UPDATE_BYTECODE_OFFSET(); -#else - #define DEFINE_OPCODE(opcode) case opcode: UPDATE_BYTECODE_OFFSET(); -#endif - while (1) { // iterator loop begins - interpreterLoopStart:; - switch (vPC->u.opcode) -#endif // !ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) - { - DEFINE_OPCODE(op_new_object) { - /* new_object dst(r) - - Constructs a new empty Object instance using the original - constructor, and puts the result in register dst. - */ - int dst = vPC[1].u.operand; - callFrame->uncheckedR(dst) = JSValue(constructEmptyObject(callFrame)); - - vPC += OPCODE_LENGTH(op_new_object); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_new_array) { - /* new_array dst(r) firstArg(r) argCount(n) - - Constructs a new Array instance using the original - constructor, and puts the result in register dst. - The array will contain argCount elements with values - taken from registers starting at register firstArg. - */ - int dst = vPC[1].u.operand; - int firstArg = vPC[2].u.operand; - int argCount = vPC[3].u.operand; - callFrame->uncheckedR(dst) = JSValue(constructArray(callFrame, reinterpret_cast<JSValue*>(&callFrame->registers()[firstArg]), argCount)); - - vPC += OPCODE_LENGTH(op_new_array); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_new_array_buffer) { - /* new_array_buffer dst(r) index(n) argCount(n) - - Constructs a new Array instance using the original - constructor, and puts the result in register dst. - The array be initialized with the values from constantBuffer[index] - */ - int dst = vPC[1].u.operand; - int firstArg = vPC[2].u.operand; - int argCount = vPC[3].u.operand; - callFrame->uncheckedR(dst) = JSValue(constructArray(callFrame, codeBlock->constantBuffer(firstArg), argCount)); - - vPC += OPCODE_LENGTH(op_new_array); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_new_regexp) { - /* new_regexp dst(r) regExp(re) - - Constructs a new RegExp instance using the original - constructor from regexp regExp, and puts the result in - register dst. - */ - int dst = vPC[1].u.operand; - RegExp* regExp = codeBlock->regexp(vPC[2].u.operand); - if (!regExp->isValid()) { - exceptionValue = createSyntaxError(callFrame, "Invalid flags supplied to RegExp constructor."); - goto vm_throw; - } - callFrame->uncheckedR(dst) = JSValue(RegExpObject::create(*globalData, callFrame->lexicalGlobalObject(), callFrame->scope()->globalObject()->regExpStructure(), regExp)); - - vPC += OPCODE_LENGTH(op_new_regexp); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_mov) { - /* mov dst(r) src(r) - - Copies register src to register dst. - */ - int dst = vPC[1].u.operand; - int src = vPC[2].u.operand; - - callFrame->uncheckedR(dst) = callFrame->r(src); - - vPC += OPCODE_LENGTH(op_mov); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_eq) { - /* eq dst(r) src1(r) src2(r) - - Checks whether register src1 and register src2 are equal, - as with the ECMAScript '==' operator, and puts the result - as a boolean in register dst. - */ - int dst = vPC[1].u.operand; - JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - if (src1.isInt32() && src2.isInt32()) - callFrame->uncheckedR(dst) = jsBoolean(src1.asInt32() == src2.asInt32()); - else { - JSValue result = jsBoolean(JSValue::equalSlowCase(callFrame, src1, src2)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } - - vPC += OPCODE_LENGTH(op_eq); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_eq_null) { - /* eq_null dst(r) src(r) - - Checks whether register src is null, as with the ECMAScript '!=' - operator, and puts the result as a boolean in register dst. - */ - int dst = vPC[1].u.operand; - JSValue src = callFrame->r(vPC[2].u.operand).jsValue(); - - if (src.isUndefinedOrNull()) { - callFrame->uncheckedR(dst) = jsBoolean(true); - vPC += OPCODE_LENGTH(op_eq_null); - NEXT_INSTRUCTION(); - } - - callFrame->uncheckedR(dst) = jsBoolean(src.isCell() && src.asCell()->structure()->masqueradesAsUndefined(callFrame->lexicalGlobalObject())); - vPC += OPCODE_LENGTH(op_eq_null); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_neq) { - /* neq dst(r) src1(r) src2(r) - - Checks whether register src1 and register src2 are not - equal, as with the ECMAScript '!=' operator, and puts the - result as a boolean in register dst. - */ - int dst = vPC[1].u.operand; - JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - if (src1.isInt32() && src2.isInt32()) - callFrame->uncheckedR(dst) = jsBoolean(src1.asInt32() != src2.asInt32()); - else { - JSValue result = jsBoolean(!JSValue::equalSlowCase(callFrame, src1, src2)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } - - vPC += OPCODE_LENGTH(op_neq); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_neq_null) { - /* neq_null dst(r) src(r) - - Checks whether register src is not null, as with the ECMAScript '!=' - operator, and puts the result as a boolean in register dst. - */ - int dst = vPC[1].u.operand; - JSValue src = callFrame->r(vPC[2].u.operand).jsValue(); - - if (src.isUndefinedOrNull()) { - callFrame->uncheckedR(dst) = jsBoolean(false); - vPC += OPCODE_LENGTH(op_neq_null); - NEXT_INSTRUCTION(); - } - - callFrame->uncheckedR(dst) = jsBoolean(!src.isCell() || !src.asCell()->structure()->masqueradesAsUndefined(callFrame->lexicalGlobalObject())); - vPC += OPCODE_LENGTH(op_neq_null); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_stricteq) { - /* stricteq dst(r) src1(r) src2(r) - - Checks whether register src1 and register src2 are strictly - equal, as with the ECMAScript '===' operator, and puts the - result as a boolean in register dst. - */ - int dst = vPC[1].u.operand; - JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - bool result = JSValue::strictEqual(callFrame, src1, src2); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = jsBoolean(result); - - vPC += OPCODE_LENGTH(op_stricteq); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_nstricteq) { - /* nstricteq dst(r) src1(r) src2(r) - - Checks whether register src1 and register src2 are not - strictly equal, as with the ECMAScript '!==' operator, and - puts the result as a boolean in register dst. - */ - int dst = vPC[1].u.operand; - JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - bool result = !JSValue::strictEqual(callFrame, src1, src2); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = jsBoolean(result); - - vPC += OPCODE_LENGTH(op_nstricteq); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_less) { - /* less dst(r) src1(r) src2(r) - - Checks whether register src1 is less than register src2, as - with the ECMAScript '<' operator, and puts the result as - a boolean in register dst. - */ - int dst = vPC[1].u.operand; - JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - JSValue result = jsBoolean(jsLess<true>(callFrame, src1, src2)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - - vPC += OPCODE_LENGTH(op_less); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_lesseq) { - /* lesseq dst(r) src1(r) src2(r) - - Checks whether register src1 is less than or equal to - register src2, as with the ECMAScript '<=' operator, and - puts the result as a boolean in register dst. - */ - int dst = vPC[1].u.operand; - JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - JSValue result = jsBoolean(jsLessEq<true>(callFrame, src1, src2)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - - vPC += OPCODE_LENGTH(op_lesseq); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_greater) { - /* greater dst(r) src1(r) src2(r) - - Checks whether register src1 is greater than register src2, as - with the ECMAScript '>' operator, and puts the result as - a boolean in register dst. - */ - int dst = vPC[1].u.operand; - JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - JSValue result = jsBoolean(jsLess<false>(callFrame, src2, src1)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - - vPC += OPCODE_LENGTH(op_greater); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_greatereq) { - /* greatereq dst(r) src1(r) src2(r) - - Checks whether register src1 is greater than or equal to - register src2, as with the ECMAScript '>=' operator, and - puts the result as a boolean in register dst. - */ - int dst = vPC[1].u.operand; - JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - JSValue result = jsBoolean(jsLessEq<false>(callFrame, src2, src1)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - - vPC += OPCODE_LENGTH(op_greatereq); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_pre_inc) { - /* pre_inc srcDst(r) - - Converts register srcDst to number, adds one, and puts the result - back in register srcDst. - */ - int srcDst = vPC[1].u.operand; - JSValue v = callFrame->r(srcDst).jsValue(); - if (v.isInt32() && v.asInt32() < INT_MAX) - callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() + 1); - else { - JSValue result = jsNumber(v.toNumber(callFrame) + 1); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(srcDst) = result; - } - - vPC += OPCODE_LENGTH(op_pre_inc); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_pre_dec) { - /* pre_dec srcDst(r) - - Converts register srcDst to number, subtracts one, and puts the result - back in register srcDst. - */ - int srcDst = vPC[1].u.operand; - JSValue v = callFrame->r(srcDst).jsValue(); - if (v.isInt32() && v.asInt32() > INT_MIN) - callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() - 1); - else { - JSValue result = jsNumber(v.toNumber(callFrame) - 1); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(srcDst) = result; - } - - vPC += OPCODE_LENGTH(op_pre_dec); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_post_inc) { - /* post_inc dst(r) srcDst(r) - - Converts register srcDst to number. The number itself is - written to register dst, and the number plus one is written - back to register srcDst. - */ - int dst = vPC[1].u.operand; - int srcDst = vPC[2].u.operand; - JSValue v = callFrame->r(srcDst).jsValue(); - if (v.isInt32() && v.asInt32() < INT_MAX) { - callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() + 1); - callFrame->uncheckedR(dst) = v; - } else { - double number = callFrame->r(srcDst).jsValue().toNumber(callFrame); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(srcDst) = jsNumber(number + 1); - callFrame->uncheckedR(dst) = jsNumber(number); - } - - vPC += OPCODE_LENGTH(op_post_inc); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_post_dec) { - /* post_dec dst(r) srcDst(r) - - Converts register srcDst to number. The number itself is - written to register dst, and the number minus one is written - back to register srcDst. - */ - int dst = vPC[1].u.operand; - int srcDst = vPC[2].u.operand; - JSValue v = callFrame->r(srcDst).jsValue(); - if (v.isInt32() && v.asInt32() > INT_MIN) { - callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() - 1); - callFrame->uncheckedR(dst) = v; - } else { - double number = callFrame->r(srcDst).jsValue().toNumber(callFrame); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(srcDst) = jsNumber(number - 1); - callFrame->uncheckedR(dst) = jsNumber(number); - } - - vPC += OPCODE_LENGTH(op_post_dec); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_to_jsnumber) { - /* to_jsnumber dst(r) src(r) - - Converts register src to number, and puts the result - in register dst. - */ - int dst = vPC[1].u.operand; - int src = vPC[2].u.operand; - - JSValue srcVal = callFrame->r(src).jsValue(); - - if (LIKELY(srcVal.isNumber())) - callFrame->uncheckedR(dst) = callFrame->r(src); - else { - double number = srcVal.toNumber(callFrame); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = jsNumber(number); - } - - vPC += OPCODE_LENGTH(op_to_jsnumber); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_negate) { - /* negate dst(r) src(r) - - Converts register src to number, negates it, and puts the - result in register dst. - */ - int dst = vPC[1].u.operand; - JSValue src = callFrame->r(vPC[2].u.operand).jsValue(); - if (src.isInt32() && (src.asInt32() & 0x7fffffff)) // non-zero and no overflow - callFrame->uncheckedR(dst) = jsNumber(-src.asInt32()); - else { - JSValue result = jsNumber(-src.toNumber(callFrame)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } - - vPC += OPCODE_LENGTH(op_negate); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_add) { - /* add dst(r) src1(r) src2(r) - - Adds register src1 and register src2, and puts the result - in register dst. (JS add may be string concatenation or - numeric add, depending on the types of the operands.) - */ - int dst = vPC[1].u.operand; - JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - if (src1.isInt32() && src2.isInt32() && !((src1.asInt32() | src2.asInt32()) & 0xc0000000)) // no overflow - callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() + src2.asInt32()); - else { - JSValue result = jsAdd(callFrame, src1, src2); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } - vPC += OPCODE_LENGTH(op_add); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_mul) { - /* mul dst(r) src1(r) src2(r) - - Multiplies register src1 and register src2 (converted to - numbers), and puts the product in register dst. - */ - int dst = vPC[1].u.operand; - JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32()) >> 15) // no overflow - callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() * src2.asInt32()); - else { - JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } - - vPC += OPCODE_LENGTH(op_mul); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_div) { - /* div dst(r) dividend(r) divisor(r) - - Divides register dividend (converted to number) by the - register divisor (converted to number), and puts the - quotient in register dst. - */ - int dst = vPC[1].u.operand; - JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue(); - - JSValue result = jsNumber(dividend.toNumber(callFrame) / divisor.toNumber(callFrame)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - - vPC += OPCODE_LENGTH(op_div); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_mod) { - /* mod dst(r) dividend(r) divisor(r) - - Divides register dividend (converted to number) by - register divisor (converted to number), and puts the - remainder in register dst. - */ - int dst = vPC[1].u.operand; - JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue(); - - if (dividend.isInt32() && divisor.isInt32() && divisor.asInt32() != 0 && divisor.asInt32() != -1) { - JSValue result = jsNumber(dividend.asInt32() % divisor.asInt32()); - ASSERT(result); - callFrame->uncheckedR(dst) = result; - vPC += OPCODE_LENGTH(op_mod); - NEXT_INSTRUCTION(); - } - - // Conversion to double must happen outside the call to fmod since the - // order of argument evaluation is not guaranteed. - double d1 = dividend.toNumber(callFrame); - double d2 = divisor.toNumber(callFrame); - JSValue result = jsNumber(fmod(d1, d2)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - vPC += OPCODE_LENGTH(op_mod); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_sub) { - /* sub dst(r) src1(r) src2(r) - - Subtracts register src2 (converted to number) from register - src1 (converted to number), and puts the difference in - register dst. - */ - int dst = vPC[1].u.operand; - JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - if (src1.isInt32() && src2.isInt32() && !((src1.asInt32() | src2.asInt32()) & 0xc0000000)) // no overflow - callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() - src2.asInt32()); - else { - JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } - vPC += OPCODE_LENGTH(op_sub); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_lshift) { - /* lshift dst(r) val(r) shift(r) - - Performs left shift of register val (converted to int32) by - register shift (converted to uint32), and puts the result - in register dst. - */ - int dst = vPC[1].u.operand; - JSValue val = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue shift = callFrame->r(vPC[3].u.operand).jsValue(); - - if (val.isInt32() && shift.isInt32()) - callFrame->uncheckedR(dst) = jsNumber(val.asInt32() << (shift.asInt32() & 0x1f)); - else { - JSValue result = jsNumber((val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } - - vPC += OPCODE_LENGTH(op_lshift); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_rshift) { - /* rshift dst(r) val(r) shift(r) - - Performs arithmetic right shift of register val (converted - to int32) by register shift (converted to - uint32), and puts the result in register dst. - */ - int dst = vPC[1].u.operand; - JSValue val = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue shift = callFrame->r(vPC[3].u.operand).jsValue(); - - if (val.isInt32() && shift.isInt32()) - callFrame->uncheckedR(dst) = jsNumber(val.asInt32() >> (shift.asInt32() & 0x1f)); - else { - JSValue result = jsNumber((val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } - - vPC += OPCODE_LENGTH(op_rshift); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_urshift) { - /* rshift dst(r) val(r) shift(r) - - Performs logical right shift of register val (converted - to uint32) by register shift (converted to - uint32), and puts the result in register dst. - */ - int dst = vPC[1].u.operand; - JSValue val = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue shift = callFrame->r(vPC[3].u.operand).jsValue(); - if (val.isUInt32() && shift.isInt32()) - callFrame->uncheckedR(dst) = jsNumber(val.asInt32() >> (shift.asInt32() & 0x1f)); - else { - JSValue result = jsNumber((val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } - - vPC += OPCODE_LENGTH(op_urshift); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_bitand) { - /* bitand dst(r) src1(r) src2(r) - - Computes bitwise AND of register src1 (converted to int32) - and register src2 (converted to int32), and puts the result - in register dst. - */ - int dst = vPC[1].u.operand; - JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - if (src1.isInt32() && src2.isInt32()) - callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() & src2.asInt32()); - else { - JSValue result = jsNumber(src1.toInt32(callFrame) & src2.toInt32(callFrame)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } - - vPC += OPCODE_LENGTH(op_bitand); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_bitxor) { - /* bitxor dst(r) src1(r) src2(r) - - Computes bitwise XOR of register src1 (converted to int32) - and register src2 (converted to int32), and puts the result - in register dst. - */ - int dst = vPC[1].u.operand; - JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - if (src1.isInt32() && src2.isInt32()) - callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() ^ src2.asInt32()); - else { - JSValue result = jsNumber(src1.toInt32(callFrame) ^ src2.toInt32(callFrame)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } - - vPC += OPCODE_LENGTH(op_bitxor); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_bitor) { - /* bitor dst(r) src1(r) src2(r) - - Computes bitwise OR of register src1 (converted to int32) - and register src2 (converted to int32), and puts the - result in register dst. - */ - int dst = vPC[1].u.operand; - JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - if (src1.isInt32() && src2.isInt32()) - callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() | src2.asInt32()); - else { - JSValue result = jsNumber(src1.toInt32(callFrame) | src2.toInt32(callFrame)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } - - vPC += OPCODE_LENGTH(op_bitor); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_not) { - /* not dst(r) src(r) - - Computes logical NOT of register src (converted to - boolean), and puts the result in register dst. - */ - int dst = vPC[1].u.operand; - int src = vPC[2].u.operand; - JSValue result = jsBoolean(!callFrame->r(src).jsValue().toBoolean(callFrame)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - - vPC += OPCODE_LENGTH(op_not); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_check_has_instance) { - /* check_has_instance constructor(r) - - Check 'constructor' is an object with the internal property - [HasInstance] (i.e. is a function ... *shakes head sadly at - JSC API*). Raises an exception if register constructor is not - an valid parameter for instanceof. - */ - int dst = vPC[1].u.operand; - int value = vPC[2].u.operand; - int base = vPC[3].u.operand; - int target = vPC[4].u.operand; - - JSValue baseVal = callFrame->r(base).jsValue(); - - if (baseVal.isObject()) { - TypeInfo info = asObject(baseVal)->structure()->typeInfo(); - if (info.implementsDefaultHasInstance()) { - vPC += OPCODE_LENGTH(op_check_has_instance); - NEXT_INSTRUCTION(); - } - if (info.implementsHasInstance()) { - JSValue baseVal = callFrame->r(base).jsValue(); - bool result = asObject(baseVal)->methodTable()->customHasInstance(asObject(baseVal), callFrame, callFrame->r(value).jsValue()); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = jsBoolean(result); - - vPC += target; - NEXT_INSTRUCTION(); - } - } - - exceptionValue = createInvalidParamError(callFrame, "instanceof" , baseVal); - goto vm_throw; - } - DEFINE_OPCODE(op_instanceof) { - /* instanceof dst(r) value(r) constructor(r) constructorProto(r) - - Tests whether register value is an instance of register - constructor, and puts the boolean result in register - dst. Register constructorProto must contain the "prototype" - property (not the actual prototype) of the object in - register constructor. This lookup is separated so that - polymorphic inline caching can apply. - - Raises an exception if register constructor is not an - object. - */ - int dst = vPC[1].u.operand; - int value = vPC[2].u.operand; - int baseProto = vPC[3].u.operand; - - bool result = JSObject::defaultHasInstance(callFrame, callFrame->r(value).jsValue(), callFrame->r(baseProto).jsValue()); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = jsBoolean(result); - - vPC += OPCODE_LENGTH(op_instanceof); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_typeof) { - /* typeof dst(r) src(r) - - Determines the type string for src according to ECMAScript - rules, and puts the result in register dst. - */ - int dst = vPC[1].u.operand; - int src = vPC[2].u.operand; - callFrame->uncheckedR(dst) = JSValue(jsTypeStringForValue(callFrame, callFrame->r(src).jsValue())); - - vPC += OPCODE_LENGTH(op_typeof); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_is_undefined) { - /* is_undefined dst(r) src(r) - - Determines whether the type string for src according to - the ECMAScript rules is "undefined", and puts the result - in register dst. - */ - int dst = vPC[1].u.operand; - int src = vPC[2].u.operand; - JSValue v = callFrame->r(src).jsValue(); - callFrame->uncheckedR(dst) = jsBoolean(v.isCell() ? v.asCell()->structure()->masqueradesAsUndefined(callFrame->lexicalGlobalObject()) : v.isUndefined()); - - vPC += OPCODE_LENGTH(op_is_undefined); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_is_boolean) { - /* is_boolean dst(r) src(r) - - Determines whether the type string for src according to - the ECMAScript rules is "boolean", and puts the result - in register dst. - */ - int dst = vPC[1].u.operand; - int src = vPC[2].u.operand; - callFrame->uncheckedR(dst) = jsBoolean(callFrame->r(src).jsValue().isBoolean()); - - vPC += OPCODE_LENGTH(op_is_boolean); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_is_number) { - /* is_number dst(r) src(r) - - Determines whether the type string for src according to - the ECMAScript rules is "number", and puts the result - in register dst. - */ - int dst = vPC[1].u.operand; - int src = vPC[2].u.operand; - callFrame->uncheckedR(dst) = jsBoolean(callFrame->r(src).jsValue().isNumber()); - - vPC += OPCODE_LENGTH(op_is_number); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_is_string) { - /* is_string dst(r) src(r) - - Determines whether the type string for src according to - the ECMAScript rules is "string", and puts the result - in register dst. - */ - int dst = vPC[1].u.operand; - int src = vPC[2].u.operand; - callFrame->uncheckedR(dst) = jsBoolean(callFrame->r(src).jsValue().isString()); - - vPC += OPCODE_LENGTH(op_is_string); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_is_object) { - /* is_object dst(r) src(r) - - Determines whether the type string for src according to - the ECMAScript rules is "object", and puts the result - in register dst. - */ - int dst = vPC[1].u.operand; - int src = vPC[2].u.operand; - callFrame->uncheckedR(dst) = jsBoolean(jsIsObjectType(callFrame, callFrame->r(src).jsValue())); - - vPC += OPCODE_LENGTH(op_is_object); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_is_function) { - /* is_function dst(r) src(r) - - Determines whether the type string for src according to - the ECMAScript rules is "function", and puts the result - in register dst. - */ - int dst = vPC[1].u.operand; - int src = vPC[2].u.operand; - callFrame->uncheckedR(dst) = jsBoolean(jsIsFunctionType(callFrame->r(src).jsValue())); - - vPC += OPCODE_LENGTH(op_is_function); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_in) { - /* in dst(r) property(r) base(r) - - Tests whether register base has a property named register - property, and puts the boolean result in register dst. - - Raises an exception if register constructor is not an - object. - */ - int dst = vPC[1].u.operand; - int property = vPC[2].u.operand; - int base = vPC[3].u.operand; - - JSValue baseVal = callFrame->r(base).jsValue(); - if (isInvalidParamForIn(callFrame, baseVal, exceptionValue)) - goto vm_throw; - - JSObject* baseObj = asObject(baseVal); - - JSValue propName = callFrame->r(property).jsValue(); - - uint32_t i; - if (propName.getUInt32(i)) - callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, i)); - else if (isName(propName)) - callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, jsCast<NameInstance*>(propName.asCell())->privateName())); - else { - Identifier property(callFrame, propName.toString(callFrame)->value(callFrame)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, property)); - } - - vPC += OPCODE_LENGTH(op_in); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_resolve) { - /* resolve dst(r) property(id) - - Looks up the property named by identifier property in the - scope chain, and writes the resulting value to register - dst. If the property is not found, raises an exception. - */ - int dst = vPC[1].u.operand; - int property = vPC[2].u.operand; - Identifier& ident = callFrame->codeBlock()->identifier(property); - - JSValue result = JSScope::resolve(callFrame, ident); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - - vPC += OPCODE_LENGTH(op_resolve); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_resolve_skip) { - /* resolve_skip dst(r) property(id) skip(n) - - Looks up the property named by identifier property in the - scope chain skipping the top 'skip' levels, and writes the resulting - value to register dst. If the property is not found, raises an exception. - */ - int dst = vPC[1].u.operand; - int property = vPC[2].u.operand; - int skip = vPC[3].u.operand; - Identifier& ident = callFrame->codeBlock()->identifier(property); - - JSValue result = JSScope::resolveSkip(callFrame, ident, skip); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - - vPC += OPCODE_LENGTH(op_resolve_skip); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_resolve_global) { - /* resolve_skip dst(r) globalObject(c) property(id) structure(sID) offset(n) - - Performs a dynamic property lookup for the given property, on the provided - global object. If structure matches the Structure of the global then perform - a fast lookup using the case offset, otherwise fall back to a full resolve and - cache the new structure and offset - */ - int dst = vPC[1].u.operand; - int property = vPC[2].u.operand; - Identifier& ident = callFrame->codeBlock()->identifier(property); - - JSValue result = JSScope::resolveGlobal( - callFrame, - ident, - callFrame->lexicalGlobalObject(), - &vPC[3].u.structure, - &vPC[4].u.operand - ); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - - vPC += OPCODE_LENGTH(op_resolve_global); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_resolve_global_dynamic) { - /* resolve_skip dst(r) globalObject(c) property(id) structure(sID) offset(n), depth(n) - - Performs a dynamic property lookup for the given property, on the provided - global object. If structure matches the Structure of the global then perform - a fast lookup using the case offset, otherwise fall back to a full resolve and - cache the new structure and offset. - - This walks through n levels of the scope chain to verify that none of those levels - in the scope chain include dynamically added properties. - */ - int dst = vPC[1].u.operand; - int property = vPC[2].u.operand; - int skip = vPC[5].u.operand; - Identifier& ident = callFrame->codeBlock()->identifier(property); - - JSValue result = JSScope::resolveGlobalDynamic(callFrame, ident, skip, &vPC[3].u.structure, &vPC[4].u.operand); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - - vPC += OPCODE_LENGTH(op_resolve_global_dynamic); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_get_global_var) { - /* get_global_var dst(r) globalObject(c) registerPointer(n) - - Gets the global var at global slot index and places it in register dst. - */ - int dst = vPC[1].u.operand; - WriteBarrier<Unknown>* registerPointer = vPC[2].u.registerPointer; - - callFrame->uncheckedR(dst) = registerPointer->get(); - vPC += OPCODE_LENGTH(op_get_global_var); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_get_global_var_watchable) { - /* get_global_var_watchable dst(r) globalObject(c) registerPointer(n) - - Gets the global var at global slot index and places it in register dst. - */ - int dst = vPC[1].u.operand; - WriteBarrier<Unknown>* registerPointer = vPC[2].u.registerPointer; - - callFrame->uncheckedR(dst) = registerPointer->get(); - vPC += OPCODE_LENGTH(op_get_global_var_watchable); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_init_global_const) - DEFINE_OPCODE(op_put_global_var) { - /* put_global_var globalObject(c) registerPointer(n) value(r) - - Puts value into global slot index. - */ - JSGlobalObject* scope = codeBlock->globalObject(); - ASSERT(scope->isGlobalObject()); - WriteBarrier<Unknown>* registerPointer = vPC[1].u.registerPointer; - int value = vPC[2].u.operand; - - registerPointer->set(*globalData, scope, callFrame->r(value).jsValue()); - vPC += OPCODE_LENGTH(op_put_global_var); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_init_global_const_check) - DEFINE_OPCODE(op_put_global_var_check) { - /* put_global_var_check globalObject(c) registerPointer(n) value(r) - - Puts value into global slot index. In JIT configurations this will - perform a watchpoint check. If we're running with the old interpreter, - this is not necessary; the interpreter never uses these watchpoints. - */ - JSGlobalObject* scope = codeBlock->globalObject(); - ASSERT(scope->isGlobalObject()); - WriteBarrier<Unknown>* registerPointer = vPC[1].u.registerPointer; - int value = vPC[2].u.operand; - - registerPointer->set(*globalData, scope, callFrame->r(value).jsValue()); - vPC += OPCODE_LENGTH(op_put_global_var_check); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_get_scoped_var) { - /* get_scoped_var dst(r) index(n) skip(n) - - Loads the contents of the index-th local from the scope skip nodes from - the top of the scope chain, and places it in register dst. - */ - int dst = vPC[1].u.operand; - int index = vPC[2].u.operand; - int skip = vPC[3].u.operand; - - JSScope* scope = callFrame->scope(); - ScopeChainIterator iter = scope->begin(); - ScopeChainIterator end = scope->end(); - ASSERT_UNUSED(end, iter != end); - ASSERT(codeBlock == callFrame->codeBlock()); - bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain(); - ASSERT(skip || !checkTopLevel); - if (checkTopLevel && skip--) { - if (callFrame->r(codeBlock->activationRegister()).jsValue()) - ++iter; - } - while (skip--) { - ++iter; - ASSERT_UNUSED(end, iter != end); - } - ASSERT(iter->isVariableObject()); - JSVariableObject* variableObject = jsCast<JSVariableObject*>(iter.get()); - callFrame->uncheckedR(dst) = variableObject->registerAt(index).get(); - ASSERT(callFrame->r(dst).jsValue()); - vPC += OPCODE_LENGTH(op_get_scoped_var); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_put_scoped_var) { - /* put_scoped_var index(n) skip(n) value(r) - - */ - int index = vPC[1].u.operand; - int skip = vPC[2].u.operand; - int value = vPC[3].u.operand; - - JSScope* scope = callFrame->scope(); - ScopeChainIterator iter = scope->begin(); - ScopeChainIterator end = scope->end(); - ASSERT(codeBlock == callFrame->codeBlock()); - ASSERT_UNUSED(end, iter != end); - bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain(); - ASSERT(skip || !checkTopLevel); - if (checkTopLevel && skip--) { - if (callFrame->r(codeBlock->activationRegister()).jsValue()) - ++iter; - } - while (skip--) { - ++iter; - ASSERT_UNUSED(end, iter != end); - } - - ASSERT(iter->isVariableObject()); - JSVariableObject* variableObject = jsCast<JSVariableObject*>(iter.get()); - ASSERT(callFrame->r(value).jsValue()); - variableObject->registerAt(index).set(*globalData, variableObject, callFrame->r(value).jsValue()); - vPC += OPCODE_LENGTH(op_put_scoped_var); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_resolve_base) { - /* resolve_base dst(r) property(id) isStrict(bool) - - Searches the scope chain for an object containing - identifier property, and if one is found, writes it to - register dst. If none is found and isStrict is false, the - outermost scope (which will be the global object) is - stored in register dst. - */ - int dst = vPC[1].u.operand; - int property = vPC[2].u.operand; - bool isStrict = vPC[3].u.operand; - Identifier& ident = callFrame->codeBlock()->identifier(property); - - JSValue result = JSScope::resolveBase(callFrame, ident, isStrict); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - - vPC += OPCODE_LENGTH(op_resolve_base); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_ensure_property_exists) { - /* ensure_property_exists base(r) property(id) - - Throws an exception if property does not exist on base - */ - int base = vPC[1].u.operand; - int property = vPC[2].u.operand; - Identifier& ident = codeBlock->identifier(property); - - JSValue baseVal = callFrame->r(base).jsValue(); - JSObject* baseObject = asObject(baseVal); - PropertySlot slot(baseVal); - if (!baseObject->getPropertySlot(callFrame, ident, slot)) { - exceptionValue = createErrorForInvalidGlobalAssignment(callFrame, ident.string()); - goto vm_throw; - } - - vPC += OPCODE_LENGTH(op_ensure_property_exists); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_resolve_with_base) { - /* resolve_with_base baseDst(r) propDst(r) property(id) - - Searches the scope chain for an object containing - identifier property, and if one is found, writes it to - register srcDst, and the retrieved property value to register - propDst. If the property is not found, raises an exception. - - This is more efficient than doing resolve_base followed by - resolve, or resolve_base followed by get_by_id, as it - avoids duplicate hash lookups. - */ - int baseDst = vPC[1].u.operand; - int propDst = vPC[2].u.operand; - int property = vPC[3].u.operand; - Identifier& ident = codeBlock->identifier(property); - - JSValue prop = JSScope::resolveWithBase(callFrame, ident, &callFrame->uncheckedR(baseDst)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(propDst) = prop; - - vPC += OPCODE_LENGTH(op_resolve_with_base); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_resolve_with_this) { - /* resolve_with_this thisDst(r) propDst(r) property(id) - - Searches the scope chain for an object containing - identifier property, and if one is found, writes the - retrieved property value to register propDst, and the - this object to pass in a call to thisDst. - - If the property is not found, raises an exception. - */ - int thisDst = vPC[1].u.operand; - int propDst = vPC[2].u.operand; - int property = vPC[3].u.operand; - Identifier& ident = codeBlock->identifier(property); - - JSValue prop = JSScope::resolveWithThis(callFrame, ident, &callFrame->uncheckedR(thisDst)); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(propDst) = prop; - - vPC += OPCODE_LENGTH(op_resolve_with_this); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_get_by_id_out_of_line) - DEFINE_OPCODE(op_get_by_id) { - /* get_by_id dst(r) base(r) property(id) structure(sID) nop(n) nop(n) nop(n) - - Generic property access: Gets the property named by identifier - property from the value base, and puts the result in register dst. - */ - int dst = vPC[1].u.operand; - int base = vPC[2].u.operand; - int property = vPC[3].u.operand; - - Identifier& ident = codeBlock->identifier(property); - JSValue baseValue = callFrame->r(base).jsValue(); - PropertySlot slot(baseValue); - JSValue result = baseValue.get(callFrame, ident, slot); - CHECK_FOR_EXCEPTION(); - - tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot); - - callFrame->uncheckedR(dst) = result; - vPC += OPCODE_LENGTH(op_get_by_id); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_get_by_id_self) { - /* op_get_by_id_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n) - - Cached property access: Attempts to get a cached property from the - value base. If the cache misses, op_get_by_id_self reverts to - op_get_by_id. - */ - int base = vPC[2].u.operand; - JSValue baseValue = callFrame->r(base).jsValue(); - - if (LIKELY(baseValue.isCell())) { - JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure.get(); - - if (LIKELY(baseCell->structure() == structure)) { - ASSERT(baseCell->isObject()); - JSObject* baseObject = asObject(baseCell); - int dst = vPC[1].u.operand; - int offset = vPC[5].u.operand; - - ASSERT(baseObject->get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset)); - callFrame->uncheckedR(dst) = JSValue(baseObject->getDirectOffset(offset)); - - vPC += OPCODE_LENGTH(op_get_by_id_self); - NEXT_INSTRUCTION(); - } - } - - uncacheGetByID(codeBlock, vPC); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_get_by_id_proto) { - /* op_get_by_id_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n) - - Cached property access: Attempts to get a cached property from the - value base's prototype. If the cache misses, op_get_by_id_proto - reverts to op_get_by_id. - */ - int base = vPC[2].u.operand; - JSValue baseValue = callFrame->r(base).jsValue(); - - if (LIKELY(baseValue.isCell())) { - JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure.get(); - - if (LIKELY(baseCell->structure() == structure)) { - ASSERT(structure->prototypeForLookup(callFrame).isObject()); - JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame)); - Structure* prototypeStructure = vPC[5].u.structure.get(); - - if (LIKELY(protoObject->structure() == prototypeStructure)) { - int dst = vPC[1].u.operand; - int offset = vPC[6].u.operand; - - ASSERT(protoObject->get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset)); - ASSERT(baseValue.get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset)); - callFrame->uncheckedR(dst) = JSValue(protoObject->getDirectOffset(offset)); - - vPC += OPCODE_LENGTH(op_get_by_id_proto); - NEXT_INSTRUCTION(); - } - } - } - - uncacheGetByID(codeBlock, vPC); - NEXT_INSTRUCTION(); - } -#if USE(GCC_COMPUTED_GOTO_WORKAROUND) - goto *(&&skip_id_getter_proto); -#endif - DEFINE_OPCODE(op_get_by_id_getter_proto) { - /* op_get_by_id_getter_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n) - - Cached property access: Attempts to get a cached getter property from the - value base's prototype. If the cache misses, op_get_by_id_getter_proto - reverts to op_get_by_id. - */ - int base = vPC[2].u.operand; - JSValue baseValue = callFrame->r(base).jsValue(); - - if (LIKELY(baseValue.isCell())) { - JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure.get(); - - if (LIKELY(baseCell->structure() == structure)) { - ASSERT(structure->prototypeForLookup(callFrame).isObject()); - JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame)); - Structure* prototypeStructure = vPC[5].u.structure.get(); - - if (LIKELY(protoObject->structure() == prototypeStructure)) { - int dst = vPC[1].u.operand; - int offset = vPC[6].u.operand; - if (GetterSetter* getterSetter = asGetterSetter(protoObject->getDirectOffset(offset).asCell())) { - JSObject* getter = getterSetter->getter(); - CallData callData; - CallType callType = getter->methodTable()->getCallData(getter, callData); - JSValue result = call(callFrame, getter, callType, callData, asObject(baseCell), ArgList()); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } else - callFrame->uncheckedR(dst) = jsUndefined(); - vPC += OPCODE_LENGTH(op_get_by_id_getter_proto); - NEXT_INSTRUCTION(); - } - } - } - uncacheGetByID(codeBlock, vPC); - NEXT_INSTRUCTION(); - } -#if USE(GCC_COMPUTED_GOTO_WORKAROUND) - skip_id_getter_proto: -#endif -#if USE(GCC_COMPUTED_GOTO_WORKAROUND) - goto *(&&skip_id_custom_proto); -#endif - DEFINE_OPCODE(op_get_by_id_custom_proto) { - /* op_get_by_id_custom_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n) - - Cached property access: Attempts to use a cached named property getter - from the value base's prototype. If the cache misses, op_get_by_id_custom_proto - reverts to op_get_by_id. - */ - int base = vPC[2].u.operand; - JSValue baseValue = callFrame->r(base).jsValue(); - - if (LIKELY(baseValue.isCell())) { - JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure.get(); - - if (LIKELY(baseCell->structure() == structure)) { - ASSERT(structure->prototypeForLookup(callFrame).isObject()); - JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame)); - Structure* prototypeStructure = vPC[5].u.structure.get(); - - if (LIKELY(protoObject->structure() == prototypeStructure)) { - int dst = vPC[1].u.operand; - int property = vPC[3].u.operand; - Identifier& ident = codeBlock->identifier(property); - - PropertySlot::GetValueFunc getter = vPC[6].u.getterFunc; - JSValue result = getter(callFrame, protoObject, ident); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - vPC += OPCODE_LENGTH(op_get_by_id_custom_proto); - NEXT_INSTRUCTION(); - } - } - } - uncacheGetByID(codeBlock, vPC); - NEXT_INSTRUCTION(); - } -#if USE(GCC_COMPUTED_GOTO_WORKAROUND) - skip_id_custom_proto: -#endif -#if USE(GCC_COMPUTED_GOTO_WORKAROUND) - goto *(&&skip_get_by_id_chain); -#endif - DEFINE_OPCODE(op_get_by_id_chain) { - /* op_get_by_id_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n) - - Cached property access: Attempts to get a cached property from the - value base's prototype chain. If the cache misses, op_get_by_id_chain - reverts to op_get_by_id. - */ - int base = vPC[2].u.operand; - JSValue baseValue = callFrame->r(base).jsValue(); - - if (LIKELY(baseValue.isCell())) { - JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure.get(); - - if (LIKELY(baseCell->structure() == structure)) { - WriteBarrier<Structure>* it = vPC[5].u.structureChain->head(); - size_t count = vPC[6].u.operand; - WriteBarrier<Structure>* end = it + count; - - while (true) { - JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame)); - - if (UNLIKELY(baseObject->structure() != (*it).get())) - break; - - if (++it == end) { - int dst = vPC[1].u.operand; - int offset = vPC[7].u.operand; - - ASSERT(baseObject->get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset)); - ASSERT(baseValue.get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset)); - callFrame->uncheckedR(dst) = JSValue(baseObject->getDirectOffset(offset)); - - vPC += OPCODE_LENGTH(op_get_by_id_chain); - NEXT_INSTRUCTION(); - } - - // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype. - baseCell = baseObject; - } - } - } - - uncacheGetByID(codeBlock, vPC); - NEXT_INSTRUCTION(); - } -#if USE(GCC_COMPUTED_GOTO_WORKAROUND) - skip_get_by_id_chain: - goto *(&&skip_id_getter_self); -#endif - DEFINE_OPCODE(op_get_by_id_getter_self) { - /* op_get_by_id_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n) - - Cached property access: Attempts to get a cached property from the - value base. If the cache misses, op_get_by_id_getter_self reverts to - op_get_by_id. - */ - int base = vPC[2].u.operand; - JSValue baseValue = callFrame->r(base).jsValue(); - - if (LIKELY(baseValue.isCell())) { - JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure.get(); - - if (LIKELY(baseCell->structure() == structure)) { - ASSERT(baseCell->isObject()); - JSObject* baseObject = asObject(baseCell); - int dst = vPC[1].u.operand; - int offset = vPC[5].u.operand; - - if (GetterSetter* getterSetter = asGetterSetter(baseObject->getDirectOffset(offset).asCell())) { - JSObject* getter = getterSetter->getter(); - CallData callData; - CallType callType = getter->methodTable()->getCallData(getter, callData); - JSValue result = call(callFrame, getter, callType, callData, baseObject, ArgList()); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } else - callFrame->uncheckedR(dst) = jsUndefined(); - - vPC += OPCODE_LENGTH(op_get_by_id_getter_self); - NEXT_INSTRUCTION(); - } - } - uncacheGetByID(codeBlock, vPC); - NEXT_INSTRUCTION(); - } -#if USE(GCC_COMPUTED_GOTO_WORKAROUND) - skip_id_getter_self: -#endif -#if USE(GCC_COMPUTED_GOTO_WORKAROUND) - goto *(&&skip_id_custom_self); -#endif - DEFINE_OPCODE(op_get_by_id_custom_self) { - /* op_get_by_id_custom_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n) - - Cached property access: Attempts to use a cached named property getter - from the value base. If the cache misses, op_get_by_id_custom_self reverts to - op_get_by_id. - */ - int base = vPC[2].u.operand; - JSValue baseValue = callFrame->r(base).jsValue(); - - if (LIKELY(baseValue.isCell())) { - JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure.get(); - - if (LIKELY(baseCell->structure() == structure)) { - ASSERT(baseCell->isObject()); - int dst = vPC[1].u.operand; - int property = vPC[3].u.operand; - Identifier& ident = codeBlock->identifier(property); - - PropertySlot::GetValueFunc getter = vPC[5].u.getterFunc; - JSValue result = getter(callFrame, baseValue, ident); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - vPC += OPCODE_LENGTH(op_get_by_id_custom_self); - NEXT_INSTRUCTION(); - } - } - uncacheGetByID(codeBlock, vPC); - NEXT_INSTRUCTION(); - } -#if USE(GCC_COMPUTED_GOTO_WORKAROUND) -skip_id_custom_self: -#endif - DEFINE_OPCODE(op_get_by_id_generic) { - /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n) - - Generic property access: Gets the property named by identifier - property from the value base, and puts the result in register dst. - */ - int dst = vPC[1].u.operand; - int base = vPC[2].u.operand; - int property = vPC[3].u.operand; - - Identifier& ident = codeBlock->identifier(property); - JSValue baseValue = callFrame->r(base).jsValue(); - PropertySlot slot(baseValue); - JSValue result = baseValue.get(callFrame, ident, slot); - CHECK_FOR_EXCEPTION(); - - callFrame->uncheckedR(dst) = result; - vPC += OPCODE_LENGTH(op_get_by_id_generic); - NEXT_INSTRUCTION(); - } -#if USE(GCC_COMPUTED_GOTO_WORKAROUND) - goto *(&&skip_id_getter_chain); -#endif - DEFINE_OPCODE(op_get_by_id_getter_chain) { - /* op_get_by_id_getter_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n) - - Cached property access: Attempts to get a cached property from the - value base's prototype chain. If the cache misses, op_get_by_id_getter_chain - reverts to op_get_by_id. - */ - int base = vPC[2].u.operand; - JSValue baseValue = callFrame->r(base).jsValue(); - - if (LIKELY(baseValue.isCell())) { - JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure.get(); - - if (LIKELY(baseCell->structure() == structure)) { - WriteBarrier<Structure>* it = vPC[5].u.structureChain->head(); - size_t count = vPC[6].u.operand; - WriteBarrier<Structure>* end = it + count; - - while (true) { - JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame)); - - if (UNLIKELY(baseObject->structure() != (*it).get())) - break; - - if (++it == end) { - int dst = vPC[1].u.operand; - int offset = vPC[7].u.operand; - if (GetterSetter* getterSetter = asGetterSetter(baseObject->getDirectOffset(offset).asCell())) { - JSObject* getter = getterSetter->getter(); - CallData callData; - CallType callType = getter->methodTable()->getCallData(getter, callData); - JSValue result = call(callFrame, getter, callType, callData, baseValue, ArgList()); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } else - callFrame->uncheckedR(dst) = jsUndefined(); - vPC += OPCODE_LENGTH(op_get_by_id_getter_chain); - NEXT_INSTRUCTION(); - } - - // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype. - baseCell = baseObject; - } - } - } - uncacheGetByID(codeBlock, vPC); - NEXT_INSTRUCTION(); - } -#if USE(GCC_COMPUTED_GOTO_WORKAROUND) - skip_id_getter_chain: -#endif -#if USE(GCC_COMPUTED_GOTO_WORKAROUND) - goto *(&&skip_id_custom_chain); -#endif - DEFINE_OPCODE(op_get_by_id_custom_chain) { - /* op_get_by_id_custom_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n) - - Cached property access: Attempts to use a cached named property getter on the - value base's prototype chain. If the cache misses, op_get_by_id_custom_chain - reverts to op_get_by_id. - */ - int base = vPC[2].u.operand; - JSValue baseValue = callFrame->r(base).jsValue(); - - if (LIKELY(baseValue.isCell())) { - JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure.get(); - - if (LIKELY(baseCell->structure() == structure)) { - WriteBarrier<Structure>* it = vPC[5].u.structureChain->head(); - size_t count = vPC[6].u.operand; - WriteBarrier<Structure>* end = it + count; - - while (true) { - JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame)); - - if (UNLIKELY(baseObject->structure() != (*it).get())) - break; - - if (++it == end) { - int dst = vPC[1].u.operand; - int property = vPC[3].u.operand; - Identifier& ident = codeBlock->identifier(property); - - PropertySlot::GetValueFunc getter = vPC[7].u.getterFunc; - JSValue result = getter(callFrame, baseObject, ident); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - vPC += OPCODE_LENGTH(op_get_by_id_custom_chain); - NEXT_INSTRUCTION(); - } - - // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype. - baseCell = baseObject; - } - } - } - uncacheGetByID(codeBlock, vPC); - NEXT_INSTRUCTION(); - } -#if USE(GCC_COMPUTED_GOTO_WORKAROUND) - skip_id_custom_chain: - goto *(&&skip_get_array_length); -#endif - DEFINE_OPCODE(op_get_array_length) { - /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n) - - Cached property access: Gets the length of the array in register base, - and puts the result in register dst. If register base does not hold - an array, op_get_array_length reverts to op_get_by_id. - */ - - int base = vPC[2].u.operand; - JSValue baseValue = callFrame->r(base).jsValue(); - if (LIKELY(isJSArray(baseValue))) { - int dst = vPC[1].u.operand; - callFrame->uncheckedR(dst) = jsNumber(asArray(baseValue)->length()); - vPC += OPCODE_LENGTH(op_get_array_length); - NEXT_INSTRUCTION(); - } - - uncacheGetByID(codeBlock, vPC); - NEXT_INSTRUCTION(); - } -#if USE(GCC_COMPUTED_GOTO_WORKAROUND) - skip_get_array_length: - goto *(&&skip_get_string_length); -#endif - DEFINE_OPCODE(op_get_string_length) { - /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n) - - Cached property access: Gets the length of the string in register base, - and puts the result in register dst. If register base does not hold - a string, op_get_string_length reverts to op_get_by_id. - */ - - int base = vPC[2].u.operand; - JSValue baseValue = callFrame->r(base).jsValue(); - if (LIKELY(isJSString(baseValue))) { - int dst = vPC[1].u.operand; - callFrame->uncheckedR(dst) = jsNumber(asString(baseValue)->length()); - vPC += OPCODE_LENGTH(op_get_string_length); - NEXT_INSTRUCTION(); - } - - uncacheGetByID(codeBlock, vPC); - NEXT_INSTRUCTION(); - } -#if USE(GCC_COMPUTED_GOTO_WORKAROUND) - skip_get_string_length: - goto *(&&skip_put_by_id); -#endif - DEFINE_OPCODE(op_put_by_id_out_of_line) - DEFINE_OPCODE(op_put_by_id) { - /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) direct(b) - - Generic property access: Sets the property named by identifier - property, belonging to register base, to register value. - - Unlike many opcodes, this one does not write any output to - the register file. - - The "direct" flag should only be set this put_by_id is to initialize - an object literal. - */ - - int base = vPC[1].u.operand; - int property = vPC[2].u.operand; - int value = vPC[3].u.operand; - int direct = vPC[8].u.operand; - - JSValue baseValue = callFrame->r(base).jsValue(); - Identifier& ident = codeBlock->identifier(property); - PutPropertySlot slot(codeBlock->isStrictMode()); - if (direct) { - ASSERT(baseValue.isObject()); - asObject(baseValue)->putDirect(*globalData, ident, callFrame->r(value).jsValue(), slot); - } else - baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot); - CHECK_FOR_EXCEPTION(); - - tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot); - - vPC += OPCODE_LENGTH(op_put_by_id); - NEXT_INSTRUCTION(); - } -#if USE(GCC_COMPUTED_GOTO_WORKAROUND) - skip_put_by_id: -#endif - DEFINE_OPCODE(op_put_by_id_transition_direct) - DEFINE_OPCODE(op_put_by_id_transition_normal) - DEFINE_OPCODE(op_put_by_id_transition_direct_out_of_line) - DEFINE_OPCODE(op_put_by_id_transition_normal_out_of_line) - DEFINE_OPCODE(op_put_by_id_transition) { - /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n) direct(b) - - Cached property access: Attempts to set a new property with a cached transition - property named by identifier property, belonging to register base, - to register value. If the cache misses, op_put_by_id_transition - reverts to op_put_by_id_generic. - - Unlike many opcodes, this one does not write any output to - the register file. - */ - int base = vPC[1].u.operand; - JSValue baseValue = callFrame->r(base).jsValue(); - - if (LIKELY(baseValue.isCell())) { - JSCell* baseCell = baseValue.asCell(); - Structure* oldStructure = vPC[4].u.structure.get(); - Structure* newStructure = vPC[5].u.structure.get(); - - if (LIKELY(baseCell->structure() == oldStructure)) { - ASSERT(baseCell->isObject()); - JSObject* baseObject = asObject(baseCell); - int direct = vPC[8].u.operand; - - if (!direct) { - WriteBarrier<Structure>* it = vPC[6].u.structureChain->head(); - - JSValue proto = baseObject->structure()->prototypeForLookup(callFrame); - while (!proto.isNull()) { - if (UNLIKELY(asObject(proto)->structure() != (*it).get())) { - uncachePutByID(codeBlock, vPC); - NEXT_INSTRUCTION(); - } - ++it; - proto = asObject(proto)->structure()->prototypeForLookup(callFrame); - } - } - baseObject->setStructureAndReallocateStorageIfNecessary(*globalData, newStructure); - - int value = vPC[3].u.operand; - int offset = vPC[7].u.operand; - ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(*globalData, codeBlock->identifier(vPC[2].u.operand))) == offset); - baseObject->putDirectOffset(callFrame->globalData(), offset, callFrame->r(value).jsValue()); - - vPC += OPCODE_LENGTH(op_put_by_id_transition); - NEXT_INSTRUCTION(); - } - } - - uncachePutByID(codeBlock, vPC); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_put_by_id_replace) { - /* op_put_by_id_replace base(r) property(id) value(r) structure(sID) offset(n) nop(n) nop(n) direct(b) - - Cached property access: Attempts to set a pre-existing, cached - property named by identifier property, belonging to register base, - to register value. If the cache misses, op_put_by_id_replace - reverts to op_put_by_id. - - Unlike many opcodes, this one does not write any output to - the register file. - */ - int base = vPC[1].u.operand; - JSValue baseValue = callFrame->r(base).jsValue(); - - if (LIKELY(baseValue.isCell())) { - JSCell* baseCell = baseValue.asCell(); - Structure* structure = vPC[4].u.structure.get(); - - if (LIKELY(baseCell->structure() == structure)) { - ASSERT(baseCell->isObject()); - JSObject* baseObject = asObject(baseCell); - int value = vPC[3].u.operand; - int offset = vPC[5].u.operand; - - ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(*globalData, codeBlock->identifier(vPC[2].u.operand))) == offset); - baseObject->putDirectOffset(callFrame->globalData(), offset, callFrame->r(value).jsValue()); - - vPC += OPCODE_LENGTH(op_put_by_id_replace); - NEXT_INSTRUCTION(); - } - } - - uncachePutByID(codeBlock, vPC); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_put_by_id_generic) { - /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) direct(b) - - Generic property access: Sets the property named by identifier - property, belonging to register base, to register value. - - Unlike many opcodes, this one does not write any output to - the register file. - */ - int base = vPC[1].u.operand; - int property = vPC[2].u.operand; - int value = vPC[3].u.operand; - int direct = vPC[8].u.operand; - - JSValue baseValue = callFrame->r(base).jsValue(); - Identifier& ident = codeBlock->identifier(property); - PutPropertySlot slot(codeBlock->isStrictMode()); - if (direct) { - ASSERT(baseValue.isObject()); - asObject(baseValue)->putDirect(*globalData, ident, callFrame->r(value).jsValue(), slot); - } else - baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot); - CHECK_FOR_EXCEPTION(); - - vPC += OPCODE_LENGTH(op_put_by_id_generic); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_del_by_id) { - /* del_by_id dst(r) base(r) property(id) - - Converts register base to Object, deletes the property - named by identifier property from the object, and writes a - boolean indicating success (if true) or failure (if false) - to register dst. - */ - int dst = vPC[1].u.operand; - int base = vPC[2].u.operand; - int property = vPC[3].u.operand; - - JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame); - Identifier& ident = codeBlock->identifier(property); - bool result = baseObj->methodTable()->deleteProperty(baseObj, callFrame, ident); - if (!result && codeBlock->isStrictMode()) { - exceptionValue = createTypeError(callFrame, "Unable to delete property."); - goto vm_throw; - } - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = jsBoolean(result); - vPC += OPCODE_LENGTH(op_del_by_id); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_get_by_pname) { - int dst = vPC[1].u.operand; - int base = vPC[2].u.operand; - int property = vPC[3].u.operand; - int expected = vPC[4].u.operand; - int iter = vPC[5].u.operand; - int i = vPC[6].u.operand; - - JSValue baseValue = callFrame->r(base).jsValue(); - JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator(); - JSValue subscript = callFrame->r(property).jsValue(); - JSValue expectedSubscript = callFrame->r(expected).jsValue(); - int index = callFrame->r(i).i() - 1; - JSValue result; - PropertyOffset offset = 0; - if (subscript == expectedSubscript && baseValue.isCell() && (baseValue.asCell()->structure() == it->cachedStructure()) && it->getOffset(index, offset)) { - callFrame->uncheckedR(dst) = JSValue(asObject(baseValue)->getDirectOffset(offset)); - vPC += OPCODE_LENGTH(op_get_by_pname); - NEXT_INSTRUCTION(); - } - { - Identifier propertyName(callFrame, subscript.toString(callFrame)->value(callFrame)); - result = baseValue.get(callFrame, propertyName); - } - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - vPC += OPCODE_LENGTH(op_get_by_pname); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_get_arguments_length) { - int dst = vPC[1].u.operand; - int argumentsRegister = vPC[2].u.operand; - int property = vPC[3].u.operand; - JSValue arguments = callFrame->r(argumentsRegister).jsValue(); - if (arguments) { - Identifier& ident = codeBlock->identifier(property); - PropertySlot slot(arguments); - JSValue result = arguments.get(callFrame, ident, slot); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - } else - callFrame->uncheckedR(dst) = jsNumber(callFrame->argumentCount()); - - vPC += OPCODE_LENGTH(op_get_arguments_length); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_get_argument_by_val) { - int dst = vPC[1].u.operand; - int argumentsRegister = vPC[2].u.operand; - int property = vPC[3].u.operand; - JSValue arguments = callFrame->r(argumentsRegister).jsValue(); - JSValue subscript = callFrame->r(property).jsValue(); - if (!arguments && subscript.isUInt32() && subscript.asUInt32() < callFrame->argumentCount()) { - callFrame->uncheckedR(dst) = callFrame->argument(subscript.asUInt32()); - vPC += OPCODE_LENGTH(op_get_argument_by_val); - NEXT_INSTRUCTION(); - } - if (!arguments) { - Arguments* arguments = Arguments::create(*globalData, callFrame); - callFrame->uncheckedR(argumentsRegister) = JSValue(arguments); - callFrame->uncheckedR(unmodifiedArgumentsRegister(argumentsRegister)) = JSValue(arguments); - } - // fallthrough - } - DEFINE_OPCODE(op_get_by_val) { - /* get_by_val dst(r) base(r) property(r) - - Converts register base to Object, gets the property named - by register property from the object, and puts the result - in register dst. property is nominally converted to string - but numbers are treated more efficiently. - */ - int dst = vPC[1].u.operand; - int base = vPC[2].u.operand; - int property = vPC[3].u.operand; - - JSValue baseValue = callFrame->r(base).jsValue(); - JSValue subscript = callFrame->r(property).jsValue(); - - JSValue result; - - if (LIKELY(subscript.isUInt32())) { - uint32_t i = subscript.asUInt32(); - if (isJSArray(baseValue)) { - JSArray* jsArray = asArray(baseValue); - if (jsArray->canGetIndexQuickly(i)) - result = jsArray->getIndexQuickly(i); - else - result = jsArray->JSArray::get(callFrame, i); - } else if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) - result = asString(baseValue)->getIndex(callFrame, i); - else - result = baseValue.get(callFrame, i); - } else if (isName(subscript)) - result = baseValue.get(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName()); - else { - Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); - result = baseValue.get(callFrame, property); - } - - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = result; - vPC += OPCODE_LENGTH(op_get_by_val); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_put_by_val) { - /* put_by_val base(r) property(r) value(r) - - Sets register value on register base as the property named - by register property. Base is converted to object - first. register property is nominally converted to string - but numbers are treated more efficiently. - - Unlike many opcodes, this one does not write any output to - the register file. - */ - int base = vPC[1].u.operand; - int property = vPC[2].u.operand; - int value = vPC[3].u.operand; - - JSValue baseValue = callFrame->r(base).jsValue(); - JSValue subscript = callFrame->r(property).jsValue(); - - if (LIKELY(subscript.isUInt32())) { - uint32_t i = subscript.asUInt32(); - if (isJSArray(baseValue)) { - JSArray* jsArray = asArray(baseValue); - if (jsArray->canSetIndexQuickly(i)) - jsArray->setIndexQuickly(*globalData, i, callFrame->r(value).jsValue()); - else - jsArray->JSArray::putByIndex(jsArray, callFrame, i, callFrame->r(value).jsValue(), codeBlock->isStrictMode()); - } else - baseValue.putByIndex(callFrame, i, callFrame->r(value).jsValue(), codeBlock->isStrictMode()); - } else if (isName(subscript)) { - PutPropertySlot slot(codeBlock->isStrictMode()); - baseValue.put(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName(), callFrame->r(value).jsValue(), slot); - } else { - Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); - if (!globalData->exception) { // Don't put to an object if toString threw an exception. - PutPropertySlot slot(codeBlock->isStrictMode()); - baseValue.put(callFrame, property, callFrame->r(value).jsValue(), slot); - } - } - - CHECK_FOR_EXCEPTION(); - vPC += OPCODE_LENGTH(op_put_by_val); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_del_by_val) { - /* del_by_val dst(r) base(r) property(r) - - Converts register base to Object, deletes the property - named by register property from the object, and writes a - boolean indicating success (if true) or failure (if false) - to register dst. - */ - int dst = vPC[1].u.operand; - int base = vPC[2].u.operand; - int property = vPC[3].u.operand; - - JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame); // may throw - - JSValue subscript = callFrame->r(property).jsValue(); - bool result; - uint32_t i; - if (subscript.getUInt32(i)) - result = baseObj->methodTable()->deletePropertyByIndex(baseObj, callFrame, i); - else if (isName(subscript)) - result = baseObj->methodTable()->deleteProperty(baseObj, callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName()); - else { - CHECK_FOR_EXCEPTION(); - Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); - CHECK_FOR_EXCEPTION(); - result = baseObj->methodTable()->deleteProperty(baseObj, callFrame, property); - } - if (!result && codeBlock->isStrictMode()) { - exceptionValue = createTypeError(callFrame, "Unable to delete property."); - goto vm_throw; - } - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(dst) = jsBoolean(result); - vPC += OPCODE_LENGTH(op_del_by_val); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_put_by_index) { - /* put_by_index base(r) property(n) value(r) - - Sets register value on register base as the property named - by the immediate number property. Base is converted to - object first. - - Unlike many opcodes, this one does not write any output to - the register file. - - This opcode is mainly used to initialize array literals. - */ - int base = vPC[1].u.operand; - unsigned property = vPC[2].u.operand; - int value = vPC[3].u.operand; - - JSValue arrayValue = callFrame->r(base).jsValue(); - ASSERT(isJSArray(arrayValue)); - asArray(arrayValue)->putDirectIndex(callFrame, property, callFrame->r(value).jsValue()); - - vPC += OPCODE_LENGTH(op_put_by_index); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_loop) { - /* loop target(offset) - - Jumps unconditionally to offset target from the current - instruction. - - Additionally this loop instruction may terminate JS execution is - the JS timeout is reached. - */ -#if ENABLE(OPCODE_STATS) - OpcodeStats::resetLastInstruction(); -#endif - int target = vPC[1].u.operand; - CHECK_FOR_TIMEOUT(); - vPC += target; - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_jmp) { - /* jmp target(offset) - - Jumps unconditionally to offset target from the current - instruction. - */ -#if ENABLE(OPCODE_STATS) - OpcodeStats::resetLastInstruction(); -#endif - int target = vPC[1].u.operand; - - vPC += target; - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_loop_hint) { - // This is a no-op unless we intend on doing OSR from the interpreter. - vPC += OPCODE_LENGTH(op_loop_hint); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_loop_if_true) { - /* loop_if_true cond(r) target(offset) - - Jumps to offset target from the current instruction, if and - only if register cond converts to boolean as true. - - Additionally this loop instruction may terminate JS execution is - the JS timeout is reached. - */ - int cond = vPC[1].u.operand; - int target = vPC[2].u.operand; - if (callFrame->r(cond).jsValue().toBoolean(callFrame)) { - vPC += target; - CHECK_FOR_TIMEOUT(); - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_loop_if_true); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_loop_if_false) { - /* loop_if_true cond(r) target(offset) - - Jumps to offset target from the current instruction, if and - only if register cond converts to boolean as false. - - Additionally this loop instruction may terminate JS execution is - the JS timeout is reached. - */ - int cond = vPC[1].u.operand; - int target = vPC[2].u.operand; - if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) { - vPC += target; - CHECK_FOR_TIMEOUT(); - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_loop_if_true); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_jtrue) { - /* jtrue cond(r) target(offset) - - Jumps to offset target from the current instruction, if and - only if register cond converts to boolean as true. - */ - int cond = vPC[1].u.operand; - int target = vPC[2].u.operand; - if (callFrame->r(cond).jsValue().toBoolean(callFrame)) { - vPC += target; - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_jtrue); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_jfalse) { - /* jfalse cond(r) target(offset) - - Jumps to offset target from the current instruction, if and - only if register cond converts to boolean as false. - */ - int cond = vPC[1].u.operand; - int target = vPC[2].u.operand; - if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) { - vPC += target; - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_jfalse); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_jeq_null) { - /* jeq_null src(r) target(offset) - - Jumps to offset target from the current instruction, if and - only if register src is null. - */ - int src = vPC[1].u.operand; - int target = vPC[2].u.operand; - JSValue srcValue = callFrame->r(src).jsValue(); - - if (srcValue.isUndefinedOrNull() || (srcValue.isCell() && srcValue.asCell()->structure()->masqueradesAsUndefined(callFrame->lexicalGlobalObject()))) { - vPC += target; - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_jeq_null); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_jneq_null) { - /* jneq_null src(r) target(offset) - - Jumps to offset target from the current instruction, if and - only if register src is not null. - */ - int src = vPC[1].u.operand; - int target = vPC[2].u.operand; - JSValue srcValue = callFrame->r(src).jsValue(); - - if (!srcValue.isUndefinedOrNull() && (!srcValue.isCell() || !(srcValue.asCell()->structure()->masqueradesAsUndefined(callFrame->lexicalGlobalObject())))) { - vPC += target; - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_jneq_null); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_jneq_ptr) { - /* jneq_ptr src(r) ptr(jsCell) target(offset) - - Jumps to offset target from the current instruction, if the value r is equal - to ptr, using pointer equality. - */ - int src = vPC[1].u.operand; - int target = vPC[3].u.operand; - JSValue srcValue = callFrame->r(src).jsValue(); - if (srcValue != vPC[2].u.jsCell.get()) { - vPC += target; - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_jneq_ptr); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_loop_if_less) { - /* loop_if_less src1(r) src2(r) target(offset) - - Checks whether register src1 is less than 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. - - Additionally this loop instruction may terminate JS execution is - the JS timeout is reached. - */ - 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 = jsLess<true>(callFrame, src1, src2); - CHECK_FOR_EXCEPTION(); - - if (result) { - vPC += target; - CHECK_FOR_TIMEOUT(); - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_loop_if_less); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_loop_if_lesseq) { - /* loop_if_lesseq 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. - - Additionally this loop instruction may terminate JS execution is - the JS timeout is reached. - */ - 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<true>(callFrame, src1, src2); - CHECK_FOR_EXCEPTION(); - - if (result) { - vPC += target; - CHECK_FOR_TIMEOUT(); - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_loop_if_lesseq); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_loop_if_greater) { - /* loop_if_greater src1(r) src2(r) target(offset) - - Checks whether register src1 is greater than 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. - - Additionally this loop instruction may terminate JS execution is - the JS timeout is reached. - */ - 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 = jsLess<false>(callFrame, src2, src1); - CHECK_FOR_EXCEPTION(); - - if (result) { - vPC += target; - CHECK_FOR_TIMEOUT(); - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_loop_if_greater); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_loop_if_greatereq) { - /* loop_if_greatereq src1(r) src2(r) target(offset) - - Checks whether register src1 is greater 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. - - Additionally this loop instruction may terminate JS execution is - the JS timeout is reached. - */ - 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<false>(callFrame, src2, src1); - CHECK_FOR_EXCEPTION(); - - if (result) { - vPC += target; - CHECK_FOR_TIMEOUT(); - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_loop_if_greatereq); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_jless) { - /* jless src1(r) src2(r) target(offset) - - Checks whether register src1 is less than 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 = jsLess<true>(callFrame, src1, src2); - CHECK_FOR_EXCEPTION(); - - if (result) { - vPC += target; - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_jless); - 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<true>(callFrame, src1, src2); - CHECK_FOR_EXCEPTION(); - - if (result) { - vPC += target; - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_jlesseq); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_jgreater) { - /* jgreater src1(r) src2(r) target(offset) - - Checks whether register src1 is greater than 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 = jsLess<false>(callFrame, src2, src1); - CHECK_FOR_EXCEPTION(); - - if (result) { - vPC += target; - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_jgreater); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_jgreatereq) { - /* jgreatereq src1(r) src2(r) target(offset) - - Checks whether register src1 is greater 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<false>(callFrame, src2, src1); - CHECK_FOR_EXCEPTION(); - - if (result) { - vPC += target; - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_jgreatereq); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_jnless) { - /* jnless src1(r) src2(r) target(offset) - - Checks whether register src1 is less than 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 false. - */ - 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 = jsLess<true>(callFrame, src1, src2); - CHECK_FOR_EXCEPTION(); - - if (!result) { - vPC += target; - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_jnless); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_jnlesseq) { - /* jnlesseq 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 theresult of the comparison is false. - */ - 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<true>(callFrame, src1, src2); - CHECK_FOR_EXCEPTION(); - - if (!result) { - vPC += target; - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_jnlesseq); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_jngreater) { - /* jngreater src1(r) src2(r) target(offset) - - Checks whether register src1 is greater than 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 false. - */ - 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 = jsLess<false>(callFrame, src2, src1); - CHECK_FOR_EXCEPTION(); - - if (!result) { - vPC += target; - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_jngreater); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_jngreatereq) { - /* jngreatereq src1(r) src2(r) target(offset) - - Checks whether register src1 is greater 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 theresult of the comparison is false. - */ - 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<false>(callFrame, src2, src1); - CHECK_FOR_EXCEPTION(); - - if (!result) { - vPC += target; - NEXT_INSTRUCTION(); - } - - vPC += OPCODE_LENGTH(op_jngreatereq); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_switch_imm) { - /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r) - - Performs a range checked switch on the scrutinee value, using - the tableIndex-th immediate switch jump table. If the scrutinee value - is an immediate number in the range covered by the referenced jump - table, and the value at jumpTable[scrutinee value] is non-zero, then - that value is used as the jump offset, otherwise defaultOffset is used. - */ - int tableIndex = vPC[1].u.operand; - int defaultOffset = vPC[2].u.operand; - JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue(); - if (scrutinee.isInt32()) - vPC += codeBlock->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.asInt32(), defaultOffset); - else if (scrutinee.isDouble() && scrutinee.asDouble() == static_cast<int32_t>(scrutinee.asDouble())) - vPC += codeBlock->immediateSwitchJumpTable(tableIndex).offsetForValue(static_cast<int32_t>(scrutinee.asDouble()), defaultOffset); - else - vPC += defaultOffset; - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_switch_char) { - /* switch_char tableIndex(n) defaultOffset(offset) scrutinee(r) - - Performs a range checked switch on the scrutinee value, using - the tableIndex-th character switch jump table. If the scrutinee value - is a single character string in the range covered by the referenced jump - table, and the value at jumpTable[scrutinee value] is non-zero, then - that value is used as the jump offset, otherwise defaultOffset is used. - */ - int tableIndex = vPC[1].u.operand; - int defaultOffset = vPC[2].u.operand; - JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue(); - if (!scrutinee.isString()) - vPC += defaultOffset; - else { - StringImpl* value = asString(scrutinee)->value(callFrame).impl(); - if (value->length() != 1) - vPC += defaultOffset; - else - vPC += codeBlock->characterSwitchJumpTable(tableIndex).offsetForValue((*value)[0], defaultOffset); - } - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_switch_string) { - /* switch_string tableIndex(n) defaultOffset(offset) scrutinee(r) - - Performs a sparse hashmap based switch on the value in the scrutinee - register, using the tableIndex-th string switch jump table. If the - scrutinee value is a string that exists as a key in the referenced - jump table, then the value associated with the string is used as the - jump offset, otherwise defaultOffset is used. - */ - int tableIndex = vPC[1].u.operand; - int defaultOffset = vPC[2].u.operand; - JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue(); - if (!scrutinee.isString()) - vPC += defaultOffset; - else - vPC += codeBlock->stringSwitchJumpTable(tableIndex).offsetForValue(asString(scrutinee)->value(callFrame).impl(), defaultOffset); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_new_func) { - /* new_func dst(r) func(f) - - Constructs a new Function instance from function func and - the current scope chain using the original Function - constructor, using the rules for function declarations, and - puts the result in register dst. - */ - int dst = vPC[1].u.operand; - int func = vPC[2].u.operand; - int shouldCheck = vPC[3].u.operand; - ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue()); - if (!shouldCheck || !callFrame->r(dst).jsValue()) - callFrame->uncheckedR(dst) = JSValue(JSFunction::create(callFrame, codeBlock->functionDecl(func), callFrame->scope())); - - vPC += OPCODE_LENGTH(op_new_func); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_new_func_exp) { - /* new_func_exp dst(r) func(f) - - Constructs a new Function instance from function func and - the current scope chain using the original Function - constructor, using the rules for function expressions, and - puts the result in register dst. - */ - int dst = vPC[1].u.operand; - int funcIndex = vPC[2].u.operand; - - ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue()); - FunctionExecutable* function = codeBlock->functionExpr(funcIndex); - JSFunction* func = JSFunction::create(callFrame, function, callFrame->scope()); - - callFrame->uncheckedR(dst) = JSValue(func); - - vPC += OPCODE_LENGTH(op_new_func_exp); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_call_eval) { - /* call_eval func(r) argCount(n) registerOffset(n) - - Call a function named "eval" with no explicit "this" value - (which may therefore be the eval operator). If register - thisVal is the global object, and register func contains - that global object's original global eval function, then - perform the eval operator in local scope (interpreting - the argument registers as for the "call" - opcode). Otherwise, act exactly as the "call" opcode would. - */ - - int func = vPC[1].u.operand; - int argCount = vPC[2].u.operand; - int registerOffset = vPC[3].u.operand; - - ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue()); - JSValue funcVal = callFrame->r(func).jsValue(); - - if (isHostFunction(funcVal, globalFuncEval)) { - CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); - newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call_eval), callFrame->scope(), callFrame, argCount, jsCast<JSFunction*>(funcVal)); - - JSValue result = eval(newCallFrame); - if ((exceptionValue = globalData->exception)) - goto vm_throw; - functionReturnValue = result; - - vPC += OPCODE_LENGTH(op_call_eval); - NEXT_INSTRUCTION(); - } - - // We didn't find the blessed version of eval, so process this - // instruction as a normal function call. - // fall through to op_call - } - DEFINE_OPCODE(op_call) { - /* call func(r) argCount(n) registerOffset(n) - - Perform a function call. - - registerOffset is the distance the callFrame pointer should move - before the VM initializes the new call frame's header. - - dst is where op_ret should store its result. - */ - - int func = vPC[1].u.operand; - int argCount = vPC[2].u.operand; - int registerOffset = vPC[3].u.operand; - - JSValue v = callFrame->r(func).jsValue(); - - CallData callData; - CallType callType = getCallData(v, callData); - - if (callType == CallTypeJS) { - JSScope* callDataScope = callData.js.scope; - - JSObject* error = callData.js.functionExecutable->compileForCall(callFrame, callDataScope); - if (UNLIKELY(!!error)) { - exceptionValue = error; - goto vm_throw; - } - - CallFrame* previousCallFrame = callFrame; - CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall(); - callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount); - if (UNLIKELY(!callFrame)) { - callFrame = previousCallFrame; - exceptionValue = createStackOverflowError(callFrame); - goto vm_throw; - } - - callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call), callDataScope, previousCallFrame, argCount, jsCast<JSFunction*>(v)); - codeBlock = newCodeBlock; - ASSERT(codeBlock == callFrame->codeBlock()); - *topCallFrameSlot = callFrame; - vPC = newCodeBlock->instructions().begin(); - -#if ENABLE(OPCODE_STATS) - OpcodeStats::resetLastInstruction(); -#endif - - NEXT_INSTRUCTION(); - } - - if (callType == CallTypeHost) { - JSScope* scope = callFrame->scope(); - CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); - newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call), scope, callFrame, argCount, asObject(v)); - JSValue returnValue; - { - *topCallFrameSlot = newCallFrame; - SamplingTool::HostCallRecord callRecord(m_sampler.get()); - returnValue = JSValue::decode(callData.native.function(newCallFrame)); - *topCallFrameSlot = callFrame; - } - CHECK_FOR_EXCEPTION(); - - functionReturnValue = returnValue; - - vPC += OPCODE_LENGTH(op_call); - NEXT_INSTRUCTION(); - } - - ASSERT(callType == CallTypeNone); - - exceptionValue = createNotAFunctionError(callFrame, v); - goto vm_throw; - } - DEFINE_OPCODE(op_call_varargs) { - /* call_varargs callee(r) thisValue(r) arguments(r) firstFreeRegister(n) - - Perform a function call with a dynamic set of arguments. - - registerOffset is the distance the callFrame pointer should move - before the VM initializes the new call frame's header, excluding - space for arguments. - - dst is where op_ret should store its result. - */ - - JSValue v = callFrame->r(vPC[1].u.operand).jsValue(); - JSValue thisValue = callFrame->r(vPC[2].u.operand).jsValue(); - JSValue arguments = callFrame->r(vPC[3].u.operand).jsValue(); - int firstFreeRegister = vPC[4].u.operand; - - CallFrame* newCallFrame = loadVarargs(callFrame, registerFile, thisValue, arguments, firstFreeRegister); - if ((exceptionValue = globalData->exception)) - goto vm_throw; - int argCount = newCallFrame->argumentCountIncludingThis(); - - CallData callData; - CallType callType = getCallData(v, callData); - - if (callType == CallTypeJS) { - JSScope* callDataScope = callData.js.scope; - - JSObject* error = callData.js.functionExecutable->compileForCall(callFrame, callDataScope); - if (UNLIKELY(!!error)) { - exceptionValue = error; - goto vm_throw; - } - - CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall(); - newCallFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, newCallFrame, 0, argCount); - if (UNLIKELY(!newCallFrame)) { - exceptionValue = createStackOverflowError(callFrame); - goto vm_throw; - } - - newCallFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call_varargs), callDataScope, callFrame, argCount, jsCast<JSFunction*>(v)); - codeBlock = newCodeBlock; - callFrame = newCallFrame; - ASSERT(codeBlock == callFrame->codeBlock()); - *topCallFrameSlot = callFrame; - vPC = newCodeBlock->instructions().begin(); - -#if ENABLE(OPCODE_STATS) - OpcodeStats::resetLastInstruction(); -#endif - - NEXT_INSTRUCTION(); - } - - if (callType == CallTypeHost) { - JSScope* scope = callFrame->scope(); - newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call_varargs), scope, callFrame, argCount, asObject(v)); - - JSValue returnValue; - { - *topCallFrameSlot = newCallFrame; - SamplingTool::HostCallRecord callRecord(m_sampler.get()); - returnValue = JSValue::decode(callData.native.function(newCallFrame)); - *topCallFrameSlot = callFrame; - } - CHECK_FOR_EXCEPTION(); - - functionReturnValue = returnValue; - - vPC += OPCODE_LENGTH(op_call_varargs); - NEXT_INSTRUCTION(); - } - - ASSERT(callType == CallTypeNone); - - exceptionValue = createNotAFunctionError(callFrame, v); - goto vm_throw; - } - DEFINE_OPCODE(op_tear_off_activation) { - /* tear_off_activation activation(r) - - Copy locals and named parameters from the register file to the heap. - Point the bindings in 'activation' to this new backing store. - - This opcode appears before op_ret in functions that require full scope chains. - */ - - int activation = vPC[1].u.operand; - ASSERT(codeBlock->needsFullScopeChain()); - JSValue activationValue = callFrame->r(activation).jsValue(); - if (activationValue) - asActivation(activationValue)->tearOff(*globalData); - - vPC += OPCODE_LENGTH(op_tear_off_activation); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_tear_off_arguments) { - /* tear_off_arguments arguments(r) activation(r) - - Copy named parameters from the register file to the heap. Point the - bindings in 'arguments' to this new backing store. (If 'activation' - was also copied to the heap, 'arguments' will point to its storage.) - - This opcode appears before op_ret in functions that don't require full - scope chains, but do use 'arguments'. - */ - - int arguments = vPC[1].u.operand; - int activation = vPC[2].u.operand; - ASSERT(codeBlock->usesArguments()); - if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) { - if (JSValue activationValue = callFrame->r(activation).jsValue()) - asArguments(argumentsValue)->didTearOffActivation(callFrame, asActivation(activationValue)); - else - asArguments(argumentsValue)->tearOff(callFrame); - } - - vPC += OPCODE_LENGTH(op_tear_off_arguments); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_ret) { - /* ret result(r) - - Return register result as the return value of the current - function call, writing it into functionReturnValue. - In addition, unwind one call frame and restore the scope - chain, code block instruction pointer and register base - to those of the calling function. - */ - - int result = vPC[1].u.operand; - - JSValue returnValue = callFrame->r(result).jsValue(); - - vPC = callFrame->returnVPC(); - callFrame = callFrame->callerFrame(); - - if (callFrame->hasHostCallFrameFlag()) - return returnValue; - - *topCallFrameSlot = callFrame; - functionReturnValue = returnValue; - codeBlock = callFrame->codeBlock(); - ASSERT(codeBlock == callFrame->codeBlock()); - - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_call_put_result) { - /* op_call_put_result result(r) - - Move call result from functionReturnValue to caller's - expected return value register. - */ - - callFrame->uncheckedR(vPC[1].u.operand) = functionReturnValue; - - vPC += OPCODE_LENGTH(op_call_put_result); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_ret_object_or_this) { - /* ret result(r) - - Return register result as the return value of the current - function call, writing it into the caller's expected return - value register. In addition, unwind one call frame and - restore the scope chain, code block instruction pointer and - register base to those of the calling function. - */ - - int result = vPC[1].u.operand; - - JSValue returnValue = callFrame->r(result).jsValue(); - - if (UNLIKELY(!returnValue.isObject())) - returnValue = callFrame->r(vPC[2].u.operand).jsValue(); - - vPC = callFrame->returnVPC(); - callFrame = callFrame->callerFrame(); - - if (callFrame->hasHostCallFrameFlag()) - return returnValue; - - *topCallFrameSlot = callFrame; - functionReturnValue = returnValue; - codeBlock = callFrame->codeBlock(); - ASSERT(codeBlock == callFrame->codeBlock()); - - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_enter) { - /* enter - - Initializes local variables to undefined. If the code block requires - an activation, enter_with_activation is used instead. - - This opcode appears only at the beginning of a code block. - */ - - size_t i = 0; - for (size_t count = codeBlock->m_numVars; i < count; ++i) - callFrame->uncheckedR(i) = jsUndefined(); - - vPC += OPCODE_LENGTH(op_enter); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_create_activation) { - /* create_activation dst(r) - - If the activation object for this callframe has not yet been created, - this creates it and writes it back to dst. - */ - - int activationReg = vPC[1].u.operand; - if (!callFrame->r(activationReg).jsValue()) { - JSActivation* activation = JSActivation::create(*globalData, callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable())); - callFrame->r(activationReg) = JSValue(activation); - callFrame->setScope(activation); - } - vPC += OPCODE_LENGTH(op_create_activation); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_create_this) { - /* op_create_this this(r) proto(r) - - Allocate an object as 'this', fr use in construction. - - This opcode should only be used at the beginning of a code - block. - */ - - int thisRegister = vPC[1].u.operand; - - JSFunction* constructor = jsCast<JSFunction*>(callFrame->callee()); -#if !ASSERT_DISABLED - ConstructData constructData; - ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS); -#endif - - Structure* structure = constructor->cachedInheritorID(callFrame); - callFrame->uncheckedR(thisRegister) = constructEmptyObject(callFrame, structure); - - vPC += OPCODE_LENGTH(op_create_this); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_convert_this) { - /* convert_this this(r) - - Takes the value in the 'this' register, converts it to a - value that is suitable for use as the 'this' value, and - stores it in the 'this' register. This opcode is emitted - to avoid doing the conversion in the caller unnecessarily. - - This opcode should only be used at the beginning of a code - block. - */ - - int thisRegister = vPC[1].u.operand; - JSValue thisVal = callFrame->r(thisRegister).jsValue(); - if (thisVal.isPrimitive()) - callFrame->uncheckedR(thisRegister) = JSValue(thisVal.toThisObject(callFrame)); - - vPC += OPCODE_LENGTH(op_convert_this); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_init_lazy_reg) { - /* init_lazy_reg dst(r) - - Initialises dst(r) to JSValue(). - - This opcode appears only at the beginning of a code block. - */ - int dst = vPC[1].u.operand; - - callFrame->uncheckedR(dst) = JSValue(); - vPC += OPCODE_LENGTH(op_init_lazy_reg); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_create_arguments) { - /* create_arguments dst(r) - - Creates the 'arguments' object and places it in both the - 'arguments' call frame slot and the local 'arguments' - register, if it has not already been initialised. - */ - - int dst = vPC[1].u.operand; - - if (!callFrame->r(dst).jsValue()) { - Arguments* arguments = Arguments::create(*globalData, callFrame); - callFrame->uncheckedR(dst) = JSValue(arguments); - callFrame->uncheckedR(unmodifiedArgumentsRegister(dst)) = JSValue(arguments); - } - vPC += OPCODE_LENGTH(op_create_arguments); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_construct) { - /* construct func(r) argCount(n) registerOffset(n) proto(r) thisRegister(r) - - Invoke register "func" as a constructor. For JS - functions, the calling convention is exactly as for the - "call" opcode, except that the "this" value is a newly - created Object. For native constructors, no "this" - value is passed. In either case, the argCount and registerOffset - registers are interpreted as for the "call" opcode. - - Register proto must contain the prototype property of - register func. This is to enable polymorphic inline - caching of this lookup. - */ - - int func = vPC[1].u.operand; - int argCount = vPC[2].u.operand; - int registerOffset = vPC[3].u.operand; - - JSValue v = callFrame->r(func).jsValue(); - - ConstructData constructData; - ConstructType constructType = getConstructData(v, constructData); - - if (constructType == ConstructTypeJS) { - JSScope* callDataScope = constructData.js.scope; - - JSObject* error = constructData.js.functionExecutable->compileForConstruct(callFrame, callDataScope); - if (UNLIKELY(!!error)) { - exceptionValue = error; - goto vm_throw; - } - - CallFrame* previousCallFrame = callFrame; - CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct(); - callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount); - if (UNLIKELY(!callFrame)) { - callFrame = previousCallFrame; - exceptionValue = createStackOverflowError(callFrame); - goto vm_throw; - } - - callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_construct), callDataScope, previousCallFrame, argCount, jsCast<JSFunction*>(v)); - codeBlock = newCodeBlock; - *topCallFrameSlot = callFrame; - vPC = newCodeBlock->instructions().begin(); -#if ENABLE(OPCODE_STATS) - OpcodeStats::resetLastInstruction(); -#endif - - NEXT_INSTRUCTION(); - } - - if (constructType == ConstructTypeHost) { - JSScope* scope = callFrame->scope(); - CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); - newCallFrame->init(0, vPC + OPCODE_LENGTH(op_construct), scope, callFrame, argCount, asObject(v)); - - JSValue returnValue; - { - *topCallFrameSlot = newCallFrame; - SamplingTool::HostCallRecord callRecord(m_sampler.get()); - returnValue = JSValue::decode(constructData.native.function(newCallFrame)); - *topCallFrameSlot = callFrame; - } - CHECK_FOR_EXCEPTION(); - functionReturnValue = returnValue; - - vPC += OPCODE_LENGTH(op_construct); - NEXT_INSTRUCTION(); - } - - ASSERT(constructType == ConstructTypeNone); - - exceptionValue = createNotAConstructorError(callFrame, v); - goto vm_throw; - } - DEFINE_OPCODE(op_strcat) { - /* strcat dst(r) src(r) count(n) - - Construct a new String instance using the original - constructor, and puts the result in register dst. - The string will be the result of concatenating count - strings with values taken from registers starting at - register src. - */ - int dst = vPC[1].u.operand; - int src = vPC[2].u.operand; - int count = vPC[3].u.operand; - - callFrame->uncheckedR(dst) = concatenateStrings(callFrame, &callFrame->registers()[src], count); - CHECK_FOR_EXCEPTION(); - vPC += OPCODE_LENGTH(op_strcat); - - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_to_primitive) { - int dst = vPC[1].u.operand; - int src = vPC[2].u.operand; - - callFrame->uncheckedR(dst) = callFrame->r(src).jsValue().toPrimitive(callFrame); - vPC += OPCODE_LENGTH(op_to_primitive); - - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_push_with_scope) { - /* push_with_scope scope(r) - - Converts register scope to object, and pushes it onto the top - of the scope chain. - */ - int scope = vPC[1].u.operand; - JSValue v = callFrame->r(scope).jsValue(); - JSObject* o = v.toObject(callFrame); - CHECK_FOR_EXCEPTION(); - - callFrame->setScope(JSWithScope::create(callFrame, o)); - - vPC += OPCODE_LENGTH(op_push_with_scope); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_pop_scope) { - /* pop_scope - - Removes the top item from the current scope chain. - */ - callFrame->setScope(callFrame->scope()->next()); - - vPC += OPCODE_LENGTH(op_pop_scope); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_get_pnames) { - /* get_pnames dst(r) base(r) i(n) size(n) breakTarget(offset) - - Creates a property name list for register base and puts it - in register dst, initializing i and size for iteration. If - base is undefined or null, jumps to breakTarget. - */ - int dst = vPC[1].u.operand; - int base = vPC[2].u.operand; - int i = vPC[3].u.operand; - int size = vPC[4].u.operand; - int breakTarget = vPC[5].u.operand; - - JSValue v = callFrame->r(base).jsValue(); - if (v.isUndefinedOrNull()) { - vPC += breakTarget; - NEXT_INSTRUCTION(); - } - - JSObject* o = v.toObject(callFrame); - Structure* structure = o->structure(); - JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache(); - if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame)) - jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o); - - callFrame->uncheckedR(dst) = jsPropertyNameIterator; - callFrame->uncheckedR(base) = JSValue(o); - callFrame->uncheckedR(i) = Register::withInt(0); - callFrame->uncheckedR(size) = Register::withInt(jsPropertyNameIterator->size()); - vPC += OPCODE_LENGTH(op_get_pnames); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_next_pname) { - /* next_pname dst(r) base(r) i(n) size(n) iter(r) target(offset) - - Copies the next name from the property name list in - register iter to dst, then jumps to offset target. If there are no - names left, invalidates the iterator and continues to the next - instruction. - */ - int dst = vPC[1].u.operand; - int base = vPC[2].u.operand; - int i = vPC[3].u.operand; - int size = vPC[4].u.operand; - int iter = vPC[5].u.operand; - int target = vPC[6].u.operand; - - JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator(); - while (callFrame->r(i).i() != callFrame->r(size).i()) { - JSValue key = it->get(callFrame, asObject(callFrame->r(base).jsValue()), callFrame->r(i).i()); - CHECK_FOR_EXCEPTION(); - callFrame->uncheckedR(i) = Register::withInt(callFrame->r(i).i() + 1); - if (key) { - CHECK_FOR_TIMEOUT(); - callFrame->uncheckedR(dst) = key; - vPC += target; - NEXT_INSTRUCTION(); - } - } - - vPC += OPCODE_LENGTH(op_next_pname); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_jmp_scopes) { - /* jmp_scopes count(n) target(offset) - - Removes the a number of items from the current scope chain - specified by immediate number count, then jumps to offset - target. - */ - int count = vPC[1].u.operand; - int target = vPC[2].u.operand; - - JSScope* tmp = callFrame->scope(); - while (count--) - tmp = tmp->next(); - callFrame->setScope(tmp); - - vPC += target; - NEXT_INSTRUCTION(); - } -#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) - // Appease GCC - goto *(&&skip_new_scope); -#endif - DEFINE_OPCODE(op_push_name_scope) { - /* new_scope property(id) value(r) attributes(unsigned) - - Constructs a name scope of the form { property<attributes>: value }, - and pushes it onto the scope chain. - */ - callFrame->setScope(createNameScope(callFrame, vPC)); - - vPC += OPCODE_LENGTH(op_push_name_scope); - NEXT_INSTRUCTION(); - } -#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) - skip_new_scope: -#endif - DEFINE_OPCODE(op_catch) { - /* catch ex(r) - - Retrieves the VM's current exception and puts it in register - ex. This is only valid after an exception has been raised, - and usually forms the beginning of an exception handler. - */ - ASSERT(exceptionValue); - ASSERT(!globalData->exception); - int ex = vPC[1].u.operand; - callFrame->uncheckedR(ex) = exceptionValue; - exceptionValue = JSValue(); - - vPC += OPCODE_LENGTH(op_catch); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_throw) { - /* throw ex(r) - - Throws register ex as an exception. This involves three - steps: first, it is set as the current exception in the - VM's internal state, then the stack is unwound until an - exception handler or a native code boundary is found, and - then control resumes at the exception handler if any or - else the script returns control to the nearest native caller. - */ - - int ex = vPC[1].u.operand; - exceptionValue = callFrame->r(ex).jsValue(); - - handler = throwException(callFrame, exceptionValue, vPC - codeBlock->instructions().begin()); - if (!handler) - return throwError(callFrame, exceptionValue); - - codeBlock = callFrame->codeBlock(); - vPC = codeBlock->instructions().begin() + handler->target; - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_throw_reference_error) { - /* op_throw_reference_error message(k) - - Constructs a new reference Error instance using the - original constructor, using constant message as the - message string. The result is thrown. - */ - String message = callFrame->r(vPC[1].u.operand).jsValue().toString(callFrame)->value(callFrame); - exceptionValue = JSValue(createReferenceError(callFrame, message)); - goto vm_throw; - } - DEFINE_OPCODE(op_end) { - /* end result(r) - - Return register result as the value of a global or eval - program. Return control to the calling native code. - */ - - int result = vPC[1].u.operand; - return callFrame->r(result).jsValue(); - } - DEFINE_OPCODE(op_put_getter_setter) { - /* put_getter_setter base(r) property(id) getter(r) setter(r) - - Puts accessor descriptor to register base as the named - identifier property. Base and function may be objects - or undefined, this op should only be used for accessors - defined in object literal form. - - Unlike many opcodes, this one does not write any output to - the register file. - */ - int base = vPC[1].u.operand; - int property = vPC[2].u.operand; - int getterReg = vPC[3].u.operand; - int setterReg = vPC[4].u.operand; - - ASSERT(callFrame->r(base).jsValue().isObject()); - JSObject* baseObj = asObject(callFrame->r(base).jsValue()); - Identifier& ident = codeBlock->identifier(property); - - GetterSetter* accessor = GetterSetter::create(callFrame); - - JSValue getter = callFrame->r(getterReg).jsValue(); - JSValue setter = callFrame->r(setterReg).jsValue(); - ASSERT(getter.isObject() || getter.isUndefined()); - ASSERT(setter.isObject() || setter.isUndefined()); - ASSERT(getter.isObject() || setter.isObject()); - - if (!getter.isUndefined()) - accessor->setGetter(callFrame->globalData(), asObject(getter)); - if (!setter.isUndefined()) - accessor->setSetter(callFrame->globalData(), asObject(setter)); - baseObj->putDirectAccessor(callFrame, ident, accessor, Accessor); - - vPC += OPCODE_LENGTH(op_put_getter_setter); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_method_check) { - vPC++; - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_debug) { - /* debug debugHookID(n) firstLine(n) lastLine(n) column(n) - - Notifies the debugger of the current state of execution. This opcode - is only generated while the debugger is attached. - */ - int debugHookID = vPC[1].u.operand; - int firstLine = vPC[2].u.operand; - int lastLine = vPC[3].u.operand; - int column = vPC[4].u.operand; - - - debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine, column); - - vPC += OPCODE_LENGTH(op_debug); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_profile_will_call) { - /* op_profile_will_call function(r) - - Notifies the profiler of the beginning of a function call. This opcode - is only generated if developer tools are enabled. - */ - int function = vPC[1].u.operand; - - if (Profiler* profiler = globalData->enabledProfiler()) - profiler->willExecute(callFrame, callFrame->r(function).jsValue()); - - vPC += OPCODE_LENGTH(op_profile_will_call); - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_profile_did_call) { - /* op_profile_did_call function(r) - - Notifies the profiler of the end of a function call. This opcode - is only generated if developer tools are enabled. - */ - int function = vPC[1].u.operand; - - if (Profiler* profiler = globalData->enabledProfiler()) - profiler->didExecute(callFrame, callFrame->r(function).jsValue()); - - vPC += OPCODE_LENGTH(op_profile_did_call); - NEXT_INSTRUCTION(); - } - vm_throw: { - globalData->exception = JSValue(); - if (!tickCount) { - // The exceptionValue is a lie! (GCC produces bad code for reasons I - // cannot fathom if we don't assign to the exceptionValue before branching) - exceptionValue = createInterruptedExecutionException(globalData); - } - JSGlobalObject* globalObject = callFrame->lexicalGlobalObject(); - handler = throwException(callFrame, exceptionValue, vPC - codeBlock->instructions().begin()); - if (!handler) { - // Can't use the callframe at this point as the scopechain, etc have - // been released. - return throwError(globalObject->globalExec(), exceptionValue); - } - - codeBlock = callFrame->codeBlock(); - vPC = codeBlock->instructions().begin() + handler->target; - NEXT_INSTRUCTION(); - } - } -#if !ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) - } // iterator loop ends -#endif - #undef NEXT_INSTRUCTION - #undef DEFINE_OPCODE - #undef CHECK_FOR_EXCEPTION - #undef CHECK_FOR_TIMEOUT -#endif // ENABLE(CLASSIC_INTERPRETER) -} - -#endif // !ENABLE(LLINT_C_LOOP) - - JSValue Interpreter::retrieveArgumentsFromVMCode(CallFrame* callFrame, JSFunction* function) const { CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function); @@ -5159,16 +1342,7 @@ void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intp if (!callerCodeBlock) return; unsigned bytecodeOffset = 0; -#if ENABLE(CLASSIC_INTERPRETER) - if (!callerFrame->globalData().canUseJIT()) - bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnVPC()); -#if ENABLE(JIT) - else - bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC()); -#endif -#else bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC()); -#endif lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1); sourceID = callerCodeBlock->ownerExecutable()->sourceID(); sourceURL = callerCodeBlock->ownerExecutable()->sourceURL(); diff --git a/Source/JavaScriptCore/interpreter/Interpreter.h b/Source/JavaScriptCore/interpreter/Interpreter.h index 464056bc1..f27ae8206 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.h +++ b/Source/JavaScriptCore/interpreter/Interpreter.h @@ -204,27 +204,14 @@ namespace JSC { OpcodeID getOpcodeID(Opcode opcode) { ASSERT(m_initialized); -#if ENABLE(COMPUTED_GOTO_OPCODES) -#if ENABLE(LLINT) - ASSERT(isOpcode(opcode)); - return m_opcodeIDTable.get(opcode); -#elif ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) +#if ENABLE(COMPUTED_GOTO_OPCODES) && ENABLE(LLINT) ASSERT(isOpcode(opcode)); - if (!m_classicEnabled) - return static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode)); - return m_opcodeIDTable.get(opcode); -#endif // ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) -#else // !ENABLE(COMPUTED_GOTO_OPCODES) +#else return opcode; -#endif // !ENABLE(COMPUTED_GOTO_OPCODES) +#endif } - bool classicEnabled() - { - return m_classicEnabled; - } - bool isOpcode(Opcode); JSValue execute(ProgramExecutable*, CallFrame*, JSObject* thisObj); @@ -260,15 +247,6 @@ namespace JSC { void endRepeatCall(CallFrameClosure&); JSValue execute(CallFrameClosure&); -#if ENABLE(CLASSIC_INTERPRETER) - NEVER_INLINE JSScope* createNameScope(CallFrame*, const Instruction* vPC); - - void tryCacheGetByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const Identifier& propertyName, const PropertySlot&); - void uncacheGetByID(CodeBlock*, Instruction* vPC); - void tryCachePutByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const PutPropertySlot&); - void uncachePutByID(CodeBlock*, Instruction* vPC); -#endif // ENABLE(CLASSIC_INTERPRETER) - NEVER_INLINE bool unwindCallFrame(CallFrame*&, JSValue, unsigned& bytecodeOffset, CodeBlock*&); static ALWAYS_INLINE CallFrame* slideRegisterWindowForCall(CodeBlock*, RegisterFile*, CallFrame*, size_t registerOffset, int argc); @@ -291,20 +269,14 @@ namespace JSC { RegisterFile m_registerFile; -#if ENABLE(COMPUTED_GOTO_OPCODES) -#if ENABLE(LLINT) +#if ENABLE(COMPUTED_GOTO_OPCODES) && ENABLE(LLINT) Opcode* m_opcodeTable; // Maps OpcodeID => Opcode for compiling HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling -#elif ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) - Opcode m_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling - HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling #endif -#endif // ENABLE(COMPUTED_GOTO_OPCODES) #if !ASSERT_DISABLED bool m_initialized; #endif - bool m_classicEnabled; }; // This value must not be an object that would require this conversion (WebCore's global object). diff --git a/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp b/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp index 7a53b8e2e..2123f5a67 100644 --- a/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp +++ b/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp @@ -54,7 +54,7 @@ public: : MetaAllocator(jitAllocationGranule) // round up all allocations to 32 bytes { m_reservation = PageReservation::reserveWithGuardPages(fixedExecutableMemoryPoolSize, OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true); -#if !(ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) +#if !ENABLE(LLINT) if (!m_reservation) CRASH(); #endif diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm index 53da6424b..83abf380c 100644 --- a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm @@ -1398,7 +1398,9 @@ _llint_op_put_by_val: dispatch(5) .opPutByValEmpty: - storeb 1, ArrayProfile::m_mayStoreToHole[t3] + if VALUE_PROFILER + storeb 1, ArrayProfile::m_mayStoreToHole[t3] + end addi 1, ArrayStorage::m_numValuesInVector[t0] bib t2, -sizeof IndexingHeader + IndexingHeader::m_publicLength[t0], .opPutByValStoreResult addi 1, t2, t1 diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm index f4ff5c464..4d614f51f 100644 --- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm @@ -1241,7 +1241,9 @@ _llint_op_put_by_val: dispatch(5) .opPutByValEmpty: - storeb 1, ArrayProfile::m_mayStoreToHole[t3] + if VALUE_PROFILER + storeb 1, ArrayProfile::m_mayStoreToHole[t3] + end addi 1, ArrayStorage::m_numValuesInVector[t0] bib t2, -sizeof IndexingHeader + IndexingHeader::m_publicLength[t0], .opPutByValStoreResult addi 1, t2, t1 diff --git a/Source/JavaScriptCore/offlineasm/asm.rb b/Source/JavaScriptCore/offlineasm/asm.rb index 14d616442..4d44c5e91 100644 --- a/Source/JavaScriptCore/offlineasm/asm.rb +++ b/Source/JavaScriptCore/offlineasm/asm.rb @@ -225,7 +225,7 @@ $stderr.puts "offlineasm: Parsing #{asmFile} and #{offsetsFile} and creating ass begin configurationList = offsetsAndConfigurationIndex(offsetsFile) rescue MissingMagicValuesException - $stderr.puts "offlineasm: No magic values found. Skipping assembly file generation assuming the classic interpreter is enabled." + $stderr.puts "offlineasm: No magic values found. Skipping assembly file generation." exit 0 end diff --git a/Source/JavaScriptCore/offlineasm/cloop.rb b/Source/JavaScriptCore/offlineasm/cloop.rb index 9975e0767..b3e319c4d 100644 --- a/Source/JavaScriptCore/offlineasm/cloop.rb +++ b/Source/JavaScriptCore/offlineasm/cloop.rb @@ -507,7 +507,7 @@ end class Instruction def lowerC_LOOP $asm.codeOrigin codeOriginString if $enableCodeOriginComments - $asm.annotation annotation if $enableInstrAnnotations + $asm.annotation annotation if $enableInstrAnnotations && (opcode != "cloopDo") case opcode when "addi" @@ -981,6 +981,12 @@ class Instruction when "cloopCallSlowPath" cloopEmitCallSlowPath(operands) + # For debugging only. This is used to insert instrumentation into the + # generated LLIntAssembly.h during llint development only. Do not use + # for production code. + when "cloopDo" + $asm.putc "#{annotation}" + else lowerDefault end diff --git a/Source/JavaScriptCore/offlineasm/instructions.rb b/Source/JavaScriptCore/offlineasm/instructions.rb index d046bee6f..ddb1bb90f 100644 --- a/Source/JavaScriptCore/offlineasm/instructions.rb +++ b/Source/JavaScriptCore/offlineasm/instructions.rb @@ -227,6 +227,14 @@ CXX_INSTRUCTIONS = "cloopCallJSFunction", # operands: callee "cloopCallNative", # operands: callee "cloopCallSlowPath", # operands: callTarget, currentFrame, currentPC + + # For debugging only: + # Takes no operands but simply emits whatever follows in // comments as + # a line of C++ code in the generated LLIntAssembly.h file. This can be + # used to insert instrumentation into the interpreter loop to inspect + # variables of interest. Do not leave these instructions in production + # code. + "cloopDo", # no operands ] INSTRUCTIONS = MACRO_INSTRUCTIONS + X86_INSTRUCTIONS + ARMv7_INSTRUCTIONS + CXX_INSTRUCTIONS diff --git a/Source/JavaScriptCore/offlineasm/offsets.rb b/Source/JavaScriptCore/offlineasm/offsets.rb index 627183dc8..d9266d9a3 100644 --- a/Source/JavaScriptCore/offlineasm/offsets.rb +++ b/Source/JavaScriptCore/offlineasm/offsets.rb @@ -38,7 +38,6 @@ OFFSET_MAGIC_NUMBERS = [ to32Bit(0xec577ac7), to32Bit(0x0ff5e755) ] # MissingMagicValuesException # # Thrown when magic values are missing from the binary. -# This is usually an indication that the classic interpreter is enabled. # class MissingMagicValuesException < Exception diff --git a/Source/JavaScriptCore/offlineasm/parser.rb b/Source/JavaScriptCore/offlineasm/parser.rb index 70b03cf70..76eea522f 100644 --- a/Source/JavaScriptCore/offlineasm/parser.rb +++ b/Source/JavaScriptCore/offlineasm/parser.rb @@ -103,7 +103,11 @@ def lex(str, fileName) annotationType = whitespaceFound ? :local : :global when /\A\n/ # We've found a '\n'. Emit the last comment recorded if appropriate: - if $enableInstrAnnotations and annotation + # We need to parse annotations regardless of whether the backend does + # anything with them or not. This is because the C++ backend may make + # use of this for its cloopDo debugging utility even if + # enableInstrAnnotations is not enabled. + if annotation result << Annotation.new(CodeOrigin.new(fileName, lineNumber), annotationType, annotation) annotation = nil diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp index d7327d564..0a453eea0 100644 --- a/Source/JavaScriptCore/runtime/Executable.cpp +++ b/Source/JavaScriptCore/runtime/Executable.cpp @@ -231,11 +231,6 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCo #endif #if ENABLE(JIT) -#if ENABLE(CLASSIC_INTERPRETER) - if (!m_jitCodeForCall) - Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock)); - else -#endif Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock) + m_jitCodeForCall.size()); #else Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock)); @@ -356,12 +351,7 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, JSScope* scope, JI #endif #if ENABLE(JIT) -#if ENABLE(CLASSIC_INTERPRETER) - if (!m_jitCodeForCall) - Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock)); - else -#endif - Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock) + m_jitCodeForCall.size()); + Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock) + m_jitCodeForCall.size()); #else Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock)); #endif @@ -534,12 +524,7 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, JSScope* s #endif #if ENABLE(JIT) -#if ENABLE(CLASSIC_INTERPRETER) - if (!m_jitCodeForCall) - Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall)); - else -#endif - Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall) + m_jitCodeForCall.size()); + Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall) + m_jitCodeForCall.size()); #else Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall)); #endif @@ -576,11 +561,6 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, JSSco #endif #if ENABLE(JIT) -#if ENABLE(CLASSIC_INTERPRETER) - if (!m_jitCodeForConstruct) - Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct)); - else -#endif Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct) + m_jitCodeForConstruct.size()); #else Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct)); diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h index 808c78fba..6eeda3a82 100644 --- a/Source/JavaScriptCore/runtime/Executable.h +++ b/Source/JavaScriptCore/runtime/Executable.h @@ -266,7 +266,6 @@ namespace JSC { #if ENABLE(JIT) static NativeExecutable* create(JSGlobalData& globalData, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic) { - ASSERT(!globalData.interpreter->classicEnabled()); NativeExecutable* executable; if (!callThunk) { executable = new (NotNull, allocateCell<NativeExecutable>(globalData.heap)) NativeExecutable(globalData, function, constructor); @@ -279,7 +278,7 @@ namespace JSC { } #endif -#if ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT_C_LOOP) +#if ENABLE(LLINT_C_LOOP) static NativeExecutable* create(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor) { ASSERT(!globalData.canUseJIT()); @@ -306,7 +305,6 @@ namespace JSC { #if ENABLE(JIT) void finishCreation(JSGlobalData& globalData, JITCode callThunk, JITCode constructThunk, Intrinsic intrinsic) { - ASSERT(!globalData.interpreter->classicEnabled()); Base::finishCreation(globalData); m_jitCodeForCall = callThunk; m_jitCodeForConstruct = constructThunk; @@ -316,15 +314,6 @@ namespace JSC { } #endif -#if ENABLE(CLASSIC_INTERPRETER) - void finishCreation(JSGlobalData& globalData) - { - ASSERT(!globalData.canUseJIT()); - Base::finishCreation(globalData); - m_intrinsic = NoIntrinsic; - } -#endif - private: NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor) : ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST) diff --git a/Source/JavaScriptCore/runtime/JSActivation.h b/Source/JavaScriptCore/runtime/JSActivation.h index 442941335..fa2291813 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.h +++ b/Source/JavaScriptCore/runtime/JSActivation.h @@ -84,6 +84,8 @@ namespace JSC { bool isValidIndex(int) const; bool isValid(const SymbolTableEntry&) const; bool isTornOff(); + int registersOffset(); + static int registersOffset(SharedSymbolTable*); protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags; @@ -99,8 +101,8 @@ namespace JSC { NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter(); static size_t allocationSize(SharedSymbolTable*); + static size_t storageOffset(); - int registerOffset(); WriteBarrier<Unknown>* storage(); // captureCount() number of registers. }; @@ -141,17 +143,17 @@ namespace JSC { return false; } - inline int JSActivation::registerOffset() + inline int JSActivation::registersOffset(SharedSymbolTable* symbolTable) { - return -symbolTable()->captureStart(); + return storageOffset() - (symbolTable->captureStart() * sizeof(WriteBarrier<Unknown>)); } inline void JSActivation::tearOff(JSGlobalData& globalData) { ASSERT(!isTornOff()); - int registerOffset = this->registerOffset(); - WriteBarrierBase<Unknown>* dst = storage() + registerOffset; + WriteBarrierBase<Unknown>* dst = reinterpret_cast<WriteBarrierBase<Unknown>*>( + reinterpret_cast<char*>(this) + registersOffset(symbolTable())); WriteBarrierBase<Unknown>* src = m_registers; int captureEnd = symbolTable()->captureEnd(); @@ -164,15 +166,19 @@ namespace JSC { inline bool JSActivation::isTornOff() { - return m_registers == storage() + registerOffset(); + return m_registers == reinterpret_cast<WriteBarrierBase<Unknown>*>( + reinterpret_cast<char*>(this) + registersOffset(symbolTable())); + } + + inline size_t JSActivation::storageOffset() + { + return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(JSActivation)); } inline WriteBarrier<Unknown>* JSActivation::storage() { return reinterpret_cast<WriteBarrier<Unknown>*>( - reinterpret_cast<char*>(this) + - WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(JSActivation)) - ); + reinterpret_cast<char*>(this) + storageOffset()); } inline size_t JSActivation::allocationSize(SharedSymbolTable* symbolTable) diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp index 26f2b8616..e30a7913d 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp @@ -97,7 +97,11 @@ extern const HashTable regExpPrototypeTable; extern const HashTable stringTable; extern const HashTable stringConstructorTable; -#if ENABLE(ASSEMBLER) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) +// Note: Platform.h will enforce that ENABLE(ASSEMBLER) is true if either +// ENABLE(JIT) or ENABLE(YARR_JIT) or both are enabled. The code below +// just checks for ENABLE(JIT) or ENABLE(YARR_JIT) with this premise in mind. + +#if ENABLE(ASSEMBLER) static bool enableAssembler(ExecutableAllocator& executableAllocator) { if (!executableAllocator.isValid() || (!Options::useJIT() && !Options::useRegExpJIT())) @@ -124,7 +128,7 @@ static bool enableAssembler(ExecutableAllocator& executableAllocator) return true; #endif } -#endif +#endif // ENABLE(!ASSEMBLER) JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType, HeapType heapType) : @@ -180,9 +184,13 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread , m_timeoutCount(512) #endif , m_newStringsSinceLastHashConst(0) -#if ENABLE(ASSEMBLER) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) +#if ENABLE(ASSEMBLER) , m_canUseAssembler(enableAssembler(executableAllocator)) +#endif +#if ENABLE(JIT) , m_canUseJIT(m_canUseAssembler && Options::useJIT()) +#endif +#if ENABLE(YARR_JIT) , m_canUseRegExpJIT(m_canUseAssembler && Options::useRegExpJIT()) #endif #if ENABLE(GC_VALIDATION) @@ -370,10 +378,6 @@ static ThunkGenerator thunkGeneratorForIntrinsic(Intrinsic intrinsic) NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, NativeFunction constructor) { -#if ENABLE(CLASSIC_INTERPRETER) - if (!canUseJIT()) - return NativeExecutable::create(*this, function, constructor); -#endif return jitStubs->hostFunctionStub(this, function, constructor); } NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, Intrinsic intrinsic) diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h index 68e0e25d1..603f9f82a 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.h +++ b/Source/JavaScriptCore/runtime/JSGlobalData.h @@ -280,20 +280,18 @@ namespace JSC { return m_enabledProfiler; } -#if !ENABLE(JIT) - bool canUseJIT() { return false; } // interpreter only -#elif !ENABLE(CLASSIC_INTERPRETER) && !ENABLE(LLINT) +#if ENABLE(JIT) && ENABLE(LLINT) + bool canUseJIT() { return m_canUseJIT; } +#elif ENABLE(JIT) bool canUseJIT() { return true; } // jit only #else - bool canUseJIT() { return m_canUseJIT; } + bool canUseJIT() { return false; } // interpreter only #endif -#if !ENABLE(YARR_JIT) - bool canUseRegExpJIT() { return false; } // interpreter only -#elif !ENABLE(CLASSIC_INTERPRETER) && !ENABLE(LLINT) - bool canUseRegExpJIT() { return true; } // jit only -#else +#if ENABLE(YARR_JIT) bool canUseRegExpJIT() { return m_canUseRegExpJIT; } +#else + bool canUseRegExpJIT() { return false; } // interpreter only #endif PrivateName m_inheritorIDKey; @@ -440,9 +438,13 @@ namespace JSC { JSGlobalData(GlobalDataType, ThreadStackType, HeapType); static JSGlobalData*& sharedInstanceInternal(); void createNativeThunk(); -#if ENABLE(ASSEMBLER) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) +#if ENABLE(ASSEMBLER) bool m_canUseAssembler; +#endif +#if ENABLE(JIT) bool m_canUseJIT; +#endif +#if ENABLE(YARR_JIT) bool m_canUseRegExpJIT; #endif #if ENABLE(GC_VALIDATION) diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp index 3d643a266..b0a0e8122 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -373,7 +373,7 @@ void ObjectsWithBrokenIndexingFinder::operator()(JSCell* cell) // a different global object that have prototypes from our global object. bool foundGlobalObject = false; for (JSObject* current = object; ;) { - if (current->unwrappedGlobalObject() == m_globalObject) { + if (current->globalObject() == m_globalObject) { foundGlobalObject = true; break; } diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index e9a3e2836..c85965060 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -498,8 +498,8 @@ static double parseFloat(const String& s) EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec) { JSObject* thisObject = exec->hostThisValue().toThisObject(exec); - JSObject* unwrappedObject = thisObject->unwrappedObject(); - if (!unwrappedObject->isGlobalObject() || jsCast<JSGlobalObject*>(unwrappedObject)->evalFunction() != exec->callee()) + JSGlobalObject* calleeGlobalObject = exec->callee()->globalObject(); + if (thisObject != exec->callee()->globalObject()->globalThis()) return throwVMError(exec, createEvalError(exec, ASCIILiteral("The \"this\" value passed to eval must be the global object from which eval originated"))); JSValue x = exec->argument(0); @@ -519,11 +519,11 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec) } EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false); - JSObject* error = eval->compile(exec, jsCast<JSGlobalObject*>(unwrappedObject)); + JSObject* error = eval->compile(exec, calleeGlobalObject); if (error) return throwVMError(exec, error); - return JSValue::encode(exec->interpreter()->execute(eval, exec, thisObject, jsCast<JSGlobalObject*>(unwrappedObject))); + return JSValue::encode(exec->interpreter()->execute(eval, exec, thisObject, calleeGlobalObject)); } EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index acff8a6ae..7bf12b67e 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -601,7 +601,7 @@ Structure* JSObject::inheritorID(JSGlobalData& globalData) bool JSObject::allowsAccessFrom(ExecState* exec) { - JSGlobalObject* globalObject = unwrappedGlobalObject(); + JSGlobalObject* globalObject = this->globalObject(); return globalObject->globalObjectMethodTable()->allowsAccessFrom(globalObject, exec); } @@ -924,13 +924,6 @@ JSObject* JSObject::toThisObject(JSCell* cell, ExecState*) return jsCast<JSObject*>(cell); } -JSObject* JSObject::unwrappedObject() -{ - if (isGlobalThis()) - return jsCast<JSGlobalThis*>(this)->unwrappedObject(); - return this; -} - void JSObject::seal(JSGlobalData& globalData) { if (isSealed(globalData)) @@ -954,13 +947,6 @@ void JSObject::preventExtensions(JSGlobalData& globalData) setStructure(globalData, Structure::preventExtensionsTransition(globalData, structure())); } -JSGlobalObject* JSObject::unwrappedGlobalObject() -{ - if (isGlobalThis()) - return jsCast<JSGlobalThis*>(this)->unwrappedObject(); - return structure()->globalObject(); -} - // This presently will flatten to an uncachable dictionary; this is suitable // for use in delete, we may want to do something different elsewhere. void JSObject::reifyStaticFunctionsForDelete(ExecState* exec) @@ -1052,7 +1038,7 @@ void JSObject::notifyUsedAsPrototype(JSGlobalData& globalData) Structure* JSObject::createInheritorID(JSGlobalData& globalData) { - Structure* inheritorID = createEmptyObjectStructure(globalData, unwrappedGlobalObject(), this); + Structure* inheritorID = createEmptyObjectStructure(globalData, globalObject(), this); ASSERT(inheritorID->isEmpty()); PutPropertySlot slot; diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index bb59eb32b..16efeba5e 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -172,6 +172,15 @@ namespace JSC { JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); JS_EXPORT_PRIVATE static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); + void putByIndexInline(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow) + { + if (canSetIndexQuickly(propertyName)) { + setIndexQuickly(exec->globalData(), propertyName, value); + return; + } + methodTable()->putByIndex(this, exec, propertyName, value, shouldThrow); + } + // This is similar to the putDirect* methods: // - the prototype chain is not consulted // - accessors are not called. @@ -179,7 +188,7 @@ namespace JSC { // This method creates a property with attributes writable, enumerable and configurable all set to true. bool putDirectIndex(ExecState* exec, unsigned propertyName, JSValue value, unsigned attributes, PutDirectIndexMode mode) { - if (!attributes && canSetIndexQuickly(propertyName)) { + if (!attributes && canSetIndexQuicklyForPutDirect(propertyName)) { setIndexQuickly(exec->globalData(), propertyName, value); return true; } @@ -191,7 +200,7 @@ namespace JSC { } // A non-throwing version of putDirect and putDirectIndex. - void putDirectMayBeIndex(ExecState*, PropertyName, JSValue); + JS_EXPORT_PRIVATE void putDirectMayBeIndex(ExecState*, PropertyName, JSValue); bool canGetIndexQuickly(unsigned i) { @@ -235,6 +244,19 @@ namespace JSC { } } + bool canSetIndexQuicklyForPutDirect(unsigned i) + { + switch (structure()->indexingType()) { + case ALL_BLANK_INDEXING_TYPES: + return false; + case ALL_ARRAY_STORAGE_INDEXING_TYPES: + return i < m_butterfly->arrayStorage()->vectorLength(); + default: + ASSERT_NOT_REACHED(); + return false; + } + } + void setIndexQuickly(JSGlobalData& globalData, unsigned i, JSValue v) { switch (structure()->indexingType()) { @@ -321,7 +343,6 @@ namespace JSC { // NOTE: JSObject and its subclasses must be able to gracefully handle ExecState* = 0, // because this call may come from inside the compiler. JS_EXPORT_PRIVATE static JSObject* toThisObject(JSCell*, ExecState*); - JSObject* unwrappedObject(); bool getPropertySpecificValue(ExecState*, PropertyName, JSCell*& specificFunction) const; @@ -460,11 +481,6 @@ namespace JSC { return structure()->globalObject(); } - // Does everything possible to return the global object. If it encounters an object - // that does not have a global object, it returns 0 instead (for example - // JSNotAnObject). - JSGlobalObject* unwrappedGlobalObject(); - void switchToSlowPutArrayStorage(JSGlobalData&); // The receiver is the prototype in this case. The following: diff --git a/Source/JavaScriptCore/runtime/LiteralParser.cpp b/Source/JavaScriptCore/runtime/LiteralParser.cpp index 732d818bd..cd854417b 100644 --- a/Source/JavaScriptCore/runtime/LiteralParser.cpp +++ b/Source/JavaScriptCore/runtime/LiteralParser.cpp @@ -570,7 +570,8 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState) goto startParseExpression; } case DoParseArrayEndExpression: { - asArray(objectStack.last())->push(m_exec, lastValue); + JSArray* array = asArray(objectStack.last()); + array->putDirectIndex(m_exec, array->length(), lastValue); if (m_lexer.currentToken().type == TokComma) goto doParseArrayStartExpression; diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp index 5ac2d8788..8614b9c45 100644 --- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp @@ -404,7 +404,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorFreeze(ExecState* exec) return throwVMError(exec, createTypeError(exec, ASCIILiteral("Object.freeze can only be called on Objects."))); JSObject* object = asObject(obj); - if (isJSFinalObject(object)) { + if (isJSFinalObject(object) && !hasIndexedProperties(object->structure()->indexingType())) { object->freeze(exec->globalData()); return JSValue::encode(obj); } diff --git a/Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp b/Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp index 3f709b0a7..b9ba25735 100644 --- a/Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp +++ b/Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp @@ -159,7 +159,7 @@ JSValue SparseArrayEntry::get(ExecState* exec, JSObject* array) const CallData callData; CallType callType = getter->methodTable()->getCallData(getter, callData); - return call(exec, getter, callType, callData, array, exec->emptyList()); + return call(exec, getter, callType, callData, array->methodTable()->toThisObject(array, exec), exec->emptyList()); } void SparseArrayEntry::put(ExecState* exec, JSValue thisValue, SparseArrayValueMap* map, JSValue value, bool shouldThrow) @@ -189,6 +189,8 @@ void SparseArrayEntry::put(ExecState* exec, JSValue thisValue, SparseArrayValueM CallType callType = setter->methodTable()->getCallData(setter, callData); MarkedArgumentBuffer args; args.append(value); + if (thisValue.isObject()) + thisValue = asObject(thisValue)->methodTable()->toThisObject(asObject(thisValue), exec); call(exec, setter, callType, callData, thisValue, args); } diff --git a/Source/Platform/ChangeLog b/Source/Platform/ChangeLog index 7502f1c4d..44faebcba 100644 --- a/Source/Platform/ChangeLog +++ b/Source/Platform/ChangeLog @@ -1,3 +1,32 @@ +2012-09-24 Dana Jansens <danakj@chromium.org> + + [chromium] Add setters to WebFilterOperation for IPC pickling + https://bugs.webkit.org/show_bug.cgi?id=97147 + + Reviewed by James Robinson. + + These methods allow us to restore a WebFilterOperation from a blob + of opaque data. The pickling code needs to be able to create an + empty object and then fill in the pieces, so these setters allow it + to do so. + + Test: WebFilterOperationsTest.saveAndRestore + + * chromium/public/WebFilterOperation.h: + (WebKit::WebFilterOperation::amount): + (WebKit::WebFilterOperation::dropShadowOffset): + (WebKit::WebFilterOperation::matrix): + (WebKit::WebFilterOperation::zoomRect): + (WebFilterOperation): + (WebKit::WebFilterOperation::createEmptyFilter): + (WebKit::WebFilterOperation::setType): + (WebKit::WebFilterOperation::setAmount): + (WebKit::WebFilterOperation::setDropShadowOffset): + (WebKit::WebFilterOperation::setDropShadowColor): + (WebKit::WebFilterOperation::setMatrix): + (WebKit::WebFilterOperation::setZoomRect): + * chromium/src/WebFilterOperation.cpp: + 2012-09-24 Yury Semikhatsky <yurys@chromium.org> Unreviewed, rolling out r122243. diff --git a/Source/Platform/chromium/public/WebFilterOperation.h b/Source/Platform/chromium/public/WebFilterOperation.h index 9f15519a1..3628f487b 100644 --- a/Source/Platform/chromium/public/WebFilterOperation.h +++ b/Source/Platform/chromium/public/WebFilterOperation.h @@ -55,12 +55,23 @@ public: float amount() const { + WEBKIT_ASSERT(m_type == FilterTypeGrayscale + || m_type == FilterTypeSepia + || m_type == FilterTypeSaturate + || m_type == FilterTypeHueRotate + || m_type == FilterTypeInvert + || m_type == FilterTypeBrightness + || m_type == FilterTypeContrast + || m_type == FilterTypeOpacity + || m_type == FilterTypeBlur + || m_type == FilterTypeDropShadow + || m_type == FilterTypeZoom); return m_amount; } WebPoint dropShadowOffset() const { WEBKIT_ASSERT(m_type == FilterTypeDropShadow); - return WebPoint(m_dropShadowOffset); + return m_dropShadowOffset; } WebColor dropShadowColor() const { @@ -69,16 +80,16 @@ public: } const SkScalar* matrix() const { + WEBKIT_ASSERT(m_type == FilterTypeColorMatrix); return m_matrix; } WebRect zoomRect() const { WEBKIT_ASSERT(m_type == FilterTypeZoom); - return WebRect(m_zoomRect); + return m_zoomRect; } -#define WEBKIT_HAS_NEW_WEBFILTEROPERATION_API 1 static WebFilterOperation createGrayscaleFilter(float amount) { return WebFilterOperation(FilterTypeGrayscale, amount); } static WebFilterOperation createSepiaFilter(float amount) { return WebFilterOperation(FilterTypeSepia, amount); } static WebFilterOperation createSaturateFilter(float amount) { return WebFilterOperation(FilterTypeSaturate, amount); } @@ -94,6 +105,46 @@ public: bool equals(const WebFilterOperation& other) const; + // Methods for restoring a WebFilterOperation. + static WebFilterOperation createEmptyFilter() { return WebFilterOperation(FilterTypeGrayscale, 0.0); } + void setType(FilterType type) { m_type = type; } + void setAmount(float amount) + { + WEBKIT_ASSERT(m_type == FilterTypeGrayscale + || m_type == FilterTypeSepia + || m_type == FilterTypeSaturate + || m_type == FilterTypeHueRotate + || m_type == FilterTypeInvert + || m_type == FilterTypeBrightness + || m_type == FilterTypeContrast + || m_type == FilterTypeOpacity + || m_type == FilterTypeBlur + || m_type == FilterTypeDropShadow + || m_type == FilterTypeZoom); + m_amount = amount; + } + void setDropShadowOffset(WebPoint offset) + { + WEBKIT_ASSERT(m_type == FilterTypeDropShadow); + m_dropShadowOffset = offset; + } + void setDropShadowColor(WebColor color) + { + WEBKIT_ASSERT(m_type == FilterTypeDropShadow); + m_dropShadowColor = color; + } + void setMatrix(const SkScalar matrix[20]) + { + WEBKIT_ASSERT(m_type == FilterTypeColorMatrix); + for (unsigned i = 0; i < 20; ++i) + m_matrix[i] = matrix[i]; + } + void setZoomRect(WebRect rect) + { + WEBKIT_ASSERT(m_type == FilterTypeZoom); + m_zoomRect = rect; + } + private: FilterType m_type; diff --git a/Source/WTF/ChangeLog b/Source/WTF/ChangeLog index 7bb10c1fb..51f56d177 100644 --- a/Source/WTF/ChangeLog +++ b/Source/WTF/ChangeLog @@ -1,3 +1,337 @@ +2012-09-21 Ilya Tikhonovsky <loislo@chromium.org> + + Web Inspector: extract Vector instrumentation from core NMI code into MemoryInstrumentationVector.h header. + https://bugs.webkit.org/show_bug.cgi?id=96650 + + Reviewed by Vsevolod Vlasov. + + Added reportMemoryUsage free template function with default body to core NMI code + and add custom version of reportMemoryUsage function for Vectors. + + * GNUmakefile.list.am: + * WTF.gypi: + * WTF.pro: + * WTF.vcproj/WTF.vcproj: + * WTF.xcodeproj/project.pbxproj: + * wtf/MemoryInstrumentation.h: + (WTF): + (MemoryInstrumentation): + (WTF::MemoryInstrumentation::addObjectImpl): + * wtf/MemoryInstrumentationVector.h: Added. + (WTF): + (WTF::instrumentVectorValues): + (WTF::reportMemoryUsage): + +2012-09-24 Mark Lam <mark.lam@apple.com> + + Deleting the classic interpreter and cleaning up some build options. + https://bugs.webkit.org/show_bug.cgi?id=96969. + + Reviewed by Geoffrey Garen. + + * wtf/OSAllocatorPosix.cpp: + (WTF::OSAllocator::reserveAndCommit): + * wtf/Platform.h: + +2012-09-24 Patrick Gansterer <paroga@webkit.org> + + Remove String::operator+=() + https://bugs.webkit.org/show_bug.cgi?id=96172 + + Reviewed by Benjamin Poulain. + + * wtf/Platform.h: + * wtf/text/WTFString.h: + +2012-09-24 Benjamin Poulain <benjamin@webkit.org> + + Add support for query encoding to WTFURL + https://bugs.webkit.org/show_bug.cgi?id=97422 + + Reviewed by Adam Barth. + + Expose character conversion through the new abstract class URLQueryCharsetConverter. + URLQueryCharsetConverter is implemented by WebCore to expose the TextEncoding classes. + + Unfortunatelly that forces us to bring over URLBuffer in the public API. We may be able + to mitigate that later when moving WTFURL to more templates. + + The change fixes 2 of the URL layout tests. + + * WTF.xcodeproj/project.pbxproj: + * wtf/url/api/ParsedURL.cpp: + (WTF::ParsedURL::ParsedURL): + * wtf/url/api/ParsedURL.h: + (ParsedURL): + ParsedURL was using the same constructor for ParsedURLString, and URL without a base. + That was a mistake on my part, I did not intend that, fixed it now :) + + * wtf/url/api/URLBuffer.h: Renamed from Source/WTF/wtf/url/src/URLBuffer.h. + (URLBuffer): + (WTF::URLBuffer::URLBuffer): + (WTF::URLBuffer::~URLBuffer): + (WTF::URLBuffer::at): + (WTF::URLBuffer::set): + (WTF::URLBuffer::capacity): + (WTF::URLBuffer::length): + (WTF::URLBuffer::data): + (WTF::URLBuffer::setLength): + (WTF::URLBuffer::append): + (WTF::URLBuffer::grow): + * wtf/url/api/URLQueryCharsetConverter.h: Added. + (URLQueryCharsetConverter): + (WTF::URLQueryCharsetConverter::URLQueryCharsetConverter): + (WTF::URLQueryCharsetConverter::~URLQueryCharsetConverter): + * wtf/url/src/URLCanon.h: + (URLCanonicalizer): + * wtf/url/src/URLCanonFilesystemurl.cpp: + (WTF::URLCanonicalizer::canonicalizeFileSystemURL): + (WTF::URLCanonicalizer::ReplaceFileSystemURL): + * wtf/url/src/URLCanonFileurl.cpp: + (WTF::URLCanonicalizer::CanonicalizeFileURL): + (WTF::URLCanonicalizer::ReplaceFileURL): + * wtf/url/src/URLCanonInternal.h: + (URLCanonicalizer): + * wtf/url/src/URLCanonQuery.cpp: + (WTF::URLCanonicalizer::CanonicalizeQuery): + (WTF::URLCanonicalizer::ConvertUTF16ToQueryEncoding): + * wtf/url/src/URLCanonRelative.cpp: + (WTF::URLCanonicalizer::resolveRelativeURL): + * wtf/url/src/URLCanonStdURL.cpp: + (WTF::URLCanonicalizer::CanonicalizeStandardURL): + (WTF::URLCanonicalizer::ReplaceStandardURL): + * wtf/url/src/URLUtil.cpp: + (URLUtilities): + (WTF::URLUtilities::canonicalize): + (WTF::URLUtilities::resolveRelative): + (WTF::URLUtilities::ReplaceComponents): + * wtf/url/src/URLUtil.h: + (URLUtilities): + +2012-09-24 Benjamin Poulain <benjamin@webkit.org> + + Integrate most of GoogleURL in WTFURL + https://bugs.webkit.org/show_bug.cgi?id=97405 + + Reviewed by Adam Barth. + + This patch brings almost all of the implementatation of Google-URL in WTFURL + with only minor changes. + + The changes from the original code are mostly: + -Code cleaning. + -Replace url_parse::Parsed by URLSegments. + -Replace url_parse::Component by URLComponent + -More code cleaning. + -Adopt URLBuffer and RawURLBuffer instead of the CanonOutputT and RawCanonOutputT. + -Use URLCharacterTypes instead of the litany of characters functions. + -Some more code cleaning. + -Fix the style to match WebKit as much as possible. + -Rename the files to match WebKit style. + + * WTF.xcodeproj/project.pbxproj: + * wtf/url/api/ParsedURL.cpp: + (WTF::ParsedURL::ParsedURL): + (WTF::ParsedURL::segment): + * wtf/url/api/ParsedURL.h: + (WTF::ParsedURL::isValid): + * wtf/url/src/RawURLBuffer.h: + * wtf/url/src/URLCanon.h: Added. + (URLCanonicalizer): + (CharsetConverter): + (WTF::URLCanonicalizer::CharsetConverter::CharsetConverter): + (WTF::URLCanonicalizer::CharsetConverter::~CharsetConverter): + (CanonHostInfo): + (WTF::URLCanonicalizer::CanonHostInfo::CanonHostInfo): + (WTF::URLCanonicalizer::CanonHostInfo::IsIPAddress): + (WTF::URLCanonicalizer::CanonHostInfo::AddressLength): + (URLComponentSource): + (WTF::URLCanonicalizer::URLComponentSource::URLComponentSource): + (Replacements): + (WTF::URLCanonicalizer::Replacements::Replacements): + (WTF::URLCanonicalizer::Replacements::SetScheme): + (WTF::URLCanonicalizer::Replacements::IsSchemeOverridden): + (WTF::URLCanonicalizer::Replacements::SetUsername): + (WTF::URLCanonicalizer::Replacements::ClearUsername): + (WTF::URLCanonicalizer::Replacements::IsUsernameOverridden): + (WTF::URLCanonicalizer::Replacements::SetPassword): + (WTF::URLCanonicalizer::Replacements::ClearPassword): + (WTF::URLCanonicalizer::Replacements::IsPasswordOverridden): + (WTF::URLCanonicalizer::Replacements::SetHost): + (WTF::URLCanonicalizer::Replacements::ClearHost): + (WTF::URLCanonicalizer::Replacements::IsHostOverridden): + (WTF::URLCanonicalizer::Replacements::SetPort): + (WTF::URLCanonicalizer::Replacements::ClearPort): + (WTF::URLCanonicalizer::Replacements::IsPortOverridden): + (WTF::URLCanonicalizer::Replacements::SetPath): + (WTF::URLCanonicalizer::Replacements::ClearPath): + (WTF::URLCanonicalizer::Replacements::IsPathOverridden): + (WTF::URLCanonicalizer::Replacements::SetQuery): + (WTF::URLCanonicalizer::Replacements::ClearQuery): + (WTF::URLCanonicalizer::Replacements::IsQueryOverridden): + (WTF::URLCanonicalizer::Replacements::SetRef): + (WTF::URLCanonicalizer::Replacements::ClearRef): + (WTF::URLCanonicalizer::Replacements::IsRefOverridden): + (WTF::URLCanonicalizer::Replacements::sources): + (WTF::URLCanonicalizer::Replacements::components): + (WTF::URLCanonicalizer::Replacements::Placeholder): + * wtf/url/src/URLCanonEtc.cpp: Added. + (WTF::URLCanonicalizer::removeURLWhitespace): + (URLCanonicalizer): + (WTF::URLCanonicalizer::canonicalSchemeChar): + (WTF::URLCanonicalizer::CanonicalizeScheme): + (WTF::URLCanonicalizer::CanonicalizeUserInfo): + (WTF::URLCanonicalizer::CanonicalizePort): + (WTF::URLCanonicalizer::CanonicalizeRef): + * wtf/url/src/URLCanonFilesystemurl.cpp: Added. + (WTF::URLCanonicalizer::CanonicalizeFileSystemURL): + (URLCanonicalizer): + (WTF::URLCanonicalizer::ReplaceFileSystemURL): + * wtf/url/src/URLCanonFileurl.cpp: Added. + (WTF::URLCanonicalizer::CanonicalizeFileURL): + (URLCanonicalizer): + (WTF::URLCanonicalizer::FileCanonicalizePath): + (WTF::URLCanonicalizer::ReplaceFileURL): + * wtf/url/src/URLCanonHost.cpp: Added. + (WTF::URLCanonicalizer::CanonicalizeHost): + (URLCanonicalizer): + (WTF::URLCanonicalizer::CanonicalizeHostVerbose): + * wtf/url/src/URLCanonICU.cpp: Added. + (WTF::URLCanonicalizer::IDNToASCII): + (URLCanonicalizer): + (WTF::URLCanonicalizer::readUTFChar): + * wtf/url/src/URLCanonIP.cpp: Added. + (WTF::URLCanonicalizer::CanonicalizeIPAddress): + (URLCanonicalizer): + * wtf/url/src/URLCanonInternal.cpp: Added. + (URLCanonicalizer): + (WTF::URLCanonicalizer::AppendInvalidNarrowString): + (WTF::URLCanonicalizer::ConvertUTF16ToUTF8): + (WTF::URLCanonicalizer::ConvertUTF8ToUTF16): + (WTF::URLCanonicalizer::SetupOverrideComponents): + (WTF::URLCanonicalizer::SetupUTF16OverrideComponents): + (WTF::URLCanonicalizer::_itoa_s): + (WTF::URLCanonicalizer::_itow_s): + * wtf/url/src/URLCanonInternal.h: Added. + (URLCanonicalizer): + (WTF::URLCanonicalizer::hexCharToValue): + (WTF::URLCanonicalizer::isDot): + (WTF::URLCanonicalizer::appendURLEscapedCharacter): + (WTF::URLCanonicalizer::doAppendUTF8): + (WTF::URLCanonicalizer::AppendCharToOutput): + (WTF::URLCanonicalizer::AppendUTF8Value): + (WTF::URLCanonicalizer::AppendUTF8EscapedValue): + (WTF::URLCanonicalizer::AppendUTF16Value): + (WTF::URLCanonicalizer::AppendUTF8EscapedChar): + (WTF::URLCanonicalizer::Is8BitChar): + (WTF::URLCanonicalizer::DecodeEscaped): + (WTF::URLCanonicalizer::_itoa_s): + (WTF::URLCanonicalizer::_itow_s): + (WTF::URLCanonicalizer::_strtoui64): + * wtf/url/src/URLCanonMailto.cpp: Added. + (WTF::URLCanonicalizer::CanonicalizeMailtoURL): + (URLCanonicalizer): + (WTF::URLCanonicalizer::ReplaceMailtoURL): + * wtf/url/src/URLCanonPath.cpp: Added. + (WTF::URLCanonicalizer::CanonicalizePath): + (URLCanonicalizer): + (WTF::URLCanonicalizer::CanonicalizePartialPath): + * wtf/url/src/URLCanonPathurl.cpp: Added. + (WTF::URLCanonicalizer::canonicalizePathURL): + (URLCanonicalizer): + (WTF::URLCanonicalizer::ReplacePathURL): + * wtf/url/src/URLCanonQuery.cpp: Added. + (WTF::URLCanonicalizer::CanonicalizeQuery): + (URLCanonicalizer): + (WTF::URLCanonicalizer::ConvertUTF16ToQueryEncoding): + * wtf/url/src/URLCanonRelative.cpp: Added. + (WTF::URLCanonicalizer::isRelativeURL): + (URLCanonicalizer): + (WTF::URLCanonicalizer::resolveRelativeURL): + * wtf/url/src/URLCanonStdURL.cpp: Added. + (WTF::URLCanonicalizer::DefaultPortForScheme): + (URLCanonicalizer): + (WTF::URLCanonicalizer::CanonicalizeStandardURL): + (WTF::URLCanonicalizer::ReplaceStandardURL): + * wtf/url/src/URLCharacterTypes.cpp: + * wtf/url/src/URLCharacterTypes.h: + (WTF::URLCharacterTypes::isComponentChar): + (WTF::URLCharacterTypes::isHexChar): + (WTF::URLCharacterTypes::isIPv4Char): + (WTF::URLCharacterTypes::isQueryChar): + (WTF::URLCharacterTypes::isCharacterOfType): + (URLCharacterTypes): + * wtf/url/src/URLEscape.cpp: Removed. + * wtf/url/src/URLFile.h: Added. + (URLParser): + (WTF::URLParser::isWindowsDriveSeparator): + (WTF::URLParser::isWindowsDriveLetter): + (WTF::URLParser::findNextSlash): + (WTF::URLParser::doesBeginWindowsDriveSpec): + (WTF::URLParser::doesBeginUNCPath): + * wtf/url/src/URLParse.cpp: Added. + (WTF::URLParser::ExtractScheme): + (URLParser): + (WTF::URLParser::IsAuthorityTerminator): + (WTF::URLParser::ExtractFileName): + (WTF::URLParser::ExtractQueryKeyValue): + (WTF::URLParser::ParseAuthority): + (WTF::URLParser::ParsePort): + (WTF::URLParser::ParseStandardURL): + (WTF::URLParser::ParsePathURL): + (WTF::URLParser::ParseFileSystemURL): + (WTF::URLParser::ParseMailtoURL): + (WTF::URLParser::parsePathInternal): + (WTF::URLParser::ParseAfterScheme): + * wtf/url/src/URLParse.h: Added. + (URLParser): + * wtf/url/src/URLParseFile.cpp: Added. + (WTF): + (WTF::URLParser::ParseFileURL): + (URLParser): + * wtf/url/src/URLParseInternal.h: Added. + (URLParser): + (WTF::URLParser::isURLSlash): + (WTF::URLParser::shouldTrimFromURL): + (WTF::URLParser::trimURL): + (WTF::URLParser::countConsecutiveSlashes): + * wtf/url/src/URLParser.h: Removed. + * wtf/url/src/URLQueryCanonicalizer.h: Removed. + * wtf/url/src/URLSegments.cpp: + * wtf/url/src/URLSegments.h: + (WTF::URLSegments::URLSegments): + (URLSegments): + (WTF::URLSegments::operator=): + (WTF::URLSegments::innerURLSegments): + (WTF::URLSegments::setInnerURLSegments): + (WTF::URLSegments::clearInnerURLSegments): + * wtf/url/src/URLUtil.cpp: Added. + (URLUtilities): + (WTF::URLUtilities::IsStandard): + (WTF::URLUtilities::FindAndCompareScheme): + (WTF::URLUtilities::Canonicalize): + (WTF::URLUtilities::resolveRelative): + (WTF::URLUtilities::ReplaceComponents): + (WTF::URLUtilities::LowerCaseEqualsASCII): + (WTF::URLUtilities::DecodeURLEscapeSequences): + (WTF::URLUtilities::EncodeURIComponent): + (WTF::URLUtilities::CompareSchemeComponent): + * wtf/url/src/URLUtil.h: Added. + (URLUtilities): + * wtf/url/src/URLUtilInternal.h: Renamed from Source/WTF/wtf/url/src/URLEscape.h. + (URLUtilities): + +2012-09-24 Joone Hur <joone.hur@intel.com> + + [GTK] Implement GraphicsLayer using Clutter + https://bugs.webkit.org/show_bug.cgi?id=73767 + + Reviewed by Martin Robinson. + + Add ClutterActor and GraphicsLayerActor to GTypedefs.h. + + * wtf/gobject/GTypedefs.h: + 2012-09-23 Byungwoo Lee <bw80.lee@gmail.com> Fix build warnings : -Wunused-parameter, -Wparentheses, -Wuninitialized. diff --git a/Source/WTF/GNUmakefile.list.am b/Source/WTF/GNUmakefile.list.am index e8e42edd3..0ed10ddae 100644 --- a/Source/WTF/GNUmakefile.list.am +++ b/Source/WTF/GNUmakefile.list.am @@ -80,6 +80,7 @@ wtf_sources += \ Source/WTF/wtf/MediaTime.h \ Source/WTF/wtf/MediaTime.cpp \ Source/WTF/wtf/MemoryInstrumentation.h \ + Source/WTF/wtf/MemoryInstrumentationVector.h \ Source/WTF/wtf/MessageQueue.h \ Source/WTF/wtf/MetaAllocator.cpp \ Source/WTF/wtf/MetaAllocator.h \ diff --git a/Source/WTF/WTF.gypi b/Source/WTF/WTF.gypi index 5dcd01ed7..fdc28d6bb 100644 --- a/Source/WTF/WTF.gypi +++ b/Source/WTF/WTF.gypi @@ -50,6 +50,7 @@ 'wtf/MainThread.h', 'wtf/MathExtras.h', 'wtf/MemoryInstrumentation.h', + 'wtf/MemoryInstrumentationVector.h', 'wtf/MessageQueue.h', 'wtf/NonCopyingSort.h', 'wtf/Noncopyable.h', diff --git a/Source/WTF/WTF.pro b/Source/WTF/WTF.pro index bc0a8770e..e8da4c0c6 100644 --- a/Source/WTF/WTF.pro +++ b/Source/WTF/WTF.pro @@ -87,6 +87,7 @@ HEADERS += \ MD5.h \ MediaTime.h \ MemoryInstrumentation.h \ + MemoryInstrumentationVector.h \ MessageQueue.h \ MetaAllocator.h \ MetaAllocatorHandle.h \ diff --git a/Source/WTF/WTF.vcproj/WTF.vcproj b/Source/WTF/WTF.vcproj/WTF.vcproj index 4ec3e5544..9610092d0 100644 --- a/Source/WTF/WTF.vcproj/WTF.vcproj +++ b/Source/WTF/WTF.vcproj/WTF.vcproj @@ -905,6 +905,10 @@ >
</File>
<File
+ RelativePath="..\wtf\MemoryInstrumentationVector.h"
+ >
+ </File>
+ <File
RelativePath="..\wtf\MessageQueue.h"
>
</File>
diff --git a/Source/WTF/WTF.xcodeproj/project.pbxproj b/Source/WTF/WTF.xcodeproj/project.pbxproj index 52af7b9ce..3a89edfa1 100644 --- a/Source/WTF/WTF.xcodeproj/project.pbxproj +++ b/Source/WTF/WTF.xcodeproj/project.pbxproj @@ -12,11 +12,36 @@ 143F61201565F0F900DB514A /* RAMSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 143F611E1565F0F900DB514A /* RAMSize.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14F3B0F715E45E4600210069 /* SaturatedArithmetic.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F3B0F615E45E4600210069 /* SaturatedArithmetic.h */; settings = {ATTRIBUTES = (Private, ); }; }; 26147B0A15DDCCDC00DDB907 /* IntegerToStringConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 26147B0815DDCCDC00DDB907 /* IntegerToStringConversion.h */; }; + 2661122E160FEAD40013F5C3 /* URLQueryCharsetConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2661122D160FEAD40013F5C3 /* URLQueryCharsetConverter.h */; }; + 26E6C1EE1609037300CA6AF4 /* URLCanonEtc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E6C1CE1609037300CA6AF4 /* URLCanonEtc.cpp */; }; + 26E6C1EF1609037300CA6AF4 /* URLCanonFilesystemurl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E6C1CF1609037300CA6AF4 /* URLCanonFilesystemurl.cpp */; }; + 26E6C1F01609037300CA6AF4 /* URLCanonFileurl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E6C1D01609037300CA6AF4 /* URLCanonFileurl.cpp */; }; + 26E6C1F11609037300CA6AF4 /* URLCanonHost.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E6C1D11609037300CA6AF4 /* URLCanonHost.cpp */; }; + 26E6C1F21609037300CA6AF4 /* URLCanonICU.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E6C1D21609037300CA6AF4 /* URLCanonICU.cpp */; }; + 26E6C1F51609037300CA6AF4 /* URLCanonInternal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E6C1D51609037300CA6AF4 /* URLCanonInternal.cpp */; }; + 26E6C1F61609037300CA6AF4 /* URLCanonInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 26E6C1D61609037300CA6AF4 /* URLCanonInternal.h */; }; + 26E6C1F71609037300CA6AF4 /* URLCanonIP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E6C1D71609037300CA6AF4 /* URLCanonIP.cpp */; }; + 26E6C1F91609037300CA6AF4 /* URLCanonMailto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E6C1D91609037300CA6AF4 /* URLCanonMailto.cpp */; }; + 26E6C1FA1609037300CA6AF4 /* URLCanonPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E6C1DA1609037300CA6AF4 /* URLCanonPath.cpp */; }; + 26E6C1FB1609037300CA6AF4 /* URLCanonPathurl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E6C1DB1609037300CA6AF4 /* URLCanonPathurl.cpp */; }; + 26E6C1FC1609037300CA6AF4 /* URLCanonQuery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E6C1DC1609037300CA6AF4 /* URLCanonQuery.cpp */; }; + 26E6C1FD1609037300CA6AF4 /* URLCanonRelative.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E6C1DD1609037300CA6AF4 /* URLCanonRelative.cpp */; }; + 26E6C1FF1609037300CA6AF4 /* URLCanonStdURL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E6C1DF1609037300CA6AF4 /* URLCanonStdURL.cpp */; }; + 26E6C2011609037300CA6AF4 /* URLCanon.h in Headers */ = {isa = PBXBuildFile; fileRef = 26E6C1E11609037300CA6AF4 /* URLCanon.h */; }; + 26E6C2031609037300CA6AF4 /* URLFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 26E6C1E31609037300CA6AF4 /* URLFile.h */; }; + 26E6C2041609037300CA6AF4 /* URLParseFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E6C1E41609037300CA6AF4 /* URLParseFile.cpp */; }; + 26E6C2051609037300CA6AF4 /* URLParseInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 26E6C1E51609037300CA6AF4 /* URLParseInternal.h */; }; + 26E6C2071609037300CA6AF4 /* URLParse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E6C1E71609037300CA6AF4 /* URLParse.cpp */; }; + 26E6C2081609037300CA6AF4 /* URLParse.h in Headers */ = {isa = PBXBuildFile; fileRef = 26E6C1E81609037300CA6AF4 /* URLParse.h */; }; + 26E6C20A1609037300CA6AF4 /* URLUtilInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 26E6C1EA1609037300CA6AF4 /* URLUtilInternal.h */; }; + 26E6C20C1609037300CA6AF4 /* URLUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E6C1EC1609037300CA6AF4 /* URLUtil.cpp */; }; + 26E6C20D1609037300CA6AF4 /* URLUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 26E6C1ED1609037300CA6AF4 /* URLUtil.h */; }; 2C05385415BC819000F21B96 /* GregorianDateTime.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C05385315BC819000F21B96 /* GregorianDateTime.h */; }; 2CCD892A15C0390200285083 /* GregorianDateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2CCD892915C0390200285083 /* GregorianDateTime.cpp */; }; 4330F38F15745B0500AAFA8F /* URLString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4330F38E15745B0500AAFA8F /* URLString.cpp */; }; 4F0321BC156AA8D1006EBAF6 /* BitArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F0321BB156AA8D1006EBAF6 /* BitArray.h */; }; 4F1D115415FF11BE0026E908 /* MemoryInstrumentation.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F1D115315FF11BE0026E908 /* MemoryInstrumentation.h */; }; + 4FCB710A160A1A07008425EC /* MemoryInstrumentationVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FCB7109160A1A07008425EC /* MemoryInstrumentationVector.h */; }; 7E29C33E15FFD79B00516D61 /* ObjcRuntimeExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E29C33D15FFD79B00516D61 /* ObjcRuntimeExtras.h */; }; 8134013815B092FD001FF0B8 /* Base64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8134013615B092FD001FF0B8 /* Base64.cpp */; }; 8134013915B092FD001FF0B8 /* Base64.h in Headers */ = {isa = PBXBuildFile; fileRef = 8134013715B092FD001FF0B8 /* Base64.h */; }; @@ -237,10 +262,6 @@ A8A47474151A825B004123FF /* URLCharacterTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8A47366151A825B004123FF /* URLCharacterTypes.cpp */; }; A8A47475151A825B004123FF /* URLCharacterTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = A8A47367151A825B004123FF /* URLCharacterTypes.h */; }; A8A47476151A825B004123FF /* URLComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = A8A47368151A825B004123FF /* URLComponent.h */; }; - A8A47477151A825B004123FF /* URLEscape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8A47369151A825B004123FF /* URLEscape.cpp */; }; - A8A47478151A825B004123FF /* URLEscape.h in Headers */ = {isa = PBXBuildFile; fileRef = A8A4736A151A825B004123FF /* URLEscape.h */; }; - A8A47479151A825B004123FF /* URLParser.h in Headers */ = {isa = PBXBuildFile; fileRef = A8A4736B151A825B004123FF /* URLParser.h */; }; - A8A4747A151A825B004123FF /* URLQueryCanonicalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = A8A4736C151A825B004123FF /* URLQueryCanonicalizer.h */; }; A8A4747B151A825B004123FF /* URLSegments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8A4736D151A825B004123FF /* URLSegments.cpp */; }; A8A4747C151A825B004123FF /* URLSegments.h in Headers */ = {isa = PBXBuildFile; fileRef = A8A4736E151A825B004123FF /* URLSegments.h */; }; A8A4747D151A825B004123FF /* ValueCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = A8A4736F151A825B004123FF /* ValueCheck.h */; }; @@ -260,11 +281,36 @@ 143F611E1565F0F900DB514A /* RAMSize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RAMSize.h; sourceTree = "<group>"; }; 14F3B0F615E45E4600210069 /* SaturatedArithmetic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SaturatedArithmetic.h; sourceTree = "<group>"; }; 26147B0815DDCCDC00DDB907 /* IntegerToStringConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntegerToStringConversion.h; sourceTree = "<group>"; }; + 2661122D160FEAD40013F5C3 /* URLQueryCharsetConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLQueryCharsetConverter.h; sourceTree = "<group>"; }; + 26E6C1CE1609037300CA6AF4 /* URLCanonEtc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLCanonEtc.cpp; sourceTree = "<group>"; }; + 26E6C1CF1609037300CA6AF4 /* URLCanonFilesystemurl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLCanonFilesystemurl.cpp; sourceTree = "<group>"; }; + 26E6C1D01609037300CA6AF4 /* URLCanonFileurl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLCanonFileurl.cpp; sourceTree = "<group>"; }; + 26E6C1D11609037300CA6AF4 /* URLCanonHost.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLCanonHost.cpp; sourceTree = "<group>"; }; + 26E6C1D21609037300CA6AF4 /* URLCanonICU.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLCanonICU.cpp; sourceTree = "<group>"; }; + 26E6C1D51609037300CA6AF4 /* URLCanonInternal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLCanonInternal.cpp; sourceTree = "<group>"; }; + 26E6C1D61609037300CA6AF4 /* URLCanonInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLCanonInternal.h; sourceTree = "<group>"; }; + 26E6C1D71609037300CA6AF4 /* URLCanonIP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLCanonIP.cpp; sourceTree = "<group>"; }; + 26E6C1D91609037300CA6AF4 /* URLCanonMailto.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLCanonMailto.cpp; sourceTree = "<group>"; }; + 26E6C1DA1609037300CA6AF4 /* URLCanonPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLCanonPath.cpp; sourceTree = "<group>"; }; + 26E6C1DB1609037300CA6AF4 /* URLCanonPathurl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLCanonPathurl.cpp; sourceTree = "<group>"; }; + 26E6C1DC1609037300CA6AF4 /* URLCanonQuery.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLCanonQuery.cpp; sourceTree = "<group>"; }; + 26E6C1DD1609037300CA6AF4 /* URLCanonRelative.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLCanonRelative.cpp; sourceTree = "<group>"; }; + 26E6C1DF1609037300CA6AF4 /* URLCanonStdURL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLCanonStdURL.cpp; sourceTree = "<group>"; }; + 26E6C1E11609037300CA6AF4 /* URLCanon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLCanon.h; sourceTree = "<group>"; }; + 26E6C1E31609037300CA6AF4 /* URLFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLFile.h; sourceTree = "<group>"; }; + 26E6C1E41609037300CA6AF4 /* URLParseFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLParseFile.cpp; sourceTree = "<group>"; }; + 26E6C1E51609037300CA6AF4 /* URLParseInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLParseInternal.h; sourceTree = "<group>"; }; + 26E6C1E71609037300CA6AF4 /* URLParse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLParse.cpp; sourceTree = "<group>"; }; + 26E6C1E81609037300CA6AF4 /* URLParse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLParse.h; sourceTree = "<group>"; }; + 26E6C1EA1609037300CA6AF4 /* URLUtilInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLUtilInternal.h; sourceTree = "<group>"; }; + 26E6C1EC1609037300CA6AF4 /* URLUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLUtil.cpp; sourceTree = "<group>"; }; + 26E6C1ED1609037300CA6AF4 /* URLUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLUtil.h; sourceTree = "<group>"; }; 2C05385315BC819000F21B96 /* GregorianDateTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GregorianDateTime.h; sourceTree = "<group>"; }; 2CCD892915C0390200285083 /* GregorianDateTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GregorianDateTime.cpp; sourceTree = "<group>"; }; 4330F38E15745B0500AAFA8F /* URLString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLString.cpp; sourceTree = "<group>"; }; 4F0321BB156AA8D1006EBAF6 /* BitArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BitArray.h; sourceTree = "<group>"; }; 4F1D115315FF11BE0026E908 /* MemoryInstrumentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryInstrumentation.h; sourceTree = "<group>"; }; + 4FCB7109160A1A07008425EC /* MemoryInstrumentationVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryInstrumentationVector.h; sourceTree = "<group>"; }; 5D247B6214689B8600E78B76 /* libWTF.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libWTF.a; sourceTree = BUILT_PRODUCTS_DIR; }; 5D247B6E14689C4700E78B76 /* Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; }; 5D247B6F14689C4700E78B76 /* CompilerVersion.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = CompilerVersion.xcconfig; sourceTree = "<group>"; }; @@ -494,10 +540,6 @@ A8A47366151A825B004123FF /* URLCharacterTypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLCharacterTypes.cpp; sourceTree = "<group>"; }; A8A47367151A825B004123FF /* URLCharacterTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLCharacterTypes.h; sourceTree = "<group>"; }; A8A47368151A825B004123FF /* URLComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLComponent.h; sourceTree = "<group>"; }; - A8A47369151A825B004123FF /* URLEscape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLEscape.cpp; sourceTree = "<group>"; }; - A8A4736A151A825B004123FF /* URLEscape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLEscape.h; sourceTree = "<group>"; }; - A8A4736B151A825B004123FF /* URLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLParser.h; sourceTree = "<group>"; }; - A8A4736C151A825B004123FF /* URLQueryCanonicalizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLQueryCanonicalizer.h; sourceTree = "<group>"; }; A8A4736D151A825B004123FF /* URLSegments.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLSegments.cpp; sourceTree = "<group>"; }; A8A4736E151A825B004123FF /* URLSegments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLSegments.h; sourceTree = "<group>"; }; A8A4736F151A825B004123FF /* ValueCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueCheck.h; sourceTree = "<group>"; }; @@ -650,6 +692,7 @@ CD5497AA15857D0300B5BC30 /* MediaTime.cpp */, CD5497AB15857D0300B5BC30 /* MediaTime.h */, 4F1D115315FF11BE0026E908 /* MemoryInstrumentation.h */, + 4FCB7109160A1A07008425EC /* MemoryInstrumentationVector.h */, A8A472CC151A825B004123FF /* MessageQueue.h */, A8A472CD151A825B004123FF /* MetaAllocator.cpp */, A8A472CE151A825B004123FF /* MetaAllocator.h */, @@ -862,6 +905,8 @@ children = ( A8A47360151A825B004123FF /* ParsedURL.cpp */, A8A47361151A825B004123FF /* ParsedURL.h */, + A8A47365151A825B004123FF /* URLBuffer.h */, + 2661122D160FEAD40013F5C3 /* URLQueryCharsetConverter.h */, 4330F38E15745B0500AAFA8F /* URLString.cpp */, A8A47362151A825B004123FF /* URLString.h */, ); @@ -872,16 +917,34 @@ isa = PBXGroup; children = ( A8A47364151A825B004123FF /* RawURLBuffer.h */, - A8A47365151A825B004123FF /* URLBuffer.h */, + 26E6C1E11609037300CA6AF4 /* URLCanon.h */, + 26E6C1CE1609037300CA6AF4 /* URLCanonEtc.cpp */, + 26E6C1CF1609037300CA6AF4 /* URLCanonFilesystemurl.cpp */, + 26E6C1D01609037300CA6AF4 /* URLCanonFileurl.cpp */, + 26E6C1D11609037300CA6AF4 /* URLCanonHost.cpp */, + 26E6C1D21609037300CA6AF4 /* URLCanonICU.cpp */, + 26E6C1D51609037300CA6AF4 /* URLCanonInternal.cpp */, + 26E6C1D61609037300CA6AF4 /* URLCanonInternal.h */, + 26E6C1D71609037300CA6AF4 /* URLCanonIP.cpp */, + 26E6C1D91609037300CA6AF4 /* URLCanonMailto.cpp */, + 26E6C1DA1609037300CA6AF4 /* URLCanonPath.cpp */, + 26E6C1DB1609037300CA6AF4 /* URLCanonPathurl.cpp */, + 26E6C1DC1609037300CA6AF4 /* URLCanonQuery.cpp */, + 26E6C1DD1609037300CA6AF4 /* URLCanonRelative.cpp */, + 26E6C1DF1609037300CA6AF4 /* URLCanonStdURL.cpp */, A8A47366151A825B004123FF /* URLCharacterTypes.cpp */, A8A47367151A825B004123FF /* URLCharacterTypes.h */, A8A47368151A825B004123FF /* URLComponent.h */, - A8A47369151A825B004123FF /* URLEscape.cpp */, - A8A4736A151A825B004123FF /* URLEscape.h */, - A8A4736B151A825B004123FF /* URLParser.h */, - A8A4736C151A825B004123FF /* URLQueryCanonicalizer.h */, + 26E6C1E31609037300CA6AF4 /* URLFile.h */, + 26E6C1E71609037300CA6AF4 /* URLParse.cpp */, + 26E6C1E81609037300CA6AF4 /* URLParse.h */, + 26E6C1E41609037300CA6AF4 /* URLParseFile.cpp */, + 26E6C1E51609037300CA6AF4 /* URLParseInternal.h */, A8A4736D151A825B004123FF /* URLSegments.cpp */, A8A4736E151A825B004123FF /* URLSegments.h */, + 26E6C1EC1609037300CA6AF4 /* URLUtil.cpp */, + 26E6C1ED1609037300CA6AF4 /* URLUtil.h */, + 26E6C1EA1609037300CA6AF4 /* URLUtilInternal.h */, ); path = src; sourceTree = "<group>"; @@ -1062,9 +1125,6 @@ A8A47473151A825B004123FF /* URLBuffer.h in Headers */, A8A47475151A825B004123FF /* URLCharacterTypes.h in Headers */, A8A47476151A825B004123FF /* URLComponent.h in Headers */, - A8A47478151A825B004123FF /* URLEscape.h in Headers */, - A8A47479151A825B004123FF /* URLParser.h in Headers */, - A8A4747A151A825B004123FF /* URLQueryCanonicalizer.h in Headers */, A8A4747C151A825B004123FF /* URLSegments.h in Headers */, A8A47471151A825B004123FF /* URLString.h in Headers */, A8A4746A151A825B004123FF /* UTF8.h in Headers */, @@ -1076,6 +1136,15 @@ A8A47446151A825B004123FF /* WTFString.h in Headers */, A8A47487151A825B004123FF /* WTFThreadData.h in Headers */, 4F1D115415FF11BE0026E908 /* MemoryInstrumentation.h in Headers */, + 26E6C1F61609037300CA6AF4 /* URLCanonInternal.h in Headers */, + 26E6C2011609037300CA6AF4 /* URLCanon.h in Headers */, + 26E6C2031609037300CA6AF4 /* URLFile.h in Headers */, + 26E6C2051609037300CA6AF4 /* URLParseInternal.h in Headers */, + 26E6C2081609037300CA6AF4 /* URLParse.h in Headers */, + 2661122E160FEAD40013F5C3 /* URLQueryCharsetConverter.h in Headers */, + 26E6C20A1609037300CA6AF4 /* URLUtilInternal.h in Headers */, + 26E6C20D1609037300CA6AF4 /* URLUtil.h in Headers */, + 4FCB710A160A1A07008425EC /* MemoryInstrumentationVector.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1219,10 +1288,25 @@ A8A4744A151A825B004123FF /* Threading.cpp in Sources */, A8A4744E151A825B004123FF /* ThreadingPthreads.cpp in Sources */, A8A47458151A825B004123FF /* TypeTraits.cpp in Sources */, + 26E6C1EE1609037300CA6AF4 /* URLCanonEtc.cpp in Sources */, + 26E6C1EF1609037300CA6AF4 /* URLCanonFilesystemurl.cpp in Sources */, + 26E6C1F01609037300CA6AF4 /* URLCanonFileurl.cpp in Sources */, + 26E6C1F11609037300CA6AF4 /* URLCanonHost.cpp in Sources */, + 26E6C1F21609037300CA6AF4 /* URLCanonICU.cpp in Sources */, + 26E6C1F51609037300CA6AF4 /* URLCanonInternal.cpp in Sources */, + 26E6C1F71609037300CA6AF4 /* URLCanonIP.cpp in Sources */, + 26E6C1F91609037300CA6AF4 /* URLCanonMailto.cpp in Sources */, + 26E6C1FA1609037300CA6AF4 /* URLCanonPath.cpp in Sources */, + 26E6C1FB1609037300CA6AF4 /* URLCanonPathurl.cpp in Sources */, + 26E6C1FC1609037300CA6AF4 /* URLCanonQuery.cpp in Sources */, + 26E6C1FD1609037300CA6AF4 /* URLCanonRelative.cpp in Sources */, + 26E6C1FF1609037300CA6AF4 /* URLCanonStdURL.cpp in Sources */, A8A47474151A825B004123FF /* URLCharacterTypes.cpp in Sources */, - A8A47477151A825B004123FF /* URLEscape.cpp in Sources */, + 26E6C2041609037300CA6AF4 /* URLParseFile.cpp in Sources */, + 26E6C2071609037300CA6AF4 /* URLParse.cpp in Sources */, A8A4747B151A825B004123FF /* URLSegments.cpp in Sources */, 4330F38F15745B0500AAFA8F /* URLString.cpp in Sources */, + 26E6C20C1609037300CA6AF4 /* URLUtil.cpp in Sources */, A8A47469151A825B004123FF /* UTF8.cpp in Sources */, A8A47445151A825B004123FF /* WTFString.cpp in Sources */, A8A47486151A825B004123FF /* WTFThreadData.cpp in Sources */, diff --git a/Source/WTF/wtf/MemoryInstrumentation.h b/Source/WTF/wtf/MemoryInstrumentation.h index 131af8497..b1f2e294a 100644 --- a/Source/WTF/wtf/MemoryInstrumentation.h +++ b/Source/WTF/wtf/MemoryInstrumentation.h @@ -81,6 +81,8 @@ private: size_t m_objectSize; }; +template<typename T> void reportMemoryUsage(const T* const&, MemoryObjectInfo*); + class MemoryInstrumentation { public: virtual ~MemoryInstrumentation() { } @@ -107,6 +109,7 @@ private: virtual void processDeferredInstrumentedPointers() = 0; friend class MemoryClassInfo; + template<typename T> friend void reportMemoryUsage(const T* const&, MemoryObjectInfo*); template<typename T> static void selectInstrumentationMethod(const T* const& object, MemoryObjectInfo* memoryObjectInfo) { @@ -148,7 +151,6 @@ private: template<typename MapType> void addInstrumentedMapEntries(const MapType&, MemoryObjectType); template<typename MapType> void addInstrumentedMapValues(const MapType&, MemoryObjectType); template<typename ListHashSetType> void addListHashSet(const ListHashSetType&, MemoryObjectType, bool contentOnly = false); - template<typename VectorType> void addVector(const VectorType&, MemoryObjectType, bool contentOnly = false); void addRawBuffer(const void* const& buffer, MemoryObjectType ownerObjectType, size_t size) { if (!buffer || visited(buffer)) @@ -194,14 +196,9 @@ public: template<typename HashSetType> void addHashSet(const HashSetType& set) { m_memoryInstrumentation->addHashSet(set, m_objectType, true); } template<typename HashSetType> void addHashCountedSet(const HashSetType& set) { m_memoryInstrumentation->addHashSet(set, m_objectType, true); } template<typename HashSetType> void addInstrumentedHashSet(const HashSetType& set) { m_memoryInstrumentation->addInstrumentedCollection(set, m_objectType, true); } - template<typename VectorType> void addInstrumentedVector(const VectorType& vector) { m_memoryInstrumentation->addInstrumentedCollection(vector, m_objectType, true); } - template<typename VectorType> void addInstrumentedVectorPtr(const OwnPtr<VectorType>& vector) { m_memoryInstrumentation->addInstrumentedCollection(*vector, m_objectType, false); } - template<typename VectorType> void addInstrumentedVectorPtr(const VectorType* const& vector) { m_memoryInstrumentation->addInstrumentedCollection(*vector, m_objectType, false); } template<typename MapType> void addInstrumentedMapEntries(const MapType& map) { m_memoryInstrumentation->addInstrumentedMapEntries(map, m_objectType); } template<typename MapType> void addInstrumentedMapValues(const MapType& map) { m_memoryInstrumentation->addInstrumentedMapValues(map, m_objectType); } template<typename ListHashSetType> void addListHashSet(const ListHashSetType& set) { m_memoryInstrumentation->addListHashSet(set, m_objectType, true); } - template<typename VectorType> void addVector(const VectorType& vector) { m_memoryInstrumentation->addVector(vector, m_objectType, true); } - template<typename VectorType> void addVectorPtr(const VectorType* const vector) { m_memoryInstrumentation->addVector(*vector, m_objectType, false); } void addRawBuffer(const void* const& buffer, size_t size) { m_memoryInstrumentation->addRawBuffer(buffer, m_objectType, size); } void addWeakPointer(void*) { } @@ -213,11 +210,17 @@ private: }; template<typename T> +void reportMemoryUsage(const T* const& object, MemoryObjectInfo* memoryObjectInfo) +{ + MemoryInstrumentation::selectInstrumentationMethod<T>(object, memoryObjectInfo); +} + +template<typename T> void MemoryInstrumentation::addObjectImpl(const T* const& object, MemoryObjectType ownerObjectType, MemoryOwningType owningType) { if (owningType == byReference) { MemoryObjectInfo memoryObjectInfo(this, ownerObjectType); - selectInstrumentationMethod<T>(object, &memoryObjectInfo); + reportMemoryUsage(object, &memoryObjectInfo); } else { if (!object || visited(object)) return; @@ -295,14 +298,6 @@ void MemoryInstrumentation::addListHashSet(const ListHashSetType& hashSet, Memor countObjectSize(ownerObjectType, size); } -template<typename VectorType> -void MemoryInstrumentation::addVector(const VectorType& vector, MemoryObjectType ownerObjectType, bool contentOnly) -{ - if (!vector.data() || visited(vector.data())) - return; - countObjectSize(ownerObjectType, calculateContainerSize(vector, contentOnly)); -} - template<typename Container> size_t MemoryInstrumentation::calculateContainerSize(const Container& container, bool contentOnly) { @@ -313,10 +308,14 @@ template<typename T> void MemoryInstrumentation::InstrumentedPointer<T>::process(MemoryInstrumentation* memoryInstrumentation) { MemoryObjectInfo memoryObjectInfo(memoryInstrumentation, m_ownerObjectType); - selectInstrumentationMethod<T>(m_pointer, &memoryObjectInfo); + reportMemoryUsage(m_pointer, &memoryObjectInfo); memoryInstrumentation->countObjectSize(memoryObjectInfo.objectType(), memoryObjectInfo.objectSize()); } +// Link time guard for vector memory instrumentation. +template<typename T, size_t inlineCapacity> class Vector; +template<typename T, size_t inlineCapacity> void reportMemoryUsage(const Vector<T, inlineCapacity>* const&, MemoryObjectInfo*); + } // namespace WTF #endif // !defined(MemoryInstrumentation_h) diff --git a/Source/WTF/wtf/MemoryInstrumentationVector.h b/Source/WTF/wtf/MemoryInstrumentationVector.h new file mode 100644 index 000000000..fea5cb746 --- /dev/null +++ b/Source/WTF/wtf/MemoryInstrumentationVector.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2012 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 MemoryInstrumentationVector_h +#define MemoryInstrumentationVector_h + +#include <wtf/MemoryInstrumentation.h> +#include <wtf/Vector.h> + +namespace WTF { + +template<typename T, size_t inlineCapacity> +void instrumentVectorValues(MemoryClassInfo& info, const Vector<T, inlineCapacity>* const& vector) +{ + for (size_t i = 0; i < vector->size(); ++i) + info.addMember(vector->at(i)); +} + +template<size_t inlineCapacity> void instrumentVectorValues(MemoryClassInfo&, const Vector<int, inlineCapacity>* const&) { } +template<size_t inlineCapacity> void instrumentVectorValues(MemoryClassInfo&, const Vector<char, inlineCapacity>* const&) { } +template<size_t inlineCapacity> void instrumentVectorValues(MemoryClassInfo&, const Vector<char*, inlineCapacity>* const&) { } + +template<typename T, size_t inlineCapacity> +void reportMemoryUsage(const Vector<T, inlineCapacity>* const& vector, MemoryObjectInfo* memoryObjectInfo) +{ + MemoryClassInfo info(memoryObjectInfo, vector); + if (inlineCapacity < vector->capacity()) + info.addRawBuffer(vector->data(), vector->capacity() * sizeof(T)); + instrumentVectorValues(info, vector); +} + +} + +#endif // !defined(MemoryInstrumentationVector_h) diff --git a/Source/WTF/wtf/OSAllocatorPosix.cpp b/Source/WTF/wtf/OSAllocatorPosix.cpp index f21f16aa7..a2f6a79bd 100644 --- a/Source/WTF/wtf/OSAllocatorPosix.cpp +++ b/Source/WTF/wtf/OSAllocatorPosix.cpp @@ -113,11 +113,11 @@ void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bo result = mmap(result, bytes, protection, flags, fd, 0); if (result == MAP_FAILED) { - #if ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT) +#if ENABLE(LLINT) if (executable) result = 0; else - #endif +#endif CRASH(); } if (result && includesGuardPages) { diff --git a/Source/WTF/wtf/Platform.h b/Source/WTF/wtf/Platform.h index 0be4bb07d..9d032dd97 100644 --- a/Source/WTF/wtf/Platform.h +++ b/Source/WTF/wtf/Platform.h @@ -604,11 +604,9 @@ #define WTF_USE_PTHREADS 1 #if PLATFORM(IOS_SIMULATOR) - #define ENABLE_CLASSIC_INTERPRETER 1 #define ENABLE_JIT 0 #define ENABLE_YARR_JIT 0 #else - #define ENABLE_CLASSIC_INTERPRETER 0 #define ENABLE_JIT 1 #define ENABLE_LLINT 1 #define ENABLE_YARR_JIT 1 @@ -641,7 +639,9 @@ #if PLATFORM(WX) #if !CPU(PPC) +#if !defined(ENABLE_ASSEMBLER) #define ENABLE_ASSEMBLER 1 +#endif #define ENABLE_JIT 1 #endif #define ENABLE_GLOBAL_FASTMALLOC_NEW 0 @@ -953,13 +953,8 @@ #define ENABLE_WRITE_BARRIER_PROFILING 0 #endif -/* Ensure that either the JIT or the interpreter has been enabled. */ -#if !defined(ENABLE_CLASSIC_INTERPRETER) && !ENABLE(JIT) && !ENABLE(LLINT) -#define ENABLE_CLASSIC_INTERPRETER 1 -#endif - /* If the jit and classic interpreter is not available, enable the LLInt C Loop: */ -#if !ENABLE(JIT) && !ENABLE(CLASSIC_INTERPRETER) +#if !ENABLE(JIT) #define ENABLE_LLINT 1 #define ENABLE_LLINT_C_LOOP 1 #define ENABLE_DFG_JIT 0 @@ -967,14 +962,9 @@ /* Do a sanity check to make sure that we at least have one execution engine in use: */ -#if !(ENABLE(JIT) || ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) +#if !(ENABLE(JIT) || ENABLE(LLINT)) #error You have to have at least one execution model enabled to build JSC #endif -/* Do a sanity check to make sure that we don't have both the classic interpreter - and the llint C loop in use at the same time: */ -#if ENABLE(CLASSIC_INTERPRETER) && ENABLE(LLINT_C_LOOP) -#error You cannot build both the classic interpreter and the llint C loop together -#endif /* Configure the JIT */ #if CPU(X86) && COMPILER(MSVC) @@ -989,12 +979,9 @@ #if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(4, 0, 0, 0) && defined(__GNUC__)) #define HAVE_COMPUTED_GOTO 1 #endif -#if HAVE(COMPUTED_GOTO) && ENABLE(CLASSIC_INTERPRETER) -#define ENABLE_COMPUTED_GOTO_CLASSIC_INTERPRETER 1 -#endif /* Determine if we need to enable Computed Goto Opcodes or not: */ -#if (HAVE(COMPUTED_GOTO) && ENABLE(LLINT)) || ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) +#if HAVE(COMPUTED_GOTO) && ENABLE(LLINT) #define ENABLE_COMPUTED_GOTO_OPCODES 1 #endif @@ -1009,9 +996,16 @@ #define ENABLE_YARR_JIT_DEBUG 0 #endif +/* If either the JIT or the RegExp JIT is enabled, then the Assembler must be + enabled as well: */ #if ENABLE(JIT) || ENABLE(YARR_JIT) +#if defined(ENABLE_ASSEMBLER) && !ENABLE_ASSEMBLER +#error "Cannot enable the JIT or RegExp JIT without enabling the Assembler" +#else +#undef ENABLE_ASSEMBLER #define ENABLE_ASSEMBLER 1 #endif +#endif /* Pick which allocator to use; we only need an executable allocator if the assembler is compiled in. On x86-64 we use a single fixed mmap, on other platforms we mmap on demand. */ @@ -1181,10 +1175,6 @@ #define WTF_USE_ZLIB 1 #endif -#if PLATFORM(GTK) -#define WTF_DEPRECATED_STRING_OPERATORS -#endif - #if PLATFORM(QT) #include <qglobal.h> #if defined(QT_OPENGL_ES_2) && !defined(WTF_USE_OPENGL_ES_2) diff --git a/Source/WTF/wtf/gobject/GTypedefs.h b/Source/WTF/wtf/gobject/GTypedefs.h index 2efc07233..77858d5e9 100644 --- a/Source/WTF/wtf/gobject/GTypedefs.h +++ b/Source/WTF/wtf/gobject/GTypedefs.h @@ -71,6 +71,11 @@ typedef struct _cairo_surface cairo_surface_t; typedef struct _cairo_rectangle_int cairo_rectangle_int_t; #endif +#if USE(CLUTTER) +typedef struct _ClutterActor ClutterActor; +typedef struct _GraphicsLayerActor GraphicsLayerActor; +#endif + #if PLATFORM(GTK) typedef struct _GtkAction GtkAction; typedef struct _GtkAdjustment GtkAdjustment; diff --git a/Source/WTF/wtf/text/WTFString.h b/Source/WTF/wtf/text/WTFString.h index c232c67ee..ef8f8da06 100644 --- a/Source/WTF/wtf/text/WTFString.h +++ b/Source/WTF/wtf/text/WTFString.h @@ -467,10 +467,6 @@ QDataStream& operator<<(QDataStream& stream, const String& str); QDataStream& operator>>(QDataStream& stream, String& str); #endif -#ifdef WTF_DEPRECATED_STRING_OPERATORS -inline String& operator+=(String& a, const String& b) { a.append(b); return a; } -#endif - inline bool operator==(const String& a, const String& b) { return equal(a.impl(), b.impl()); } inline bool operator==(const String& a, const LChar* b) { return equal(a.impl(), b); } inline bool operator==(const String& a, const char* b) { return equal(a.impl(), reinterpret_cast<const LChar*>(b)); } diff --git a/Source/WTF/wtf/url/api/ParsedURL.cpp b/Source/WTF/wtf/url/api/ParsedURL.cpp index 0b15fcbca..c700dd59b 100644 --- a/Source/WTF/wtf/url/api/ParsedURL.cpp +++ b/Source/WTF/wtf/url/api/ParsedURL.cpp @@ -33,60 +33,96 @@ #include <wtf/MemoryInstrumentation.h> #include <wtf/RawURLBuffer.h> #include <wtf/URLComponent.h> -#include <wtf/URLParser.h> +#include <wtf/URLUtil.h> +#include <wtf/text/CString.h> namespace WTF { -ParsedURL::ParsedURL(const String& urlString) +ParsedURL::ParsedURL(const String& urlString, ParsedURLStringTag) { - if (urlString.isEmpty()) { - m_spec = URLString(); + unsigned urlStringLength = urlString.length(); + if (!urlStringLength) + return; // FIXME: we should ASSERT on this, but people use KURL incorrectly with ParsedURLStringTag :(. + + RawURLBuffer<char> outputBuffer; + String base; + const CString& baseStr = base.utf8(); + bool isValid = false; + URLSegments baseSegments; + + // FIXME: we should take shortcuts here! We do not have to resolve the relative part. + if (urlString.is8Bit()) + isValid = URLUtilities::resolveRelative(baseStr.data(), baseSegments, + reinterpret_cast<const char*>(urlString.characters8()), urlStringLength, + /* charsetConverter */ 0, + outputBuffer, &m_segments); + else + isValid = URLUtilities::resolveRelative(baseStr.data(), baseSegments, + urlString.characters16(), urlStringLength, + /* charsetConverter */ 0, + outputBuffer, &m_segments); + + // FIXME: we should ASSERT on isValid, but people use KURL incorrectly with ParsedURLStringTag :(. + if (isValid) + m_spec = URLString(String(outputBuffer.data(), outputBuffer.length())); +} + +ParsedURL::ParsedURL(const String& urlString, URLQueryCharsetConverter* queryCharsetConverter) +{ + unsigned urlStringLength = urlString.length(); + if (!urlStringLength) return; - } - // FIXME: handle invalid urlString. - m_spec = URLString(urlString); + RawURLBuffer<char> outputBuffer; + String base; + const CString& baseStr = base.utf8(); + bool isValid = false; + URLSegments baseSegments; + + // FIXME: we should take shortcuts here! We do not have to resolve the relative part. if (urlString.is8Bit()) - URLParser<LChar>::parseStandardURL(urlString.characters8(), urlString.length(), m_segments); + isValid = URLUtilities::resolveRelative(baseStr.data(), baseSegments, + reinterpret_cast<const char*>(urlString.characters8()), urlStringLength, + queryCharsetConverter, + outputBuffer, &m_segments); else - URLParser<UChar>::parseStandardURL(urlString.characters16(), urlString.length(), m_segments); + isValid = URLUtilities::resolveRelative(baseStr.data(), baseSegments, + urlString.characters16(), urlStringLength, + queryCharsetConverter, + outputBuffer, &m_segments); + + if (isValid) + m_spec = URLString(String(outputBuffer.data(), outputBuffer.length())); } -ParsedURL::ParsedURL(const ParsedURL& base, const String& relative) +ParsedURL::ParsedURL(const ParsedURL& base, const String& relative, URLQueryCharsetConverter* queryCharsetConverter) { if (!base.isValid()) return; - if (relative.isEmpty()) { + unsigned relativeLength = relative.length(); + if (!relativeLength) { *this = base.withoutFragment(); return; } - // FIXME: handle invalid URLs. - const String& baseString = base.m_spec.string(); - RawURLBuffer<char, 1024> outputBuffer; - if (relative.is8Bit()) { - if (baseString.is8Bit()) { - URLParser<LChar, LChar>::parseURLWithBase(relative.characters8(), relative.length(), - baseString.characters8(), baseString.length(), base.m_segments, - outputBuffer, m_segments); - } else { - URLParser<LChar, UChar>::parseURLWithBase(relative.characters8(), relative.length(), - baseString.characters16(), baseString.length(), base.m_segments, - outputBuffer, m_segments); - } - } else { - if (baseString.is8Bit()) { - URLParser<UChar, LChar>::parseURLWithBase(relative.characters16(), relative.length(), - baseString.characters8(), baseString.length(), base.m_segments, - outputBuffer, m_segments); - } else { - URLParser<UChar, UChar>::parseURLWithBase(relative.characters16(), relative.length(), - baseString.characters16(), baseString.length(), base.m_segments, - outputBuffer, m_segments); - } - } - m_spec = URLString(String(outputBuffer.data(), outputBuffer.length())); + RawURLBuffer<char> outputBuffer; + const CString& baseStr = base.m_spec.m_string.utf8(); + bool isValid = false; + + if (relative.is8Bit()) + isValid = URLUtilities::resolveRelative(baseStr.data(), base.m_segments, + reinterpret_cast<const char*>(relative.characters8()), relativeLength, + queryCharsetConverter, + outputBuffer, &m_segments); + else + isValid = URLUtilities::resolveRelative(baseStr.data(), base.m_segments, + relative.characters16(), relativeLength, + queryCharsetConverter, + outputBuffer, &m_segments); + + if (isValid) + m_spec = URLString(String(outputBuffer.data(), outputBuffer.length())); } ParsedURL ParsedURL::isolatedCopy() const @@ -171,7 +207,9 @@ String ParsedURL::segment(const URLComponent& component) const return String(); String segment = m_spec.string().substring(component.begin(), component.length()); - ASSERT_WITH_MESSAGE(!segment.isEmpty(), "A valid URL component should not be empty."); + + // FIXME: GoogleURL create empty segments. This happen for the fragment for the test fast/url/segments.html + // ASSERT_WITH_MESSAGE(!segment.isEmpty(), "A valid URL component should not be empty."); return segment; } diff --git a/Source/WTF/wtf/url/api/ParsedURL.h b/Source/WTF/wtf/url/api/ParsedURL.h index 0603cf116..79a72dd2d 100644 --- a/Source/WTF/wtf/url/api/ParsedURL.h +++ b/Source/WTF/wtf/url/api/ParsedURL.h @@ -35,17 +35,22 @@ namespace WTF { class URLComponent; +class URLQueryCharsetConverter; // ParsedURL represents a valid URL decomposed by components. class ParsedURL { public: + enum ParsedURLStringTag { ParsedURLString }; + ParsedURL() { }; - WTF_EXPORT_PRIVATE explicit ParsedURL(const String&); - WTF_EXPORT_PRIVATE explicit ParsedURL(const ParsedURL& base, const String& relative); + WTF_EXPORT_PRIVATE explicit ParsedURL(const String&, ParsedURLStringTag); + + WTF_EXPORT_PRIVATE explicit ParsedURL(const String&, URLQueryCharsetConverter*); + WTF_EXPORT_PRIVATE explicit ParsedURL(const ParsedURL& base, const String& relative, URLQueryCharsetConverter*); WTF_EXPORT_PRIVATE ParsedURL isolatedCopy() const; - bool isValid() const { return !m_spec.string().isEmpty(); } + bool isValid() const { return !m_spec.string().isNull(); } // Return a URL component or a null String if the component is undefined for the URL. WTF_EXPORT_PRIVATE String scheme() const; diff --git a/Source/WTF/wtf/url/src/URLBuffer.h b/Source/WTF/wtf/url/api/URLBuffer.h index 84a4f85c2..6eccd04fa 100644 --- a/Source/WTF/wtf/url/src/URLBuffer.h +++ b/Source/WTF/wtf/url/api/URLBuffer.h @@ -1,30 +1,32 @@ -// 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. +/* + * 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 URLBuffer_h #define URLBuffer_h diff --git a/Source/WTF/wtf/url/api/URLQueryCharsetConverter.h b/Source/WTF/wtf/url/api/URLQueryCharsetConverter.h new file mode 100644 index 000000000..5771a42e4 --- /dev/null +++ b/Source/WTF/wtf/url/api/URLQueryCharsetConverter.h @@ -0,0 +1,54 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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. + */ + +#ifndef URLQueryCharsetConverter_h +#define URLQueryCharsetConverter_h + +#include <wtf/unicode/Unicode.h> + +#if USE(WTFURL) + +namespace WTF { + +template<typename CharacterType> class URLBuffer; + +class URLQueryCharsetConverter { +public: + URLQueryCharsetConverter() { } + virtual ~URLQueryCharsetConverter() { } + virtual void convertFromUTF16(const UChar* input, unsigned inputLength, URLBuffer<char>& output) = 0; +}; + +} // namespace WTF + +#endif // USE(WTFURL) + +#endif // URLQueryCharsetConverter_h diff --git a/Source/WTF/wtf/url/src/RawURLBuffer.h b/Source/WTF/wtf/url/src/RawURLBuffer.h index 59a7f18af..e6f238c29 100644 --- a/Source/WTF/wtf/url/src/RawURLBuffer.h +++ b/Source/WTF/wtf/url/src/RawURLBuffer.h @@ -1,30 +1,32 @@ -// 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. +/* + * 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 RawURLBuffer_h #define RawURLBuffer_h @@ -32,6 +34,7 @@ #if USE(WTFURL) #include "URLBuffer.h" +#include <string.h> namespace WTF { diff --git a/Source/WTF/wtf/url/src/URLCanon.h b/Source/WTF/wtf/url/src/URLCanon.h new file mode 100644 index 000000000..d1e2b1caa --- /dev/null +++ b/Source/WTF/wtf/url/src/URLCanon.h @@ -0,0 +1,617 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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. + */ +#ifndef URLCanon_h +#define URLCanon_h + +#include "URLBuffer.h" +#include "URLParse.h" +#include <stdlib.h> +#include <wtf/unicode/Unicode.h> + +#if USE(WTFURL) + +namespace WTF { + +class URLQueryCharsetConverter; + +namespace URLCanonicalizer { + +// Whitespace ----------------------------------------------------------------- + +// Searches for whitespace that should be removed from the middle of URLs, and +// removes it. Removed whitespace are tabs and newlines, but NOT spaces. Spaces +// are preserved, which is what most browsers do. A pointer to the output will +// be returned, and the length of that output will be in |outputLength|. +// +// This should be called before parsing if whitespace removal is desired (which +// it normally is when you are canonicalizing). +// +// If no whitespace is removed, this function will not use the buffer and will +// return a pointer to the input, to avoid the extra copy. If modification is +// required, the given |buffer| will be used and the returned pointer will +// point to the beginning of the buffer. +// +// Therefore, callers should not use the buffer, since it may actuall be empty, +// use the computed pointer and |outputLength| instead. +const char* removeURLWhitespace(const char* input, int inputLength, URLBuffer<char>&, int& outputLength); +const UChar* removeURLWhitespace(const UChar* input, int inputLength, URLBuffer<UChar>&, int& outputLength); + +// IDN ------------------------------------------------------------------------ + +// Converts the Unicode input representing a hostname to ASCII using IDN rules. +// The output must fall in the ASCII range, but will be encoded in UTF-16. +// +// On success, the output will be filled with the ASCII host name and it will +// return true. Unlike most other canonicalization functions, this assumes that +// the output is empty. The beginning of the host will be at offset 0, and +// the length of the output will be set to the length of the new host name. +// +// On error, returns false. The output in this case is undefined. +bool IDNToASCII(const UChar* src, int sourceLength, URLBuffer<UChar>& output); + +// Piece-by-piece canonicalizers ---------------------------------------------- +// +// These individual canonicalizers append the canonicalized versions of the +// corresponding URL component to the given std::string. The spec and the +// previously-identified range of that component are the input. The range of +// the canonicalized component will be written to the output component. +// +// These functions all append to the output so they can be chained. Make sure +// the output is empty when you start. +// +// These functions returns boolean values indicating success. On failure, they +// will attempt to write something reasonable to the output so that, if +// displayed to the user, they will recognise it as something that's messed up. +// Nothing more should ever be done with these invalid URLs, however. + +// Scheme: Appends the scheme and colon to the URL. The output component will +// indicate the range of characters up to but not including the colon. +// +// Canonical URLs always have a scheme. If the scheme is not present in the +// input, this will just write the colon to indicate an empty scheme. Does not +// append slashes which will be needed before any authority components for most +// URLs. +// +// The 8-bit version requires UTF-8 encoding. +bool canonicalizeScheme(const char* spec, const URLComponent& scheme, URLBuffer<char>&, URLComponent& ouputScheme); +bool canonicalizeScheme(const UChar* spec, const URLComponent& scheme, URLBuffer<char>&, URLComponent& ouputScheme); + +// User info: username/password. If present, this will add the delimiters so +// the output will be "<username>:<password>@" or "<username>@". Empty +// username/password pairs, or empty passwords, will get converted to +// nonexistant in the canonical version. +// +// The components for the username and password refer to ranges in the +// respective source strings. Usually, these will be the same string, which +// is legal as long as the two components don't overlap. +// +// The 8-bit version requires UTF-8 encoding. +bool canonicalizeUserInfo(const char* usernameSource, const URLComponent& username, const char* passwordSource, const URLComponent& password, + URLBuffer<char>&, URLComponent& outputUsername, URLComponent& outputPassword); +bool canonicalizeUserInfo(const UChar* usernameSource, const URLComponent& username, const UChar* passwordSource, const URLComponent& password, + URLBuffer<char>&, URLComponent& outputUsername, URLComponent& outputPassword); + + +// This structure holds detailed state exported from the IP/Host canonicalizers. +// Additional fields may be added as callers require them. +struct CanonHostInfo { + CanonHostInfo() + : family(NEUTRAL) + , ipv4ComponentsCount(0) + , ouputHost() + { + } + + // Convenience function to test if family is an IP address. + bool IsIPAddress() const { return family == IPV4 || family == IPV6; } + + // This field summarizes how the input was classified by the canonicalizer. + enum Family { + // - Doesn't resemble an IP address. As far as the IP + // canonicalizer is concerned, it should be treated as a + // hostname. + NEUTRAL, + + // - Almost an IP, but was not canonicalized. This could be an + // IPv4 address where truncation occurred, or something + // containing the special characters :[] which did not parse + // as an IPv6 address. Never attempt to connect to this + // address, because it might actually succeed! + BROKEN, + + IPV4, // - Successfully canonicalized as an IPv4 address. + IPV6, // - Successfully canonicalized as an IPv6 address. + }; + Family family; + + // If |family| is IPV4, then this is the number of nonempty dot-separated + // components in the input text, from 1 to 4. If |family| is not IPV4, + // this value is undefined. + int ipv4ComponentsCount; + + // Location of host within the canonicalized output. + // canonicalizeIPAddress() only sets this field if |family| is IPV4 or IPV6. + URLComponent ouputHost; + + // |address| contains the parsed IP Address (if any) in its first + // AddressLength() bytes, in network order. If IsIPAddress() is false + // AddressLength() will return zero and the content of |address| is undefined. + unsigned char address[16]; + + // Convenience function to calculate the length of an IP address corresponding + // to the current IP version in |family|, if any. For use with |address|. + int AddressLength() const + { + return family == IPV4 ? 4 : (family == IPV6 ? 16 : 0); + } +}; + +// Host. +// +// The 8-bit version requires UTF-8 encoding. Use this version when you only +// need to know whether canonicalization succeeded. +bool canonicalizeHost(const char* spec, const URLComponent& host, URLBuffer<char>&, URLComponent& ouputHost); +bool canonicalizeHost(const UChar* spec, const URLComponent& host, URLBuffer<char>&, URLComponent& ouputHost); + +// IP addresses. +// +// Tries to interpret the given host name as an IPv4 or IPv6 address. If it is +// an IP address, it will canonicalize it as such, appending it to |output|. +// Additional status information is returned via the |*hostInfo| parameter. +// See the definition of CanonHostInfo above for details. +// +// This is called AUTOMATICALLY from the host canonicalizer, which ensures that +// the input is unescaped and name-prepped, etc. It should not normally be +// necessary or wise to call this directly. +void canonicalizeIPAddress(const char* spec, const URLComponent& host, URLBuffer<char>&, CanonHostInfo&); +void canonicalizeIPAddress(const UChar* spec, const URLComponent& host, URLBuffer<char>&, CanonHostInfo&); + +// Port: this function will add the colon for the port if a port is present. +// The caller can pass URLParser::PORT_UNSPECIFIED as the +// defaultPortForScheme argument if there is no default port. +// +// The 8-bit version requires UTF-8 encoding. +bool canonicalizePort(const char* spec, const URLComponent& port, int defaultPortForScheme, URLBuffer<char>&, URLComponent& ouputPort); +bool canonicalizePort(const UChar* spec, const URLComponent& port, int defaultPortForScheme, URLBuffer<char>&, URLComponent& ouputPort); + +// Returns the default port for the given canonical scheme, or PORT_UNSPECIFIED +// if the scheme is unknown. +int defaultPortForScheme(const char* scheme, int schemeLength); + +// Path. If the input does not begin in a slash (including if the input is +// empty), we'll prepend a slash to the path to make it canonical. +// +// The 8-bit version assumes UTF-8 encoding, but does not verify the validity +// of the UTF-8 (i.e., you can have invalid UTF-8 sequences, invalid +// characters, etc.). Normally, URLs will come in as UTF-16, so this isn't +// an issue. Somebody giving us an 8-bit path is responsible for generating +// the path that the server expects (we'll escape high-bit characters), so +// if something is invalid, it's their problem. +bool CanonicalizePath(const char* spec, const URLComponent& path, URLBuffer<char>&, URLComponent* outputPath); +bool CanonicalizePath(const UChar* spec, const URLComponent& path, URLBuffer<char>&, URLComponent* outputPath); + +// Canonicalizes the input as a file path. This is like CanonicalizePath except +// that it also handles Windows drive specs. For example, the path can begin +// with "c|\" and it will get properly canonicalized to "C:/". +// The string will be appended to |output| and |outputPath| will be updated. +// +// The 8-bit version requires UTF-8 encoding. +bool FileCanonicalizePath(const char* spec, const URLComponent& path, URLBuffer<char>&, URLComponent* outputPath); +bool FileCanonicalizePath(const UChar* spec, const URLComponent& path, URLBuffer<char>&, URLComponent* outputPath); + +// Query: Prepends the ? if needed. +// +// The 8-bit version requires the input to be UTF-8 encoding. Incorrectly +// encoded characters (in UTF-8 or UTF-16) will be replaced with the Unicode +// "invalid character." This function can not fail, we always just try to do +// our best for crazy input here since web pages can set it themselves. +// +// This will convert the given input into the output encoding that the given +// character set converter object provides. The converter will only be called +// if necessary, for ASCII input, no conversions are necessary. +// +// The converter can be null. In this case, the output encoding will be UTF-8. +void CanonicalizeQuery(const char* spec, const URLComponent& query, URLQueryCharsetConverter*, URLBuffer<char>&, URLComponent* outputQuery); +void CanonicalizeQuery(const UChar* spec, const URLComponent& query, URLQueryCharsetConverter*, URLBuffer<char>&, URLComponent* outputQuery); + +// Ref: Prepends the # if needed. The output will be UTF-8 (this is the only +// canonicalizer that does not produce ASCII output). The output is +// guaranteed to be valid UTF-8. +// +// This function will not fail. If the input is invalid UTF-8/UTF-16, we'll use +// the "Unicode replacement character" for the confusing bits and copy the rest. +void canonicalizeFragment(const char* spec, const URLComponent& path, URLBuffer<char>&, URLComponent& outputFragment); +void canonicalizeFragment(const UChar* spec, const URLComponent& path, URLBuffer<char>&, URLComponent& outputFragment); + +// Full canonicalizer --------------------------------------------------------- +// +// These functions replace any string contents, rather than append as above. +// See the above piece-by-piece functions for information specific to +// canonicalizing individual components. +// +// The output will be ASCII except the reference fragment, which may be UTF-8. +// +// The 8-bit versions require UTF-8 encoding. + +// Use for standard URLs with authorities and paths. +bool CanonicalizeStandardURL(const char* spec, int specLength, const URLSegments& parsed, URLQueryCharsetConverter* queryConverter, + URLBuffer<char>&, URLSegments* outputParsed); +bool CanonicalizeStandardURL(const UChar* spec, int specLength, const URLSegments& parsed, URLQueryCharsetConverter* queryConverter, + URLBuffer<char>&, URLSegments* outputParsed); + +// Use for file URLs. +bool CanonicalizeFileURL(const char* spec, int specLength, const URLSegments& parsed, URLQueryCharsetConverter* queryConverter, + URLBuffer<char>&, URLSegments* outputParsed); +bool CanonicalizeFileURL(const UChar* spec, int specLength, const URLSegments& parsed, URLQueryCharsetConverter* queryConverter, + URLBuffer<char>&, URLSegments* outputParsed); + +// Use for filesystem URLs. +bool canonicalizeFileSystemURL(const char* spec, const URLSegments& parsed, URLQueryCharsetConverter* queryConverter, + URLBuffer<char>&, URLSegments& outputParsed); +bool canonicalizeFileSystemURL(const UChar* spec, const URLSegments& parsed, URLQueryCharsetConverter* queryConverter, + URLBuffer<char>&, URLSegments& outputParsed); + +// Use for path URLs such as javascript. This does not modify the path in any +// way, for example, by escaping it. +bool canonicalizePathURL(const char* spec, const URLSegments& parsed, URLBuffer<char>& output, URLSegments& ouputParsed); +bool canonicalizePathURL(const UChar* spec, const URLSegments& parsed, URLBuffer<char>& output, URLSegments& ouputParsed); + +// Use for mailto URLs. This "canonicalizes" the url into a path and query +// component. It does not attempt to merge "to" fields. It uses UTF-8 for +// the query encoding if there is a query. This is because a mailto URL is +// really intended for an external mail program, and the encoding of a page, +// etc. which would influence a query encoding normally are irrelevant. +bool canonicalizeMailtoURL(const char* spec, const URLSegments& parsed, URLBuffer<char>&, URLSegments& outputParsed); +bool canonicalizeMailtoURL(const UChar* spec, const URLSegments& parsed, URLBuffer<char>&, URLSegments& outputParsed); + +// Part replacer -------------------------------------------------------------- + +// Internal structure used for storing separate strings for each component. +// The basic canonicalization functions use this structure internally so that +// component replacement (different strings for different components) can be +// treated on the same code path as regular canonicalization (the same string +// for each component). +// +// A URLSegments structure usually goes along with this. Those +// components identify offsets within these strings, so that they can all be +// in the same string, or spread arbitrarily across different ones. +// +// This structures does not own any data. It is the caller's responsibility to +// ensure that the data the pointers point to stays in scope and is not +// modified. +template<typename CharacterType> +struct URLComponentSource { + // Constructor normally used by callers wishing to replace components. This + // will make them all null, which is no replacement. The caller would then + // override the components they want to replace. + URLComponentSource() + : scheme(0) + , username(0) + , password(0) + , host(0) + , port(0) + , path(0) + , query(0) + , ref(0) + { + } + + // Constructor normally used internally to initialize all the components to + // point to the same spec. + explicit URLComponentSource(const CharacterType* defaultValue) + : scheme(defaultValue) + , username(defaultValue) + , password(defaultValue) + , host(defaultValue) + , port(defaultValue) + , path(defaultValue) + , query(defaultValue) + , ref(defaultValue) + { + } + + const CharacterType* scheme; + const CharacterType* username; + const CharacterType* password; + const CharacterType* host; + const CharacterType* port; + const CharacterType* path; + const CharacterType* query; + const CharacterType* ref; +}; + +// This structure encapsulates information on modifying a URL. Each component +// may either be left unchanged, replaced, or deleted. +// +// By default, each component is unchanged. For those components that should be +// modified, call either Set* or Clear* to modify it. +// +// The string passed to Set* functions DOES NOT GET COPIED AND MUST BE KEPT +// IN SCOPE BY THE CALLER for as long as this object exists! +// +// Prefer the 8-bit replacement version if possible since it is more efficient. +template<typename CharacterType> +class Replacements { +public: + Replacements() + { + } + + // Scheme + void SetScheme(const CharacterType* s, const URLComponent& comp) + { + m_sources.scheme = s; + m_segments.scheme = comp; + } + // Note: we don't have a ClearScheme since this doesn't make any sense. + bool IsSchemeOverridden() const { return !!m_sources.scheme; } + + // Username + void SetUsername(const CharacterType* s, const URLComponent& comp) + { + m_sources.username = s; + m_segments.username = comp; + } + void ClearUsername() + { + m_sources.username = Placeholder(); + m_segments.username = URLComponent(); + } + bool IsUsernameOverridden() const { return !!m_sources.username; } + + // Password + void SetPassword(const CharacterType* s, const URLComponent& comp) + { + m_sources.password = s; + m_segments.password = comp; + } + void ClearPassword() + { + m_sources.password = Placeholder(); + m_segments.password = URLComponent(); + } + bool IsPasswordOverridden() const { return !!m_sources.password; } + + // Host + void SetHost(const CharacterType* s, const URLComponent& comp) + { + m_sources.host = s; + m_segments.host = comp; + } + void ClearHost() + { + m_sources.host = Placeholder(); + m_segments.host = URLComponent(); + } + bool IsHostOverridden() const { return !!m_sources.host; } + + // Port + void SetPort(const CharacterType* s, const URLComponent& comp) + { + m_sources.port = s; + m_segments.port = comp; + } + void ClearPort() + { + m_sources.port = Placeholder(); + m_segments.port = URLComponent(); + } + bool IsPortOverridden() const { return !!m_sources.port; } + + // Path + void SetPath(const CharacterType* s, const URLComponent& comp) + { + m_sources.path = s; + m_segments.path = comp; + } + void ClearPath() + { + m_sources.path = Placeholder(); + m_segments.path = URLComponent(); + } + bool IsPathOverridden() const { return !m_sources.path; } + + // Query + void SetQuery(const CharacterType* s, const URLComponent& comp) + { + m_sources.query = s; + m_segments.query = comp; + } + void ClearQuery() + { + m_sources.query = Placeholder(); + m_segments.query = URLComponent(); + } + bool IsQueryOverridden() const { return !m_sources.query; } + + // Ref + void SetRef(const CharacterType* s, const URLComponent& comp) + { + m_sources.ref = s; + m_segments.fragment = comp; + } + void ClearRef() + { + m_sources.ref = Placeholder(); + m_segments.fragment = URLComponent(); + } + bool IsRefOverridden() const { return !m_sources.ref; } + + // Getters for the itnernal data. See the variables below for how the + // information is encoded. + const URLComponentSource<CharacterType>& sources() const { return m_sources; } + const URLSegments& components() const { return m_segments; } + +private: + // Returns a pointer to a static empty string that is used as a placeholder + // to indicate a component should be deleted (see below). + const CharacterType* Placeholder() + { + static const CharacterType emptyString = 0; + return &emptyString; + } + + // We support three states: + // + // Action | Source Component + // -----------------------+-------------------------------------------------- + // Don't change component | null (unused) + // Replace component | (replacement string) (replacement component) + // Delete component | (non-null) (invalid component: (0,-1)) + // + // We use a pointer to the empty string for the source when the component + // should be deleted. + URLComponentSource<CharacterType> m_sources; + URLSegments m_segments; +}; + +// The base must be an 8-bit canonical URL. +bool ReplaceStandardURL(const char* base, + const URLSegments& baseParsed, + const Replacements<char>&, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>&, + URLSegments* outputParsed); +bool ReplaceStandardURL(const char* base, + const URLSegments& baseParsed, + const Replacements<UChar>&, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>&, + URLSegments* outputParsed); + +// Filesystem URLs can only have the path, query, or ref replaced. +// All other components will be ignored. +bool ReplaceFileSystemURL(const char* base, + const URLSegments& baseParsed, + const Replacements<char>&, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>&, + URLSegments* outputParsed); +bool ReplaceFileSystemURL(const char* base, + const URLSegments& baseParsed, + const Replacements<UChar>&, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>&, + URLSegments* outputParsed); + +// Replacing some parts of a file URL is not permitted. Everything except +// the host, path, query, and ref will be ignored. +bool ReplaceFileURL(const char* base, + const URLSegments& baseParsed, + const Replacements<char>&, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>&, + URLSegments* outputParsed); +bool ReplaceFileURL(const char* base, + const URLSegments& baseParsed, + const Replacements<UChar>&, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>&, + URLSegments* outputParsed); + +// Path URLs can only have the scheme and path replaced. All other components +// will be ignored. +bool ReplacePathURL(const char* base, + const URLSegments& baseParsed, + const Replacements<char>&, + URLBuffer<char>&, + URLSegments* outputParsed); +bool ReplacePathURL(const char* base, + const URLSegments& baseParsed, + const Replacements<UChar>&, + URLBuffer<char>&, + URLSegments* outputParsed); + +// Mailto URLs can only have the scheme, path, and query replaced. +// All other components will be ignored. +bool replaceMailtoURL(const char* base, const URLSegments& baseParsed, + const Replacements<char>&, + URLBuffer<char>& output, URLSegments& outputParsed); +bool replaceMailtoURL(const char* base, const URLSegments& baseParsed, + const Replacements<UChar>&, + URLBuffer<char>& output, URLSegments& outputParsed); + +// Relative URL --------------------------------------------------------------- + +// Given an input URL or URL fragment |fragment|, determines if it is a +// relative or absolute URL and places the result into |*isRelative|. If it is +// relative, the relevant portion of the URL will be placed into +// |*relativeComponent| (there may have been trimmed whitespace, for example). +// This value is passed to resolveRelativeURL. If the input is not relative, +// this value is UNDEFINED (it may be changed by the function). +// +// Returns true on success (we successfully determined the URL is relative or +// not). Failure means that the combination of URLs doesn't make any sense. +// +// The base URL should always be canonical, therefore is ASCII. +bool isRelativeURL(const char* base, const URLSegments& baseParsed, + const char* fragment, int fragmentLength, + bool isBaseHierarchical, + bool& isRelative, URLComponent& relativeComponent); +bool isRelativeURL(const char* base, const URLSegments& baseParsed, + const UChar* fragment, int fragmentLength, + bool isBaseHierarchical, + bool& isRelative, URLComponent& relativeComponent); + +// Given a canonical parsed source URL, a URL fragment known to be relative, +// and the identified relevant portion of the relative URL (computed by +// isRelativeURL), this produces a new parsed canonical URL in |output| and +// |outputParsed|. +// +// It also requires a flag indicating whether the base URL is a file: URL +// which triggers additional logic. +// +// The base URL should be canonical and have a host (may be empty for file +// URLs) and a path. If it doesn't have these, we can't resolve relative +// URLs off of it and will return the base as the output with an error flag. +// Becausee it is canonical is should also be ASCII. +// +// The query charset converter follows the same rules as CanonicalizeQuery. +// +// Returns true on success. On failure, the output will be "something +// reasonable" that will be consistent and valid, just probably not what +// was intended by the web page author or caller. +bool resolveRelativeURL(const char* baseURL, const URLSegments& baseParsed, bool baseIsFile, + const char* relativeURL, const URLComponent& relativeComponent, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>&, URLSegments* outputParsed); +bool resolveRelativeURL(const char* baseURL, const URLSegments& baseParsed, bool baseIsFile, + const UChar* relativeURL, const URLComponent& relativeComponent, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>&, URLSegments* outputParsed); + +} // namespace URLCanonicalizer + +} // namespace WTF + +#endif // USE(WTFURL) + +#endif // URLCanon_h diff --git a/Source/WTF/wtf/url/src/URLCanonEtc.cpp b/Source/WTF/wtf/url/src/URLCanonEtc.cpp new file mode 100644 index 000000000..4ed6d18e8 --- /dev/null +++ b/Source/WTF/wtf/url/src/URLCanonEtc.cpp @@ -0,0 +1,374 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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. + */ + +// Canonicalizers for random bits that aren't big enough for their own files. + +#include "config.h" +#include "URLCanon.h" + +#include "URLCanonInternal.h" +#include <wtf/ASCIICType.h> + +#if USE(WTFURL) + +namespace WTF { + +namespace URLCanonicalizer { + +namespace { + +// Returns true if the given character should be removed from the middle of a +// URL. +inline bool isRemovableURLWhitespace(int character) +{ + return character == '\r' || character == '\n' || character == '\t'; +} + +// Backend for removeURLWhitespace (see declaration in URLCanon.h). +// It sucks that we have to do this, since this takes about 13% of the total URL +// canonicalization time. +template<typename CharacterType> +const CharacterType* doRemoveURLWhitespace(const CharacterType* input, int inputLength, URLBuffer<CharacterType>& buffer, int& outputLength) +{ + // Fast verification that there's nothing that needs removal. This is the 99% + // case, so we want it to be fast and don't care about impacting the speed + // when we do find whitespace. + bool foundWhitespace = false; + for (int i = 0; i < inputLength; ++i) { + if (!isRemovableURLWhitespace(input[i])) + continue; + foundWhitespace = true; + break; + } + + if (!foundWhitespace) { + // Didn't find any whitespace, we don't need to do anything. We can just + // return the input as the output. + outputLength = inputLength; + return input; + } + + // Remove the whitespace into the new buffer and return it. + for (int i = 0; i < inputLength; i++) { + if (!isRemovableURLWhitespace(input[i])) + buffer.append(input[i]); + } + outputLength = buffer.length(); + return buffer.data(); +} + +// Contains the canonical version of each possible input letter in the scheme +// (basically, lower-cased). The corresponding entry will be 0 if the letter +// is not allowed in a scheme. +const char kSchemeCanonical[0x80] = { +// 00-1f: all are invalid + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +// ' ' ! " # $ % & ' ( ) * + , - . / + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '+', 0, '-', '.', 0, +// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 , 0 , 0 , 0 , 0 , 0 , +// @ A B C D E F G H I J K L M N O + 0 , 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', +// P Q R S T U V W X Y Z [ \ ] ^ _ + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0 , 0, 0 , 0, +// ` a b c d e f g h i j k l m n o + 0 , 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', +// p q r s t u v w x y z { | } ~ + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0 , 0 , 0 , 0 , 0 }; + +// This could be a table lookup as well by setting the high bit for each +// valid character, but it's only called once per URL, and it makes the lookup +// table easier to read not having extra stuff in it. +inline bool isSchemeFirstChar(unsigned char character) +{ + return isASCIIAlpha(character); +} + +template<typename CharacterType, typename UCHAR> +bool doScheme(const CharacterType* spec, const URLComponent& scheme, URLBuffer<char>& output, URLComponent& outputScheme) +{ + if (scheme.length() <= 0) { + // Scheme is unspecified or empty, convert to empty by appending a colon. + outputScheme = URLComponent(output.length(), 0); + output.append(':'); + return true; + } + + // The output scheme starts from the current position. + outputScheme.setBegin(outputScheme.begin() + output.length()); + + // Danger: it's important that this code does not strip any characters: it + // only emits the canonical version (be it valid or escaped) of each of + // the input characters. Stripping would put it out of sync with + // URLUtilities::FindAndCompareScheme, which could cause some security checks on + // schemes to be incorrect. + bool success = true; + int end = scheme.end(); + for (int i = scheme.begin(); i < end; ++i) { + UCHAR character = static_cast<UCHAR>(spec[i]); + char replacement = 0; + if (character < 0x80) { + if (i == scheme.begin()) { + // Need to do a special check for the first letter of the scheme. + if (isSchemeFirstChar(static_cast<unsigned char>(character))) + replacement = kSchemeCanonical[character]; + } else + replacement = kSchemeCanonical[character]; + } + + if (replacement) + output.append(replacement); + else if (character == '%') { + // Canonicalizing the scheme multiple times should lead to the same + // result. Since invalid characters will be escaped, we need to preserve + // the percent to avoid multiple escaping. The scheme will be invalid. + success = false; + output.append('%'); + } else { + // Invalid character, store it but mark this scheme as invalid. + success = false; + + // This will escape the output and also handle encoding issues. + // Ignore the return value since we already failed. + AppendUTF8EscapedChar(spec, &i, end, output); + } + } + + // The output scheme ends with the the current position, before appending + // the colon. + outputScheme.setLength(output.length() - outputScheme.begin()); + output.append(':'); + return success; +} + +// The username and password components reference ranges in the corresponding +// *_spec strings. Typically, these specs will be the same (we're +// canonicalizing a single source string), but may be different when +// replacing components. +template<typename CharacterType, typename UCHAR> +bool doUserInfo(const CharacterType* usernameSpec, + const URLComponent& username, + const CharacterType* passwordSpec, + const URLComponent& password, + URLBuffer<char>& output, + URLComponent& outputUsername, + URLComponent& outputPassword) +{ + if (username.length() <= 0 && password.length() <= 0) { + // Common case: no user info. We strip empty username/passwords. + outputUsername = URLComponent(); + outputPassword = URLComponent(); + return true; + } + + // Write the username. + outputUsername.setBegin(output.length()); + if (username.length() > 0) { + // This will escape characters not valid for the username. + appendStringOfType(&usernameSpec[username.begin()], username.length(), URLCharacterTypes::UserInfoCharacter, output); + } + outputUsername.setLength(output.length() - outputUsername.begin()); + + // When there is a password, we need the separator. Note that we strip + // empty but specified passwords. + if (password.length() > 0) { + output.append(':'); + outputPassword.setBegin(output.length()); + appendStringOfType(&passwordSpec[password.begin()], password.length(), URLCharacterTypes::UserInfoCharacter, output); + outputPassword.setLength(output.length() - outputPassword.begin()); + } else + outputPassword = URLComponent(); + + output.append('@'); + return true; +} + +// Helper functions for converting port integers to strings. +inline void writePortInt(char* output, int outputLength, int port) +{ + _itoa_s(port, output, outputLength, 10); +} + +// This function will prepend the colon if there will be a port. +template<typename CharacterType, typename UCHAR> +bool doPort(const CharacterType* spec, + const URLComponent& port, + int defaultPortForScheme, + URLBuffer<char>& output, + URLComponent& outputPortComponent) +{ + int portNumber = URLParser::ParsePort(spec, port); + if (portNumber == URLParser::PORT_UNSPECIFIED || portNumber == defaultPortForScheme) { + outputPortComponent = URLComponent(); + return true; // Leave port empty. + } + + if (portNumber == URLParser::PORT_INVALID) { + // Invalid port: We'll copy the text from the input so the user can see + // what the error was, and mark the URL as invalid by returning false. + output.append(':'); + outputPortComponent.setBegin(output.length()); + AppendInvalidNarrowString(spec, port.begin(), port.end(), output); + outputPortComponent.setLength(output.length() - outputPortComponent.begin()); + return false; + } + + // Convert port number back to an integer. Max port value is 5 digits, and + // the Parsed::ExtractPort will have made sure the integer is in range. + const int bufferSize = 6; + char buffer[bufferSize]; + writePortInt(buffer, bufferSize, portNumber); + + // Append the port number to the output, preceeded by a colon. + output.append(':'); + outputPortComponent.setBegin(output.length()); + for (int i = 0; i < bufferSize && buffer[i]; ++i) + output.append(buffer[i]); + + outputPortComponent.setLength(output.length() - outputPortComponent.begin()); + return true; +} + +template<typename CharacterType, typename UCHAR> +void doCanonicalizeFragment(const CharacterType* spec, const URLComponent& fragment, URLBuffer<char>& output, URLComponent& outputFragment) +{ + if (fragment.length() < 0) { + // Common case of no fragment. + outputFragment = URLComponent(); + return; + } + + // Append the fragment separator. Note that we need to do this even when the fragment + // is empty but present. + output.append('#'); + outputFragment.setBegin(output.length()); + + // Now iterate through all the characters, converting to UTF-8 and validating. + int end = fragment.end(); + for (int i = fragment.begin(); i < end; ++i) { + if (!spec[i]) { + // IE just strips NULLs, so we do too. + continue; + } + if (static_cast<UCHAR>(spec[i]) < 0x20) { + // Unline IE seems to, we escape control characters. This will probably + // make the reference fragment unusable on a web page, but people + // shouldn't be using control characters in their anchor names. + appendURLEscapedCharacter(static_cast<unsigned char>(spec[i]), output); + } else if (static_cast<UCHAR>(spec[i]) < 0x80) { + // Normal ASCII characters are just appended. + output.append(static_cast<char>(spec[i])); + } else { + // Non-ASCII characters are appended unescaped, but only when they are + // valid. Invalid Unicode characters are replaced with the "invalid + // character" as IE seems to (readUTFChar puts the unicode replacement + // character in the output on failure for us). + unsigned codePoint; + readUTFChar(spec, &i, end, &codePoint); + AppendUTF8Value(codePoint, output); + } + } + + outputFragment.setLength(output.length() - outputFragment.begin()); +} + +} // namespace + +const char* removeURLWhitespace(const char* input, int inputLength, URLBuffer<char>& buffer, int& outputLength) +{ + return doRemoveURLWhitespace(input, inputLength, buffer, outputLength); +} + +const UChar* removeURLWhitespace(const UChar* input, int inputLength, URLBuffer<UChar>& buffer, int& outputLength) +{ + return doRemoveURLWhitespace(input, inputLength, buffer, outputLength); +} + +char canonicalSchemeChar(UChar character) +{ + if (character >= 0x80) + return 0; // Non-ASCII is not supported by schemes. + return kSchemeCanonical[character]; +} + +bool canonicalizeScheme(const char* spec, const URLComponent& scheme, URLBuffer<char>& output, URLComponent& outputScheme) +{ + return doScheme<char, unsigned char>(spec, scheme, output, outputScheme); +} + +bool canonicalizeScheme(const UChar* spec, const URLComponent& scheme, URLBuffer<char>& output, URLComponent& outputScheme) +{ + return doScheme<UChar, UChar>(spec, scheme, output, outputScheme); +} + +bool canonicalizeUserInfo(const char* usernameSource, const URLComponent& username, const char* passwordSource, const URLComponent& password, + URLBuffer<char>& output, URLComponent& outputUsername, URLComponent& outputPassword) +{ + return doUserInfo<char, unsigned char>(usernameSource, username, passwordSource, password, output, outputUsername, outputPassword); +} + +bool canonicalizeUserInfo(const UChar* usernameSource, const URLComponent& username, const UChar* passwordSource, const URLComponent& password, + URLBuffer<char>& output, URLComponent& outputUsername, URLComponent& outputPassword) +{ + return doUserInfo<UChar, UChar>(usernameSource, username, passwordSource, password, output, outputUsername, outputPassword); +} + +bool canonicalizePort(const char* spec, const URLComponent& port, int defaultPortForScheme, + URLBuffer<char>& output, URLComponent& outputPortComponent) +{ + return doPort<char, unsigned char>(spec, port, + defaultPortForScheme, + output, outputPortComponent); +} + +bool canonicalizePort(const UChar* spec, const URLComponent& port, int defaultPortForScheme, + URLBuffer<char>& output, URLComponent& outputPortComponent) +{ + return doPort<UChar, UChar>(spec, port, defaultPortForScheme, + output, outputPortComponent); +} + +void canonicalizeFragment(const char* spec, const URLComponent& ref, URLBuffer<char>& output, URLComponent& outputFragment) +{ + doCanonicalizeFragment<char, unsigned char>(spec, ref, output, outputFragment); +} + +void canonicalizeFragment(const UChar* spec, const URLComponent& ref, URLBuffer<char>& output, URLComponent& outputFragment) +{ + doCanonicalizeFragment<UChar, UChar>(spec, ref, output, outputFragment); +} + +} // namespace URLCanonicalizer + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonFilesystemurl.cpp b/Source/WTF/wtf/url/src/URLCanonFilesystemurl.cpp new file mode 100644 index 000000000..361bbbef7 --- /dev/null +++ b/Source/WTF/wtf/url/src/URLCanonFilesystemurl.cpp @@ -0,0 +1,164 @@ +/* + * Copyright 2012 Google Inc. All rights reserved. + * Copyright 2012 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. + */ + +// Functions for canonicalizing "filesystem:file:" URLs. + +#include "config.h" +#include "URLCanon.h" + +#include "RawURLBuffer.h" +#include "URLCanonInternal.h" +#include "URLFile.h" +#include "URLParseInternal.h" +#include "URLUtil.h" +#include "URLUtilInternal.h" + +#if USE(WTFURL) + +namespace WTF { + +namespace URLCanonicalizer { + +namespace { + +// We use the URLComponentSource for the outer URL, as it can have replacements, +// whereas the inner_url can't, so it uses spec. +template<typename CharacterType, typename UCHAR> +bool doCanonicalizeFileSystemURL(const CharacterType* spec, + const URLComponentSource<CharacterType>& source, + const URLSegments& parsed, + URLQueryCharsetConverter* charsetConverter, + URLBuffer<char>& output, + URLSegments& outputParsed) +{ + // filesystem only uses {scheme, path, query, ref} -- clear the rest. + outputParsed.username = URLComponent(); + outputParsed.password = URLComponent(); + outputParsed.host = URLComponent(); + outputParsed.port = URLComponent(); + + const URLSegments* innerParsed = parsed.innerURLSegments(); + URLSegments newInnerParsed; + + // Scheme (known, so we don't bother running it through the more + // complicated scheme canonicalizer). + outputParsed.scheme.setBegin(output.length()); + output.append("filesystem:", 11); + outputParsed.scheme.setLength(10); + + if (!parsed.innerURLSegments() || !parsed.innerURLSegments()->scheme.isValid()) + return false; + + bool success = true; + if (URLUtilities::CompareSchemeComponent(spec, innerParsed->scheme, URLUtilities::kFileScheme)) { + newInnerParsed.scheme.setBegin(output.length()); + output.append("file://", 7); + newInnerParsed.scheme.setLength(4); + success &= CanonicalizePath(spec, innerParsed->path, output, + &newInnerParsed.path); + } else if (URLUtilities::isStandard(spec, innerParsed->scheme)) { + success = + URLCanonicalizer::CanonicalizeStandardURL(spec, + parsed.innerURLSegments()->length(), + *parsed.innerURLSegments(), + charsetConverter, output, + &newInnerParsed); + } else { + // TODO(ericu): The URL is wrong, but should we try to output more of what + // we were given? Echoing back filesystem:mailto etc. doesn't seem all that useful. + return false; + } + // The filesystem type must be more than just a leading slash for validity. + success &= parsed.innerURLSegments()->path.length() > 1; + + success &= CanonicalizePath(source.path, parsed.path, output, &outputParsed.path); + + // Ignore failures for query/ref since the URL can probably still be loaded. + CanonicalizeQuery(source.query, parsed.query, charsetConverter, output, &outputParsed.query); + canonicalizeFragment(source.ref, parsed.fragment, output, outputParsed.fragment); + if (success) + outputParsed.setInnerURLSegments(newInnerParsed); + + return success; +} + +} // namespace + +bool canonicalizeFileSystemURL(const char* spec, + const URLSegments& parsed, + URLQueryCharsetConverter* charsetConverter, + URLBuffer<char>& output, + URLSegments& outputParsed) +{ + return doCanonicalizeFileSystemURL<char, unsigned char>(spec, URLComponentSource<char>(spec), parsed, charsetConverter, output, outputParsed); +} + +bool canonicalizeFileSystemURL(const UChar* spec, + const URLSegments& parsed, + URLQueryCharsetConverter* charsetConverter, + URLBuffer<char>& output, + URLSegments& outputParsed) +{ + return doCanonicalizeFileSystemURL<UChar, UChar>(spec, URLComponentSource<UChar>(spec), parsed, charsetConverter, output, outputParsed); +} + +bool ReplaceFileSystemURL(const char* base, + const URLSegments& baseParsed, + const Replacements<char>& replacements, + URLQueryCharsetConverter* charsetConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + URLComponentSource<char> source(base); + URLSegments parsed(baseParsed); + SetupOverrideComponents(base, replacements, &source, &parsed); + return doCanonicalizeFileSystemURL<char, unsigned char>(base, source, parsed, charsetConverter, output, *outputParsed); +} + +bool ReplaceFileSystemURL(const char* base, + const URLSegments& baseParsed, + const Replacements<UChar>& replacements, + URLQueryCharsetConverter* charsetConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + RawURLBuffer<char> utf8; + URLComponentSource<char> source(base); + URLSegments parsed(baseParsed); + SetupUTF16OverrideComponents(base, replacements, utf8, &source, &parsed); + return doCanonicalizeFileSystemURL<char, unsigned char>(base, source, parsed, charsetConverter, output, *outputParsed); +} + +} // namespace URLCanonicalizer + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonFileurl.cpp b/Source/WTF/wtf/url/src/URLCanonFileurl.cpp new file mode 100644 index 000000000..73a9f6dd1 --- /dev/null +++ b/Source/WTF/wtf/url/src/URLCanonFileurl.cpp @@ -0,0 +1,224 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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. + */ + +// Functions for canonicalizing "file:" URLs. + +#include "config.h" +#include "URLCanon.h" + +#include "RawURLBuffer.h" +#include "URLCanonInternal.h" +#include "URLFile.h" +#include "URLParseInternal.h" + +#if USE(WTFURL) + +namespace WTF { + +namespace URLCanonicalizer { + +namespace { + +#if OS(WINDOWS) + +// Given a pointer into the spec, this copies and canonicalizes the drive +// letter and colon to the output, if one is found. If there is not a drive +// spec, it won't do anything. The index of the next character in the input +// spec is returned (after the colon when a drive spec is found, the begin +// offset if one is not). +template<typename CHAR> +int FileDoDriveSpec(const CHAR* spec, int begin, int end, URLBuffer<char>& output) +{ + // The path could be one of several things: /foo/bar, c:/foo/bar, /c:/foo, + // (with backslashes instead of slashes as well). + int numSlashes = URLParser::countConsecutiveSlashes(spec, begin, end); + int afterSlashes = begin + numSlashes; + + if (!URLParser::doesBeginWindowsDriveSpec(spec, afterSlashes, end)) + return begin; // Haven't consumed any characters + + // A drive spec is the start of a path, so we need to add a slash for the + // authority terminator (typically the third slash). + output.append('/'); + + // doesBeginWindowsDriveSpec will ensure that the drive letter is valid + // and that it is followed by a colon/pipe. + + // Normalize Windows drive letters to uppercase + if (spec[afterSlashes] >= 'a' && spec[afterSlashes] <= 'z') + output.append(spec[afterSlashes] - 'a' + 'A'); + else + output.append(static_cast<char>(spec[afterSlashes])); + + // Normalize the character following it to a colon rather than pipe. + output.append(':'); + return afterSlashes + 2; +} + +#endif // OS(WINDOWS) + +template<typename CharacterType, typename UCHAR> +bool doFileCanonicalizePath(const CharacterType* spec, + const URLComponent& path, + URLBuffer<char>& output, + URLComponent& outputPath) +{ + // Copies and normalizes the "c:" at the beginning, if present. + outputPath.setBegin(output.length()); + int afterDrive; +#if OS(WINDOWS) + afterDrive = FileDoDriveSpec(spec, path.begin, path.end(), output); +#else + afterDrive = path.begin(); +#endif + + // Copies the rest of the path, starting from the slash following the + // drive colon (if any, Windows only), or the first slash of the path. + bool success = true; + if (afterDrive < path.end()) { + // Use the regular path canonicalizer to canonicalize the rest of the + // path. Give it a fake output component to write into. DoCanonicalizeFile + // will compute the full path component. + URLComponent subPath = URLComponent::fromRange(afterDrive, path.end()); + URLComponent fakeOutputPath; + success = CanonicalizePath(spec, subPath, output, &fakeOutputPath); + } else { + // No input path, canonicalize to a slash. + output.append('/'); + } + + outputPath.setLength(output.length() - outputPath.begin()); + return success; +} + +template<typename CharacterType, typename UCHAR> +bool doCanonicalizeFileURL(const URLComponentSource<CharacterType>& source, + const URLSegments& parsed, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>& output, + URLSegments& outputParsed) +{ + // Things we don't set in file: URLs. + outputParsed.username = URLComponent(); + outputParsed.password = URLComponent(); + outputParsed.port = URLComponent(); + + // Scheme (known, so we don't bother running it through the more + // complicated scheme canonicalizer). + outputParsed.scheme.setBegin(output.length()); + output.append("file://", 7); + outputParsed.scheme.setLength(4); + + // Append the host. For many file URLs, this will be empty. For UNC, this + // will be present. + // TODO(brettw) This doesn't do any checking for host name validity. We + // should probably handle validity checking of UNC hosts differently than + // for regular IP hosts. + bool success = canonicalizeHost(source.host, parsed.host, output, outputParsed.host); + success &= doFileCanonicalizePath<CharacterType, UCHAR>(source.path, parsed.path, output, outputParsed.path); + CanonicalizeQuery(source.query, parsed.query, queryConverter, output, &outputParsed.query); + + // Ignore failure for refs since the URL can probably still be loaded. + canonicalizeFragment(source.ref, parsed.fragment, output, outputParsed.fragment); + + return success; +} + +} // namespace + +bool CanonicalizeFileURL(const char* spec, + int /* specLength */, + const URLSegments& parsed, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + return doCanonicalizeFileURL<char, unsigned char>(URLComponentSource<char>(spec), parsed, queryConverter, output, *outputParsed); +} + +bool CanonicalizeFileURL(const UChar* spec, + int /* specLength */, + const URLSegments& parsed, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + return doCanonicalizeFileURL<UChar, UChar>(URLComponentSource<UChar>(spec), parsed, queryConverter, output, *outputParsed); +} + +bool FileCanonicalizePath(const char* spec, + const URLComponent& path, + URLBuffer<char>& output, + URLComponent* outputPath) +{ + return doFileCanonicalizePath<char, unsigned char>(spec, path, output, *outputPath); +} + +bool FileCanonicalizePath(const UChar* spec, + const URLComponent& path, + URLBuffer<char>& output, + URLComponent* outputPath) +{ + return doFileCanonicalizePath<UChar, UChar>(spec, path, output, *outputPath); +} + +bool ReplaceFileURL(const char* base, + const URLSegments& baseParsed, + const Replacements<char>& replacements, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + URLComponentSource<char> source(base); + URLSegments parsed(baseParsed); + SetupOverrideComponents(base, replacements, &source, &parsed); + return doCanonicalizeFileURL<char, unsigned char>(source, parsed, queryConverter, output, *outputParsed); +} + +bool ReplaceFileURL(const char* base, + const URLSegments& baseParsed, + const Replacements<UChar>& replacements, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + RawURLBuffer<char> utf8; + URLComponentSource<char> source(base); + URLSegments parsed(baseParsed); + SetupUTF16OverrideComponents(base, replacements, utf8, &source, &parsed); + return doCanonicalizeFileURL<char, unsigned char>(source, parsed, queryConverter, output, *outputParsed); +} + +} // namespace URLCanonicalizer + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonHost.cpp b/Source/WTF/wtf/url/src/URLCanonHost.cpp new file mode 100644 index 000000000..5ea2f9906 --- /dev/null +++ b/Source/WTF/wtf/url/src/URLCanonHost.cpp @@ -0,0 +1,383 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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" +#include "URLCanon.h" + +#include "RawURLBuffer.h" +#include "URLCanonInternal.h" + +#if USE(WTFURL) + +namespace WTF { + +namespace URLCanonicalizer { + +namespace { + +// For reference, here's what IE supports: +// Key: 0 (disallowed: failure if present in the input) +// + (allowed either escaped or unescaped, and unmodified) +// U (allowed escaped or unescaped but always unescaped if present in +// escaped form) +// E (allowed escaped or unescaped but always escaped if present in +// unescaped form) +// % (only allowed escaped in the input, will be unmodified). +// I left blank alpha numeric characters. +// +// 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f +// ----------------------------------------------- +// 0 0 E E E E E E E E E E E E E E E +// 1 E E E E E E E E E E E E E E E E +// 2 E + E E + E + + + + + + + U U 0 +// 3 % % E + E 0 <-- Those are : ; < = > ? +// 4 % +// 5 U 0 U U U <-- Those are [ \ ] ^ _ +// 6 E <-- That's ` +// 7 E E E U E <-- Those are { | } ~ (UNPRINTABLE) +// +// NOTE: I didn't actually test all the control characters. Some may be +// disallowed in the input, but they are all accepted escaped except for 0. +// I also didn't test if characters affecting HTML parsing are allowed +// unescaped, eg. (") or (#), which would indicate the beginning of the path. +// Surprisingly, space is accepted in the input and always escaped. + +// This table lists the canonical version of all characters we allow in the +// input, with 0 indicating it is disallowed. We use the magic kEscapedHostChar +// value to indicate that this character should be escaped. We are a little more +// restrictive than IE, but less restrictive than Firefox. +// +// Note that we disallow the % character. We will allow it when part of an +// escape sequence, of course, but this disallows "%25". Even though IE allows +// it, allowing it would put us in a funny state. If there was an invalid +// escape sequence like "%zz", we'll add "%25zz" to the output and fail. +// Allowing percents means we'll succeed a second time, so validity would change +// based on how many times you run the canonicalizer. We prefer to always report +// the same vailidity, so reject this. +const unsigned char kEsc = 0xff; +const unsigned char kHostCharLookup[0x80] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +// ' ' ! " # $ % & ' ( ) * + , - . / + kEsc, kEsc, kEsc, kEsc, kEsc, 0, kEsc, kEsc, kEsc, kEsc, kEsc, '+', kEsc, '-', '.', 0, +// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', 0 , kEsc, kEsc, kEsc, 0 , +// @ A B C D E F G H I J K L M N O + kEsc, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', +// P Q R S T U V W X Y Z [ \ ] ^ _ + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', 0 , ']', 0 , '_', +// ` a b c d e f g h i j k l m n o + kEsc, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', +// p q r s t u v w x y z { | } ~ + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', kEsc, kEsc, kEsc, 0 , 0 }; + +typedef RawURLBuffer<char> StackBuffer; +typedef RawURLBuffer<UChar> StackBufferW; + +// Scans a host name and fills in the output flags according to what we find. +// |hasNonASCII| will be true if there are any non-7-bit characters, and +// |hasEscaped| will be true if there is a percent sign. +template<typename CharacterType, typename UCHAR> +void scanHostname(const CharacterType* spec, const URLComponent& host, bool& hasNonASCII, bool& hasEscaped) +{ + int end = host.end(); + hasNonASCII = false; + hasEscaped = false; + for (int i = host.begin(); i < end; ++i) { + if (static_cast<UCHAR>(spec[i]) >= 0x80) + hasNonASCII = true; + else if (spec[i] == '%') + hasEscaped = true; + } +} + +// Canonicalizes a host name that is entirely 8-bit characters (even though +// the type holding them may be 16 bits. Escaped characters will be unescaped. +// Non-7-bit characters (for example, UTF-8) will be passed unchanged. +// +// The |*hasNonASCII| flag will be true if there are non-7-bit characters in +// the output. +// +// This function is used in two situations: +// +// * When the caller knows there is no non-ASCII or percent escaped +// characters. This is what DoHost does. The result will be a completely +// canonicalized host since we know nothing weird can happen (escaped +// characters could be unescaped to non-7-bit, so they have to be treated +// with suspicion at this point). It does not use the |hasNonASCII| flag. +// +// * When the caller has an 8-bit string that may need unescaping. +// doComplexHost calls us this situation to do unescaping and validation. +// After this, it may do other IDN operations depending on the value of the +// |*hasNonASCII| flag. +// +// The return value indicates if the output is a potentially valid host name. +template<typename INCHAR, typename OUTCHAR> +bool doSimpleHost(const INCHAR* host, int hostLength, URLBuffer<OUTCHAR>& output, bool& hasNonASCII) +{ + hasNonASCII = false; + + bool success = true; + for (int i = 0; i < hostLength; ++i) { + unsigned source = host[i]; + if (source == '%') { + // Unescape first, if possible. + // Source will be used only if decode operation was successful. + if (!DecodeEscaped(host, &i, hostLength, + reinterpret_cast<unsigned char*>(&source))) { + // Invalid escaped character. There is nothing that can make this + // host valid. We append an escaped percent so the URL looks reasonable + // and mark as failed. + appendURLEscapedCharacter('%', output); + success = false; + continue; + } + } + + if (source < 0x80) { + // We have ASCII input, we can use our lookup table. + unsigned char replacement = kHostCharLookup[source]; + if (!replacement) { + // Invalid character, add it as percent-escaped and mark as failed. + appendURLEscapedCharacter(source, output); + success = false; + } else if (replacement == kEsc) { + // This character is valid but should be escaped. + appendURLEscapedCharacter(source, output); + } else { + // Common case, the given character is valid in a hostname, the lookup + // table tells us the canonical representation of that character (lower + // cased). + output.append(replacement); + } + } else { + // It's a non-ascii char. Just push it to the output. + // In case where we have UChar input, and char output it's safe to + // cast UChar->char only if input string was converted to ASCII. + output.append(static_cast<OUTCHAR>(source)); + hasNonASCII = true; + } + } + + return success; +} + +// Canonicalizes a host that requires IDN conversion. Returns true on success +bool doIDNHost(const UChar* src, int sourceLength, URLBuffer<char>& output) +{ + // We need to escape URL before doing IDN conversion, since punicode strings + // cannot be escaped after they are created. + RawURLBuffer<UChar> urlEscapedHost; + bool hasNonASCII; + doSimpleHost(src, sourceLength, urlEscapedHost, hasNonASCII); + + StackBufferW wideOutput; + if (!IDNToASCII(urlEscapedHost.data(), + urlEscapedHost.length(), + wideOutput)) { + // Some error, give up. This will write some reasonable looking + // representation of the string to the output. + AppendInvalidNarrowString(src, 0, sourceLength, output); + return false; + } + + // Now we check the ASCII output like a normal host. It will also handle + // unescaping. Although we unescaped everything before this function call, if + // somebody does %00 as fullwidth, ICU will convert this to ASCII. + bool success = doSimpleHost(wideOutput.data(), wideOutput.length(), output, hasNonASCII); + ASSERT(!hasNonASCII); + return success; +} + +// 8-bit convert host to its ASCII version: this converts the UTF-8 input to +// UTF-16. The hasEscaped flag should be set if the input string requires +// unescaping. +bool doComplexHost(const char* host, int hostLength, bool hasNonASCII, bool hasEscaped, URLBuffer<char>& output) +{ + // Save the current position in the output. We may write stuff and rewind it + // below, so we need to know where to rewind to. + int beginLength = output.length(); + + // Points to the UTF-8 data we want to convert. This will either be the + // input or the unescaped version written to |output| if necessary. + const char* utf8Source; + int utf8SourceLength; + if (hasEscaped) { + // Unescape before converting to UTF-16 for IDN. We write this into the + // output because it most likely does not require IDNization, and we can + // save another huge stack buffer. It will be replaced below if it requires + // IDN. This will also update our non-ASCII flag so we know whether the + // unescaped input requires IDN. + if (!doSimpleHost(host, hostLength, output, hasNonASCII)) { + // Error with some escape sequence. We'll call the current output + // complete. doSimpleHost will have written some "reasonable" output. + return false; + } + + // Unescaping may have left us with ASCII input, in which case the + // unescaped version we wrote to output is complete. + if (!hasNonASCII) + return true; + + // Save the pointer into the data was just converted (it may be appended to + // other data in the output buffer). + utf8Source = &output.data()[beginLength]; + utf8SourceLength = output.length() - beginLength; + } else { + // We don't need to unescape, use input for IDNization later. (We know the + // input has non-ASCII, or the simple version would have been called + // instead of us.) + utf8Source = host; + utf8SourceLength = hostLength; + } + + // Non-ASCII input requires IDN, convert to UTF-16 and do the IDN conversion. + // Above, we may have used the output to write the unescaped values to, so + // we have to rewind it to where we started after we convert it to UTF-16. + StackBufferW utf16; + if (!ConvertUTF8ToUTF16(utf8Source, utf8SourceLength, utf16)) { + // In this error case, the input may or may not be the output. + StackBuffer utf8; + for (int i = 0; i < utf8SourceLength; i++) + utf8.append(utf8Source[i]); + output.setLength(beginLength); + AppendInvalidNarrowString(utf8.data(), 0, utf8.length(), output); + return false; + } + output.setLength(beginLength); + + // This will call doSimpleHost which will do normal ASCII canonicalization + // and also check for IP addresses in the outpt. + return doIDNHost(utf16.data(), utf16.length(), output); +} + +// UTF-16 convert host to its ASCII version. The set up is already ready for +// the backend, so we just pass through. The hasEscaped flag should be set if +// the input string requires unescaping. +bool doComplexHost(const UChar* host, int hostLength, bool hasNonASCII, bool hasEscaped, URLBuffer<char>& output) +{ + if (hasEscaped) { + // Yikes, we have escaped characters with wide input. The escaped + // characters should be interpreted as UTF-8. To solve this problem, + // we convert to UTF-8, unescape, then convert back to UTF-16 for IDN. + // + // We don't bother to optimize the conversion in the ASCII case (which + // *could* just be a copy) and use the UTF-8 path, because it should be + // very rare that host names have escaped characters, and it is relatively + // fast to do the conversion anyway. + StackBuffer utf8; + if (!ConvertUTF16ToUTF8(host, hostLength, utf8)) { + AppendInvalidNarrowString(host, 0, hostLength, output); + return false; + } + + // Once we convert to UTF-8, we can use the 8-bit version of the complex + // host handling code above. + return doComplexHost(utf8.data(), utf8.length(), hasNonASCII, + hasEscaped, output); + } + + // No unescaping necessary, we can safely pass the input to ICU. This + // function will only get called if we either have escaped or non-ascii + // input, so it's safe to just use ICU now. Even if the input is ASCII, + // this function will do the right thing (just slower than we could). + return doIDNHost(host, hostLength, output); +} + +template<typename CharacterType, typename UCHAR> +void doHost(const CharacterType* spec, const URLComponent& host, URLBuffer<char>& output, CanonHostInfo& hostInfo) +{ + if (host.length() <= 0) { + // Empty hosts don't need anything. + hostInfo.family = CanonHostInfo::NEUTRAL; + hostInfo.ouputHost = URLComponent(); + return; + } + + bool hasNonASCII; + bool hasEscaped; + scanHostname<CharacterType, UCHAR>(spec, host, hasNonASCII, hasEscaped); + + // Keep track of output's initial length, so we can rewind later. + const int outputBegin = output.length(); + + bool success; + if (!hasNonASCII && !hasEscaped) { + success = doSimpleHost(&spec[host.begin()], host.length(), output, hasNonASCII); + ASSERT(!hasNonASCII); + } else + success = doComplexHost(&spec[host.begin()], host.length(), hasNonASCII, hasEscaped, output); + + if (!success) { + // Canonicalization failed. Set BROKEN to notify the caller. + hostInfo.family = CanonHostInfo::BROKEN; + } else { + // After all the other canonicalization, check if we ended up with an IP + // address. IP addresses are small, so writing into this temporary buffer + // should not cause an allocation. + RawURLBuffer<char, 64> canon_ip; + canonicalizeIPAddress(output.data(), URLComponent::fromRange(outputBegin, output.length()), canon_ip, hostInfo); + + // If we got an IPv4/IPv6 address, copy the canonical form back to the + // real buffer. Otherwise, it's a hostname or broken IP, in which case + // we just leave it in place. + if (hostInfo.IsIPAddress()) { + output.setLength(outputBegin); + output.append(canon_ip.data(), canon_ip.length()); + } + } + + hostInfo.ouputHost = URLComponent::fromRange(outputBegin, output.length()); +} + +} // namespace + +bool canonicalizeHost(const char* spec, const URLComponent& host, URLBuffer<char>& output, URLComponent& ouputHost) +{ + CanonHostInfo hostInfo; + doHost<char, unsigned char>(spec, host, output, hostInfo); + ouputHost = hostInfo.ouputHost; + return (hostInfo.family != CanonHostInfo::BROKEN); +} + +bool canonicalizeHost(const UChar* spec, const URLComponent& host, URLBuffer<char>& output, URLComponent& ouputHost) +{ + CanonHostInfo hostInfo; + doHost<UChar, UChar>(spec, host, output, hostInfo); + ouputHost = hostInfo.ouputHost; + return (hostInfo.family != CanonHostInfo::BROKEN); +} + +} // namespace URLCanonicalizer + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonICU.cpp b/Source/WTF/wtf/url/src/URLCanonICU.cpp new file mode 100644 index 000000000..e61fa707a --- /dev/null +++ b/Source/WTF/wtf/url/src/URLCanonICU.cpp @@ -0,0 +1,187 @@ +/* + * Copyright 2011 Google Inc. All rights reserved. + * Copyright 2012 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. + */ + +// ICU integration functions. + +#include "config.h" + +#if USE(WTFURL) + +#include "URLCanonInternal.h" // for _itoa_s +#include <stdlib.h> +#include <string.h> +#include <unicode/ucnv.h> +#include <unicode/ucnv_cb.h> +#include <unicode/uidna.h> + +namespace WTF { + +namespace URLCanonicalizer { + +namespace { + +// Called when converting a character that can not be represented, this will +// append an escaped version of the numerical character reference for that code +// point. It is of the form "Ӓ" and we will escape the non-digits to +// "%26%231234%3B". Why? This is what Netscape did back in the olden days. +void appendURLEscapedChar(const void* /* context */, + UConverterFromUnicodeArgs* fromArgs, + const UChar* /* code_units */, + int32_t /* length */, + UChar32 codePoint, + UConverterCallbackReason reason, + UErrorCode* err) +{ + if (reason == UCNV_UNASSIGNED) { + *err = U_ZERO_ERROR; + + const static int prefixLength = 6; + const static char prefix[prefixLength + 1] = "%26%23"; // "&#" percent-escaped + ucnv_cbFromUWriteBytes(fromArgs, prefix, prefixLength, 0, err); + + ASSERT(codePoint < 0x110000); + char number[8]; // Max Unicode code point is 7 digits. + _itoa_s(codePoint, number, 10); + int numberLength = static_cast<int>(strlen(number)); + ucnv_cbFromUWriteBytes(fromArgs, number, numberLength, 0, err); + + const static int postfixLength = 3; + const static char postfix[postfixLength + 1] = "%3B"; // ";" percent-escaped + ucnv_cbFromUWriteBytes(fromArgs, postfix, postfixLength, 0, err); + } +} + +// A class for scoping the installation of the invalid character callback. +class AppendHandlerInstaller { +public: + // The owner of this object must ensure that the converter is alive for the + // duration of this object's lifetime. + AppendHandlerInstaller(UConverter* converter) + : m_converter(converter) + { + UErrorCode err = U_ZERO_ERROR; + ucnv_setFromUCallBack(m_converter, appendURLEscapedChar, 0, &m_oldCallback, &m_oldContext, &err); + } + + ~AppendHandlerInstaller() + { + UErrorCode err = U_ZERO_ERROR; + ucnv_setFromUCallBack(m_converter, m_oldCallback, m_oldContext, 0, 0, &err); + } + +private: + UConverter* m_converter; + + UConverterFromUCallback m_oldCallback; + const void* m_oldContext; +}; + +} // namespace + +// Converts the Unicode input representing a hostname to ASCII using IDN rules. +// The output must be ASCII, but is represented as wide characters. +// +// On success, the output will be filled with the ASCII host name and it will +// return true. Unlike most other canonicalization functions, this assumes that +// the output is empty. The beginning of the host will be at offset 0, and +// the length of the output will be set to the length of the new host name. +// +// On error, this will return false. The output in this case is undefined. +bool IDNToASCII(const UChar* src, int sourceLength, URLBuffer<UChar>& output) +{ + ASSERT(!output.length()); // Output buffer is assumed empty. + while (true) { + // Use ALLOW_UNASSIGNED to be more tolerant of hostnames that violate + // the spec (which do exist). This does not present any risk and is a + // little more future proof. + UErrorCode err = U_ZERO_ERROR; + int numConverted = uidna_IDNToASCII(src, sourceLength, output.data(), + output.capacity(), + UIDNA_ALLOW_UNASSIGNED, 0, &err); + if (err == U_ZERO_ERROR) { + output.setLength(numConverted); + return true; + } + if (err != U_BUFFER_OVERFLOW_ERROR) + return false; // Unknown error, give up. + + // Not enough room in our buffer, expand. + output.resize(output.capacity() * 2); + } +} + +bool readUTFChar(const char* str, int* begin, int length, unsigned* codePointOut) +{ + int codePoint; // Avoids warning when U8_NEXT writes -1 to it. + U8_NEXT(str, *begin, length, codePoint); + *codePointOut = static_cast<unsigned>(codePoint); + + // The ICU macro above moves to the next char, we want to point to the last + // char consumed. + (*begin)--; + + // Validate the decoded value. + if (U_IS_UNICODE_CHAR(codePoint)) + return true; + *codePointOut = kUnicodeReplacementCharacter; + return false; +} + +bool readUTFChar(const UChar* str, int* begin, int length, unsigned* codePoint) +{ + if (U16_IS_SURROGATE(str[*begin])) { + if (!U16_IS_SURROGATE_LEAD(str[*begin]) || *begin + 1 >= length || !U16_IS_TRAIL(str[*begin + 1])) { + // Invalid surrogate pair. + *codePoint = kUnicodeReplacementCharacter; + return false; + } + + // Valid surrogate pair. + *codePoint = U16_GET_SUPPLEMENTARY(str[*begin], str[*begin + 1]); + (*begin)++; + } else { + // Not a surrogate, just one 16-bit word. + *codePoint = str[*begin]; + } + + if (U_IS_UNICODE_CHAR(*codePoint)) + return true; + + // Invalid code point. + *codePoint = kUnicodeReplacementCharacter; + return false; +} + +} // namespace URLCanonicalizer + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonIP.cpp b/Source/WTF/wtf/url/src/URLCanonIP.cpp new file mode 100644 index 000000000..4462353cb --- /dev/null +++ b/Source/WTF/wtf/url/src/URLCanonIP.cpp @@ -0,0 +1,683 @@ +/* + * Copyright 2009 Google Inc. All rights reserved. + * Copyright 2012 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" + +#include "URLCanonInternal.h" +#include "URLCharacterTypes.h" +#include <limits> +#include <stdint.h> +#include <stdlib.h> + +#if USE(WTFURL) + +namespace WTF { + +namespace URLCanonicalizer { + +namespace { + +// Converts one of the character types that represent a numerical base to the +// corresponding base. +static inline int baseForType(URLCharacterTypes::CharacterTypes type) +{ + switch (type) { + case URLCharacterTypes::HexadecimalCharacter: + return 16; + case URLCharacterTypes::DecimalCharacter: + return 10; + case URLCharacterTypes::OctalCharacter: + return 8; + default: + return 0; + } +} + +// Converts an IPv4 component to a 32-bit number, while checking for overflow. +// +// Possible return values: +// - IPV4 - The number was valid, and did not overflow. +// - BROKEN - The input was numeric, but too large for a 32-bit field. +// - NEUTRAL - Input was not numeric. +// +// The input is assumed to be ASCII. FindIPv4Components should have stripped +// out any input that is greater than 7 bits. The components are assumed +// to be non-empty. +template<typename CharacterType> +CanonHostInfo::Family IPv4ComponentToNumber(const CharacterType* spec, const URLComponent& component, uint32_t* number) +{ + // Figure out the base + URLCharacterTypes::CharacterTypes base; + int basePrefixLength = 0; // Size of the prefix for this base. + if (spec[component.begin()] == '0') { + // Either hex or dec, or a standalone zero. + if (component.length() == 1) { + base = URLCharacterTypes::DecimalCharacter; + } else if (spec[component.begin() + 1] == 'X' || spec[component.begin() + 1] == 'x') { + base = URLCharacterTypes::HexadecimalCharacter; + basePrefixLength = 2; + } else { + base = URLCharacterTypes::OctalCharacter; + basePrefixLength = 1; + } + } else + base = URLCharacterTypes::DecimalCharacter; + + // Extend the prefix to consume all leading zeros. + while (basePrefixLength < component.length() && spec[component.begin() + basePrefixLength] == '0') + ++basePrefixLength; + + // Put the component, minus any base prefix, into a zero-terminated buffer so + // we can call the standard library. Because leading zeros have already been + // discarded, filling the entire buffer is guaranteed to trigger the 32-bit + // overflow check. + const int kMaxComponentLen = 16; + char buf[kMaxComponentLen + 1]; // digits + '\0' + int destI = 0; + for (int i = component.begin() + basePrefixLength; i < component.end(); i++) { + // We know the input is 7-bit, so convert to narrow (if this is the wide + // version of the template) by casting. + char input = static_cast<char>(spec[i]); + + // Validate that this character is OK for the given base. + if (!URLCharacterTypes::isCharacterOfType(input, base)) + return CanonHostInfo::NEUTRAL; + + // Fill the buffer, if there's space remaining. This check allows us to + // verify that all characters are numeric, even those that don't fit. + if (destI < kMaxComponentLen) + buf[destI++] = input; + } + + buf[destI] = '\0'; + + // Use the 64-bit strtoi so we get a big number (no hex, decimal, or octal + // number can overflow a 64-bit number in <= 16 characters). + uint64_t num = _strtoui64(buf, 0, baseForType(base)); + + // Check for 32-bit overflow. + if (num > std::numeric_limits<uint32_t>::max()) + return CanonHostInfo::BROKEN; + + // No overflow. Success! + *number = static_cast<uint32_t>(num); + return CanonHostInfo::IPV4; +} + +template<typename CharacterType, typename UCHAR> +bool doFindIPv4Components(const CharacterType* spec, const URLComponent& host, URLComponent components[4]) +{ + if (!host.isNonEmpty()) + return false; + + int currentComponent = 0; // Index of the component we're working on. + int currentComponentBegin = host.begin(); // Start of the current component. + int end = host.end(); + for (int i = host.begin(); /* nothing */; ++i) { + if (i >= end || spec[i] == '.') { + // Found the end of the current component. + int componentLength = i - currentComponentBegin; + components[currentComponent] = URLComponent(currentComponentBegin, componentLength); + + // The next component starts after the dot. + currentComponentBegin = i + 1; + currentComponent++; + + // Don't allow empty components (two dots in a row), except we may + // allow an empty component at the end (this would indicate that the + // input ends in a dot). We also want to error if the component is + // empty and it's the only component (currentComponent == 1). + if (!componentLength && (i < end || currentComponent == 1)) + return false; + + if (i >= end) + break; // End of the input. + + if (currentComponent == 4) { + // Anything else after the 4th component is an error unless it is a + // dot that would otherwise be treated as the end of input. + if (spec[i] == '.' && i + 1 == end) + break; + return false; + } + } else if (static_cast<UCHAR>(spec[i]) >= 0x80 || !URLCharacterTypes::isIPv4Char(static_cast<unsigned char>(spec[i]))) { + // Invalid character for an IPv4 address. + return false; + } + } + + // Fill in any unused components. + while (currentComponent < 4) + components[currentComponent++] = URLComponent(); + return true; +} + +static bool FindIPv4Components(const char* spec, const URLComponent& host, URLComponent components[4]) +{ + return doFindIPv4Components<char, unsigned char>(spec, host, components); +} + +static bool FindIPv4Components(const UChar* spec, const URLComponent& host, URLComponent components[4]) +{ + return doFindIPv4Components<UChar, UChar>(spec, host, components); +} + +template<typename CharacterType> +CanonHostInfo::Family doIPv4AddressToNumber(const CharacterType* spec, const URLComponent& host, unsigned char address[4], int& ipv4ComponentsCount) +{ + // The identified components. Not all may exist. + URLComponent components[4]; + if (!FindIPv4Components(spec, host, components)) + return CanonHostInfo::NEUTRAL; + + // Convert existing components to digits. Values up to + // |existingComponents| will be valid. + uint32_t componentValues[4]; + int existingComponents = 0; + + // Set to true if one or more components are BROKEN. BROKEN is only + // returned if all components are IPV4 or BROKEN, so, for example, + // 12345678912345.de returns NEUTRAL rather than broken. + bool broken = false; + for (int i = 0; i < 4; i++) { + if (components[i].length() <= 0) + continue; + CanonHostInfo::Family family = IPv4ComponentToNumber(spec, components[i], &componentValues[existingComponents]); + + if (family == CanonHostInfo::BROKEN) + broken = true; + else if (family != CanonHostInfo::IPV4) { + // Stop if we hit a non-BROKEN invalid non-empty component. + return family; + } + + existingComponents++; + } + + if (broken) + return CanonHostInfo::BROKEN; + + // Use that sequence of numbers to fill out the 4-component IP address. + + // First, process all components but the last, while making sure each fits + // within an 8-bit field. + for (int i = 0; i < existingComponents - 1; i++) { + if (componentValues[i] > std::numeric_limits<uint8_t>::max()) + return CanonHostInfo::BROKEN; + address[i] = static_cast<unsigned char>(componentValues[i]); + } + + // Next, consume the last component to fill in the remaining bytes. + uint32_t lastValue = componentValues[existingComponents - 1]; + for (int i = 3; i >= existingComponents - 1; i--) { + address[i] = static_cast<unsigned char>(lastValue); + lastValue >>= 8; + } + + // If the last component has residual bits, report overflow. + if (lastValue) + return CanonHostInfo::BROKEN; + + // Tell the caller how many components we saw. + ipv4ComponentsCount = existingComponents; + + // Success! + return CanonHostInfo::IPV4; +} + +static inline void appendIPv4Address(const unsigned char address[4], URLBuffer<char>& output) +{ + for (int i = 0; i < 4; ++i) { + char buffer[16]; + _itoa_s(address[i], buffer, 10); + + for (int ch = 0; buffer[ch]; ch++) + output.append(buffer[ch]); + + if (i != 3) + output.append('.'); + } +} + +// Return true if we've made a final IPV4/BROKEN decision, false if the result +// is NEUTRAL, and we could use a second opinion. +template<typename CharacterType, typename UCHAR> +bool doCanonicalizeIPv4Address(const CharacterType* spec, const URLComponent& host, URLBuffer<char>& output, CanonHostInfo& hostInfo) +{ + hostInfo.family = doIPv4AddressToNumber(spec, host, hostInfo.address, hostInfo.ipv4ComponentsCount); + + switch (hostInfo.family) { + case CanonHostInfo::IPV4: + // Definitely an IPv4 address. + hostInfo.ouputHost.setBegin(output.length()); + appendIPv4Address(hostInfo.address, output); + hostInfo.ouputHost.setLength(output.length() - hostInfo.ouputHost.begin()); + return true; + case CanonHostInfo::BROKEN: + // Definitely broken. + return true; + default: + // Could be IPv6 or a hostname. + return false; + } +} + +// Helper class that describes the main components of an IPv6 input string. +// See the following examples to understand how it breaks up an input string: +// +// [Example 1]: input = "[::aa:bb]" +// ==> numHexComponents = 2 +// ==> hexComponents[0] = Component(3,2) "aa" +// ==> hexComponents[1] = Component(6,2) "bb" +// ==> indexOfContraction = 0 +// ==> ipv4Component = Component(0, -1) +// +// [Example 2]: input = "[1:2::3:4:5]" +// ==> numHexComponents = 5 +// ==> hexComponents[0] = Component(1,1) "1" +// ==> hexComponents[1] = Component(3,1) "2" +// ==> hexComponents[2] = Component(6,1) "3" +// ==> hexComponents[3] = Component(8,1) "4" +// ==> hexComponents[4] = Component(10,1) "5" +// ==> indexOfContraction = 2 +// ==> ipv4Component = Component(0, -1) +// +// [Example 3]: input = "[::ffff:192.168.0.1]" +// ==> numHexComponents = 1 +// ==> hexComponents[0] = Component(3,4) "ffff" +// ==> indexOfContraction = 0 +// ==> ipv4Component = Component(8, 11) "192.168.0.1" +// +// [Example 4]: input = "[1::]" +// ==> numHexComponents = 1 +// ==> hexComponents[0] = Component(1,1) "1" +// ==> indexOfContraction = 1 +// ==> ipv4Component = Component(0, -1) +// +// [Example 5]: input = "[::192.168.0.1]" +// ==> numHexComponents = 0 +// ==> indexOfContraction = 0 +// ==> ipv4Component = Component(8, 11) "192.168.0.1" +// +struct IPv6Parsed { + // Zero-out the parse information. + void reset() + { + numHexComponents = 0; + indexOfContraction = -1; + ipv4Component.reset(); + } + + // There can be up to 8 hex components (colon separated) in the literal. + URLComponent hexComponents[8]; + + // The count of hex components present. Ranges from [0,8]. + int numHexComponents; + + // The index of the hex component that the "::" contraction precedes, or + // -1 if there is no contraction. + int indexOfContraction; + + // The range of characters which are an IPv4 literal. + URLComponent ipv4Component; +}; + +// Parse the IPv6 input string. If parsing succeeded returns true and fills +// |parsed| with the information. If parsing failed (because the input is +// invalid) returns false. +template<typename CharacterType, typename UCHAR> +bool doParseIPv6(const CharacterType* spec, const URLComponent& host, IPv6Parsed& parsed) +{ + // Zero-out the info. + parsed.reset(); + + if (!host.isNonEmpty()) + return false; + + // The index for start and end of address range (no brackets). + int begin = host.begin(); + int end = host.end(); + + int currentComponentBegin = begin; // Start of the current component. + + // Scan through the input, searching for hex components, "::" contractions, + // and IPv4 components. + for (int i = begin; /* i <= end */; i++) { + bool isColon = spec[i] == ':'; + bool isContraction = isColon && i < end - 1 && spec[i + 1] == ':'; + + // We reached the end of the current component if we encounter a colon + // (separator between hex components, or start of a contraction), or end of + // input. + if (isColon || i == end) { + int componentLength = i - currentComponentBegin; + + // A component should not have more than 4 hex digits. + if (componentLength > 4) + return false; + + // Don't allow empty components. + if (!componentLength) { + // The exception is when contractions appear at beginning of the + // input or at the end of the input. + if (!((isContraction && i == begin) || (i == end && parsed.indexOfContraction == parsed.numHexComponents))) + return false; + } + + // Add the hex component we just found to running list. + if (componentLength > 0) { + // Can't have more than 8 components! + if (parsed.numHexComponents >= 8) + return false; + + parsed.hexComponents[parsed.numHexComponents++] = + URLComponent(currentComponentBegin, componentLength); + } + } + + if (i == end) + break; // Reached the end of the input, DONE. + + // We found a "::" contraction. + if (isContraction) { + // There can be at most one contraction in the literal. + if (parsed.indexOfContraction != -1) + return false; + parsed.indexOfContraction = parsed.numHexComponents; + ++i; // Consume the colon we peeked. + } + + if (isColon) { + // Colons are separators between components, keep track of where the + // current component started (after this colon). + currentComponentBegin = i + 1; + } else { + if (static_cast<UCHAR>(spec[i]) >= 0x80) + return false; // Not ASCII. + + if (!URLCharacterTypes::isHexChar(static_cast<unsigned char>(spec[i]))) { + // Regular components are hex numbers. It is also possible for + // a component to be an IPv4 address in dotted form. + if (URLCharacterTypes::isIPv4Char(static_cast<unsigned char>(spec[i]))) { + // Since IPv4 address can only appear at the end, assume the rest + // of the string is an IPv4 address. (We will parse this separately + // later). + parsed.ipv4Component = URLComponent::fromRange(currentComponentBegin, end); + break; + } + // The character was neither a hex digit, nor an IPv4 character. + return false; + } + } + } + + return true; +} + +// Verifies the parsed IPv6 information, checking that the various components +// add up to the right number of bits (hex components are 16 bits, while +// embedded IPv4 formats are 32 bits, and contractions are placeholdes for +// 16 or more bits). Returns true if sizes match up, false otherwise. On +// success writes the length of the contraction (if any) to +// |outNumBytesOfContraction|. +bool CheckIPv6ComponentsSize(const IPv6Parsed& parsed, int* outNumBytesOfContraction) +{ + // Each group of four hex digits contributes 16 bits. + int numBytesWithoutContraction = parsed.numHexComponents * 2; + + // If an IPv4 address was embedded at the end, it contributes 32 bits. + if (parsed.ipv4Component.isValid()) + numBytesWithoutContraction += 4; + + // If there was a "::" contraction, its size is going to be: + // MAX([16bits], [128bits] - numBytesWithoutContraction). + int numBytesOfContraction = 0; + if (parsed.indexOfContraction != -1) { + numBytesOfContraction = 16 - numBytesWithoutContraction; + if (numBytesOfContraction < 2) + numBytesOfContraction = 2; + } + + // Check that the numbers add up. + if (numBytesWithoutContraction + numBytesOfContraction != 16) + return false; + + *outNumBytesOfContraction = numBytesOfContraction; + return true; +} + +// Converts a hex comonent into a number. This cannot fail since the caller has +// already verified that each character in the string was a hex digit, and +// that there were no more than 4 characters. +template<typename CharacterType> +uint16_t IPv6HexComponentToNumber(const CharacterType* spec, const URLComponent& component) +{ + ASSERT(component.length() <= 4); + + // Copy the hex string into a C-string. + char buf[5]; + for (int i = 0; i < component.length(); ++i) + buf[i] = static_cast<char>(spec[component.begin() + i]); + buf[component.length()] = '\0'; + + // Convert it to a number (overflow is not possible, since with 4 hex + // characters we can at most have a 16 bit number). + return static_cast<uint16_t>(_strtoui64(buf, 0, 16)); +} + +// Converts an IPv6 address to a 128-bit number (network byte order), returning +// true on success. False means that the input was not a valid IPv6 address. +template<typename CharacterType, typename UCHAR> +bool doIPv6AddressToNumber(const CharacterType* spec, + const URLComponent& host, + unsigned char address[16]) +{ + // Make sure the component is bounded by '[' and ']'. + int end = host.end(); + if (!host.isNonEmpty() || spec[host.begin()] != '[' || spec[end - 1] != ']') + return false; + + // Exclude the square brackets. + URLComponent ipv6Component(host.begin() + 1, host.length() - 2); + + // Parse the IPv6 address -- identify where all the colon separated hex + // components are, the "::" contraction, and the embedded IPv4 address. + IPv6Parsed ipv6Parsed; + if (!doParseIPv6<CharacterType, UCHAR>(spec, ipv6Component, ipv6Parsed)) + return false; + + // Do some basic size checks to make sure that the address doesn't + // specify more than 128 bits or fewer than 128 bits. This also resolves + // how may zero bytes the "::" contraction represents. + int numBytesOfContraction; + if (!CheckIPv6ComponentsSize(ipv6Parsed, &numBytesOfContraction)) + return false; + + int currentIndexInAddress = 0; + + // Loop through each hex components, and contraction in order. + for (int i = 0; i <= ipv6Parsed.numHexComponents; ++i) { + // Append the contraction if it appears before this component. + if (i == ipv6Parsed.indexOfContraction) { + for (int j = 0; j < numBytesOfContraction; ++j) + address[currentIndexInAddress++] = 0; + } + // Append the hex component's value. + if (i != ipv6Parsed.numHexComponents) { + // Get the 16-bit value for this hex component. + uint16_t number = IPv6HexComponentToNumber<CharacterType>(spec, ipv6Parsed.hexComponents[i]); + // Append to |address|, in network byte order. + address[currentIndexInAddress++] = (number & 0xFF00) >> 8; + address[currentIndexInAddress++] = (number & 0x00FF); + } + } + + // If there was an IPv4 section, convert it into a 32-bit number and append + // it to |address|. + if (ipv6Parsed.ipv4Component.isValid()) { + // Append the 32-bit number to |address|. + int ignoredIPv4ComponentsCount; + if (CanonHostInfo::IPV4 != + doIPv4AddressToNumber(spec, ipv6Parsed.ipv4Component, &address[currentIndexInAddress], ignoredIPv4ComponentsCount)) + return false; + } + + return true; +} + +// Searches for the longest sequence of zeros in |address|, and writes the +// range into |contractionRange|. The run of zeros must be at least 16 bits, +// and if there is a tie the first is chosen. +void ChooseIPv6ContractionRange(const unsigned char address[16], URLComponent* contractionRange) +{ + // The longest run of zeros in |address| seen so far. + URLComponent maxRange; + + // The current run of zeros in |address| being iterated over. + URLComponent currentRange; + + for (int i = 0; i < 16; i += 2) { + // Test for 16 bits worth of zero. + bool isZero = (!address[i] && !address[i + 1]); + + if (isZero) { + // Add the zero to the current range (or start a new one). + if (!currentRange.isValid()) + currentRange = URLComponent(i, 0); + currentRange.setLength(currentRange.length() + 2); + } + + if (!isZero || i == 14) { + // Just completed a run of zeros. If the run is greater than 16 bits, + // it is a candidate for the contraction. + if (currentRange.length() > 2 && currentRange.length() > maxRange.length()) + maxRange = currentRange; + + currentRange.reset(); + } + } + *contractionRange = maxRange; +} + +static inline void appendIPv6Address(const unsigned char address[16], URLBuffer<char>& output) +{ + // We will output the address according to the rules in: + // http://tools.ietf.org/html/draft-kawamura-ipv6-text-representation-01#section-4 + + // Start by finding where to place the "::" contraction (if any). + URLComponent contractionRange; + ChooseIPv6ContractionRange(address, &contractionRange); + + for (int i = 0; i <= 14;) { + // We check 2 bytes at a time, from bytes (0, 1) to (14, 15), inclusive. + ASSERT(!(i % 2)); + if (i == contractionRange.begin() && contractionRange.length() > 0) { + // Jump over the contraction. + if (!i) + output.append(':'); + output.append(':'); + i = contractionRange.end(); + } else { + // Consume the next 16 bits from |address|. + int x = address[i] << 8 | address[i + 1]; + + i += 2; + + // Stringify the 16 bit number (at most requires 4 hex digits). + char str[5]; + _itoa_s(x, str, 16); + for (int ch = 0; str[ch]; ++ch) + output.append(str[ch]); + + // Put a colon after each number, except the last. + if (i < 16) + output.append(':'); + } + } +} + +// Return true if we've made a final IPV6/BROKEN decision, false if the result +// is NEUTRAL, and we could use a second opinion. +template<typename CharacterType, typename UCHAR> +bool doCanonicalizeIPv6Address(const CharacterType* spec, const URLComponent& host, URLBuffer<char>& output, CanonHostInfo& hostInfo) +{ + // Turn the IP address into a 128 bit number. + if (!doIPv6AddressToNumber<CharacterType, UCHAR>(spec, host, hostInfo.address)) { + // If it's not an IPv6 address, scan for characters that should *only* + // exist in an IPv6 address. + for (int i = host.begin(); i < host.end(); i++) { + switch (spec[i]) { + case '[': + case ']': + case ':': + hostInfo.family = CanonHostInfo::BROKEN; + return true; + } + } + + // No invalid characters. Could still be IPv4 or a hostname. + hostInfo.family = CanonHostInfo::NEUTRAL; + return false; + } + + hostInfo.ouputHost.setBegin(output.length()); + output.append('['); + appendIPv6Address(hostInfo.address, output); + output.append(']'); + hostInfo.ouputHost.setLength(output.length() - hostInfo.ouputHost.begin()); + + hostInfo.family = CanonHostInfo::IPV6; + return true; +} + +} // namespace + +void canonicalizeIPAddress(const char* spec, const URLComponent& host, URLBuffer<char>& output, CanonHostInfo& hostInfo) +{ + if (doCanonicalizeIPv4Address<char, unsigned char>(spec, host, output, hostInfo)) + return; + if (doCanonicalizeIPv6Address<char, unsigned char>(spec, host, output, hostInfo)) + return; +} + +void canonicalizeIPAddress(const UChar* spec, const URLComponent& host, URLBuffer<char>& output, CanonHostInfo& hostInfo) +{ + if (doCanonicalizeIPv4Address<UChar, UChar>(spec, host, output, hostInfo)) + return; + if (doCanonicalizeIPv6Address<UChar, UChar>(spec, host, output, hostInfo)) + return; +} + +} // namespace URLCanonicalizer + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonInternal.cpp b/Source/WTF/wtf/url/src/URLCanonInternal.cpp new file mode 100644 index 000000000..b7ae09814 --- /dev/null +++ b/Source/WTF/wtf/url/src/URLCanonInternal.cpp @@ -0,0 +1,310 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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" +#include "URLCanonInternal.h" + +#include <cstdio> +#include <errno.h> +#include <stdlib.h> +#include <string> + +#if USE(WTFURL) + +namespace WTF { + +namespace URLCanonicalizer { + +namespace { + +template<typename CharacterType, typename UCHAR> +void doAppendStringOfType(const CharacterType* source, int length, URLCharacterTypes::CharacterTypes type, URLBuffer<char>& output) +{ + for (int i = 0; i < length; ++i) { + if (static_cast<UCHAR>(source[i]) >= 0x80) { + // ReadChar will fill the code point with kUnicodeReplacementCharacter + // when the input is invalid, which is what we want. + unsigned codePoint; + readUTFChar(source, &i, length, &codePoint); + AppendUTF8EscapedValue(codePoint, output); + } else { + // Just append the 7-bit character, possibly escaping it. + unsigned char uch = static_cast<unsigned char>(source[i]); + if (!URLCharacterTypes::isCharacterOfType(uch, type)) + appendURLEscapedCharacter(uch, output); + else + output.append(uch); + } + } +} + +// This function assumes the input values are all contained in 8-bit, +// although it allows any type. Returns true if input is valid, false if not. +template<typename CharacterType, typename UCHAR> +void doAppendInvalidNarrowString(const CharacterType* spec, int begin, int end, URLBuffer<char>& output) +{ + for (int i = begin; i < end; ++i) { + UCHAR uch = static_cast<UCHAR>(spec[i]); + if (uch >= 0x80) { + // Handle UTF-8/16 encodings. This call will correctly handle the error + // case by appending the invalid character. + AppendUTF8EscapedChar(spec, &i, end, output); + } else if (uch <= ' ' || uch == 0x7f) { + // This function is for error handling, so we escape all control + // characters and spaces, but not anything else since we lack + // context to do something more specific. + appendURLEscapedCharacter(static_cast<unsigned char>(uch), output); + } else + output.append(static_cast<char>(uch)); + } +} + +// Overrides one component, see the URLCanonicalizer::Replacements structure for +// what the various combionations of source pointer and component mean. +void doOverrideComponent(const char* overrideSource, const URLComponent& overrideComponent, const char*& destination, URLComponent& destinationComponent) +{ + if (overrideSource) { + destination = overrideSource; + destinationComponent = overrideComponent; + } +} + +// Similar to doOverrideComponent except that it takes a UTF-16 input and does +// not actually set the output character pointer. +// +// The input is converted to UTF-8 at the end of the given buffer as a temporary +// holding place. The component indentifying the portion of the buffer used in +// the |utf8Buffer| will be specified in |*destinationComponent|. +// +// This will not actually set any |dest| pointer like doOverrideComponent +// does because all of the pointers will point into the |utf8Buffer|, which +// may get resized while we're overriding a subsequent component. Instead, the +// caller should use the beginning of the |utf8Buffer| as the string pointer +// for all components once all overrides have been prepared. +bool PrepareUTF16OverrideComponent(const UChar* overrideSource, + const URLComponent& overrideComponent, + URLBuffer<char>& utf8Buffer, + URLComponent* destinationComponent) +{ + bool success = true; + if (overrideSource) { + if (!overrideComponent.isValid()) { + // Non-"valid" component (means delete), so we need to preserve that. + *destinationComponent = URLComponent(); + } else { + // Convert to UTF-8. + destinationComponent->setBegin(utf8Buffer.length()); + success = ConvertUTF16ToUTF8(&overrideSource[overrideComponent.begin()], + overrideComponent.length(), utf8Buffer); + destinationComponent->setLength(utf8Buffer.length() - destinationComponent->begin()); + } + } + return success; +} + +} // namespace + +const char kCharToHexLookup[8] = { + 0, // 0x00 - 0x1f + '0', // 0x20 - 0x3f: digits 0 - 9 are 0x30 - 0x39 + 'A' - 10, // 0x40 - 0x5f: letters A - F are 0x41 - 0x46 + 'a' - 10, // 0x60 - 0x7f: letters a - f are 0x61 - 0x66 + 0, // 0x80 - 0x9F + 0, // 0xA0 - 0xBF + 0, // 0xC0 - 0xDF + 0, // 0xE0 - 0xFF +}; + +const UChar kUnicodeReplacementCharacter = 0xfffd; + +void appendStringOfType(const char* source, int length, URLCharacterTypes::CharacterTypes urlComponentType, URLBuffer<char>& output) +{ + doAppendStringOfType<char, unsigned char>(source, length, urlComponentType, output); +} + +void appendStringOfType(const UChar* source, int length, URLCharacterTypes::CharacterTypes urlComponentType, URLBuffer<char>& output) +{ + doAppendStringOfType<UChar, UChar>(source, length, urlComponentType, output); +} + +void AppendInvalidNarrowString(const char* spec, int begin, int end, URLBuffer<char>& output) +{ + doAppendInvalidNarrowString<char, unsigned char>(spec, begin, end, output); +} + +void AppendInvalidNarrowString(const UChar* spec, int begin, int end, URLBuffer<char>& output) +{ + doAppendInvalidNarrowString<UChar, UChar>(spec, begin, end, output); +} + +bool ConvertUTF16ToUTF8(const UChar* input, int inputLength, URLBuffer<char>& output) +{ + bool success = true; + for (int i = 0; i < inputLength; ++i) { + unsigned codePoint; + success &= readUTFChar(input, &i, inputLength, &codePoint); + AppendUTF8Value(codePoint, output); + } + return success; +} + +bool ConvertUTF8ToUTF16(const char* input, int inputLength, URLBuffer<UChar>& output) +{ + bool success = true; + for (int i = 0; i < inputLength; i++) { + unsigned codePoint; + success &= readUTFChar(input, &i, inputLength, &codePoint); + AppendUTF16Value(codePoint, output); + } + return success; +} + +void SetupOverrideComponents(const char* /* base */, + const Replacements<char>& repl, + URLComponentSource<char>* source, + URLSegments* parsed) +{ + // Get the source and parsed structures of the things we are replacing. + const URLComponentSource<char>& replSource = repl.sources(); + const URLSegments& replParsed = repl.components(); + + doOverrideComponent(replSource.scheme, replParsed.scheme, source->scheme, parsed->scheme); + doOverrideComponent(replSource.username, replParsed.username, source->username, parsed->username); + doOverrideComponent(replSource.password, replParsed.password, source->password, parsed->password); + + // Our host should be empty if not present, so override the default setup. + doOverrideComponent(replSource.host, replParsed.host, source->host, parsed->host); + if (parsed->host.length() == -1) + parsed->host.setLength(0); + + doOverrideComponent(replSource.port, replParsed.port, source->port, parsed->port); + doOverrideComponent(replSource.path, replParsed.path, source->path, parsed->path); + doOverrideComponent(replSource.query, replParsed.query, source->query, parsed->query); + doOverrideComponent(replSource.ref, replParsed.fragment, source->ref, parsed->fragment); +} + +bool SetupUTF16OverrideComponents(const char* /* base */, + const Replacements<UChar>& repl, + URLBuffer<char>& utf8Buffer, + URLComponentSource<char>* source, + URLSegments* parsed) + { + bool success = true; + + // Get the source and parsed structures of the things we are replacing. + const URLComponentSource<UChar>& replSource = repl.sources(); + const URLSegments& replParsed = repl.components(); + + success &= PrepareUTF16OverrideComponent(replSource.scheme, replParsed.scheme, + utf8Buffer, &parsed->scheme); + success &= PrepareUTF16OverrideComponent(replSource.username, replParsed.username, + utf8Buffer, &parsed->username); + success &= PrepareUTF16OverrideComponent(replSource.password, replParsed.password, + utf8Buffer, &parsed->password); + success &= PrepareUTF16OverrideComponent(replSource.host, replParsed.host, + utf8Buffer, &parsed->host); + success &= PrepareUTF16OverrideComponent(replSource.port, replParsed.port, + utf8Buffer, &parsed->port); + success &= PrepareUTF16OverrideComponent(replSource.path, replParsed.path, + utf8Buffer, &parsed->path); + success &= PrepareUTF16OverrideComponent(replSource.query, replParsed.query, + utf8Buffer, &parsed->query); + success &= PrepareUTF16OverrideComponent(replSource.ref, replParsed.fragment, + utf8Buffer, &parsed->fragment); + + // PrepareUTF16OverrideComponent will not have set the data pointer since the + // buffer could be resized, invalidating the pointers. We set the data + // pointers for affected components now that the buffer is finalized. + if (replSource.scheme) + source->scheme = utf8Buffer.data(); + if (replSource.username) + source->username = utf8Buffer.data(); + if (replSource.password) + source->password = utf8Buffer.data(); + if (replSource.host) + source->host = utf8Buffer.data(); + if (replSource.port) + source->port = utf8Buffer.data(); + if (replSource.path) + source->path = utf8Buffer.data(); + if (replSource.query) + source->query = utf8Buffer.data(); + if (replSource.ref) + source->ref = utf8Buffer.data(); + + return success; +} + +#if !OS(WINDOWS) +int _itoa_s(int value, char* buffer, size_t sizeInChars, int radix) +{ + int written; + if (radix == 10) + written = snprintf(buffer, sizeInChars, "%d", value); + else if (radix == 16) + written = snprintf(buffer, sizeInChars, "%x", value); + else + return EINVAL; + + if (static_cast<size_t>(written) >= sizeInChars) { + // Output was truncated, or written was negative. + return EINVAL; + } + return 0; +} + +int _itow_s(int value, UChar* buffer, size_t sizeInChars, int radix) +{ + if (radix != 10) + return EINVAL; + + // No more than 12 characters will be required for a 32-bit integer. + // Add an extra byte for the terminating null. + char temp[13]; + int written = snprintf(temp, sizeof(temp), "%d", value); + if (static_cast<size_t>(written) >= sizeInChars) { + // Output was truncated, or written was negative. + return EINVAL; + } + + for (int i = 0; i < written; ++i) + buffer[i] = static_cast<UChar>(temp[i]); + buffer[written] = '\0'; + return 0; +} + +#endif // !OS(WINDOWS) + +} // namespace URLCanonicalizer + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonInternal.h b/Source/WTF/wtf/url/src/URLCanonInternal.h new file mode 100644 index 000000000..9b2970632 --- /dev/null +++ b/Source/WTF/wtf/url/src/URLCanonInternal.h @@ -0,0 +1,394 @@ +/* + * Copyright 2011 Google Inc. All rights reserved. + * Copyright 2012 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. + */ + +// This file is intended to be included in another C++ file where the character +// types are defined. This allows us to write mostly generic code, but not have +// templace bloat because everything is inlined when anybody calls any of our +// functions. + +#ifndef URLCanonInternal_h +#define URLCanonInternal_h + +#include "URLCanon.h" +#include "URLCharacterTypes.h" +#include <stdlib.h> +#include <wtf/HexNumber.h> + +#if USE(WTFURL) + +namespace WTF { + +namespace URLCanonicalizer { + +// Appends the given string to the output, escaping characters that do not +// match the given |type| in SharedCharTypes. +void appendStringOfType(const char* source, int length, URLCharacterTypes::CharacterTypes urlComponentType, URLBuffer<char>& output); +void appendStringOfType(const UChar* source, int length, URLCharacterTypes::CharacterTypes urlComponentType, URLBuffer<char>& output); + +// This lookup table allows fast conversion between ASCII hex letters and their +// corresponding numerical value. The 8-bit range is divided up into 8 +// regions of 0x20 characters each. Each of the three character types (numbers, +// uppercase, lowercase) falls into different regions of this range. The table +// contains the amount to subtract from characters in that range to get at +// the corresponding numerical value. +// +// See HexDigitToValue for the lookup. +extern const char kCharToHexLookup[8]; + +// Assumes the input is a valid hex digit! Call isHexChar before using this. +inline unsigned char hexCharToValue(unsigned char character) +{ + return character - kCharToHexLookup[character / 0x20]; +} + +// Indicates if the given character is a dot or dot equivalent, returning the +// number of characters taken by it. This will be one for a literal dot, 3 for +// an escaped dot. If the character is not a dot, this will return 0. +template<typename CharacterType> +inline int isDot(const CharacterType* spec, int offset, int end) +{ + if (spec[offset] == '.') + return 1; + + if (spec[offset] == '%' && offset + 3 <= end && spec[offset + 1] == '2' && (spec[offset + 2] == 'e' || spec[offset + 2] == 'E')) { + // Found "%2e" + return 3; + } + return 0; +} + +// Returns the canonicalized version of the input character according to scheme +// rules. This is implemented alongside the scheme canonicalizer, and is +// required for relative URL resolving to test for scheme equality. +// +// Returns 0 if the input character is not a valid scheme character. +char canonicalSchemeChar(UChar); + +// Write a single character, escaped, to the output. This always escapes: it +// does no checking that thee character requires escaping. +// Escaping makes sense only 8 bit chars, so code works in all cases of +// input parameters (8/16bit). +template<typename InChar, typename OutChar> +inline void appendURLEscapedCharacter(InChar character, URLBuffer<OutChar>& buffer) +{ + buffer.append('%'); + buffer.append(WTF::Internal::upperHexDigits[character >> 4]); + buffer.append(WTF::Internal::upperHexDigits[character & 0xf]); +} + +// The character we'll substitute for undecodable or invalid characters. +extern const UChar kUnicodeReplacementCharacter; + +// UTF-8 functions ------------------------------------------------------------ + +// Reads one character in UTF-8 starting at |*begin| in |str| and places +// the decoded value into |*codePoint|. If the character is valid, we will +// return true. If invalid, we'll return false and put the +// kUnicodeReplacementCharacter into |*codePoint|. +// +// |*begin| will be updated to point to the last character consumed so it +// can be incremented in a loop and will be ready for the next character. +// (for a single-byte ASCII character, it will not be changed). +// +// Implementation is in URLCanonicalizer_icu.cc. +bool readUTFChar(const char* str, int* begin, int length, unsigned* codePointOut); + +// Generic To-UTF-8 converter. This will call the given append method for each +// character that should be appended, with the given output method. Wrappers +// are provided below for escaped and non-escaped versions of this. +// +// The charactervalue must have already been checked that it's a valid Unicode +// character. +template<class Output, void appendFunction(unsigned char, Output&)> +inline void doAppendUTF8(unsigned charactervalue, Output& output) +{ + if (charactervalue <= 0x7f) { + appendFunction(static_cast<unsigned char>(charactervalue), output); + } else if (charactervalue <= 0x7ff) { + // 110xxxxx 10xxxxxx + appendFunction(static_cast<unsigned char>(0xC0 | (charactervalue >> 6)), output); + appendFunction(static_cast<unsigned char>(0x80 | (charactervalue & 0x3f)), output); + } else if (charactervalue <= 0xffff) { + // 1110xxxx 10xxxxxx 10xxxxxx + appendFunction(static_cast<unsigned char>(0xe0 | (charactervalue >> 12)), output); + appendFunction(static_cast<unsigned char>(0x80 | ((charactervalue >> 6) & 0x3f)), output); + appendFunction(static_cast<unsigned char>(0x80 | (charactervalue & 0x3f)), output); + } else if (charactervalue <= 0x10FFFF) { // Max unicode code point. + // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + appendFunction(static_cast<unsigned char>(0xf0 | (charactervalue >> 18)), output); + appendFunction(static_cast<unsigned char>(0x80 | ((charactervalue >> 12) & 0x3f)), output); + appendFunction(static_cast<unsigned char>(0x80 | ((charactervalue >> 6) & 0x3f)), output); + appendFunction(static_cast<unsigned char>(0x80 | (charactervalue & 0x3f)), output); + } else { + // Invalid UTF-8 character (>20 bits). + ASSERT_NOT_REACHED(); + } +} + +// Helper used by AppendUTF8Value below. We use an unsigned parameter so there +// are no funny sign problems with the input, but then have to convert it to +// a regular char for appending. +inline void AppendCharToOutput(unsigned char character, URLBuffer<char>& output) +{ + output.append(static_cast<char>(character)); +} + +// Writes the given character to the output as UTF-8. This does NO checking +// of the validity of the unicode characters; the caller should ensure that +// the value it is appending is valid to append. +inline void AppendUTF8Value(unsigned charactervalue, URLBuffer<char>& output) +{ + doAppendUTF8<URLBuffer<char>, AppendCharToOutput>(charactervalue, output); +} + +// Writes the given character to the output as UTF-8, escaping ALL +// characters (even when they are ASCII). This does NO checking of the +// validity of the unicode characters; the caller should ensure that the value +// it is appending is valid to append. +inline void AppendUTF8EscapedValue(unsigned charactervalue, URLBuffer<char>& output) +{ + doAppendUTF8<URLBuffer<char>, appendURLEscapedCharacter>(charactervalue, output); +} + +// UTF-16 functions ----------------------------------------------------------- + +// Reads one character in UTF-16 starting at |*begin| in |str| and places +// the decoded value into |*codePoint|. If the character is valid, we will +// return true. If invalid, we'll return false and put the +// kUnicodeReplacementCharacter into |*codePoint|. +// +// |*begin| will be updated to point to the last character consumed so it +// can be incremented in a loop and will be ready for the next character. +// (for a single-16-bit-word character, it will not be changed). +// +// Implementation is in URLCanonicalizer_icu.cc. +bool readUTFChar(const UChar* str, int* begin, int length, unsigned* codePoint); + +// Equivalent to U16_APPEND_UNSAFE in ICU but uses our output method. +inline void AppendUTF16Value(unsigned codePoint, URLBuffer<UChar>& output) +{ + if (codePoint > 0xffff) { + output.append(static_cast<UChar>((codePoint >> 10) + 0xd7c0)); + output.append(static_cast<UChar>((codePoint & 0x3ff) | 0xdc00)); + } else + output.append(static_cast<UChar>(codePoint)); +} + +// Escaping functions --------------------------------------------------------- + +// Writes the given character to the output as UTF-8, escaped. Call this +// function only when the input is wide. Returns true on success. Failure +// means there was some problem with the encoding, we'll still try to +// update the |*begin| pointer and add a placeholder character to the +// output so processing can continue. +// +// We will append the character starting at ch[begin] with the buffer ch +// being |length|. |*begin| will be updated to point to the last character +// consumed (we may consume more than one for UTF-16) so that if called in +// a loop, incrementing the pointer will move to the next character. +// +// Every single output character will be escaped. This means that if you +// give it an ASCII character as input, it will be escaped. Some code uses +// this when it knows that a character is invalid according to its rules +// for validity. If you don't want escaping for ASCII characters, you will +// have to filter them out prior to calling this function. +// +// Assumes that ch[begin] is within range in the array, but does not assume +// that any following characters are. +inline bool AppendUTF8EscapedChar(const UChar* str, int* begin, int length, URLBuffer<char>& output) +{ + // UTF-16 input. ReadUChar will handle invalid characters for us and give + // us the kUnicodeReplacementCharacter, so we don't have to do special + // checking after failure, just pass through the failure to the caller. + unsigned charactervalue; + bool success = readUTFChar(str, begin, length, &charactervalue); + AppendUTF8EscapedValue(charactervalue, output); + return success; +} + +// Handles UTF-8 input. See the wide version above for usage. +inline bool AppendUTF8EscapedChar(const char* str, int* begin, int length, URLBuffer<char>& output) +{ + // ReadUTF8Char will handle invalid characters for us and give us the + // kUnicodeReplacementCharacter, so we don't have to do special checking + // after failure, just pass through the failure to the caller. + unsigned ch; + bool success = readUTFChar(str, begin, length, &ch); + AppendUTF8EscapedValue(ch, output); + return success; +} + +// Given a '%' character at |*begin| in the string |spec|, this will decode +// the escaped value and put it into |*unescapedValue| on success (returns +// true). On failure, this will return false, and will not write into +// |*unescapedValue|. +// +// |*begin| will be updated to point to the last character of the escape +// sequence so that when called with the index of a for loop, the next time +// through it will point to the next character to be considered. On failure, +// |*begin| will be unchanged. +inline bool Is8BitChar(char) +{ + return true; // this case is specialized to avoid a warning +} +inline bool Is8BitChar(UChar c) +{ + return c <= 255; +} + +template<typename CHAR> +inline bool DecodeEscaped(const CHAR* spec, int* begin, int end, unsigned char* unescapedValue) +{ + if (*begin + 3 > end || !Is8BitChar(spec[*begin + 1]) || !Is8BitChar(spec[*begin + 2])) { + // Invalid escape sequence because there's not enough room, or the + // digits are not ASCII. + return false; + } + + unsigned char first = static_cast<unsigned char>(spec[*begin + 1]); + unsigned char second = static_cast<unsigned char>(spec[*begin + 2]); + if (!URLCharacterTypes::isHexChar(first) || !URLCharacterTypes::isHexChar(second)) { + // Invalid hex digits, fail. + return false; + } + + // Valid escape sequence. + *unescapedValue = (hexCharToValue(first) << 4) + hexCharToValue(second); + *begin += 2; + return true; +} + +// Appends the given substring to the output, escaping "some" characters that +// it feels may not be safe. It assumes the input values are all contained in +// 8-bit although it allows any type. +// +// This is used in error cases to append invalid output so that it looks +// approximately correct. Non-error cases should not call this function since +// the escaping rules are not guaranteed! +void AppendInvalidNarrowString(const char* spec, int begin, int end, URLBuffer<char>& output); +void AppendInvalidNarrowString(const UChar* spec, int begin, int end, URLBuffer<char>& output); + +// Misc canonicalization helpers ---------------------------------------------- + +// Converts between UTF-8 and UTF-16, returning true on successful conversion. +// The output will be appended to the given canonicalizer output (so make sure +// it's empty if you want to replace). +// +// On invalid input, this will still write as much output as possible, +// replacing the invalid characters with the "invalid character". It will +// return false in the failure case, and the caller should not continue as +// normal. +bool ConvertUTF16ToUTF8(const UChar* input, int inputLength, URLBuffer<char>& output); +bool ConvertUTF8ToUTF16(const char* input, int inputLength, URLBuffer<UChar>& output); + +// Converts from UTF-16 to 8-bit using the character set converter. If the +// converter is null, this will use UTF-8. +void ConvertUTF16ToQueryEncoding(const UChar* input, const URLComponent& query, URLQueryCharsetConverter*, URLBuffer<char>& output); + +// Applies the replacements to the given component source. The component source +// should be pre-initialized to the "old" base. That is, all pointers will +// point to the spec of the old URL, and all of the Parsed components will +// be indices into that string. +// +// The pointers and components in the |source| for all non-null strings in the +// |repl| (replacements) will be updated to reference those strings. +// Canonicalizing with the new |source| and |parsed| can then combine URL +// components from many different strings. +void SetupOverrideComponents(const char* base, + const Replacements<char>&, + URLComponentSource<char>*, + URLSegments* parsed); + +// Like the above 8-bit version, except that it additionally converts the +// UTF-16 input to UTF-8 before doing the overrides. +// +// The given utf8Buffer is used to store the converted components. They will +// be appended one after another, with the parsed structure identifying the +// appropriate substrings. This buffer is a parameter because the source has +// no storage, so the buffer must have the same lifetime as the source +// parameter owned by the caller. +// +// THE CALLER MUST NOT ADD TO THE |utf8Buffer| AFTER THIS CALL. Members of +// |source| will point into this buffer, which could be invalidated if +// additional data is added and the CanonOutput resizes its buffer. +// +// Returns true on success. Fales means that the input was not valid UTF-16, +// although we will have still done the override with "invalid characters" in +// place of errors. +bool SetupUTF16OverrideComponents(const char* base, + const Replacements<UChar>&, + URLBuffer<char>& utf8Buffer, + URLComponentSource<char>*, + URLSegments* parsed); + +// Implemented in URLCanonicalizer_path.cc, these are required by the relative URL +// resolver as well, so we declare them here. +bool CanonicalizePartialPath(const char* spec, + const URLComponent& path, + int pathBeginInOutput, + URLBuffer<char>& output); +bool CanonicalizePartialPath(const UChar* spec, + const URLComponent& path, + int pathBeginInOutput, + URLBuffer<char>& output); + +#if !OS(WINDOWS) +// Implementations of Windows' int-to-string conversions +int _itoa_s(int value, char* buffer, size_t sizeInChars, int radix); +int _itow_s(int value, UChar* buffer, size_t sizeInChars, int radix); + +// Secure template overloads for these functions +template<size_t N> +inline int _itoa_s(int value, char (&buffer)[N], int radix) +{ + return _itoa_s(value, buffer, N, radix); +} + +template<size_t N> +inline int _itow_s(int value, UChar (&buffer)[N], int radix) +{ + return _itow_s(value, buffer, N, radix); +} + +// _strtoui64 and strtoull behave the same +inline unsigned long long _strtoui64(const char* nptr, char** endptr, int base) +{ + return strtoull(nptr, endptr, base); +} +#endif // OS(WINDOWS) + +} // namespace URLCanonicalizer + +} // namespace WTF + +#endif // USE(WTFURL) + +#endif // URLCanonInternal_h diff --git a/Source/WTF/wtf/url/src/URLCanonMailto.cpp b/Source/WTF/wtf/url/src/URLCanonMailto.cpp new file mode 100644 index 000000000..bdb353845 --- /dev/null +++ b/Source/WTF/wtf/url/src/URLCanonMailto.cpp @@ -0,0 +1,134 @@ +/* + * Copyright 2008 Google Inc. All rights reserved. + * Copyright 2012 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. + */ + +// Functions for canonicalizing "mailto:" URLs. + +#include "config.h" +#include "URLCanon.h" + +#include "RawURLBuffer.h" +#include "URLCanonInternal.h" +#include "URLFile.h" +#include "URLParseInternal.h" + +#if USE(WTFURL) + +namespace WTF { + +namespace URLCanonicalizer { + +namespace { + + +template<typename CharacterType, typename UCHAR> +bool doCanonicalizeMailtoURL(const URLComponentSource<CharacterType>& source, const URLSegments& parsed, URLBuffer<char>& output, URLSegments& outputParsed) +{ + // mailto: only uses {scheme, path, query} -- clear the rest. + outputParsed.username = URLComponent(); + outputParsed.password = URLComponent(); + outputParsed.host = URLComponent(); + outputParsed.port = URLComponent(); + outputParsed.fragment = URLComponent(); + + // Scheme (known, so we don't bother running it through the more + // complicated scheme canonicalizer). + outputParsed.scheme.setBegin(output.length()); + output.append("mailto:", 7); + outputParsed.scheme.setLength(6); + + bool success = true; + + // Path + if (parsed.path.isValid()) { + outputParsed.path.setBegin(output.length()); + + // Copy the path using path URL's more lax escaping rules. + // We convert to UTF-8 and escape non-ASCII, but leave all + // ASCII characters alone. + int end = parsed.path.end(); + for (int i = parsed.path.begin(); i < end; ++i) { + UCHAR uch = static_cast<UCHAR>(source.path[i]); + if (uch < 0x20 || uch >= 0x80) + success &= AppendUTF8EscapedChar(source.path, &i, end, output); + else + output.append(static_cast<char>(uch)); + } + + outputParsed.path.setLength(output.length() - outputParsed.path.begin()); + } else { + // No path at all + outputParsed.path.reset(); + } + + // Query -- always use the default utf8 charset converter. + CanonicalizeQuery(source.query, parsed.query, 0, output, &outputParsed.query); + + return success; +} + +} // namespace + +bool canonicalizeMailtoURL(const char* spec, const URLSegments& parsed, URLBuffer<char>& output, URLSegments& outputParsed) +{ + return doCanonicalizeMailtoURL<char, unsigned char>(URLComponentSource<char>(spec), parsed, output, outputParsed); +} + +bool canonicalizeMailtoURL(const UChar* spec, const URLSegments& parsed, URLBuffer<char>& output, URLSegments& outputParsed) +{ + return doCanonicalizeMailtoURL<UChar, UChar>(URLComponentSource<UChar>(spec), parsed, output, outputParsed); +} + +bool replaceMailtoURL(const char* base, const URLSegments& baseParsed, + const Replacements<char>& replacements, + URLBuffer<char>& output, URLSegments& outputParsed) +{ + URLComponentSource<char> source(base); + URLSegments parsed(baseParsed); + SetupOverrideComponents(base, replacements, &source, &parsed); + return doCanonicalizeMailtoURL<char, unsigned char>(source, parsed, output, outputParsed); +} + +bool replaceMailtoURL(const char* base, const URLSegments& baseParsed, + const Replacements<UChar>& replacements, + URLBuffer<char>& output, URLSegments& outputParsed) +{ + RawURLBuffer<char> utf8; + URLComponentSource<char> source(base); + URLSegments parsed(baseParsed); + SetupUTF16OverrideComponents(base, replacements, utf8, &source, &parsed); + return doCanonicalizeMailtoURL<char, unsigned char>(source, parsed, output, outputParsed); +} + +} // namespace URLCanonicalizer + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonPath.cpp b/Source/WTF/wtf/url/src/URLCanonPath.cpp new file mode 100644 index 000000000..9bc443fd7 --- /dev/null +++ b/Source/WTF/wtf/url/src/URLCanonPath.cpp @@ -0,0 +1,372 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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. + */ + +// Canonicalization functions for the paths of URLs. + +#include "config.h" +#include "URLCanon.h" + +#include "URLCanonInternal.h" +#include "URLParseInternal.h" + +#if USE(WTFURL) + +namespace WTF { + +namespace URLCanonicalizer { + +namespace { + +enum CharacterFlags { + // Pass through unchanged, whether escaped or unescaped. This doesn't + // actually set anything so you can't OR it to check, it's just to make the + // table below more clear when neither ESCAPE or UNESCAPE is set. + PASS = 0, + + // This character requires special handling in doPartialPath. Doing this test + // first allows us to filter out the common cases of regular characters that + // can be directly copied. + SPECIAL = 1, + + // This character must be escaped in the canonical output. Note that all + // escaped chars also have the "special" bit set so that the code that looks + // for this is triggered. Not valid with PASS or ESCAPE + ESCAPE_BIT = 2, + ESCAPE = ESCAPE_BIT | SPECIAL, + + // This character must be unescaped in canonical output. Not valid with + // ESCAPE or PASS. We DON'T set the SPECIAL flag since if we encounter these + // characters unescaped, they should just be copied. + UNESCAPE = 4, + + // This character is disallowed in URLs. Note that the "special" bit is also + // set to trigger handling. + INVALID_BIT = 8, + INVALID = INVALID_BIT | SPECIAL, +}; + +// This table contains one of the above flag values. Note some flags are more +// than one bits because they also turn on the "special" flag. Special is the +// only flag that may be combined with others. +// +// This table is designed to match exactly what IE does with the characters. +// +// Dot is even more special, and the escaped version is handled specially by +// isDot. Therefore, we don't need the "escape" flag, and even the "unescape" +// bit is never handled (we just need the "special") bit. +const unsigned char kPathCharLookup[0x100] = { +// null control chars... + INVALID, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, +// control chars... + ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, +// ' ' ! " # $ % & ' ( ) * + , - . / + ESCAPE, PASS, ESCAPE, ESCAPE, PASS, ESCAPE, PASS, PASS, PASS, PASS, PASS, PASS, PASS, UNESCAPE, SPECIAL, PASS, +// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? + UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, PASS, PASS, ESCAPE, PASS, ESCAPE, ESCAPE, +// @ A B C D E F G H I J K L M N O + PASS, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, +// P Q R S T U V W X Y Z [ \ ] ^ _ + UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, PASS, ESCAPE, PASS, ESCAPE, UNESCAPE, +// ` a b c d e f g h i j k l m n o + ESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, +// p q r s t u v w x y z { | } ~ <NBSP> + UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, UNESCAPE, ESCAPE, ESCAPE, ESCAPE, UNESCAPE, ESCAPE, +// ...all the high-bit characters are escaped + ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, + ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, + ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, + ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, + ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, + ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, + ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, + ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE, ESCAPE}; + +enum DotDisposition { + // The given dot is just part of a filename and is not special. + NOT_A_DIRECTORY, + + // The given dot is the current directory. + DIRECTORY_CUR, + + // The given dot is the first of a double dot that should take us up one. + DIRECTORY_UP +}; + +// When the path resolver finds a dot, this function is called with the +// character following that dot to see what it is. The return value +// indicates what type this dot is (see above). This code handles the case +// where the dot is at the end of the input. +// +// |*consumedLength| will contain the number of characters in the input that +// express what we found. +// +// If the input is "../foo", |afterDot| = 1, |end| = 6, and +// at the end, |*consumedLength| = 2 for the "./" this function consumed. The +// original dot length should be handled by the caller. +template<typename CHAR> +DotDisposition ClassifyAfterDot(const CHAR* spec, int afterDot, int end, int* consumedLength) +{ + if (afterDot == end) { + // Single dot at the end. + *consumedLength = 0; + return DIRECTORY_CUR; + } + if (URLParser::isURLSlash(spec[afterDot])) { + // Single dot followed by a slash. + *consumedLength = 1; // Consume the slash + return DIRECTORY_CUR; + } + + int secondDotLength = isDot(spec, afterDot, end); + if (secondDotLength) { + int afterSecondDot = afterDot + secondDotLength; + if (afterSecondDot == end) { + // Double dot at the end. + *consumedLength = secondDotLength; + return DIRECTORY_UP; + } + if (URLParser::isURLSlash(spec[afterSecondDot])) { + // Double dot followed by a slash. + *consumedLength = secondDotLength + 1; + return DIRECTORY_UP; + } + } + + // The dots are followed by something else, not a directory. + *consumedLength = 0; + return NOT_A_DIRECTORY; +} + +// Rewinds the output to the previous slash. It is assumed that the output +// ends with a slash and this doesn't count (we call this when we are +// appending directory paths, so the previous path component has and ending +// slash). +// +// This will stop at the first slash (assumed to be at position +// |pathBeginInOutput| and not go any higher than that. Some web pages +// do ".." too many times, so we need to handle that brokenness. +// +// It searches for a literal slash rather than including a backslash as well +// because it is run only on the canonical output. +// +// The output is guaranteed to end in a slash when this function completes. +void BackUpToPreviousSlash(int pathBeginInOutput, URLBuffer<char>& output) +{ + ASSERT(output.length() > 0); + + int i = output.length() - 1; + ASSERT(output.at(i) == '/'); + if (i == pathBeginInOutput) + return; // We're at the first slash, nothing to do. + + // Now back up (skipping the trailing slash) until we find another slash. + i--; + while (output.at(i) != '/' && i > pathBeginInOutput) + i--; + + // Now shrink the output to just include that last slash we found. + output.setLength(i + 1); +} + +// Appends the given path to the output. It assumes that if the input path +// starts with a slash, it should be copied to the output. If no path has +// already been appended to the output (the case when not resolving +// relative URLs), the path should begin with a slash. +// +// If there are already path components (this mode is used when appending +// relative paths for resolving), it assumes that the output already has +// a trailing slash and that if the input begins with a slash, it should be +// copied to the output. +// +// We do not collapse multiple slashes in a row to a single slash. It seems +// no web browsers do this, and we don't want incompababilities, even though +// it would be correct for most systems. +template<typename CharacterType, typename UCHAR> +bool doPartialPath(const CharacterType* spec, const URLComponent& path, int pathBeginInOutput, URLBuffer<char>& output) +{ + int end = path.end(); + + bool success = true; + for (int i = path.begin(); i < end; ++i) { + UCHAR uch = static_cast<UCHAR>(spec[i]); + if (sizeof(CharacterType) > sizeof(char) && uch >= 0x80) { + // We only need to test wide input for having non-ASCII characters. For + // narrow input, we'll always just use the lookup table. We don't try to + // do anything tricky with decoding/validating UTF-8. This function will + // read one or two UTF-16 characters and append the output as UTF-8. This + // call will be removed in 8-bit mode. + success &= AppendUTF8EscapedChar(spec, &i, end, output); + } else { + // Normal ASCII character or 8-bit input, use the lookup table. + unsigned char outCh = static_cast<unsigned char>(uch); + unsigned char flags = kPathCharLookup[outCh]; + if (flags & SPECIAL) { + // Needs special handling of some sort. + int dotlen; + if ((dotlen = isDot(spec, i, end)) > 0) { + // See if this dot was preceeded by a slash in the output. We + // assume that when canonicalizing paths, they will always + // start with a slash and not a dot, so we don't have to + // bounds check the output. + // + // Note that we check this in the case of dots so we don't have to + // special case slashes. Since slashes are much more common than + // dots, this actually increases performance measurably (though + // slightly). + ASSERT(output.length() > pathBeginInOutput); + if (output.length() > pathBeginInOutput && output.at(output.length() - 1) == '/') { + // Slash followed by a dot, check to see if this is means relative + int consumedLength; + switch (ClassifyAfterDot<CharacterType>(spec, i + dotlen, end, &consumedLength)) { + case NOT_A_DIRECTORY: + // Copy the dot to the output, it means nothing special. + output.append('.'); + i += dotlen - 1; + break; + case DIRECTORY_CUR: // Current directory, just skip the input. + i += dotlen + consumedLength - 1; + break; + case DIRECTORY_UP: + BackUpToPreviousSlash(pathBeginInOutput, output); + i += dotlen + consumedLength - 1; + break; + } + } else { + // This dot is not preceeded by a slash, it is just part of some + // file name. + output.append('.'); + i += dotlen - 1; + } + } else if (outCh == '\\') { + // Convert backslashes to forward slashes + output.append('/'); + } else if (outCh == '%') { + // Handle escape sequences. + unsigned char unescapedValue; + if (DecodeEscaped(spec, &i, end, &unescapedValue)) { + // Valid escape sequence, see if we keep, reject, or unescape it. + char unescapedFlags = kPathCharLookup[unescapedValue]; + + if (unescapedFlags & UNESCAPE) { + // This escaped value shouldn't be escaped, copy it. + output.append(unescapedValue); + } else if (unescapedFlags & INVALID_BIT) { + // Invalid escaped character, copy it and remember the error. + output.append('%'); + output.append(static_cast<char>(spec[i - 1])); + output.append(static_cast<char>(spec[i])); + success = false; + } else { + // Valid escaped character but we should keep it escaped. We + // don't want to change the case of any hex letters in case + // the server is sensitive to that, so we just copy the two + // characters without checking (DecodeEscape will have advanced + // to the last character of the pair). + output.append('%'); + output.append(static_cast<char>(spec[i - 1])); + output.append(static_cast<char>(spec[i])); + } + } else { + // Invalid escape sequence. IE7 rejects any URLs with such + // sequences, while Firefox, IE6, and Safari all pass it through + // unchanged. We are more permissive unlike IE7. I don't think this + // can cause significant problems, if it does, we should change + // to be more like IE7. + output.append('%'); + } + + } else if (flags & INVALID_BIT) { + // For NULLs, etc. fail. + appendURLEscapedCharacter(outCh, output); + success = false; + + } else if (flags & ESCAPE_BIT) { + // This character should be escaped. + appendURLEscapedCharacter(outCh, output); + } + } else { + // Nothing special about this character, just append it. + output.append(outCh); + } + } + } + return success; +} + +template<typename CharacterType, typename UCHAR> +bool doPath(const CharacterType* spec, const URLComponent& path, URLBuffer<char>& output, URLComponent& outputPath) +{ + bool success = true; + outputPath.setBegin(output.length()); + if (path.length() > 0) { + // Write out an initial slash if the input has none. If we just parse a URL + // and then canonicalize it, it will of course have a slash already. This + // check is for the replacement and relative URL resolving cases of file + // URLs. + if (!URLParser::isURLSlash(spec[path.begin()])) + output.append('/'); + + success = doPartialPath<CharacterType, UCHAR>(spec, path, outputPath.begin(), output); + } else { + // No input, canonical path is a slash. + output.append('/'); + } + outputPath.setLength(output.length() - outputPath.begin()); + return success; +} + +} // namespace + +bool CanonicalizePath(const char* spec, const URLComponent& path, URLBuffer<char>& output, URLComponent* outputPath) +{ + return doPath<char, unsigned char>(spec, path, output, *outputPath); +} + +bool CanonicalizePath(const UChar* spec, const URLComponent& path, URLBuffer<char>& output, URLComponent* outputPath) +{ + return doPath<UChar, UChar>(spec, path, output, *outputPath); +} + +bool CanonicalizePartialPath(const char* spec, const URLComponent& path, int pathBeginInOutput, URLBuffer<char>& output) +{ + return doPartialPath<char, unsigned char>(spec, path, pathBeginInOutput, output); +} + +bool CanonicalizePartialPath(const UChar* spec, const URLComponent& path, int pathBeginInOutput, URLBuffer<char>& output) +{ + return doPartialPath<UChar, UChar>(spec, path, pathBeginInOutput, output); +} + +} // namespace URLCanonicalizer + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonPathurl.cpp b/Source/WTF/wtf/url/src/URLCanonPathurl.cpp new file mode 100644 index 000000000..cea037c21 --- /dev/null +++ b/Source/WTF/wtf/url/src/URLCanonPathurl.cpp @@ -0,0 +1,122 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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. + */ + +// Functions for canonicalizing "path" URLs. Not to be confused with the path +// of a URL, these are URLs that have no authority section, only a path. For +// example, "javascript:" and "data:". + +#include "config.h" +#include "URLCanon.h" + +#include "RawURLBuffer.h" +#include "URLCanonInternal.h" + +#if USE(WTFURL) + +namespace WTF { + +namespace URLCanonicalizer { + +namespace { + +template<typename CharacterType, typename UCHAR> +bool doCanonicalizePathURL(const URLComponentSource<CharacterType>& source, const URLSegments& parsed, URLBuffer<char>& output, URLSegments& ouputParsed) +{ + // Scheme: this will append the colon. + bool success = canonicalizeScheme(source.scheme, parsed.scheme, output, ouputParsed.scheme); + + // We assume there's no authority for path URLs. Note that hosts should never + // have -1 length. + ouputParsed.username.reset(); + ouputParsed.password.reset(); + ouputParsed.host.reset(); + ouputParsed.port.reset(); + + if (parsed.path.isValid()) { + // Copy the path using path URL's more lax escaping rules (think for + // javascript:). We convert to UTF-8 and escape non-ASCII, but leave all + // ASCII characters alone. This helps readability of JavaStript. + ouputParsed.path.setBegin(output.length()); + int end = parsed.path.end(); + for (int i = parsed.path.begin(); i < end; ++i) { + UCHAR uch = static_cast<UCHAR>(source.path[i]); + if (uch < 0x20 || uch >= 0x80) + success &= AppendUTF8EscapedChar(source.path, &i, end, output); + else + output.append(static_cast<char>(uch)); + } + ouputParsed.path.setLength(output.length() - ouputParsed.path.begin()); + } else { + // Empty path. + ouputParsed.path.reset(); + } + + // Assume there's no query or ref. + ouputParsed.query.reset(); + ouputParsed.fragment.reset(); + + return success; +} + +} // namespace + +bool canonicalizePathURL(const char* spec, const URLSegments& parsed, URLBuffer<char>& output, URLSegments& ouputParsed) +{ + return doCanonicalizePathURL<char, unsigned char>(URLComponentSource<char>(spec), parsed, output, ouputParsed); +} + +bool canonicalizePathURL(const UChar* spec, const URLSegments& parsed, URLBuffer<char>& output, URLSegments& ouputParsed) +{ + return doCanonicalizePathURL<UChar, UChar>(URLComponentSource<UChar>(spec), parsed, output, ouputParsed); +} + +bool ReplacePathURL(const char* base, const URLSegments& baseParsed, const Replacements<char>& replacements, URLBuffer<char>& output, URLSegments* ouputParsed) +{ + URLComponentSource<char> source(base); + URLSegments parsed(baseParsed); + SetupOverrideComponents(base, replacements, &source, &parsed); + return doCanonicalizePathURL<char, unsigned char>(source, parsed, output, *ouputParsed); +} + +bool ReplacePathURL(const char* base, const URLSegments& baseParsed, const Replacements<UChar>& replacements, URLBuffer<char>& output, URLSegments* ouputParsed) +{ + RawURLBuffer<char> utf8; + URLComponentSource<char> source(base); + URLSegments parsed(baseParsed); + SetupUTF16OverrideComponents(base, replacements, utf8, &source, &parsed); + return doCanonicalizePathURL<char, unsigned char>(source, parsed, output, *ouputParsed); +} + +} // namespace URLCanonicalizer + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonQuery.cpp b/Source/WTF/wtf/url/src/URLCanonQuery.cpp new file mode 100644 index 000000000..0b829ba5b --- /dev/null +++ b/Source/WTF/wtf/url/src/URLCanonQuery.cpp @@ -0,0 +1,189 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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" +#include "URLCanon.h" + +#include "RawURLBuffer.h" +#include "URLCanonInternal.h" +#include "URLCharacterTypes.h" +#include "URLQueryCharsetConverter.h" +#include <wtf/text/ASCIIFastPath.h> + +// Query canonicalization in IE +// ---------------------------- +// IE is very permissive for query parameters specified in links on the page +// (in contrast to links that it constructs itself based on form data). It does +// not unescape any character. It does not reject any escape sequence (be they +// invalid like "%2y" or freaky like %00). +// +// IE only escapes spaces and nothing else. Embedded NULLs, tabs (0x09), +// LF (0x0a), and CR (0x0d) are removed (this probably happens at an earlier +// layer since they are removed from all portions of the URL). All other +// characters are passed unmodified. Invalid UTF-16 sequences are preserved as +// well, with each character in the input being converted to UTF-8. It is the +// server's job to make sense of this invalid query. +// +// Invalid multibyte sequences (for example, invalid UTF-8 on a UTF-8 page) +// are converted to the invalid character and sent as unescaped UTF-8 (0xef, +// 0xbf, 0xbd). This may not be canonicalization, the parser may generate these +// strings before the URL handler ever sees them. +// +// Our query canonicalization +// -------------------------- +// We escape all non-ASCII characters and control characters, like Firefox. +// This is more conformant to the URL spec, and there do not seem to be many +// problems relating to Firefox's behavior. +// +// Like IE, we will never unescape (although the application may want to try +// unescaping to present the user with a more understandable URL). We will +// replace all invalid sequences (including invalid UTF-16 sequences, which IE +// doesn't) with the "invalid character," and we will escape it. + +#if USE(WTFURL) + +namespace WTF { + +namespace URLCanonicalizer { + +namespace { + +// Returns true if the characters starting at |begin| and going until |end| +// (non-inclusive) are all representable in 7-bits. +template<typename CharacterType> +bool isAllASCII(const CharacterType* spec, const URLComponent& query) +{ + return charactersAreAllASCII(spec + query.begin(), query.length()); +} + +// FIXME: Benjamin: get rid of this when everything is based on LChar. +template<> +bool isAllASCII<char>(const char* spec, const URLComponent& query) +{ + return charactersAreAllASCII(reinterpret_cast<const LChar*>(spec + query.begin()), query.length()); +} + +// Appends the given string to the output, escaping characters that do not +// match the given |type| in SharedCharTypes. This version will accept 8 or 16 +// bit characters, but assumes that they have only 7-bit values. It also assumes +// that all UTF-8 values are correct, so doesn't bother checking +template<typename CharacterType> +void appendRaw8BitQueryString(const CharacterType* source, int length, URLBuffer<char>& output) +{ + for (int i = 0; i < length; ++i) { + if (!URLCharacterTypes::isQueryChar(static_cast<unsigned char>(source[i]))) + appendURLEscapedCharacter(static_cast<unsigned char>(source[i]), output); + else // Doesn't need escaping. + output.append(static_cast<char>(source[i])); + } +} + +// Runs the converter on the given UTF-8 input. Since the converter expects +// UTF-16, we have to convert first. The converter must be non-null. +void runConverter(const char* spec, const URLComponent& query, URLQueryCharsetConverter* converter, URLBuffer<char>& output) +{ + // This function will replace any misencoded values with the invalid + // character. This is what we want so we don't have to check for error. + RawURLBuffer<UChar> utf16; + ConvertUTF8ToUTF16(&spec[query.begin()], query.length(), utf16); + converter->convertFromUTF16(utf16.data(), utf16.length(), output); +} + +// Runs the converter with the given UTF-16 input. We don't have to do +// anything, but this overriddden function allows us to use the same code +// for both UTF-8 and UTF-16 input. +void runConverter(const UChar* spec, const URLComponent& query, URLQueryCharsetConverter* converter, URLBuffer<char>& output) +{ + converter->convertFromUTF16(&spec[query.begin()], query.length(), output); +} + +template<typename CharacterType> +void doConvertToQueryEncoding(const CharacterType* spec, const URLComponent& query, URLQueryCharsetConverter* converter, URLBuffer<char>& output) +{ + if (isAllASCII(spec, query)) { + // Easy: the input can just appended with no character set conversions. + appendRaw8BitQueryString(&spec[query.begin()], query.length(), output); + } else { + // Harder: convert to the proper encoding first. + if (converter) { + // Run the converter to get an 8-bit string, then append it, escaping + // necessary values. + RawURLBuffer<char> eightBitQueryString; + runConverter(spec, query, converter, eightBitQueryString); + appendRaw8BitQueryString(eightBitQueryString.data(), eightBitQueryString.length(), output); + } else { + // No converter, do our own UTF-8 conversion. + appendStringOfType(&spec[query.begin()], query.length(), URLCharacterTypes::QueryCharacter, output); + } + } +} + +template<typename CharacterType> +void doCanonicalizeQuery(const CharacterType* spec, const URLComponent& query, URLQueryCharsetConverter* converter, + URLBuffer<char>& output, URLComponent& outputQueryComponent) +{ + if (query.length() < 0) { + outputQueryComponent = URLComponent(); + return; + } + + output.append('?'); + outputQueryComponent.setBegin(output.length()); + + doConvertToQueryEncoding<CharacterType>(spec, query, converter, output); + + outputQueryComponent.setLength(output.length() - outputQueryComponent.begin()); +} + +} // namespace + +void CanonicalizeQuery(const char* spec, const URLComponent& query, URLQueryCharsetConverter* converter, + URLBuffer<char>& output, URLComponent* outputQueryComponent) +{ + doCanonicalizeQuery(spec, query, converter, output, *outputQueryComponent); +} + +void CanonicalizeQuery(const UChar* spec, const URLComponent& query, URLQueryCharsetConverter* converter, + URLBuffer<char>& output, URLComponent* outputQueryComponent) +{ + doCanonicalizeQuery(spec, query, converter, output, *outputQueryComponent); +} + +void ConvertUTF16ToQueryEncoding(const UChar* input, const URLComponent& query, URLQueryCharsetConverter* converter, URLBuffer<char>& output) +{ + doConvertToQueryEncoding<UChar>(input, query, converter, output); +} + +} // namespace URLCanonicalizer + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonRelative.cpp b/Source/WTF/wtf/url/src/URLCanonRelative.cpp new file mode 100644 index 000000000..7ef050064 --- /dev/null +++ b/Source/WTF/wtf/url/src/URLCanonRelative.cpp @@ -0,0 +1,572 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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. + */ + +// Canonicalizer functions for working with and resolving relative URLs. + +#include "config.h" +#include "URLCanon.h" + +#include "URLCanonInternal.h" +#include "URLFile.h" +#include "URLParseInternal.h" +#include "URLUtilInternal.h" + +#if USE(WTFURL) + +namespace WTF { + +namespace URLCanonicalizer { + +namespace { + +// Firefox does a case-sensitive compare (which is probably wrong--Mozilla bug +// 379034), whereas IE is case-insensetive. +// +// We choose to be more permissive like IE. We don't need to worry about +// unescaping or anything here: neither IE or Firefox allow this. We also +// don't have to worry about invalid scheme characters since we are comparing +// against the canonical scheme of the base. +// +// The base URL should always be canonical, therefore is ASCII. +template<typename CHAR> +bool AreSchemesEqual(const char* base, + const URLComponent& baseScheme, + const CHAR* cmp, + const URLComponent& cmpScheme) +{ + if (baseScheme.length() != cmpScheme.length()) + return false; + for (int i = 0; i < baseScheme.length(); i++) { + // We assume the base is already canonical, so we don't have to + // canonicalize it. + if (canonicalSchemeChar(cmp[cmpScheme.begin() + i]) != + base[baseScheme.begin() + i]) + return false; + } + return true; +} + +#if OS(WINDOWS) +// Here, we also allow Windows paths to be represented as "/C:/" so we can be +// consistent about URL paths beginning with slashes. This function is like +// DoesBeginWindowsDrivePath except that it also requires a slash at the +// beginning. +template<typename CHAR> +bool doesBeginSlashWindowsDriveSpec(const CHAR* spec, int startOffset, int specLength) +{ + if (startOffset >= specLength) + return false; + return URLParser::isURLSlash(spec[startOffset]) && URLParser::doesBeginWindowsDriveSpec(spec, startOffset + 1, specLength); +} + +#endif // OS(WINDOWS) + +// See isRelativeURL in the header file for usage. +template<typename CharacterType> +bool doIsRelativeURL(const char* base, const URLSegments& baseParsed, + const CharacterType* url, int urlLength, + bool isBaseHierarchical, + bool& isRelative, URLComponent& relativeComponent) +{ + isRelative = false; // So we can default later to not relative. + + // Trim whitespace and construct a new range for the substring. + int begin = 0; + URLParser::trimURL(url, begin, urlLength); + if (begin >= urlLength) { + // Empty URLs are relative, but do nothing. + relativeComponent = URLComponent(begin, 0); + isRelative = true; + return true; + } + +#if OS(WINDOWS) + // We special case paths like "C:\foo" so they can link directly to the + // file on Windows (IE compatability). The security domain stuff should + // prevent a link like this from actually being followed if its on a + // web page. + // + // We treat "C:/foo" as an absolute URL. We can go ahead and treat "/c:/" + // as relative, as this will just replace the path when the base scheme + // is a file and the answer will still be correct. + // + // We require strict backslashes when detecting UNC since two forward + // shashes should be treated a a relative URL with a hostname. + if (URLParser::doesBeginWindowsDriveSpec(url, begin, urlLength) || URLParser::doesBeginUNCPath(url, begin, urlLength, true)) + return true; +#endif // OS(WINDOWS) + + // See if we've got a scheme, if not, we know this is a relative URL. + // BUT: Just because we have a scheme, doesn't make it absolute. + // "http:foo.html" is a relative URL with path "foo.html". If the scheme is + // empty, we treat it as relative (":foo") like IE does. + URLComponent scheme; + if (!URLParser::ExtractScheme(url, urlLength, &scheme) || !scheme.length()) { + // Don't allow relative URLs if the base scheme doesn't support it. + if (!isBaseHierarchical) + return false; + + relativeComponent = URLComponent::fromRange(begin, urlLength); + isRelative = true; + return true; + } + + // If the scheme isn't valid, then it's relative. + int schemeEnd = scheme.end(); + for (int i = scheme.begin(); i < schemeEnd; i++) { + if (!canonicalSchemeChar(url[i])) { + relativeComponent = URLComponent::fromRange(begin, urlLength); + isRelative = true; + return true; + } + } + + // If the scheme is not the same, then we can't count it as relative. + if (!AreSchemesEqual(base, baseParsed.scheme, url, scheme)) + return true; + + // When the scheme that they both share is not hierarchical, treat the + // incoming scheme as absolute (this way with the base of "data:foo", + // "data:bar" will be reported as absolute. + if (!isBaseHierarchical) + return true; + + int colonOffset = scheme.end(); + + // If it's a filesystem URL, the only valid way to make it relative is not to + // supply a scheme. There's no equivalent to e.g. http:index.html. + if (URLUtilities::CompareSchemeComponent(url, scheme, "filesystem")) + return true; + + // ExtractScheme guarantees that the colon immediately follows what it + // considers to be the scheme. countConsecutiveSlashes will handle the + // case where the begin offset is the end of the input. + int numSlashes = URLParser::countConsecutiveSlashes(url, colonOffset + 1, urlLength); + + if (!numSlashes || numSlashes == 1) { + // No slashes means it's a relative path like "http:foo.html". One slash + // is an absolute path. "http:/home/foo.html" + isRelative = true; + relativeComponent = URLComponent::fromRange(colonOffset + 1, urlLength); + return true; + } + + // Two or more slashes after the scheme we treat as absolute. + return true; +} + +// Copies all characters in the range [begin, end) of |spec| to the output, +// up until and including the last slash. There should be a slash in the +// range, if not, nothing will be copied. +// +// The input is assumed to be canonical, so we search only for exact slashes +// and not backslashes as well. We also know that it's ASCII. +void CopyToLastSlash(const char* spec, int begin, int end, URLBuffer<char>& output) +{ + // Find the last slash. + int lastSlash = -1; + for (int i = end - 1; i >= begin; --i) { + if (spec[i] == '/') { + lastSlash = i; + break; + } + } + if (lastSlash < 0) + return; // No slash. + + // Copy. + for (int i = begin; i <= lastSlash; ++i) + output.append(spec[i]); +} + +// Copies a single component from the source to the output. This is used +// when resolving relative URLs and a given component is unchanged. Since the +// source should already be canonical, we don't have to do anything special, +// and the input is ASCII. +void CopyOneComponent(const char* source, + const URLComponent& sourceComponent, + URLBuffer<char>& output, + URLComponent* outputComponent) +{ + if (sourceComponent.length() < 0) { + // This component is not present. + *outputComponent = URLComponent(); + return; + } + + outputComponent->setBegin(output.length()); + int sourceEnd = sourceComponent.end(); + for (int i = sourceComponent.begin(); i < sourceEnd; i++) + output.append(source[i]); + outputComponent->setLength(output.length() - outputComponent->begin()); +} + +#if OS(WINDOWS) + +// Called on Windows when the base URL is a file URL, this will copy the "C:" +// to the output, if there is a drive letter and if that drive letter is not +// being overridden by the relative URL. Otherwise, do nothing. +// +// It will return the index of the beginning of the next character in the +// base to be processed: if there is a "C:", the slash after it, or if +// there is no drive letter, the slash at the beginning of the path, or +// the end of the base. This can be used as the starting offset for further +// path processing. +template<typename CHAR> +int CopyBaseDriveSpecIfNecessary(const char* baseURL, + int basePathBegin, + int basePathEnd, + const CHAR* relativeURL, + int pathStart, + int relativeUrlLength, + URLBuffer<char>& output) +{ + if (basePathBegin >= basePathEnd) + return basePathBegin; // No path. + + // If the relative begins with a drive spec, don't do anything. The existing + // drive spec in the base will be replaced. + if (URLParser::doesBeginWindowsDriveSpec(relativeURL, + pathStart, relativeUrlLength)) { + return basePathBegin; // Relative URL path is "C:/foo" + } + + // The path should begin with a slash (as all canonical paths do). We check + // if it is followed by a drive letter and copy it. + if (doesBeginSlashWindowsDriveSpec(baseURL, basePathBegin, basePathEnd)) { + // Copy the two-character drive spec to the output. It will now look like + // "file:///C:" so the rest of it can be treated like a standard path. + output.append('/'); + output.append(baseURL[basePathBegin + 1]); + output.append(baseURL[basePathBegin + 2]); + return basePathBegin + 3; + } + + return basePathBegin; +} + +#endif // OS(WINDOWS) + +// A subroutine of doResolveRelativeURL, this resolves the URL knowning that +// the input is a relative path or less (qyuery or ref). +template<typename CHAR> +bool doResolveRelativePath(const char* baseURL, + const URLSegments& baseParsed, + bool /* baseIsFile */, + const CHAR* relativeURL, + const URLComponent& relativeComponent, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + bool success = true; + + // We know the authority section didn't change, copy it to the output. We + // also know we have a path so can copy up to there. + URLComponent path, query, ref; + URLParser::parsePathInternal(relativeURL, + relativeComponent, + &path, + &query, + &ref); + // Canonical URLs always have a path, so we can use that offset. + output.append(baseURL, baseParsed.path.begin()); + + if (path.length() > 0) { + // The path is replaced or modified. + int truePathBegin = output.length(); + + // For file: URLs on Windows, we don't want to treat the drive letter and + // colon as part of the path for relative file resolution when the + // incoming URL does not provide a drive spec. We save the true path + // beginning so we can fix it up after we are done. + int basePathBegin = baseParsed.path.begin(); +#if OS(WINDOWS) + if (baseIsFile) { + basePathBegin = CopyBaseDriveSpecIfNecessary(baseURL, baseParsed.path.begin(), baseParsed.path.end(), + relativeURL, relativeComponent.begin(), relativeComponent.end(), + output); + // Now the output looks like either "file://" or "file:///C:" + // and we can start appending the rest of the path. |basePathBegin| + // points to the character in the base that comes next. + } +#endif // OS(WINDOWS) + + if (URLParser::isURLSlash(relativeURL[path.begin()])) { + // Easy case: the path is an absolute path on the server, so we can + // just replace everything from the path on with the new versions. + // Since the input should be canonical hierarchical URL, we should + // always have a path. + success &= CanonicalizePath(relativeURL, path, + output, &outputParsed->path); + } else { + // Relative path, replace the query, and reference. We take the + // original path with the file part stripped, and append the new path. + // The canonicalizer will take care of resolving ".." and "." + int pathBegin = output.length(); + CopyToLastSlash(baseURL, basePathBegin, baseParsed.path.end(), + output); + success &= CanonicalizePartialPath(relativeURL, path, pathBegin, + output); + outputParsed->path = URLComponent::fromRange(pathBegin, output.length()); + + // Copy the rest of the stuff after the path from the relative path. + } + + // Finish with the query and reference part (these can't fail). + CanonicalizeQuery(relativeURL, query, queryConverter, output, &outputParsed->query); + canonicalizeFragment(relativeURL, ref, output, outputParsed->fragment); + + // Fix the path beginning to add back the "C:" we may have written above. + outputParsed->path = URLComponent::fromRange(truePathBegin, + outputParsed->path.end()); + return success; + } + + // If we get here, the path is unchanged: copy to output. + CopyOneComponent(baseURL, baseParsed.path, output, &outputParsed->path); + + if (query.isValid()) { + // Just the query specified, replace the query and reference (ignore + // failures for refs) + CanonicalizeQuery(relativeURL, query, queryConverter, + output, &outputParsed->query); + canonicalizeFragment(relativeURL, ref, output, outputParsed->fragment); + return success; + } + + // If we get here, the query is unchanged: copy to output. Note that the + // range of the query parameter doesn't include the question mark, so we + // have to add it manually if there is a component. + if (baseParsed.query.isValid()) + output.append('?'); + CopyOneComponent(baseURL, baseParsed.query, output, &outputParsed->query); + + if (ref.isValid()) { + // Just the reference specified: replace it (ignoring failures). + canonicalizeFragment(relativeURL, ref, output, outputParsed->fragment); + return success; + } + + // We should always have something to do in this function, the caller checks + // that some component is being replaced. + ASSERT_NOT_REACHED(); + return success; +} + +// Resolves a relative URL that contains a host. Typically, these will +// be of the form "//www.apple.com/foo/bar?baz#fragment" and the only thing which +// should be kept from the original URL is the scheme. +template<typename CHAR> +bool doResolveRelativeHost(const char* baseURL, + const URLSegments& baseParsed, + const CHAR* relativeURL, + const URLComponent& relativeComponent, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + // Parse the relative URL, just like we would for anything following a + // scheme. + URLSegments relativeParsed; // Everything but the scheme is valid. + URLParser::parseAfterScheme(&relativeURL[relativeComponent.begin()], + relativeComponent.length(), relativeComponent.begin(), + relativeParsed); + + // Now we can just use the replacement function to replace all the necessary + // parts of the old URL with the new one. + Replacements<CHAR> replacements; + replacements.SetUsername(relativeURL, relativeParsed.username); + replacements.SetPassword(relativeURL, relativeParsed.password); + replacements.SetHost(relativeURL, relativeParsed.host); + replacements.SetPort(relativeURL, relativeParsed.port); + replacements.SetPath(relativeURL, relativeParsed.path); + replacements.SetQuery(relativeURL, relativeParsed.query); + replacements.SetRef(relativeURL, relativeParsed.fragment); + + return ReplaceStandardURL(baseURL, baseParsed, replacements, + queryConverter, output, outputParsed); +} + +// Resolves a relative URL that happens to be an absolute file path. Examples +// include: "//hostname/path", "/c:/foo", and "//hostname/c:/foo". +template<typename CharacterType> +bool doResolveAbsoluteFile(const CharacterType* relativeURL, + const URLComponent& relativeComponent, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>& output, + URLSegments& outputParsed) +{ + // Parse the file URL. The file URl parsing function uses the same logic + // as we do for determining if the file is absolute, in which case it will + // not bother to look for a scheme. + URLSegments relativeParsed; + URLParser::ParseFileURL(&relativeURL[relativeComponent.begin()], + relativeComponent.length(), &relativeParsed); + + return CanonicalizeFileURL(&relativeURL[relativeComponent.begin()], + relativeComponent.length(), relativeParsed, + queryConverter, output, &outputParsed); +} + +// TODO(brettw) treat two slashes as root like Mozilla for FTP? +template<typename CHAR> +bool doResolveRelativeURL(const char* baseURL, + const URLSegments& baseParsed, + bool baseIsFile, + const CHAR* relativeURL, + const URLComponent& relativeComponent, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + // Starting point for our output parsed. We'll fix what we change. + *outputParsed = baseParsed; + + // Sanity check: the input should have a host or we'll break badly below. + // We can only resolve relative URLs with base URLs that have hosts and + // paths (even the default path of "/" is OK). + // + // We allow hosts with no length so we can handle file URLs, for example. + if (baseParsed.path.length() <= 0) { + // On error, return the input (resolving a relative URL on a non-relative + // base = the base). + int baseLength = baseParsed.length(); + for (int i = 0; i < baseLength; i++) + output.append(baseURL[i]); + return false; + } + + if (relativeComponent.length() <= 0) { + // Empty relative URL, leave unchanged, only removing the ref component. + int baseLength = baseParsed.length(); + baseLength -= baseParsed.fragment.length() + 1; + outputParsed->fragment.reset(); + output.append(baseURL, baseLength); + return true; + } + + int numSlashes = URLParser::countConsecutiveSlashes(relativeURL, relativeComponent.begin(), relativeComponent.end()); + +#if OS(WINDOWS) + // On Windows, two slashes for a file path (regardless of which direction + // they are) means that it's UNC. Two backslashes on any base scheme mean + // that it's an absolute UNC path (we use the baseIsFile flag to control + // how strict the UNC finder is). + // + // We also allow Windows absolute drive specs on any scheme (for example + // "c:\foo") like IE does. There must be no preceeding slashes in this + // case (we reject anything like "/c:/foo") because that should be treated + // as a path. For file URLs, we allow any number of slashes since that would + // be setting the path. + // + // This assumes the absolute path resolver handles absolute URLs like this + // properly. URLUtilities::DoCanonicalize does this. + int afterSlashes = relativeComponent.begin + numSlashes; + if (URLParser::doesBeginUNCPath(relativeURL, relativeComponent.begin(), relativeComponent.end(), !baseIsFile) + || ((!numSlashes || baseIsFile) && URLParser::doesBeginWindowsDriveSpec(relativeURL, afterSlashes, relativeComponent.end()))) { + return doResolveAbsoluteFile(relativeURL, relativeComponent, + queryConverter, output, *outputParsed); + } +#else + // Other platforms need explicit handling for file: URLs with multiple + // slashes because the generic scheme parsing always extracts a host, but a + // file: URL only has a host if it has exactly 2 slashes. This also + // handles the special case where the URL is only slashes, since that + // doesn't have a host part either. + if (baseIsFile && (numSlashes > 2 || numSlashes == relativeComponent.length())) { + return doResolveAbsoluteFile(relativeURL, relativeComponent, + queryConverter, output, *outputParsed); + } +#endif + + // Any other double-slashes mean that this is relative to the scheme. + if (numSlashes >= 2) { + return doResolveRelativeHost(baseURL, baseParsed, + relativeURL, relativeComponent, + queryConverter, output, outputParsed); + } + + // When we get here, we know that the relative URL is on the same host. + return doResolveRelativePath(baseURL, baseParsed, baseIsFile, + relativeURL, relativeComponent, + queryConverter, output, outputParsed); +} + +} // namespace + +bool isRelativeURL(const char* base, const URLSegments& baseParsed, + const char* fragment, int fragmentLength, + bool isBaseHierarchical, + bool& isRelative, URLComponent& relativeComponent) +{ + return doIsRelativeURL<char>(base, baseParsed, fragment, fragmentLength, isBaseHierarchical, isRelative, relativeComponent); +} + +bool isRelativeURL(const char* base, const URLSegments& baseParsed, + const UChar* fragment, int fragmentLength, + bool isBaseHierarchical, + bool& isRelative, URLComponent& relativeComponent) +{ + return doIsRelativeURL<UChar>(base, baseParsed, fragment, fragmentLength, isBaseHierarchical, isRelative, relativeComponent); +} + +bool resolveRelativeURL(const char* baseURL, + const URLSegments& baseParsed, + bool baseIsFile, + const char* relativeURL, + const URLComponent& relativeComponent, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + return doResolveRelativeURL<char>(baseURL, baseParsed, baseIsFile, relativeURL, + relativeComponent, queryConverter, output, outputParsed); +} + +bool resolveRelativeURL(const char* baseURL, + const URLSegments& baseParsed, + bool baseIsFile, + const UChar* relativeURL, + const URLComponent& relativeComponent, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + return doResolveRelativeURL<UChar>(baseURL, baseParsed, baseIsFile, relativeURL, + relativeComponent, queryConverter, output, outputParsed); +} + +} // namespace URLCanonicalizer + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCanonStdURL.cpp b/Source/WTF/wtf/url/src/URLCanonStdURL.cpp new file mode 100644 index 000000000..5e2dd1cea --- /dev/null +++ b/Source/WTF/wtf/url/src/URLCanonStdURL.cpp @@ -0,0 +1,210 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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. + */ + +// Functions to canonicalize "standard" URLs, which are ones that have an +// authority section including a host name. + +#include "config.h" +#include "URLCanon.h" + +#include "RawURLBuffer.h" +#include "URLCanonInternal.h" + +#if USE(WTFURL) + +namespace WTF { + +namespace URLCanonicalizer { + +namespace { + +template<typename CHAR, typename UCHAR> +bool doCanonicalizeStandardURL(const URLComponentSource<CHAR>& source, + const URLSegments& parsed, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>& output, + URLSegments& outputParsed) +{ + // Scheme: this will append the colon. + bool success = canonicalizeScheme(source.scheme, parsed.scheme, output, outputParsed.scheme); + + // Authority (username, password, host, port) + bool haveAuthority; + if (parsed.username.isNonEmpty() || parsed.password.isValid() || parsed.host.isNonEmpty() || parsed.port.isValid()) { + haveAuthority = true; + + // Only write the authority separators when we have a scheme. + if (parsed.scheme.isValid()) + output.append("//", 2); + + // User info: the canonicalizer will handle the : and @. + success &= canonicalizeUserInfo(source.username, parsed.username, source.password, parsed.password, + output, outputParsed.username, outputParsed.password); + success &= canonicalizeHost(source.host, parsed.host, output, outputParsed.host); + + // Host must not be empty for standard URLs. + if (!parsed.host.isNonEmpty()) + success = false; + + // Port: the port canonicalizer will handle the colon. + int defaultPort = defaultPortForScheme(&output.data()[outputParsed.scheme.begin()], outputParsed.scheme.length()); + success &= canonicalizePort(source.port, parsed.port, defaultPort, output, outputParsed.port); + } else { + // No authority, clear the components. + haveAuthority = false; + outputParsed.host.reset(); + outputParsed.username.reset(); + outputParsed.password.reset(); + outputParsed.port.reset(); + success = false; // Standard URLs must have an authority. + } + + // Path + if (parsed.path.isNonEmpty()) + success &= CanonicalizePath(source.path, parsed.path, output, &outputParsed.path); + else if (haveAuthority || parsed.query.isNonEmpty() || parsed.fragment.isNonEmpty()) { + // When we have an empty path, make up a path when we have an authority + // or something following the path. The only time we allow an empty + // output path is when there is nothing else. + outputParsed.path = URLComponent(output.length(), 1); + output.append('/'); + } else + outputParsed.path.reset(); // No path at all + + // Query + CanonicalizeQuery(source.query, parsed.query, queryConverter, output, &outputParsed.query); + + // Ref: ignore failure for this, since the page can probably still be loaded. + canonicalizeFragment(source.ref, parsed.fragment, output, outputParsed.fragment); + + return success; +} + +} // namespace + + +// Returns the default port for the given canonical scheme, or PORT_UNSPECIFIED +// if the scheme is unknown. +int defaultPortForScheme(const char* scheme, int schemeLength) +{ + int defaultPort = URLParser::PORT_UNSPECIFIED; + switch (schemeLength) { + case 4: + if (!strncmp(scheme, "http", schemeLength)) + defaultPort = 80; + break; + case 5: + if (!strncmp(scheme, "https", schemeLength)) + defaultPort = 443; + break; + case 3: + if (!strncmp(scheme, "ftp", schemeLength)) + defaultPort = 21; + else if (!strncmp(scheme, "wss", schemeLength)) + defaultPort = 443; + break; + case 6: + if (!strncmp(scheme, "gopher", schemeLength)) + defaultPort = 70; + break; + case 2: + if (!strncmp(scheme, "ws", schemeLength)) + defaultPort = 80; + break; + } + return defaultPort; +} + +bool CanonicalizeStandardURL(const char* spec, + int /* specLength */, + const URLSegments& parsed, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + return doCanonicalizeStandardURL<char, unsigned char>(URLComponentSource<char>(spec), parsed, queryConverter, + output, *outputParsed); +} + +bool CanonicalizeStandardURL(const UChar* spec, + int /* specLength */, + const URLSegments& parsed, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + return doCanonicalizeStandardURL<UChar, UChar>(URLComponentSource<UChar>(spec), parsed, queryConverter, + output, *outputParsed); +} + +// It might be nice in the future to optimize this so unchanged components don't +// need to be recanonicalized. This is especially true since the common case for +// ReplaceComponents is removing things we don't want, like reference fragments +// and usernames. These cases can become more efficient if we can assume the +// rest of the URL is OK with these removed (or only the modified parts +// recanonicalized). This would be much more complex to implement, however. +// +// You would also need to update DoReplaceComponents in URLUtilities.cc which +// relies on this re-checking everything (see the comment there for why). +bool ReplaceStandardURL(const char* base, + const URLSegments& baseParsed, + const Replacements<char>& replacements, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + URLComponentSource<char> source(base); + URLSegments parsed(baseParsed); + SetupOverrideComponents(base, replacements, &source, &parsed); + return doCanonicalizeStandardURL<char, unsigned char>(source, parsed, queryConverter, output, *outputParsed); +} + +// For 16-bit replacements, we turn all the replacements into UTF-8 so the +// regular codepath can be used. +bool ReplaceStandardURL(const char* base, + const URLSegments& baseParsed, + const Replacements<UChar>& replacements, + URLQueryCharsetConverter* queryConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + RawURLBuffer<char> utf8; + URLComponentSource<char> source(base); + URLSegments parsed(baseParsed); + SetupUTF16OverrideComponents(base, replacements, utf8, &source, &parsed); + return doCanonicalizeStandardURL<char, unsigned char>(source, parsed, queryConverter, output, *outputParsed); +} + +} // namespace URLCanonicalizer + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLCharacterTypes.cpp b/Source/WTF/wtf/url/src/URLCharacterTypes.cpp index f56e7207c..21dd22fcc 100644 --- a/Source/WTF/wtf/url/src/URLCharacterTypes.cpp +++ b/Source/WTF/wtf/url/src/URLCharacterTypes.cpp @@ -1,30 +1,32 @@ -// 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. +/* + * 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. + */ #include "config.h" #include "URLCharacterTypes.h" @@ -32,7 +34,6 @@ #if USE(WTFURL) namespace WTF { - const unsigned char URLCharacterTypes::characterTypeTable[0x100] = { InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, @@ -43,100 +44,100 @@ const unsigned char URLCharacterTypes::characterTypeTable[0x100] = { InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x10 - 0x1f InvalidCharacter, // 0x20 ' ' (escape spaces in queries) - QueryCharacter | UserInfoCharacter, // 0x21 ! + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x21 ! InvalidCharacter, // 0x22 " InvalidCharacter, // 0x23 # (invalid in query since it marks the ref) QueryCharacter | UserInfoCharacter, // 0x24 $ QueryCharacter | UserInfoCharacter, // 0x25 % QueryCharacter | UserInfoCharacter, // 0x26 & - QueryCharacter | UserInfoCharacter, // 0x27 ' - QueryCharacter | UserInfoCharacter, // 0x28 ( - QueryCharacter | UserInfoCharacter, // 0x29 ) - QueryCharacter | UserInfoCharacter, // 0x2a * + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x27 ' + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x28 ( + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x29 ) + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x2a * QueryCharacter | UserInfoCharacter, // 0x2b + QueryCharacter | UserInfoCharacter, // 0x2c , - QueryCharacter | UserInfoCharacter, // 0x2d - - QueryCharacter | UserInfoCharacter | IPv4Character, // 0x2e . + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x2d - + QueryCharacter | UserInfoCharacter | IPv4Character | ComponentCharacter, // 0x2e . QueryCharacter, // 0x2f / - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x30 0 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x31 1 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x32 2 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x33 3 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x34 4 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x35 5 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x36 6 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x37 7 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter, // 0x38 8 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter, // 0x39 9 + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | OctalCharacter | ComponentCharacter, // 0x30 0 + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | OctalCharacter | ComponentCharacter, // 0x31 1 + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | OctalCharacter | ComponentCharacter, // 0x32 2 + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | OctalCharacter | ComponentCharacter, // 0x33 3 + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | OctalCharacter | ComponentCharacter, // 0x34 4 + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | OctalCharacter | ComponentCharacter, // 0x35 5 + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | OctalCharacter | ComponentCharacter, // 0x36 6 + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | OctalCharacter | ComponentCharacter, // 0x37 7 + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | ComponentCharacter, // 0x38 8 + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | DecimalCharacter | ComponentCharacter, // 0x39 9 QueryCharacter, // 0x3a : QueryCharacter, // 0x3b ; - InvalidCharacter, // 0x3c < + InvalidCharacter, // 0x3c < (Try to prevent certain types of XSS.) QueryCharacter, // 0x3d = - InvalidCharacter, // 0x3e > + InvalidCharacter, // 0x3e > (Try to prevent certain types of XSS.) QueryCharacter, // 0x3f ? QueryCharacter, // 0x40 @ - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x41 A - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x42 B - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x43 C - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x44 D - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x45 E - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x46 F - QueryCharacter | UserInfoCharacter, // 0x47 G - QueryCharacter | UserInfoCharacter, // 0x48 H - QueryCharacter | UserInfoCharacter, // 0x49 I - QueryCharacter | UserInfoCharacter, // 0x4a J - QueryCharacter | UserInfoCharacter, // 0x4b K - QueryCharacter | UserInfoCharacter, // 0x4c L - QueryCharacter | UserInfoCharacter, // 0x4d M - QueryCharacter | UserInfoCharacter, // 0x4e N - QueryCharacter | UserInfoCharacter, // 0x4f O - QueryCharacter | UserInfoCharacter, // 0x50 P - QueryCharacter | UserInfoCharacter, // 0x51 Q - QueryCharacter | UserInfoCharacter, // 0x52 R - QueryCharacter | UserInfoCharacter, // 0x53 S - QueryCharacter | UserInfoCharacter, // 0x54 T - QueryCharacter | UserInfoCharacter, // 0x55 U - QueryCharacter | UserInfoCharacter, // 0x56 V - QueryCharacter | UserInfoCharacter, // 0x57 W - QueryCharacter | UserInfoCharacter | IPv4Character, // 0x58 X - QueryCharacter | UserInfoCharacter, // 0x59 Y - QueryCharacter | UserInfoCharacter, // 0x5a Z + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x41 A + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x42 B + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x43 C + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x44 D + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x45 E + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x46 F + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x47 G + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x48 H + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x49 I + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x4a J + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x4b K + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x4c L + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x4d M + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x4e N + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x4f O + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x50 P + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x51 Q + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x52 R + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x53 S + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x54 T + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x55 U + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x56 V + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x57 W + QueryCharacter | UserInfoCharacter | IPv4Character | ComponentCharacter, // 0x58 X + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x59 Y + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x5a Z QueryCharacter, // 0x5b [ QueryCharacter, // 0x5c '\' QueryCharacter, // 0x5d ] QueryCharacter, // 0x5e ^ - QueryCharacter | UserInfoCharacter, // 0x5f _ + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x5f _ QueryCharacter, // 0x60 ` - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x61 a - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x62 b - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x63 c - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x64 d - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x65 e - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x66 f - QueryCharacter | UserInfoCharacter, // 0x67 g - QueryCharacter | UserInfoCharacter, // 0x68 h - QueryCharacter | UserInfoCharacter, // 0x69 i - QueryCharacter | UserInfoCharacter, // 0x6a j - QueryCharacter | UserInfoCharacter, // 0x6b k - QueryCharacter | UserInfoCharacter, // 0x6c l - QueryCharacter | UserInfoCharacter, // 0x6d m - QueryCharacter | UserInfoCharacter, // 0x6e n - QueryCharacter | UserInfoCharacter, // 0x6f o - QueryCharacter | UserInfoCharacter, // 0x70 p - QueryCharacter | UserInfoCharacter, // 0x71 q - QueryCharacter | UserInfoCharacter, // 0x72 r - QueryCharacter | UserInfoCharacter, // 0x73 s - QueryCharacter | UserInfoCharacter, // 0x74 t - QueryCharacter | UserInfoCharacter, // 0x75 u - QueryCharacter | UserInfoCharacter, // 0x76 v - QueryCharacter | UserInfoCharacter, // 0x77 w - QueryCharacter | UserInfoCharacter | IPv4Character, // 0x78 x - QueryCharacter | UserInfoCharacter, // 0x79 y - QueryCharacter | UserInfoCharacter, // 0x7a z + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x61 a + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x62 b + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x63 c + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x64 d + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x65 e + QueryCharacter | UserInfoCharacter | IPv4Character | HexadecimalCharacter | ComponentCharacter, // 0x66 f + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x67 g + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x68 h + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x69 i + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x6a j + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x6b k + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x6c l + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x6d m + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x6e n + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x6f o + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x70 p + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x71 q + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x72 r + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x73 s + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x74 t + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x75 u + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x76 v + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x77 w + QueryCharacter | UserInfoCharacter | IPv4Character | ComponentCharacter, // 0x78 x + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x79 y + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x7a z QueryCharacter, // 0x7b { QueryCharacter, // 0x7c | QueryCharacter, // 0x7d } - QueryCharacter | UserInfoCharacter, // 0x7e ~ + QueryCharacter | UserInfoCharacter | ComponentCharacter, // 0x7e ~ InvalidCharacter, // 0x7f InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, diff --git a/Source/WTF/wtf/url/src/URLCharacterTypes.h b/Source/WTF/wtf/url/src/URLCharacterTypes.h index 6edb98ca2..6652105e8 100644 --- a/Source/WTF/wtf/url/src/URLCharacterTypes.h +++ b/Source/WTF/wtf/url/src/URLCharacterTypes.h @@ -1,30 +1,32 @@ -// 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. +/* + * 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 URLCharacterTypes_h #define URLCharacterTypes_h @@ -35,27 +37,29 @@ namespace WTF { class URLCharacterTypes { public: - static inline bool isQueryChar(unsigned char c) { return isCharOfType(c, QueryCharacter); } - static inline bool isIPv4Char(unsigned char c) { return isCharOfType(c, IPv4Character); } - static inline bool isHexChar(unsigned char c) { return isCharOfType(c, HexCharacter); } - -private: - enum CharTypes { + enum CharacterTypes { InvalidCharacter = 0, QueryCharacter = 1 << 0, UserInfoCharacter = 1 << 1, IPv4Character = 1 << 2, - HexCharacter = 1 << 3, + HexadecimalCharacter = 1 << 3, DecimalCharacter = 1 << 4, OctalCharacter = 1 << 5, + ComponentCharacter = 1 << 6, }; - static const unsigned char characterTypeTable[0x100]; + static inline bool isComponentChar(unsigned char character) { return isCharacterOfType(character, ComponentCharacter); } + static inline bool isHexChar(unsigned char character) { return isCharacterOfType(character, HexadecimalCharacter); } + static inline bool isIPv4Char(unsigned char character) { return isCharacterOfType(character, IPv4Character); } + static inline bool isQueryChar(unsigned char character) { return isCharacterOfType(character, QueryCharacter); } - static inline bool isCharOfType(unsigned char c, CharTypes type) + static inline bool isCharacterOfType(unsigned char HexCharacter, CharacterTypes type) { - return !!(characterTypeTable[c] & type); + return !!(characterTypeTable[HexCharacter] & type); } + +private: + static const unsigned char characterTypeTable[0x100]; }; } diff --git a/Source/WTF/wtf/url/src/URLComponent.h b/Source/WTF/wtf/url/src/URLComponent.h index 747a80b80..308cc0b5e 100644 --- a/Source/WTF/wtf/url/src/URLComponent.h +++ b/Source/WTF/wtf/url/src/URLComponent.h @@ -1,30 +1,32 @@ -// 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. +/* + * 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 diff --git a/Source/WTF/wtf/url/src/URLEscape.cpp b/Source/WTF/wtf/url/src/URLEscape.cpp deleted file mode 100644 index 5acdcde24..000000000 --- a/Source/WTF/wtf/url/src/URLEscape.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// 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. - -#include "config.h" -#include "URLEscape.h" - -#if USE(WTFURL) - -namespace WTF { - -const char hexCharacterTable[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', -}; - -} - -#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLEscape.h b/Source/WTF/wtf/url/src/URLEscape.h deleted file mode 100644 index e010012a3..000000000 --- a/Source/WTF/wtf/url/src/URLEscape.h +++ /dev/null @@ -1,53 +0,0 @@ -// 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 URLEscape_h -#define URLEscape_h - -#if USE(WTFURL) - -#include "URLBuffer.h" - -namespace WTF { - -extern const char hexCharacterTable[16]; - -template<typename InChar, typename OutChar> -inline void appendURLEscapedCharacter(InChar ch, URLBuffer<OutChar>& buffer) -{ - buffer.append('%'); - buffer.append(hexCharacterTable[ch >> 4]); - buffer.append(hexCharacterTable[ch & 0xf]); -} - -} - -#endif // USE(WTFURL) - -#endif diff --git a/Source/WTF/wtf/url/src/URLFile.h b/Source/WTF/wtf/url/src/URLFile.h new file mode 100644 index 000000000..48b12ebdf --- /dev/null +++ b/Source/WTF/wtf/url/src/URLFile.h @@ -0,0 +1,116 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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. + */ + +// Provides shared functions used by the internals of the parser and +// canonicalizer for file URLs. Do not use outside of these modules. + +#ifndef URLFile_h +#define URLFile_h + +#include "URLParseInternal.h" +#include <wtf/unicode/Unicode.h> + +#if USE(WTFURL) + +namespace WTF { + +namespace URLParser { + +#if OS(WINDOWS) +// We allow both "c:" and "c|" as drive identifiers. +inline bool isWindowsDriveSeparator(UChar character) +{ + return character == ':' || character == '|'; +} +inline bool isWindowsDriveLetter(UChar character) +{ + return (character >= 'A' && character <= 'Z') || (character >= 'a' && character <= 'z'); +} +#endif // OS(WINDOWS) + +// Returns the index of the next slash in the input after the given index, or +// specLength if the end of the input is reached. +template<typename CharacterType> +inline int findNextSlash(const CharacterType* spec, int beginIndex, int specLength) +{ + int idx = beginIndex; + while (idx < specLength && !isURLSlash(spec[idx])) + ++idx; + return idx; +} + +#if OS(WINDOWS) +// Returns true if the startOffset in the given spec looks like it begins a +// drive spec, for example "c:". This function explicitly handles startOffset +// values that are equal to or larger than the specLength to simplify callers. +// +// If this returns true, the spec is guaranteed to have a valid drive letter +// plus a colon starting at |startOffset|. +template<typename CharacterType> +inline bool doesBeginWindowsDriveSpec(const CharacterType* spec, int startOffset, int specLength) +{ + int remainingLength = specLength - startOffset; + if (remainingLength < 2) + return false; // Not enough room. + if (!isWindowsDriveLetter(spec[startOffset])) + return false; // Doesn't start with a valid drive letter. + if (!isWindowsDriveSeparator(spec[startOffset + 1])) + return false; // Isn't followed with a drive separator. + return true; +} + +// Returns true if the startOffset in the given text looks like it begins a +// UNC path, for example "\\". This function explicitly handles startOffset +// values that are equal to or larger than the specLength to simplify callers. +// +// When strictSlashes is set, this function will only accept backslashes as is +// standard for Windows. Otherwise, it will accept forward slashes as well +// which we use for a lot of URL handling. +template<typename CharacterType> +inline bool doesBeginUNCPath(const CharacterType* text, int startOffset, int length, bool strictSlashes) +{ + int remainingLength = length - startOffset; + if (remainingLength < 2) + return false; + + if (strictSlashes) + return text[startOffset] == '\\' && text[startOffset + 1] == '\\'; + return isURLSlash(text[startOffset]) && isURLSlash(text[startOffset + 1]); +} +#endif // OS(WINDOWS) + +} // namespace URLParser + +} // namespace WTF + +#endif // USE(WTFURL) + +#endif // URLFile_h diff --git a/Source/WTF/wtf/url/src/URLParse.cpp b/Source/WTF/wtf/url/src/URLParse.cpp new file mode 100644 index 000000000..1d7e42edd --- /dev/null +++ b/Source/WTF/wtf/url/src/URLParse.cpp @@ -0,0 +1,787 @@ +/* Based on nsURLParsers.cc from Mozilla + * ------------------------------------- + * Copyright (C) 1998 Netscape Communications Corporation. + * Copyright 2012, Google Inc. All rights reserved. + * Copyright (C) 2012 Apple Inc. All rights reserved. + * 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 + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher (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. + * + */ + +#include "config.h" +#include "URLParse.h" + +#include "URLParseInternal.h" +#include "URLUtil.h" +#include "URLUtilInternal.h" +#include <stdlib.h> +#include <wtf/ASCIICType.h> + +#if USE(WTFURL) + +namespace WTF { + +namespace URLParser { + +namespace { + +// Returns the offset of the next authority terminator in the input starting +// from startOffset. If no terminator is found, the return value will be equal +// to specLength. +template<typename CharacterType> +int findNextAuthorityTerminator(const CharacterType* spec, int startOffset, int specLength) +{ + for (int i = startOffset; i < specLength; i++) { + if (IsAuthorityTerminator(spec[i])) + return i; + } + return specLength; // Not found. +} + +template<typename CharacterType> +void parseUserInfo(const CharacterType* spec, const URLComponent& user, URLComponent& username, URLComponent& password) +{ + // Find the first colon in the user section, which separates the username and + // password. + int colonOffset = 0; + while (colonOffset < user.length() && spec[user.begin() + colonOffset] != ':') + ++colonOffset; + + if (colonOffset < user.length()) { + // Found separator: <username>:<password> + username = URLComponent(user.begin(), colonOffset); + password = URLComponent::fromRange(user.begin() + colonOffset + 1, user.end()); + } else { + // No separator, treat everything as the username + username = user; + password = URLComponent(); + } +} + +template<typename CharacterType> +void parseServerInfo(const CharacterType* spec, const URLComponent& serverInfo, URLComponent& hostname, URLComponent& port) +{ + if (!serverInfo.length()) { + // No server info, host name is empty. + hostname = URLComponent(); + port = URLComponent(); + return; + } + + // If the host starts with a left-bracket, assume the entire host is an + // IPv6 literal. Otherwise, assume none of the host is an IPv6 literal. + // This assumption will be overridden if we find a right-bracket. + // + // Our IPv6 address canonicalization code requires both brackets to exist, + // but the ability to locate an incomplete address can still be useful. + int ipv6Terminator = spec[serverInfo.begin()] == '[' ? serverInfo.end() : -1; + int colon = -1; + + // Find the last right-bracket, and the last colon. + for (int i = serverInfo.begin(); i < serverInfo.end(); ++i) { + switch (spec[i]) { + case ']': + ipv6Terminator = i; + break; + case ':': + colon = i; + break; + } + } + + if (colon > ipv6Terminator) { + // Found a port number: <hostname>:<port> + hostname = URLComponent::fromRange(serverInfo.begin(), colon); + if (!hostname.length()) + hostname.reset(); + port = URLComponent::fromRange(colon + 1, serverInfo.end()); + } else { + // No port: <hostname> + hostname = serverInfo; + port = URLComponent(); + } +} + +// Given an already-identified auth section, breaks it into its consituent +// parts. The port number will be parsed and the resulting integer will be +// filled into the given *port variable, or -1 if there is no port number or it +// is invalid. +template<typename CharacterType> +void doParseAuthority(const CharacterType* spec, const URLComponent& authority, URLComponent& username, URLComponent& password, URLComponent& hostname, URLComponent& port) +{ + ASSERT_WITH_MESSAGE(authority.isValid(), "We should always get an authority"); + if (!authority.length()) { + username = URLComponent(); + password = URLComponent(); + hostname = URLComponent(); + port = URLComponent(); + return; + } + + // Search backwards for @, which is the separator between the user info and + // the server info. + int i = authority.end() - 1; + while (i > authority.begin() && spec[i] != '@') + --i; + + if (spec[i] == '@') { + // Found user info: <user-info>@<server-info> + parseUserInfo(spec, URLComponent(authority.begin(), i - authority.begin()), username, password); + parseServerInfo(spec, URLComponent::fromRange(i + 1, authority.end()), hostname, port); + } else { + // No user info, everything is server info. + username = URLComponent(); + password = URLComponent(); + parseServerInfo(spec, authority, hostname, port); + } +} + +template<typename CharacterType> +void parsePath(const CharacterType* spec, const URLComponent& hierarchicalidentifiers, URLComponent& resourcePath, URLComponent& query, URLComponent& fragment) +{ + // path = [/]<segment1>/<segment2>/<...>/<segmentN>;<param>?<query>#<ref> + + // Special case when there is no path. + if (hierarchicalidentifiers.length() == -1) { + resourcePath = URLComponent(); + query = URLComponent(); + fragment = URLComponent(); + return; + } + ASSERT_WITH_MESSAGE(hierarchicalidentifiers.length() > 0, "We should never have 0 length paths"); + + // Search for first occurrence of either ? or #. + int pathEnd = hierarchicalidentifiers.end(); + + int querySeparator = -1; // Index of the '?' + int fragmentSeparator = -1; // Index of the '#' + for (int i = hierarchicalidentifiers.begin(); i < pathEnd; ++i) { + switch (spec[i]) { + case '?': + // Only match the query string if it precedes the reference fragment + // and when we haven't found one already. + if (fragmentSeparator < 0 && querySeparator < 0) + querySeparator = i; + break; + case '#': + // Record the first # sign only. + if (fragmentSeparator < 0) + fragmentSeparator = i; + break; + } + } + + // Markers pointing to the character after each of these corresponding + // components. The code below words from the end back to the beginning, + // and will update these indices as it finds components that exist. + int resourcePathEnd = -1; + int queryEnd = -1; + + // Ref fragment: from the # to the end of the path. + if (fragmentSeparator >= 0) { + resourcePathEnd = queryEnd = fragmentSeparator; + fragment = URLComponent::fromRange(fragmentSeparator + 1, pathEnd); + } else { + resourcePathEnd = queryEnd = pathEnd; + fragment = URLComponent(); + } + + // Query fragment: everything from the ? to the next boundary (either the end + // of the path or the ref fragment). + if (querySeparator >= 0) { + resourcePathEnd = querySeparator; + query = URLComponent::fromRange(querySeparator + 1, queryEnd); + } else + query = URLComponent(); + + // File path: treat an empty file path as no file path. + if (resourcePathEnd != hierarchicalidentifiers.begin()) + resourcePath = URLComponent::fromRange(hierarchicalidentifiers.begin(), resourcePathEnd); + else + resourcePath = URLComponent(); +} + +template<typename CharacterType> +bool doExtractScheme(const CharacterType* url, int urlLength, URLComponent& scheme) +{ + // Skip leading whitespace and control characters. + int begin = 0; + while (begin < urlLength && shouldTrimFromURL(url[begin])) + ++begin; + + if (begin == urlLength) + return false; // Input is empty or all whitespace. + + // Find the first colon character. + for (int i = begin; i < urlLength; ++i) { + if (url[i] == ':') { + scheme = URLComponent::fromRange(begin, i); + return true; + } + } + return false; // No colon found: no scheme +} + +// Fills in all members of the Parsed structure except for the scheme. +// +// |spec| is the full spec being parsed, of length |specLength|. +// |afterScheme| is the character immediately following the scheme (after the +// colon) where we'll begin parsing. +// +// Compatability data points. I list "host", "path" extracted: +// Input IE6 Firefox Us +// ----- -------------- -------------- -------------- +// http://foo.com/ "foo.com", "/" "foo.com", "/" "foo.com", "/" +// http:foo.com/ "foo.com", "/" "foo.com", "/" "foo.com", "/" +// http:/foo.com/ fail(*) "foo.com", "/" "foo.com", "/" +// http:\foo.com/ fail(*) "\foo.com", "/"(fail) "foo.com", "/" +// http:////foo.com/ "foo.com", "/" "foo.com", "/" "foo.com", "/" +// +// (*) Interestingly, although IE fails to load these URLs, its history +// canonicalizer handles them, meaning if you've been to the corresponding +// "http://foo.com/" link, it will be colored. +template <typename CharacterType> +void doParseAfterScheme(const CharacterType* spec, int specLength, int afterScheme, URLSegments& parsed) +{ + int slashesCount = countConsecutiveSlashes(spec, afterScheme, specLength); + int afterSlashes = afterScheme + slashesCount; + + // First split into two main parts, the authority (username, password, host, + // and port) and the full path (path, query, and reference). + URLComponent authority; + URLComponent fullPath; + + // Found "//<some data>", looks like an authority section. Treat everything + // from there to the next slash (or end of spec) to be the authority. Note + // that we ignore the number of slashes and treat it as the authority. + int endAuth = findNextAuthorityTerminator(spec, afterSlashes, specLength); + authority = URLComponent::fromRange(afterSlashes, endAuth); + + if (endAuth == specLength) // No beginning of path found. + fullPath = URLComponent(); + else // Everything starting from the slash to the end is the path. + fullPath = URLComponent::fromRange(endAuth, specLength); + + // Now parse those two sub-parts. + doParseAuthority(spec, authority, parsed.username, parsed.password, parsed.host, parsed.port); + parsePath(spec, fullPath, parsed.path, parsed.query, parsed.fragment); +} + +// The main parsing function for standard URLs. Standard URLs have a scheme, +// host, path, etc. +template<typename CharacterType> +void doParseStandardURL(const CharacterType* spec, int specLength, URLSegments& parsed) +{ + ASSERT(specLength >= 0); + + // Strip leading & trailing spaces and control characters. + int begin = 0; + trimURL(spec, begin, specLength); + + int afterScheme = -1; + if (doExtractScheme(spec, specLength, parsed.scheme)) + afterScheme = parsed.scheme.end() + 1; // Skip past the colon. + else { + // Say there's no scheme when there is no colon. We could also say that + // everything is the scheme. Both would produce an invalid URL, but this way + // seems less wrong in more cases. + parsed.scheme.reset(); + afterScheme = begin; + } + doParseAfterScheme(spec, specLength, afterScheme, parsed); +} + +template<typename CharacterType> +void doParseFileSystemURL(const CharacterType* spec, int specLength, URLSegments& parsed) +{ + ASSERT(specLength >= 0); + + // Get the unused parts of the URL out of the way. + parsed.username.reset(); + parsed.password.reset(); + parsed.host.reset(); + parsed.port.reset(); + parsed.path.reset(); // May use this; reset for convenience. + parsed.fragment.reset(); // May use this; reset for convenience. + parsed.query.reset(); // May use this; reset for convenience. + parsed.clearInnerURLSegments(); // May use this; reset for convenience. + + // Strip leading & trailing spaces and control characters. + int begin = 0; + trimURL(spec, begin, specLength); + + // Handle empty specs or ones that contain only whitespace or control chars. + if (begin == specLength) { + parsed.scheme.reset(); + return; + } + + int innerStart = -1; + + // Extract the scheme. We also handle the case where there is no scheme. + if (doExtractScheme(&spec[begin], specLength - begin, parsed.scheme)) { + // Offset the results since we gave ExtractScheme a substring. + parsed.scheme.setBegin(parsed.scheme.begin() + begin); + + if (parsed.scheme.end() == specLength - 1) + return; + + innerStart = parsed.scheme.end() + 1; + } else { + // No scheme found; that's not valid for filesystem URLs. + parsed.scheme.reset(); + return; + } + + URLComponent innerScheme; + const CharacterType* innerSpec = &spec[innerStart]; + int innerSpecLength = specLength - innerStart; + + if (doExtractScheme(innerSpec, innerSpecLength, innerScheme)) { + // Offset the results since we gave ExtractScheme a substring. + innerScheme.setBegin(innerScheme.begin() + innerStart); + + if (innerScheme.end() == specLength - 1) + return; + } else { + // No scheme found; that's not valid for filesystem URLs. + // The best we can do is return "filesystem://". + return; + } + + URLSegments innerParsed; + if (URLUtilities::CompareSchemeComponent(spec, innerScheme, URLUtilities::kFileScheme)) { + // File URLs are special. + ParseFileURL(innerSpec, innerSpecLength, &innerParsed); + } else if (URLUtilities::CompareSchemeComponent(spec, innerScheme, URLUtilities::kFileSystemScheme)) { + // Filesystem URLs don't nest. + return; + } else if (URLUtilities::isStandard(spec, innerScheme)) { + // All "normal" URLs. + doParseStandardURL(innerSpec, innerSpecLength, innerParsed); + } else + return; + + // All members of innerParsed need to be offset by innerStart. + // If we had any scheme that supported nesting more than one level deep, + // we'd have to recurse into the innerParsed's innerParsed when + // adjusting by innerStart. + innerParsed.scheme.setBegin(innerParsed.scheme.begin() + innerStart); + innerParsed.username.setBegin(innerParsed.username.begin() + innerStart); + innerParsed.password.setBegin(innerParsed.password.begin() + innerStart); + innerParsed.host.setBegin(innerParsed.host.begin() + innerStart); + innerParsed.port.setBegin(innerParsed.port.begin() + innerStart); + innerParsed.query.setBegin(innerParsed.query.begin() + innerStart); + innerParsed.fragment.setBegin(innerParsed.fragment.begin() + innerStart); + innerParsed.path.setBegin(innerParsed.path.begin() + innerStart); + + // Query and ref move from innerParsed to parsed. + parsed.query = innerParsed.query; + innerParsed.query.reset(); + parsed.fragment = innerParsed.fragment; + innerParsed.fragment.reset(); + + parsed.setInnerURLSegments(innerParsed); + if (!innerParsed.scheme.isValid() || !innerParsed.path.isValid() || innerParsed.innerURLSegments()) + return; + + // The path in innerParsed should start with a slash, then have a filesystem + // type followed by a slash. From the first slash up to but excluding the + // second should be what it keeps; the rest goes to parsed. If the path ends + // before the second slash, it's still pretty clear what the user meant, so + // we'll let that through. + if (!isURLSlash(spec[innerParsed.path.begin()])) + return; + + int innerPathEnd = innerParsed.path.begin() + 1; // skip the leading slash + while (innerPathEnd < specLength && !isURLSlash(spec[innerPathEnd])) + ++innerPathEnd; + parsed.path.setBegin(innerPathEnd); + int newInnerPathLength = innerPathEnd - innerParsed.path.begin(); + parsed.path.setLength(innerParsed.path.length() - newInnerPathLength); + innerParsed.path.setLength(newInnerPathLength); + parsed.setInnerURLSegments(innerParsed); +} + +// Initializes a path URL which is merely a scheme followed by a path. Examples +// include "about:foo" and "javascript:alert('bar');" +template<typename CharacterType> +void doParsePathURL(const CharacterType* spec, int specLength, URLSegments& parsed) +{ + // Get the non-path and non-scheme parts of the URL out of the way, we never + // use them. + parsed.username.reset(); + parsed.password.reset(); + parsed.host.reset(); + parsed.port.reset(); + parsed.query.reset(); + parsed.fragment.reset(); + + // Strip leading & trailing spaces and control characters. + int begin = 0; + trimURL(spec, begin, specLength); + + // Handle empty specs or ones that contain only whitespace or control chars. + if (begin == specLength) { + parsed.scheme.reset(); + parsed.path.reset(); + return; + } + + // Extract the scheme, with the path being everything following. We also + // handle the case where there is no scheme. + if (ExtractScheme(&spec[begin], specLength - begin, &parsed.scheme)) { + // Offset the results since we gave ExtractScheme a substring. + parsed.scheme.setBegin(parsed.scheme.begin() + begin); + + // For compatability with the standard URL parser, we treat no path as + // -1, rather than having a length of 0 (we normally wouldn't care so + // much for these non-standard URLs). + if (parsed.scheme.end() == specLength - 1) + parsed.path.reset(); + else + parsed.path = URLComponent::fromRange(parsed.scheme.end() + 1, specLength); + } else { + // No scheme found, just path. + parsed.scheme.reset(); + parsed.path = URLComponent::fromRange(begin, specLength); + } +} + +template<typename CharacterType> +void doParseMailtoURL(const CharacterType* spec, int specLength, URLSegments& parsed) +{ + ASSERT(specLength >= 0); + + // Get the non-path and non-scheme parts of the URL out of the way, we never + // use them. + parsed.username.reset(); + parsed.password.reset(); + parsed.host.reset(); + parsed.port.reset(); + parsed.fragment.reset(); + parsed.query.reset(); // May use this; reset for convenience. + + // Strip leading & trailing spaces and control characters. + int begin = 0; + trimURL(spec, begin, specLength); + + // Handle empty specs or ones that contain only whitespace or control chars. + if (begin == specLength) { + parsed.scheme.reset(); + parsed.path.reset(); + return; + } + + int pathBegin = -1; + int pathEnd = -1; + + // Extract the scheme, with the path being everything following. We also + // handle the case where there is no scheme. + if (ExtractScheme(&spec[begin], specLength - begin, &parsed.scheme)) { + // Offset the results since we gave ExtractScheme a substring. + parsed.scheme.setBegin(parsed.scheme.begin() + begin); + + if (parsed.scheme.end() != specLength - 1) { + pathBegin = parsed.scheme.end() + 1; + pathEnd = specLength; + } + } else { + // No scheme found, just path. + parsed.scheme.reset(); + pathBegin = begin; + pathEnd = specLength; + } + + // Split [pathBegin, pathEnd) into a path + query. + for (int i = pathBegin; i < pathEnd; ++i) { + if (spec[i] == '?') { + parsed.query = URLComponent::fromRange(i + 1, pathEnd); + pathEnd = i; + break; + } + } + + // For compatability with the standard URL parser, treat no path as + // -1, rather than having a length of 0 + if (pathBegin == pathEnd) + parsed.path.reset(); + else + parsed.path = URLComponent::fromRange(pathBegin, pathEnd); +} + +// Converts a port number in a string to an integer. We'd like to just call +// sscanf but our input is not null-terminated, which sscanf requires. Instead, +// we copy the digits to a small stack buffer (since we know the maximum number +// of digits in a valid port number) that we can null terminate. +template<typename CharacterType> +int doParsePort(const CharacterType* spec, const URLComponent& component) +{ + // Easy success case when there is no port. + const int kMaxDigits = 5; + if (!component.isNonEmpty()) + return PORT_UNSPECIFIED; + + // Skip over any leading 0s. + URLComponent digitComponent(component.end(), 0); + for (int i = 0; i < component.length(); i++) { + if (spec[component.begin() + i] != '0') { + digitComponent = URLComponent::fromRange(component.begin() + i, component.end()); + break; + } + } + if (!digitComponent.length()) + return 0; // All digits were 0. + + // Verify we don't have too many digits (we'll be copying to our buffer so + // we need to double-check). + if (digitComponent.length() > kMaxDigits) + return PORT_INVALID; + + // Copy valid digits to the buffer. + char digits[kMaxDigits + 1]; // +1 for null terminator + for (int i = 0; i < digitComponent.length(); i++) { + CharacterType ch = spec[digitComponent.begin() + i]; + if (!isASCIIDigit(ch)) { + // Invalid port digit, fail. + return PORT_INVALID; + } + digits[i] = static_cast<char>(ch); + } + + // Null-terminate the string and convert to integer. Since we guarantee + // only digits, atoi's lack of error handling is OK. + digits[digitComponent.length()] = 0; + int port = atoi(digits); + if (port > 65535) + return PORT_INVALID; // Out of range. + return port; +} + +template<typename CharacterType> +void doExtractFileName(const CharacterType* spec, const URLComponent& path, URLComponent& fileName) +{ + // Handle empty paths: they have no file names. + if (!path.isNonEmpty()) { + fileName = URLComponent(); + return; + } + + // Search backwards for a parameter, which is a normally unused field in a + // URL delimited by a semicolon. We parse the parameter as part of the + // path, but here, we don't want to count it. The last semicolon is the + // parameter. The path should start with a slash, so we don't need to check + // the first one. + int fileEnd = path.end(); + for (int i = path.end() - 1; i > path.begin(); --i) { + if (spec[i] == ';') { + fileEnd = i; + break; + } + } + + // Now search backwards from the filename end to the previous slash + // to find the beginning of the filename. + for (int i = fileEnd - 1; i >= path.begin(); --i) { + if (isURLSlash(spec[i])) { + // File name is everything following this character to the end + fileName = URLComponent::fromRange(i + 1, fileEnd); + return; + } + } + + // No slash found, this means the input was degenerate (generally paths + // will start with a slash). Let's call everything the file name. + fileName = URLComponent::fromRange(path.begin(), fileEnd); + return; +} + +template<typename CharacterType> +bool doExtractQueryKeyValue(const CharacterType* spec, URLComponent& query, URLComponent& key, URLComponent& value) +{ + if (!query.isNonEmpty()) + return false; + + int start = query.begin(); + int current = start; + int end = query.end(); + + // We assume the beginning of the input is the beginning of the "key" and we + // skip to the end of it. + key.setBegin(current); + while (current < end && spec[current] != '&' && spec[current] != '=') + ++current; + key.setLength(current - key.begin()); + + // Skip the separator after the key (if any). + if (current < end && spec[current] == '=') + ++current; + + // Find the value part. + value.setBegin(current); + while (current < end && spec[current] != '&') + ++current; + value.setLength(current - value.begin()); + + // Finally skip the next separator if any + if (current < end && spec[current] == '&') + ++current; + + // Save the new query + query = URLComponent::fromRange(current, end); + return true; +} + +} // namespace + +bool ExtractScheme(const char* url, int urlLength, URLComponent* scheme) +{ + return doExtractScheme(url, urlLength, *scheme); +} + +bool ExtractScheme(const UChar* url, int urlLength, URLComponent* scheme) +{ + return doExtractScheme(url, urlLength, *scheme); +} + +// This handles everything that may be an authority terminator, including +// backslash. For special backslash handling see DoParseAfterScheme. +bool IsAuthorityTerminator(UChar character) +{ + return isURLSlash(character) || character == '?' || character == '#'; +} + +void ExtractFileName(const char* url, const URLComponent& path, URLComponent* fileName) +{ + doExtractFileName(url, path, *fileName); +} + +void ExtractFileName(const UChar* url, const URLComponent& path, URLComponent* fileName) +{ + doExtractFileName(url, path, *fileName); +} + +bool ExtractQueryKeyValue(const char* url, URLComponent* query, URLComponent* key, URLComponent* value) +{ + return doExtractQueryKeyValue(url, *query, *key, *value); +} + +bool ExtractQueryKeyValue(const UChar* url, URLComponent* query, URLComponent* key, URLComponent* value) +{ + return doExtractQueryKeyValue(url, *query, *key, *value); +} + +void ParseAuthority(const char* spec, const URLComponent& auth, URLComponent* username, URLComponent* password, URLComponent* hostname, URLComponent* portNumber) +{ + doParseAuthority(spec, auth, *username, *password, *hostname, *portNumber); +} + +void ParseAuthority(const UChar* spec, const URLComponent& auth, URLComponent* username, URLComponent* password, URLComponent* hostname, URLComponent* portNumber) +{ + doParseAuthority(spec, auth, *username, *password, *hostname, *portNumber); +} + +int ParsePort(const char* url, const URLComponent& port) +{ + return doParsePort(url, port); +} + +int ParsePort(const UChar* url, const URLComponent& port) +{ + return doParsePort(url, port); +} + +void ParseStandardURL(const char* url, int urlLength, URLSegments* parsed) +{ + doParseStandardURL(url, urlLength, *parsed); +} + +void ParseStandardURL(const UChar* url, int urlLength, URLSegments* parsed) +{ + doParseStandardURL(url, urlLength, *parsed); +} + +void ParsePathURL(const char* url, int urlLength, URLSegments* parsed) +{ + doParsePathURL(url, urlLength, *parsed); +} + +void ParsePathURL(const UChar* url, int urlLength, URLSegments* parsed) +{ + doParsePathURL(url, urlLength, *parsed); +} + +void ParseFileSystemURL(const char* url, int urlLength, URLSegments* parsed) +{ + doParseFileSystemURL(url, urlLength, *parsed); +} + +void ParseFileSystemURL(const UChar* url, int urlLength, URLSegments* parsed) +{ + doParseFileSystemURL(url, urlLength, *parsed); +} + +void ParseMailtoURL(const char* url, int urlLength, URLSegments* parsed) +{ + doParseMailtoURL(url, urlLength, *parsed); +} + +void ParseMailtoURL(const UChar* url, int urlLength, URLSegments* parsed) +{ + doParseMailtoURL(url, urlLength, *parsed); +} + +void parsePathInternal(const char* spec, const URLComponent& path, URLComponent* filepath, URLComponent* query, URLComponent* fragment) +{ + parsePath(spec, path, *filepath, *query, *fragment); +} + +void parsePathInternal(const UChar* spec, const URLComponent& path, URLComponent* filepath, URLComponent* query, URLComponent* fragment) +{ + parsePath(spec, path, *filepath, *query, *fragment); +} + +void parseAfterScheme(const char* spec, int specLength, int afterScheme, URLSegments& parsed) +{ + doParseAfterScheme(spec, specLength, afterScheme, parsed); +} + +void parseAfterScheme(const UChar* spec, int specLength, int afterScheme, URLSegments& parsed) +{ + doParseAfterScheme(spec, specLength, afterScheme, parsed); +} + +} // namespace URLParser + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLParse.h b/Source/WTF/wtf/url/src/URLParse.h new file mode 100644 index 000000000..c97b10a91 --- /dev/null +++ b/Source/WTF/wtf/url/src/URLParse.h @@ -0,0 +1,167 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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. + */ + +#ifndef URLParse_h +#define URLParse_h + +#include "URLComponent.h" +#include "URLSegments.h" +#include <wtf/unicode/Unicode.h> + +#if USE(WTFURL) + +namespace WTF { + +namespace URLParser { + +// Initialization functions --------------------------------------------------- +// +// These functions parse the given URL, filling in all of the structure's +// components. These functions can not fail, they will always do their best +// at interpreting the input given. +// +// The string length of the URL MUST be specified, we do not check for NULLs +// at any point in the process, and will actually handle embedded NULLs. +// +// IMPORTANT: These functions do NOT hang on to the given pointer or copy it +// in any way. See the comment above the struct. +// +// The 8-bit versions require UTF-8 encoding. + +// StandardURL is for when the scheme is known to be one that has an +// authority (host) like "http". This function will not handle weird ones +// like "about:" and "javascript:", or do the right thing for "file:" URLs. +void ParseStandardURL(const char* url, int urlLength, URLSegments* parsed); +void ParseStandardURL(const UChar* url, int urlLength, URLSegments* parsed); + +// PathURL is for when the scheme is known not to have an authority (host) +// section but that aren't file URLs either. The scheme is parsed, and +// everything after the scheme is considered as the path. This is used for +// things like "about:" and "javascript:" +void ParsePathURL(const char* url, int urlLength, URLSegments* parsed); +void ParsePathURL(const UChar* url, int urlLength, URLSegments* parsed); + +// FileURL is for file URLs. There are some special rules for interpreting +// these. +void ParseFileURL(const char* url, int urlLength, URLSegments* parsed); +void ParseFileURL(const UChar* url, int urlLength, URLSegments* parsed); + +// Filesystem URLs are structured differently than other URLs. +void ParseFileSystemURL(const char* url, int urlLength, URLSegments* parsed); +void ParseFileSystemURL(const UChar* url, int urlLength, URLSegments* parsed); + +// MailtoURL is for mailto: urls. They are made up scheme,path,query +void ParseMailtoURL(const char* url, int urlLength, URLSegments* parsed); +void ParseMailtoURL(const UChar* url, int urlLength, URLSegments* parsed); + +// Helper functions ----------------------------------------------------------- + +// Locates the scheme according to the URL parser's rules. This function is +// designed so the caller can find the scheme and call the correct Init* +// function according to their known scheme types. +// +// It also does not perform any validation on the scheme. +// +// This function will return true if the scheme is found and will put the +// scheme's range into *scheme. False means no scheme could be found. Note +// that a URL beginning with a colon has a scheme, but it is empty, so this +// function will return true but *scheme will = (0,0). +// +// The scheme is found by skipping spaces and control characters at the +// beginning, and taking everything from there to the first colon to be the +// scheme. The character at scheme.end() will be the colon (we may enhance +// this to handle full width colons or something, so don't count on the +// actual character value). The character at scheme.end()+1 will be the +// beginning of the rest of the URL, be it the authority or the path (or the +// end of the string). +// +// The 8-bit version requires UTF-8 encoding. +bool ExtractScheme(const char* url, int urlLength, URLComponent* scheme); +bool ExtractScheme(const UChar* url, int urlLength, URLComponent* scheme); + +// Returns true if ch is a character that terminates the authority segment of a URL. +bool IsAuthorityTerminator(UChar); + +// Does a best effort parse of input |spec|, in range |auth|. If a particular +// component is not found, it will be set to invalid. +void ParseAuthority(const char* spec, const URLComponent& auth, + URLComponent* username, URLComponent* password, URLComponent* hostname, URLComponent* portNumber); +void ParseAuthority(const UChar* spec, const URLComponent& auth, + URLComponent* username, URLComponent* password, URLComponent* hostname, URLComponent* portNumber); + +// Computes the integer port value from the given port component. The port +// component should have been identified by one of the init functions on +// |Parsed| for the given input url. +// +// The return value will be a positive integer between 0 and 64K, or one of +// the two special values below. +enum SpecialPort { PORT_UNSPECIFIED = -1, PORT_INVALID = -2 }; +int ParsePort(const char* url, const URLComponent& port); +int ParsePort(const UChar* url, const URLComponent& port); + +// Extracts the range of the file name in the given url. The path must +// already have been computed by the parse function, and the matching URL +// and extracted path are provided to this function. The filename is +// defined as being everything from the last slash/backslash of the path +// to the end of the path. +// +// The file name will be empty if the path is empty or there is nothing +// following the last slash. +// +// The 8-bit version requires UTF-8 encoding. +void ExtractFileName(const char* url, const URLComponent& path, URLComponent* fileName); +void ExtractFileName(const UChar* url, const URLComponent& path, URLComponent* fileName); + +// Extract the first key/value from the range defined by |*query|. Updates +// |*query| to start at the end of the extracted key/value pair. This is +// designed for use in a loop: you can keep calling it with the same query +// object and it will iterate over all items in the query. +// +// Some key/value pairs may have the key, the value, or both be empty (for +// example, the query string "?&"). These will be returned. Note that an empty +// last parameter "foo.com?" or foo.com?a&" will not be returned, this case +// is the same as "done." +// +// The initial query component should not include the '?' (this is the default +// for parsed URLs). +// +// If no key/value are found |*key| and |*value| will be unchanged and it will +// return false. +bool ExtractQueryKeyValue(const char* url, URLComponent* query, URLComponent* key, URLComponent* value); +bool ExtractQueryKeyValue(const UChar* url, URLComponent* query, URLComponent* key, URLComponent* value); + +} // namespace URLParser + +} // namespace WTF + +#endif // USE(WTFURL) + +#endif // URLParse_h diff --git a/Source/WTF/wtf/url/src/URLParseFile.cpp b/Source/WTF/wtf/url/src/URLParseFile.cpp new file mode 100644 index 000000000..455ef5559 --- /dev/null +++ b/Source/WTF/wtf/url/src/URLParseFile.cpp @@ -0,0 +1,251 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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" +#include "URLParse.h" + +#include "URLFile.h" +#include "URLParseInternal.h" + +// Interesting IE file:isms... +// +// INPUT OUTPUT +// ========================= ============================== +// file:/foo/bar file:///foo/bar +// The result here seems totally invalid!?!? This isn't UNC. +// +// file:/ +// file:// or any other number of slashes +// IE6 doesn't do anything at all if you click on this link. No error: +// nothing. IE6's history system seems to always color this link, so I'm +// guessing that it maps internally to the empty URL. +// +// C:\ file:///C:/ +// When on a file: URL source page, this link will work. When over HTTP, +// the file: URL will appear in the status bar but the link will not work +// (security restriction for all file URLs). +// +// file:foo/ file:foo/ (invalid?!?!?) +// file:/foo/ file:///foo/ (invalid?!?!?) +// file://foo/ file://foo/ (UNC to server "foo") +// file:///foo/ file:///foo/ (invalid, seems to be a file) +// file:////foo/ file://foo/ (UNC to server "foo") +// Any more than four slashes is also treated as UNC. +// +// file:C:/ file://C:/ +// file:/C:/ file://C:/ +// The number of slashes after "file:" don't matter if the thing following +// it looks like an absolute drive path. Also, slashes and backslashes are +// equally valid here. + +#if USE(WTFURL) + +namespace WTF { + +namespace URLParser { + +namespace { + +// A subcomponent of DoInitFileURL, the input of this function should be a UNC +// path name, with the index of the first character after the slashes following +// the scheme given in |afterSlashes|. This will initialize the host, path, +// query, and ref, and leave the other output components untouched +// (DoInitFileURL handles these for us). +template<typename CharacterType> +void doParseUNC(const CharacterType* spec, int afterSlashes, int specLength, URLSegments& parsed) +{ + int nextSlash = findNextSlash(spec, afterSlashes, specLength); + if (nextSlash == specLength) { + // No additional slash found, as in "file://foo", treat the text as the + // host with no path (this will end up being UNC to server "foo"). + int hostLength = specLength - afterSlashes; + if (hostLength) + parsed.host = URLComponent(afterSlashes, hostLength); + else + parsed.host.reset(); + parsed.path.reset(); + return; + } + +#if OS(WINDOWS) + // See if we have something that looks like a path following the first + // component. As in "file://localhost/c:/", we get "c:/" out. We want to + // treat this as a having no host but the path given. Works on Windows only. + if (doesBeginWindowsDriveSpec(spec, nextSlash + 1, specLength)) { + parsed.host.reset(); + parsePathInternal(spec, MakeRange(nextSlash, specLength), + &parsed.path, &parsed.query, &parsed.ref); + return; + } +#endif + + // Otherwise, everything up until that first slash we found is the host name, + // which will end up being the UNC host. For example "file://foo/bar.txt" + // will get a server name of "foo" and a path of "/bar". Later, on Windows, + // this should be treated as the filename "\\foo\bar.txt" in proper UNC + // notation. + int hostLength = nextSlash - afterSlashes; + if (hostLength) + parsed.host = URLComponent::fromRange(afterSlashes, nextSlash); + else + parsed.host.reset(); + if (nextSlash < specLength) { + parsePathInternal(spec, URLComponent::fromRange(nextSlash, specLength), + &parsed.path, &parsed.query, &parsed.fragment); + } else + parsed.path.reset(); +} + +// A subcomponent of DoParseFileURL, the input should be a local file, with the +// beginning of the path indicated by the index in |pathBegin|. This will +// initialize the host, path, query, and ref, and leave the other output +// components untouched (DoInitFileURL handles these for us). +template<typename CharacterType> +void doParseLocalFile(const CharacterType* spec, int pathBegin, int specLength, URLSegments& parsed) +{ + parsed.host.reset(); + parsePathInternal(spec, URLComponent::fromRange(pathBegin, specLength), + &parsed.path, &parsed.query, &parsed.fragment); +} + +// Backend for the external functions that operates on either char type. +// We are handed the character after the "file:" at the beginning of the spec. +// Usually this is a slash, but needn't be; we allow paths like "file:c:\foo". +template<typename CharacterType> +void doParseFileURL(const CharacterType* spec, int specLength, URLSegments& parsed) +{ + ASSERT(specLength >= 0); + + // Get the parts we never use for file URLs out of the way. + parsed.username.reset(); + parsed.password.reset(); + parsed.port.reset(); + + // Many of the code paths don't set these, so it's convenient to just clear + // them. We'll write them in those cases we need them. + parsed.query.reset(); + parsed.fragment.reset(); + + // Strip leading & trailing spaces and control characters. + int begin = 0; + trimURL(spec, begin, specLength); + + // Find the scheme. + int numSlashes; + int afterScheme; + int afterSlashes; +#if OS(WINDOWS) + // See how many slashes there are. We want to handle cases like UNC but also + // "/c:/foo". This is when there is no scheme, so we can allow pages to do + // links like "c:/foo/bar" or "//foo/bar". This is also called by the + // relative URL resolver when it determines there is an absolute URL, which + // may give us input like "/c:/foo". + numSlashes = countConsecutiveSlashes(spec, begin, specLength); + afterSlashes = begin + numSlashes; + if (doesBeginWindowsDriveSpec(spec, afterSlashes, specLength)) { + // Windows path, don't try to extract the scheme (for example, "c:\foo"). + parsed.scheme.reset(); + afterScheme = afterSlashes; + } else if (doesBeginUNCPath(spec, begin, specLength, false)) { + // Windows UNC path: don't try to extract the scheme, but keep the slashes. + parsed.scheme.reset(); + afterScheme = begin; + } else +#endif + { + if (ExtractScheme(&spec[begin], specLength - begin, &parsed.scheme)) { + // Offset the results since we gave ExtractScheme a substring. + parsed.scheme.setBegin(parsed.scheme.begin() + begin); + afterScheme = parsed.scheme.end() + 1; + } else { + // No scheme found, remember that. + parsed.scheme.reset(); + afterScheme = begin; + } + } + + // Handle empty specs ones that contain only whitespace or control chars, + // or that are just the scheme (for example "file:"). + if (afterScheme == specLength) { + parsed.host.reset(); + parsed.path.reset(); + return; + } + + numSlashes = countConsecutiveSlashes(spec, afterScheme, specLength); + + afterSlashes = afterScheme + numSlashes; +#if OS(WINDOWS) + // Check whether the input is a drive again. We checked above for windows + // drive specs, but that's only at the very beginning to see if we have a + // scheme at all. This test will be duplicated in that case, but will + // additionally handle all cases with a real scheme such as "file:///C:/". + if (!doesBeginWindowsDriveSpec(spec, afterSlashes, specLength) && numSlashes != 3) { + // Anything not beginning with a drive spec ("c:\") on Windows is treated + // as UNC, with the exception of three slashes which always means a file. + // Even IE7 treats file:///foo/bar as "/foo/bar", which then fails. + doParseUNC(spec, afterSlashes, specLength, parsed); + return; + } +#else + // file: URL with exactly 2 slashes is considered to have a host component. + if (numSlashes == 2) { + doParseUNC(spec, afterSlashes, specLength, parsed); + return; + } +#endif // OS(WINDOWS) + + // Easy and common case, the full path immediately follows the scheme + // (modulo slashes), as in "file://c:/foo". Just treat everything from + // there to the end as the path. Empty hosts have 0 length instead of -1. + // We include the last slash as part of the path if there is one. + doParseLocalFile(spec, + numSlashes > 0 ? afterScheme + numSlashes - 1 : afterScheme, + specLength, parsed); +} + +} // namespace + +void ParseFileURL(const char* url, int urlLength, URLSegments* parsed) +{ + doParseFileURL(url, urlLength, *parsed); +} + +void ParseFileURL(const UChar* url, int urlLength, URLSegments* parsed) +{ + doParseFileURL(url, urlLength, *parsed); +} + +} // namespace URLParser + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLParseInternal.h b/Source/WTF/wtf/url/src/URLParseInternal.h new file mode 100644 index 000000000..de27aedd0 --- /dev/null +++ b/Source/WTF/wtf/url/src/URLParseInternal.h @@ -0,0 +1,119 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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. + */ + +// Contains common inline helper functions used by the URL parsing routines. + +#ifndef URLParseInternal_h +#define URLParseInternal_h + +#include "URLParse.h" +#include <wtf/unicode/Unicode.h> + +#if USE(WTFURL) + +namespace WTF { + +namespace URLParser { + +// We treat slashes and backslashes the same for IE compatability. +inline bool isURLSlash(UChar ch) +{ + return ch == '/' || ch == '\\'; +} + +// Returns true if we should trim this character from the URL because it is a +// space or a control character. +inline bool shouldTrimFromURL(UChar ch) +{ + return ch <= ' '; +} + +// Given an already-initialized begin index and length, this shrinks the range +// to eliminate "should-be-trimmed" characters. Note that the length does *not* +// indicate the length of untrimmed data from |*begin|, but rather the position +// in the input string (so the string starts at character |*begin| in the spec, +// and goes until |*len|). +template<typename CharacterType> +inline void trimURL(const CharacterType* spec, int& begin, int& length) +{ + // Strip leading whitespace and control characters. + while (begin < length && shouldTrimFromURL(spec[begin])) + ++begin; + + // Strip trailing whitespace and control characters. We need the >i test for + // when the input string is all blanks; we don't want to back past the input. + while (length > begin && shouldTrimFromURL(spec[length - 1])) + --length; +} + +// Counts the number of consecutive slashes starting at the given offset +// in the given string of the given length. +template<typename CharacterType> +inline int countConsecutiveSlashes(const CharacterType *str, int begin_offset, int strLength) +{ + int count = 0; + while (begin_offset + count < strLength && isURLSlash(str[begin_offset + count])) + ++count; + return count; +} + +// Internal functions in URLParser.cc that parse the path, that is, everything +// following the authority section. The input is the range of everything +// following the authority section, and the output is the identified ranges. +// +// This is designed for the file URL parser or other consumers who may do +// special stuff at the beginning, but want regular path parsing, it just +// maps to the internal parsing function for paths. +void parsePathInternal(const char* spec, + const URLComponent& path, + URLComponent* filepath, + URLComponent* query, + URLComponent* fragment); +void parsePathInternal(const UChar* spec, + const URLComponent& path, + URLComponent* filepath, + URLComponent* query, + URLComponent* fragment); + + +// Given a spec and a pointer to the character after the colon following the +// scheme, this parses it and fills in the structure, Every item in the parsed +// structure is filled EXCEPT for the scheme, which is untouched. +void parseAfterScheme(const char* spec, int specLength, int afterScheme, URLSegments& parsed); +void parseAfterScheme(const UChar* spec, int specLength, int afterScheme, URLSegments& parsed); + +} // namespace URLParser + +} // namespace WTF + +#endif // USE(WTFURL) + +#endif // URLParseInternal_h diff --git a/Source/WTF/wtf/url/src/URLParser.h b/Source/WTF/wtf/url/src/URLParser.h deleted file mode 100644 index 2b4d598a3..000000000 --- a/Source/WTF/wtf/url/src/URLParser.h +++ /dev/null @@ -1,596 +0,0 @@ -/* Based on nsURLParsers.cc from Mozilla - * ------------------------------------- - * Copyright (C) 1998 Netscape Communications Corporation. - * Copyright (C) 2012 Apple Inc. All rights reserved. - * - * 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. - */ - -#ifndef URLParser_h -#define URLParser_h - -#include "URLComponent.h" -#include "URLSegments.h" -#include "UnusedParam.h" - -#if USE(WTFURL) - -namespace WTF { - -template<typename CharacterType, typename BaseCharacterType = CharacterType> -class URLParser { -public: - enum SpecialPort { - UnspecifiedPort = -1, - InvalidPort = -2, - }; - - // This handles everything that may be an authority terminator, including - // backslash. For special backslash handling see parseAfterScheme. - static bool isPossibleAuthorityTerminator(CharacterType ch) - { - return isURLSlash(ch) || ch == '?' || ch == '#' || ch == ';'; - } - - // Given an already-identified auth section, breaks it into its constituent - // parts. The port number will be parsed and the resulting integer will be - // filled into the given *port variable, or -1 if there is no port number - // or it is invalid. - static void parseAuthority(const CharacterType* spec, const URLComponent& auth, URLComponent& username, URLComponent& password, URLComponent& host, URLComponent& port) - { - // FIXME: add ASSERT(auth.isValid()); // We should always get an authority. - if (!auth.length()) { - username.reset(); - password.reset(); - host.reset(); - port.reset(); - return; - } - - // Search backwards for @, which is the separator between the user info - // and the server info. RFC 3986 forbids @ from occuring in auth, but - // someone might include it in a password unescaped. - int i = auth.begin() + auth.length() - 1; - while (i > auth.begin() && spec[i] != '@') - --i; - - if (spec[i] == '@') { - // Found user info: <user-info>@<server-info> - parseUserInfo(spec, URLComponent(auth.begin(), i - auth.begin()), username, password); - parseServerInfo(spec, URLComponent::fromRange(i + 1, auth.begin() + auth.length()), host, port); - } else { - // No user info, everything is server info. - username.reset(); - password.reset(); - parseServerInfo(spec, auth, host, port); - } - } - - static bool extractScheme(const CharacterType* spec, int specLength, URLComponent& scheme) - { - // Skip leading whitespace and control characters. - int begin = 0; - while (begin < specLength && shouldTrimFromURL(spec[begin])) - begin++; - if (begin == specLength) - return false; // Input is empty or all whitespace. - - // Find the first colon character. - for (int i = begin; i < specLength; i++) { - if (spec[i] == ':') { - scheme = URLComponent::fromRange(begin, i); - return true; - } - } - return false; // No colon found: no scheme - } - - // Fills in all members of the URLSegments structure (except for the - // scheme) for standard URLs. - // - // |spec| is the full spec being parsed, of length |specLength|. - // |afterScheme| is the character immediately following the scheme (after - // the colon) where we'll begin parsing. - static void parseAfterScheme(const CharacterType* spec, int specLength, int afterScheme, URLSegments& parsed) - { - int numberOfSlashes = consecutiveSlashes(spec, afterScheme, specLength); - int afterSlashes = afterScheme + numberOfSlashes; - - // First split into two main parts, the authority (username, password, - // host, and port) and the full path (path, query, and reference). - URLComponent authority; - URLComponent fullPath; - - // Found "//<some data>", looks like an authority section. Treat - // everything from there to the next slash (or end of spec) to be the - // authority. Note that we ignore the number of slashes and treat it as - // the authority. - int authEnd = nextAuthorityTerminator(spec, afterSlashes, specLength); - authority = URLComponent(afterSlashes, authEnd - afterSlashes); - - if (authEnd == specLength) // No beginning of path found. - fullPath = URLComponent(); - else // Everything starting from the slash to the end is the path. - fullPath = URLComponent(authEnd, specLength - authEnd); - - // Now parse those two sub-parts. - parseAuthority(spec, authority, parsed.username, parsed.password, parsed.host, parsed.port); - parsePath(spec, fullPath, parsed.path, parsed.query, parsed.fragment); - } - - // The main parsing function for standard URLs. Standard URLs have a scheme, - // host, path, etc. - static void parseStandardURL(const CharacterType* spec, int specLength, URLSegments& parsed) - { - // FIXME: add ASSERT(specLength >= 0); - - // Strip leading & trailing spaces and control characters. - int begin = 0; - trimURL(spec, begin, specLength); - - int afterScheme; - if (extractScheme(spec, specLength, parsed.scheme)) - afterScheme = parsed.scheme.end() + 1; // Skip past the colon. - else { - // Say there's no scheme when there is a colon. We could also say - // that everything is the scheme. Both would produce an invalid - // URL, but this way seems less wrong in more cases. - parsed.scheme.reset(); - afterScheme = begin; - } - parseAfterScheme(spec, specLength, afterScheme, parsed); - } - - // The main parsing function for (may be) relative URLs. - static void parseURLWithBase(const CharacterType* spec, int specLength, - const BaseCharacterType* baseStringSpec, int baseStringSpecLength, const URLSegments& baseStringSegments, - URLBuffer<char>&outputBuffer, URLSegments& parsed) - { - UNUSED_PARAM(baseStringSpec); - UNUSED_PARAM(baseStringSpecLength); - UNUSED_PARAM(baseStringSegments); - UNUSED_PARAM(spec); - UNUSED_PARAM(specLength); - UNUSED_PARAM(outputBuffer); - UNUSED_PARAM(parsed); - // FIXME: To implement. - } - - static void parsePath(const CharacterType* spec, const URLComponent& path, URLComponent& filepath, URLComponent& query, URLComponent& fragment) - { - // path = [/]<segment1>/<segment2>/<...>/<segmentN>;<param>?<query>#<fragment> - - // Special case when there is no path. - if (!path.isValid()) { - filepath.reset(); - query.reset(); - fragment.reset(); - return; - } - // FIXME: add ASSERT(path.length() > 0); // We should never have 0 length paths. - - // Search for first occurrence of either ? or #. - int pathEnd = path.begin() + path.length(); - - int querySeparator = -1; // Index of the '?' - int refSeparator = -1; // Index of the '#' - for (int i = path.begin(); i < pathEnd; i++) { - switch (spec[i]) { - case '?': - if (querySeparator < 0) - querySeparator = i; - break; - case '#': - refSeparator = i; - i = pathEnd; // Break out of the loop. - break; - default: - break; - } - } - - // Markers pointing to the character after each of these corresponding - // components. The code below works from the end back to the beginning, - // and will update these indices as it finds components that exist. - int fileEnd, queryEnd; - - // Fragment: from the # to the end of the path. - if (refSeparator >= 0) { - fileEnd = refSeparator; - queryEnd = refSeparator; - fragment = URLComponent::fromRange(refSeparator + 1, pathEnd); - } else { - fileEnd = pathEnd; - queryEnd = pathEnd; - fragment.reset(); - } - - // Query fragment: everything from the ? to the next boundary (either - // the end of the path or the fragment fragment). - if (querySeparator >= 0) { - fileEnd = querySeparator; - query = URLComponent::fromRange(querySeparator + 1, queryEnd); - } else - query.reset(); - - // File path: treat an empty file path as no file path. - if (fileEnd != path.begin()) - filepath = URLComponent::fromRange(path.begin(), fileEnd); - else - filepath.reset(); - } - - // Initializes a path URL which is merely a scheme followed by a path. - // Examples include "about:foo" and "javascript:alert('bar');" - static void parsePathURL(const CharacterType* spec, int specLength, URLSegments& parsed) - { - // Get the non-path and non-scheme parts of the URL out of the way, we - // never use them. - parsed.username.reset(); - parsed.password.reset(); - parsed.host.reset(); - parsed.port.reset(); - parsed.query.reset(); - parsed.fragment.reset(); - - // Strip leading & trailing spaces and control characters. - // FIXME: Perhaps this is unnecessary? - int begin = 0; - trimURL(spec, begin, specLength); - - // Handle empty specs or ones that contain only whitespace or control - // chars. - if (begin == specLength) { - parsed.scheme.reset(); - parsed.path.reset(); - return; - } - - // Extract the scheme, with the path being everything following. We also - // handle the case where there is no scheme. - if (extractScheme(&spec[begin], specLength - begin, parsed.scheme)) { - // Offset the results since we gave extractScheme a substring. - parsed.scheme.setBegin(parsed.scheme.begin() + begin); - - // For compatibility with the standard URL parser, we treat no path - // as -1, rather than having a length of 0 (we normally wouldn't - // care so much for these non-standard URLs). - if (parsed.scheme.end() == specLength - 1) - parsed.path.reset(); - else - parsed.path = URLComponent::fromRange(parsed.scheme.end() + 1, specLength); - } else { - // No scheme found, just path. - parsed.scheme.reset(); - parsed.path = URLComponent::fromRange(begin, specLength); - } - } - - static void parseMailtoURL(const CharacterType* spec, int specLength, URLSegments& parsed) - { - // FIXME: add ASSERT(specLength >= 0); - - // Get the non-path and non-scheme parts of the URL out of the way, we - // never use them. - parsed.username.reset(); - parsed.password.reset(); - parsed.host.reset(); - parsed.port.reset(); - parsed.fragment.reset(); - parsed.query.reset(); // May use this; reset for convenience. - - // Strip leading & trailing spaces and control characters. - int begin = 0; - trimURL(spec, begin, specLength); - - // Handle empty specs or ones that contain only whitespace or control - // chars. - if (begin == specLength) { - parsed.scheme.reset(); - parsed.path.reset(); - return; - } - - int pathBegin = -1; - int pathEnd = -1; - - // Extract the scheme, with the path being everything following. We also - // handle the case where there is no scheme. - if (extractScheme(&spec[begin], specLength - begin, parsed.scheme)) { - // Offset the results since we gave extractScheme a substring. - parsed.scheme.setBegin(parsed.scheme.begin() + begin); - - if (parsed.scheme.end() != specLength - 1) { - pathBegin = parsed.scheme.end() + 1; - pathEnd = specLength; - } - } else { - // No scheme found, just path. - parsed.scheme.reset(); - pathBegin = begin; - pathEnd = specLength; - } - - // Split [pathBegin, pathEnd) into a path + query. - for (int i = pathBegin; i < pathEnd; ++i) { - if (spec[i] == '?') { - parsed.query = URLComponent::fromRange(i + 1, pathEnd); - pathEnd = i; - break; - } - } - - // For compatibility with the standard URL parser, treat no path as - // -1, rather than having a length of 0 - if (pathBegin == pathEnd) - parsed.path.reset(); - else - parsed.path = URLComponent::fromRange(pathBegin, pathEnd); - } - - static int parsePort(const CharacterType* spec, const URLComponent& component) - { - // Easy success case when there is no port. - const int maxDigits = 5; - if (component.isEmptyOrInvalid()) - return UnspecifiedPort; - - URLComponent nonZeroDigits(component.end(), 0); - for (int i = 0; i < component.length(); ++i) { - if (spec[component.begin() + i] != '0') { - nonZeroDigits = URLComponent::fromRange(component.begin() + i, component.end()); - break; - } - } - if (!nonZeroDigits.length()) - return 0; // All digits were 0. - - if (nonZeroDigits.length() > maxDigits) - return InvalidPort; - - int port = 0; - for (int i = 0; i < nonZeroDigits.length(); ++i) { - CharacterType ch = spec[nonZeroDigits.begin() + i]; - if (!isPortDigit(ch)) - return InvalidPort; - port *= 10; - port += static_cast<char>(ch) - '0'; - } - if (port > 65535) - return InvalidPort; - return port; - } - - static void extractFileName(const CharacterType* spec, const URLComponent& path, URLComponent& fileName) - { - // Handle empty paths: they have no file names. - if (path.isEmptyOrInvalid()) { - fileName.reset(); - return; - } - - // Search backwards for a parameter, which is a normally unused field - // in a URL delimited by a semicolon. We parse the parameter as part of - // the path, but here, we don't want to count it. The last semicolon is - // the parameter. - int fileEnd = path.end(); - for (int i = path.end() - 1; i > path.begin(); --i) { - if (spec[i] == ';') { - fileEnd = i; - break; - } - } - - // Now search backwards from the filename end to the previous slash - // to find the beginning of the filename. - for (int i = fileEnd - 1; i >= path.begin(); --i) { - if (isURLSlash(spec[i])) { - // File name is everything following this character to the end - fileName = URLComponent::fromRange(i + 1, fileEnd); - return; - } - } - - // No slash found, this means the input was degenerate (generally paths - // will start with a slash). Let's call everything the file name. - fileName = URLComponent::fromRange(path.begin(), fileEnd); - } - - static bool extractQueryKeyValue(const CharacterType* spec, URLComponent& query, URLComponent& key, URLComponent& value) - { - if (query.isEmptyOrInvalid()) - return false; - - int start = query.begin(); - int current = start; - int end = query.end(); - - // We assume the beginning of the input is the beginning of the "key" - // and we skip to the end of it. - key.setBegin(current); - while (current < end && spec[current] != '&' && spec[current] != '=') - ++current; - key.setLength(current - key.begin()); - - // Skip the separator after the key (if any). - if (current < end && spec[current] == '=') - ++current; - - // Find the value part. - value.setBegin(current); - while (current < end && spec[current] != '&') - ++current; - value.setLength(current - value.begin()); - - // Finally skip the next separator if any - if (current < end && spec[current] == '&') - ++current; - - // Save the new query - query = URLComponent::fromRange(current, end); - return true; - } - -// FIXME: This should be protected or private. -public: - // We treat slashes and backslashes the same for IE compatibility. - static inline bool isURLSlash(CharacterType ch) - { - return ch == '/' || ch == '\\'; - } - - // Returns true if we should trim this character from the URL because it is - // a space or a control character. - static inline bool shouldTrimFromURL(CharacterType ch) - { - return ch <= ' '; - } - - // Given an already-initialized begin index and end index (the index after - // the last CharacterType in spec), this shrinks the range to eliminate - // "should-be-trimmed" characters. - static inline void trimURL(const CharacterType* spec, int& begin, int& end) - { - // Strip leading whitespace and control characters. - while (begin < end && shouldTrimFromURL(spec[begin])) - ++begin; - - // Strip trailing whitespace and control characters. We need the >i - // test for when the input string is all blanks; we don't want to back - // past the input. - while (end > begin && shouldTrimFromURL(spec[end - 1])) - --end; - } - - // Counts the number of consecutive slashes starting at the given offset - // in the given string of the given length. - static inline int consecutiveSlashes(const CharacterType *string, int beginOffset, int stringLength) - { - int count = 0; - while (beginOffset + count < stringLength && isURLSlash(string[beginOffset + count])) - ++count; - return count; - } - -private: - // URLParser cannot be constructed. - URLParser(); - - // Returns true if the given character is a valid digit to use in a port. - static inline bool isPortDigit(CharacterType ch) - { - return ch >= '0' && ch <= '9'; - } - - // Returns the offset of the next authority terminator in the input starting - // from startOffset. If no terminator is found, the return value will be equal - // to specLength. - static int nextAuthorityTerminator(const CharacterType* spec, int startOffset, int specLength) - { - for (int i = startOffset; i < specLength; i++) { - if (isPossibleAuthorityTerminator(spec[i])) - return i; - } - return specLength; // Not found. - } - - static void parseUserInfo(const CharacterType* spec, const URLComponent& user, URLComponent& username, URLComponent& password) - { - // Find the first colon in the user section, which separates the - // username and password. - int colonOffset = 0; - while (colonOffset < user.length() && spec[user.begin() + colonOffset] != ':') - ++colonOffset; - - if (colonOffset < user.length()) { - // Found separator: <username>:<password> - username = URLComponent(user.begin(), colonOffset); - password = URLComponent::fromRange(user.begin() + colonOffset + 1, user.begin() + user.length()); - } else { - // No separator, treat everything as the username - username = user; - password = URLComponent(); - } - } - - static void parseServerInfo(const CharacterType* spec, const URLComponent& serverInfo, URLComponent& host, URLComponent& port) - { - if (!serverInfo.length()) { - // No server info, host name is empty. - host.reset(); - port.reset(); - return; - } - - // If the host starts with a left-bracket, assume the entire host is an - // IPv6 literal. Otherwise, assume none of the host is an IPv6 literal. - // This assumption will be overridden if we find a right-bracket. - // - // Our IPv6 address canonicalization code requires both brackets to - // exist, but the ability to locate an incomplete address can still be - // useful. - int ipv6Terminator = spec[serverInfo.begin()] == '[' ? serverInfo.end() : -1; - int colon = -1; - - // Find the last right-bracket, and the last colon. - for (int i = serverInfo.begin(); i < serverInfo.end(); i++) { - switch (spec[i]) { - case ']': - ipv6Terminator = i; - break; - case ':': - colon = i; - break; - default: - break; - } - } - - if (colon > ipv6Terminator) { - // Found a port number: <hostname>:<port> - host = URLComponent::fromRange(serverInfo.begin(), colon); - if (!host.length()) - host.reset(); - port = URLComponent::fromRange(colon + 1, serverInfo.end()); - } else { - // No port: <hostname> - host = serverInfo; - port.reset(); - } - } -}; - -} // namespace WTF - -#endif // USE(WTFURL) - -#endif // URLParser_h diff --git a/Source/WTF/wtf/url/src/URLQueryCanonicalizer.h b/Source/WTF/wtf/url/src/URLQueryCanonicalizer.h deleted file mode 100644 index 467c497fd..000000000 --- a/Source/WTF/wtf/url/src/URLQueryCanonicalizer.h +++ /dev/null @@ -1,109 +0,0 @@ -// 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 URLQueryCanonicalizer_h -#define URLQueryCanonicalizer_h - -#if USE(WTFURL) - -#include "RawURLBuffer.h" -#include "URLBuffer.h" -#include "URLCharacterTypes.h" -#include "URLComponent.h" -#include "URLEscape.h" - -namespace WTF { - -template<typename InChar, typename OutChar, void convertCharset(const InChar*, int length, URLBuffer<char>&)> -class URLQueryCanonicalizer { -public: - static void canonicalize(const InChar* spec, const URLComponent& query, URLBuffer<OutChar>& buffer, URLComponent& resultQuery) - { - if (query.length() < 0) { - resultQuery = URLComponent(); - return; - } - - buffer->append('?'); - resultQuery.setBegin(buffer->length()); - convertToQueryEncoding(spec, query, buffer); - resultQuery.setLength(buffer->length() - resultQuery.begin()); - } - -private: - static bool isAllASCII(const InChar* spec, const URLComponent& query) - { - int end = query.end(); - for (int i = query.begin(); i < end; ++i) { - if (static_cast<unsigned>(spec[i]) >= 0x80) - return false; - } - return true; - } - -#ifndef NDEBUG - static bool isRaw8Bit(const InChar* source, int length) - { - for (int i = source; i < length; ++i) { - if (source[i] & 0xFF != source[i]) - return false; - } - return true; - } -#endif - - static void appendRaw8BitQueryString(const InChar* source, int length, URLBuffer<OutChar>* buffer) - { - ASSERT(isRaw8Bit(source, length)); - for (int i = 0; i < length; ++i) { - if (!URLCharacterTypes::isQueryChar(source[i])) - appendURLEscapedCharacter(static_cast<unsigned char>(source[i]), buffer); - else - buffer->append(static_cast<char>(source[i])); - } - } - - static void convertToQueryEncoding(const InChar* spec, const URLComponent& query, URLBuffer<OutChar>& buffer) - { - if (isAllASCII(spec, query)) { - appendRaw8BitQueryString(&spec[query.begin()], query.length(), buffer); - return; - } - - RawURLBuffer<char, 1024> convertedQuery; - convertCharset(spec, query, convertedQuery); - appendRaw8BitQueryString(convertedQuery.data(), convertedQuery.length(), buffer); - } -}; - -} - -#endif // USE(WTFURL) - -#endif diff --git a/Source/WTF/wtf/url/src/URLSegments.cpp b/Source/WTF/wtf/url/src/URLSegments.cpp index 158e5d9d4..8d973cc2a 100644 --- a/Source/WTF/wtf/url/src/URLSegments.cpp +++ b/Source/WTF/wtf/url/src/URLSegments.cpp @@ -13,7 +13,7 @@ * * 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 + * 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 @@ -25,7 +25,7 @@ * 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 + * 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 diff --git a/Source/WTF/wtf/url/src/URLSegments.h b/Source/WTF/wtf/url/src/URLSegments.h index 9f17228d6..9e5ae6bd0 100644 --- a/Source/WTF/wtf/url/src/URLSegments.h +++ b/Source/WTF/wtf/url/src/URLSegments.h @@ -1,41 +1,47 @@ -// Copyright 2007, Google Inc. All rights reserved. -// Copyright 2012 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. +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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. + */ #ifndef URLSegments_h #define URLSegments_h #include "URLComponent.h" +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> #if USE(WTFURL) namespace WTF { +class URLSegments; + // 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. @@ -59,6 +65,26 @@ public: URLSegments() { } + URLSegments(const URLSegments& otherSegment) + { + *this = otherSegment; + } + + URLSegments& operator=(const URLSegments& otherSegment) + { + scheme = otherSegment.scheme; + username = otherSegment.username; + password = otherSegment.password; + host = otherSegment.host; + port = otherSegment.port; + path = otherSegment.path; + query = otherSegment.query; + fragment = otherSegment.fragment; + if (otherSegment.m_innerURLSegments) + m_innerURLSegments = adoptPtr(new URLSegments(*otherSegment.m_innerURLSegments)); + return *this; + } + // 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 @@ -105,6 +131,16 @@ public: URLComponent path; URLComponent query; URLComponent fragment; + + // FIXME: this is a damn ugly API and is basically untested. + const URLSegments* innerURLSegments() const { return m_innerURLSegments.get(); } + void setInnerURLSegments(const URLSegments& urlSegments) { m_innerURLSegments = adoptPtr(new URLSegments(urlSegments)); } + void clearInnerURLSegments() { return m_innerURLSegments.clear(); } + +private: + // The Filesystem API describe a URL format with an internal URL. E.g.: filesystem:http://www.apple.com/ + // The inner URL segment contains the parsed inner URL of a filesystem: URL. + OwnPtr<URLSegments> m_innerURLSegments; }; } // namespace WTF diff --git a/Source/WTF/wtf/url/src/URLUtil.cpp b/Source/WTF/wtf/url/src/URLUtil.cpp new file mode 100644 index 000000000..d0535138d --- /dev/null +++ b/Source/WTF/wtf/url/src/URLUtil.cpp @@ -0,0 +1,494 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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" +#include "URLUtil.h" + +#include "RawURLBuffer.h" +#include "URLCanonInternal.h" +#include "URLFile.h" +#include "URLUtilInternal.h" +#include <wtf/ASCIICType.h> + +#if USE(WTFURL) + +namespace WTF { + +namespace URLUtilities { + +const char kFileScheme[] = "file"; +const char kFileSystemScheme[] = "filesystem"; +const char kMailtoScheme[] = "mailto"; + +namespace { + +// Backend for LowerCaseEqualsASCII. +template<typename Iter> +inline bool doLowerCaseEqualsASCII(Iter aBegin, Iter aEnd, const char* b) +{ + for (Iter it = aBegin; it != aEnd; ++it, ++b) { + if (!*b || toASCIILower(*it) != *b) + return false; + } + return !(*b); +} + +const int kNumStandardURLSchemes = 8; +const char* kStandardURLSchemes[kNumStandardURLSchemes] = { + "http", + "https", + kFileScheme, // Yes, file urls can have a hostname! + "ftp", + "gopher", + "ws", // WebSocket. + "wss", // WebSocket secure. + kFileSystemScheme +}; + +// Given a string and a range inside the string, compares it to the given +// lower-case |compareTo| buffer. +template<typename CharacterType> +inline bool doCompareSchemeComponent(const CharacterType* spec, const URLComponent& component, const char* compareTo) +{ + if (!component.isNonEmpty()) + return !compareTo[0]; // When component is empty, match empty scheme. + return LowerCaseEqualsASCII(&spec[component.begin()], &spec[component.end()], compareTo); +} + +// Returns true if the given scheme identified by |scheme| within |spec| is one +// of the registered "standard" schemes. +template<typename CharacterType> +bool doIsStandard(const CharacterType* spec, const URLComponent& scheme) +{ + if (!scheme.isNonEmpty()) + return false; // Empty or invalid schemes are non-standard. + + for (size_t i = 0; i < kNumStandardURLSchemes; ++i) { + if (LowerCaseEqualsASCII(&spec[scheme.begin()], &spec[scheme.end()], kStandardURLSchemes[i])) + return true; + } + return false; +} + +template<typename CharacterType> +bool doFindAndCompareScheme(const CharacterType* str, int strLength, const char* compare, URLComponent* foundScheme) +{ + // Before extracting scheme, canonicalize the URL to remove any whitespace. + // This matches the canonicalization done in doCanonicalize function. + RawURLBuffer<CharacterType> whitespaceBuffer; + int specLength; + const CharacterType* spec = URLCanonicalizer::removeURLWhitespace(str, strLength, whitespaceBuffer, specLength); + + URLComponent ourScheme; + if (!URLParser::ExtractScheme(spec, specLength, &ourScheme)) { + // No scheme. + if (foundScheme) + *foundScheme = URLComponent(); + return false; + } + if (foundScheme) + *foundScheme = ourScheme; + return doCompareSchemeComponent(spec, ourScheme, compare); +} + +template<typename CharacterType> +bool doCanonicalize(const CharacterType* inSpec, int inSpecLength, + URLQueryCharsetConverter* charsetConverter, + URLBuffer<char>& output, URLSegments& ouputParsed) +{ + // Remove any whitespace from the middle of the relative URL, possibly + // copying to the new buffer. + RawURLBuffer<CharacterType> whitespaceBuffer; + int specLength; + const CharacterType* spec = URLCanonicalizer::removeURLWhitespace(inSpec, inSpecLength, whitespaceBuffer, specLength); + + URLSegments parsedInput; +#if OS(WINDOWS) + // For Windows, we allow things that look like absolute Windows paths to be + // fixed up magically to file URLs. This is done for IE compatability. For + // example, this will change "c:/foo" into a file URL rather than treating + // it as a URL with the protocol "c". It also works for UNC ("\\foo\bar.txt"). + // There is similar logic in URLCanonicalizer_relative.cc for + // + // For Max & Unix, we don't do this (the equivalent would be "/foo/bar" which + // has no meaning as an absolute path name. This is because browsers on Mac + // & Unix don't generally do this, so there is no compatibility reason for + // doing so. + if (URLParser::doesBeginUNCPath(spec, 0, specLength, false) + || URLParser::doesBeginWindowsDriveSpec(spec, 0, specLength)) { + URLParser::ParseFileURL(spec, specLength, &parsedInput); + return URLCanonicalizer::CanonicalizeFileURL(spec, specLength, parsedInput, + charsetConverter, + output, *ouputParsed); + } +#endif + + URLComponent scheme; + if (!URLParser::ExtractScheme(spec, specLength, &scheme)) + return false; + + // This is the parsed version of the input URL, we have to canonicalize it + // before storing it in our object. + bool success; + if (doCompareSchemeComponent(spec, scheme, kFileScheme)) { + // File URLs are special. + URLParser::ParseFileURL(spec, specLength, &parsedInput); + success = URLCanonicalizer::CanonicalizeFileURL(spec, specLength, parsedInput, + charsetConverter, output, + &ouputParsed); + } else if (doCompareSchemeComponent(spec, scheme, kFileSystemScheme)) { + // Filesystem URLs are special. + URLParser::ParseFileSystemURL(spec, specLength, &parsedInput); + success = URLCanonicalizer::canonicalizeFileSystemURL(spec, parsedInput, + charsetConverter, + output, ouputParsed); + + } else if (doIsStandard(spec, scheme)) { + // All "normal" URLs. + URLParser::ParseStandardURL(spec, specLength, &parsedInput); + success = URLCanonicalizer::CanonicalizeStandardURL(spec, specLength, parsedInput, + charsetConverter, + output, &ouputParsed); + + } else if (doCompareSchemeComponent(spec, scheme, kMailtoScheme)) { + // Mailto are treated like a standard url with only a scheme, path, query + URLParser::ParseMailtoURL(spec, specLength, &parsedInput); + success = URLCanonicalizer::canonicalizeMailtoURL(spec, parsedInput, output, ouputParsed); + + } else { + // "Weird" URLs like data: and javascript: + URLParser::ParsePathURL(spec, specLength, &parsedInput); + success = URLCanonicalizer::canonicalizePathURL(spec, parsedInput, output, ouputParsed); + } + return success; +} + +template<typename CharacterType> +bool doResolveRelative(const char* baseSpec, const URLSegments& baseParsed, + const CharacterType* inRelative, int inRelativeLength, + URLQueryCharsetConverter* charsetConverter, + URLBuffer<char>& output, URLSegments* ouputParsed) +{ + // Remove any whitespace from the middle of the relative URL, possibly + // copying to the new buffer. + RawURLBuffer<CharacterType> whitespaceBuffer; + int relativeLength; + const CharacterType* relative = URLCanonicalizer::removeURLWhitespace(inRelative, inRelativeLength, whitespaceBuffer, relativeLength); + + // See if our base URL should be treated as "standard". + bool standardBaseScheme = baseParsed.scheme.isNonEmpty() && doIsStandard(baseSpec, baseParsed.scheme); + + bool isRelative; + URLComponent relativeComponent; + if (!URLCanonicalizer::isRelativeURL(baseSpec, baseParsed, + relative, relativeLength, + standardBaseScheme, + isRelative, relativeComponent)) + return false; // Error resolving. + + if (isRelative) { + // Relative, resolve and canonicalize. + bool fileBaseScheme = baseParsed.scheme.isNonEmpty() && doCompareSchemeComponent(baseSpec, baseParsed.scheme, kFileScheme); + return URLCanonicalizer::resolveRelativeURL(baseSpec, baseParsed, + fileBaseScheme, relative, + relativeComponent, charsetConverter, + output, ouputParsed); + } + + // Not relative, canonicalize the input. + return doCanonicalize(relative, relativeLength, charsetConverter, output, *ouputParsed); +} + +template<typename CharacterType> +bool doReplaceComponents(const char* spec, + int specLength, + const URLSegments& parsed, + const URLCanonicalizer::Replacements<CharacterType>& replacements, + URLQueryCharsetConverter* charsetConverter, + URLBuffer<char>& output, + URLSegments& outputParsed) +{ + // If the scheme is overridden, just do a simple string substitution and + // reparse the whole thing. There are lots of edge cases that we really don't + // want to deal with. Like what happens if I replace "http://e:8080/foo" + // with a file. Does it become "file:///E:/8080/foo" where the port number + // becomes part of the path? Parsing that string as a file URL says "yes" + // but almost no sane rule for dealing with the components individually would + // come up with that. + // + // Why allow these crazy cases at all? Programatically, there is almost no + // case for replacing the scheme. The most common case for hitting this is + // in JS when building up a URL using the location object. In this case, the + // JS code expects the string substitution behavior: + // http://www.w3.org/TR/2008/WD-html5-20080610/structured.html#common3 + if (replacements.IsSchemeOverridden()) { + // Canonicalize the new scheme so it is 8-bit and can be concatenated with + // the existing spec. + RawURLBuffer<char, 128> scheme_replaced; + URLComponent schemeReplacedParsed; + URLCanonicalizer::canonicalizeScheme(replacements.sources().scheme, + replacements.components().scheme, + scheme_replaced, schemeReplacedParsed); + + // We can assume that the input is canonicalized, which means it always has + // a colon after the scheme (or where the scheme would be). + int specAfterColon = parsed.scheme.isValid() ? parsed.scheme.end() + 1 + : 1; + if (specLength - specAfterColon > 0) { + scheme_replaced.append(&spec[specAfterColon], + specLength - specAfterColon); + } + + // We now need to completely re-parse the resulting string since its meaning + // may have changed with the different scheme. + RawURLBuffer<char, 128> recanonicalized; + URLSegments recanonicalizedParsed; + doCanonicalize(scheme_replaced.data(), scheme_replaced.length(), + charsetConverter, + recanonicalized, recanonicalizedParsed); + + // Recurse using the version with the scheme already replaced. This will now + // use the replacement rules for the new scheme. + // + // Warning: this code assumes that ReplaceComponents will re-check all + // components for validity. This is because we can't fail if DoCanonicalize + // failed above since theoretically the thing making it fail could be + // getting replaced here. If ReplaceComponents didn't re-check everything, + // we wouldn't know if something *not* getting replaced is a problem. + // If the scheme-specific replacers are made more intelligent so they don't + // re-check everything, we should instead recanonicalize the whole thing + // after this call to check validity (this assumes replacing the scheme is + // much much less common than other types of replacements, like clearing the + // ref). + URLCanonicalizer::Replacements<CharacterType> replacementsNoScheme = replacements; + replacementsNoScheme.SetScheme(0, URLComponent()); + return doReplaceComponents(recanonicalized.data(), recanonicalized.length(), + recanonicalizedParsed, replacementsNoScheme, + charsetConverter, output, outputParsed); + } + + // If we get here, then we know the scheme doesn't need to be replaced, so can + // just key off the scheme in the spec to know how to do the replacements. + if (doCompareSchemeComponent(spec, parsed.scheme, kFileScheme)) { + return URLCanonicalizer::ReplaceFileURL(spec, parsed, replacements, + charsetConverter, output, &outputParsed); + } + if (doCompareSchemeComponent(spec, parsed.scheme, kFileSystemScheme)) { + return URLCanonicalizer::ReplaceFileSystemURL(spec, parsed, replacements, + charsetConverter, output, + &outputParsed); + } + if (doIsStandard(spec, parsed.scheme)) { + return URLCanonicalizer::ReplaceStandardURL(spec, parsed, replacements, + charsetConverter, output, &outputParsed); + } + if (doCompareSchemeComponent(spec, parsed.scheme, kMailtoScheme)) + return URLCanonicalizer::replaceMailtoURL(spec, parsed, replacements, output, outputParsed); + + // Default is a path URL. + return URLCanonicalizer::ReplacePathURL(spec, parsed, replacements, output, &outputParsed); +} + +} // namespace + +bool isStandard(const char* spec, const URLComponent& scheme) +{ + return doIsStandard(spec, scheme); +} + +bool isStandard(const UChar* spec, const URLComponent& scheme) +{ + return doIsStandard(spec, scheme); +} + +bool FindAndCompareScheme(const char* str, int strLength, const char* compare, URLComponent* foundScheme) +{ + return doFindAndCompareScheme(str, strLength, compare, foundScheme); +} + +bool FindAndCompareScheme(const UChar* str, int strLength, const char* compare, URLComponent* foundScheme) +{ + return doFindAndCompareScheme(str, strLength, compare, foundScheme); +} + +bool canonicalize(const char* spec, int specLength, + URLQueryCharsetConverter* charsetConverter, + URLBuffer<char>& output, URLSegments& ouputParsed) +{ + return doCanonicalize(spec, specLength, charsetConverter, output, ouputParsed); +} + +bool canonicalize(const UChar* spec, int specLength, + URLQueryCharsetConverter* charsetConverter, + URLBuffer<char>& output, URLSegments& ouputParsed) +{ + return doCanonicalize(spec, specLength, charsetConverter, output, ouputParsed); +} + +bool resolveRelative(const char* baseSpec, const URLSegments& baseParsed, + const char* relative, int relativeLength, + URLQueryCharsetConverter* charsetConverter, + URLBuffer<char>& output, URLSegments* ouputParsed) +{ + return doResolveRelative(baseSpec, baseParsed, + relative, relativeLength, + charsetConverter, output, ouputParsed); +} + +bool resolveRelative(const char* baseSpec, const URLSegments& baseParsed, + const UChar* relative, int relativeLength, + URLQueryCharsetConverter* charsetConverter, + URLBuffer<char>& output, URLSegments* ouputParsed) +{ + return doResolveRelative(baseSpec, baseParsed, + relative, relativeLength, + charsetConverter, output, ouputParsed); +} + +bool ReplaceComponents(const char* spec, + int specLength, + const URLSegments& parsed, + const URLCanonicalizer::Replacements<char>& replacements, + URLQueryCharsetConverter* charsetConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + return doReplaceComponents(spec, specLength, parsed, replacements, + charsetConverter, output, *outputParsed); +} + +bool ReplaceComponents(const char* spec, + int specLength, + const URLSegments& parsed, + const URLCanonicalizer::Replacements<UChar>& replacements, + URLQueryCharsetConverter* charsetConverter, + URLBuffer<char>& output, + URLSegments* outputParsed) +{ + return doReplaceComponents(spec, specLength, parsed, replacements, + charsetConverter, output, *outputParsed); +} + +// Front-ends for LowerCaseEqualsASCII. +bool LowerCaseEqualsASCII(const char* aBegin, const char* aEnd, const char* b) +{ + return doLowerCaseEqualsASCII(aBegin, aEnd, b); +} + +bool LowerCaseEqualsASCII(const char* aBegin, const char* aEnd, const char* bBegin, const char* bEnd) +{ + while (aBegin != aEnd && bBegin != bEnd && toASCIILower(*aBegin) == *bBegin) { + aBegin++; + bBegin++; + } + return aBegin == aEnd && bBegin == bEnd; +} + +bool LowerCaseEqualsASCII(const UChar* aBegin, const UChar* aEnd, const char* b) +{ + return doLowerCaseEqualsASCII(aBegin, aEnd, b); +} + +void DecodeURLEscapeSequences(const char* input, int length, URLBuffer<UChar>& output) +{ + RawURLBuffer<char> unescapedChars; + for (int i = 0; i < length; ++i) { + if (input[i] == '%') { + unsigned char ch; + if (URLCanonicalizer::DecodeEscaped(input, &i, length, &ch)) + unescapedChars.append(ch); + else { + // Invalid escape sequence, copy the percent literal. + unescapedChars.append('%'); + } + } else { + // Regular non-escaped 8-bit character. + unescapedChars.append(input[i]); + } + } + + // Convert that 8-bit to UTF-16. It's not clear IE does this at all to + // JavaScript URLs, but Firefox and Safari do. + for (int i = 0; i < unescapedChars.length(); i++) { + unsigned char uch = static_cast<unsigned char>(unescapedChars.at(i)); + if (uch < 0x80) { + // Non-UTF-8, just append directly + output.append(uch); + } else { + // next_ch will point to the last character of the decoded + // character. + int nextCharacter = i; + unsigned codePoint; + if (URLCanonicalizer::readUTFChar(unescapedChars.data(), &nextCharacter, + unescapedChars.length(), &codePoint)) { + // Valid UTF-8 character, convert to UTF-16. + URLCanonicalizer::AppendUTF16Value(codePoint, output); + i = nextCharacter; + } else { + // If there are any sequences that are not valid UTF-8, we keep + // invalid code points and promote to UTF-16. We copy all characters + // from the current position to the end of the identified sequence. + while (i < nextCharacter) { + output.append(static_cast<unsigned char>(unescapedChars.at(i))); + i++; + } + output.append(static_cast<unsigned char>(unescapedChars.at(i))); + } + } + } +} + +void EncodeURIComponent(const char* input, int length, URLBuffer<char>& output) +{ + for (int i = 0; i < length; ++i) { + unsigned char c = static_cast<unsigned char>(input[i]); + if (URLCharacterTypes::isComponentChar(c)) + output.append(c); + else + URLCanonicalizer::appendURLEscapedCharacter(c, output); + } +} + +bool CompareSchemeComponent(const char* spec, const URLComponent& component, const char* compareTo) +{ + return doCompareSchemeComponent(spec, component, compareTo); +} + +bool CompareSchemeComponent(const UChar* spec, const URLComponent& component, const char* compareTo) +{ + return doCompareSchemeComponent(spec, component, compareTo); +} + +} // namespace URLUtilities + +} // namespace WTF + +#endif // USE(WTFURL) diff --git a/Source/WTF/wtf/url/src/URLUtil.h b/Source/WTF/wtf/url/src/URLUtil.h new file mode 100644 index 000000000..a73924177 --- /dev/null +++ b/Source/WTF/wtf/url/src/URLUtil.h @@ -0,0 +1,137 @@ +/* + * Copyright 2007 Google Inc. All rights reserved. + * Copyright 2012 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. + */ + +#ifndef URLUtil_h +#define URLUtil_h + +#include "URLBuffer.h" +#include "URLCanon.h" +#include "URLParse.h" +#include <wtf/unicode/Unicode.h> + +#if USE(WTFURL) + +namespace WTF { + +class URLQueryCharsetConverter; + +namespace URLUtilities { + +// Locates the scheme in the given string and places it into |foundScheme|, +// which may be 0 to indicate the caller does not care about the range. +// +// Returns whether the given |compare| scheme matches the scheme found in the +// input (if any). The |compare| scheme must be a valid canonical scheme or +// the result of the comparison is undefined. +bool FindAndCompareScheme(const char* str, int strLength, const char* compare, URLComponent* foundScheme); +bool FindAndCompareScheme(const UChar* str, int strLength, const char* compare, URLComponent* foundScheme); + +// Returns true if the given string represents a standard URL. This means that +// either the scheme is in the list of known standard schemes. +bool isStandard(const char* spec, const URLComponent& scheme); +bool isStandard(const UChar* spec, const URLComponent& scheme); + +// URL library wrappers ------------------------------------------------------- + +// Parses the given spec according to the extracted scheme type. Normal users +// should use the URL object, although this may be useful if performance is +// critical and you don't want to do the heap allocation for the std::string. +// +// As with the URLCanonicalizer::Canonicalize* functions, the charset converter can +// be 0 to use UTF-8 (it will be faster in this case). +// +// Returns true if a valid URL was produced, false if not. On failure, the +// output and parsed structures will still be filled and will be consistent, +// but they will not represent a loadable URL. +bool canonicalize(const char* spec, int specLength, URLQueryCharsetConverter*, + URLBuffer<char>&, URLSegments& ouputParsed); +bool canonicalize(const UChar* spec, int specLength, URLQueryCharsetConverter*, + URLBuffer<char>&, URLSegments& ouputParsed); + +// Resolves a potentially relative URL relative to the given parsed base URL. +// The base MUST be valid. The resulting canonical URL and parsed information +// will be placed in to the given out variables. +// +// The relative need not be relative. If we discover that it's absolute, this +// will produce a canonical version of that URL. See Canonicalize() for more +// about the charsetConverter. +// +// Returns true if the output is valid, false if the input could not produce +// a valid URL. +bool resolveRelative(const char* baseSpec, const URLSegments& baseParsed, + const char* relative, int relativeLength, + URLQueryCharsetConverter*, + URLBuffer<char>&, URLSegments* ouputParsed); +bool resolveRelative(const char* baseSpec, const URLSegments& baseParsed, + const UChar* relative, int relativeLength, + URLQueryCharsetConverter*, + URLBuffer<char>&, URLSegments* ouputParsed); + +// Replaces components in the given VALID input url. The new canonical URL info +// is written to output and outputParsed. +// +// Returns true if the resulting URL is valid. +bool ReplaceComponents(const char* spec, int specLength, const URLSegments& parsed, + const URLCanonicalizer::Replacements<char>&, + URLQueryCharsetConverter*, + URLBuffer<char>&, URLSegments* outputParsed); +bool ReplaceComponents(const char* spec, int specLength, const URLSegments& parsed, + const URLCanonicalizer::Replacements<UChar>&, + URLQueryCharsetConverter*, + URLBuffer<char>&, URLSegments* outputParsed); + +// String helper functions ---------------------------------------------------- + +// Compare the lower-case form of the given string against the given ASCII +// string. This is useful for doing checking if an input string matches some +// token, and it is optimized to avoid intermediate string copies. +// +// The versions of this function that don't take a bEnd assume that the b +// string is zero terminated. +bool LowerCaseEqualsASCII(const char* aBegin, const char* aEnd, const char* b); +bool LowerCaseEqualsASCII(const char* aBegin, const char* aEnd, const char* bBegin, const char* bEnd); +bool LowerCaseEqualsASCII(const UChar* aBegin, const UChar* aEnd, const char* b); + +// Unescapes the given string using URL escaping rules. +void DecodeURLEscapeSequences(const char* input, int length, URLBuffer<UChar>&); + +// Escapes the given string as defined by the JS method encodeURIComponent. +// See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/encodeURIComponent +void EncodeURIComponent(const char* input, int length, URLBuffer<char>&); + + +} // namespace URLUtilities + +} // namespace WTF + +#endif // USE(WTFURL) + +#endif // URLUtil_h diff --git a/Source/WTF/wtf/url/src/URLUtilInternal.h b/Source/WTF/wtf/url/src/URLUtilInternal.h new file mode 100644 index 000000000..0840aec86 --- /dev/null +++ b/Source/WTF/wtf/url/src/URLUtilInternal.h @@ -0,0 +1,58 @@ +/* + * Copyright 2011 Google Inc. All rights reserved. + * Copyright 2012 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. + */ + +#ifndef URLUtilInternal_h +#define URLUtilInternal_h + +#include "URLParse.h" + +#if USE(WTFURL) + +namespace WTF { + +namespace URLUtilities { + +extern const char kFileScheme[]; +extern const char kFileSystemScheme[]; +extern const char kMailtoScheme[]; + +// Given a string and a range inside the string, compares it to the given +// lower-case |compareTo| buffer. +bool CompareSchemeComponent(const char* spec, const URLComponent&, const char* compareTo); +bool CompareSchemeComponent(const UChar* spec, const URLComponent&, const char* compareTo); + +} // namespace URLUtilities + +} // namespace WTF + +#endif // USE(WTFURL) + +#endif // URLUtilInternal_h diff --git a/Source/WebCore/CMakeLists.txt b/Source/WebCore/CMakeLists.txt index 4b0250629..5d06bb550 100644 --- a/Source/WebCore/CMakeLists.txt +++ b/Source/WebCore/CMakeLists.txt @@ -1125,6 +1125,7 @@ SET(WebCore_SOURCES dom/DocumentFragment.cpp dom/DocumentParser.cpp dom/DocumentOrderedMap.cpp + dom/DocumentStyleSheetCollection.cpp dom/DocumentType.cpp dom/DynamicNodeList.cpp dom/EditingText.cpp diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog index c4321a62b..50675f666 100644 --- a/Source/WebCore/ChangeLog +++ b/Source/WebCore/ChangeLog @@ -1,3 +1,1627 @@ +2012-09-25 Vsevolod Vlasov <vsevik@chromium.org> + + Web Inspector: ResourceScriptMapping should no steal scripts from other mappings. + https://bugs.webkit.org/show_bug.cgi?id=97453 + + Reviewed by Pavel Feldman. + + Exposed sourceMapping getter on Script so that resource mapping could check it. + + * inspector/front-end/ResourceScriptMapping.js: + (WebInspector.ResourceScriptMapping): + (WebInspector.ResourceScriptMapping.prototype._scriptsForSourceURL): + (WebInspector.ResourceScriptMapping.prototype._reset): + +2012-09-25 Keishi Hattori <keishi@webkit.org> + + REGRESSION(r129448): multiple fields time input UI doesn't use system time format settings on Chromium-Mac + https://bugs.webkit.org/show_bug.cgi?id=97517 + + Reviewed by Kent Tamura. + + We need to locale [NSLocale currentLocale] if browser language/@lang equals [[NSLocal currentLocale] localeIdentifier]. Otherwise it won't use the custom time format that the user has set. + + No new tests. Unable to test because we need to change system locale settings. + + * platform/text/mac/LocaleMac.h: + (LocaleMac): + * platform/text/mac/LocaleMac.mm: + (WebCore::languageFromLocale): Moved to top. + (WebCore): + (WebCore::determineLocale): Modified so it takes a locale as an argument. + (WebCore::Localizer::create): + (WebCore::LocaleMac::LocaleMac): Added checks for invalid locales to this constructor and removed the other one so we don't have duplicated code. + (WebCore::LocaleMac::create): + (WebCore::LocaleMac::currentLocale): + +2012-09-20 Alexander Pavlov <apavlov@chromium.org> + + Web Inspector: Relative URL Link Tooltips do not respect <base> + https://bugs.webkit.org/show_bug.cgi?id=43434 + + Reviewed by Pavel Feldman. + + New "baseURL" field added into the DOM.Node payload for document nodes and is made use of while resolving and completing URLs. + + * inspector/Inspector.json: + * inspector/InspectorDOMAgent.cpp: + (WebCore::documentBaseURLString): + (WebCore): + (WebCore::InspectorDOMAgent::buildObjectForNode): + * inspector/front-end/AuditRules.js: + (WebInspector.AuditRules.ImageDimensionsRule.prototype.doRun): + (WebInspector.AuditRules.CssInHeadRule.prototype.doRun.externalStylesheetsReceived): + (WebInspector.AuditRules.StylesScriptsOrderRule.prototype.doRun.cssBeforeInlineReceived): + * inspector/front-end/DOMAgent.js: + (WebInspector.DOMNode.prototype.resolveURL): + (WebInspector.DOMDocument): + +2012-09-25 Peter Wang <peter.wang@torchmobile.com.cn> + + Web Inspector: The JS code injected by worker inspector shouldn't be evaluated through JSMainThreadExecState + https://bugs.webkit.org/show_bug.cgi?id=95341 + + Reviewed by Yury Semikhatsky. + + Add extra code to "JSC::InjectedScriptManager" and "JSC::ScriptFunctionCall" to make sure the + interfaces of JSMainThreadExecState are invoked only in main thread. + + No new test case for this bug. Without this patch, opening worker inspector will meet failed assert statements. + + * bindings/js/JSInjectedScriptManager.cpp: + (WebCore::InjectedScriptManager::createInjectedScript): + * bindings/js/ScriptFunctionCall.cpp: + (WebCore::ScriptFunctionCall::call): + +2012-09-25 Andreas Kling <kling@webkit.org> + + CSSParserString: Avoid pointless String refcount churn in init(). + <http://webkit.org/b/94748> + + Reviewed by Sam Weinig. + + Have CSSParserString::init() take a const String& instead of a String. + + * css/CSSParserValues.h: + (WebCore::CSSParserString::init): + +2012-09-25 Alexander Pavlov <apavlov@chromium.org> + + Web Inspector: [Styles] For group selectors, transmit their segments with the "matches" flag + https://bugs.webkit.org/show_bug.cgi?id=96999 + + Reviewed by Pavel Feldman. + + The CSSRule protocol object has been modified to include a SelectorList object that contains selector-related data. + CSSAgent methods that return CSS rule matches will return RuleMatch objects that encapsulate matching CSSRules + with indices of matching selectors on the associated selector list, so the additional backend roundtrips + from StylesSidebarPane are no longer necessary. + + * inspector/Inspector.json: + * inspector/InspectorCSSAgent.cpp: + (WebCore::InspectorCSSAgent::getMatchedStylesForNode): + (WebCore::InspectorCSSAgent::buildObjectForRule): + (WebCore): + (WebCore::InspectorCSSAgent::buildArrayForRuleList): + (WebCore::InspectorCSSAgent::buildArrayForMatchedRuleList): + * inspector/InspectorCSSAgent.h: + (InspectorCSSAgent): + * inspector/InspectorStyleSheet.cpp: + (WebCore::InspectorStyleSheet::buildObjectForSelectorList): + (WebCore): + (WebCore::InspectorStyleSheet::buildObjectForRule): + * inspector/InspectorStyleSheet.h: + (InspectorStyleSheet): + * inspector/front-end/CSSStyleModel.js: + (WebInspector.CSSStyleModel.parseRuleMatchArrayPayload): + (WebInspector.CSSStyleModel.prototype.getMatchedStylesAsync): + (WebInspector.CSSRule): + (WebInspector.CSSRule.parsePayload): + * inspector/front-end/StylesSidebarPane.js: + (WebInspector.StylesSidebarPane.prototype._innerRebuildUpdate): + (WebInspector.StylesSidebarPane.prototype._rebuildSectionsForStyleRules): + (WebInspector.StylePropertiesSection.prototype._markSelectorMatches): + (WebInspector.StylePropertiesSection.prototype._moveEditorFromSelector): + (WebInspector.StylePropertiesSection.prototype.editingSelectorCancelled): + +2012-09-25 MORITA Hajime <morrita@google.com> + + adoptNode() shouldn't reset ownerDocument if the source node failed to remove itself + https://bugs.webkit.org/show_bug.cgi?id=97527 + + Reviewed by Ryosuke Niwa. + + Document::adoptNode() overlooked an error which can happen in Node::removeChild(). + Which results an assertion failure. This change adds an error check for that code path. + + Test: fast/dom/adopt-node-prevented.html + + * dom/Document.cpp: + (WebCore::Document::adoptNode): + +2012-09-21 Ilya Tikhonovsky <loislo@chromium.org> + + Web Inspector: extract Vector instrumentation from core NMI code into MemoryInstrumentationVector.h header. + https://bugs.webkit.org/show_bug.cgi?id=96650 + + Reviewed by Vsevolod Vlasov. + + addInstrumentedVector and addInstrumentedVectorPtr were replaced with addMember. + The same thing happens with addVector and addVectorPtr. + + * css/CSSGradientValue.cpp: + (WebCore::CSSGradientValue::reportBaseClassMemoryUsage): + * css/CSSImageSetValue.cpp: + (WebCore::CSSImageSetValue::reportDescendantMemoryUsage): + * css/CSSMediaRule.cpp: + (WebCore::CSSMediaRule::reportDescendantMemoryUsage): + * css/CSSRuleList.cpp: + (WebCore::StaticCSSRuleList::reportMemoryUsage): + * css/CSSStyleSheet.cpp: + (WebCore::CSSStyleSheet::reportMemoryUsage): + * css/CSSValueList.cpp: + (WebCore::CSSValueList::reportDescendantMemoryUsage): + * css/MediaList.cpp: + (WebCore::MediaQuerySet::reportMemoryUsage): + * css/MediaQuery.cpp: + (WebCore::MediaQuery::reportMemoryUsage): + * css/StyleResolver.cpp: + (WebCore::StyleResolver::collectMatchingRulesForList): + * css/StyleRule.cpp: + (WebCore::StyleRuleBlock::reportDescendantMemoryUsage): + * css/StyleSheetContents.cpp: + (WebCore::StyleSheetContents::reportMemoryUsage): + * css/WebKitCSSKeyframesRule.cpp: + (WebCore::StyleRuleKeyframes::reportDescendantMemoryUsage): + (WebCore::WebKitCSSKeyframesRule::reportDescendantMemoryUsage): + * css/WebKitCSSRegionRule.cpp: + (WebCore::WebKitCSSRegionRule::reportDescendantMemoryUsage): + * dom/Document.cpp: + (WebCore::Document::reportMemoryUsage): + * loader/DocumentLoader.cpp: + (WebCore::DocumentLoader::reportMemoryUsage): + * platform/network/ResourceRequestBase.cpp: + (WebCore::ResourceRequestBase::reportMemoryUsage): + +2012-09-25 Vivek Galatage <vivekgalatage@gmail.com> + + REGRESSION(r129346): It broke !ENABLE(INSPECTOR) build + https://bugs.webkit.org/show_bug.cgi?id=97490 + + Reviewed by Csaba Osztrogonác. + + The dummy class implementation must be under the ENABLE(INSPECTOR) + guard. Added them to prevent from braking the build with --minimal + option for build-webkit + + No new tests as caused by missing compile guard. + + * testing/Internals.cpp: + (WebCore): + +2012-09-24 Bo Liu <boliu@chromium.org> + + Reland "Add in-place reload behavior to ImagesEnabled setting" with optimizations + https://bugs.webkit.org/show_bug.cgi?id=97055 + + Reviewed by Adam Barth. + + Relanding 128780, 128676, 128645. Was reverted in 128914 due to + performance regression in Chromium. + + New changes in addition to previously reverted patches: + + Refactored CachedResource::requestResource, loadResource, and + revalidateResource. Moved CachedResource::load method to end of + requestResource so there is one place where load is called for all + resources. + + Added a enum parameter for requestResource and + determineRevalidationPolicy so that FrameLoaderClient::allowImage call + do not need to be called multiple times. + + Removed CachedImage::load call in requestImage so it is not called + twice. + + Removed unnecessary Frame.h includes in CachedResource and + CachedImage. + + Removed dead load() method declaration in CachedImage. + + Updated text expectation for two image-permissions tests to reflect + the removed calls to allowImage. + + Tests: fast/loader/display-image-unset-allows-cached-image-load.html + fast/loader/display-image-unset-can-block-image-and-can-reload-in-place.html + fast/loader/images-enabled-unset-can-block-image-and-can-reload-in-place.html + + * WebCore.exp.in: + * loader/FrameLoader.cpp: + (WebCore::FrameLoader::didBeginDocument): + * loader/SubresourceLoader.cpp: + (WebCore::SubresourceLoader::willSendRequest): + * loader/cache/CachedImage.cpp: + * loader/cache/CachedImage.h: + * loader/cache/CachedResource.cpp: + (WebCore::CachedResource::didAddClient): + * loader/cache/CachedResource.h: + (WebCore): + (WebCore::CachedResource::stillNeedsLoad): + * loader/cache/CachedResourceLoader.cpp: + (WebCore::CachedResourceLoader::CachedResourceLoader): + (WebCore::CachedResourceLoader::requestImage): + (WebCore::CachedResourceLoader::canRequest): + (WebCore::CachedResourceLoader::requestResource): + (WebCore::CachedResourceLoader::revalidateResource): + (WebCore::CachedResourceLoader::loadResource): + (WebCore::CachedResourceLoader::determineRevalidationPolicy): + (WebCore::CachedResourceLoader::setAutoLoadImages): + (WebCore): + (WebCore::CachedResourceLoader::setImagesEnabled): + (WebCore::CachedResourceLoader::clientDefersImage): + (WebCore::CachedResourceLoader::shouldDeferImageLoad): + (WebCore::CachedResourceLoader::reloadImagesIfNotDeferred): + * loader/cache/CachedResourceLoader.h: + (CachedResourceLoader): + * page/Settings.cpp: + (WebCore::setImageLoadingSettings): + (WebCore::Settings::Settings): + (WebCore::Settings::setLoadsImagesAutomatically): + (WebCore::Settings::imageLoadingSettingsTimerFired): + (WebCore::Settings::setImagesEnabled): + * page/Settings.h: + (Settings): + * testing/InternalSettings.cpp: + (WebCore::InternalSettings::Backup::Backup): + (WebCore::InternalSettings::Backup::restoreTo): + (WebCore::InternalSettings::setImagesEnabled): + (WebCore): + * testing/InternalSettings.h: + (Backup): + (InternalSettings): + * testing/InternalSettings.idl: + +2012-09-24 Filip Pizlo <fpizlo@apple.com> + + SerializedScriptValue isn't aware of indexed storage, but should be + https://bugs.webkit.org/show_bug.cgi?id=97515 + <rdar://problem/12361874> + + Reviewed by Sam Weinig. + + New test: fast/js/post-message-numeric-property.html + + * bindings/js/SerializedScriptValue.cpp: + (WebCore::CloneDeserializer::putProperty): + +2012-09-24 Gavin Barraclough <barraclough@apple.com> + + Remove JSObject::unwrappedGlobalObject(), JSObject::unwrappedObject() + https://bugs.webkit.org/show_bug.cgi?id=97519 + + Reviewed by Geoff Garen. + + JSDOMWindowShell::setWindow should update the structure's globalObject. + + * bindings/js/JSDOMWindowShell.h: + (WebCore::JSDOMWindowShell::setWindow): + - Update the JSDOMWindowShell's structure's globalObject when the + window changes. + +2012-09-24 Yoshifumi Inoue <yosin@chromium.org> + + [Forms] We should remove DateTimeEditElement::valueAsDouble() + https://bugs.webkit.org/show_bug.cgi?id=97327 + + Reviewed by Kent Tamura. + + This patch removes unused function DateTimeEditElement::valueAsDouble() + and related functions in DateTimeFieldElement. + + This patch affects ports which enable both ENABLE_INPUT_TYPE_TIME and + ENABLE_INPUT_TYPE_TIME_MULTIPLE_FIELDS. + + No new tests. This patch doesn't change behavior. + + * html/shadow/DateTimeEditElement.cpp: Removed valueAsDouble() implementation. + * html/shadow/DateTimeEditElement.h: Removed valueAsDouble() declaration. + (DateTimeEditElement): + * html/shadow/DateTimeFieldElement.cpp: Removed valueAsDouble() implementation. + * html/shadow/DateTimeFieldElement.h: Removed unitInMillisecond() and valueAsDouble() declarations. + (DateTimeFieldElement): + * html/shadow/DateTimeFieldElements.cpp: Removed unitInMillisecond() implementations. + * html/shadow/DateTimeFieldElements.h: + (DateTimeAMPMFieldElement): Removed unitInMillisecond() declaration. + (DateTimeHourFieldElement): ditto. + (DateTimeMillisecondFieldElement): ditto. + (DateTimeMinuteFieldElement): ditto. + (DateTimeSecondFieldElement): ditto. + +2012-09-24 Antti Koivisto <antti@apple.com> + + Don't use StyleSheetList internally. + https://bugs.webkit.org/show_bug.cgi?id=97504 + + Reviewed by Ryosuke Niwa. + + StyleSheetList is a DOM type and should not be used internally. Use plain Vector instead and construct StyleSheetList on DOM access only. + + * css/StyleResolver.cpp: + (WebCore::StyleResolver::StyleResolver): + (WebCore::StyleResolver::addStylesheetsFromSeamlessParents): + (WebCore::StyleResolver::collectMatchingRulesForList): + * css/StyleSheetList.cpp: + (WebCore::StyleSheetList::StyleSheetList): + (WebCore::StyleSheetList::styleSheets): + (WebCore): + (WebCore::StyleSheetList::detachFromDocument): + + Use live stylesheet vector of the documents stylesheet collection as long as we are attached to a document. + When detached copy the stylesheet vector to a member field and use that instead. + + (WebCore::StyleSheetList::length): + (WebCore::StyleSheetList::item): + (WebCore::StyleSheetList::getNamedItem): + * css/StyleSheetList.h: + + Removed StyleSheetVector typedef as Vector<RefPtr<StyleSheet> > is less opaque and not much longer. + + (WebCore): + (WebCore::StyleSheetList::create): + (StyleSheetList): + (WebCore::StyleSheetList::document): + * dom/Document.cpp: + (WebCore::Document::~Document): + (WebCore::Document::setCompatibilityMode): + (WebCore::Document::styleSheets): + * dom/Document.h: + (Document): + * dom/DocumentStyleSheetCollection.cpp: + (WebCore::DocumentStyleSheetCollection::DocumentStyleSheetCollection): + (WebCore::DocumentStyleSheetCollection::~DocumentStyleSheetCollection): + (WebCore::DocumentStyleSheetCollection::analyzeStyleSheetChange): + (WebCore::DocumentStyleSheetCollection::updateActiveStyleSheets): + * dom/DocumentStyleSheetCollection.h: + (WebCore::DocumentStyleSheetCollec + +2012-09-24 Laszlo Gombos <l.gombos@samsung.com> + + [GTK][EFL] Remove cairo prefix from include statements + https://bugs.webkit.org/show_bug.cgi?id=97509 + + Reviewed by Gyuyoung Kim. + + Make the build system consistent by always assuming that directory + that includes the cairo headers is included in the include path. + + No new tests as there is no new functionality. + + * platform/cairo/WidgetBackingStoreCairo.cpp: + * platform/gtk/GtkWidgetBackingStoreX11.cpp: + * plugins/gtk/PluginViewGtk.cpp: + +2012-09-24 Yoshifumi Inoue <yosin@chromium.org> + + Document::adoptNode for multiple fields time input UI should not crash + https://bugs.webkit.org/show_bug.cgi?id=97428 + + Reviewed by Dimitri Glazkov. + + This patch changes Document::removeFocusedNodeOfSubtree() to check + focused node in shadow DOM tree for avoiding Document::m_focusedNode + not to have dangling pointer to field owner in DateTimeFieldElement. + + Test: + - fast/dom/shadow/shadow-removechild-and-blur-event.html: test for removeChild dispatches blur event. + - fast/forms/time-multiple-fields/time-multiple-fields-crash-after-adoptnode.html: test for adoptNode not to crash. + - fast/forms/time-multiple-fields/time-multiple-fields-state-change-on-focus-or-blur.html: removeChild of input type "time" dispatches blur event, existing test. + + * dom/Document.cpp: + (WebCore::Document::removeFocusedNodeOfSubtree): Changed to check + focused node in shadow DOM tree in addition to descendant node. + +2012-09-24 Robin Cao <robin.cao@torchmobile.com.cn> + + [Blackberry] Add a software rendering path for media player + https://bugs.webkit.org/show_bug.cgi?id=97443 + + Reviewed by Yong Li. + + This patch adds a software rendering path for media player. When accelerated rendering + is not supported by the media engine for the current media, the rendering will fallback + to this software path. + + PR #212386 + Reviewed internally by Max Feil. + + * platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp: + (WebCore::MediaPlayerPrivate::paint): + (WebCore::MediaPlayerPrivate::updateStates): + (WebCore::MediaPlayerPrivate::supportsAcceleratedRendering): + (WebCore): + * platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h: + (MediaPlayerPrivate): + +2012-09-24 Benjamin Poulain <bpoulain@apple.com> + + Fix Geolocation error reporting in the test support + https://bugs.webkit.org/show_bug.cgi?id=97386 + + Reviewed by Sam Weinig. + + GeolocationController currently expose GeolocationError which can be either + PermissionDenied or PositionUnavailable. + + In practice, only PositionUnavailable is supported and tested, only Chrome + somewhat expose PermissionDenied. + The correct way to deny the permission is through Geolocation::setIsAllowed(). + + This patch does some of the initial cleanup toward that goal, reducing how + far GeolocationError is spread. + + * WebCore.exp.in: + * WebCore.xcodeproj/project.pbxproj: + Mac does not use GeolocationClientMock, it should not be compiled in WebCore. + + * platform/mock/GeolocationClientMock.cpp: + (WebCore::GeolocationClientMock::GeolocationClientMock): + (WebCore::GeolocationClientMock::setPosition): + (WebCore::GeolocationClientMock::setPositionUnavailableError): + This method replace setError(). It is limited to PositionUnavailable errors. + + (WebCore::GeolocationClientMock::reset): + (WebCore::GeolocationClientMock::controllerTimerFired): + (WebCore): + (WebCore::GeolocationClientMock::clearError): + * platform/mock/GeolocationClientMock.h: + (WebCore): + (GeolocationClientMock): + +2012-09-24 Kent Tamura <tkent@chromium.org> + + [Chromium] Implement ValidationMessageClient for Chromium + https://bugs.webkit.org/show_bug.cgi?id=97167 + + Reviewed by Hajime Morita. + + * page/ValidationMessageClient.h: + Add forward declaration for WTF::String. + +2012-09-24 Yoshifumi Inoue <yosin@chromium.org> + + [Forms] DateTimeEditElement should return string value for ease of implementing other date/time input types. + https://bugs.webkit.org/show_bug.cgi?id=97303 + + Reviewed by Kent Tamura. + + This patch introduces a function DateTimeEditElement::value() for + setting internal text value of TimeInputType with new function + EditControlOwner::formatDateTimeFieldsState() to utilize this protocl + in other date time input types. + + We used DateTimeEditElement::valueAsDouble() and and BaseDateAndTimeInputType::serialize() + to make string value then setting internal text value of multiple + fields time input UI. Although, this steps doesn't work well for + other date/time input types. + + This patch affects ports which enable both ENABLE_INPUT_TYPE_TIME and + ENABLE_INPUT_TYPE_TIME_MULTIPLE_FIELDS. + + No new tests. This patch doesn't change behavior. + + * html/DateTimeFieldsState.cpp: + (WebCore::DateTimeFieldsState::hour23): Added to convert 1 to 12 hour value to 0 to 23 hour. + * html/DateTimeFieldsState.h: + (DateTimeFieldsState): Added declaration of hour23(). + * html/TimeInputType.cpp: + (WebCore::TimeInputType::DateTimeEditControlOwnerImpl::editControlValueChanged): Changed to use DateTimeEditElement::value() instead of DateTimeEditElement::valueAsDouble(). + (WebCore::TimeInputType::DateTimeEditControlOwnerImpl::formatDateTimeFieldsState): Added to format time. + (WebCore::TimeInputType::restoreFormControlState): Changed to use DateTimeEditElement::value() instead of DateTimeEditElement::valueAsDouble(). + * html/TimeInputType.h: + (DateTimeEditControlOwnerImpl): Added a declaration of formatDateTimeFieldsState(). + * html/shadow/DateTimeEditElement.cpp: + (WebCore::DateTimeEditElement::value): Added. + * html/shadow/DateTimeEditElement.h: + (EditControlOwner): Added a declaration of formatDateTimeFieldsState(). + (DateTimeEditElement): Added a declaration of value(). + +2012-09-24 Dean Jackson <dino@apple.com> + + [WebGL] Intel Mac needs built-in function emulation + https://bugs.webkit.org/show_bug.cgi?id=96140 + + Reviewed by Sam Weinig. + + Temporarily turn on built-in function emulation for Intel GPUs + on OS X. This is a work-around for a driver bug, and + will be removed once the driver is updated: + https://bugs.webkit.org/show_bug.cgi?id=97503 + + This can be tested using the Khronos WebGL conformance + suite, in particular: + + conformance/glsl/functions/glsl-function-dot.html + conformance/glsl/functions/glsl-function-length.html + conformance/glsl/functions/glsl-function-normalize.html + conformance/glsl/functions/glsl-function-reflect.html + + Note that the faceforward built-in will still cause + problems on Intel GPUs, but this would require an unnecessary + change in the ANGLE project (remember, we're going to + remove this code once the driver is fixed). + + * platform/graphics/opengl/Extensions3DOpenGLCommon.cpp: + (WebCore::Extensions3DOpenGLCommon::getTranslatedShaderSourceANGLE): + Temporarily add "Intel" to the list of GPUs we do translation + for in the shader compiler. + +2012-09-24 Peter Wang <peter.wang@torchmobile.com.cn> + + There is a mistake in InspectorProfilerAgent::enable(bool skipRecompile) + https://bugs.webkit.org/show_bug.cgi?id=97450 + + Reviewed by Yury Semikhatsky. + + The "InspectorProfilerAgent::enable()" should invokes "PageScriptDebugServer" in + no-worker thread. + + No new test case. + + * inspector/InspectorProfilerAgent.cpp: + (WebCore::PageProfilerAgent::recompileScript): + (PageProfilerAgent): + (WebCore::WorkerProfilerAgent::recompileScript): + (WorkerProfilerAgent): + (WebCore::InspectorProfilerAgent::disable): + (WebCore::InspectorProfilerAgent::enable): + * inspector/InspectorProfilerAgent.h: + (InspectorProfilerAgent): + +2012-09-24 Patrick Gansterer <paroga@webkit.org> + + Remove String::operator+=() + https://bugs.webkit.org/show_bug.cgi?id=96172 + + Reviewed by Benjamin Poulain. + + Replace the last usage with String::append() in Gtk. + + * platform/gtk/GtkInputMethodFilter.cpp: + (WebCore::GtkInputMethodFilter::handleCommit): + +2012-09-24 Mark Pilgrim <pilgrim@chromium.org> + + [Chromium][Mac] Remove loadFont from PlatformSupport + https://bugs.webkit.org/show_bug.cgi?id=97360 + + Reviewed by Adam Barth. + + Part of a refactoring series. See tracking bug 82948. + + * platform/chromium/PlatformSupport.h: + (PlatformSupport): + * platform/graphics/chromium/CrossProcessFontLoading.mm: + +2012-09-24 Tony Chang <tony@chromium.org> + + Replace 2 uses of updateLogicalHeight with computeLogicalHeight + https://bugs.webkit.org/show_bug.cgi?id=97486 + + Reviewed by Ojan Vafai. + + More work for bug 96804. This is just a refactoring. + + No new tests, behavior should be the same as before. + + * rendering/RenderFlowThread.cpp: + (WebCore::RenderFlowThread::computeLogicalHeight): + * rendering/RenderFlowThread.h: + * rendering/RenderMultiColumnFlowThread.cpp: + (WebCore::RenderMultiColumnFlowThread::computeLogicalHeight): + (WebCore): + * rendering/RenderMultiColumnFlowThread.h: + (RenderMultiColumnFlowThread): + +2012-09-21 Kenneth Russell <kbr@google.com> + + [V8] ArrayBuffer code should not pass a negative length to SetIndexedPropertiesToExternalArrayData() + https://bugs.webkit.org/show_bug.cgi?id=96703 + + Reviewed by Adam Barth. + + Check length arguments that may be passed to SetIndexedPropertiesToExternalArrayData. + + No tests because it is not guaranteed that buffers this large can actually be allocated. + + * bindings/v8/custom/V8ArrayBufferViewCustom.h: + (WebCore::wrapArrayBufferView): + (WebCore::constructWebGLArrayWithArrayBufferArgument): + (WebCore::constructWebGLArray): + +2012-09-24 Antti Koivisto <antti@apple.com> + + Split stylesheet related code out from Document + https://bugs.webkit.org/show_bug.cgi?id=97353 + + Reviewed by Andreas Kling. + + Document is big and unwieldy. The code related to tracking active stylesheets can be factored out. + + The patch moves stylesheet upkeep, collection and invalidation code from Document to a separate + DocumentStyleSheetCollection class. There are no functional changes. + + The usesLinkRules stylesheet feature bit and the related code is removed as no one was using it. + + * WebCore.xcodeproj/project.pbxproj: + * css/SelectorChecker.cpp: + (WebCore::SelectorChecker::checkOneSelector): + * css/StyleResolver.cpp: + (WebCore::StyleResolver::StyleResolver): + (WebCore::StyleResolver::Features::Features): + (WebCore::StyleResolver::Features::add): + (WebCore::StyleResolver::Features::clear): + (WebCore::StyleResolver::collectMatchingRulesForList): + * css/StyleResolver.h: + (WebCore::StyleResolver::usesBeforeAfterRules): + (Features): + * dom/Document.cpp: + (WebCore::Document::Document): + (WebCore::Document::~Document): + (WebCore::Document::setCompatibilityMode): + (WebCore::Document::recalcStyle): + (WebCore): + (WebCore::Document::createStyleResolver): + (WebCore::Document::seamlessParentUpdatedStylesheets): + (WebCore::Document::didRemoveAllPendingStylesheet): + (WebCore::Document::processHttpEquiv): + (WebCore::Document::styleSheets): + (WebCore::Document::preferredStylesheetSet): + (WebCore::Document::selectedStylesheetSet): + (WebCore::Document::setSelectedStylesheetSet): + (WebCore::Document::styleResolverChanged): + (WebCore::Document::reportMemoryUsage): + (WebCore::Document::haveStylesheetsLoaded): + * dom/Document.h: + (WebCore): + (Document): + (WebCore::Document::styleSheetCollection): + (WebCore::Document::hasNodesWithPlaceholderStyle): + (WebCore::Document::setNeedsNotifyRemoveAllPendingStylesheet): + (WebCore::Document::inStyleRecalc): + * dom/DocumentStyleSheetCollection.cpp: Added. + (WebCore): + (WebCore::DocumentStyleSheetCollection::DocumentStyleSheetCollection): + (WebCore::DocumentStyleSheetCollection::~DocumentStyleSheetCollection): + (WebCore::DocumentStyleSheetCollection::pageUserSheet): + (WebCore::DocumentStyleSheetCollection::clearPageUserSheet): + (WebCore::DocumentStyleSheetCollection::updatePageUserSheet): + (WebCore::DocumentStyleSheetCollection::pageGroupUserSheets): + (WebCore::DocumentStyleSheetCollection::clearPageGroupUserSheets): + (WebCore::DocumentStyleSheetCollection::updatePageGroupUserSheets): + (WebCore::DocumentStyleSheetCollection::addUserSheet): + (WebCore::DocumentStyleSheetCollection::removePendingSheet): + (WebCore::DocumentStyleSheetCollection::addStyleSheetCandidateNode): + (WebCore::DocumentStyleSheetCollection::removeStyleSheetCandidateNode): + (WebCore::DocumentStyleSheetCollection::collectActiveStyleSheets): + (WebCore::DocumentStyleSheetCollection::testAddedStyleSheetRequiresStyleRecalc): + (WebCore::DocumentStyleSheetCollection::analyzeStyleSheetChange): + (WebCore::styleSheetsUseRemUnits): + (WebCore::DocumentStyleSheetCollection::updateActiveStyleSheets): + (WebCore::DocumentStyleSheetCollection::combineCSSFeatureFlags): + (WebCore::DocumentStyleSheetCollection::resetCSSFeatureFlags): + (WebCore::DocumentStyleSheetCollection::reportMemoryUsage): + * dom/DocumentStyleSheetCollection.h: Added. + (WebCore): + (DocumentStyleSheetCollection): + (WebCore::DocumentStyleSheetCollection::authorStyleSheets): + (WebCore::DocumentStyleSheetCollection::documentUserSheets): + (WebCore::DocumentStyleSheetCollection::needsUpdateActiveStylesheetsOnStyleRecalc): + (WebCore::DocumentStyleSheetCollection::preferredStylesheetSetName): + (WebCore::DocumentStyleSheetCollection::selectedStylesheetSetName): + (WebCore::DocumentStyleSheetCollection::setPreferredStylesheetSetName): + (WebCore::DocumentStyleSheetCollection::setSelectedStylesheetSetName): + (WebCore::DocumentStyleSheetCollection::addPendingSheet): + (WebCore::DocumentStyleSheetCollection::hasPendingSheets): + (WebCore::DocumentStyleSheetCollection::usesSiblingRules): + (WebCore::DocumentStyleSheetCollection::setUsesSiblingRulesOverride): + (WebCore::DocumentStyleSheetCollection::usesFirstLineRules): + (WebCore::DocumentStyleSheetCollection::usesFirstLetterRules): + (WebCore::DocumentStyleSheetCollection::setUsesFirstLetterRules): + (WebCore::DocumentStyleSheetCollection::usesBeforeAfterRules): + (WebCore::DocumentStyleSheetCollection::setUsesBeforeAfterRulesOverride): + (WebCore::DocumentStyleSheetCollection::usesRemUnits): + (WebCore::DocumentStyleSheetCollection::setUsesRemUnit): + * dom/Element.cpp: + (WebCore::Element::recalcStyle): + * dom/ProcessingInstruction.cpp: + (WebCore::ProcessingInstruction::~ProcessingInstruction): + (WebCore::ProcessingInstruction::checkStyleSheet): + (WebCore::ProcessingInstruction::sheetLoaded): + (WebCore::ProcessingInstruction::insertedInto): + (WebCore::ProcessingInstruction::removedFrom): + * dom/StyleElement.cpp: + (WebCore::StyleElement::insertedIntoDocument): + (WebCore::StyleElement::removedFromDocument): + (WebCore::StyleElement::clearDocumentData): + (WebCore::StyleElement::createSheet): + (WebCore::StyleElement::sheetLoaded): + (WebCore::StyleElement::startLoadingDynamicSheet): + * html/HTMLLinkElement.cpp: + (WebCore::HTMLLinkElement::~HTMLLinkElement): + (WebCore::HTMLLinkElement::insertedInto): + (WebCore::HTMLLinkElement::removedFrom): + (WebCore::HTMLLinkElement::addPendingSheet): + (WebCore::HTMLLinkElement::removePendingSheet): + * html/HTMLQuoteElement.cpp: + (WebCore::HTMLQuoteElement::insertedInto): + * html/HTMLViewSourceDocument.cpp: + (WebCore::HTMLViewSourceDocument::HTMLViewSourceDocument): + * mathml/MathMLMathElement.cpp: + (WebCore::MathMLMathElement::insertedInto): + * page/Page.cpp: + (WebCore::Page::userStyleSheetLocationChanged): + * page/PageGroup.cpp: + (WebCore::PageGroup::resetUserStyleCacheInAllFrames): + * rendering/RenderBR.cpp: + (WebCore::RenderBR::lineHeight): + * rendering/RenderBlock.cpp: + (WebCore::RenderBlock::styleDidChange): + (WebCore::RenderBlock::splitBlocks): + (WebCore::RenderBlock::addChildIgnoringAnonymousColumnBlocks): + (WebCore::RenderBlock::lineHeight): + (WebCore::RenderBlock::updateFirstLetter): + * rendering/RenderInline.cpp: + (WebCore::RenderInline::styleDidChange): + (WebCore::RenderInline::updateAlwaysCreateLineBoxes): + (WebCore::RenderInline::addChildIgnoringContinuation): + (WebCore::RenderInline::splitInlines): + (WebCore::RenderInline::lineHeight): + * rendering/RenderObject.cpp: + (WebCore::RenderObject::uncachedFirstLineStyle): + (WebCore::RenderObject::firstLineStyleSlowCase): + * rendering/RenderObject.h: + (WebCore::RenderObject::firstLineStyle): + * rendering/RenderObjectChildList.cpp: + (WebCore::RenderObjectChildList::updateBeforeAfterContent): + * rendering/RenderTableRow.cpp: + (WebCore::RenderTableRow::updateBeforeAndAfterContent): + * rendering/RootInlineBox.cpp: + (WebCore::RootInlineBox::verticalPositionForBox): + +2012-09-24 Otto Derek Cheung <otcheung@rim.com> + + [BlackBerry] Reverting implementation for 407 error pages + https://bugs.webkit.org/show_bug.cgi?id=97455 + + Reviewed by Rob Buis. + + Revert "[BlackBerry] Reverting implementation for 407 error pages" + This reverts commit fda0a1b6ac40c06c03bb6293b4a7d7353c3ca238. + + This revert also reverts commit 0cffe01961fb80204138505bcec29a83818efb73 + due to dependency issues. + + * PlatformBlackBerry.cmake: + * platform/blackberry/AuthenticationChallengeManager.cpp: Removed. + * platform/blackberry/AuthenticationChallengeManager.h: + * platform/blackberry/PageClientBlackBerry.h: + * platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp: + (WebCore::MediaPlayerPrivate::MediaPlayerPrivate): + (WebCore::MediaPlayerPrivate::~MediaPlayerPrivate): + (WebCore::MediaPlayerPrivate::onAuthenticationNeeded): + (WebCore::MediaPlayerPrivate::notifyChallengeResult): + * platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h: + (MediaPlayerPrivate): + * platform/network/blackberry/NetworkJob.cpp: + (WebCore::NetworkJob::NetworkJob): + (WebCore::NetworkJob::handleNotifyStatusReceived): + (WebCore::NetworkJob::notifyAuthReceived): + (WebCore::NetworkJob::handleNotifyClose): + (WebCore::NetworkJob::sendRequestWithCredentials): + (WebCore::NetworkJob::notifyChallengeResult): + * platform/network/blackberry/NetworkJob.h: + (NetworkJob): + +2012-09-24 Chris Rogers <crogers@google.com> + + [REGRESSION] Layout Test webaudio/biquad-getFrequencyResponse.html is failing + https://bugs.webkit.org/show_bug.cgi?id=97439 + + Reviewed by Kenneth Russell. + + Fixes uninitialized member variable. + + This should fix flaky failing test: webaudio/biquad-getFrequencyResponse.html + + * Modules/webaudio/BiquadProcessor.cpp: + (WebCore::BiquadProcessor::BiquadProcessor): + +2012-09-24 Tony Chang <tony@chromium.org> + + flex-grow should be 1 when omitted from flex shorthand + https://bugs.webkit.org/show_bug.cgi?id=97480 + + Reviewed by Ojan Vafai. + + We were using 0, based on an outdated version of the spec. + + Tests: css3/flexbox/flex-property-parsing.html + css3/flexbox/flex-algorithm.html: New test case. + + * css/CSSParser.cpp: + (WebCore::CSSParser::parseFlex): + +2012-09-24 Benjamin Poulain <benjamin@webkit.org> + + Add support for query encoding to WTFURL + https://bugs.webkit.org/show_bug.cgi?id=97422 + + Reviewed by Adam Barth. + + Add the Charset conversion on WebCore side. + + * platform/KURLWTFURL.cpp: + (WebCore::KURL::KURL): + (CharsetConverter): + (WebCore::CharsetConverter::CharsetConverter): + * platform/mac/KURLMac.mm: + (WebCore::KURL::KURL): + +2012-09-24 Benjamin Poulain <benjamin@webkit.org> + + Integrate most of GoogleURL in WTFURL + https://bugs.webkit.org/show_bug.cgi?id=97405 + + Reviewed by Adam Barth. + + Loosen KURLWTFURL to be able to run most tests in Debug. + + * platform/KURLWTFURL.cpp: + (WebCore::KURL::KURL): + (WebCore::KURL::hasPort): + (WebCore::KURL::user): + (WebCore::KURL::pass): + (WebCore::KURL::hasPath): + (WebCore::KURL::path): + (WebCore::KURL::query): + (WebCore::KURL::fragmentIdentifier): + (WebCore::KURL::fileSystemPath): + +2012-09-24 Hans Muller <hmuller@adobe.com> + + [CSS Exclusions] ExclusionShape API should use logical coordinates for input/output + https://bugs.webkit.org/show_bug.cgi?id=96156 + + Reviewed by Dirk Schulze. + + Correct how ExclusionShapes deal with logical coordinates and enable + shape-inside exclusion layout for vertical writing-modes. + + BasicShape's are defined in physical cooordinates, incoming line and box + dimensions are logical coordinates, and the ExclusionShape internals assume + that lines are aligned with the Y axis. The createExclusionShape() method + is responsible for converting the BasicShape to the internal coordinate + system when the writing-mode is vertical. Similarly, the getInclude,ExcludedIntervals() + methods are responsible for converting their logical line parameters to Y + values in the internal coordinate system. The min,maxYForLogicalLine() + methods do the conversion, based on the WritingMode the ExclusionShape + was created with. The getInclude,ExcludedIntervals() methods return the + logical left and right edges of line segments. No transformation is needed for this. + + The ExclusionShape's internal coordinate system is essentially the + "logical" one, except that top/bottom always map to Y, no matter what + the writing-mode is. This is just to simplify writing geometrical shape + algorithms, notably the complex ones for polygons. The bug report includes a + pair of diagrams that clarify how internal coordinates are related to logical + and physical coordinates. + + Test: fast/exclusions/shape-inside/shape-inside-vertical-text.html + + * rendering/ExclusionRectangle.cpp: + (WebCore::ExclusionRectangle::getExcludedIntervals): rename more accurately reflects return value + (WebCore::ExclusionRectangle::getIncludedIntervals): rename for consistency with "excluded" version + * rendering/ExclusionRectangle.h: + * rendering/ExclusionShape.cpp: + (WebCore): + (WebCore::ExclusionShape::createExclusionShape): + * rendering/ExclusionShape.h: + (LineSegment): + (WebCore::LineSegment::LineSegment): relocated from WrapShapeInfo.h + (WebCore): + (ExclusionShape): + (WebCore::ExclusionShape::minYForLogicalLine): + (WebCore::ExclusionShape::maxYForLogicalLine): + (WebCore::ExclusionShape::internalToLogicalBoundingBox): + * rendering/WrapShapeInfo.cpp: + (WebCore::WrapShapeInfo::isWrapShapeInfoEnabledForRenderBlock): + (WebCore::WrapShapeInfo::computeShapeSize): pass writingMode to createExclusionShape() + (WebCore::WrapShapeInfo::computeSegmentsForLine): removed short-circuit for vertical writing-modes + * rendering/WrapShapeInfo.h: + (WebCore): + +2012-09-24 Tony Chang <tony@chromium.org> + + Replace RenderMeter::updateLogicalHeight to RenderMeter::computeLogicalHeight + https://bugs.webkit.org/show_bug.cgi?id=97475 + + Reviewed by Ojan Vafai. + + Using RenderMeter::computeLogicalHeight is part of bug 96804. + Also fix some code to be vertical writing mode aware. This doesn't actually cause + a behavioral difference because we use percentage heights/widths which don't depend on + updateLogicalWidth or computeLogicalHeight. You can still see bugs if you try to set + the min-width on a <meter> node in a vertical writing mode. + + No new tests, no behavioral changes. + + * rendering/RenderMeter.cpp: + (WebCore::RenderMeter::updateLogicalWidth): Make vertical writing mode aware. + (WebCore::RenderMeter::computeLogicalHeight): Switch from updateLogicalHeight and make vertical writing mode aware. + * rendering/RenderMeter.h: + (RenderMeter): + +2012-09-24 Dimitri Glazkov <dglazkov@chromium.org> + + Remove unbaked support for :scope pseudo-class. + https://bugs.webkit.org/show_bug.cgi?id=97467 + + Reviewed by Antti Koivisto. + + It turns out, the Selectors 4 require ":scope" to match contextual reference element set, which would be the root node in querySelector: + http://dev.w3.org/csswg/selectors4/#the-scope-pseudo + + Right now, we simply make ":scope" equivalent to ":root", which is not correct. Let's remove the partial implementation until we have + time/energy to fully implement it. + + No new tests, removing half-baked feature. + + * css/CSSSelector.cpp: + (WebCore::CSSSelector::pseudoId): Removed all mentions of PseudoScope + (WebCore::nameToPseudoTypeMap): Ditto. + (WebCore::CSSSelector::extractPseudoType): Ditto. + * css/CSSSelector.h: Ditto. + * css/SelectorChecker.cpp: + (WebCore::SelectorChecker::checkOneSelector): Ditto. + +2012-09-24 Ryosuke Niwa <rniwa@webkit.org> + + suspend/resumeWidgetHierarchyUpdates should be a RAII object + https://bugs.webkit.org/show_bug.cgi?id=96706 + + Reviewed by Simon Fraser. + + Replaced suspendWidgetHierarchyUpdates and resumeWidgetHierarchyUpdates by WidgetHierarchyUpdatesSuspensionScope. + + * WebCore.exp.in: Export new symbols. + * dom/ContainerNode.cpp: + (WebCore::ContainerNode::removeChild): + (WebCore::ContainerNode::removeChildren): + * dom/Document.cpp: + (WebCore::Document::recalcStyle): + * dom/Element.cpp: + (WebCore::Element::attach): + (WebCore::Element::detach): + * page/mac/EventHandlerMac.mm: + (WebCore::EventHandler::passMouseDownEventToWidget): + * rendering/RenderWidget.cpp: + (WebCore): + (WebCore::WidgetHierarchyUpdatesSuspensionScope::widgetNewParentMap): + (WebCore::WidgetHierarchyUpdatesSuspensionScope::moveWidgets): + (WebCore::moveWidgetToParentSoon): + * rendering/RenderWidget.h: + (WidgetHierarchyUpdatesSuspensionScope): + (WebCore::WidgetHierarchyUpdatesSuspensionScope::WidgetHierarchyUpdatesSuspensionScope): + (WebCore::WidgetHierarchyUpdatesSuspensionScope::~WidgetHierarchyUpdatesSuspensionScope): + (WebCore::WidgetHierarchyUpdatesSuspensionScope::isSuspended): + (WebCore::WidgetHierarchyUpdatesSuspensionScope::scheduleWidgetToMove): + (WebCore): + (RenderWidget): + +2012-09-24 Otto Derek Cheung <otcheung@rim.com> + + [BlackBerry] Reverting implementation for 407 error pages + https://bugs.webkit.org/show_bug.cgi?id=97455 + + Reviewed by Rob Buis. + + Revert "[BlackBerry] Show custom error page when 407 is received" + This reverts commit e6d14529428fe47916fcb997528095b8acad2f2b. + + * platform/network/blackberry/NetworkJob.cpp: + (WebCore::NetworkJob::handleNotifyStatusReceived): + (WebCore::NetworkJob::notifyAuthReceived): + (WebCore::NetworkJob::sendRequestWithCredentials): + +2012-09-24 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r129388. + http://trac.webkit.org/changeset/129388 + https://bugs.webkit.org/show_bug.cgi?id=97477 + + Caused an assertion in a WebKit2 unit test (Requested by + abarth on #webkit). + + * WebCore.exp.in: + * loader/FrameLoader.cpp: + (WebCore::FrameLoader::didBeginDocument): + * loader/SubresourceLoader.cpp: + (WebCore::SubresourceLoader::willSendRequest): + * loader/cache/CachedImage.cpp: + * loader/cache/CachedImage.h: + (WebCore::CachedImage::stillNeedsLoad): + (CachedImage): + * loader/cache/CachedResource.cpp: + (WebCore::CachedResource::didAddClient): + * loader/cache/CachedResource.h: + (WebCore): + * loader/cache/CachedResourceLoader.cpp: + (WebCore::CachedResourceLoader::CachedResourceLoader): + (WebCore::CachedResourceLoader::requestImage): + (WebCore::CachedResourceLoader::canRequest): + (WebCore::CachedResourceLoader::requestResource): + (WebCore::CachedResourceLoader::revalidateResource): + (WebCore::CachedResourceLoader::loadResource): + (WebCore::CachedResourceLoader::determineRevalidationPolicy): + (WebCore::CachedResourceLoader::setAutoLoadImages): + * loader/cache/CachedResourceLoader.h: + (CachedResourceLoader): + * page/Settings.cpp: + (WebCore::setLoadsImagesAutomaticallyInAllFrames): + (WebCore::Settings::Settings): + (WebCore::Settings::setLoadsImagesAutomatically): + (WebCore::Settings::loadsImagesAutomaticallyTimerFired): + (WebCore::Settings::setImagesEnabled): + * page/Settings.h: + (Settings): + * testing/InternalSettings.cpp: + (WebCore::InternalSettings::Backup::Backup): + (WebCore::InternalSettings::Backup::restoreTo): + * testing/InternalSettings.h: + (Backup): + (InternalSettings): + * testing/InternalSettings.idl: + +2012-09-24 Erik Arvidsson <arv@chromium.org> + + DOM4 remove method + https://bugs.webkit.org/show_bug.cgi?id=73885 + + Reviewed by Ojan Vafai. + + This adds the DOM 4 remove method. + + http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-childnode-remove + + The remove method removes the node from its parent if it has a parent. + + Tests: fast/dom/Comment/remove.html + fast/dom/DocumentType/remove.html + fast/dom/Element/remove.html + fast/dom/Text/remove.html + + * dom/CharacterData.idl: + * dom/DocumentType.idl: + * dom/Element.idl: + * dom/Node.cpp: + (WebCore::Node::remove): The spec says to do nothing if the node has no parent. + * html/parser/HTMLTreeBuilder.cpp: + (WebCore::HTMLTreeBuilder::processStartTagForInBody): Cleanup. + * html/track/TextTrackCue.cpp: + (WebCore::TextTrackCue::removeDisplayTree): No need to check parenNode twice. + +2012-09-24 Tommy Widenflycht <tommyw@google.com> + + MediaStream API: Fix the incorrectly spelled RTCPeerConnection::onnegotiationneeded callback + https://bugs.webkit.org/show_bug.cgi?id=97456 + + Reviewed by Adam Barth. + + Renamed onnegotationneeded to onnegotiationneeded. + + Existing test updated. + + * Modules/mediastream/RTCPeerConnection.cpp: + (WebCore::RTCPeerConnection::negotiationNeeded): + * Modules/mediastream/RTCPeerConnection.h: + (RTCPeerConnection): + * Modules/mediastream/RTCPeerConnection.idl: + * dom/EventNames.h: + (WebCore): + +2012-09-24 Peter Beverloo <peter@chromium.org> + + Android's mock scrollbars shows up as a difference in layout test results + https://bugs.webkit.org/show_bug.cgi?id=96382 + + Reviewed by Adam Barth. + + Remove the exceptions made for layout tests in Android's scrollbar theme. + This will make our actual scrollbars show up in layout test pixel results, + bringing the tests closer to what we actually ship. + + An important difference with other platforms is that scrollbars do not + take any width on Android, they're rendered on top of the content. Therefore + each test that has a visible scrollbar does not just need a new pixel + result, but will also need a new text result. This will be handled as part + of a larger rebaselining process. + + Will be exercised by every layout test that has a scrollbar. + + * platform/chromium/ScrollbarThemeChromiumAndroid.cpp: + (WebCore::ScrollbarThemeChromiumAndroid::scrollbarThickness): + (WebCore::ScrollbarThemeChromiumAndroid::usesOverlayScrollbars): + (WebCore::ScrollbarThemeChromiumAndroid::hasThumb): + * platform/chromium/ScrollbarThemeChromiumAndroid.h: + (ScrollbarThemeChromiumAndroid): + +2012-09-24 Sean Wang <Xuewen.Wang@torchmobile.com.cn> + + [BlackBerry] Basic authentication challenge credentials for stored credentials again after restarting browser + https://bugs.webkit.org/show_bug.cgi?id=96362 + + Reviewed by Rob Buis. + + Fix a mistake of the commit 11fdc73c7c74bbd736ed4160248ff59636a01864 + Trunk has been changed during reviewing that patch. + + No new tests, this is to correct a build error. + + * platform/network/blackberry/CredentialBackingStore.cpp: + (WebCore::CredentialBackingStore::getProtectionSpace): + +2012-09-24 Dan Bernstein <mitz@apple.com> + + Reverted r129176, the fix for <http://webkit.org/b/97269>, because it introduced a + discrepancy between line breaking and max width computation. + + Rubber-stamped by Anders Carlsson. + + * platform/graphics/mac/ComplexTextController.cpp: + (WebCore::ComplexTextController::adjustGlyphsAndAdvances): + +2012-09-24 Bo Liu <boliu@chromium.org> + + Reland "Add in-place reload behavior to ImagesEnabled setting" with optimizations + https://bugs.webkit.org/show_bug.cgi?id=97055 + + Reviewed by Adam Barth. + + Relanding 128780, 128676, 128645. Was reverted in 128914 due to + performance regression in Chromium. + + New changes in addition to previously reverted patches: + + Refactored CachedResource::requestResource, loadResource, and + revalidateResource. Moved CachedResource::load method to end of + requestResource so there is one place where load is called for all + resources. + + Added a enum parameter for requestResource and + determineRevalidationPolicy so that FrameLoaderClient::allowImage call + do not need to be called multiple times. + + Removed CachedImage::load call in requestImage so it is not called + twice. + + Removed unnecessary Frame.h includes in CachedResource and + CachedImage. + + Removed dead load() method declaration in CachedImage. + + Updated text expectation for two image-permissions tests to reflect + the removed calls to allowImage. + + Tests: fast/loader/display-image-unset-allows-cached-image-load.html + fast/loader/display-image-unset-can-block-image-and-can-reload-in-place.html + fast/loader/images-enabled-unset-can-block-image-and-can-reload-in-place.html + + * WebCore.exp.in: + * loader/FrameLoader.cpp: + (WebCore::FrameLoader::didBeginDocument): + * loader/SubresourceLoader.cpp: + (WebCore::SubresourceLoader::willSendRequest): + * loader/cache/CachedImage.cpp: + * loader/cache/CachedImage.h: + * loader/cache/CachedResource.cpp: + (WebCore::CachedResource::didAddClient): + * loader/cache/CachedResource.h: + (WebCore): + (WebCore::CachedResource::stillNeedsLoad): + * loader/cache/CachedResourceLoader.cpp: + (WebCore::CachedResourceLoader::CachedResourceLoader): + (WebCore::CachedResourceLoader::requestImage): + (WebCore::CachedResourceLoader::canRequest): + (WebCore::CachedResourceLoader::requestResource): + (WebCore::CachedResourceLoader::revalidateResource): + (WebCore::CachedResourceLoader::loadResource): + (WebCore::CachedResourceLoader::determineRevalidationPolicy): + (WebCore::CachedResourceLoader::setAutoLoadImages): + (WebCore): + (WebCore::CachedResourceLoader::setImagesEnabled): + (WebCore::CachedResourceLoader::clientDefersImage): + (WebCore::CachedResourceLoader::shouldDeferImageLoad): + (WebCore::CachedResourceLoader::reloadImagesIfNotDeferred): + * loader/cache/CachedResourceLoader.h: + (CachedResourceLoader): + * page/Settings.cpp: + (WebCore::setImageLoadingSettings): + (WebCore::Settings::Settings): + (WebCore::Settings::setLoadsImagesAutomatically): + (WebCore::Settings::imageLoadingSettingsTimerFired): + (WebCore::Settings::setImagesEnabled): + * page/Settings.h: + (Settings): + * testing/InternalSettings.cpp: + (WebCore::InternalSettings::Backup::Backup): + (WebCore::InternalSettings::Backup::restoreTo): + (WebCore::InternalSettings::setImagesEnabled): + (WebCore): + * testing/InternalSettings.h: + (Backup): + (InternalSettings): + * testing/InternalSettings.idl: + +2012-09-24 Joone Hur <joone.hur@intel.com>, Gustavo Noronha Silva <gustavo.noronha@collabora.com> + + [GTK] Implement GraphicsLayer using Clutter + https://bugs.webkit.org/show_bug.cgi?id=73767 + + Reviewed by Martin Robinson. + + This patch is needed for enabling Accelerated Compositing(Clutter backend) + with the patches submitted in bug 92045 and 91940. + + No new tests. This will be covered by pixel tests for Qt/GTK+ accelerated + compositing and 3D transforms. + + * GNUmakefile.list.am: + * platform/clutter/GRefPtrClutter.cpp: Removed. + * platform/clutter/GRefPtrClutter.h: Removed. + * platform/graphics/clutter/PlatformClutterLayerClient.h: Added. + (WebCore): + (PlatformClutterLayerClient): + (WebCore::PlatformClutterLayerClient::~PlatformClutterLayerClient): + * platform/graphics/clutter/TransformationMatrixClutter.cpp: Added to convert CoglMatrix to + TransformationMatrix. + (WebCore): + (WebCore::TransformationMatrix::operator CoglMatrix): + * platform/graphics/transforms/TransformationMatrix.h: + (TransformationMatrix): + +2012-09-24 David Grogan <dgrogan@chromium.org> + + Unprefix IndexedDB + https://bugs.webkit.org/show_bug.cgi?id=96548 + + Reviewed by Adam Barth. + + We are largely compatible with the FF implementation and the w3c test + suite submitted by MS. The w3c test suite doesn't yet check + for lack of prefix; this is mostly to signal to devs that we think our + implementation is stable. + + This patch uses the new FeatureObserver to get data about prefixed + vs unprefixed usage. + + Tests: storage/indexeddb/unprefix-workers.html + storage/indexeddb/unprefix.html + + * Modules/indexeddb/DOMWindowIndexedDatabase.cpp: + (WebCore::DOMWindowIndexedDatabase::indexedDB): + * Modules/indexeddb/DOMWindowIndexedDatabase.h: + (DOMWindowIndexedDatabase): + * Modules/indexeddb/DOMWindowIndexedDatabase.idl: + * Modules/indexeddb/WorkerContextIndexedDatabase.cpp: + (WebCore::WorkerContextIndexedDatabase::indexedDB): + * Modules/indexeddb/WorkerContextIndexedDatabase.h: + (WorkerContextIndexedDatabase): + * Modules/indexeddb/WorkerContextIndexedDatabase.idl: + * bindings/generic/RuntimeEnabledFeatures.h: + Making the auxiliary objects RuntimeEnabled didn't make much sense as + they are useless without the factory, so always enable them. + + (WebCore::RuntimeEnabledFeatures::indexedDBEnabled): + * bindings/scripts/CodeGeneratorGObject.pm: + (SkipAttribute): + * page/FeatureObserver.h: + +2012-09-24 Andrey Adaikin <aandrey@chromium.org> + + Web Inspector: [WebGL] First step towards 2D canvas instrumentation in injected script + https://bugs.webkit.org/show_bug.cgi?id=96746 + + Reviewed by Pavel Feldman. + + First step towards the 2D canvas instrumentation from the WebGL injected script module side. + We trace and save all calls that affect the 2D canvas context state and it's resources (Gradient and Pattern) + so that we could replay the context and resources states later. + The 2D canvas context state consists of: + - current transformation matrix + - current default path + - current clipping region (affected by the "clip" command) + - current values of the context attributes (like strokeStyle, fillStyle, etc.) + - a stack of saved drawing states (affected by the "save" and "restore" commands) + + * inspector/InjectedScriptCanvasModuleSource.js: + (.): + +2012-09-24 Andrey Adaikin <aandrey@chromium.org> + + Web Inspector: [TextEditor] conditional breakpoint popup not showing up the first time + https://bugs.webkit.org/show_bug.cgi?id=97442 + + Reviewed by Pavel Feldman. + + 1) The conditional breakpoint popup may not show up the first time we click on the gutter. + This was the case because the popup decoration element would be deleted from the line while + it was being highlighted and appended afterwards. Now we do not remove decorations from the + DOM while highlighting. + + 2) Also the popup will close itself on any mouse click event, even if it's targeted to the + input box itself. This was due to pointer-events: none; CSS style for the parent element. + Now we just override this style for the input box. + + * inspector/front-end/DefaultTextEditor.js: + (WebInspector.TextEditorMainPanel.prototype._paintLine): + (WebInspector.TextEditorMainPanel.prototype._insertSpanBefore): + (WebInspector.TextEditorMainPanel.prototype._insertTextNodeBefore): + * inspector/front-end/inspector.css: + (.source-frame-breakpoint-condition): + +2012-09-24 Andrey Adaikin <aandrey@chromium.org> + + Web Inspector: [Canvas] set CanvasAgent in InstrumentingAgents upon calling enable command + https://bugs.webkit.org/show_bug.cgi?id=97331 + + Reviewed by Yury Semikhatsky. + + We should set CanvasAgent in InstrumentingAgents from enable() command and remove from disable(), instead of doing this in constructor and destructor. + + * inspector/InspectorCanvasAgent.cpp: + (WebCore::InspectorCanvasAgent::InspectorCanvasAgent): + (WebCore::InspectorCanvasAgent::~InspectorCanvasAgent): + (WebCore::InspectorCanvasAgent::restore): + (WebCore::InspectorCanvasAgent::enable): + (WebCore::InspectorCanvasAgent::disable): + * inspector/InspectorCanvasAgent.h: + (InspectorCanvasAgent): + * inspector/InspectorCanvasInstrumentation.h: + (WebCore::InspectorInstrumentation::wrapCanvas2DRenderingContextForInstrumentation): + (WebCore::InspectorInstrumentation::wrapWebGLRenderingContextForInstrumentation): + +2012-09-24 Patrick Gansterer <paroga@webkit.org> + + Remove remaining WTF_DEPRECATED_STRING_OPERATORS from cpp files + https://bugs.webkit.org/show_bug.cgi?id=97412 + + Reviewed by Adam Barth. + + * css/StylePropertySet.cpp: Removed useless define. + +2012-09-20 Emil A Eklund <eae@chromium.org> + + snapToSize rounds the incorrectly for negative locations + https://bugs.webkit.org/show_bug.cgi?id=97265 + + Reviewed by Eric Seidel. + + Change snapSizeToPixel to preserve sign for location which + affects rounding. + + Test: fast/sub-pixel/snap-negative-location.html + + * platform/FractionalLayoutUnit.h: + (WebCore::snapSizeToPixel): + +2012-09-24 Jonathan Liu <net147@gmail.com> + + Use unsigned char for bitfield instead of unsigned. + https://bugs.webkit.org/show_bug.cgi?id=97447 + + Reviewed by Andreas Kling. + + Not all compilers will pad an unsigned bitfield to the smallest size. + Use unsigned char instead of unsigned to reduce padding for compilers + that pad to the underlying type. + + No new tests. There is already a compile-time assertion. + + * css/CSSRule.cpp: + (SameSizeAsCSSRule): + * css/CSSRule.h: + (CSSRule): + +2012-09-24 Peter Rybin <peter.rybin@gmail.com> + + Web Inspector: don't allow exception in front-end when expanding function scope + https://bugs.webkit.org/show_bug.cgi?id=97346 + + Reviewed by Yury Semikhatsky. + + A missing guard condition is added. + + * inspector/front-end/ObjectPropertiesSection.js: + (WebInspector.FunctionScopeMainTreeElement.prototype.onpopulate.didGetDetails): + (WebInspector.FunctionScopeMainTreeElement.prototype.onpopulate): + +2012-09-24 Arvid Nilsson <anilsson@rim.com> + + [BlackBerry] Add cookie database API + https://bugs.webkit.org/show_bug.cgi?id=97102 + + Reviewed by Antonio Gomes. + + Add a CookieManager method that takes a list of strings to parse + instead of just one string. Expose CookieParser::parseOneCookie. + + Reviewed internally by Otto D. Cheung. + + No change in behavior, no new tests. + + * platform/blackberry/CookieManager.cpp: + (WebCore::CookieManager::setCookies): + (WebCore): + * platform/blackberry/CookieManager.h: + * platform/blackberry/CookieParser.cpp: + (WebCore::CookieParser::parseOneCookie): + (WebCore): + * platform/blackberry/CookieParser.h: + (CookieParser): + +2012-09-24 Vsevolod Vlasov <vsevik@chromium.org> + + Web Inspector: Open resource dialog has too many false positive matches. + https://bugs.webkit.org/show_bug.cgi?id=97332 + + Reviewed by Alexander Pavlov. + + Improved open resource dialog filtering to make the amount of false + positive search results less. + + * inspector/front-end/FilteredItemSelectionDialog.js: + (WebInspector.FilteredItemSelectionDialog.prototype._innerCreateSearchRegExp): + (WebInspector.FilteredItemSelectionDialog.prototype._highlightItem.get var): + (WebInspector.FilteredItemSelectionDialog.prototype._highlightItem): + +2012-09-24 Andrey Adaikin <aandrey@chromium.org> + + Web Inspector: [Canvas] support 2D canvas instrumentation from the inspector C++ code + https://bugs.webkit.org/show_bug.cgi?id=97203 + + Reviewed by Yury Semikhatsky. + + Implements wrapping a 2D canvas context through the injected canvas module script facility. + + * bindings/js/JSHTMLCanvasElementCustom.cpp: + (WebCore::JSHTMLCanvasElement::getContext): + * bindings/v8/custom/V8HTMLCanvasElementCustom.cpp: + (WebCore::V8HTMLCanvasElement::getContextCallback): + * inspector/InjectedScriptCanvasModule.cpp: + (WebCore::InjectedScriptCanvasModule::wrapCanvas2DContext): + (WebCore): + (WebCore::InjectedScriptCanvasModule::wrapWebGLContext): + (WebCore::InjectedScriptCanvasModule::callWrapContextFunction): + * inspector/InjectedScriptCanvasModule.h: + (InjectedScriptCanvasModule): + * inspector/InspectorCanvasAgent.cpp: + (WebCore::InspectorCanvasAgent::wrapCanvas2DRenderingContextForInstrumentation): + (WebCore): + * inspector/InspectorCanvasAgent.h: + (InspectorCanvasAgent): + * inspector/InspectorCanvasInstrumentation.h: + (WebCore::InspectorInstrumentation::wrapCanvas2DRenderingContextForInstrumentation): + (WebCore): + * inspector/InspectorInstrumentation.h: + (InspectorInstrumentation): + +2012-09-24 Pavel Feldman <pfeldman@chromium.org> + + Web Inspector:EXC_BAD_ACCESS upon closing page with node highlighted + https://bugs.webkit.org/show_bug.cgi?id=97446 + + Reviewed by Alexander Pavlov. + + Added 0 check on frame view. + + * inspector/InspectorOverlay.cpp: + (WebCore::InspectorOverlay::update): + +2012-09-21 Alexander Pavlov <apavlov@chromium.org> + + Web Inspector: [REGRESSION] Cmd-Shift-C doesn't enable element inspection mode when inspector hidden + https://bugs.webkit.org/show_bug.cgi?id=97249 + + Reviewed by Yury Semikhatsky. + + Fix regression from r125871. + + * inspector/front-end/InspectorFrontendAPI.js: + (InspectorFrontendAPI.enterInspectElementMode): + * inspector/front-end/inspector.js: + (WebInspector._createGlobalStatusBarItems): + (WebInspector.documentKeyDown): + +2012-09-24 Alexander Pavlov <apavlov@chromium.org> + + Web Inspector: Disable persistence of master switches in the "Overrides" settings tab + https://bugs.webkit.org/show_bug.cgi?id=97440 + + Reviewed by Yury Semikhatsky. + + Disables enforcement of device metrics, geolocation, and device orientation overrides on Web Inspector start. + + * inspector/InspectorPageAgent.cpp: + (WebCore::InspectorPageAgent::restore): + * inspector/front-end/SettingsScreen.js: + (WebInspector.UserAgentSettingsTab.prototype._onMetricsCheckboxClicked): + (WebInspector.UserAgentSettingsTab.prototype._onGeolocationOverrideCheckboxClicked): + (WebInspector.UserAgentSettingsTab.prototype._onDeviceOrientationOverrideCheckboxClicked): + * inspector/front-end/UserAgentSupport.js: + (WebInspector.UserAgentSupport): + (WebInspector.UserAgentSupport.prototype.toggleDeviceMetricsOverride): + (WebInspector.UserAgentSupport.prototype.toggleGeolocationPositionOverride): + (WebInspector.UserAgentSupport.prototype.toggleDeviceOrientationOverride): + * inspector/front-end/externs.js: + +2012-09-24 Vivek Galatage <vivekgalatage@gmail.com> + + Web Inspector: implement testing harness for pure protocol tests. + https://bugs.webkit.org/show_bug.cgi?id=90675 + + Reviewed by Yury Semikhatsky. + + Implementing the testing harness as the APIs of Internals object not + only reduced platform specific patching of DRTs but also minimized the + the effort required to open up the new dummy inspector Frontend. + + The openDummyInspectorFrontend method will return the handle to newly + created DOMWindow. This DOMWindow object can be utilized inside the test + case to communicate using postMessage WebAPI. + + The newly created DOMWindow will host the protocol-test.html which + will seed the necessary JS libraries to communicate with the + InspectorBackend. + + Test: inspector-protocol/css-getSupportedCSSProperties.html + + * WebCore.exp.in: + * WebCore.gypi: + * inspector/InspectorClient.h: + (InspectorClient): + * testing/Internals.cpp: + (InspectorFrontendClientDummy): + (WebCore::InspectorFrontendClientDummy::~InspectorFrontendClientDummy): + (WebCore): + (WebCore::InspectorFrontendClientDummy::InspectorFrontendClientDummy): + (InspectorFrontendChannelDummy): + (WebCore::InspectorFrontendChannelDummy::~InspectorFrontendChannelDummy): + (WebCore::InspectorFrontendChannelDummy::InspectorFrontendChannelDummy): + (WebCore::InspectorFrontendChannelDummy::sendMessageToFrontend): + (WebCore::Internals::consoleMessageArgumentCounts): + (WebCore::Internals::openDummyInspectorFrontend): + (WebCore::Internals::closeDummyInspectorFrontend): + * testing/Internals.h: + (WebCore): + (Internals): + * testing/Internals.idl: + +2012-09-24 Keishi Hattori <keishi@webkit.org> + + REGRESSION(r127727): Calendar picker focus doesn't loop in calendar-picker.html + https://bugs.webkit.org/show_bug.cgi?id=97183 + + Reviewed by Kent Tamura. + + Fixing bug calendar-picker.html. The page popup behaves fine because + this code is only necessary in calendar-picker.html where the focus can + move outside of the picker because we are just using an iframe. + + No new tests. Added tests to calendar-picker-key-operations.html. + + * Resources/pagepopups/calendarPicker.js: + (YearMonthController.prototype.attachTo): + (CalendarPicker.prototype._handleBodyKeyDown): + 2012-09-24 Andrey Kosyakov <caseq@chromium.org> Unreviewed follow-up to r129336 -- fixed closure compiler warnings. diff --git a/Source/WebCore/GNUmakefile.list.am b/Source/WebCore/GNUmakefile.list.am index 8ca8b268e..d2ed2915f 100644 --- a/Source/WebCore/GNUmakefile.list.am +++ b/Source/WebCore/GNUmakefile.list.am @@ -2734,6 +2734,8 @@ webcore_sources += \ Source/WebCore/dom/DocumentOrderedMap.h \ Source/WebCore/dom/DocumentParser.cpp \ Source/WebCore/dom/DocumentParser.h \ + Source/WebCore/dom/DocumentStyleSheetCollection.cpp \ + Source/WebCore/dom/DocumentStyleSheetCollection.h \ Source/WebCore/dom/DocumentTiming.h \ Source/WebCore/dom/DocumentType.cpp \ Source/WebCore/dom/DocumentType.h \ @@ -6238,10 +6240,9 @@ endif # END ENABLE_WEBGL if USE_ACCELERATED_COMPOSITING if USE_CLUTTER webcore_sources += \ - Source/WebCore/platform/clutter/GRefPtrClutter.cpp \ - Source/WebCore/platform/clutter/GRefPtrClutter.h \ Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp \ - Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.h + Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.h \ + Source/WebCore/platform/graphics/clutter/TransformationMatrixClutter.cpp endif # END USE_CLUTTER if USE_TEXTURE_MAPPER_CAIRO diff --git a/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.cpp b/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.cpp index 9f4cbb4f7..168028b63 100644 --- a/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.cpp +++ b/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.cpp @@ -88,12 +88,12 @@ void DOMWindowIndexedDatabase::willDetachGlobalObjectFromFrame() DOMWindowProperty::willDetachGlobalObjectFromFrame(); } -IDBFactory* DOMWindowIndexedDatabase::webkitIndexedDB(DOMWindow* window) +IDBFactory* DOMWindowIndexedDatabase::indexedDB(DOMWindow* window) { - return from(window)->webkitIndexedDB(); + return from(window)->indexedDB(); } -IDBFactory* DOMWindowIndexedDatabase::webkitIndexedDB() +IDBFactory* DOMWindowIndexedDatabase::indexedDB() { Document* document = m_window->document(); if (!document) diff --git a/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.h b/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.h index fd32f9d42..c8c6303b2 100644 --- a/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.h +++ b/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.h @@ -41,7 +41,7 @@ public: virtual ~DOMWindowIndexedDatabase(); static DOMWindowIndexedDatabase* from(DOMWindow*); - static IDBFactory* webkitIndexedDB(DOMWindow*); + static IDBFactory* indexedDB(DOMWindow*); virtual void disconnectFrameForPageCache() OVERRIDE; virtual void reconnectFrameFromPageCache(Frame*) OVERRIDE; @@ -52,7 +52,7 @@ public: private: explicit DOMWindowIndexedDatabase(DOMWindow*); - IDBFactory* webkitIndexedDB(); + IDBFactory* indexedDB(); DOMWindow* m_window; RefPtr<IDBFactory> m_idbFactory; diff --git a/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.idl b/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.idl index 09513f1fa..a290b7300 100644 --- a/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.idl +++ b/Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.idl @@ -30,7 +30,7 @@ module window { Conditional=INDEXED_DATABASE, Supplemental=DOMWindow ] DOMWindowIndexedDatabase { - readonly attribute [V8MeasureAs=PrefixedIndexedDB] IDBFactory webkitIndexedDB; + readonly attribute [ImplementedAs=indexedDB,V8MeasureAs=PrefixedIndexedDB] IDBFactory webkitIndexedDB; attribute IDBCursorConstructor webkitIDBCursor; attribute IDBDatabaseConstructor webkitIDBDatabase; @@ -41,6 +41,18 @@ module window { attribute IDBObjectStoreConstructor webkitIDBObjectStore; attribute IDBRequestConstructor webkitIDBRequest; attribute IDBTransactionConstructor webkitIDBTransaction; + + readonly attribute [V8MeasureAs=UnprefixedIndexedDB] IDBFactory indexedDB; + + attribute IDBCursorConstructor IDBCursor; + attribute IDBDatabaseConstructor IDBDatabase; + attribute IDBDatabaseExceptionConstructor IDBDatabaseException; + attribute IDBFactoryConstructor IDBFactory; + attribute IDBIndexConstructor IDBIndex; + attribute IDBKeyRangeConstructor IDBKeyRange; + attribute IDBObjectStoreConstructor IDBObjectStore; + attribute IDBRequestConstructor IDBRequest; + attribute IDBTransactionConstructor IDBTransaction; }; } diff --git a/Source/WebCore/Modules/indexeddb/WorkerContextIndexedDatabase.cpp b/Source/WebCore/Modules/indexeddb/WorkerContextIndexedDatabase.cpp index b3d209992..0a25ea7d7 100644 --- a/Source/WebCore/Modules/indexeddb/WorkerContextIndexedDatabase.cpp +++ b/Source/WebCore/Modules/indexeddb/WorkerContextIndexedDatabase.cpp @@ -58,12 +58,12 @@ WorkerContextIndexedDatabase* WorkerContextIndexedDatabase::from(ScriptExecution return supplement; } -IDBFactory* WorkerContextIndexedDatabase::webkitIndexedDB(ScriptExecutionContext* context) +IDBFactory* WorkerContextIndexedDatabase::indexedDB(ScriptExecutionContext* context) { - return from(context)->webkitIndexedDB(); + return from(context)->indexedDB(); } -IDBFactory* WorkerContextIndexedDatabase::webkitIndexedDB() +IDBFactory* WorkerContextIndexedDatabase::indexedDB() { if (!m_context->securityOrigin()->canAccessDatabase()) return 0; diff --git a/Source/WebCore/Modules/indexeddb/WorkerContextIndexedDatabase.h b/Source/WebCore/Modules/indexeddb/WorkerContextIndexedDatabase.h index 836caa8c6..9a84f1799 100644 --- a/Source/WebCore/Modules/indexeddb/WorkerContextIndexedDatabase.h +++ b/Source/WebCore/Modules/indexeddb/WorkerContextIndexedDatabase.h @@ -42,12 +42,12 @@ public: virtual ~WorkerContextIndexedDatabase(); static WorkerContextIndexedDatabase* from(ScriptExecutionContext*); - static IDBFactory* webkitIndexedDB(ScriptExecutionContext*); + static IDBFactory* indexedDB(ScriptExecutionContext*); private: explicit WorkerContextIndexedDatabase(ScriptExecutionContext*); - IDBFactory* webkitIndexedDB(); + IDBFactory* indexedDB(); ScriptExecutionContext* m_context; RefPtr<IDBFactoryBackendInterface> m_factoryBackend; diff --git a/Source/WebCore/Modules/indexeddb/WorkerContextIndexedDatabase.idl b/Source/WebCore/Modules/indexeddb/WorkerContextIndexedDatabase.idl index c336c57ee..acc5565bd 100644 --- a/Source/WebCore/Modules/indexeddb/WorkerContextIndexedDatabase.idl +++ b/Source/WebCore/Modules/indexeddb/WorkerContextIndexedDatabase.idl @@ -30,17 +30,29 @@ module threads { Conditional=INDEXED_DATABASE, Supplemental=WorkerContext ] WorkerContextIndexedDatabase { - readonly attribute [V8EnabledAtRuntime] IDBFactory webkitIndexedDB; + readonly attribute [ImplementedAs=indexedDB,V8EnabledAtRuntime] IDBFactory webkitIndexedDB; - attribute [V8EnabledAtRuntime] IDBCursorConstructor webkitIDBCursor; - attribute [V8EnabledAtRuntime] IDBDatabaseConstructor webkitIDBDatabase; - attribute [V8EnabledAtRuntime] IDBDatabaseExceptionConstructor webkitIDBDatabaseException; - attribute [V8EnabledAtRuntime] IDBFactoryConstructor webkitIDBFactory; - attribute [V8EnabledAtRuntime] IDBIndexConstructor webkitIDBIndex; - attribute [V8EnabledAtRuntime] IDBKeyRangeConstructor webkitIDBKeyRange; - attribute [V8EnabledAtRuntime] IDBObjectStoreConstructor webkitIDBObjectStore; - attribute [V8EnabledAtRuntime] IDBRequestConstructor webkitIDBRequest; - attribute [V8EnabledAtRuntime] IDBTransactionConstructor webkitIDBTransaction; + attribute IDBCursorConstructor webkitIDBCursor; + attribute IDBDatabaseConstructor webkitIDBDatabase; + attribute IDBDatabaseExceptionConstructor webkitIDBDatabaseException; + attribute IDBFactoryConstructor webkitIDBFactory; + attribute IDBIndexConstructor webkitIDBIndex; + attribute IDBKeyRangeConstructor webkitIDBKeyRange; + attribute IDBObjectStoreConstructor webkitIDBObjectStore; + attribute IDBRequestConstructor webkitIDBRequest; + attribute IDBTransactionConstructor webkitIDBTransaction; + + readonly attribute [V8EnabledAtRuntime] IDBFactory indexedDB; + + attribute IDBCursorConstructor IDBCursor; + attribute IDBDatabaseConstructor IDBDatabase; + attribute IDBDatabaseExceptionConstructor IDBDatabaseException; + attribute IDBFactoryConstructor IDBFactory; + attribute IDBIndexConstructor IDBIndex; + attribute IDBKeyRangeConstructor IDBKeyRange; + attribute IDBObjectStoreConstructor IDBObjectStore; + attribute IDBRequestConstructor IDBRequest; + attribute IDBTransactionConstructor IDBTransaction; }; } diff --git a/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp b/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp index 78896a796..cb9ba7c5a 100644 --- a/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp +++ b/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp @@ -393,7 +393,7 @@ void RTCPeerConnection::close(ExceptionCode& ec) void RTCPeerConnection::negotiationNeeded() { - dispatchEvent(Event::create(eventNames().negotationneededEvent, false, false)); + dispatchEvent(Event::create(eventNames().negotiationneededEvent, false, false)); } void RTCPeerConnection::didGenerateIceCandidate(PassRefPtr<RTCIceCandidateDescriptor> iceCandidateDescriptor) diff --git a/Source/WebCore/Modules/mediastream/RTCPeerConnection.h b/Source/WebCore/Modules/mediastream/RTCPeerConnection.h index 1615581a5..84d1e1fbe 100644 --- a/Source/WebCore/Modules/mediastream/RTCPeerConnection.h +++ b/Source/WebCore/Modules/mediastream/RTCPeerConnection.h @@ -86,7 +86,7 @@ public: void close(ExceptionCode&); - DEFINE_ATTRIBUTE_EVENT_LISTENER(negotationneeded); + DEFINE_ATTRIBUTE_EVENT_LISTENER(negotiationneeded); DEFINE_ATTRIBUTE_EVENT_LISTENER(icecandidate); DEFINE_ATTRIBUTE_EVENT_LISTENER(open); DEFINE_ATTRIBUTE_EVENT_LISTENER(statechange); diff --git a/Source/WebCore/Modules/mediastream/RTCPeerConnection.idl b/Source/WebCore/Modules/mediastream/RTCPeerConnection.idl index 967ad4023..bc4390f54 100644 --- a/Source/WebCore/Modules/mediastream/RTCPeerConnection.idl +++ b/Source/WebCore/Modules/mediastream/RTCPeerConnection.idl @@ -75,7 +75,7 @@ module mediastream { void close() raises(DOMException); - attribute EventListener onnegotationneeded; + attribute EventListener onnegotiationneeded; attribute EventListener onicecandidate; attribute EventListener onopen; attribute EventListener onstatechange; diff --git a/Source/WebCore/Modules/webaudio/BiquadProcessor.cpp b/Source/WebCore/Modules/webaudio/BiquadProcessor.cpp index 3ae02636a..6362a10e7 100644 --- a/Source/WebCore/Modules/webaudio/BiquadProcessor.cpp +++ b/Source/WebCore/Modules/webaudio/BiquadProcessor.cpp @@ -39,6 +39,7 @@ BiquadProcessor::BiquadProcessor(AudioContext* context, float sampleRate, size_t , m_parameter2(0) , m_parameter3(0) , m_filterCoefficientsDirty(true) + , m_hasSampleAccurateValues(false) { double nyquist = 0.5 * this->sampleRate(); diff --git a/Source/WebCore/PlatformBlackBerry.cmake b/Source/WebCore/PlatformBlackBerry.cmake index 987202cde..b608ae873 100644 --- a/Source/WebCore/PlatformBlackBerry.cmake +++ b/Source/WebCore/PlatformBlackBerry.cmake @@ -61,7 +61,6 @@ LIST(APPEND WebCore_SOURCES bindings/cpp/WebDOMString.cpp bindings/cpp/WebExceptionHandler.cpp platform/blackberry/CookieDatabaseBackingStore/CookieDatabaseBackingStore.cpp - platform/blackberry/AuthenticationChallengeManager.cpp platform/blackberry/CookieManager.cpp platform/blackberry/CookieMap.cpp platform/blackberry/CookieParser.cpp diff --git a/Source/WebCore/Resources/pagepopups/calendarPicker.js b/Source/WebCore/Resources/pagepopups/calendarPicker.js index db984a538..3758006f9 100644 --- a/Source/WebCore/Resources/pagepopups/calendarPicker.js +++ b/Source/WebCore/Resources/pagepopups/calendarPicker.js @@ -479,7 +479,7 @@ YearMonthController.prototype.attachTo = function(element) { } this._month.style.minWidth = maxWidth + 'px'; - global.firstFocusableControl = this._left2; // FIXME: Should it be this.month? + this.picker.firstFocusableControl = this._left2; // FIXME: Should it be this.month? }; YearMonthController.addTenYearsButtons = false; @@ -1178,11 +1178,11 @@ CalendarPicker.prototype._handleBodyKeyDown = function(event) { this.maybeUpdateFocusStyle(); var key = event.keyIdentifier; if (key == "U+0009") { - if (!event.shiftKey && document.activeElement == global.lastFocusableControl) { + if (!event.shiftKey && document.activeElement == this.lastFocusableControl) { event.stopPropagation(); event.preventDefault(); this.firstFocusableControl.focus(); - } else if (event.shiftKey && document.activeElement == global.firstFocusableControl) { + } else if (event.shiftKey && document.activeElement == this.firstFocusableControl) { event.stopPropagation(); event.preventDefault(); this.lastFocusableControl.focus(); diff --git a/Source/WebCore/Target.pri b/Source/WebCore/Target.pri index 7465d4405..523d884df 100644 --- a/Source/WebCore/Target.pri +++ b/Source/WebCore/Target.pri @@ -371,6 +371,7 @@ SOURCES += \ dom/DocumentMarker.cpp \ dom/DocumentOrderedMap.cpp \ dom/DocumentParser.cpp \ + dom/DocumentStyleSheetCollection.cpp \ dom/DocumentType.cpp \ dom/DOMCoreException.cpp \ dom/DOMError.cpp \ @@ -1528,6 +1529,7 @@ HEADERS += \ dom/DocumentMarker.h \ dom/DocumentMarkerController.h \ dom/DocumentOrderedMap.h \ + dom/DocumentStyleSheetCollection.h \ dom/DocumentType.h \ dom/DOMError.h \ dom/DOMImplementation.h \ diff --git a/Source/WebCore/WebCore.exp.in b/Source/WebCore/WebCore.exp.in index dff830d50..5e087ac56 100644 --- a/Source/WebCore/WebCore.exp.in +++ b/Source/WebCore/WebCore.exp.in @@ -186,8 +186,6 @@ __ZN7WebCore12PrintContextC1EPNS_5FrameE __ZN7WebCore12PrintContextD1Ev __ZNK7WebCore12RenderObject16repaintRectangleERKNS_20FractionalLayoutRectEb __ZN7WebCore12RenderObject19scrollRectToVisibleERKNS_20FractionalLayoutRectERKNS_15ScrollAlignmentES6_ -__ZN7WebCore12RenderWidget28resumeWidgetHierarchyUpdatesEv -__ZN7WebCore12RenderWidget29suspendWidgetHierarchyUpdatesEv __ZN7WebCore12SharedBuffer10wrapCFDataEPK8__CFData __ZN7WebCore12SharedBuffer10wrapNSDataEP6NSData __ZN7WebCore12SharedBuffer12createNSDataEv @@ -638,6 +636,8 @@ __ZN7WebCore31CrossOriginPreflightResultCache5emptyEv __ZN7WebCore31CrossOriginPreflightResultCache6sharedEv __ZN7WebCore32plainTextToMallocAllocatedBufferEPKNS_5RangeERjbNS_20TextIteratorBehaviorE __ZN7WebCore33stripLeadingAndTrailingHTMLSpacesERKN3WTF6StringE +__ZN7WebCore37WidgetHierarchyUpdatesSuspensionScope11moveWidgetsEv +__ZN7WebCore37WidgetHierarchyUpdatesSuspensionScope35s_widgetHierarchyUpdateSuspendCountE __ZN7WebCore3macERKNS_10CredentialE __ZN7WebCore3macERKNS_23AuthenticationChallengeE __ZN7WebCore40restrictMinimumScaleFactorToViewportSizeERNS_18ViewportAttributesENS_7IntSizeE @@ -852,6 +852,7 @@ __ZN7WebCore8GradientC1ERKNS_10FloatPointES3_ __ZN7WebCore8PositionC1EN3WTF10PassRefPtrINS_4NodeEEEiNS0_10AnchorTypeE __ZN7WebCore8Settings14setJavaEnabledEb __ZN7WebCore8Settings15setWebGLEnabledEb +__ZN7WebCore8Settings16setImagesEnabledEb __ZN7WebCore8Settings16setScriptEnabledEb __ZN7WebCore8Settings16setUsesPageCacheEb __ZN7WebCore8Settings17setPluginsEnabledEb @@ -2191,7 +2192,6 @@ __ZN7WebCore11Geolocation12setIsAllowedEb __ZN7WebCore11GeolocationD1Ev __ZNK7WebCore11Geolocation5frameEv __ZN7WebCore20provideGeolocationToEPNS_4PageEPNS_17GeolocationClientE -__ZN7WebCore21GeolocationClientMock13setPermissionEb __ZN7WebCore21GeolocationController13errorOccurredEPNS_16GeolocationErrorE __ZN7WebCore21GeolocationController14supplementNameEv __ZN7WebCore21GeolocationController15positionChangedEPNS_19GeolocationPositionE @@ -2235,6 +2235,7 @@ __ZN7WebCore16HTMLInputElement25selectColorInColorChooserERKNS_5ColorE __ZN7WebCore15InspectorClient31doDispatchMessageOnFrontendPageEPNS_4PageERKN3WTF6StringE __ZN7WebCore17InspectorCounters12counterValueENS0_11CounterTypeE __ZN7WebCore19InspectorController15profilerEnabledEv +__ZN7WebCore19InspectorController15connectFrontendEPNS_24InspectorFrontendChannelE __ZN7WebCore19InspectorController18disconnectFrontendEv __ZN7WebCore19InspectorController18setProfilerEnabledEb __ZN7WebCore19InspectorController25evaluateForTestInFrontendElRKN3WTF6StringE @@ -2273,7 +2274,11 @@ __ZN7WebCore28InspectorFrontendClientLocal27setTimelineProfilingEnabledEb __ZN7WebCore28InspectorFrontendClientLocal31constrainedAttachedWindowHeightEjj __ZN7WebCore28InspectorFrontendClientLocalC2EPNS_19InspectorControllerEPNS_4PageEN3WTF10PassOwnPtrINS0_8SettingsEEE __ZN7WebCore28InspectorFrontendClientLocalD2Ev +__ZN7WebCore4toJSEPN3JSC9ExecStateEPNS_17JSDOMGlobalObjectEPNS_9DOMWindowE +__ZN7WebCore9DOMWindow4openERKN3WTF6StringERKNS1_12AtomicStringES4_PS0_S8_ +__ZN7WebCore9DOMWindow5closeEPNS_22ScriptExecutionContextE __ZNK7WebCore19InspectorController13drawHighlightERNS_15GraphicsContextE +__ZNK7WebCore9DOMWindow8documentEv #endif #if ENABLE(INSPECTOR) && PLATFORM(IOS) diff --git a/Source/WebCore/WebCore.gypi b/Source/WebCore/WebCore.gypi index e8af673cc..311e75866 100644 --- a/Source/WebCore/WebCore.gypi +++ b/Source/WebCore/WebCore.gypi @@ -657,6 +657,7 @@ 'dom/DocumentMarkerController.h', 'dom/DocumentOrderedMap.h', 'dom/DocumentParser.h', + 'dom/DocumentStyleSheetCollection.h', 'dom/DocumentTiming.h', 'dom/DocumentType.h', 'dom/Element.h', @@ -3816,6 +3817,7 @@ 'dom/DocumentMarker.cpp', 'dom/DocumentOrderedMap.cpp', 'dom/DocumentParser.cpp', + 'dom/DocumentStyleSheetCollection.cpp', 'dom/DocumentType.cpp', 'dom/DynamicNodeList.cpp', 'dom/DynamicNodeList.h', @@ -6313,6 +6315,8 @@ 'testing/MallocStatistics.idl', ], 'webcore_test_support_files': [ + 'inspector/InspectorFrontendClientLocal.cpp', + 'inspector/InspectorFrontendClientLocal.h', 'testing/v8/WebCoreTestSupport.cpp', 'testing/v8/WebCoreTestSupport.h', 'testing/js/WebCoreTestSupport.cpp', diff --git a/Source/WebCore/WebCore.vcproj/WebCore.vcproj b/Source/WebCore/WebCore.vcproj/WebCore.vcproj index ce26603d8..16ab4216d 100755 --- a/Source/WebCore/WebCore.vcproj/WebCore.vcproj +++ b/Source/WebCore/WebCore.vcproj/WebCore.vcproj @@ -50406,6 +50406,14 @@ RelativePath="..\dom\DocumentParser.h"
>
</File>
+ <File
+ RelativePath="..\dom\DocumentStyleSheetCollection.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\dom\DocumentStyleSheetCollection.h"
+ >
+ </File>
<File
RelativePath="..\dom\DocumentTiming.h"
>
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj index 7a25eaa88..b32c24029 100644 --- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj +++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj @@ -76,8 +76,6 @@ 033A6A7E147E07E700509B36 /* HTMLPropertiesCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 033A6A7D147E07E700509B36 /* HTMLPropertiesCollection.cpp */; }; 033A6A81147E088600509B36 /* JSHTMLPropertiesCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 033A6A80147E088600509B36 /* JSHTMLPropertiesCollection.cpp */; }; 033A6A83147E08A600509B36 /* JSHTMLPropertiesCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 033A6A82147E08A600509B36 /* JSHTMLPropertiesCollection.h */; }; - 052BFCE9128ABF1500FD338D /* GeolocationClientMock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 052BFCE8128ABF1500FD338D /* GeolocationClientMock.cpp */; }; - 052BFCEB128ABF2100FD338D /* GeolocationClientMock.h in Headers */ = {isa = PBXBuildFile; fileRef = 052BFCEA128ABF2100FD338D /* GeolocationClientMock.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0562F9461573ECEB0031CA16 /* WebKitCSSSVGDocumentValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0562F9441573ECEB0031CA16 /* WebKitCSSSVGDocumentValue.cpp */; }; 0562F9471573ECEB0031CA16 /* WebKitCSSSVGDocumentValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0562F9451573ECEB0031CA16 /* WebKitCSSSVGDocumentValue.h */; }; 0562F9611573F88F0031CA16 /* PlatformLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0562F9601573F88F0031CA16 /* PlatformLayer.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -6141,6 +6139,8 @@ E4778B80115A581A00B5D372 /* JSCustomEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = E4778B7E115A581A00B5D372 /* JSCustomEvent.h */; }; E47B4BE80E71241600038854 /* CachedResourceHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = E47B4BE60E71241600038854 /* CachedResourceHandle.h */; settings = {ATTRIBUTES = (Private, ); }; }; E47B4BE90E71241600038854 /* CachedResourceHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E47B4BE70E71241600038854 /* CachedResourceHandle.cpp */; }; + E47E276516036ED200EE2AFB /* DocumentStyleSheetCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = E47E276416036ED200EE2AFB /* DocumentStyleSheetCollection.h */; settings = {ATTRIBUTES = (Private, ); }; }; + E47E276816036EDC00EE2AFB /* DocumentStyleSheetCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E47E276716036EDC00EE2AFB /* DocumentStyleSheetCollection.cpp */; }; E4946EAE156E64DD00D3297F /* StyleRuleImport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4946EAC156E64DD00D3297F /* StyleRuleImport.cpp */; }; E4946EAF156E64DD00D3297F /* StyleRuleImport.h in Headers */ = {isa = PBXBuildFile; fileRef = E4946EAD156E64DD00D3297F /* StyleRuleImport.h */; }; E49BD9FA131FD2ED003C56F0 /* CSSValuePool.h in Headers */ = {isa = PBXBuildFile; fileRef = E49BD9F9131FD2ED003C56F0 /* CSSValuePool.h */; }; @@ -7088,8 +7088,6 @@ 033A6A7F147E07F900509B36 /* HTMLPropertiesCollection.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = HTMLPropertiesCollection.idl; sourceTree = "<group>"; }; 033A6A80147E088600509B36 /* JSHTMLPropertiesCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLPropertiesCollection.cpp; sourceTree = "<group>"; }; 033A6A82147E08A600509B36 /* JSHTMLPropertiesCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSHTMLPropertiesCollection.h; sourceTree = "<group>"; }; - 052BFCE8128ABF1500FD338D /* GeolocationClientMock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GeolocationClientMock.cpp; path = mock/GeolocationClientMock.cpp; sourceTree = "<group>"; }; - 052BFCEA128ABF2100FD338D /* GeolocationClientMock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GeolocationClientMock.h; path = mock/GeolocationClientMock.h; sourceTree = "<group>"; }; 0562F9441573ECEB0031CA16 /* WebKitCSSSVGDocumentValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebKitCSSSVGDocumentValue.cpp; sourceTree = "<group>"; }; 0562F9451573ECEB0031CA16 /* WebKitCSSSVGDocumentValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitCSSSVGDocumentValue.h; sourceTree = "<group>"; }; 0562F9601573F88F0031CA16 /* PlatformLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformLayer.h; sourceTree = "<group>"; }; @@ -13520,6 +13518,8 @@ E4778B7E115A581A00B5D372 /* JSCustomEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCustomEvent.h; sourceTree = "<group>"; }; E47B4BE60E71241600038854 /* CachedResourceHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedResourceHandle.h; sourceTree = "<group>"; }; E47B4BE70E71241600038854 /* CachedResourceHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CachedResourceHandle.cpp; sourceTree = "<group>"; }; + E47E276416036ED200EE2AFB /* DocumentStyleSheetCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentStyleSheetCollection.h; sourceTree = "<group>"; }; + E47E276716036EDC00EE2AFB /* DocumentStyleSheetCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentStyleSheetCollection.cpp; sourceTree = "<group>"; }; E4946EAC156E64DD00D3297F /* StyleRuleImport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleRuleImport.cpp; sourceTree = "<group>"; }; E4946EAD156E64DD00D3297F /* StyleRuleImport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleRuleImport.h; sourceTree = "<group>"; }; E49BD9F9131FD2ED003C56F0 /* CSSValuePool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSValuePool.h; sourceTree = "<group>"; }; @@ -15461,8 +15461,6 @@ children = ( 59309A1011F4AE5800250603 /* DeviceOrientationClientMock.cpp */, 59309A1211F4AE6A00250603 /* DeviceOrientationClientMock.h */, - 052BFCE8128ABF1500FD338D /* GeolocationClientMock.cpp */, - 052BFCEA128ABF2100FD338D /* GeolocationClientMock.h */, 0FE71403142170B800DB33BA /* ScrollbarThemeMock.cpp */, 0FE71404142170B800DB33BA /* ScrollbarThemeMock.h */, ); @@ -21671,6 +21669,8 @@ 14947FFC12F80CD200A0F631 /* DocumentOrderedMap.h */, A8C2280D11D4A59700D5A7D3 /* DocumentParser.cpp */, BCCFBAE70B5152ED0001F1D7 /* DocumentParser.h */, + E47E276716036EDC00EE2AFB /* DocumentStyleSheetCollection.cpp */, + E47E276416036ED200EE2AFB /* DocumentStyleSheetCollection.h */, 86D982F6125C154000AD9E3D /* DocumentTiming.h */, A8185F3209765765005826D9 /* DocumentType.cpp */, A8185F3109765765005826D9 /* DocumentType.h */, @@ -22275,6 +22275,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + E47E276516036ED200EE2AFB /* DocumentStyleSheetCollection.h in Headers */, 97BC69DB1505F076001B74AC /* AbstractDatabase.h in Headers */, 41E1B1D10FF5986900576B3B /* AbstractWorker.h in Headers */, 29A8122E0FBB9C1D00510293 /* AccessibilityARIAGridCell.h in Headers */, @@ -23521,7 +23522,6 @@ 0720B0A114D3323500642955 /* GenericEventQueue.h in Headers */, 9746AF2414F4DDE6003E7A70 /* Geolocation.h in Headers */, BC56CB2310D5AC8000A77C64 /* GeolocationClient.h in Headers */, - 052BFCEB128ABF2100FD338D /* GeolocationClientMock.h in Headers */, 9746AF2714F4DDE6003E7A70 /* GeolocationController.h in Headers */, 9746AF2814F4DDE6003E7A70 /* GeolocationError.h in Headers */, 9746AF2914F4DDE6003E7A70 /* GeolocationPosition.h in Headers */, @@ -26753,7 +26753,6 @@ 2D481F03146B5C6500AA7834 /* GeneratorGeneratedImage.cpp in Sources */, 0720B0A014D3323500642955 /* GenericEventQueue.cpp in Sources */, 9746AF2314F4DDE6003E7A70 /* Geolocation.cpp in Sources */, - 052BFCE9128ABF1500FD338D /* GeolocationClientMock.cpp in Sources */, 9746AF2614F4DDE6003E7A70 /* GeolocationController.cpp in Sources */, 0720B0A014D3323500642956 /* GestureEvent.cpp in Sources */, B2C3DA6D0D006CD600EF6F26 /* GlyphPageTreeNode.cpp in Sources */, @@ -28668,6 +28667,7 @@ E1BE512D0CF6C512002EA959 /* XSLTUnicodeSort.cpp in Sources */, 977E2E0E12F0FC9C00C13379 /* XSSAuditor.cpp in Sources */, FD537352137B651800008DCE /* ZeroPole.cpp in Sources */, + E47E276816036EDC00EE2AFB /* DocumentStyleSheetCollection.cpp in Sources */, 4F1D11BF15FF37200026E908 /* PlatformMemoryInstrumentation.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.h b/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.h index fa5945843..33a7e6fe5 100644 --- a/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.h +++ b/Source/WebCore/bindings/generic/RuntimeEnabledFeatures.h @@ -61,16 +61,7 @@ public: static void setWebkitIndexedDBEnabled(bool isEnabled) { isIndexedDBEnabled = isEnabled; } static bool webkitIndexedDBEnabled() { return isIndexedDBEnabled; } - static bool webkitIDBCursorEnabled() { return isIndexedDBEnabled; } - static bool webkitIDBDatabaseEnabled() { return isIndexedDBEnabled; } - static bool webkitIDBDatabaseErrorEnabled() { return isIndexedDBEnabled; } - static bool webkitIDBDatabaseExceptionEnabled() { return isIndexedDBEnabled; } - static bool webkitIDBFactoryEnabled() { return isIndexedDBEnabled; } - static bool webkitIDBIndexEnabled() { return isIndexedDBEnabled; } - static bool webkitIDBKeyRangeEnabled() { return isIndexedDBEnabled; } - static bool webkitIDBObjectStoreEnabled() { return isIndexedDBEnabled; } - static bool webkitIDBRequestEnabled() { return isIndexedDBEnabled; } - static bool webkitIDBTransactionEnabled() { return isIndexedDBEnabled; } + static bool indexedDBEnabled() { return isIndexedDBEnabled; } #if ENABLE(CSS_EXCLUSIONS) static void setCSSExclusionsEnabled(bool isEnabled) { isCSSExclusionsEnabled = isEnabled; } diff --git a/Source/WebCore/bindings/js/JSDOMWindowShell.h b/Source/WebCore/bindings/js/JSDOMWindowShell.h index 9fe38ea41..fccc703e1 100644 --- a/Source/WebCore/bindings/js/JSDOMWindowShell.h +++ b/Source/WebCore/bindings/js/JSDOMWindowShell.h @@ -48,6 +48,7 @@ namespace WebCore { { ASSERT_ARG(window, window); setUnwrappedObject(globalData, window); + structure()->setGlobalObject(*JSDOMWindow::commonJSGlobalData(), window); } void setWindow(PassRefPtr<DOMWindow>); diff --git a/Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp index 556bdf75f..72bf386a0 100644 --- a/Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp @@ -29,11 +29,11 @@ #include "CanvasContextAttributes.h" #include "HTMLCanvasElement.h" +#include "InspectorCanvasInstrumentation.h" #include "JSCanvasRenderingContext2D.h" +#include "ScriptObject.h" #if ENABLE(WEBGL) -#include "InspectorCanvasInstrumentation.h" #include "JSWebGLRenderingContext.h" -#include "ScriptObject.h" #include "WebGLContextAttributes.h" #endif #include <wtf/GetPtr.h> @@ -78,14 +78,18 @@ JSValue JSHTMLCanvasElement::getContext(ExecState* exec) if (!context) return jsNull(); JSValue jsValue = toJS(exec, globalObject(), WTF::getPtr(context)); + if (InspectorInstrumentation::hasFrontends()) { + ScriptObject contextObject(exec, jsValue.getObject()); + ScriptObject wrapped; + if (context->is2d()) + wrapped = InspectorInstrumentation::wrapCanvas2DRenderingContextForInstrumentation(canvas->document(), contextObject); #if ENABLE(WEBGL) - if (context->is3d() && InspectorInstrumentation::hasFrontends()) { - ScriptObject glContext(exec, jsValue.getObject()); - ScriptObject wrapped = InspectorInstrumentation::wrapWebGLRenderingContextForInstrumentation(canvas->document(), glContext); + else if (context->is3d()) + wrapped = InspectorInstrumentation::wrapWebGLRenderingContextForInstrumentation(canvas->document(), contextObject); +#endif if (!wrapped.hasNoValue()) return wrapped.jsValue(); } -#endif return jsValue; } diff --git a/Source/WebCore/bindings/js/JSInjectedScriptManager.cpp b/Source/WebCore/bindings/js/JSInjectedScriptManager.cpp index dc502fc8d..9f9109849 100644 --- a/Source/WebCore/bindings/js/JSInjectedScriptManager.cpp +++ b/Source/WebCore/bindings/js/JSInjectedScriptManager.cpp @@ -59,7 +59,13 @@ ScriptObject InjectedScriptManager::createInjectedScript(const String& source, S JSValue globalThisValue = scriptState->globalThisValue(); JSValue evaluationException; - JSValue evaluationReturnValue = JSMainThreadExecState::evaluate(scriptState, sourceCode, globalThisValue, &evaluationException); + JSValue evaluationReturnValue; + if (isMainThread()) + evaluationReturnValue = JSMainThreadExecState::evaluate(scriptState, sourceCode, globalThisValue, &evaluationException); + else { + JSC::JSLockHolder lock(scriptState); + evaluationReturnValue = JSC::evaluate(scriptState, sourceCode, globalThisValue, &evaluationException); + } if (evaluationException) return ScriptObject(); diff --git a/Source/WebCore/bindings/js/ScriptFunctionCall.cpp b/Source/WebCore/bindings/js/ScriptFunctionCall.cpp index e52842e0b..be91d5cdc 100644 --- a/Source/WebCore/bindings/js/ScriptFunctionCall.cpp +++ b/Source/WebCore/bindings/js/ScriptFunctionCall.cpp @@ -135,7 +135,12 @@ ScriptValue ScriptFunctionCall::call(bool& hadException, bool reportExceptions) if (callType == CallTypeNone) return ScriptValue(); - JSValue result = JSMainThreadExecState::call(m_exec, function, callType, callData, thisObject, m_arguments); + JSValue result; + if (isMainThread()) + result = JSMainThreadExecState::call(m_exec, function, callType, callData, thisObject, m_arguments); + else + result = JSC::call(m_exec, function, callType, callData, thisObject, m_arguments); + if (m_exec->hadException()) { if (reportExceptions) reportException(m_exec, m_exec->exception()); diff --git a/Source/WebCore/bindings/js/SerializedScriptValue.cpp b/Source/WebCore/bindings/js/SerializedScriptValue.cpp index 6ae5e3803..02f8cff66 100644 --- a/Source/WebCore/bindings/js/SerializedScriptValue.cpp +++ b/Source/WebCore/bindings/js/SerializedScriptValue.cpp @@ -1320,7 +1320,7 @@ private: void putProperty(JSObject* object, const Identifier& property, JSValue value) { - object->putDirect(m_exec->globalData(), property, value); + object->putDirectMayBeIndex(m_exec, property, value); } bool readFile(RefPtr<File>& file) diff --git a/Source/WebCore/bindings/scripts/CodeGeneratorGObject.pm b/Source/WebCore/bindings/scripts/CodeGeneratorGObject.pm index c84087b19..5d8af4a0e 100644 --- a/Source/WebCore/bindings/scripts/CodeGeneratorGObject.pm +++ b/Source/WebCore/bindings/scripts/CodeGeneratorGObject.pm @@ -203,7 +203,7 @@ sub SkipAttribute { } # Skip indexed database attributes for now, they aren't yet supported for the GObject generator. - if ($attribute->signature->name =~ /^webkitIndexedDB/ or $attribute->signature->name =~ /^webkitIDB/) { + if ($attribute->signature->name =~ /^(?:webkit)?[Ii]ndexedDB/ or $attribute->signature->name =~ /^(?:webkit)?IDB/) { return 1; } diff --git a/Source/WebCore/bindings/v8/V8PerIsolateData.cpp b/Source/WebCore/bindings/v8/V8PerIsolateData.cpp index e1bc31e5c..4e1e0a1f5 100644 --- a/Source/WebCore/bindings/v8/V8PerIsolateData.cpp +++ b/Source/WebCore/bindings/v8/V8PerIsolateData.cpp @@ -28,6 +28,7 @@ #include "ScriptGCEvent.h" #include "V8Binding.h" +#include <wtf/MemoryInstrumentationVector.h> namespace WebCore { @@ -87,7 +88,7 @@ void V8PerIsolateData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) con info.addHashMap(m_rawTemplates); info.addHashMap(m_templates); info.addMember(m_stringCache); - info.addVector(m_domDataList); + info.addMember(m_domDataList); for (size_t i = 0; i < m_domDataList.size(); i++) info.addMember(m_domDataList[i]); diff --git a/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.h b/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.h index 1ce2bebd1..615584438 100644 --- a/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.h +++ b/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.h @@ -52,6 +52,7 @@ v8::Handle<v8::Value> wrapArrayBufferView(const v8::Arguments& args, WrapperType { // Transform the holder into a wrapper object for the array. V8DOMWrapper::setDOMWrapper(args.Holder(), type, array.get()); + ASSERT(!hasIndexer || static_cast<int32_t>(array.get()->length()) >= 0); if (hasIndexer) args.Holder()->SetIndexedPropertiesToExternalArrayData(array.get()->baseAddress(), arrayType, array.get()->length()); v8::Handle<v8::Object> wrapper = args.Holder(); @@ -85,6 +86,10 @@ v8::Handle<v8::Value> constructWebGLArrayWithArrayBufferArgument(const v8::Argum return throwError(RangeError, "ArrayBuffer length minus the byteOffset is not a multiple of the element size.", args.GetIsolate()); length = (buf->byteLength() - offset) / sizeof(ElementType); } + + if (static_cast<int32_t>(length) < 0) + return throwError(RangeError, tooLargeSize, args.GetIsolate()); + RefPtr<ArrayClass> array = ArrayClass::create(buf, offset, length); if (!array) return throwError(RangeError, tooLargeSize, args.GetIsolate()); @@ -143,6 +148,10 @@ v8::Handle<v8::Value> constructWebGLArray(const v8::Arguments& args, WrapperType if (JavaScriptWrapperArrayType::HasInstance(args[0])) { ArrayClass* source = JavaScriptWrapperArrayType::toNative(args[0]->ToObject()); uint32_t length = source->length(); + + if (static_cast<int32_t>(length) < 0) + return throwError(RangeError, tooLargeSize, args.GetIsolate()); + RefPtr<ArrayClass> array = ArrayClass::createUninitialized(length); if (!array.get()) return throwError(RangeError, tooLargeSize, args.GetIsolate()); @@ -174,6 +183,9 @@ v8::Handle<v8::Value> constructWebGLArray(const v8::Arguments& args, WrapperType } } + if (static_cast<int32_t>(len) < 0) + return throwError(RangeError, tooLargeSize, args.GetIsolate()); + RefPtr<ArrayClass> array; if (doInstantiation) { if (srcArray.IsEmpty()) diff --git a/Source/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp b/Source/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp index 0b157279c..a6fb22a44 100644 --- a/Source/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp +++ b/Source/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp @@ -35,12 +35,12 @@ #include "CanvasContextAttributes.h" #include "CanvasRenderingContext.h" #include "HTMLCanvasElement.h" +#include "InspectorCanvasInstrumentation.h" #include "WebGLContextAttributes.h" #include "V8Binding.h" #include "V8CanvasRenderingContext2D.h" #include "V8Node.h" #if ENABLE(WEBGL) -#include "InspectorCanvasInstrumentation.h" #include "V8WebGLRenderingContext.h" #endif #include <wtf/MathExtras.h> @@ -85,9 +85,17 @@ v8::Handle<v8::Value> V8HTMLCanvasElement::getContextCallback(const v8::Argument CanvasRenderingContext* result = imp->getContext(contextId, attrs.get()); if (!result) return v8::Null(args.GetIsolate()); - - if (result->is2d()) - return toV8(static_cast<CanvasRenderingContext2D*>(result), args.Holder(), args.GetIsolate()); + else if (result->is2d()) { + v8::Handle<v8::Value> v8Result = toV8(static_cast<CanvasRenderingContext2D*>(result), args.Holder(), args.GetIsolate()); + if (InspectorInstrumentation::hasFrontends()) { + ScriptState* scriptState = ScriptState::forContext(v8::Context::GetCurrent()); + ScriptObject context(scriptState, v8::Handle<v8::Object>::Cast(v8Result)); + ScriptObject wrapped = InspectorInstrumentation::wrapCanvas2DRenderingContextForInstrumentation(imp->document(), context); + if (!wrapped.hasNoValue()) + return wrapped.v8Value(); + } + return v8Result; + } #if ENABLE(WEBGL) else if (result->is3d()) { // 3D canvas contexts can hold on to lots of GPU resources, and we want to take an diff --git a/Source/WebCore/css/CSSGradientValue.cpp b/Source/WebCore/css/CSSGradientValue.cpp index f9715f27f..d00c1308e 100644 --- a/Source/WebCore/css/CSSGradientValue.cpp +++ b/Source/WebCore/css/CSSGradientValue.cpp @@ -37,6 +37,7 @@ #include "RenderObject.h" #include "StyleResolver.h" #include "WebCoreMemoryInstrumentation.h" +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/text/StringBuilder.h> #include <wtf/text/WTFString.h> @@ -469,7 +470,7 @@ void CSSGradientValue::reportBaseClassMemoryUsage(MemoryObjectInfo* memoryObject info.addMember(m_firstY); info.addMember(m_secondX); info.addMember(m_secondY); - info.addInstrumentedVector(m_stops); + info.addMember(m_stops); } String CSSLinearGradientValue::customCssText() const diff --git a/Source/WebCore/css/CSSImageSetValue.cpp b/Source/WebCore/css/CSSImageSetValue.cpp index 5e6bee5a6..6e02a20f9 100644 --- a/Source/WebCore/css/CSSImageSetValue.cpp +++ b/Source/WebCore/css/CSSImageSetValue.cpp @@ -37,6 +37,7 @@ #include "StyleCachedImageSet.h" #include "StylePendingImage.h" #include "WebCoreMemoryInstrumentation.h" +#include <wtf/MemoryInstrumentationVector.h> namespace WebCore { @@ -168,7 +169,7 @@ void CSSImageSetValue::reportDescendantMemoryUsage(MemoryObjectInfo* memoryObjec { MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); CSSValueList::reportDescendantMemoryUsage(memoryObjectInfo); - info.addInstrumentedVector(m_imagesInSet); + info.addMember(m_imagesInSet); } void CSSImageSetValue::ImageWithScale::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const diff --git a/Source/WebCore/css/CSSMediaRule.cpp b/Source/WebCore/css/CSSMediaRule.cpp index f0e9c79c3..8c2c973c2 100644 --- a/Source/WebCore/css/CSSMediaRule.cpp +++ b/Source/WebCore/css/CSSMediaRule.cpp @@ -29,6 +29,7 @@ #include "ExceptionCode.h" #include "StyleRule.h" #include "WebCoreMemoryInstrumentation.h" +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/text/StringBuilder.h> namespace WebCore { @@ -180,7 +181,7 @@ void CSSMediaRule::reportDescendantMemoryUsage(MemoryObjectInfo* memoryObjectInf MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); CSSRule::reportBaseClassMemoryUsage(memoryObjectInfo); info.addMember(m_mediaCSSOMWrapper); - info.addInstrumentedVector(m_childRuleCSSOMWrappers); + info.addMember(m_childRuleCSSOMWrappers); info.addMember(m_ruleListCSSOMWrapper); } diff --git a/Source/WebCore/css/CSSParser.cpp b/Source/WebCore/css/CSSParser.cpp index efd9bae3a..9a922f191 100644 --- a/Source/WebCore/css/CSSParser.cpp +++ b/Source/WebCore/css/CSSParser.cpp @@ -5994,7 +5994,7 @@ bool CSSParser::parseFlex(CSSParserValueList* args, bool important) } if (flexGrow == unsetValue) - flexGrow = 0; + flexGrow = 1; if (flexShrink == unsetValue) flexShrink = 1; if (!flexBasis) diff --git a/Source/WebCore/css/CSSParserValues.h b/Source/WebCore/css/CSSParserValues.h index ad11198be..83aa77c33 100644 --- a/Source/WebCore/css/CSSParserValues.h +++ b/Source/WebCore/css/CSSParserValues.h @@ -46,7 +46,7 @@ struct CSSParserString { m_is8Bit = false; } - void init(String string) + void init(const String& string) { m_length = string.length(); if (m_length && string.is8Bit()) { diff --git a/Source/WebCore/css/CSSRule.cpp b/Source/WebCore/css/CSSRule.cpp index b61f3fe65..cd533d9a8 100644 --- a/Source/WebCore/css/CSSRule.cpp +++ b/Source/WebCore/css/CSSRule.cpp @@ -40,11 +40,7 @@ namespace WebCore { struct SameSizeAsCSSRule : public RefCounted<SameSizeAsCSSRule> { -#if USE(JSC) - char bitfields; -#else - unsigned bitfields; -#endif + unsigned char bitfields; void* pointerUnion; }; diff --git a/Source/WebCore/css/CSSRule.h b/Source/WebCore/css/CSSRule.h index c3bfcab01..b31fe7b8d 100644 --- a/Source/WebCore/css/CSSRule.h +++ b/Source/WebCore/css/CSSRule.h @@ -127,9 +127,9 @@ protected: void reportBaseClassMemoryUsage(MemoryObjectInfo*) const; private: - mutable unsigned m_hasCachedSelectorText : 1; - unsigned m_parentIsRule : 1; - unsigned m_type : 5; + mutable unsigned char m_hasCachedSelectorText : 1; + unsigned char m_parentIsRule : 1; + unsigned char m_type : 5; union { CSSRule* m_parentRule; CSSStyleSheet* m_parentStyleSheet; diff --git a/Source/WebCore/css/CSSRuleList.cpp b/Source/WebCore/css/CSSRuleList.cpp index 472b3dd60..dadc93b15 100644 --- a/Source/WebCore/css/CSSRuleList.cpp +++ b/Source/WebCore/css/CSSRuleList.cpp @@ -24,6 +24,7 @@ #include "CSSRule.h" #include "CSSStyleSheet.h" +#include <wtf/MemoryInstrumentationVector.h> namespace WebCore { @@ -54,7 +55,7 @@ void StaticCSSRuleList::deref() void StaticCSSRuleList::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); - info.addInstrumentedVector(m_rules); + info.addMember(m_rules); } } // namespace WebCore diff --git a/Source/WebCore/css/CSSSelector.cpp b/Source/WebCore/css/CSSSelector.cpp index 5c26256a8..62233e6d4 100644 --- a/Source/WebCore/css/CSSSelector.cpp +++ b/Source/WebCore/css/CSSSelector.cpp @@ -183,7 +183,6 @@ PseudoId CSSSelector::pseudoId(PseudoType type) case PseudoValid: case PseudoInvalid: case PseudoIndeterminate: - case PseudoScope: case PseudoTarget: case PseudoLang: case PseudoNot: @@ -265,7 +264,6 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap( DEFINE_STATIC_LOCAL(AtomicString, scrollbarTrack, ("-webkit-scrollbar-track", AtomicString::ConstructFromLiteral)); DEFINE_STATIC_LOCAL(AtomicString, scrollbarTrackPiece, ("-webkit-scrollbar-track-piece", AtomicString::ConstructFromLiteral)); DEFINE_STATIC_LOCAL(AtomicString, selection, ("selection", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, scope, ("scope", AtomicString::ConstructFromLiteral)); DEFINE_STATIC_LOCAL(AtomicString, target, ("target", AtomicString::ConstructFromLiteral)); DEFINE_STATIC_LOCAL(AtomicString, visited, ("visited", AtomicString::ConstructFromLiteral)); DEFINE_STATIC_LOCAL(AtomicString, windowInactive, ("window-inactive", AtomicString::ConstructFromLiteral)); @@ -353,7 +351,6 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap( nameToPseudoType->set(scrollbarTrackPiece.impl(), CSSSelector::PseudoScrollbarTrackPiece); nameToPseudoType->set(cornerPresent.impl(), CSSSelector::PseudoCornerPresent); nameToPseudoType->set(selection.impl(), CSSSelector::PseudoSelection); - nameToPseudoType->set(scope.impl(), CSSSelector::PseudoScope); nameToPseudoType->set(target.impl(), CSSSelector::PseudoTarget); nameToPseudoType->set(visited.impl(), CSSSelector::PseudoVisited); nameToPseudoType->set(firstPage.impl(), CSSSelector::PseudoFirstPage); @@ -445,7 +442,6 @@ void CSSSelector::extractPseudoType() const case PseudoValid: case PseudoInvalid: case PseudoIndeterminate: - case PseudoScope: case PseudoTarget: case PseudoLang: case PseudoNot: diff --git a/Source/WebCore/css/CSSSelector.h b/Source/WebCore/css/CSSSelector.h index 2e9e5908f..5ca24f4e0 100644 --- a/Source/WebCore/css/CSSSelector.h +++ b/Source/WebCore/css/CSSSelector.h @@ -116,7 +116,6 @@ namespace WebCore { PseudoValid, PseudoInvalid, PseudoIndeterminate, - PseudoScope, PseudoTarget, PseudoBefore, PseudoAfter, diff --git a/Source/WebCore/css/CSSStyleSheet.cpp b/Source/WebCore/css/CSSStyleSheet.cpp index 0e10202c7..dcfc22006 100644 --- a/Source/WebCore/css/CSSStyleSheet.cpp +++ b/Source/WebCore/css/CSSStyleSheet.cpp @@ -38,6 +38,7 @@ #include "StyleRule.h" #include "StyleSheetContents.h" #include "WebCoreMemoryInstrumentation.h" +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/text/StringBuilder.h> namespace WebCore { @@ -187,7 +188,7 @@ void CSSStyleSheet::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const info.addMember(m_ownerNode); info.addMember(m_ownerRule); info.addMember(m_mediaCSSOMWrapper); - info.addInstrumentedVector(m_childRuleCSSOMWrappers); + info.addMember(m_childRuleCSSOMWrappers); } void CSSStyleSheet::setDisabled(bool disabled) diff --git a/Source/WebCore/css/CSSValueList.cpp b/Source/WebCore/css/CSSValueList.cpp index 21e4fa703..9ec2d5085 100644 --- a/Source/WebCore/css/CSSValueList.cpp +++ b/Source/WebCore/css/CSSValueList.cpp @@ -23,6 +23,7 @@ #include "CSSParserValues.h" #include "WebCoreMemoryInstrumentation.h" +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/PassOwnPtr.h> #include <wtf/text/StringBuilder.h> @@ -189,7 +190,7 @@ PassRefPtr<CSSValueList> CSSValueList::cloneForCSSOM() const void CSSValueList::reportDescendantMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); - info.addInstrumentedVector(m_values); + info.addMember(m_values); } } // namespace WebCore diff --git a/Source/WebCore/css/MediaList.cpp b/Source/WebCore/css/MediaList.cpp index 62903d6b1..bdbc57174 100644 --- a/Source/WebCore/css/MediaList.cpp +++ b/Source/WebCore/css/MediaList.cpp @@ -27,6 +27,7 @@ #include "MediaQuery.h" #include "MediaQueryExp.h" #include "WebCoreMemoryInstrumentation.h" +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/text/StringBuilder.h> namespace WebCore { @@ -215,7 +216,7 @@ String MediaQuerySet::mediaText() const void MediaQuerySet::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); - info.addInstrumentedVector(m_queries); + info.addMember(m_queries); } MediaList::MediaList(MediaQuerySet* mediaQueries, CSSStyleSheet* parentSheet) diff --git a/Source/WebCore/css/MediaQuery.cpp b/Source/WebCore/css/MediaQuery.cpp index a3f25d712..fc4551ffb 100644 --- a/Source/WebCore/css/MediaQuery.cpp +++ b/Source/WebCore/css/MediaQuery.cpp @@ -31,6 +31,7 @@ #include "MediaQueryExp.h" #include "WebCoreMemoryInstrumentation.h" +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/NonCopyingSort.h> #include <wtf/text/StringBuilder.h> @@ -138,7 +139,7 @@ void MediaQuery::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); info.addMember(m_mediaType); - info.addInstrumentedVectorPtr(m_expressions); + info.addMember(m_expressions); info.addMember(m_serializationCache); } diff --git a/Source/WebCore/css/SelectorChecker.cpp b/Source/WebCore/css/SelectorChecker.cpp index 133e2a8aa..aae47e2cf 100644 --- a/Source/WebCore/css/SelectorChecker.cpp +++ b/Source/WebCore/css/SelectorChecker.cpp @@ -31,6 +31,7 @@ #include "CSSSelector.h" #include "CSSSelectorList.h" #include "Document.h" +#include "DocumentStyleSheetCollection.h" #include "FocusController.h" #include "Frame.h" #include "FrameSelection.h" @@ -783,7 +784,7 @@ bool SelectorChecker::checkOneSelector(const SelectorCheckingContext& context, P if (m_mode == ResolvingStyle) { if (context.elementStyle) context.elementStyle->setEmptyState(result); - else if (element->renderStyle() && (element->document()->usesSiblingRules() || element->renderStyle()->unique())) + else if (element->renderStyle() && (element->document()->styleSheetCollection()->usesSiblingRules() || element->renderStyle()->unique())) element->renderStyle()->setEmptyState(result); } return result; @@ -1115,10 +1116,6 @@ bool SelectorChecker::checkOneSelector(const SelectorCheckingContext& context, P return true; break; } - case CSSSelector::PseudoScope: - if (context.scope) - return element == context.scope; - // If there is no scope, :scope should behave as :root -> fall through case CSSSelector::PseudoRoot: if (element == element->document()->documentElement()) return true; @@ -1187,7 +1184,7 @@ bool SelectorChecker::checkOneSelector(const SelectorCheckingContext& context, P PseudoId pseudoId = CSSSelector::pseudoId(selector->pseudoType()); if (pseudoId == FIRST_LETTER) { if (Document* document = element->document()) - document->setUsesFirstLetterRules(true); + document->styleSheetCollection()->setUsesFirstLetterRules(true); } if (pseudoId != NOPSEUDO) dynamicPseudo = pseudoId; diff --git a/Source/WebCore/css/StylePropertySet.cpp b/Source/WebCore/css/StylePropertySet.cpp index 6e3c0fde9..52e4a24d7 100644 --- a/Source/WebCore/css/StylePropertySet.cpp +++ b/Source/WebCore/css/StylePropertySet.cpp @@ -19,8 +19,6 @@ * Boston, MA 02110-1301, USA. */ -#define WTF_DEPRECATED_STRING_OPERATORS - #include "config.h" #include "StylePropertySet.h" @@ -33,6 +31,7 @@ #include "StylePropertyShorthand.h" #include "StyleSheetContents.h" #include <wtf/BitArray.h> +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/text/StringBuilder.h> #ifndef NDEBUG @@ -1123,7 +1122,7 @@ void StylePropertySet::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) con size_t actualSize = m_isMutable ? sizeof(StylePropertySet) : immutableStylePropertySetSize(m_arraySize); MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS, actualSize); if (m_isMutable) - info.addVectorPtr(m_mutablePropertyVector); + info.addMember(m_mutablePropertyVector); unsigned count = propertyCount(); for (unsigned i = 0; i < count; ++i) diff --git a/Source/WebCore/css/StyleResolver.cpp b/Source/WebCore/css/StyleResolver.cpp index ec0c39c49..6ae35acf8 100644 --- a/Source/WebCore/css/StyleResolver.cpp +++ b/Source/WebCore/css/StyleResolver.cpp @@ -60,6 +60,7 @@ #include "Counter.h" #include "CounterContent.h" #include "CursorList.h" +#include "DocumentStyleSheetCollection.h" #include "FontFeatureValue.h" #include "FontValue.h" #include "Frame.h" @@ -125,6 +126,7 @@ #include "WebKitCSSTransformValue.h" #include "WebKitFontFamilyNames.h" #include "XMLNames.h" +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/StdLibExtras.h> #include <wtf/Vector.h> @@ -428,12 +430,13 @@ StyleResolver::StyleResolver(Document* document, bool matchAuthorAndUserStyles) // Note that there usually is only 1 sheet for scoped rules, so auto-shrink-to-fit is fine. m_authorStyle->disableAutoShrinkToFit(); + DocumentStyleSheetCollection* styleSheetCollection = document->styleSheetCollection(); // FIXME: This sucks! The user sheet is reparsed every time! OwnPtr<RuleSet> tempUserStyle = RuleSet::create(); - if (CSSStyleSheet* pageUserSheet = document->pageUserSheet()) + if (CSSStyleSheet* pageUserSheet = styleSheetCollection->pageUserSheet()) tempUserStyle->addRulesFromSheet(pageUserSheet->contents(), *m_medium, this); - addAuthorRulesAndCollectUserRulesFromSheets(document->pageGroupUserSheets(), *tempUserStyle); - addAuthorRulesAndCollectUserRulesFromSheets(document->documentUserSheets(), *tempUserStyle); + addAuthorRulesAndCollectUserRulesFromSheets(styleSheetCollection->pageGroupUserSheets(), *tempUserStyle); + addAuthorRulesAndCollectUserRulesFromSheets(styleSheetCollection->documentUserSheets(), *tempUserStyle); if (tempUserStyle->m_ruleCount > 0 || tempUserStyle->m_pageRules.size() > 0) m_userStyle = tempUserStyle.release(); @@ -447,7 +450,7 @@ StyleResolver::StyleResolver(Document* document, bool matchAuthorAndUserStyles) #endif addStylesheetsFromSeamlessParents(); - appendAuthorStylesheets(0, document->styleSheets()->vector()); + appendAuthorStylesheets(0, styleSheetCollection->authorStyleSheets()); } void StyleResolver::addStylesheetsFromSeamlessParents() @@ -455,14 +458,14 @@ void StyleResolver::addStylesheetsFromSeamlessParents() // Build a list of stylesheet lists from our ancestors, and walk that // list in reverse order so that the root-most sheets are appended first. Document* childDocument = document(); - Vector<StyleSheetList*> ancestorSheets; + Vector<const Vector<RefPtr<StyleSheet> >* > ancestorSheets; while (HTMLIFrameElement* parentIFrame = childDocument->seamlessParentIFrame()) { Document* parentDocument = parentIFrame->document(); - ancestorSheets.append(parentDocument->styleSheets()); + ancestorSheets.append(&parentDocument->styleSheetCollection()->authorStyleSheets()); childDocument = parentDocument; } for (int i = ancestorSheets.size() - 1; i >= 0; i--) - appendAuthorStylesheets(0, ancestorSheets.at(i)->vector()); + appendAuthorStylesheets(0, *ancestorSheets[i]); } void StyleResolver::addAuthorRulesAndCollectUserRulesFromSheets(const Vector<RefPtr<CSSStyleSheet> >* userSheets, RuleSet& userStyle) @@ -708,7 +711,6 @@ void StyleResolver::sweepMatchedPropertiesCache() StyleResolver::Features::Features() : usesFirstLineRules(false) , usesBeforeAfterRules(false) - , usesLinkRules(false) { } @@ -728,7 +730,6 @@ void StyleResolver::Features::add(const StyleResolver::Features& other) uncommonAttributeRules.append(other.uncommonAttributeRules); usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules; usesBeforeAfterRules = usesBeforeAfterRules || other.usesBeforeAfterRules; - usesLinkRules = usesLinkRules || other.usesLinkRules; } void StyleResolver::Features::clear() @@ -739,7 +740,6 @@ void StyleResolver::Features::clear() uncommonAttributeRules.clear(); usesFirstLineRules = false; usesBeforeAfterRules = false; - usesLinkRules = false; } void StyleResolver::Features::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const @@ -747,8 +747,8 @@ void StyleResolver::Features::reportMemoryUsage(MemoryObjectInfo* memoryObjectIn MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); info.addHashSet(idsInRules); info.addHashSet(attrsInRules); - info.addVector(siblingRules); - info.addVector(uncommonAttributeRules); + info.addMember(siblingRules); + info.addMember(uncommonAttributeRules); } static StyleSheetContents* parseUASheet(const String& str) @@ -2568,7 +2568,7 @@ static void reportAtomRuleMap(MemoryClassInfo* info, const RuleSet::AtomRuleMap& { info->addHashMap(atomicRuleMap); for (RuleSet::AtomRuleMap::const_iterator it = atomicRuleMap.begin(); it != atomicRuleMap.end(); ++it) - info->addInstrumentedVector(*it->second); + info->addMember(*it->second); } void RuleSet::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const @@ -2578,11 +2578,11 @@ void RuleSet::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const reportAtomRuleMap(&info, m_classRules); reportAtomRuleMap(&info, m_tagRules); reportAtomRuleMap(&info, m_shadowPseudoElementRules); - info.addInstrumentedVector(m_linkPseudoClassRules); - info.addInstrumentedVector(m_focusPseudoClassRules); - info.addInstrumentedVector(m_universalRules); - info.addVector(m_pageRules); - info.addInstrumentedVector(m_regionSelectorsAndRuleSets); + info.addMember(m_linkPseudoClassRules); + info.addMember(m_focusPseudoClassRules); + info.addMember(m_universalRules); + info.addMember(m_pageRules); + info.addMember(m_regionSelectorsAndRuleSets); } void RuleSet::RuleSetSelectorPair::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const @@ -2605,10 +2605,6 @@ static inline void collectFeaturesFromSelector(StyleResolver::Features& features case CSSSelector::PseudoAfter: features.usesBeforeAfterRules = true; break; - case CSSSelector::PseudoLink: - case CSSSelector::PseudoVisited: - features.usesLinkRules = true; - break; default: break; } @@ -3181,25 +3177,25 @@ static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >& wra collectCSSOMWrappers(wrapperMap, styleSheetWrapper.get()); } -static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >& wrapperMap, Document* document) +static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >& wrapperMap, DocumentStyleSheetCollection* styleSheetCollection) { - const Vector<RefPtr<StyleSheet> >& styleSheets = document->styleSheets()->vector(); + const Vector<RefPtr<StyleSheet> >& styleSheets = styleSheetCollection->authorStyleSheets(); for (unsigned i = 0; i < styleSheets.size(); ++i) { StyleSheet* styleSheet = styleSheets[i].get(); if (!styleSheet->isCSSStyleSheet()) continue; collectCSSOMWrappers(wrapperMap, static_cast<CSSStyleSheet*>(styleSheet)); } - collectCSSOMWrappers(wrapperMap, document->pageUserSheet()); + collectCSSOMWrappers(wrapperMap, styleSheetCollection->pageUserSheet()); { - const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets = document->pageGroupUserSheets(); + const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets = styleSheetCollection->pageGroupUserSheets(); if (pageGroupUserSheets) { for (size_t i = 0, size = pageGroupUserSheets->size(); i < size; ++i) collectCSSOMWrappers(wrapperMap, pageGroupUserSheets->at(i).get()); } } { - const Vector<RefPtr<CSSStyleSheet> >* documentUserSheets = document->documentUserSheets(); + const Vector<RefPtr<CSSStyleSheet> >* documentUserSheets = styleSheetCollection->documentUserSheets(); if (documentUserSheets) { for (size_t i = 0, size = documentUserSheets->size(); i < size; ++i) collectCSSOMWrappers(wrapperMap, documentUserSheets->at(i).get()); @@ -3218,7 +3214,7 @@ CSSStyleRule* StyleResolver::ensureFullCSSOMWrapperForInspector(StyleRule* rule) collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, m_styleSheetCSSOMWrapperSet, mediaControlsStyleSheet); collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, m_styleSheetCSSOMWrapperSet, fullscreenStyleSheet); - collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, document()); + collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, document()->styleSheetCollection()); } return m_styleRuleToCSSOMWrapperMap.get(rule).get(); } @@ -5767,7 +5763,7 @@ void StyleResolver::MatchedProperties::reportMemoryUsage(MemoryObjectInfo* memor void StyleResolver::MatchedPropertiesCacheItem::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); - info.addInstrumentedVector(matchedProperties); + info.addMember(matchedProperties); } void MediaQueryResult::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const @@ -5787,13 +5783,13 @@ void StyleResolver::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const info.addHashMap(m_keyframesRuleMap); info.addHashMap(m_matchedPropertiesCache); info.addInstrumentedMapValues(m_matchedPropertiesCache); - info.addVector(m_matchedRules); + info.addMember(m_matchedRules); info.addMember(m_ruleList); info.addHashMap(m_pendingImageProperties); info.addInstrumentedMapValues(m_pendingImageProperties); info.addMember(m_lineHeightValue); - info.addInstrumentedVector(m_viewportDependentMediaQueryResults); + info.addMember(m_viewportDependentMediaQueryResults); info.addHashMap(m_styleRuleToCSSOMWrapperMap); info.addInstrumentedMapEntries(m_styleRuleToCSSOMWrapperMap); info.addInstrumentedHashSet(m_styleSheetCSSOMWrapperSet); @@ -5803,7 +5799,7 @@ void StyleResolver::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const #if ENABLE(STYLE_SCOPED) info.addHashMap(m_scopedAuthorStyles); info.addInstrumentedMapEntries(m_scopedAuthorStyles); - info.addVector(m_scopeStack); + info.addMember(m_scopeStack); #endif // FIXME: move this to a place where it would be called only once? diff --git a/Source/WebCore/css/StyleResolver.h b/Source/WebCore/css/StyleResolver.h index 9c6fe1d3c..2e530f0e5 100644 --- a/Source/WebCore/css/StyleResolver.h +++ b/Source/WebCore/css/StyleResolver.h @@ -244,7 +244,6 @@ public: bool usesSiblingRules() const { return !m_features.siblingRules.isEmpty(); } bool usesFirstLineRules() const { return m_features.usesFirstLineRules; } bool usesBeforeAfterRules() const { return m_features.usesBeforeAfterRules; } - bool usesLinkRules() const { return m_features.usesLinkRules; } static bool createTransformOperations(CSSValue* inValue, RenderStyle* inStyle, RenderStyle* rootStyle, TransformOperations& outOperations); @@ -297,7 +296,6 @@ public: Vector<RuleFeature> uncommonAttributeRules; bool usesFirstLineRules; bool usesBeforeAfterRules; - bool usesLinkRules; }; private: diff --git a/Source/WebCore/css/StyleRule.cpp b/Source/WebCore/css/StyleRule.cpp index 5ece1b4a2..73b0af26c 100644 --- a/Source/WebCore/css/StyleRule.cpp +++ b/Source/WebCore/css/StyleRule.cpp @@ -33,6 +33,7 @@ #include "WebKitCSSKeyframeRule.h" #include "WebKitCSSKeyframesRule.h" #include "WebKitCSSRegionRule.h" +#include <wtf/MemoryInstrumentationVector.h> namespace WebCore { @@ -340,7 +341,7 @@ void StyleRuleBlock::wrapperRemoveRule(unsigned index) void StyleRuleBlock::reportDescendantMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); - info.addInstrumentedVector(m_childRules); + info.addMember(m_childRules); } StyleRuleMedia::StyleRuleMedia(PassRefPtr<MediaQuerySet> media, Vector<RefPtr<StyleRuleBase> >& adoptRules) diff --git a/Source/WebCore/css/StyleSheetContents.cpp b/Source/WebCore/css/StyleSheetContents.cpp index 048273bec..945f355a3 100644 --- a/Source/WebCore/css/StyleSheetContents.cpp +++ b/Source/WebCore/css/StyleSheetContents.cpp @@ -33,6 +33,7 @@ #include "StyleRuleImport.h" #include "WebCoreMemoryInstrumentation.h" #include <wtf/Deque.h> +#include <wtf/MemoryInstrumentationVector.h> namespace WebCore { @@ -489,10 +490,10 @@ void StyleSheetContents::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) c MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); info.addMember(m_originalURL); info.addMember(m_encodingFromCharsetRule); - info.addVector(m_importRules); - info.addInstrumentedVector(m_childRules); + info.addMember(m_importRules); + info.addMember(m_childRules); info.addHashMap(m_namespaces); - info.addVector(m_clients); + info.addMember(m_clients); } } diff --git a/Source/WebCore/css/StyleSheetList.cpp b/Source/WebCore/css/StyleSheetList.cpp index f1ab52dc9..0f8fc2517 100644 --- a/Source/WebCore/css/StyleSheetList.cpp +++ b/Source/WebCore/css/StyleSheetList.cpp @@ -23,6 +23,7 @@ #include "CSSStyleSheet.h" #include "Document.h" +#include "DocumentStyleSheetCollection.h" #include "HTMLNames.h" #include "HTMLStyleElement.h" #include <wtf/text/WTFString.h> @@ -31,8 +32,8 @@ namespace WebCore { using namespace HTMLNames; -StyleSheetList::StyleSheetList(Document* doc) - : m_doc(doc) +StyleSheetList::StyleSheetList(Document* document) + : m_document(document) { } @@ -40,24 +41,33 @@ StyleSheetList::~StyleSheetList() { } -void StyleSheetList::documentDestroyed() +inline const Vector<RefPtr<StyleSheet> >& StyleSheetList::styleSheets() const { - m_doc = 0; + if (!m_document) + return m_detachedStyleSheets; + return m_document->styleSheetCollection()->authorStyleSheets(); +} + +void StyleSheetList::detachFromDocument() +{ + m_detachedStyleSheets = m_document->styleSheetCollection()->authorStyleSheets(); + m_document = 0; } unsigned StyleSheetList::length() const { - return m_sheets.size(); + return styleSheets().size(); } StyleSheet* StyleSheetList::item(unsigned index) { - return index < length() ? m_sheets[index].get() : 0; + const Vector<RefPtr<StyleSheet> >& sheets = styleSheets(); + return index < sheets.size() ? sheets[index].get() : 0; } HTMLStyleElement* StyleSheetList::getNamedItem(const String& name) const { - if (!m_doc) + if (!m_document) return 0; // IE also supports retrieving a stylesheet by name, using the name/id of the <style> tag @@ -65,8 +75,7 @@ HTMLStyleElement* StyleSheetList::getNamedItem(const String& name) const // ### Bad implementation because returns a single element (are IDs always unique?) // and doesn't look for name attribute. // But unicity of stylesheet ids is good practice anyway ;) - - Element* element = m_doc->getElementById(name); + Element* element = m_document->getElementById(name); if (element && element->hasTagName(styleTag)) return static_cast<HTMLStyleElement*>(element); return 0; diff --git a/Source/WebCore/css/StyleSheetList.h b/Source/WebCore/css/StyleSheetList.h index 3f81163e6..c05284159 100644 --- a/Source/WebCore/css/StyleSheetList.h +++ b/Source/WebCore/css/StyleSheetList.h @@ -32,40 +32,26 @@ class Document; class HTMLStyleElement; class StyleSheet; -typedef Vector<RefPtr<StyleSheet> > StyleSheetVector; - class StyleSheetList : public RefCounted<StyleSheetList> { public: - static PassRefPtr<StyleSheetList> create(Document* doc) { return adoptRef(new StyleSheetList(doc)); } + static PassRefPtr<StyleSheetList> create(Document* document) { return adoptRef(new StyleSheetList(document)); } ~StyleSheetList(); - void documentDestroyed(); - unsigned length() const; StyleSheet* item(unsigned index); HTMLStyleElement* getNamedItem(const String&) const; - const StyleSheetVector& vector() const - { - return m_sheets; - } - - void swap(StyleSheetVector& sheets) - { - m_sheets.swap(sheets); - } + Document* document() { return m_document; } - Document* document() - { - return m_doc; - } + void detachFromDocument(); private: StyleSheetList(Document*); + const Vector<RefPtr<StyleSheet> >& styleSheets() const; - Document* m_doc; - StyleSheetVector m_sheets; + Document* m_document; + Vector<RefPtr<StyleSheet> > m_detachedStyleSheets; }; } // namespace WebCore diff --git a/Source/WebCore/css/WebKitCSSKeyframesRule.cpp b/Source/WebCore/css/WebKitCSSKeyframesRule.cpp index a2991a818..08fbb0a55 100644 --- a/Source/WebCore/css/WebKitCSSKeyframesRule.cpp +++ b/Source/WebCore/css/WebKitCSSKeyframesRule.cpp @@ -33,6 +33,7 @@ #include "StyleSheet.h" #include "WebCoreMemoryInstrumentation.h" #include "WebKitCSSKeyframeRule.h" +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/text/StringBuilder.h> namespace WebCore { @@ -90,7 +91,7 @@ int StyleRuleKeyframes::findKeyframeIndex(const String& key) const void StyleRuleKeyframes::reportDescendantMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); - info.addInstrumentedVector(m_keyframes); + info.addMember(m_keyframes); info.addMember(m_name); } @@ -211,7 +212,7 @@ void WebKitCSSKeyframesRule::reportDescendantMemoryUsage(MemoryObjectInfo* memor MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); CSSRule::reportBaseClassMemoryUsage(memoryObjectInfo); info.addMember(m_keyframesRule); - info.addInstrumentedVector(m_childRuleCSSOMWrappers); + info.addMember(m_childRuleCSSOMWrappers); info.addMember(m_ruleListCSSOMWrapper); } diff --git a/Source/WebCore/css/WebKitCSSRegionRule.cpp b/Source/WebCore/css/WebKitCSSRegionRule.cpp index 5c2c721cd..ce1207cab 100644 --- a/Source/WebCore/css/WebKitCSSRegionRule.cpp +++ b/Source/WebCore/css/WebKitCSSRegionRule.cpp @@ -34,6 +34,7 @@ #include "CSSParser.h" #include "CSSRuleList.h" #include "StyleRule.h" +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/text/StringBuilder.h> #if ENABLE(CSS_REGIONS) @@ -113,7 +114,7 @@ void WebKitCSSRegionRule::reportDescendantMemoryUsage(MemoryObjectInfo* memoryOb MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); CSSRule::reportBaseClassMemoryUsage(memoryObjectInfo); info.addMember(m_regionRule); - info.addInstrumentedVector(m_childRuleCSSOMWrappers); + info.addMember(m_childRuleCSSOMWrappers); info.addMember(m_ruleListCSSOMWrapper); } diff --git a/Source/WebCore/dom/CharacterData.idl b/Source/WebCore/dom/CharacterData.idl index 2bb3d4e49..bf8fef19f 100644 --- a/Source/WebCore/dom/CharacterData.idl +++ b/Source/WebCore/dom/CharacterData.idl @@ -45,7 +45,10 @@ module core { in [IsIndex,Optional=DefaultIsUndefined] unsigned long length, in [Optional=DefaultIsUndefined] DOMString data) raises(DOMException); - + + // DOM 4 + void remove() + raises(DOMException); }; } diff --git a/Source/WebCore/dom/ContainerNode.cpp b/Source/WebCore/dom/ContainerNode.cpp index cd118f17d..dafee6077 100644 --- a/Source/WebCore/dom/ContainerNode.cpp +++ b/Source/WebCore/dom/ContainerNode.cpp @@ -419,15 +419,15 @@ bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec) return false; } - RenderWidget::suspendWidgetHierarchyUpdates(); - - Node* prev = child->previousSibling(); - Node* next = child->nextSibling(); - removeBetween(prev, next, child.get()); - childrenChanged(false, prev, next, -1); - ChildNodeRemovalNotifier(this).notify(child.get()); - - RenderWidget::resumeWidgetHierarchyUpdates(); + { + WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; + + Node* prev = child->previousSibling(); + Node* next = child->nextSibling(); + removeBetween(prev, next, child.get()); + childrenChanged(false, prev, next, -1); + ChildNodeRemovalNotifier(this).notify(child.get()); + } dispatchSubtreeModifiedEvent(); return child; @@ -497,49 +497,50 @@ void ContainerNode::removeChildren() // and remove... e.g. stop loading frames, fire unload events. willRemoveChildren(protect.get()); - RenderWidget::suspendWidgetHierarchyUpdates(); - forbidEventDispatch(); Vector<RefPtr<Node>, 10> removedChildren; - removedChildren.reserveInitialCapacity(childNodeCount()); - while (RefPtr<Node> n = m_firstChild) { - Node* next = n->nextSibling(); - - // Remove the node from the tree before calling detach or removedFromDocument (4427024, 4129744). - // removeChild() does this after calling detach(). There is no explanation for - // this discrepancy between removeChild() and its optimized version removeChildren(). - n->setPreviousSibling(0); - n->setNextSibling(0); - n->setParentOrHostNode(0); - document()->adoptIfNeeded(n.get()); - - m_firstChild = next; - if (n == m_lastChild) - m_lastChild = 0; - removedChildren.append(n.release()); - } + { + WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; + forbidEventDispatch(); + removedChildren.reserveInitialCapacity(childNodeCount()); + while (RefPtr<Node> n = m_firstChild) { + Node* next = n->nextSibling(); + + // Remove the node from the tree before calling detach or removedFromDocument (4427024, 4129744). + // removeChild() does this after calling detach(). There is no explanation for + // this discrepancy between removeChild() and its optimized version removeChildren(). + n->setPreviousSibling(0); + n->setNextSibling(0); + n->setParentOrHostNode(0); + document()->adoptIfNeeded(n.get()); + + m_firstChild = next; + if (n == m_lastChild) + m_lastChild = 0; + removedChildren.append(n.release()); + } - size_t removedChildrenCount = removedChildren.size(); - size_t i; - - // Detach the nodes only after properly removed from the tree because - // a. detaching requires a proper DOM tree (for counters and quotes for - // example) and during the previous loop the next sibling still points to - // the node being removed while the node being removed does not point back - // and does not point to the same parent as its next sibling. - // b. destroying Renderers of standalone nodes is sometimes faster. - for (i = 0; i < removedChildrenCount; ++i) { - Node* removedChild = removedChildren[i].get(); - if (removedChild->attached()) - removedChild->detach(); - } + size_t removedChildrenCount = removedChildren.size(); + size_t i; + + // Detach the nodes only after properly removed from the tree because + // a. detaching requires a proper DOM tree (for counters and quotes for + // example) and during the previous loop the next sibling still points to + // the node being removed while the node being removed does not point back + // and does not point to the same parent as its next sibling. + // b. destroying Renderers of standalone nodes is sometimes faster. + for (i = 0; i < removedChildrenCount; ++i) { + Node* removedChild = removedChildren[i].get(); + if (removedChild->attached()) + removedChild->detach(); + } - childrenChanged(false, 0, 0, -static_cast<int>(removedChildrenCount)); + childrenChanged(false, 0, 0, -static_cast<int>(removedChildrenCount)); - for (i = 0; i < removedChildrenCount; ++i) - ChildNodeRemovalNotifier(this).notify(removedChildren[i].get()); + for (i = 0; i < removedChildrenCount; ++i) + ChildNodeRemovalNotifier(this).notify(removedChildren[i].get()); - allowEventDispatch(); - RenderWidget::resumeWidgetHierarchyUpdates(); + allowEventDispatch(); + } dispatchSubtreeModifiedEvent(); } diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp index 3fa6b41ab..009c84592 100644 --- a/Source/WebCore/dom/Document.cpp +++ b/Source/WebCore/dom/Document.cpp @@ -57,6 +57,7 @@ #include "DocumentFragment.h" #include "DocumentLoader.h" #include "DocumentMarkerController.h" +#include "DocumentStyleSheetCollection.h" #include "DocumentType.h" #include "EditingText.h" #include "Editor.h" @@ -173,6 +174,7 @@ #include <wtf/CurrentTime.h> #include <wtf/HashFunctions.h> #include <wtf/MainThread.h> +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/PassRefPtr.h> #include <wtf/StdLibExtras.h> #include <wtf/text/StringBuffer.h> @@ -437,8 +439,7 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML) #if ENABLE(MUTATION_OBSERVERS) , m_mutationObserverTypes(0) #endif - , m_styleSheets(StyleSheetList::create(this)) - , m_hadActiveLoadingStylesheet(false) + , m_styleSheetCollection(adoptPtr(new DocumentStyleSheetCollection(this))) , m_readyState(Complete) , m_styleRecalcTimer(this, &Document::styleRecalcTimerFired) , m_pendingStyleRecalcShouldForce(false) @@ -504,8 +505,6 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML) { m_document = this; - m_pageGroupUserSheetCacheValid = false; - m_printing = false; m_paginatedForScreen = false; @@ -543,20 +542,9 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML) m_inStyleRecalc = false; m_closeAfterStyleRecalc = false; - m_usesSiblingRules = false; - m_usesSiblingRulesOverride = false; - m_usesFirstLineRules = false; - m_usesFirstLetterRules = false; - m_usesBeforeAfterRules = false; - m_usesBeforeAfterRulesOverride = false; - m_usesRemUnits = false; - m_usesLinkRules = false; - m_gotoAnchorNeededAfterStylesheetsLoad = false; m_didCalculateStyleResolver = false; - m_hasDirtyStyleResolver = false; - m_pendingStylesheets = 0; m_ignorePendingStylesheets = false; m_needsNotifyRemoveAllPendingStylesheet = false; m_hasNodesWithPlaceholderStyle = false; @@ -643,24 +631,16 @@ Document::~Document() m_decoder = 0; - if (m_styleSheets) - m_styleSheets->documentDestroyed(); + if (m_styleSheetList) + m_styleSheetList->detachFromDocument(); + + m_styleSheetCollection.clear(); if (m_namedFlows) m_namedFlows->documentDestroyed(); if (m_elemSheet) m_elemSheet->clearOwnerNode(); - if (m_pageUserSheet) - m_pageUserSheet->clearOwnerNode(); - if (m_pageGroupUserSheets) { - for (size_t i = 0; i < m_pageGroupUserSheets->size(); ++i) - (*m_pageGroupUserSheets)[i]->clearOwnerNode(); - } - if (m_userSheets) { - for (size_t i = 0; i < m_userSheets->size(); ++i) - (*m_userSheets)[i]->clearOwnerNode(); - } deleteCustomFonts(); @@ -802,14 +782,14 @@ void Document::setCompatibilityMode(CompatibilityMode mode) { if (m_compatibilityModeLocked || mode == m_compatibilityMode) return; - ASSERT(!m_styleSheets->length()); + ASSERT(m_styleSheetCollection->authorStyleSheets().isEmpty()); bool wasInQuirksMode = inQuirksMode(); m_compatibilityMode = mode; selectorQueryCache()->invalidate(); if (inQuirksMode() != wasInQuirksMode) { // All user stylesheets have to reparse using the different mode. - clearPageUserSheet(); - clearPageGroupUserSheets(); + m_styleSheetCollection->clearPageUserSheet(); + m_styleSheetCollection->clearPageGroupUserSheets(); } } @@ -1069,8 +1049,11 @@ PassRefPtr<Node> Document::adoptNode(PassRefPtr<Node> source, ExceptionCode& ec) return 0; } } - if (source->parentNode()) + if (source->parentNode()) { source->parentNode()->removeChild(source.get(), ec); + if (ec) + return 0; + } } this->adoptIfNeeded(source.get()); @@ -1822,75 +1805,76 @@ void Document::recalcStyle(StyleChange change) // re-attaching our containing iframe, which when asked HTMLFrameElementBase::isURLAllowed // hits a null-dereference due to security code always assuming the document has a SecurityOrigin. - if (m_hasDirtyStyleResolver) - updateActiveStylesheets(RecalcStyleImmediately); + if (m_styleSheetCollection->needsUpdateActiveStylesheetsOnStyleRecalc()) + m_styleSheetCollection->updateActiveStyleSheets(DocumentStyleSheetCollection::FullUpdate); InspectorInstrumentationCookie cookie = InspectorInstrumentation::willRecalculateStyle(this); if (m_elemSheet && m_elemSheet->contents()->usesRemUnits()) - m_usesRemUnits = true; + m_styleSheetCollection->setUsesRemUnit(true); m_inStyleRecalc = true; suspendPostAttachCallbacks(); - RenderWidget::suspendWidgetHierarchyUpdates(); - - RefPtr<FrameView> frameView = view(); - if (frameView) { - frameView->pauseScheduledEvents(); - frameView->beginDeferredRepaints(); - } + { + WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; - ASSERT(!renderer() || renderArena()); - if (!renderer() || !renderArena()) - goto bail_out; + RefPtr<FrameView> frameView = view(); + if (frameView) { + frameView->pauseScheduledEvents(); + frameView->beginDeferredRepaints(); + } - if (m_pendingStyleRecalcShouldForce) - change = Force; + ASSERT(!renderer() || renderArena()); + if (!renderer() || !renderArena()) + goto bailOut; - // Recalculating the root style (on the document) is not needed in the common case. - if ((change == Force) || (shouldDisplaySeamlesslyWithParent() && (change >= Inherit))) { - // style selector may set this again during recalc - m_hasNodesWithPlaceholderStyle = false; - - RefPtr<RenderStyle> documentStyle = StyleResolver::styleForDocument(this, m_styleResolver ? m_styleResolver->fontSelector() : 0); - StyleChange ch = Node::diff(documentStyle.get(), renderer()->style(), this); - if (ch != NoChange) - renderer()->setStyle(documentStyle.release()); - } + if (m_pendingStyleRecalcShouldForce) + change = Force; - for (Node* n = firstChild(); n; n = n->nextSibling()) { - if (!n->isElementNode()) - continue; - Element* element = static_cast<Element*>(n); - if (change >= Inherit || element->childNeedsStyleRecalc() || element->needsStyleRecalc()) - element->recalcStyle(change); - } + // Recalculating the root style (on the document) is not needed in the common case. + if ((change == Force) || (shouldDisplaySeamlesslyWithParent() && (change >= Inherit))) { + // style selector may set this again during recalc + m_hasNodesWithPlaceholderStyle = false; + + RefPtr<RenderStyle> documentStyle = StyleResolver::styleForDocument(this, m_styleResolver ? m_styleResolver->fontSelector() : 0); + StyleChange ch = Node::diff(documentStyle.get(), renderer()->style(), this); + if (ch != NoChange) + renderer()->setStyle(documentStyle.release()); + } -#if USE(ACCELERATED_COMPOSITING) - if (view()) { - bool layoutPending = view()->layoutPending() || renderer()->needsLayout(); - // If we didn't update compositing layers because of layout(), we need to do so here. - if (!layoutPending) - view()->updateCompositingLayersAfterStyleChange(); - } -#endif + for (Node* n = firstChild(); n; n = n->nextSibling()) { + if (!n->isElementNode()) + continue; + Element* element = static_cast<Element*>(n); + if (change >= Inherit || element->childNeedsStyleRecalc() || element->needsStyleRecalc()) + element->recalcStyle(change); + } -bail_out: - clearNeedsStyleRecalc(); - clearChildNeedsStyleRecalc(); - unscheduleStyleRecalc(); + #if USE(ACCELERATED_COMPOSITING) + if (view()) { + bool layoutPending = view()->layoutPending() || renderer()->needsLayout(); + // If we didn't update compositing layers because of layout(), we need to do so here. + if (!layoutPending) + view()->updateCompositingLayersAfterStyleChange(); + } + #endif - m_inStyleRecalc = false; - - // Pseudo element removal and similar may only work with these flags still set. Reset them after the style recalc. - if (m_styleResolver) - resetCSSFeatureFlags(); + bailOut: + clearNeedsStyleRecalc(); + clearChildNeedsStyleRecalc(); + unscheduleStyleRecalc(); + + m_inStyleRecalc = false; - if (frameView) { - frameView->resumeScheduledEvents(); - frameView->endDeferredRepaints(); + // Pseudo element removal and similar may only work with these flags still set. Reset them after the style recalc. + if (m_styleResolver) + m_styleSheetCollection->resetCSSFeatureFlags(); + + if (frameView) { + frameView->resumeScheduledEvents(); + frameView->endDeferredRepaints(); + } } - RenderWidget::resumeWidgetHierarchyUpdates(); resumePostAttachCallbacks(); // If we wanted to call implicitClose() during recalcStyle, do so now that we're finished. @@ -2067,33 +2051,16 @@ void Document::setIsViewSource(bool isViewSource) didUpdateSecurityOrigin(); } -void Document::combineCSSFeatureFlags() -{ - // Delay resetting the flags until after next style recalc since unapplying the style may not work without these set (this is true at least with before/after). - m_usesSiblingRules = m_usesSiblingRules || m_styleResolver->usesSiblingRules(); - m_usesFirstLineRules = m_usesFirstLineRules || m_styleResolver->usesFirstLineRules(); - m_usesBeforeAfterRules = m_usesBeforeAfterRules || m_styleResolver->usesBeforeAfterRules(); - m_usesLinkRules = m_usesLinkRules || m_styleResolver->usesLinkRules(); -} - -void Document::resetCSSFeatureFlags() -{ - m_usesSiblingRules = m_styleResolver->usesSiblingRules(); - m_usesFirstLineRules = m_styleResolver->usesFirstLineRules(); - m_usesBeforeAfterRules = m_styleResolver->usesBeforeAfterRules(); - m_usesLinkRules = m_styleResolver->usesLinkRules(); -} - void Document::createStyleResolver() { bool matchAuthorAndUserStyles = true; if (Settings* docSettings = settings()) matchAuthorAndUserStyles = docSettings->authorAndUserStylesEnabled(); m_styleResolver = adoptPtr(new StyleResolver(this, matchAuthorAndUserStyles)); - combineCSSFeatureFlags(); + m_styleSheetCollection->combineCSSFeatureFlags(); } -inline void Document::clearStyleResolver() +void Document::clearStyleResolver() { m_styleResolver.clear(); } @@ -2903,105 +2870,23 @@ Frame* Document::findUnsafeParentScrollPropagationBoundary() return 0; } -CSSStyleSheet* Document::pageUserSheet() -{ - if (m_pageUserSheet) - return m_pageUserSheet.get(); - - Page* owningPage = page(); - if (!owningPage) - return 0; - - String userSheetText = owningPage->userStyleSheet(); - if (userSheetText.isEmpty()) - return 0; - - // Parse the sheet and cache it. - m_pageUserSheet = CSSStyleSheet::createInline(this, settings()->userStyleSheetLocation()); - m_pageUserSheet->contents()->setIsUserStyleSheet(true); - m_pageUserSheet->contents()->parseString(userSheetText); - return m_pageUserSheet.get(); -} - -void Document::clearPageUserSheet() -{ - if (m_pageUserSheet) { - m_pageUserSheet = 0; - styleResolverChanged(DeferRecalcStyle); - } -} - -void Document::updatePageUserSheet() -{ - clearPageUserSheet(); - if (pageUserSheet()) - styleResolverChanged(RecalcStyleImmediately); -} -const Vector<RefPtr<CSSStyleSheet> >* Document::pageGroupUserSheets() const +void Document::seamlessParentUpdatedStylesheets() { - if (m_pageGroupUserSheetCacheValid) - return m_pageGroupUserSheets.get(); - - m_pageGroupUserSheetCacheValid = true; - - Page* owningPage = page(); - if (!owningPage) - return 0; - - const PageGroup& pageGroup = owningPage->group(); - const UserStyleSheetMap* sheetsMap = pageGroup.userStyleSheets(); - if (!sheetsMap) - return 0; - - UserStyleSheetMap::const_iterator end = sheetsMap->end(); - for (UserStyleSheetMap::const_iterator it = sheetsMap->begin(); it != end; ++it) { - const UserStyleSheetVector* sheets = it->second.get(); - for (unsigned i = 0; i < sheets->size(); ++i) { - const UserStyleSheet* sheet = sheets->at(i).get(); - if (sheet->injectedFrames() == InjectInTopFrameOnly && ownerElement()) - continue; - if (!UserContentURLPattern::matchesPatterns(url(), sheet->whitelist(), sheet->blacklist())) - continue; - RefPtr<CSSStyleSheet> groupSheet = CSSStyleSheet::createInline(const_cast<Document*>(this), sheet->url()); - if (!m_pageGroupUserSheets) - m_pageGroupUserSheets = adoptPtr(new Vector<RefPtr<CSSStyleSheet> >); - m_pageGroupUserSheets->append(groupSheet); - groupSheet->contents()->setIsUserStyleSheet(sheet->level() == UserStyleUserLevel); - groupSheet->contents()->parseString(sheet->source()); - } - } - - return m_pageGroupUserSheets.get(); + styleResolverChanged(RecalcStyleImmediately); } -void Document::clearPageGroupUserSheets() +void Document::didRemoveAllPendingStylesheet() { - m_pageGroupUserSheetCacheValid = false; - if (m_pageGroupUserSheets && m_pageGroupUserSheets->size()) { - m_pageGroupUserSheets->clear(); - styleResolverChanged(DeferRecalcStyle); - } -} + m_needsNotifyRemoveAllPendingStylesheet = false; -void Document::updatePageGroupUserSheets() -{ - clearPageGroupUserSheets(); - if (pageGroupUserSheets() && pageGroupUserSheets()->size()) - styleResolverChanged(RecalcStyleImmediately); -} + styleResolverChanged(RecalcStyleIfNeeded); -void Document::addUserSheet(PassRefPtr<StyleSheetContents> userSheet) -{ - if (!m_userSheets) - m_userSheets = adoptPtr(new Vector<RefPtr<CSSStyleSheet> >); - m_userSheets->append(CSSStyleSheet::create(userSheet, this)); - styleResolverChanged(RecalcStyleImmediately); -} + if (ScriptableDocumentParser* parser = scriptableDocumentParser()) + parser->executeScriptsWaitingForStylesheets(); -void Document::seamlessParentUpdatedStylesheets() -{ - styleResolverChanged(RecalcStyleImmediately); + if (m_gotoAnchorNeededAfterStylesheetsLoad && view()) + view()->scrollToFragment(m_url); } CSSStyleSheet* Document::elementSheet() @@ -3042,8 +2927,8 @@ void Document::processHttpEquiv(const String& equiv, const String& content) // For more info, see the test at: // http://www.hixie.ch/tests/evil/css/import/main/preferred.html // -dwh - m_selectedStylesheetSet = content; - m_preferredStylesheetSet = content; + m_styleSheetCollection->setSelectedStylesheetSetName(content); + m_styleSheetCollection->setPreferredStylesheetSetName(content); styleResolverChanged(DeferRecalcStyle); } else if (equalIgnoringCase(equiv, "refresh")) { double delay; @@ -3315,63 +3200,27 @@ PassRefPtr<Node> Document::cloneNode(bool /*deep*/) StyleSheetList* Document::styleSheets() { - return m_styleSheets.get(); + if (!m_styleSheetList) + m_styleSheetList = StyleSheetList::create(this); + return m_styleSheetList.get(); } String Document::preferredStylesheetSet() const { - return m_preferredStylesheetSet; + return m_styleSheetCollection->preferredStylesheetSetName(); } String Document::selectedStylesheetSet() const { - return m_selectedStylesheetSet; + return m_styleSheetCollection->selectedStylesheetSetName(); } void Document::setSelectedStylesheetSet(const String& aString) { - m_selectedStylesheetSet = aString; + m_styleSheetCollection->setSelectedStylesheetSetName(aString); styleResolverChanged(DeferRecalcStyle); } -// This method is called whenever a top-level stylesheet has finished loading. -void Document::removePendingSheet(RemovePendingSheetNotificationType notification) -{ - // Make sure we knew this sheet was pending, and that our count isn't out of sync. - ASSERT(m_pendingStylesheets > 0); - - m_pendingStylesheets--; - -#ifdef INSTRUMENT_LAYOUT_SCHEDULING - if (!ownerElement()) - printf("Stylesheet loaded at time %d. %d stylesheets still remain.\n", elapsedTime(), m_pendingStylesheets); -#endif - - if (m_pendingStylesheets) - return; - - if (notification == RemovePendingSheetNotifyLater) { - setNeedsNotifyRemoveAllPendingStylesheet(); - return; - } - - didRemoveAllPendingStylesheet(); -} - -void Document::didRemoveAllPendingStylesheet() -{ - m_needsNotifyRemoveAllPendingStylesheet = false; - - styleResolverChanged(RecalcStyleIfNeeded); - - if (ScriptableDocumentParser* parser = scriptableDocumentParser()) - parser->executeScriptsWaitingForStylesheets(); - - if (m_gotoAnchorNeededAfterStylesheetsLoad && view()) - view()->scrollToFragment(m_url); -} - - void Document::evaluateMediaQueryList() { if (m_mediaQueryMatcher) @@ -3386,20 +3235,24 @@ void Document::styleResolverChanged(StyleResolverUpdateFlag updateFlag) m_styleResolver.clear(); return; } + m_didCalculateStyleResolver = true; #ifdef INSTRUMENT_LAYOUT_SCHEDULING if (!ownerElement()) printf("Beginning update of style selector at time %d.\n", elapsedTime()); #endif - bool stylesheetChangeRequiresStyleRecalc = updateActiveStylesheets(updateFlag); + DocumentStyleSheetCollection::UpdateFlag styleSheetUpdate = (updateFlag == RecalcStyleIfNeeded) + ? DocumentStyleSheetCollection::OptimizedUpdate + : DocumentStyleSheetCollection::FullUpdate; + bool stylesheetChangeRequiresStyleRecalc = m_styleSheetCollection->updateActiveStyleSheets(styleSheetUpdate); if (updateFlag == DeferRecalcStyle) { scheduleForcedStyleRecalc(); return; } - if (didLayoutWithPendingStylesheets() && m_pendingStylesheets <= 0) { + if (didLayoutWithPendingStylesheets() && !m_styleSheetCollection->hasPendingSheets()) { m_pendingSheetLayout = IgnoreLayoutWithPendingSheets; if (renderer()) renderer()->repaint(); @@ -3429,219 +3282,6 @@ void Document::styleResolverChanged(StyleResolverUpdateFlag updateFlag) evaluateMediaQueryList(); } -void Document::addStyleSheetCandidateNode(Node* node, bool createdByParser) -{ - if (!node->inDocument()) - return; - - // Until the <body> exists, we have no choice but to compare document positions, - // since styles outside of the body and head continue to be shunted into the head - // (and thus can shift to end up before dynamically added DOM content that is also - // outside the body). - if ((createdByParser && body()) || m_styleSheetCandidateNodes.isEmpty()) { - m_styleSheetCandidateNodes.add(node); - return; - } - - // Determine an appropriate insertion point. - StyleSheetCandidateListHashSet::iterator begin = m_styleSheetCandidateNodes.begin(); - StyleSheetCandidateListHashSet::iterator end = m_styleSheetCandidateNodes.end(); - StyleSheetCandidateListHashSet::iterator it = end; - Node* followingNode = 0; - do { - --it; - Node* n = *it; - unsigned short position = n->compareDocumentPosition(node); - if (position == DOCUMENT_POSITION_FOLLOWING) { - m_styleSheetCandidateNodes.insertBefore(followingNode, node); - return; - } - followingNode = n; - } while (it != begin); - - m_styleSheetCandidateNodes.insertBefore(followingNode, node); -} - -void Document::removeStyleSheetCandidateNode(Node* node) -{ - m_styleSheetCandidateNodes.remove(node); -} - -void Document::collectActiveStylesheets(Vector<RefPtr<StyleSheet> >& sheets) -{ - if (settings() && !settings()->authorAndUserStylesEnabled()) - return; - - StyleSheetCandidateListHashSet::iterator begin = m_styleSheetCandidateNodes.begin(); - StyleSheetCandidateListHashSet::iterator end = m_styleSheetCandidateNodes.end(); - for (StyleSheetCandidateListHashSet::iterator it = begin; it != end; ++it) { - Node* n = *it; - StyleSheet* sheet = 0; - if (n->nodeType() == PROCESSING_INSTRUCTION_NODE) { - // Processing instruction (XML documents only). - // We don't support linking to embedded CSS stylesheets, see <https://bugs.webkit.org/show_bug.cgi?id=49281> for discussion. - ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(n); - sheet = pi->sheet(); -#if ENABLE(XSLT) - // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806> - if (pi->isXSL() && !transformSourceDocument()) { - // Don't apply XSL transforms until loading is finished. - if (!parsing()) - applyXSLTransform(pi); - return; - } -#endif - } else if ((n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag))) -#if ENABLE(SVG) - || (n->isSVGElement() && n->hasTagName(SVGNames::styleTag)) -#endif - ) { - Element* e = static_cast<Element*>(n); - AtomicString title = e->getAttribute(titleAttr); - bool enabledViaScript = false; - if (e->hasLocalName(linkTag)) { - // <LINK> element - HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(n); - if (linkElement->isDisabled()) - continue; - enabledViaScript = linkElement->isEnabledViaScript(); - if (linkElement->styleSheetIsLoading()) { - // it is loading but we should still decide which style sheet set to use - if (!enabledViaScript && !title.isEmpty() && m_preferredStylesheetSet.isEmpty()) { - const AtomicString& rel = e->getAttribute(relAttr); - if (!rel.contains("alternate")) { - m_preferredStylesheetSet = title; - m_selectedStylesheetSet = title; - } - } - continue; - } - if (!linkElement->sheet()) - title = nullAtom; - } - // Get the current preferred styleset. This is the - // set of sheets that will be enabled. -#if ENABLE(SVG) - if (n->isSVGElement() && n->hasTagName(SVGNames::styleTag)) - sheet = static_cast<SVGStyleElement*>(n)->sheet(); - else -#endif - if (e->hasLocalName(linkTag)) - sheet = static_cast<HTMLLinkElement*>(n)->sheet(); - else - // <STYLE> element - sheet = static_cast<HTMLStyleElement*>(n)->sheet(); - // Check to see if this sheet belongs to a styleset - // (thus making it PREFERRED or ALTERNATE rather than - // PERSISTENT). - AtomicString rel = e->getAttribute(relAttr); - if (!enabledViaScript && !title.isEmpty()) { - // Yes, we have a title. - if (m_preferredStylesheetSet.isEmpty()) { - // No preferred set has been established. If - // we are NOT an alternate sheet, then establish - // us as the preferred set. Otherwise, just ignore - // this sheet. - if (e->hasLocalName(styleTag) || !rel.contains("alternate")) - m_preferredStylesheetSet = m_selectedStylesheetSet = title; - } - if (title != m_preferredStylesheetSet) - sheet = 0; - } - - if (rel.contains("alternate") && title.isEmpty()) - sheet = 0; - } - if (sheet) - sheets.append(sheet); - } -} - -bool Document::testAddedStylesheetRequiresStyleRecalc(StyleSheetContents* stylesheet) -{ - // See if all rules on the sheet are scoped to some specific ids or classes. - // Then test if we actually have any of those in the tree at the moment. - HashSet<AtomicStringImpl*> idScopes; - HashSet<AtomicStringImpl*> classScopes; - if (!StyleResolver::determineStylesheetSelectorScopes(stylesheet, idScopes, classScopes)) - return true; - // Invalidate the subtrees that match the scopes. - Node* node = firstChild(); - while (node) { - if (!node->isStyledElement()) { - node = node->traverseNextNode(); - continue; - } - StyledElement* element = static_cast<StyledElement*>(node); - if (SelectorChecker::elementMatchesSelectorScopes(element, idScopes, classScopes)) { - element->setNeedsStyleRecalc(); - // The whole subtree is now invalidated, we can skip to the next sibling. - node = node->traverseNextSibling(); - continue; - } - node = node->traverseNextNode(); - } - return false; -} - -void Document::analyzeStylesheetChange(StyleResolverUpdateFlag updateFlag, const Vector<RefPtr<StyleSheet> >& newStylesheets, bool& requiresStyleResolverReset, bool& requiresFullStyleRecalc) -{ - requiresStyleResolverReset = true; - requiresFullStyleRecalc = true; - - // Stylesheets of <style> elements that @import stylesheets are active but loading. We need to trigger a full recalc when such loads are done. - bool hasActiveLoadingStylesheet = false; - unsigned newStylesheetCount = newStylesheets.size(); - for (unsigned i = 0; i < newStylesheetCount; ++i) { - if (newStylesheets[i]->isLoading()) - hasActiveLoadingStylesheet = true; - } - if (m_hadActiveLoadingStylesheet && !hasActiveLoadingStylesheet) { - m_hadActiveLoadingStylesheet = false; - return; - } - m_hadActiveLoadingStylesheet = hasActiveLoadingStylesheet; - - if (updateFlag != RecalcStyleIfNeeded) - return; - if (!m_styleResolver) - return; - - // See if we are just adding stylesheets. - unsigned oldStylesheetCount = m_styleSheets->length(); - if (newStylesheetCount < oldStylesheetCount) - return; - for (unsigned i = 0; i < oldStylesheetCount; ++i) { - if (m_styleSheets->item(i) != newStylesheets[i]) - return; - } - requiresStyleResolverReset = false; - - // If we are already parsing the body and so may have significant amount of elements, put some effort into trying to avoid style recalcs. - if (!body() || m_hasNodesWithPlaceholderStyle) - return; - for (unsigned i = oldStylesheetCount; i < newStylesheetCount; ++i) { - if (!newStylesheets[i]->isCSSStyleSheet()) - return; - if (newStylesheets[i]->disabled()) - continue; - if (testAddedStylesheetRequiresStyleRecalc(static_cast<CSSStyleSheet*>(newStylesheets[i].get())->contents())) - return; - } - requiresFullStyleRecalc = false; -} - -static bool styleSheetsUseRemUnits(const Vector<RefPtr<StyleSheet> >& sheets) -{ - for (unsigned i = 0; i < sheets.size(); ++i) { - if (!sheets[i]->isCSSStyleSheet()) - continue; - if (static_cast<CSSStyleSheet*>(sheets[i].get())->contents()->usesRemUnits()) - return true; - } - return false; -} - void Document::notifySeamlessChildDocumentsOfStylesheetUpdate() const { // If we're not in a frame yet any potential child documents won't have a StyleResolver to update. @@ -3658,43 +3298,6 @@ void Document::notifySeamlessChildDocumentsOfStylesheetUpdate() const } } -bool Document::updateActiveStylesheets(StyleResolverUpdateFlag updateFlag) -{ - if (m_inStyleRecalc) { - // SVG <use> element may manage to invalidate style selector in the middle of a style recalc. - // https://bugs.webkit.org/show_bug.cgi?id=54344 - // FIXME: This should be fixed in SVG and this code replaced with ASSERT(!m_inStyleRecalc). - m_hasDirtyStyleResolver = true; - scheduleForcedStyleRecalc(); - return false; - } - if (!renderer() || !attached()) - return false; - - StyleSheetVector newStylesheets; - collectActiveStylesheets(newStylesheets); - - bool requiresStyleResolverReset; - bool requiresFullStyleRecalc; - analyzeStylesheetChange(updateFlag, newStylesheets, requiresStyleResolverReset, requiresFullStyleRecalc); - - if (requiresStyleResolverReset) - clearStyleResolver(); - else { - m_styleResolver->appendAuthorStylesheets(m_styleSheets->length(), newStylesheets); - resetCSSFeatureFlags(); - } - m_styleSheets->swap(newStylesheets); - - m_usesRemUnits = styleSheetsUseRemUnits(m_styleSheets->vector()); - m_didCalculateStyleResolver = true; - m_hasDirtyStyleResolver = false; - - notifySeamlessChildDocumentsOfStylesheetUpdate(); - - return requiresFullStyleRecalc; -} - void Document::setHoverNode(PassRefPtr<Node> newHoverNode) { m_hoverNode = newHoverNode; @@ -3714,12 +3317,16 @@ void Document::removeFocusedNodeOfSubtree(Node* node, bool amongChildrenOnly) { if (!m_focusedNode || this->inPageCache()) // If the document is in the page cache, then we don't need to clear out the focused node. return; - + + Node* focusedNode = node->treeScope()->focusedNode(); + if (!focusedNode) + return; + bool nodeInSubtree = false; if (amongChildrenOnly) - nodeInSubtree = m_focusedNode->isDescendantOf(node); + nodeInSubtree = focusedNode->isDescendantOf(node); else - nodeInSubtree = (m_focusedNode == node) || m_focusedNode->isDescendantOf(node); + nodeInSubtree = (focusedNode == node) || focusedNode->isDescendantOf(node); if (nodeInSubtree) document()->focusedNodeRemoved(); @@ -6262,7 +5869,7 @@ void Document::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM); info.addMember(m_styleResolver); ContainerNode::reportMemoryUsage(memoryObjectInfo); - info.addVector(m_customFonts); + info.addMember(m_customFonts); info.addMember(m_url); info.addMember(m_baseURL); info.addMember(m_baseURLOverride); @@ -6274,16 +5881,9 @@ void Document::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const info.addMember(m_frame); info.addMember(m_cachedResourceLoader); info.addMember(m_elemSheet); - info.addMember(m_pageUserSheet); - if (m_pageGroupUserSheets) - info.addInstrumentedVectorPtr(m_pageGroupUserSheets); - if (m_userSheets) - info.addInstrumentedVectorPtr(m_userSheets); + info.addMember(m_styleSheetCollection); info.addHashSet(m_nodeIterators); info.addHashSet(m_ranges); - info.addListHashSet(m_styleSheetCandidateNodes); - info.addMember(m_preferredStylesheetSet); - info.addMember(m_selectedStylesheetSet); info.addMember(m_title.string()); info.addMember(m_rawTitle.string()); info.addMember(m_xmlEncoding); @@ -6292,17 +5892,17 @@ void Document::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const info.addHashMap(m_documentNamedItemCollections); info.addHashMap(m_windowNamedItemCollections); #if ENABLE(DASHBOARD_SUPPORT) - info.addVector(m_dashboardRegions); + info.addMember(m_dashboardRegions); #endif info.addHashMap(m_cssCanvasElements); - info.addVector(m_iconURLs); + info.addMember(m_iconURLs); info.addHashSet(m_documentSuspensionCallbackElements); info.addHashSet(m_mediaVolumeCallbackElements); info.addHashSet(m_privateBrowsingStateChangedElements); info.addHashMap(m_elementsByAccessKey); info.addMember(m_eventQueue); info.addHashSet(m_mediaCanStartListeners); - info.addVector(m_pendingTasks); + info.addMember(m_pendingTasks); } #if ENABLE(UNDO_MANAGER) @@ -6378,6 +5978,11 @@ PassRefPtr<ElementAttributeData> Document::cachedImmutableAttributeData(const El return attributeData.release(); } +bool Document::haveStylesheetsLoaded() const +{ + return !m_styleSheetCollection->hasPendingSheets() || m_ignorePendingStylesheets; +} + Localizer& Document::getLocalizer(const AtomicString& locale) { AtomicString localeKey = locale; diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h index d8119c30b..f6d700ac0 100644 --- a/Source/WebCore/dom/Document.h +++ b/Source/WebCore/dom/Document.h @@ -78,6 +78,7 @@ class DocumentFragment; class DocumentLoader; class DocumentMarkerController; class DocumentParser; +class DocumentStyleSheetCollection; class DocumentType; class DocumentWeakReference; class DynamicNodeListCacheBase; @@ -485,34 +486,14 @@ public: return m_styleResolver.get(); } - /** - * Updates the pending sheet count and then calls updateActiveStylesheets. - */ - enum RemovePendingSheetNotificationType { - RemovePendingSheetNotifyImmediately, - RemovePendingSheetNotifyLater - }; - - void removePendingSheet(RemovePendingSheetNotificationType = RemovePendingSheetNotifyImmediately); void notifyRemovePendingSheetIfNeeded(); - /** - * This method returns true if all top-level stylesheets have loaded (including - * any @imports that they may be loading). - */ - bool haveStylesheetsLoaded() const - { - return m_pendingStylesheets <= 0 || m_ignorePendingStylesheets; - } + bool haveStylesheetsLoaded() const; - /** - * Increments the number of pending sheets. The <link> elements - * invoke this to add themselves to the loading list. - */ - void addPendingSheet() { m_pendingStylesheets++; } + // This is a DOM function. + StyleSheetList* styleSheets(); - void addStyleSheetCandidateNode(Node*, bool createdByParser); - void removeStyleSheetCandidateNode(Node*); + DocumentStyleSheetCollection* styleSheetCollection() { return m_styleSheetCollection.get(); } bool gotoAnchorNeededAfterStylesheetsLoad() { return m_gotoAnchorNeededAfterStylesheetsLoad; } void setGotoAnchorNeededAfterStylesheetsLoad(bool b) { m_gotoAnchorNeededAfterStylesheetsLoad = b; } @@ -530,17 +511,6 @@ public: void evaluateMediaQueryList(); - bool usesSiblingRules() const { return m_usesSiblingRules || m_usesSiblingRulesOverride; } - void setUsesSiblingRules(bool b) { m_usesSiblingRulesOverride = b; } - bool usesFirstLineRules() const { return m_usesFirstLineRules; } - bool usesFirstLetterRules() const { return m_usesFirstLetterRules; } - void setUsesFirstLetterRules(bool b) { m_usesFirstLetterRules = b; } - bool usesBeforeAfterRules() const { return m_usesBeforeAfterRules || m_usesBeforeAfterRulesOverride; } - void setUsesBeforeAfterRules(bool b) { m_usesBeforeAfterRulesOverride = b; } - bool usesRemUnits() const { return m_usesRemUnits; } - bool usesLinkRules() const { return linkColor() != visitedLinkColor() || m_usesLinkRules; } - void setUsesLinkRules(bool b) { m_usesLinkRules = b; } - // Never returns 0. FormController* formController(); Vector<String> formElementsState() const; @@ -556,7 +526,7 @@ public: PassRefPtr<NodeIterator> createNodeIterator(Node* root, unsigned whatToShow, PassRefPtr<NodeFilter>, bool expandEntityReferences, ExceptionCode&); - PassRefPtr<TreeWalker> createTreeWalker(Node* root, unsigned whatToShow, + PassRefPtr<TreeWalker> createTreeWalker(Node* root, unsigned whatToShow, PassRefPtr<NodeFilter>, bool expandEntityReferences, ExceptionCode&); // Special support for editing @@ -649,17 +619,6 @@ public: bool canNavigate(Frame* targetFrame); Frame* findUnsafeParentScrollPropagationBoundary(); - CSSStyleSheet* pageUserSheet(); - void clearPageUserSheet(); - void updatePageUserSheet(); - - const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets() const; - void clearPageGroupUserSheets(); - void updatePageGroupUserSheets(); - - const Vector<RefPtr<CSSStyleSheet> >* documentUserSheets() const { return m_userSheets.get(); } - void addUserSheet(PassRefPtr<StyleSheetContents> userSheet); - CSSStyleSheet* elementSheet(); virtual PassRefPtr<DocumentParser> createParser(); @@ -716,8 +675,6 @@ public: MouseEventWithHitTestResults prepareMouseEvent(const HitTestRequest&, const LayoutPoint&, const PlatformMouseEvent&); - StyleSheetList* styleSheets(); - /* Newly proposed CSS3 mechanism for selecting alternate stylesheets using the DOM. May be subject to change as spec matures. - dwh @@ -974,7 +931,8 @@ public: enum PendingSheetLayout { NoLayoutWithPendingSheets, DidLayoutWithPendingSheets, IgnoreLayoutWithPendingSheets }; bool didLayoutWithPendingStylesheets() const { return m_pendingSheetLayout == DidLayoutWithPendingSheets; } - + + bool hasNodesWithPlaceholderStyle() const { return m_hasNodesWithPlaceholderStyle; } void setHasNodesWithPlaceholderStyle() { m_hasNodesWithPlaceholderStyle = true; } const Vector<IconURL>& iconURLs(); @@ -1194,6 +1152,13 @@ public: PassRefPtr<ElementAttributeData> cachedImmutableAttributeData(const Element*, const Vector<Attribute>&); + void didRemoveAllPendingStylesheet(); + void setNeedsNotifyRemoveAllPendingStylesheet() { m_needsNotifyRemoveAllPendingStylesheet = true; } + void clearStyleResolver(); + void notifySeamlessChildDocumentsOfStylesheetUpdate() const; + + bool inStyleRecalc() { return m_inStyleRecalc; } + Localizer& getLocalizer(const AtomicString& locale); protected: @@ -1241,19 +1206,8 @@ private: void buildAccessKeyMap(TreeScope* root); void createStyleResolver(); - void clearStyleResolver(); - void combineCSSFeatureFlags(); - void resetCSSFeatureFlags(); - - bool updateActiveStylesheets(StyleResolverUpdateFlag); - void collectActiveStylesheets(Vector<RefPtr<StyleSheet> >&); - bool testAddedStylesheetRequiresStyleRecalc(StyleSheetContents*); - void analyzeStylesheetChange(StyleResolverUpdateFlag, const Vector<RefPtr<StyleSheet> >& newStylesheets, bool& requiresStyleResolverReset, bool& requiresFullStyleRecalc); - void didRemoveAllPendingStylesheet(); - void setNeedsNotifyRemoveAllPendingStylesheet() { m_needsNotifyRemoveAllPendingStylesheet = true; } void seamlessParentUpdatedStylesheets(); - void notifySeamlessChildDocumentsOfStylesheetUpdate() const; void deleteCustomFonts(); @@ -1290,6 +1244,17 @@ private: OwnPtr<StyleResolver> m_styleResolver; bool m_didCalculateStyleResolver; bool m_hasDirtyStyleResolver; + bool m_hasNodesWithPlaceholderStyle; + bool m_needsNotifyRemoveAllPendingStylesheet; + // But sometimes you need to ignore pending stylesheet count to + // force an immediate layout when requested by JS. + bool m_ignorePendingStylesheets; + + // If we do ignore the pending stylesheet count, then we need to add a boolean + // to track that this happened so that we can do a full repaint when the stylesheets + // do eventually load. + PendingSheetLayout m_pendingSheetLayout; + Vector<OwnPtr<FontData> > m_customFonts; Frame* m_frame; @@ -1323,29 +1288,7 @@ private: RefPtr<DocumentType> m_docType; OwnPtr<DOMImplementation> m_implementation; - // Track the number of currently loading top-level stylesheets needed for rendering. - // Sheets loaded using the @import directive are not included in this count. - // We use this count of pending sheets to detect when we can begin attaching - // elements and when it is safe to execute scripts. - int m_pendingStylesheets; - - // But sometimes you need to ignore pending stylesheet count to - // force an immediate layout when requested by JS. - bool m_ignorePendingStylesheets : 1; - bool m_needsNotifyRemoveAllPendingStylesheet : 1; - - // If we do ignore the pending stylesheet count, then we need to add a boolean - // to track that this happened so that we can do a full repaint when the stylesheets - // do eventually load. - PendingSheetLayout m_pendingSheetLayout; - - bool m_hasNodesWithPlaceholderStyle; - RefPtr<CSSStyleSheet> m_elemSheet; - RefPtr<CSSStyleSheet> m_pageUserSheet; - mutable OwnPtr<Vector<RefPtr<CSSStyleSheet> > > m_pageGroupUserSheets; - OwnPtr<Vector<RefPtr<CSSStyleSheet> > > m_userSheets; - mutable bool m_pageGroupUserSheetCacheValid; bool m_printing; bool m_paginatedForScreen; @@ -1374,11 +1317,9 @@ private: MutationObserverOptions m_mutationObserverTypes; #endif - RefPtr<StyleSheetList> m_styleSheets; // All of the stylesheets that are currently in effect for our media type and stylesheet set. - bool m_hadActiveLoadingStylesheet; - - typedef ListHashSet<Node*, 32> StyleSheetCandidateListHashSet; - StyleSheetCandidateListHashSet m_styleSheetCandidateNodes; // All of the nodes that could potentially provide stylesheets to the document (<link>, <style>, <?xml-stylesheet>) + + OwnPtr<DocumentStyleSheetCollection> m_styleSheetCollection; + RefPtr<StyleSheetList> m_styleSheetList; OwnPtr<FormController> m_formController; @@ -1386,9 +1327,6 @@ private: Color m_visitedLinkColor; Color m_activeLinkColor; - String m_preferredStylesheetSet; - String m_selectedStylesheetSet; - bool m_loadingSheet; bool m_visuallyOrdered; ReadyState m_readyState; @@ -1399,14 +1337,6 @@ private: bool m_inStyleRecalc; bool m_closeAfterStyleRecalc; - bool m_usesSiblingRules; - bool m_usesSiblingRulesOverride; - bool m_usesFirstLineRules; - bool m_usesFirstLetterRules; - bool m_usesBeforeAfterRules; - bool m_usesBeforeAfterRulesOverride; - bool m_usesRemUnits; - bool m_usesLinkRules; bool m_gotoAnchorNeededAfterStylesheetsLoad; bool m_isDNSPrefetchEnabled; bool m_haveExplicitlyDisabledDNSPrefetch; diff --git a/Source/WebCore/dom/DocumentStyleSheetCollection.cpp b/Source/WebCore/dom/DocumentStyleSheetCollection.cpp new file mode 100644 index 000000000..70f542713 --- /dev/null +++ b/Source/WebCore/dom/DocumentStyleSheetCollection.cpp @@ -0,0 +1,484 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2001 Dirk Mueller (mueller@kde.org) + * (C) 2006 Alexey Proskuryakov (ap@webkit.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved. + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) Research In Motion Limited 2010-2011. 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 "DocumentStyleSheetCollection.h" + +#include "CSSStyleSheet.h" +#include "Document.h" +#include "Element.h" +#include "HTMLLinkElement.h" +#include "HTMLNames.h" +#include "HTMLStyleElement.h" +#include "Page.h" +#include "PageGroup.h" +#include "ProcessingInstruction.h" +#include "SVGNames.h" +#include "SVGStyleElement.h" +#include "SelectorChecker.h" +#include "Settings.h" +#include "StyleResolver.h" +#include "StyleSheetContents.h" +#include "StyleSheetList.h" +#include "UserContentURLPattern.h" +#include "WebCoreMemoryInstrumentation.h" +#include <wtf/MemoryInstrumentationVector.h> + +namespace WebCore { + +using namespace HTMLNames; + +DocumentStyleSheetCollection::DocumentStyleSheetCollection(Document* document) + : m_document(document) + , m_pendingStylesheets(0) + , m_pageGroupUserSheetCacheValid(false) + , m_hadActiveLoadingStylesheet(false) + , m_needsUpdateActiveStylesheetsOnStyleRecalc(false) + , m_usesSiblingRules(false) + , m_usesSiblingRulesOverride(false) + , m_usesFirstLineRules(false) + , m_usesFirstLetterRules(false) + , m_usesBeforeAfterRules(false) + , m_usesBeforeAfterRulesOverride(false) + , m_usesRemUnits(false) +{ +} + +DocumentStyleSheetCollection::~DocumentStyleSheetCollection() +{ + if (m_pageUserSheet) + m_pageUserSheet->clearOwnerNode(); + if (m_pageGroupUserSheets) { + for (size_t i = 0; i < m_pageGroupUserSheets->size(); ++i) + (*m_pageGroupUserSheets)[i]->clearOwnerNode(); + } + if (m_userSheets) { + for (size_t i = 0; i < m_userSheets->size(); ++i) + (*m_userSheets)[i]->clearOwnerNode(); + } +} + +void DocumentStyleSheetCollection::combineCSSFeatureFlags() +{ + // Delay resetting the flags until after next style recalc since unapplying the style may not work without these set (this is true at least with before/after). + StyleResolver* styleResolver = m_document->styleResolver(); + m_usesSiblingRules = m_usesSiblingRules || styleResolver->usesSiblingRules(); + m_usesFirstLineRules = m_usesFirstLineRules || styleResolver->usesFirstLineRules(); + m_usesBeforeAfterRules = m_usesBeforeAfterRules || styleResolver->usesBeforeAfterRules(); +} + +void DocumentStyleSheetCollection::resetCSSFeatureFlags() +{ + StyleResolver* styleResolver = m_document->styleResolver(); + m_usesSiblingRules = styleResolver->usesSiblingRules(); + m_usesFirstLineRules = styleResolver->usesFirstLineRules(); + m_usesBeforeAfterRules = styleResolver->usesBeforeAfterRules(); +} + +CSSStyleSheet* DocumentStyleSheetCollection::pageUserSheet() +{ + if (m_pageUserSheet) + return m_pageUserSheet.get(); + + Page* owningPage = m_document->page(); + if (!owningPage) + return 0; + + String userSheetText = owningPage->userStyleSheet(); + if (userSheetText.isEmpty()) + return 0; + + // Parse the sheet and cache it. + m_pageUserSheet = CSSStyleSheet::createInline(m_document, m_document->settings()->userStyleSheetLocation()); + m_pageUserSheet->contents()->setIsUserStyleSheet(true); + m_pageUserSheet->contents()->parseString(userSheetText); + return m_pageUserSheet.get(); +} + +void DocumentStyleSheetCollection::clearPageUserSheet() +{ + if (m_pageUserSheet) { + m_pageUserSheet = 0; + m_document->styleResolverChanged(DeferRecalcStyle); + } +} + +void DocumentStyleSheetCollection::updatePageUserSheet() +{ + clearPageUserSheet(); + if (pageUserSheet()) + m_document->styleResolverChanged(RecalcStyleImmediately); +} + +const Vector<RefPtr<CSSStyleSheet> >* DocumentStyleSheetCollection::pageGroupUserSheets() const +{ + if (m_pageGroupUserSheetCacheValid) + return m_pageGroupUserSheets.get(); + + m_pageGroupUserSheetCacheValid = true; + + Page* owningPage = m_document->page(); + if (!owningPage) + return 0; + + const PageGroup& pageGroup = owningPage->group(); + const UserStyleSheetMap* sheetsMap = pageGroup.userStyleSheets(); + if (!sheetsMap) + return 0; + + UserStyleSheetMap::const_iterator end = sheetsMap->end(); + for (UserStyleSheetMap::const_iterator it = sheetsMap->begin(); it != end; ++it) { + const UserStyleSheetVector* sheets = it->second.get(); + for (unsigned i = 0; i < sheets->size(); ++i) { + const UserStyleSheet* sheet = sheets->at(i).get(); + if (sheet->injectedFrames() == InjectInTopFrameOnly && m_document->ownerElement()) + continue; + if (!UserContentURLPattern::matchesPatterns(m_document->url(), sheet->whitelist(), sheet->blacklist())) + continue; + RefPtr<CSSStyleSheet> groupSheet = CSSStyleSheet::createInline(const_cast<Document*>(m_document), sheet->url()); + if (!m_pageGroupUserSheets) + m_pageGroupUserSheets = adoptPtr(new Vector<RefPtr<CSSStyleSheet> >); + m_pageGroupUserSheets->append(groupSheet); + groupSheet->contents()->setIsUserStyleSheet(sheet->level() == UserStyleUserLevel); + groupSheet->contents()->parseString(sheet->source()); + } + } + + return m_pageGroupUserSheets.get(); +} + +void DocumentStyleSheetCollection::clearPageGroupUserSheets() +{ + m_pageGroupUserSheetCacheValid = false; + if (m_pageGroupUserSheets && m_pageGroupUserSheets->size()) { + m_pageGroupUserSheets->clear(); + m_document->styleResolverChanged(DeferRecalcStyle); + } +} + +void DocumentStyleSheetCollection::updatePageGroupUserSheets() +{ + clearPageGroupUserSheets(); + if (pageGroupUserSheets() && pageGroupUserSheets()->size()) + m_document->styleResolverChanged(RecalcStyleImmediately); +} + +void DocumentStyleSheetCollection::addUserSheet(PassRefPtr<StyleSheetContents> userSheet) +{ + if (!m_userSheets) + m_userSheets = adoptPtr(new Vector<RefPtr<CSSStyleSheet> >); + m_userSheets->append(CSSStyleSheet::create(userSheet, m_document)); + m_document->styleResolverChanged(RecalcStyleImmediately); +} + +// This method is called whenever a top-level stylesheet has finished loading. +void DocumentStyleSheetCollection::removePendingSheet(RemovePendingSheetNotificationType notification) +{ + // Make sure we knew this sheet was pending, and that our count isn't out of sync. + ASSERT(m_pendingStylesheets > 0); + + m_pendingStylesheets--; + +#ifdef INSTRUMENT_LAYOUT_SCHEDULING + if (!ownerElement()) + printf("Stylesheet loaded at time %d. %d stylesheets still remain.\n", elapsedTime(), m_pendingStylesheets); +#endif + + if (m_pendingStylesheets) + return; + + if (notification == RemovePendingSheetNotifyLater) { + m_document->setNeedsNotifyRemoveAllPendingStylesheet(); + return; + } + + m_document->didRemoveAllPendingStylesheet(); +} + +void DocumentStyleSheetCollection::addStyleSheetCandidateNode(Node* node, bool createdByParser) +{ + if (!node->inDocument()) + return; + + // Until the <body> exists, we have no choice but to compare document positions, + // since styles outside of the body and head continue to be shunted into the head + // (and thus can shift to end up before dynamically added DOM content that is also + // outside the body). + if ((createdByParser && m_document->body()) || m_styleSheetCandidateNodes.isEmpty()) { + m_styleSheetCandidateNodes.add(node); + return; + } + + // Determine an appropriate insertion point. + StyleSheetCandidateListHashSet::iterator begin = m_styleSheetCandidateNodes.begin(); + StyleSheetCandidateListHashSet::iterator end = m_styleSheetCandidateNodes.end(); + StyleSheetCandidateListHashSet::iterator it = end; + Node* followingNode = 0; + do { + --it; + Node* n = *it; + unsigned short position = n->compareDocumentPosition(node); + if (position == Node::DOCUMENT_POSITION_FOLLOWING) { + m_styleSheetCandidateNodes.insertBefore(followingNode, node); + return; + } + followingNode = n; + } while (it != begin); + + m_styleSheetCandidateNodes.insertBefore(followingNode, node); +} + +void DocumentStyleSheetCollection::removeStyleSheetCandidateNode(Node* node) +{ + m_styleSheetCandidateNodes.remove(node); +} + +void DocumentStyleSheetCollection::collectActiveStyleSheets(Vector<RefPtr<StyleSheet> >& sheets) +{ + if (m_document->settings() && !m_document->settings()->authorAndUserStylesEnabled()) + return; + + StyleSheetCandidateListHashSet::iterator begin = m_styleSheetCandidateNodes.begin(); + StyleSheetCandidateListHashSet::iterator end = m_styleSheetCandidateNodes.end(); + for (StyleSheetCandidateListHashSet::iterator it = begin; it != end; ++it) { + Node* n = *it; + StyleSheet* sheet = 0; + if (n->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) { + // Processing instruction (XML documents only). + // We don't support linking to embedded CSS stylesheets, see <https://bugs.webkit.org/show_bug.cgi?id=49281> for discussion. + ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(n); + sheet = pi->sheet(); +#if ENABLE(XSLT) + // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806> + if (pi->isXSL() && !m_document->transformSourceDocument()) { + // Don't apply XSL transforms until loading is finished. + if (!m_document->parsing()) + m_document->applyXSLTransform(pi); + return; + } +#endif + } else if ((n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag))) +#if ENABLE(SVG) + || (n->isSVGElement() && n->hasTagName(SVGNames::styleTag)) +#endif + ) { + Element* e = static_cast<Element*>(n); + AtomicString title = e->getAttribute(titleAttr); + bool enabledViaScript = false; + if (e->hasLocalName(linkTag)) { + // <LINK> element + HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(n); + if (linkElement->isDisabled()) + continue; + enabledViaScript = linkElement->isEnabledViaScript(); + if (linkElement->styleSheetIsLoading()) { + // it is loading but we should still decide which style sheet set to use + if (!enabledViaScript && !title.isEmpty() && m_preferredStylesheetSetName.isEmpty()) { + const AtomicString& rel = e->getAttribute(relAttr); + if (!rel.contains("alternate")) { + m_preferredStylesheetSetName = title; + m_selectedStylesheetSetName = title; + } + } + continue; + } + if (!linkElement->sheet()) + title = nullAtom; + } + // Get the current preferred styleset. This is the + // set of sheets that will be enabled. +#if ENABLE(SVG) + if (n->isSVGElement() && n->hasTagName(SVGNames::styleTag)) + sheet = static_cast<SVGStyleElement*>(n)->sheet(); + else +#endif + if (e->hasLocalName(linkTag)) + sheet = static_cast<HTMLLinkElement*>(n)->sheet(); + else + // <STYLE> element + sheet = static_cast<HTMLStyleElement*>(n)->sheet(); + // Check to see if this sheet belongs to a styleset + // (thus making it PREFERRED or ALTERNATE rather than + // PERSISTENT). + AtomicString rel = e->getAttribute(relAttr); + if (!enabledViaScript && !title.isEmpty()) { + // Yes, we have a title. + if (m_preferredStylesheetSetName.isEmpty()) { + // No preferred set has been established. If + // we are NOT an alternate sheet, then establish + // us as the preferred set. Otherwise, just ignore + // this sheet. + if (e->hasLocalName(styleTag) || !rel.contains("alternate")) + m_preferredStylesheetSetName = m_selectedStylesheetSetName = title; + } + if (title != m_preferredStylesheetSetName) + sheet = 0; + } + + if (rel.contains("alternate") && title.isEmpty()) + sheet = 0; + } + if (sheet) + sheets.append(sheet); + } +} + +bool DocumentStyleSheetCollection::testAddedStyleSheetRequiresStyleRecalc(StyleSheetContents* stylesheet) +{ + // See if all rules on the sheet are scoped to some specific ids or classes. + // Then test if we actually have any of those in the tree at the moment. + HashSet<AtomicStringImpl*> idScopes; + HashSet<AtomicStringImpl*> classScopes; + if (!StyleResolver::determineStylesheetSelectorScopes(stylesheet, idScopes, classScopes)) + return true; + // Invalidate the subtrees that match the scopes. + Node* node = m_document->firstChild(); + while (node) { + if (!node->isStyledElement()) { + node = node->traverseNextNode(); + continue; + } + StyledElement* element = static_cast<StyledElement*>(node); + if (SelectorChecker::elementMatchesSelectorScopes(element, idScopes, classScopes)) { + element->setNeedsStyleRecalc(); + // The whole subtree is now invalidated, we can skip to the next sibling. + node = node->traverseNextSibling(); + continue; + } + node = node->traverseNextNode(); + } + return false; +} + +void DocumentStyleSheetCollection::analyzeStyleSheetChange(UpdateFlag updateFlag, const Vector<RefPtr<StyleSheet> >& newStylesheets, bool& requiresStyleResolverReset, bool& requiresFullStyleRecalc) +{ + requiresStyleResolverReset = true; + requiresFullStyleRecalc = true; + + // Stylesheets of <style> elements that @import stylesheets are active but loading. We need to trigger a full recalc when such loads are done. + bool hasActiveLoadingStylesheet = false; + unsigned newStylesheetCount = newStylesheets.size(); + for (unsigned i = 0; i < newStylesheetCount; ++i) { + if (newStylesheets[i]->isLoading()) + hasActiveLoadingStylesheet = true; + } + if (m_hadActiveLoadingStylesheet && !hasActiveLoadingStylesheet) { + m_hadActiveLoadingStylesheet = false; + return; + } + m_hadActiveLoadingStylesheet = hasActiveLoadingStylesheet; + + if (updateFlag != OptimizedUpdate) + return; + if (!m_document->styleResolverIfExists()) + return; + + // See if we are just adding stylesheets. + unsigned oldStylesheetCount = m_authorStyleSheets.size(); + if (newStylesheetCount < oldStylesheetCount) + return; + for (unsigned i = 0; i < oldStylesheetCount; ++i) { + if (m_authorStyleSheets[i] != newStylesheets[i]) + return; + } + requiresStyleResolverReset = false; + + // If we are already parsing the body and so may have significant amount of elements, put some effort into trying to avoid style recalcs. + if (!m_document->body() || m_document->hasNodesWithPlaceholderStyle()) + return; + for (unsigned i = oldStylesheetCount; i < newStylesheetCount; ++i) { + if (!newStylesheets[i]->isCSSStyleSheet()) + return; + if (newStylesheets[i]->disabled()) + continue; + if (testAddedStyleSheetRequiresStyleRecalc(static_cast<CSSStyleSheet*>(newStylesheets[i].get())->contents())) + return; + } + requiresFullStyleRecalc = false; +} + +static bool styleSheetsUseRemUnits(const Vector<RefPtr<StyleSheet> >& sheets) +{ + for (unsigned i = 0; i < sheets.size(); ++i) { + if (!sheets[i]->isCSSStyleSheet()) + continue; + if (static_cast<CSSStyleSheet*>(sheets[i].get())->contents()->usesRemUnits()) + return true; + } + return false; +} + +bool DocumentStyleSheetCollection::updateActiveStyleSheets(UpdateFlag updateFlag) +{ + if (m_document->inStyleRecalc()) { + // SVG <use> element may manage to invalidate style selector in the middle of a style recalc. + // https://bugs.webkit.org/show_bug.cgi?id=54344 + // FIXME: This should be fixed in SVG and the call site replaced by ASSERT(!m_inStyleRecalc). + m_needsUpdateActiveStylesheetsOnStyleRecalc = true; + m_document->scheduleForcedStyleRecalc(); + return false; + + } + if (!m_document->renderer() || !m_document->attached()) + return false; + + Vector<RefPtr<StyleSheet> > newStylesheets; + collectActiveStyleSheets(newStylesheets); + + bool requiresStyleResolverReset; + bool requiresFullStyleRecalc; + analyzeStyleSheetChange(updateFlag, newStylesheets, requiresStyleResolverReset, requiresFullStyleRecalc); + + if (requiresStyleResolverReset) + m_document->clearStyleResolver(); + else { + m_document->styleResolver()->appendAuthorStylesheets(m_authorStyleSheets.size(), newStylesheets); + resetCSSFeatureFlags(); + } + m_authorStyleSheets.swap(newStylesheets); + + m_usesRemUnits = styleSheetsUseRemUnits(m_authorStyleSheets); + m_needsUpdateActiveStylesheetsOnStyleRecalc = false; + + m_document->notifySeamlessChildDocumentsOfStylesheetUpdate(); + + return requiresFullStyleRecalc; +} + +void DocumentStyleSheetCollection::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const +{ + MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM); + info.addMember(m_pageUserSheet); + info.addMember(m_pageGroupUserSheets); + info.addMember(m_userSheets); + info.addMember(m_authorStyleSheets); + info.addListHashSet(m_styleSheetCandidateNodes); + info.addMember(m_preferredStylesheetSetName); + info.addMember(m_selectedStylesheetSetName); +} + +} diff --git a/Source/WebCore/dom/DocumentStyleSheetCollection.h b/Source/WebCore/dom/DocumentStyleSheetCollection.h new file mode 100644 index 000000000..a8104dfd9 --- /dev/null +++ b/Source/WebCore/dom/DocumentStyleSheetCollection.h @@ -0,0 +1,143 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2001 Dirk Mueller (mueller@kde.org) + * (C) 2006 Alexey Proskuryakov (ap@webkit.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef DocumentStyleSheetCollection_h +#define DocumentStyleSheetCollection_h + +#include <wtf/FastAllocBase.h> +#include <wtf/ListHashSet.h> +#include <wtf/RefPtr.h> +#include <wtf/Vector.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +class CSSStyleSheet; +class Document; +class Node; +class StyleSheet; +class StyleSheetContents; +class StyleSheetList; + +class DocumentStyleSheetCollection { + WTF_MAKE_FAST_ALLOCATED; +public: + DocumentStyleSheetCollection(Document*); + ~DocumentStyleSheetCollection(); + + const Vector<RefPtr<StyleSheet> >& authorStyleSheets() { return m_authorStyleSheets; } + + CSSStyleSheet* pageUserSheet(); + const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets() const; + const Vector<RefPtr<CSSStyleSheet> >* documentUserSheets() const { return m_userSheets.get(); } + + void addStyleSheetCandidateNode(Node*, bool createdByParser); + void removeStyleSheetCandidateNode(Node*); + + void clearPageUserSheet(); + void updatePageUserSheet(); + void clearPageGroupUserSheets(); + void updatePageGroupUserSheets(); + + void addUserSheet(PassRefPtr<StyleSheetContents> userSheet); + + bool needsUpdateActiveStylesheetsOnStyleRecalc() { return m_needsUpdateActiveStylesheetsOnStyleRecalc; } + + enum UpdateFlag { FullUpdate, OptimizedUpdate }; + bool updateActiveStyleSheets(UpdateFlag); + + String preferredStylesheetSetName() const { return m_preferredStylesheetSetName; } + String selectedStylesheetSetName() const { return m_selectedStylesheetSetName; } + void setPreferredStylesheetSetName(const String& name) { m_preferredStylesheetSetName = name; } + void setSelectedStylesheetSetName(const String& name) { m_selectedStylesheetSetName = name; } + + void addPendingSheet() { m_pendingStylesheets++; } + enum RemovePendingSheetNotificationType { + RemovePendingSheetNotifyImmediately, + RemovePendingSheetNotifyLater + }; + void removePendingSheet(RemovePendingSheetNotificationType = RemovePendingSheetNotifyImmediately); + + bool hasPendingSheets() const { return m_pendingStylesheets > 0; } + + bool usesSiblingRules() const { return m_usesSiblingRules || m_usesSiblingRulesOverride; } + void setUsesSiblingRulesOverride(bool b) { m_usesSiblingRulesOverride = b; } + bool usesFirstLineRules() const { return m_usesFirstLineRules; } + bool usesFirstLetterRules() const { return m_usesFirstLetterRules; } + void setUsesFirstLetterRules(bool b) { m_usesFirstLetterRules = b; } + bool usesBeforeAfterRules() const { return m_usesBeforeAfterRules || m_usesBeforeAfterRulesOverride; } + void setUsesBeforeAfterRulesOverride(bool b) { m_usesBeforeAfterRulesOverride = b; } + bool usesRemUnits() const { return m_usesRemUnits; } + void setUsesRemUnit(bool b) { m_usesRemUnits = b; } + + void combineCSSFeatureFlags(); + void resetCSSFeatureFlags(); + + void reportMemoryUsage(MemoryObjectInfo*) const; + +private: + void collectActiveStyleSheets(Vector<RefPtr<StyleSheet> >&); + bool testAddedStyleSheetRequiresStyleRecalc(StyleSheetContents*); + void analyzeStyleSheetChange(UpdateFlag, const Vector<RefPtr<StyleSheet> >& newStylesheets, bool& requiresStyleResolverReset, bool& requiresFullStyleRecalc); + + Document* m_document; + + Vector<RefPtr<StyleSheet> > m_authorStyleSheets; + + // Track the number of currently loading top-level stylesheets needed for rendering. + // Sheets loaded using the @import directive are not included in this count. + // We use this count of pending sheets to detect when we can begin attaching + // elements and when it is safe to execute scripts. + int m_pendingStylesheets; + + RefPtr<CSSStyleSheet> m_pageUserSheet; + mutable OwnPtr<Vector<RefPtr<CSSStyleSheet> > > m_pageGroupUserSheets; + OwnPtr<Vector<RefPtr<CSSStyleSheet> > > m_userSheets; + mutable bool m_pageGroupUserSheetCacheValid; + + bool m_hadActiveLoadingStylesheet; + bool m_needsUpdateActiveStylesheetsOnStyleRecalc; + + typedef ListHashSet<Node*, 32> StyleSheetCandidateListHashSet; + StyleSheetCandidateListHashSet m_styleSheetCandidateNodes; + + String m_preferredStylesheetSetName; + String m_selectedStylesheetSetName; + + bool m_usesSiblingRules; + bool m_usesSiblingRulesOverride; + bool m_usesFirstLineRules; + bool m_usesFirstLetterRules; + bool m_usesBeforeAfterRules; + bool m_usesBeforeAfterRulesOverride; + bool m_usesRemUnits; +}; + +} + +#endif + diff --git a/Source/WebCore/dom/DocumentType.idl b/Source/WebCore/dom/DocumentType.idl index 729023271..4206de70d 100644 --- a/Source/WebCore/dom/DocumentType.idl +++ b/Source/WebCore/dom/DocumentType.idl @@ -35,6 +35,9 @@ module core { readonly attribute [TreatReturnedNullStringAs=Null] DOMString systemId; readonly attribute [TreatReturnedNullStringAs=Null] DOMString internalSubset; + // DOM 4 + void remove() + raises(DOMException); }; } diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp index 15804a3fa..9176f8977 100644 --- a/Source/WebCore/dom/Element.cpp +++ b/Source/WebCore/dom/Element.cpp @@ -999,7 +999,7 @@ void Element::removedFrom(ContainerNode* insertionPoint) void Element::attach() { suspendPostAttachCallbacks(); - RenderWidget::suspendWidgetHierarchyUpdates(); + WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; createRendererIfNeeded(); StyleResolverParentPusher parentPusher(this); @@ -1028,7 +1028,6 @@ void Element::attach() } } - RenderWidget::resumeWidgetHierarchyUpdates(); resumePostAttachCallbacks(); } @@ -1042,7 +1041,7 @@ void Element::unregisterNamedFlowContentNode() void Element::detach() { - RenderWidget::suspendWidgetHierarchyUpdates(); + WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; unregisterNamedFlowContentNode(); cancelFocusAppearanceUpdate(); if (hasRareData()) { @@ -1055,8 +1054,6 @@ void Element::detach() shadow->detach(); } ContainerNode::detach(); - - RenderWidget::resumeWidgetHierarchyUpdates(); } bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle) @@ -1176,7 +1173,7 @@ void Element::recalcStyle(StyleChange change) // If "rem" units are used anywhere in the document, and if the document element's font size changes, then go ahead and force font updating // all the way down the tree. This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway). - if (document()->usesRemUnits() && document()->documentElement() == this && ch != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize()) { + if (document()->styleSheetCollection()->usesRemUnits() && document()->documentElement() == this && ch != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize()) { // Cached RenderStyles may depend on the rem units. document()->styleResolver()->invalidateMatchedPropertiesCache(); change = Force; diff --git a/Source/WebCore/dom/Element.idl b/Source/WebCore/dom/Element.idl index 4bd64ed4e..6b3427c3a 100644 --- a/Source/WebCore/dom/Element.idl +++ b/Source/WebCore/dom/Element.idl @@ -120,6 +120,10 @@ module core { readonly attribute Element nextElementSibling; readonly attribute unsigned long childElementCount; + // DOM 4 + void remove() + raises(DOMException); + #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT // CSSOM View Module API ClientRectList getClientRects(); diff --git a/Source/WebCore/dom/ElementAttributeData.cpp b/Source/WebCore/dom/ElementAttributeData.cpp index 03f7b81fc..5a7f34125 100644 --- a/Source/WebCore/dom/ElementAttributeData.cpp +++ b/Source/WebCore/dom/ElementAttributeData.cpp @@ -31,6 +31,7 @@ #include "CSSStyleSheet.h" #include "StyledElement.h" #include "WebCoreMemoryInstrumentation.h" +#include <wtf/MemoryInstrumentationVector.h> namespace WebCore { @@ -300,7 +301,7 @@ void ElementAttributeData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) info.addMember(m_classNames); info.addMember(m_idForStyleResolution); if (m_isMutable) - info.addVector(mutableAttributeVector()); + info.addMember(mutableAttributeVector()); for (unsigned i = 0, len = length(); i < len; i++) info.addMember(*attributeItem(i)); } diff --git a/Source/WebCore/dom/EventNames.h b/Source/WebCore/dom/EventNames.h index b3cd846ea..136f7aac2 100644 --- a/Source/WebCore/dom/EventNames.h +++ b/Source/WebCore/dom/EventNames.h @@ -229,7 +229,7 @@ namespace WebCore { macro(unmute) \ macro(icechange) \ macro(icecandidate) \ - macro(negotationneeded) \ + macro(negotiationneeded) \ \ macro(show) \ \ diff --git a/Source/WebCore/dom/Node.cpp b/Source/WebCore/dom/Node.cpp index aef669c50..8ab3352f6 100644 --- a/Source/WebCore/dom/Node.cpp +++ b/Source/WebCore/dom/Node.cpp @@ -630,8 +630,6 @@ void Node::remove(ExceptionCode& ec) { if (ContainerNode* parent = parentNode()) parent->removeChild(this, ec); - else - ec = HIERARCHY_REQUEST_ERR; } void Node::normalize() diff --git a/Source/WebCore/dom/ProcessingInstruction.cpp b/Source/WebCore/dom/ProcessingInstruction.cpp index ef13b4690..6759becbc 100644 --- a/Source/WebCore/dom/ProcessingInstruction.cpp +++ b/Source/WebCore/dom/ProcessingInstruction.cpp @@ -23,9 +23,10 @@ #include "CSSStyleSheet.h" #include "CachedCSSStyleSheet.h" +#include "CachedResourceLoader.h" #include "CachedXSLStyleSheet.h" #include "Document.h" -#include "CachedResourceLoader.h" +#include "DocumentStyleSheetCollection.h" #include "ExceptionCode.h" #include "Frame.h" #include "FrameLoader.h" @@ -65,7 +66,7 @@ ProcessingInstruction::~ProcessingInstruction() m_cachedSheet->removeClient(this); if (inDocument()) - document()->removeStyleSheetCandidateNode(this); + document()->styleSheetCollection()->removeStyleSheetCandidateNode(this); } void ProcessingInstruction::setData(const String& data, ExceptionCode&) @@ -160,7 +161,7 @@ void ProcessingInstruction::checkStyleSheet() return; m_loading = true; - document()->addPendingSheet(); + document()->styleSheetCollection()->addPendingSheet(); ResourceRequest request(document()->completeURL(href)); #if ENABLE(XSLT) @@ -180,7 +181,7 @@ void ProcessingInstruction::checkStyleSheet() else { // The request may have been denied if (for example) the stylesheet is local and the document is remote. m_loading = false; - document()->removePendingSheet(); + document()->styleSheetCollection()->removePendingSheet(); } } } @@ -198,7 +199,7 @@ bool ProcessingInstruction::isLoading() const bool ProcessingInstruction::sheetLoaded() { if (!isLoading()) { - document()->removePendingSheet(); + document()->styleSheetCollection()->removePendingSheet(); return true; } return false; @@ -293,7 +294,7 @@ Node::InsertionNotificationRequest ProcessingInstruction::insertedInto(Container Node::insertedInto(insertionPoint); if (!insertionPoint->inDocument()) return InsertionDone; - document()->addStyleSheetCandidateNode(this, m_createdByParser); + document()->styleSheetCollection()->addStyleSheetCandidateNode(this, m_createdByParser); checkStyleSheet(); return InsertionDone; } @@ -304,7 +305,7 @@ void ProcessingInstruction::removedFrom(ContainerNode* insertionPoint) if (!insertionPoint->inDocument()) return; - document()->removeStyleSheetCandidateNode(this); + document()->styleSheetCollection()->removeStyleSheetCandidateNode(this); if (m_sheet) { ASSERT(m_sheet->ownerNode() == this); diff --git a/Source/WebCore/dom/StyleElement.cpp b/Source/WebCore/dom/StyleElement.cpp index dd4de2901..ff22fe9db 100644 --- a/Source/WebCore/dom/StyleElement.cpp +++ b/Source/WebCore/dom/StyleElement.cpp @@ -24,6 +24,7 @@ #include "Attribute.h" #include "ContentSecurityPolicy.h" #include "Document.h" +#include "DocumentStyleSheetCollection.h" #include "Element.h" #include "MediaList.h" #include "MediaQueryEvaluator.h" @@ -63,7 +64,7 @@ void StyleElement::insertedIntoDocument(Document* document, Element* element) { ASSERT(document); ASSERT(element); - document->addStyleSheetCandidateNode(element, m_createdByParser); + document->styleSheetCollection()->addStyleSheetCandidateNode(element, m_createdByParser); if (m_createdByParser) return; @@ -74,7 +75,7 @@ void StyleElement::removedFromDocument(Document* document, Element* element) { ASSERT(document); ASSERT(element); - document->removeStyleSheetCandidateNode(element); + document->styleSheetCollection()->removeStyleSheetCandidateNode(element); if (m_sheet) clearSheet(); @@ -90,7 +91,7 @@ void StyleElement::clearDocumentData(Document* document, Element* element) m_sheet->clearOwnerNode(); if (element->inDocument()) - document->removeStyleSheetCandidateNode(element); + document->styleSheetCollection()->removeStyleSheetCandidateNode(element); } void StyleElement::childrenChanged(Element* element) @@ -152,7 +153,7 @@ void StyleElement::createSheet(Element* e, WTF::OrdinalNumber startLineNumber, c Document* document = e->document(); if (m_sheet) { if (m_sheet->isLoading()) - document->removePendingSheet(); + document->styleSheetCollection()->removePendingSheet(); clearSheet(); } @@ -168,7 +169,7 @@ void StyleElement::createSheet(Element* e, WTF::OrdinalNumber startLineNumber, c MediaQueryEvaluator screenEval("screen", true); MediaQueryEvaluator printEval("print", true); if (screenEval.eval(mediaQueries.get()) || printEval.eval(mediaQueries.get())) { - document->addPendingSheet(); + document->styleSheetCollection()->addPendingSheet(); m_loading = true; m_sheet = CSSStyleSheet::createInline(e, KURL(), document->inputEncoding()); @@ -197,14 +198,14 @@ bool StyleElement::sheetLoaded(Document* document) if (isLoading()) return false; - document->removePendingSheet(); + document->styleSheetCollection()->removePendingSheet(); return true; } void StyleElement::startLoadingDynamicSheet(Document* document) { ASSERT(document); - document->addPendingSheet(); + document->styleSheetCollection()->addPendingSheet(); } } diff --git a/Source/WebCore/html/DateTimeFieldsState.cpp b/Source/WebCore/html/DateTimeFieldsState.cpp index 8e2bd6c1c..990389dc4 100644 --- a/Source/WebCore/html/DateTimeFieldsState.cpp +++ b/Source/WebCore/html/DateTimeFieldsState.cpp @@ -67,6 +67,13 @@ DateTimeFieldsState::DateTimeFieldsState() { } +unsigned DateTimeFieldsState::hour23() const +{ + if (!hasHour() || !hasAMPM()) + return emptyValue; + return (m_hour % 12) + (m_ampm == AMPMValuePM ? 12 : 0); +} + DateTimeFieldsState DateTimeFieldsState::restoreFormControlState(const FormControlState& state) { DateTimeFieldsState dateTimeFieldsState; diff --git a/Source/WebCore/html/DateTimeFieldsState.h b/Source/WebCore/html/DateTimeFieldsState.h index b6240629e..6fb444071 100644 --- a/Source/WebCore/html/DateTimeFieldsState.h +++ b/Source/WebCore/html/DateTimeFieldsState.h @@ -57,6 +57,7 @@ public: AMPMValue ampm() const { return m_ampm; } unsigned dayOfMonth() const { return m_dayOfMonth; } unsigned hour() const { return m_hour; } + unsigned hour23() const; unsigned millisecond() const { return m_millisecond; } unsigned minute() const { return m_minute; } unsigned month() const { return m_month; } @@ -88,7 +89,7 @@ private: unsigned m_year; unsigned m_month; unsigned m_dayOfMonth; - unsigned m_hour; + unsigned m_hour; // 1 to 12. unsigned m_minute; unsigned m_second; unsigned m_millisecond; diff --git a/Source/WebCore/html/HTMLLinkElement.cpp b/Source/WebCore/html/HTMLLinkElement.cpp index d2868b610..fdc7a5cce 100644 --- a/Source/WebCore/html/HTMLLinkElement.cpp +++ b/Source/WebCore/html/HTMLLinkElement.cpp @@ -30,6 +30,7 @@ #include "CachedResource.h" #include "CachedResourceLoader.h" #include "Document.h" +#include "DocumentStyleSheetCollection.h" #include "EventSender.h" #include "Frame.h" #include "FrameLoader.h" @@ -87,7 +88,7 @@ HTMLLinkElement::~HTMLLinkElement() m_cachedSheet->removeClient(this); if (inDocument()) - document()->removeStyleSheetCandidateNode(this); + document()->styleSheetCollection()->removeStyleSheetCandidateNode(this); linkLoadEventSender().cancelEvent(this); } @@ -254,7 +255,7 @@ Node::InsertionNotificationRequest HTMLLinkElement::insertedInto(ContainerNode* if (m_isInShadowTree) return InsertionDone; - document()->addStyleSheetCandidateNode(this, m_createdByParser); + document()->styleSheetCollection()->addStyleSheetCandidateNode(this, m_createdByParser); process(); return InsertionDone; @@ -272,7 +273,7 @@ void HTMLLinkElement::removedFrom(ContainerNode* insertionPoint) ASSERT(!m_sheet); return; } - document()->removeStyleSheetCandidateNode(this); + document()->styleSheetCollection()->removeStyleSheetCandidateNode(this); if (m_sheet) clearSheet(); @@ -455,7 +456,7 @@ void HTMLLinkElement::addPendingSheet(PendingSheetType type) if (m_pendingSheetType == NonBlocking) return; - document()->addPendingSheet(); + document()->styleSheetCollection()->addPendingSheet(); } void HTMLLinkElement::removePendingSheet(RemovePendingSheetNotificationType notification) @@ -471,10 +472,10 @@ void HTMLLinkElement::removePendingSheet(RemovePendingSheetNotificationType noti return; } - document()->removePendingSheet( + document()->styleSheetCollection()->removePendingSheet( notification == RemovePendingSheetNotifyImmediately - ? Document::RemovePendingSheetNotifyImmediately - : Document::RemovePendingSheetNotifyLater); + ? DocumentStyleSheetCollection::RemovePendingSheetNotifyImmediately + : DocumentStyleSheetCollection::RemovePendingSheetNotifyLater); } DOMSettableTokenList* HTMLLinkElement::sizes() const diff --git a/Source/WebCore/html/HTMLQuoteElement.cpp b/Source/WebCore/html/HTMLQuoteElement.cpp index 05a33ab5e..d5be2f2f7 100644 --- a/Source/WebCore/html/HTMLQuoteElement.cpp +++ b/Source/WebCore/html/HTMLQuoteElement.cpp @@ -24,6 +24,7 @@ #include "HTMLQuoteElement.h" #include "Document.h" +#include "DocumentStyleSheetCollection.h" #include "HTMLNames.h" namespace WebCore { @@ -44,7 +45,7 @@ PassRefPtr<HTMLQuoteElement> HTMLQuoteElement::create(const QualifiedName& tagNa Node::InsertionNotificationRequest HTMLQuoteElement::insertedInto(ContainerNode* insertionPoint) { if (hasTagName(qTag)) - document()->setUsesBeforeAfterRules(true); + document()->styleSheetCollection()->setUsesBeforeAfterRulesOverride(true); return HTMLElement::insertedInto(insertionPoint); } diff --git a/Source/WebCore/html/HTMLViewSourceDocument.cpp b/Source/WebCore/html/HTMLViewSourceDocument.cpp index 3de813770..a4da71a25 100644 --- a/Source/WebCore/html/HTMLViewSourceDocument.cpp +++ b/Source/WebCore/html/HTMLViewSourceDocument.cpp @@ -27,6 +27,7 @@ #include "Attribute.h" #include "DOMImplementation.h" +#include "DocumentStyleSheetCollection.h" #include "HTMLAnchorElement.h" #include "HTMLBRElement.h" #include "HTMLBaseElement.h" @@ -52,7 +53,7 @@ HTMLViewSourceDocument::HTMLViewSourceDocument(Frame* frame, const KURL& url, co : HTMLDocument(frame, url) , m_type(mimeType) { - setUsesBeforeAfterRules(true); + styleSheetCollection()->setUsesBeforeAfterRulesOverride(true); setIsViewSource(true); setCompatibilityMode(QuirksMode); diff --git a/Source/WebCore/html/TimeInputType.cpp b/Source/WebCore/html/TimeInputType.cpp index 4b5bb1f15..a0051513a 100644 --- a/Source/WebCore/html/TimeInputType.cpp +++ b/Source/WebCore/html/TimeInputType.cpp @@ -48,6 +48,7 @@ #include "KeyboardEvent.h" #include "Localizer.h" #include "ShadowRoot.h" +#include <wtf/text/WTFString.h> #endif namespace WebCore { @@ -149,13 +150,32 @@ void TimeInputType::DateTimeEditControlOwnerImpl::didFocusOnControl() void TimeInputType::DateTimeEditControlOwnerImpl::editControlValueChanged() { RefPtr<HTMLInputElement> input(m_timeInputType.element()); - input->setValueInternal(m_timeInputType.serialize(Decimal::fromDouble(m_timeInputType.m_dateTimeEditElement->valueAsDouble())), DispatchNoEvent); + input->setValueInternal(m_timeInputType.m_dateTimeEditElement->value(), DispatchNoEvent); input->setNeedsStyleRecalc(); input->dispatchFormControlInputEvent(); input->dispatchFormControlChangeEvent(); input->notifyFormStateChanged(); } + +String TimeInputType::DateTimeEditControlOwnerImpl::formatDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) const +{ + if (!dateTimeFieldsState.hasHour() || !dateTimeFieldsState.hasMinute() || !dateTimeFieldsState.hasAMPM()) + return emptyString(); + if (dateTimeFieldsState.hasMillisecond() && dateTimeFieldsState.millisecond()) + return String::format("%02u:%02u:%02u.%03u", + dateTimeFieldsState.hour23(), + dateTimeFieldsState.minute(), + dateTimeFieldsState.hasSecond() ? dateTimeFieldsState.second() : 0, + dateTimeFieldsState.millisecond()); + if (dateTimeFieldsState.hasSecond() && dateTimeFieldsState.second()) + return String::format("%02u:%02u:%02u", + dateTimeFieldsState.hour23(), + dateTimeFieldsState.minute(), + dateTimeFieldsState.second()); + return String::format("%02u:%02u", dateTimeFieldsState.hour23(), dateTimeFieldsState.minute()); +} + bool TimeInputType::hasCustomFocusLogic() const { return false; @@ -271,7 +291,7 @@ void TimeInputType::restoreFormControlState(const FormControlState& state) setMillisecondToDateComponents(createStepRange(AnyIsDefaultStep).minimum().toDouble(), &date); DateTimeFieldsState dateTimeFieldsState = DateTimeFieldsState::restoreFormControlState(state); m_dateTimeEditElement->setValueAsDateTimeFieldsState(dateTimeFieldsState, date); - element()->setValueInternal(serialize(Decimal::fromDouble(m_dateTimeEditElement->valueAsDouble())), DispatchNoEvent); + element()->setValueInternal(m_dateTimeEditElement->value(), DispatchNoEvent); } FormControlState TimeInputType::saveFormControlState() const diff --git a/Source/WebCore/html/TimeInputType.h b/Source/WebCore/html/TimeInputType.h index 0787c3a21..59e272102 100644 --- a/Source/WebCore/html/TimeInputType.h +++ b/Source/WebCore/html/TimeInputType.h @@ -71,6 +71,7 @@ private: virtual void didBlurFromControl() OVERRIDE FINAL; virtual void didFocusOnControl() OVERRIDE FINAL; virtual void editControlValueChanged() OVERRIDE FINAL; + virtual String formatDateTimeFieldsState(const DateTimeFieldsState&) const OVERRIDE FINAL; virtual bool isEditControlOwnerDisabled() const OVERRIDE FINAL; virtual bool isEditControlOwnerReadOnly() const OVERRIDE FINAL; diff --git a/Source/WebCore/html/parser/HTMLTreeBuilder.cpp b/Source/WebCore/html/parser/HTMLTreeBuilder.cpp index 131cdbff6..940800ef8 100644 --- a/Source/WebCore/html/parser/HTMLTreeBuilder.cpp +++ b/Source/WebCore/html/parser/HTMLTreeBuilder.cpp @@ -686,9 +686,7 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token) } if (!m_framesetOk) return; - ExceptionCode ec = 0; - m_tree.openElements()->bodyElement()->remove(ec); - ASSERT(!ec); + m_tree.openElements()->bodyElement()->remove(ASSERT_NO_EXCEPTION); m_tree.openElements()->popUntil(m_tree.openElements()->bodyElement()); m_tree.openElements()->popHTMLBodyElement(); ASSERT(m_tree.openElements()->top() == m_tree.openElements()->htmlElement()); diff --git a/Source/WebCore/html/shadow/DateTimeEditElement.cpp b/Source/WebCore/html/shadow/DateTimeEditElement.cpp index 07befd874..ad4870ca8 100644 --- a/Source/WebCore/html/shadow/DateTimeEditElement.cpp +++ b/Source/WebCore/html/shadow/DateTimeEditElement.cpp @@ -450,6 +450,13 @@ void DateTimeEditElement::updateUIState() } } +String DateTimeEditElement::value() const +{ + if (!m_editControlOwner) + return emptyString(); + return m_editControlOwner->formatDateTimeFieldsState(valueAsDateTimeFieldsState()); +} + DateTimeFieldsState DateTimeEditElement::valueAsDateTimeFieldsState() const { DateTimeFieldsState dateTimeFieldsState; @@ -458,20 +465,6 @@ DateTimeFieldsState DateTimeEditElement::valueAsDateTimeFieldsState() const return dateTimeFieldsState; } -double DateTimeEditElement::valueAsDouble() const -{ - double value = 0; - - for (size_t fieldIndex = 0; fieldIndex < m_fields.size(); ++fieldIndex) { - const DateTimeFieldElement* const field = m_fields[fieldIndex]; - if (!field->hasValue()) - return std::numeric_limits<double>::quiet_NaN(); - value += field->valueAsDouble(); - } - - return value; -} - } // namespace WebCore #endif diff --git a/Source/WebCore/html/shadow/DateTimeEditElement.h b/Source/WebCore/html/shadow/DateTimeEditElement.h index e547cbdea..84cf229c6 100644 --- a/Source/WebCore/html/shadow/DateTimeEditElement.h +++ b/Source/WebCore/html/shadow/DateTimeEditElement.h @@ -55,6 +55,7 @@ public: virtual void didBlurFromControl() = 0; virtual void didFocusOnControl() = 0; virtual void editControlValueChanged() = 0; + virtual String formatDateTimeFieldsState(const DateTimeFieldsState&) const = 0; virtual bool isEditControlOwnerDisabled() const = 0; virtual bool isEditControlOwnerReadOnly() const = 0; }; @@ -88,8 +89,8 @@ public: void setEmptyValue(const LayoutParameters&, const DateComponents& dateForReadOnlyField); void setValueAsDate(const LayoutParameters&, const DateComponents&); void setValueAsDateTimeFieldsState(const DateTimeFieldsState&, const DateComponents& dateForReadOnlyField); + String value() const; DateTimeFieldsState valueAsDateTimeFieldsState() const; - double valueAsDouble() const; private: static const size_t invalidFieldIndex = static_cast<size_t>(-1); diff --git a/Source/WebCore/html/shadow/DateTimeFieldElement.cpp b/Source/WebCore/html/shadow/DateTimeFieldElement.cpp index 74817570a..a0ec51e59 100644 --- a/Source/WebCore/html/shadow/DateTimeFieldElement.cpp +++ b/Source/WebCore/html/shadow/DateTimeFieldElement.cpp @@ -186,11 +186,6 @@ void DateTimeFieldElement::updateVisibleValue(EventBehavior eventBehavior) m_fieldOwner->fieldValueChanged(); } -double DateTimeFieldElement::valueAsDouble() const -{ - return hasValue() ? valueAsInteger() * unitInMillisecond() : std::numeric_limits<double>::quiet_NaN(); -} - } // namespace WebCore #endif diff --git a/Source/WebCore/html/shadow/DateTimeFieldElement.h b/Source/WebCore/html/shadow/DateTimeFieldElement.h index e8d25cf91..f5c9810a1 100644 --- a/Source/WebCore/html/shadow/DateTimeFieldElement.h +++ b/Source/WebCore/html/shadow/DateTimeFieldElement.h @@ -70,7 +70,6 @@ public: virtual void stepDown() = 0; virtual void stepUp() = 0; virtual String value() const = 0; - double valueAsDouble() const; virtual int valueAsInteger() const = 0; virtual String visibleValue() const = 0; @@ -83,7 +82,6 @@ protected: void initialize(const AtomicString& shadowPseudoId, const String& axHelpText); virtual int maximum() const = 0; virtual int minimum() const = 0; - virtual double unitInMillisecond() const = 0; void updateVisibleValue(EventBehavior); private: diff --git a/Source/WebCore/html/shadow/DateTimeFieldElements.cpp b/Source/WebCore/html/shadow/DateTimeFieldElements.cpp index 2016c69a8..c2f458a21 100644 --- a/Source/WebCore/html/shadow/DateTimeFieldElements.cpp +++ b/Source/WebCore/html/shadow/DateTimeFieldElements.cpp @@ -30,7 +30,6 @@ #include "DateComponents.h" #include "DateTimeFieldsState.h" #include "LocalizedStrings.h" -#include <wtf/DateMath.h> namespace WebCore { @@ -68,11 +67,6 @@ void DateTimeAMPMFieldElement::setValueAsDateTimeFieldsState(const DateTimeField setEmptyValue(dateForReadOnlyField); } -double DateTimeAMPMFieldElement::unitInMillisecond() const -{ - return msPerHour * 12; -} - // ---------------------------- DateTimeHourFieldElement::DateTimeHourFieldElement(Document* document, FieldOwner& fieldOwner, int minimum, int maximum) @@ -173,11 +167,6 @@ void DateTimeHourFieldElement::setValueAsInteger(int valueAsHour23, EventBehavio DateTimeNumericFieldElement::setValueAsInteger(range().minimum && !value ? m_alignment : value, eventBehavior); } -double DateTimeHourFieldElement::unitInMillisecond() const -{ - return msPerHour; -} - int DateTimeHourFieldElement::valueAsInteger() const { return hasValue() ? DateTimeNumericFieldElement::valueAsInteger() % m_alignment : -1; @@ -224,11 +213,6 @@ void DateTimeMillisecondFieldElement::setValueAsDateTimeFieldsState(const DateTi setValueAsInteger(value); } -double DateTimeMillisecondFieldElement::unitInMillisecond() const -{ - return 1; -} - // ---------------------------- DateTimeMinuteFieldElement::DateTimeMinuteFieldElement(Document* document, FieldOwner& fieldOwner) @@ -270,11 +254,6 @@ void DateTimeMinuteFieldElement::setValueAsDateTimeFieldsState(const DateTimeFie setValueAsInteger(value); } -double DateTimeMinuteFieldElement::unitInMillisecond() const -{ - return msPerMinute; -} - // ---------------------------- DateTimeSecondFieldElement::DateTimeSecondFieldElement(Document* document, FieldOwner& fieldOwner) @@ -316,11 +295,6 @@ void DateTimeSecondFieldElement::setValueAsDateTimeFieldsState(const DateTimeFie setValueAsInteger(value); } -double DateTimeSecondFieldElement::unitInMillisecond() const -{ - return msPerSecond; -} - } // namespace WebCore #endif diff --git a/Source/WebCore/html/shadow/DateTimeFieldElements.h b/Source/WebCore/html/shadow/DateTimeFieldElements.h index e141f838f..23f3403ea 100644 --- a/Source/WebCore/html/shadow/DateTimeFieldElements.h +++ b/Source/WebCore/html/shadow/DateTimeFieldElements.h @@ -45,7 +45,6 @@ private: virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL; virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&, const DateComponents& dateForReadOnlyField) OVERRIDE FINAL; - virtual double unitInMillisecond() const OVERRIDE FINAL; }; @@ -69,7 +68,6 @@ private: virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL; virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&, const DateComponents& dateForReadOnlyField) OVERRIDE FINAL; virtual void setValueAsInteger(int, EventBehavior = DispatchNoEvent) OVERRIDE FINAL; - virtual double unitInMillisecond() const OVERRIDE FINAL; virtual int valueAsInteger() const OVERRIDE FINAL; const int m_alignment; @@ -88,7 +86,6 @@ private: virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL; virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&, const DateComponents& dateForReadOnlyField) OVERRIDE FINAL; - virtual double unitInMillisecond() const OVERRIDE FINAL; }; class DateTimeMinuteFieldElement : public DateTimeNumericFieldElement { @@ -104,7 +101,6 @@ private: virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL; virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&, const DateComponents& dateForReadOnlyField) OVERRIDE FINAL; - virtual double unitInMillisecond() const OVERRIDE FINAL; }; class DateTimeSecondFieldElement : public DateTimeNumericFieldElement { @@ -120,7 +116,6 @@ private: virtual void populateDateTimeFieldsState(DateTimeFieldsState&) OVERRIDE FINAL; virtual void setValueAsDate(const DateComponents&) OVERRIDE FINAL; virtual void setValueAsDateTimeFieldsState(const DateTimeFieldsState&, const DateComponents& dateForReadOnlyField) OVERRIDE FINAL; - virtual double unitInMillisecond() const OVERRIDE FINAL; }; } // namespace WebCore diff --git a/Source/WebCore/html/track/TextTrackCue.cpp b/Source/WebCore/html/track/TextTrackCue.cpp index 299fc1b7c..2fd4f1d4b 100644 --- a/Source/WebCore/html/track/TextTrackCue.cpp +++ b/Source/WebCore/html/track/TextTrackCue.cpp @@ -742,8 +742,7 @@ PassRefPtr<TextTrackCueBox> TextTrackCue::getDisplayTree() void TextTrackCue::removeDisplayTree() { - if (m_displayTree->parentNode()) - m_displayTree->remove(ASSERT_NO_EXCEPTION); + m_displayTree->remove(ASSERT_NO_EXCEPTION); } std::pair<double, double> TextTrackCue::getPositionCoordinates() const diff --git a/Source/WebCore/inspector/InjectedScriptCanvasModule.cpp b/Source/WebCore/inspector/InjectedScriptCanvasModule.cpp index db278d976..b1f1dca27 100644 --- a/Source/WebCore/inspector/InjectedScriptCanvasModule.cpp +++ b/Source/WebCore/inspector/InjectedScriptCanvasModule.cpp @@ -59,20 +59,30 @@ String InjectedScriptCanvasModule::source() const return String(reinterpret_cast<const char*>(InjectedScriptCanvasModuleSource_js), sizeof(InjectedScriptCanvasModuleSource_js)); } +ScriptObject InjectedScriptCanvasModule::wrapCanvas2DContext(const ScriptObject& context) +{ + return callWrapContextFunction("wrapCanvas2DContext", context); +} + #if ENABLE(WEBGL) ScriptObject InjectedScriptCanvasModule::wrapWebGLContext(const ScriptObject& glContext) { - ScriptFunctionCall function(injectedScriptObject(), "wrapWebGLContext"); - function.appendArgument(glContext); + return callWrapContextFunction("wrapWebGLContext", glContext); +} +#endif // ENABLE(WEBGL) + +ScriptObject InjectedScriptCanvasModule::callWrapContextFunction(const String& functionName, const ScriptObject& context) +{ + ScriptFunctionCall function(injectedScriptObject(), functionName); + function.appendArgument(context); bool hadException = false; ScriptValue resultValue = callFunctionWithEvalEnabled(function, hadException); if (hadException || resultValue.hasNoValue() || !resultValue.isObject()) { ASSERT_NOT_REACHED(); return ScriptObject(); } - return ScriptObject(glContext.scriptState(), resultValue); + return ScriptObject(context.scriptState(), resultValue); } -#endif // ENABLE(WEBGL) void InjectedScriptCanvasModule::captureFrame(ErrorString* errorString, String* traceLogId) { diff --git a/Source/WebCore/inspector/InjectedScriptCanvasModule.h b/Source/WebCore/inspector/InjectedScriptCanvasModule.h index 4de223660..2e960aa6e 100644 --- a/Source/WebCore/inspector/InjectedScriptCanvasModule.h +++ b/Source/WebCore/inspector/InjectedScriptCanvasModule.h @@ -50,14 +50,18 @@ public: static InjectedScriptCanvasModule moduleForState(InjectedScriptManager*, ScriptState*); + ScriptObject wrapCanvas2DContext(const ScriptObject&); #if ENABLE(WEBGL) - ScriptObject wrapWebGLContext(const ScriptObject& glContext); + ScriptObject wrapWebGLContext(const ScriptObject&); #endif void captureFrame(ErrorString*, String*); void dropTraceLog(ErrorString*, const String&); void traceLog(ErrorString*, const String&, RefPtr<TypeBuilder::Canvas::TraceLog>*); void replayTraceLog(ErrorString*, const String&, int, String*); + +private: + ScriptObject callWrapContextFunction(const String&, const ScriptObject&); }; #endif diff --git a/Source/WebCore/inspector/InjectedScriptCanvasModuleSource.js b/Source/WebCore/inspector/InjectedScriptCanvasModuleSource.js index 6780af3c4..26afeeb54 100644 --- a/Source/WebCore/inspector/InjectedScriptCanvasModuleSource.js +++ b/Source/WebCore/inspector/InjectedScriptCanvasModuleSource.js @@ -743,7 +743,7 @@ Resource.prototype = { if (isCapturing) { var call = wrapFunction.call(); call.setStackTrace(StackTrace.create(1, arguments.callee)); - manager.reportCall(call); + manager.captureCall(call); } return wrapFunction.result(); }; @@ -767,7 +767,7 @@ Resource.prototype = { var result = originalFunction.apply(originalObject, arguments); var stackTrace = StackTrace.create(1, arguments.callee); var call = new Call(resource, functionName, arguments, result, stackTrace); - manager.reportCall(call); + manager.captureCall(call); return result; }; }, @@ -833,6 +833,27 @@ Resource.WrapFunction.prototype = { } /** + * @param {!Function} resourceConstructor + * @return {Function} + */ +Resource.WrapFunction.resourceFactoryMethod = function(resourceConstructor) +{ + /** @this Resource.WrapFunction */ + return function() + { + var wrappedObject = this.result(); + if (!wrappedObject) + return; + var resource = new resourceConstructor(wrappedObject); + var manager = this._resource.manager(); + if (manager) + manager.registerResource(resource); + this.overrideResult(resource.proxyObject()); + resource.pushCall(this.call()); + } +} + +/** * @constructor * @param {Resource} originalResource * @param {Object} data @@ -867,6 +888,10 @@ ReplayableResource.replay = function(obj, cache) return (obj instanceof ReplayableResource) ? obj.replay(cache).wrappedObject() : obj; } +//////////////////////////////////////////////////////////////////////////////// +// WebGL +//////////////////////////////////////////////////////////////////////////////// + /** * @constructor * @extends {Resource} @@ -1033,8 +1058,10 @@ WebGLTextureResource.prototype = { var framebufferResource = glResource.currentBinding(gl.FRAMEBUFFER); if (framebufferResource) this.pushCall(new Call(glResource, "bindFramebuffer", [gl.FRAMEBUFFER, framebufferResource])); - else - console.error("ASSERT_NOT_REACHED: No FRAMEBUFFER bound while calling gl." + call.functionName()); + else { + // FIXME: Implement this case. + console.error("ASSERT_NOT_REACHED: Could not properly process a gl." + call.functionName() + " call while the DRAWING BUFFER is bound."); + } this.pushCall(call); } } @@ -1369,10 +1396,10 @@ WebGLRenderingContextResource.forObject = function(obj) var resource = Resource.forObject(obj); if (!resource || resource instanceof WebGLRenderingContextResource) return resource; - var call = resource.calls(); - if (!call || !call.length) + var calls = resource.calls(); + if (!calls || !calls.length) return null; - resource = call[0].resource(); + resource = calls[0].resource(); return (resource instanceof WebGLRenderingContextResource) ? resource : null; } @@ -1593,7 +1620,7 @@ WebGLRenderingContextResource.prototype = { } gl.activeTexture(glState.ACTIVE_TEXTURE); - return Resource.prototype._doReplayCalls.call(this, data, cache); + Resource.prototype._doReplayCalls.call(this, data, cache); }, /** @@ -1661,33 +1688,13 @@ WebGLRenderingContextResource.prototype = { if (!wrapFunctions) { wrapFunctions = Object.create(null); - /** - * @param {string} methodName - * @param {Function} resourceConstructor - */ - function createResourceWrapFunction(methodName, resourceConstructor) - { - /** @this Resource.WrapFunction */ - wrapFunctions[methodName] = function() - { - var wrappedObject = this.result(); - if (!wrappedObject) - return; - var resource = new resourceConstructor(wrappedObject); - var manager = this._resource.manager(); - if (manager) - manager.registerResource(resource); - this.overrideResult(resource.proxyObject()); - resource.pushCall(this.call()); - } - } - createResourceWrapFunction("createBuffer", WebGLBufferResource); - createResourceWrapFunction("createShader", WebGLShaderResource); - createResourceWrapFunction("createProgram", WebGLProgramResource); - createResourceWrapFunction("createTexture", WebGLTextureResource); - createResourceWrapFunction("createFramebuffer", WebGLFramebufferResource); - createResourceWrapFunction("createRenderbuffer", WebGLRenderbufferResource); - createResourceWrapFunction("getUniformLocation", Resource); + wrapFunctions["createBuffer"] = Resource.WrapFunction.resourceFactoryMethod(WebGLBufferResource); + wrapFunctions["createShader"] = Resource.WrapFunction.resourceFactoryMethod(WebGLShaderResource); + wrapFunctions["createProgram"] = Resource.WrapFunction.resourceFactoryMethod(WebGLProgramResource); + wrapFunctions["createTexture"] = Resource.WrapFunction.resourceFactoryMethod(WebGLTextureResource); + wrapFunctions["createFramebuffer"] = Resource.WrapFunction.resourceFactoryMethod(WebGLFramebufferResource); + wrapFunctions["createRenderbuffer"] = Resource.WrapFunction.resourceFactoryMethod(WebGLRenderbufferResource); + wrapFunctions["getUniformLocation"] = Resource.WrapFunction.resourceFactoryMethod(Resource); /** * @param {string} methodName @@ -1753,6 +1760,227 @@ WebGLRenderingContextResource.prototype = { WebGLRenderingContextResource.prototype.__proto__ = Resource.prototype; +//////////////////////////////////////////////////////////////////////////////// +// 2D Canvas +//////////////////////////////////////////////////////////////////////////////// + +/** + * @constructor + * @extends {Resource} + * @param {CanvasRenderingContext2D} context + * @param {Function} replayContextCallback + */ +function CanvasRenderingContext2DResource(context, replayContextCallback) +{ + Resource.call(this, context); + this._replayContextCallback = replayContextCallback; + this._attributesStack = []; +} + +/** + * @const + * @type {Array.<string>} + */ +CanvasRenderingContext2DResource.AttributeProperties = [ + "strokeStyle", + "fillStyle", + "globalAlpha", + "lineWidth", + "lineCap", + "lineJoin", + "miterLimit", + "shadowOffsetX", + "shadowOffsetY", + "shadowBlur", + "shadowColor", + "globalCompositeOperation", + "font", + "textAlign", + "textBaseline" +]; + +/** + * @const + * @type {Array.<string>} + */ +CanvasRenderingContext2DResource.PathMethods = [ + "beginPath", + "moveTo", + "closePath", + "lineTo", + "quadraticCurveTo", + "bezierCurveTo", + "arcTo", + "arc", + "rect" +]; + +/** + * @const + * @type {Array.<string>} + */ +CanvasRenderingContext2DResource.TransformationMatrixMethods = [ + "scale", + "rotate", + "translate", + "transform", + "setTransform" +]; + +CanvasRenderingContext2DResource.prototype = { + /** + * @override + * @param {Object} data + * @param {Cache} cache + */ + _populateReplayableData: function(data, cache) + { + data.replayContextCallback = this._replayContextCallback; + data.attributesStack = this._attributesStack.slice(0); + data.currentAttributes = this._currentAttributesState(); + }, + + /** + * @override + * @param {Object} data + * @param {Cache} cache + */ + _doReplayCalls: function(data, cache) + { + this._replayContextCallback = data.replayContextCallback; + this._attributesStack = data.attributesStack.slice(0); + + var ctx = Resource.wrappedObject(this._replayContextCallback()); + this.setWrappedObject(ctx); + + var saveCalls = 0; + for (var i = 0, n = data.calls.length; i < n; ++i) { + var replayableCall = data.calls[i]; + if (replayableCall.functionName() === "save") { + console.assert(saveCalls < this._attributesStack.length, "Size of attributes stack is less than 'save' calls"); + this._applyAttributesState(this._attributesStack[saveCalls++]); + } + this._calls.push(replayableCall.replay(cache)); + } + console.assert(saveCalls === this._attributesStack.length, "Size of attributes stack should be equal to the number of 'save' calls"); + this._applyAttributesState(data.currentAttributes); + }, + + /** + * @param {Call} call + */ + pushCall_setTransform: function(call) + { + // FIXME: Remove obsolete transform matrix methods. + this.pushCall(call); + }, + + /** + * @param {Call} call + */ + pushCall_beginPath: function(call) + { + // FIXME: Remove obsolete path methods. + this.pushCall(call); + }, + + /** + * @param {Call} call + */ + pushCall_save: function(call) + { + this._attributesStack.push(this._currentAttributesState()); + this.pushCall(call); + }, + + /** + * @param {Call} call + */ + pushCall_restore: function(call) + { + this._attributesStack.pop(); + // FIXME: Remove obsolete clip,save methods. + this.pushCall(call); + }, + + /** + * @return {!Object.<string, string>} + */ + _currentAttributesState: function() + { + var ctx = this.wrappedObject(); + var state = {}; + CanvasRenderingContext2DResource.AttributeProperties.forEach(function(attribute) { + state[attribute] = ctx[attribute]; + }); + return state; + }, + + /** + * @param {!Object.<string, string>} state + */ + _applyAttributesState: function(state) + { + var ctx = this.wrappedObject(); + Object.keys(state).forEach(function(attribute) { + ctx[attribute] = state[attribute]; + }); + }, + + /** + * @override + * @return {Object.<string, Function>} + */ + _customWrapFunctions: function() + { + var wrapFunctions = CanvasRenderingContext2DResource._wrapFunctions; + if (!wrapFunctions) { + wrapFunctions = Object.create(null); + + wrapFunctions["createLinearGradient"] = Resource.WrapFunction.resourceFactoryMethod(Resource); + wrapFunctions["createRadialGradient"] = Resource.WrapFunction.resourceFactoryMethod(Resource); + wrapFunctions["createPattern"] = Resource.WrapFunction.resourceFactoryMethod(Resource); + + /** + * @param {string} methodName + * @param {Function=} func + */ + function stateModifyingWrapFunction(methodName, func) + { + if (func) { + /** @this Resource.WrapFunction */ + wrapFunctions[methodName] = function() + { + func.call(this._resource, this.call()); + } + } else { + /** @this Resource.WrapFunction */ + wrapFunctions[methodName] = function() + { + this._resource.pushCall(this.call()); + } + } + } + CanvasRenderingContext2DResource.TransformationMatrixMethods.forEach(function(methodName) { + var func = methodName === "setTransform" ? this.pushCall_setTransform : null; + stateModifyingWrapFunction(methodName, func); + }); + CanvasRenderingContext2DResource.PathMethods.forEach(function(methodName) { + var func = methodName === "beginPath" ? this.pushCall_beginPath : null; + stateModifyingWrapFunction(methodName, func); + }); + stateModifyingWrapFunction("save", this.pushCall_save); + stateModifyingWrapFunction("restore", this.pushCall_restore); + stateModifyingWrapFunction("clip"); + + CanvasRenderingContext2DResource._wrapFunctions = wrapFunctions; + } + return wrapFunctions; + } +}; + +CanvasRenderingContext2DResource.prototype.__proto__ = Resource.prototype; + /** * @constructor */ @@ -1942,7 +2170,7 @@ ResourceTrackingManager.prototype = { /** * @param {Call} call */ - reportCall: function(call) + captureCall: function(call) { if (!this._capturing) return; @@ -1988,8 +2216,18 @@ InjectedScript.prototype = { { var resource = Resource.forObject(glContext) || new WebGLRenderingContextResource(glContext, this._constructWebGLReplayContext.bind(this, glContext)); this._manager.registerResource(resource); - var proxy = resource.proxyObject(); - return proxy; + return resource.proxyObject(); + }, + + /** + * @param {CanvasRenderingContext2D} context + * @return {Object} + */ + wrapCanvas2DContext: function(context) + { + var resource = Resource.forObject(context) || new CanvasRenderingContext2DResource(context, this._constructCanvas2DReplayContext.bind(this, context)); + this._manager.registerResource(resource); + return resource.proxyObject(); }, captureFrame: function() @@ -2104,6 +2342,29 @@ InjectedScript.prototype = { // FIXME: Reset the replay GL state and clear the canvas. } return replayContext; + }, + + /** + * @param {CanvasRenderingContext2D} originalContext + * @return {CanvasRenderingContext2D} + */ + _constructCanvas2DReplayContext: function(originalContext) + { + var replayContext = originalContext["__replayContext"]; + if (!replayContext) { + var canvas = originalContext.canvas.cloneNode(true); + replayContext = /** @type {CanvasRenderingContext2D} */ Resource.wrappedObject(canvas.getContext("2d")); + Object.defineProperty(originalContext, "__replayContext", { + value: replayContext, + writable: false, + enumerable: false, + configurable: true + }); + this._replayContext = replayContext; + } else { + // FIXME: Clear the canvas. + } + return replayContext; } } diff --git a/Source/WebCore/inspector/Inspector.json b/Source/WebCore/inspector/Inspector.json index 5c18dad95..21d927c21 100644 --- a/Source/WebCore/inspector/Inspector.json +++ b/Source/WebCore/inspector/Inspector.json @@ -1567,6 +1567,7 @@ { "name": "children", "type": "array", "optional": true, "items": { "$ref": "Node" }, "description": "Child nodes of this node when requested with children." }, { "name": "attributes", "type": "array", "optional": true, "items": { "type": "string" }, "description": "Attributes of the <code>Element</code> node in the form of flat array <code>[name1, value1, name2, value2]</code>." }, { "name": "documentURL", "type": "string", "optional": true, "description": "Document URL that <code>Document</code> or <code>FrameOwner</code> node points to." }, + { "name": "baseURL", "type": "string", "optional": true, "description": "Base URL that <code>Document</code> or <code>FrameOwner</code> node uses for URL completion." }, { "name": "publicId", "type": "string", "optional": true, "description": "<code>DocumentType</code>'s publicId." }, { "name": "systemId", "type": "string", "optional": true, "description": "<code>DocumentType</code>'s systemId." }, { "name": "internalSubset", "type": "string", "optional": true, "description": "<code>DocumentType</code>'s internalSubset." }, @@ -2006,11 +2007,11 @@ "description": "This object identifies a CSS rule in a unique way." }, { - "id": "PseudoIdRules", + "id": "PseudoIdMatches", "type": "object", "properties": [ { "name": "pseudoId", "type": "integer", "description": "Pseudo style identifier (see <code>enum PseudoId</code> in <code>RenderStyleConstants.h</code>)."}, - { "name": "rules", "type": "array", "items": { "$ref": "CSSRule" }, "description": "CSS rules applicable to the pseudo style."} + { "name": "matches", "type": "array", "items": { "$ref": "RuleMatch" }, "description": "Matches of CSS rules applicable to the pseudo style."} ], "description": "CSS rule collection for a single pseudo style." }, @@ -2019,11 +2020,30 @@ "type": "object", "properties": [ { "name": "inlineStyle", "$ref": "CSSStyle", "optional": true, "description": "The ancestor node's inline style, if any, in the style inheritance chain." }, - { "name": "matchedCSSRules", "type": "array", "items": { "$ref": "CSSRule" }, "description": "CSS rules matching the ancestor node in the style inheritance chain." } + { "name": "matchedCSSRules", "type": "array", "items": { "$ref": "RuleMatch" }, "description": "Matches of CSS rules matching the ancestor node in the style inheritance chain." } ], "description": "CSS rule collection for a single pseudo style." }, { + "id": "RuleMatch", + "type": "object", + "properties": [ + { "name": "rule", "$ref": "CSSRule", "description": "CSS rule in the match." }, + { "name": "matchingSelectors", "type": "array", "items": { "type": "integer" }, "description": "Matching selector indices in the rule's selectorList selectors (0-based)." } + ], + "description": "Match data for a CSS rule." + }, + { + "id": "SelectorList", + "type": "object", + "properties": [ + { "name": "selectors", "type": "array", "items": { "type": "string" }, "description": "Selectors in the list." }, + { "name": "text", "type": "string", "description": "Rule selector text." }, + { "name": "range", "$ref": "SourceRange", "optional": true, "description": "Rule selector range in the underlying resource (if available)." } + ], + "description": "Selector list data." + }, + { "id": "CSSStyleAttribute", "type": "object", "properties": [ @@ -2060,12 +2080,11 @@ "type": "object", "properties": [ { "name": "ruleId", "$ref": "CSSRuleId", "optional": true, "description": "The CSS rule identifier (absent for user agent stylesheet and user-specified stylesheet rules)."}, - { "name": "selectorText", "type": "string", "description": "Rule selector."}, + { "name": "selectorList", "$ref": "SelectorList", "description": "Rule selector data." }, { "name": "sourceURL", "type": "string", "optional": true, "description": "Parent stylesheet resource URL (for regular rules)."}, { "name": "sourceLine", "type": "integer", "description": "Line ordinal of the rule selector start character in the resource."}, { "name": "origin", "$ref": "StyleSheetOrigin", "description": "Parent stylesheet's origin."}, { "name": "style", "$ref": "CSSStyle", "description": "Associated style declaration." }, - { "name": "selectorRange", "$ref": "SourceRange", "optional": true, "description": "The rule selector range in the underlying resource (if available)." }, { "name": "media", "type": "array", "items": { "$ref": "CSSMedia" }, "optional": true, "description": "Media list array (for rules involving media queries). The array enumerates media queries starting with the innermost one, going outwards." } ], "description": "CSS rule representation." @@ -2205,8 +2224,8 @@ { "name": "includeInherited", "type": "boolean", "optional": true, "description": "Whether to include inherited styles (default: true)." } ], "returns": [ - { "name": "matchedCSSRules", "type": "array", "items": { "$ref": "CSSRule" }, "optional": true, "description": "CSS rules matching this node, from all applicable stylesheets." }, - { "name": "pseudoElements", "type": "array", "items": { "$ref": "PseudoIdRules" }, "optional": true, "description": "Pseudo style rules for this node." }, + { "name": "matchedCSSRules", "type": "array", "items": { "$ref": "RuleMatch" }, "optional": true, "description": "CSS rules matching this node, from all applicable stylesheets." }, + { "name": "pseudoElements", "type": "array", "items": { "$ref": "PseudoIdMatches" }, "optional": true, "description": "Pseudo style matches for this node." }, { "name": "inherited", "type": "array", "items": { "$ref": "InheritedStyleEntry" }, "optional": true, "description": "A chain of inherited styles (from the immediate node parent up to the DOM tree root)." } ], "description": "Returns requested styles for a DOM node identified by <code>nodeId</code>." diff --git a/Source/WebCore/inspector/InspectorCSSAgent.cpp b/Source/WebCore/inspector/InspectorCSSAgent.cpp index 60ebd9312..bbe88d2c0 100644 --- a/Source/WebCore/inspector/InspectorCSSAgent.cpp +++ b/Source/WebCore/inspector/InspectorCSSAgent.cpp @@ -678,7 +678,7 @@ bool InspectorCSSAgent::forcePseudoState(Element* element, CSSSelector::PseudoTy } } -void InspectorCSSAgent::getMatchedStylesForNode(ErrorString* errorString, int nodeId, const bool* includePseudo, const bool* includeInherited, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> >& matchedCSSRules, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoIdRules> >& pseudoIdRules, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry> >& inheritedEntries) +void InspectorCSSAgent::getMatchedStylesForNode(ErrorString* errorString, int nodeId, const bool* includePseudo, const bool* includeInherited, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> >& matchedCSSRules, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoIdMatches> >& pseudoIdMatches, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry> >& inheritedEntries) { Element* element = elementForId(errorString, nodeId); if (!element) @@ -687,44 +687,44 @@ void InspectorCSSAgent::getMatchedStylesForNode(ErrorString* errorString, int no // Matched rules. StyleResolver* styleResolver = element->ownerDocument()->styleResolver(); RefPtr<CSSRuleList> matchedRules = styleResolver->styleRulesForElement(element, StyleResolver::AllCSSRules); - matchedCSSRules = buildArrayForRuleList(matchedRules.get(), styleResolver); + matchedCSSRules = buildArrayForMatchedRuleList(matchedRules.get(), styleResolver, element); // Pseudo elements. if (!includePseudo || *includePseudo) { - RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoIdRules> > pseudoElements = TypeBuilder::Array<TypeBuilder::CSS::PseudoIdRules>::create(); + RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoIdMatches> > pseudoElements = TypeBuilder::Array<TypeBuilder::CSS::PseudoIdMatches>::create(); for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < AFTER_LAST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) { RefPtr<CSSRuleList> matchedRules = styleResolver->pseudoStyleRulesForElement(element, pseudoId, StyleResolver::AllCSSRules); if (matchedRules && matchedRules->length()) { - RefPtr<TypeBuilder::CSS::PseudoIdRules> pseudoStyles = TypeBuilder::CSS::PseudoIdRules::create() + RefPtr<TypeBuilder::CSS::PseudoIdMatches> matches = TypeBuilder::CSS::PseudoIdMatches::create() .setPseudoId(static_cast<int>(pseudoId)) - .setRules(buildArrayForRuleList(matchedRules.get(), styleResolver)); - pseudoElements->addItem(pseudoStyles.release()); + .setMatches(buildArrayForMatchedRuleList(matchedRules.get(), styleResolver, element)); + pseudoElements->addItem(matches.release()); } } - pseudoIdRules = pseudoElements.release(); + pseudoIdMatches = pseudoElements.release(); } // Inherited styles. if (!includeInherited || *includeInherited) { - RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry> > inheritedStyles = TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry>::create(); + RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry> > entries = TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry>::create(); Element* parentElement = element->parentElement(); while (parentElement) { - StyleResolver* parentStyleResolver= parentElement->ownerDocument()->styleResolver(); + StyleResolver* parentStyleResolver = parentElement->ownerDocument()->styleResolver(); RefPtr<CSSRuleList> parentMatchedRules = parentStyleResolver->styleRulesForElement(parentElement, StyleResolver::AllCSSRules); - RefPtr<TypeBuilder::CSS::InheritedStyleEntry> parentStyle = TypeBuilder::CSS::InheritedStyleEntry::create() - .setMatchedCSSRules(buildArrayForRuleList(parentMatchedRules.get(), styleResolver)); + RefPtr<TypeBuilder::CSS::InheritedStyleEntry> entry = TypeBuilder::CSS::InheritedStyleEntry::create() + .setMatchedCSSRules(buildArrayForMatchedRuleList(parentMatchedRules.get(), styleResolver, parentElement)); if (parentElement->style() && parentElement->style()->length()) { InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(parentElement); if (styleSheet) - parentStyle->setInlineStyle(styleSheet->buildObjectForStyle(styleSheet->styleForId(InspectorCSSId(styleSheet->id(), 0)))); + entry->setInlineStyle(styleSheet->buildObjectForStyle(styleSheet->styleForId(InspectorCSSId(styleSheet->id(), 0)))); } - inheritedStyles->addItem(parentStyle.release()); + entries->addItem(entry.release()); parentElement = parentElement->parentElement(); } - inheritedEntries = inheritedStyles.release(); + inheritedEntries = entries.release(); } } @@ -1116,6 +1116,23 @@ TypeBuilder::CSS::StyleSheetOrigin::Enum InspectorCSSAgent::detectOrigin(CSSStyl return origin; } +PassRefPtr<TypeBuilder::CSS::CSSRule> InspectorCSSAgent::buildObjectForRule(CSSStyleRule* rule, StyleResolver* styleResolver) +{ + if (!rule) + return 0; + + // CSSRules returned by StyleResolver::styleRulesForElement lack parent pointers since that infomation is not cheaply available. + // Since the inspector wants to walk the parent chain, we construct the full wrappers here. + // FIXME: This could be factored better. StyleResolver::styleRulesForElement should return a StyleRule vector, not a CSSRuleList. + if (!rule->parentStyleSheet()) { + rule = styleResolver->ensureFullCSSOMWrapperForInspector(rule->styleRule()); + if (!rule) + return 0; + } + InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(rule->parentStyleSheet()); + return inspectorStyleSheet ? inspectorStyleSheet->buildObjectForRule(rule) : 0; +} + PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > InspectorCSSAgent::buildArrayForRuleList(CSSRuleList* ruleList, StyleResolver* styleResolver) { RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > result = TypeBuilder::Array<TypeBuilder::CSS::CSSRule>::create(); @@ -1124,22 +1141,42 @@ PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > InspectorCSSAgent::bu for (unsigned i = 0, size = ruleList->length(); i < size; ++i) { CSSStyleRule* rule = asCSSStyleRule(ruleList->item(i)); - if (!rule) + RefPtr<TypeBuilder::CSS::CSSRule> ruleObject = buildObjectForRule(rule, styleResolver); + if (!ruleObject) continue; + result->addItem(ruleObject); + } + return result.release(); +} + +PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> > InspectorCSSAgent::buildArrayForMatchedRuleList(CSSRuleList* ruleList, StyleResolver* styleResolver, Element* element) +{ + RefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> > result = TypeBuilder::Array<TypeBuilder::CSS::RuleMatch>::create(); + if (!ruleList) + return result.release(); - // CSSRules returned by StyleResolver::styleRulesForElement lack parent pointers since that infomation is not cheaply available. - // Since the inspector wants to walk the parent chain, we construct the full wrappers here. - // FIXME: This could be factored better. StyleResolver::styleRulesForElement should return a StyleRule vector, not a CSSRuleList. - if (!rule->parentStyleSheet()) { - rule = styleResolver->ensureFullCSSOMWrapperForInspector(rule->styleRule()); - if (!rule) - continue; + for (unsigned i = 0, size = ruleList->length(); i < size; ++i) { + CSSStyleRule* rule = asCSSStyleRule(ruleList->item(i)); + RefPtr<TypeBuilder::CSS::CSSRule> ruleObject = buildObjectForRule(rule, styleResolver); + if (!ruleObject) + continue; + RefPtr<TypeBuilder::Array<int> > matchingSelectors = TypeBuilder::Array<int>::create(); + const CSSSelectorList& selectorList = rule->styleRule()->selectorList(); + long index = 0; + for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) { + ExceptionCode ec; + bool matched = element->webkitMatchesSelector(selector->selectorText(), ec); + if (matched) + matchingSelectors->addItem(index); + ++index; } - InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(rule->parentStyleSheet()); - if (inspectorStyleSheet) - result->addItem(inspectorStyleSheet->buildObjectForRule(rule)); + RefPtr<TypeBuilder::CSS::RuleMatch> match = TypeBuilder::CSS::RuleMatch::create() + .setRule(ruleObject) + .setMatchingSelectors(matchingSelectors); + result->addItem(match); } - return result.release(); + + return result; } PassRefPtr<TypeBuilder::CSS::CSSStyle> InspectorCSSAgent::buildObjectForAttributesStyle(Element* element) diff --git a/Source/WebCore/inspector/InspectorCSSAgent.h b/Source/WebCore/inspector/InspectorCSSAgent.h index c9aa3a48e..3ea451c2c 100644 --- a/Source/WebCore/inspector/InspectorCSSAgent.h +++ b/Source/WebCore/inspector/InspectorCSSAgent.h @@ -107,7 +107,7 @@ public: virtual void getComputedStyleForNode(ErrorString*, int nodeId, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty> >&); virtual void getInlineStylesForNode(ErrorString*, int nodeId, RefPtr<TypeBuilder::CSS::CSSStyle>& inlineStyle, RefPtr<TypeBuilder::CSS::CSSStyle>& attributes); - virtual void getMatchedStylesForNode(ErrorString*, int nodeId, const bool* includePseudo, const bool* includeInherited, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> >& matchedCSSRules, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoIdRules> >& pseudoRules, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry> >& inheritedEntries); + virtual void getMatchedStylesForNode(ErrorString*, int nodeId, const bool* includePseudo, const bool* includeInherited, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> >& matchedCSSRules, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoIdMatches> >& pseudoIdMatches, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry> >& inheritedEntries); virtual void getAllStyleSheets(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader> >& styleSheetInfos); virtual void getStyleSheet(ErrorString*, const String& styleSheetId, RefPtr<TypeBuilder::CSS::CSSStyleSheetBody>& result); virtual void getStyleSheetText(ErrorString*, const String& styleSheetId, String* result); @@ -156,7 +156,9 @@ private: InspectorStyleSheet* assertStyleSheetForId(ErrorString*, const String&); TypeBuilder::CSS::StyleSheetOrigin::Enum detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument); + PassRefPtr<TypeBuilder::CSS::CSSRule> buildObjectForRule(CSSStyleRule*, StyleResolver*); PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > buildArrayForRuleList(CSSRuleList*, StyleResolver*); + PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> > buildArrayForMatchedRuleList(CSSRuleList*, StyleResolver*, Element*); PassRefPtr<TypeBuilder::CSS::CSSStyle> buildObjectForAttributesStyle(Element*); PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::Region> > buildArrayForRegions(ErrorString*, PassRefPtr<NodeList>, int documentNodeId); PassRefPtr<TypeBuilder::CSS::NamedFlow> buildObjectForNamedFlow(ErrorString*, WebKitNamedFlow*, int documentNodeId); diff --git a/Source/WebCore/inspector/InspectorCanvasAgent.cpp b/Source/WebCore/inspector/InspectorCanvasAgent.cpp index dff293845..10bef0cd2 100644 --- a/Source/WebCore/inspector/InspectorCanvasAgent.cpp +++ b/Source/WebCore/inspector/InspectorCanvasAgent.cpp @@ -55,14 +55,11 @@ InspectorCanvasAgent::InspectorCanvasAgent(InstrumentingAgents* instrumentingAge , m_inspectedPage(page) , m_injectedScriptManager(injectedScriptManager) , m_frontend(0) - , m_enabled(false) { - m_instrumentingAgents->setInspectorCanvasAgent(this); } InspectorCanvasAgent::~InspectorCanvasAgent() { - m_instrumentingAgents->setInspectorCanvasAgent(0); } void InspectorCanvasAgent::setFrontend(InspectorFrontend* frontend) @@ -79,23 +76,22 @@ void InspectorCanvasAgent::clearFrontend() void InspectorCanvasAgent::restore() { - m_enabled = m_state->getBoolean(CanvasAgentState::canvasAgentEnabled); + if (m_state->getBoolean(CanvasAgentState::canvasAgentEnabled)) { + ErrorString error; + enable(&error); + } } void InspectorCanvasAgent::enable(ErrorString*) { - if (m_enabled) - return; - m_enabled = true; - m_state->setBoolean(CanvasAgentState::canvasAgentEnabled, m_enabled); + m_state->setBoolean(CanvasAgentState::canvasAgentEnabled, true); + m_instrumentingAgents->setInspectorCanvasAgent(this); } void InspectorCanvasAgent::disable(ErrorString*) { - if (!m_enabled) - return; - m_enabled = false; - m_state->setBoolean(CanvasAgentState::canvasAgentEnabled, m_enabled); + m_instrumentingAgents->setInspectorCanvasAgent(0); + m_state->setBoolean(CanvasAgentState::canvasAgentEnabled, false); } void InspectorCanvasAgent::dropTraceLog(ErrorString* errorString, const String& traceLogId) @@ -130,6 +126,20 @@ void InspectorCanvasAgent::replayTraceLog(ErrorString* errorString, const String module.replayTraceLog(errorString, traceLogId, stepNo, result); } +ScriptObject InspectorCanvasAgent::wrapCanvas2DRenderingContextForInstrumentation(const ScriptObject& context) +{ + if (context.hasNoValue()) { + ASSERT_NOT_REACHED(); + return ScriptObject(); + } + InjectedScriptCanvasModule module = InjectedScriptCanvasModule::moduleForState(m_injectedScriptManager, context.scriptState()); + if (module.hasNoValue()) { + ASSERT_NOT_REACHED(); + return ScriptObject(); + } + return module.wrapCanvas2DContext(context); +} + #if ENABLE(WEBGL) ScriptObject InspectorCanvasAgent::wrapWebGLRenderingContextForInstrumentation(const ScriptObject& glContext) { diff --git a/Source/WebCore/inspector/InspectorCanvasAgent.h b/Source/WebCore/inspector/InspectorCanvasAgent.h index f460c6410..ef4cbd58c 100644 --- a/Source/WebCore/inspector/InspectorCanvasAgent.h +++ b/Source/WebCore/inspector/InspectorCanvasAgent.h @@ -64,8 +64,7 @@ public: virtual void clearFrontend(); virtual void restore(); - bool enabled() { return m_enabled; } - + ScriptObject wrapCanvas2DRenderingContextForInstrumentation(const ScriptObject&); #if ENABLE(WEBGL) ScriptObject wrapWebGLRenderingContextForInstrumentation(const ScriptObject&); #endif @@ -90,7 +89,6 @@ private: Page* m_inspectedPage; InjectedScriptManager* m_injectedScriptManager; InspectorFrontend::Canvas* m_frontend; - bool m_enabled; }; } // namespace WebCore diff --git a/Source/WebCore/inspector/InspectorCanvasInstrumentation.h b/Source/WebCore/inspector/InspectorCanvasInstrumentation.h index 5904b8789..2c2bea9d0 100644 --- a/Source/WebCore/inspector/InspectorCanvasInstrumentation.h +++ b/Source/WebCore/inspector/InspectorCanvasInstrumentation.h @@ -38,13 +38,23 @@ namespace WebCore { +ScriptObject InspectorInstrumentation::wrapCanvas2DRenderingContextForInstrumentation(Document* document, const ScriptObject& context) +{ +#if ENABLE(INSPECTOR) + if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document)) { + if (InspectorCanvasAgent* canvasAgent = instrumentingAgents->inspectorCanvasAgent()) + return canvasAgent->wrapCanvas2DRenderingContextForInstrumentation(context); + } +#endif + return ScriptObject(); +} + #if ENABLE(WEBGL) ScriptObject InspectorInstrumentation::wrapWebGLRenderingContextForInstrumentation(Document* document, const ScriptObject& glContext) { #if ENABLE(INSPECTOR) if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document)) { - InspectorCanvasAgent* canvasAgent = instrumentingAgents->inspectorCanvasAgent(); - if (canvasAgent && canvasAgent->enabled()) + if (InspectorCanvasAgent* canvasAgent = instrumentingAgents->inspectorCanvasAgent()) return canvasAgent->wrapWebGLRenderingContextForInstrumentation(glContext); } #endif diff --git a/Source/WebCore/inspector/InspectorClient.h b/Source/WebCore/inspector/InspectorClient.h index fc8d0247f..e8d2659d5 100644 --- a/Source/WebCore/inspector/InspectorClient.h +++ b/Source/WebCore/inspector/InspectorClient.h @@ -71,7 +71,7 @@ public: virtual bool supportsFrameInstrumentation() { return false; } - bool doDispatchMessageOnFrontendPage(Page* frontendPage, const String& message); + static bool doDispatchMessageOnFrontendPage(Page* frontendPage, const String& message); }; } // namespace WebCore diff --git a/Source/WebCore/inspector/InspectorDOMAgent.cpp b/Source/WebCore/inspector/InspectorDOMAgent.cpp index 4491487b3..a533e5253 100644 --- a/Source/WebCore/inspector/InspectorDOMAgent.cpp +++ b/Source/WebCore/inspector/InspectorDOMAgent.cpp @@ -1176,6 +1176,11 @@ String InspectorDOMAgent::documentURLString(Document* document) return document->url().string(); } +static String documentBaseURLString(Document* document) +{ + return document->completeURL("").string(); +} + PassRefPtr<TypeBuilder::DOM::Node> InspectorDOMAgent::buildObjectForNode(Node* node, int depth, NodeToIdMap* nodesMap) { int id = bind(node, nodesMap); @@ -1240,6 +1245,7 @@ PassRefPtr<TypeBuilder::DOM::Node> InspectorDOMAgent::buildObjectForNode(Node* n } else if (node->isDocumentNode()) { Document* document = static_cast<Document*>(node); value->setDocumentURL(documentURLString(document)); + value->setBaseURL(documentBaseURLString(document)); value->setXmlVersion(document->xmlVersion()); } else if (node->nodeType() == Node::DOCUMENT_TYPE_NODE) { DocumentType* docType = static_cast<DocumentType*>(node); diff --git a/Source/WebCore/inspector/InspectorInstrumentation.h b/Source/WebCore/inspector/InspectorInstrumentation.h index 217d98d02..400c443b8 100644 --- a/Source/WebCore/inspector/InspectorInstrumentation.h +++ b/Source/WebCore/inspector/InspectorInstrumentation.h @@ -251,6 +251,7 @@ public: static void didReceiveWebSocketFrameError(Document*, unsigned long identifier, const String& errorMessage); #endif + static ScriptObject wrapCanvas2DRenderingContextForInstrumentation(Document*, const ScriptObject&); #if ENABLE(WEBGL) static ScriptObject wrapWebGLRenderingContextForInstrumentation(Document*, const ScriptObject&); #endif diff --git a/Source/WebCore/inspector/InspectorOverlay.cpp b/Source/WebCore/inspector/InspectorOverlay.cpp index 5241545e1..7a87b0f0e 100644 --- a/Source/WebCore/inspector/InspectorOverlay.cpp +++ b/Source/WebCore/inspector/InspectorOverlay.cpp @@ -271,6 +271,9 @@ void InspectorOverlay::update() } FrameView* view = m_page->mainFrame()->view(); + if (!view) + return; + FrameView* overlayView = overlayPage()->mainFrame()->view(); IntRect visibleRect = enclosingIntRect(view->visibleContentRect()); overlayView->resize(visibleRect.width(), visibleRect.height()); diff --git a/Source/WebCore/inspector/InspectorPageAgent.cpp b/Source/WebCore/inspector/InspectorPageAgent.cpp index fa23aaaf9..ef39e6f13 100644 --- a/Source/WebCore/inspector/InspectorPageAgent.cpp +++ b/Source/WebCore/inspector/InspectorPageAgent.cpp @@ -349,13 +349,6 @@ void InspectorPageAgent::restore() ErrorString error; enable(&error); - // When restoring the agent, override values are restored into the FrameView. - int width = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenWidthOverride)); - int height = static_cast<int>(m_state->getLong(PageAgentState::pageAgentScreenHeightOverride)); - double fontScaleFactor = m_state->getDouble(PageAgentState::pageAgentFontScaleFactorOverride); - bool fitWindow = m_state->getBoolean(PageAgentState::pageAgentFitWindow); - updateViewMetrics(width, height, fontScaleFactor, fitWindow); - if (m_inspectorAgent->didCommitLoadFired()) frameNavigated(m_page->mainFrame()->loader()->documentLoader()); #if ENABLE(TOUCH_EVENTS) diff --git a/Source/WebCore/inspector/InspectorProfilerAgent.cpp b/Source/WebCore/inspector/InspectorProfilerAgent.cpp index 4540aa7cd..9c864c5dd 100644 --- a/Source/WebCore/inspector/InspectorProfilerAgent.cpp +++ b/Source/WebCore/inspector/InspectorProfilerAgent.cpp @@ -48,6 +48,7 @@ #include "ScriptObject.h" #include "ScriptProfile.h" #include "ScriptProfiler.h" +#include "WorkerScriptDebugServer.h" #include <wtf/OwnPtr.h> #include <wtf/text/StringConcatenate.h> @@ -70,6 +71,11 @@ public: virtual ~PageProfilerAgent() { } private: + virtual void recompileScript() + { + PageScriptDebugServer::shared().recompileAllJSFunctionsSoon(); + } + virtual void startProfiling(const String& title) { ScriptProfiler::startForPage(m_inspectedPage, title); @@ -88,7 +94,6 @@ PassOwnPtr<InspectorProfilerAgent> InspectorProfilerAgent::create(InstrumentingA return adoptPtr(new PageProfilerAgent(instrumentingAgents, consoleAgent, inspectedPage, inspectorState, injectedScriptManager)); } - #if ENABLE(WORKERS) class WorkerProfilerAgent : public InspectorProfilerAgent { public: @@ -97,6 +102,8 @@ public: virtual ~WorkerProfilerAgent() { } private: + virtual void recompileScript() { } + virtual void startProfiling(const String& title) { ScriptProfiler::startForWorkerContext(m_workerContext, title); @@ -222,7 +229,7 @@ void InspectorProfilerAgent::disable() return; m_enabled = false; m_headersRequested = false; - PageScriptDebugServer::shared().recompileAllJSFunctionsSoon(); + recompileScript(); } void InspectorProfilerAgent::enable(bool skipRecompile) @@ -231,7 +238,7 @@ void InspectorProfilerAgent::enable(bool skipRecompile) return; m_enabled = true; if (!skipRecompile) - PageScriptDebugServer::shared().recompileAllJSFunctionsSoon(); + recompileScript(); } String InspectorProfilerAgent::getCurrentUserInitiatedProfileName(bool incrementProfileNumber) diff --git a/Source/WebCore/inspector/InspectorProfilerAgent.h b/Source/WebCore/inspector/InspectorProfilerAgent.h index c35536fae..d548bbfa4 100644 --- a/Source/WebCore/inspector/InspectorProfilerAgent.h +++ b/Source/WebCore/inspector/InspectorProfilerAgent.h @@ -73,6 +73,7 @@ public: void resetState(); virtual void causesRecompilation(ErrorString*, bool*); + virtual void recompileScript() = 0; virtual void isSampling(ErrorString*, bool*); virtual void hasHeapProfiler(ErrorString*, bool*); diff --git a/Source/WebCore/inspector/InspectorStyleSheet.cpp b/Source/WebCore/inspector/InspectorStyleSheet.cpp index 2de8d9cba..5b94de6c1 100644 --- a/Source/WebCore/inspector/InspectorStyleSheet.cpp +++ b/Source/WebCore/inspector/InspectorStyleSheet.cpp @@ -911,6 +911,25 @@ PassRefPtr<TypeBuilder::CSS::CSSStyleSheetHeader> InspectorStyleSheet::buildObje return result.release(); } +PassRefPtr<TypeBuilder::CSS::SelectorList> InspectorStyleSheet::buildObjectForSelectorList(CSSStyleRule* rule) +{ + RefPtr<TypeBuilder::Array<String> > selectors = TypeBuilder::Array<String>::create(); + const CSSSelectorList& selectorList = rule->styleRule()->selectorList(); + for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) + selectors->addItem(selector->selectorText()); + + RefPtr<TypeBuilder::CSS::SelectorList> result = TypeBuilder::CSS::SelectorList::create() + .setSelectors(selectors) + .setText(rule->selectorText()); + + RefPtr<CSSRuleSourceData> sourceData; + if (ensureParsedDataReady()) + sourceData = ruleSourceDataFor(rule->style()); + if (sourceData) + result->setRange(buildSourceRangeObject(sourceData->ruleHeaderRange)); + return result.release(); +} + PassRefPtr<TypeBuilder::CSS::CSSRule> InspectorStyleSheet::buildObjectForRule(CSSStyleRule* rule) { CSSStyleSheet* styleSheet = pageStyleSheet(); @@ -918,7 +937,7 @@ PassRefPtr<TypeBuilder::CSS::CSSRule> InspectorStyleSheet::buildObjectForRule(CS return 0; RefPtr<TypeBuilder::CSS::CSSRule> result = TypeBuilder::CSS::CSSRule::create() - .setSelectorText(rule->selectorText()) + .setSelectorList(buildObjectForSelectorList(rule)) .setSourceLine(rule->styleRule()->sourceLine()) .setOrigin(m_origin) .setStyle(buildObjectForStyle(rule->style())); @@ -933,12 +952,6 @@ PassRefPtr<TypeBuilder::CSS::CSSRule> InspectorStyleSheet::buildObjectForRule(CS result->setRuleId(id.asProtocolValue<TypeBuilder::CSS::CSSRuleId>()); } - RefPtr<CSSRuleSourceData> sourceData; - if (ensureParsedDataReady()) - sourceData = ruleSourceDataFor(rule->style()); - if (sourceData) - result->setSelectorRange(buildSourceRangeObject(sourceData->ruleHeaderRange)); - RefPtr<Array<TypeBuilder::CSS::CSSMedia> > mediaArray = Array<TypeBuilder::CSS::CSSMedia>::create(); fillMediaListChain(rule, mediaArray.get()); diff --git a/Source/WebCore/inspector/InspectorStyleSheet.h b/Source/WebCore/inspector/InspectorStyleSheet.h index d426d579f..d8d4e481d 100644 --- a/Source/WebCore/inspector/InspectorStyleSheet.h +++ b/Source/WebCore/inspector/InspectorStyleSheet.h @@ -234,6 +234,7 @@ private: bool resourceStyleSheetText(String* result) const; bool inlineStyleSheetText(String* result) const; PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > buildArrayForRuleList(CSSRuleList*); + PassRefPtr<TypeBuilder::CSS::SelectorList> buildObjectForSelectorList(CSSStyleRule*); InspectorPageAgent* m_pageAgent; String m_id; diff --git a/Source/WebCore/inspector/front-end/AuditRules.js b/Source/WebCore/inspector/front-end/AuditRules.js index e91f27064..14b59ac47 100644 --- a/Source/WebCore/inspector/front-end/AuditRules.js +++ b/Source/WebCore/inspector/front-end/AuditRules.js @@ -755,8 +755,8 @@ WebInspector.AuditRules.ImageDimensionsRule.prototype = { var src = node.getAttribute("src"); if (!src.asParsedURL()) { for (var frameOwnerCandidate = node; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) { - if (frameOwnerCandidate.documentURL) { - var completeSrc = WebInspector.ParsedURL.completeURL(frameOwnerCandidate.documentURL, src); + if (frameOwnerCandidate.baseURL) { + var completeSrc = WebInspector.ParsedURL.completeURL(frameOwnerCandidate.baseURL, src); break; } } @@ -902,7 +902,7 @@ WebInspector.AuditRules.CssInHeadRule.prototype = { var externalStylesheetHrefs = []; for (var j = 0; j < externalStylesheetNodeIds.length; ++j) { var linkNode = WebInspector.domAgent.nodeForId(externalStylesheetNodeIds[j]); - var completeHref = WebInspector.ParsedURL.completeURL(linkNode.ownerDocument.documentURL, linkNode.getAttribute("href")); + var completeHref = WebInspector.ParsedURL.completeURL(linkNode.ownerDocument.baseURL, linkNode.getAttribute("href")); externalStylesheetHrefs.push(completeHref || "<empty>"); } urlToViolationsArray[root.documentURL] = [inlineStyleNodeIds.length, externalStylesheetHrefs]; @@ -989,7 +989,7 @@ WebInspector.AuditRules.StylesScriptsOrderRule.prototype = { var lateStyleUrls = []; for (var i = 0; i < lateStyleIds.length; ++i) { var lateStyleNode = WebInspector.domAgent.nodeForId(lateStyleIds[i]); - var completeHref = WebInspector.ParsedURL.completeURL(lateStyleNode.ownerDocument.documentURL, lateStyleNode.getAttribute("href")); + var completeHref = WebInspector.ParsedURL.completeURL(lateStyleNode.ownerDocument.baseURL, lateStyleNode.getAttribute("href")); lateStyleUrls.push(completeHref || "<empty>"); } result = [ lateStyleUrls, cssBeforeInlineCount ]; diff --git a/Source/WebCore/inspector/front-end/CSSStyleModel.js b/Source/WebCore/inspector/front-end/CSSStyleModel.js index 6e99dac82..e071f60fa 100644 --- a/Source/WebCore/inspector/front-end/CSSStyleModel.js +++ b/Source/WebCore/inspector/front-end/CSSStyleModel.js @@ -56,6 +56,17 @@ WebInspector.CSSStyleModel.parseRuleArrayPayload = function(ruleArray) return result; } +/** + * @param {Array.<CSSAgent.RuleMatch>} matchArray + */ +WebInspector.CSSStyleModel.parseRuleMatchArrayPayload = function(matchArray) +{ + var result = []; + for (var i = 0; i < matchArray.length; ++i) + result.push(WebInspector.CSSRule.parsePayload(matchArray[i].rule, matchArray[i].matchingSelectors)); + return result; +} + WebInspector.CSSStyleModel.Events = { StyleSheetChanged: "StyleSheetChanged", MediaQueryResultChanged: "MediaQueryResultChanged", @@ -90,13 +101,13 @@ WebInspector.CSSStyleModel.prototype = { var result = {}; if (matchedPayload) - result.matchedCSSRules = WebInspector.CSSStyleModel.parseRuleArrayPayload(matchedPayload); + result.matchedCSSRules = WebInspector.CSSStyleModel.parseRuleMatchArrayPayload(matchedPayload); if (pseudoPayload) { result.pseudoElements = []; for (var i = 0; i < pseudoPayload.length; ++i) { var entryPayload = pseudoPayload[i]; - result.pseudoElements.push({ pseudoId: entryPayload.pseudoId, rules: WebInspector.CSSStyleModel.parseRuleArrayPayload(entryPayload.rules) }); + result.pseudoElements.push({ pseudoId: entryPayload.pseudoId, rules: WebInspector.CSSStyleModel.parseRuleMatchArrayPayload(entryPayload.matches) }); } } @@ -108,7 +119,7 @@ WebInspector.CSSStyleModel.prototype = { if (entryPayload.inlineStyle) entry.inlineStyle = WebInspector.CSSStyleDeclaration.parsePayload(entryPayload.inlineStyle); if (entryPayload.matchedCSSRules) - entry.matchedCSSRules = WebInspector.CSSStyleModel.parseRuleArrayPayload(entryPayload.matchedCSSRules); + entry.matchedCSSRules = WebInspector.CSSStyleModel.parseRuleMatchArrayPayload(entryPayload.matchedCSSRules); result.inherited.push(entry); } } @@ -724,11 +735,16 @@ WebInspector.CSSStyleDeclaration.prototype = { /** * @constructor * @param {CSSAgent.CSSRule} payload + * @param {Array.<number>=} matchingSelectors */ -WebInspector.CSSRule = function(payload) +WebInspector.CSSRule = function(payload, matchingSelectors) { this.id = payload.ruleId; - this.selectorText = payload.selectorText; + if (matchingSelectors) + this.matchingSelectors = matchingSelectors; + this.selectors = payload.selectorList.selectors; + this.selectorText = payload.selectorList.text; + this.selectorRange = payload.selectorList.range; this.sourceLine = payload.sourceLine; this.sourceURL = payload.sourceURL; if (payload.sourceURL) @@ -736,18 +752,18 @@ WebInspector.CSSRule = function(payload) this.origin = payload.origin; this.style = WebInspector.CSSStyleDeclaration.parsePayload(payload.style); this.style.parentRule = this; - this.selectorRange = payload.selectorRange; if (payload.media) this.media = WebInspector.CSSMedia.parseMediaArrayPayload(payload.media); } /** * @param {CSSAgent.CSSRule} payload + * @param {Array.<number>=} matchingIndices * @return {WebInspector.CSSRule} */ -WebInspector.CSSRule.parsePayload = function(payload) +WebInspector.CSSRule.parsePayload = function(payload, matchingIndices) { - return new WebInspector.CSSRule(payload); + return new WebInspector.CSSRule(payload, matchingIndices); } WebInspector.CSSRule.prototype = { diff --git a/Source/WebCore/inspector/front-end/DOMAgent.js b/Source/WebCore/inspector/front-end/DOMAgent.js index 811fd2e6d..5f4f06162 100644 --- a/Source/WebCore/inspector/front-end/DOMAgent.js +++ b/Source/WebCore/inspector/front-end/DOMAgent.js @@ -747,8 +747,8 @@ WebInspector.DOMNode.prototype = { if (!url) return url; for (var frameOwnerCandidate = this; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) { - if (frameOwnerCandidate.documentURL) - return WebInspector.ParsedURL.completeURL(frameOwnerCandidate.documentURL, url); + if (frameOwnerCandidate.baseURL) + return WebInspector.ParsedURL.completeURL(frameOwnerCandidate.baseURL, url); } return null; } @@ -764,6 +764,7 @@ WebInspector.DOMDocument = function(domAgent, payload) { WebInspector.DOMNode.call(this, domAgent, this, false, payload); this.documentURL = payload.documentURL || ""; + this.baseURL = payload.baseURL; this.xmlVersion = payload.xmlVersion; this._listeners = {}; } diff --git a/Source/WebCore/inspector/front-end/DefaultTextEditor.js b/Source/WebCore/inspector/front-end/DefaultTextEditor.js index f90b902e3..69c87ce12 100644 --- a/Source/WebCore/inspector/front-end/DefaultTextEditor.js +++ b/Source/WebCore/inspector/front-end/DefaultTextEditor.js @@ -1863,10 +1863,21 @@ WebInspector.TextEditorMainPanel.prototype = { if (!highlight) return; - lineRow.removeChildren(); + var decorationsElement = lineRow.decorationsElement; + if (!decorationsElement) + lineRow.removeChildren(); + else { + while (true) { + var child = lineRow.firstChild; + if (!child || child === decorationsElement) + break; + lineRow.removeChild(child); + } + } + var line = this._textModel.line(lineNumber); if (!line) - lineRow.appendChild(document.createElement("br")); + lineRow.insertBefore(document.createElement("br"), decorationsElement); var plainTextStart = -1; for (var j = 0; j < line.length;) { @@ -1883,21 +1894,19 @@ WebInspector.TextEditorMainPanel.prototype = { j++; } else { if (plainTextStart !== -1) { - this._appendTextNode(lineRow, line.substring(plainTextStart, j)); + this._insertTextNodeBefore(lineRow, decorationsElement, line.substring(plainTextStart, j)); plainTextStart = -1; --this._paintLinesOperationsCredit; } - this._appendSpan(lineRow, line.substring(j, j + attribute.length), attribute.tokenType); + this._insertSpanBefore(lineRow, decorationsElement, line.substring(j, j + attribute.length), attribute.tokenType); j += attribute.length; --this._paintLinesOperationsCredit; } } if (plainTextStart !== -1) { - this._appendTextNode(lineRow, line.substring(plainTextStart, line.length)); + this._insertTextNodeBefore(lineRow, decorationsElement, line.substring(plainTextStart, line.length)); --this._paintLinesOperationsCredit; } - if (lineRow.decorationsElement) - lineRow.appendChild(lineRow.decorationsElement); } finally { if (this._rangeToMark && this._rangeToMark.startLine === lineNumber) this._markedRangeElement = WebInspector.highlightSearchResult(lineRow, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn); @@ -2050,20 +2059,21 @@ WebInspector.TextEditorMainPanel.prototype = { /** * @param {Element} element + * @param {Element} oldChild * @param {string} content * @param {string} className */ - _appendSpan: function(element, content, className) + _insertSpanBefore: function(element, oldChild, content, className) { if (className === "html-resource-link" || className === "html-external-link") { - element.appendChild(this._createLink(content, className === "html-external-link")); + element.insertBefore(this._createLink(content, className === "html-external-link"), oldChild); return; } var span = this._cachedSpans.pop() || document.createElement("span"); span.className = "webkit-" + className; span.textContent = content; - element.appendChild(span); + element.insertBefore(span, oldChild); if (!("spans" in element)) element.spans = []; element.spans.push(span); @@ -2071,16 +2081,17 @@ WebInspector.TextEditorMainPanel.prototype = { /** * @param {Element} element + * @param {Element} oldChild * @param {string} text */ - _appendTextNode: function(element, text) + _insertTextNodeBefore: function(element, oldChild, text) { var textNode = this._cachedTextNodes.pop(); if (textNode) textNode.nodeValue = text; else textNode = document.createTextNode(text); - element.appendChild(textNode); + element.insertBefore(textNode, oldChild); if (!("textNodes" in element)) element.textNodes = []; element.textNodes.push(textNode); diff --git a/Source/WebCore/inspector/front-end/FilteredItemSelectionDialog.js b/Source/WebCore/inspector/front-end/FilteredItemSelectionDialog.js index e086dadaf..41340a894 100644 --- a/Source/WebCore/inspector/front-end/FilteredItemSelectionDialog.js +++ b/Source/WebCore/inspector/front-end/FilteredItemSelectionDialog.js @@ -192,23 +192,17 @@ WebInspector.FilteredItemSelectionDialog.prototype = { */ _innerCreateSearchRegExp: function(query, isGlobal) { - query = query ? query.trim() : query; if (!query) return new RegExp(".*"); + query = query.trim(); var ignoreCase = (query === query.toLowerCase()); - - const toEscape = "^[]{}()\\.$*+?|"; - - var regExpString = ""; - for (var i = 0; i < query.length; ++i) { - var c = query.charAt(i); - if (toEscape.indexOf(c) !== -1) - c = "\\" + c; - if (i) - regExpString += "[^" + c + "]*"; - regExpString += c; - } + var regExpString = query.escapeForRegExp().replace(/\\\*/g, ".*").replace(/\\\?/g, ".") + if (ignoreCase) + regExpString = regExpString.replace(/(?!^)(\\\.|[_:-])/g, "[^._:-]*$1"); + else + regExpString = regExpString.replace(/(?!^)(\\\.|[A-Z_:-])/g, "[^.A-Z_:-]*$1"); + regExpString = "^" + "[^a-zA-Z0-9]*" + regExpString; return new RegExp(regExpString, (ignoreCase ? "i" : "") + (isGlobal ? "g" : "")); }, @@ -393,7 +387,7 @@ WebInspector.FilteredItemSelectionDialog.prototype = { var ranges = []; var match; - while ((match = regex.exec(key)) !== null) { + while ((match = regex.exec(key)) !== null && match[0]) { ranges.push({ offset: match.index, length: regex.lastIndex - match.index }); } diff --git a/Source/WebCore/inspector/front-end/InspectorFrontendAPI.js b/Source/WebCore/inspector/front-end/InspectorFrontendAPI.js index bab529ef0..06363986e 100644 --- a/Source/WebCore/inspector/front-end/InspectorFrontendAPI.js +++ b/Source/WebCore/inspector/front-end/InspectorFrontendAPI.js @@ -101,7 +101,7 @@ InspectorFrontendAPI = { enterInspectElementMode: function() { - WebInspector.panel("elements").toggleSearchingForNode(); + WebInspector.toggleSearchingForNode(); }, savedURL: function(url) diff --git a/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js b/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js index e9a097045..c58ff53fe 100644 --- a/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js +++ b/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js @@ -438,6 +438,8 @@ WebInspector.FunctionScopeMainTreeElement.prototype = { this.removeChildren(); var scopeChain = response.scopeChain; + if (!scopeChain) + return; for (var i = 0; i < scopeChain.length; ++i) { var scope = scopeChain[i]; var title = null; diff --git a/Source/WebCore/inspector/front-end/ResourceScriptMapping.js b/Source/WebCore/inspector/front-end/ResourceScriptMapping.js index 02eb62e72..6dfeb11ff 100644 --- a/Source/WebCore/inspector/front-end/ResourceScriptMapping.js +++ b/Source/WebCore/inspector/front-end/ResourceScriptMapping.js @@ -45,6 +45,7 @@ WebInspector.ResourceScriptMapping = function(workspace) this._temporaryUISourceCodes = new Map(); /** @type {Object.<string, number>} */ this._nextDynamicScriptIndexForURL = {}; + this._scripts = []; } WebInspector.ResourceScriptMapping.prototype = { @@ -82,6 +83,7 @@ WebInspector.ResourceScriptMapping.prototype = { var isDynamicScript = false; if (!script.isAnonymousScript()) { + this._scripts.push(script); var uiSourceCode = this._workspace.uiSourceCodeForURL(script.sourceURL); isDynamicScript = !!uiSourceCode && uiSourceCode.contentType() === WebInspector.resourceTypes.Document && !script.isInlineScript(); if (uiSourceCode && !isDynamicScript && !this._temporaryUISourceCodes.get(uiSourceCode)) @@ -122,7 +124,7 @@ WebInspector.ResourceScriptMapping.prototype = { return script.sourceURL === sourceURL && script.isInlineScript() === isInlineScript; } - return Object.values(WebInspector.debuggerModel.scripts).filter(filter); + return this._scripts.filter(filter.bind(this)); }, /** @@ -220,5 +222,6 @@ WebInspector.ResourceScriptMapping.prototype = { this._scriptIdForUISourceCode.clear(); this._temporaryUISourceCodes.clear(); this._nextDynamicScriptIndexForURL = {}; + this._scripts = []; }, } diff --git a/Source/WebCore/inspector/front-end/SettingsScreen.js b/Source/WebCore/inspector/front-end/SettingsScreen.js index 728389c7f..1c98e3e40 100644 --- a/Source/WebCore/inspector/front-end/SettingsScreen.js +++ b/Source/WebCore/inspector/front-end/SettingsScreen.js @@ -541,7 +541,7 @@ WebInspector.UserAgentSettingsTab.prototype = { const checkboxElement = labelElement.createChild("input"); checkboxElement.id = "metrics-override-checkbox"; checkboxElement.type = "checkbox"; - checkboxElement.checked = !metrics || (metrics.width && metrics.height && metrics.fontScaleFactor); + checkboxElement.checked = false; checkboxElement.addEventListener("click", this._onMetricsCheckboxClicked.bind(this), false); this._metricsCheckboxElement = checkboxElement; labelElement.appendChild(document.createTextNode(WebInspector.UIString("Device metrics"))); @@ -549,8 +549,7 @@ WebInspector.UserAgentSettingsTab.prototype = { const metricsSectionElement = this._createDeviceMetricsElement(metrics); p.appendChild(metricsSectionElement); this._metricsSectionElement = metricsSectionElement; - - this._setDeviceMetricsOverride(metrics, false, true); + this._onMetricsCheckboxClicked(); return p; }, @@ -564,16 +563,18 @@ WebInspector.UserAgentSettingsTab.prototype = { this._swapDimensionsElement.disabled = controlsDisabled; this._fitWindowCheckboxElement.disabled = controlsDisabled; - if (this._metricsCheckboxElement.checked) { - var metrics = WebInspector.UserAgentSupport.DeviceMetrics.parseUserInput(this._widthOverrideElement.value, this._heightOverrideElement.value, this._fontScaleFactorOverrideElement.value); - if (metrics && metrics.isValid() && metrics.width && metrics.height) - this._setDeviceMetricsOverride(metrics, false, false); - if (!this._widthOverrideElement.value) - this._widthOverrideElement.focus(); - } else { - if (WebInspector.settings.deviceMetrics.get()) - WebInspector.settings.deviceMetrics.set(""); + if (controlsDisabled) { + WebInspector.userAgentSupport.toggleDeviceMetricsOverride(false); + return; + } + + var metrics = WebInspector.UserAgentSupport.DeviceMetrics.parseUserInput(this._widthOverrideElement.value, this._heightOverrideElement.value, this._fontScaleFactorOverrideElement.value); + if (metrics && metrics.isValid() && metrics.width && metrics.height) { + this._setDeviceMetricsOverride(metrics, false, false); + WebInspector.userAgentSupport.toggleDeviceMetricsOverride(true); } + if (!this._widthOverrideElement.value) + this._widthOverrideElement.focus(); }, _applyDeviceMetricsUserInput: function() @@ -675,7 +676,7 @@ WebInspector.UserAgentSettingsTab.prototype = { var checkboxElement = labelElement.createChild("input"); checkboxElement.id = "geolocation-override-checkbox"; checkboxElement.type = "checkbox"; - checkboxElement.checked = !geolocation || (((typeof geolocation.latitude === "number") && (typeof geolocation.longitude === "number")) || geolocation.error); + checkboxElement.checked = false; checkboxElement.addEventListener("click", this._onGeolocationOverrideCheckboxClicked.bind(this), false); this._geolocationOverrideCheckboxElement = checkboxElement; labelElement.appendChild(document.createTextNode(WebInspector.UIString("Override Geolocation"))); @@ -683,7 +684,7 @@ WebInspector.UserAgentSettingsTab.prototype = { var geolocationSectionElement = this._createGeolocationOverrideElement(geolocation); p.appendChild(geolocationSectionElement); this._geolocationSectionElement = geolocationSectionElement; - this._setGeolocationPosition(geolocation, false, true); + this._onGeolocationOverrideCheckboxClicked(); return p; }, @@ -694,14 +695,18 @@ WebInspector.UserAgentSettingsTab.prototype = { this._longitudeElement.disabled = controlsDisabled; this._geolocationErrorElement.disabled = controlsDisabled; - if (this._geolocationOverrideCheckboxElement.checked) { - var geolocation = WebInspector.UserAgentSupport.GeolocationPosition.parseUserInput(this._latitudeElement.value, this._longitudeElement.value, this._geolocationErrorElement.checked); - if (geolocation) - this._setGeolocationPosition(geolocation, false, false); - if (!this._latitudeElement.value) - this._latitudeElement.focus(); - } else - WebInspector.UserAgentSupport.GeolocationPosition.clearGeolocationOverride(); + if (controlsDisabled) { + WebInspector.userAgentSupport.toggleGeolocationPositionOverride(false); + return; + } + + var geolocation = WebInspector.UserAgentSupport.GeolocationPosition.parseUserInput(this._latitudeElement.value, this._longitudeElement.value, this._geolocationErrorElement.checked); + if (geolocation) { + this._setGeolocationPosition(geolocation, false, false); + WebInspector.userAgentSupport.toggleGeolocationPositionOverride(true); + } + if (!this._latitudeElement.value) + this._latitudeElement.focus(); }, _applyGeolocationUserInput: function() @@ -774,7 +779,7 @@ WebInspector.UserAgentSettingsTab.prototype = { var checkboxElement = labelElement.createChild("input"); checkboxElement.id = "device-orientation-override-checkbox"; checkboxElement.type = "checkbox"; - checkboxElement.checked = !deviceOrientation; + checkboxElement.checked = false; checkboxElement.addEventListener("click", this._onDeviceOrientationOverrideCheckboxClicked.bind(this), false); this._deviceOrientationOverrideCheckboxElement = checkboxElement; labelElement.appendChild(document.createTextNode(WebInspector.UIString("Override Device Orientation"))); @@ -782,9 +787,7 @@ WebInspector.UserAgentSettingsTab.prototype = { var deviceOrientationSectionElement = this._createDeviceOrientationOverrideElement(deviceOrientation); p.appendChild(deviceOrientationSectionElement); this._deviceOrientationSectionElement = deviceOrientationSectionElement; - - this._setDeviceOrientation(deviceOrientation, false, true); - + this._onDeviceOrientationOverrideCheckboxClicked(); return p; }, @@ -795,14 +798,18 @@ WebInspector.UserAgentSettingsTab.prototype = { this._betaElement.disabled = controlsDisabled; this._gammaElement.disabled = controlsDisabled; - if (this._deviceOrientationOverrideCheckboxElement.checked) { - var deviceOrientation = WebInspector.UserAgentSupport.DeviceOrientation.parseUserInput(this._alphaElement.value, this._betaElement.value, this._gammaElement.value); - if (deviceOrientation) - this._setDeviceOrientation(deviceOrientation, false, false); - if (!this._alphaElement.value) - this._alphaElement.focus(); - } else - WebInspector.UserAgentSupport.DeviceOrientation.clearDeviceOrientationOverride(); + if (controlsDisabled) { + WebInspector.userAgentSupport.toggleDeviceOrientationOverride(false); + return; + } + + var deviceOrientation = WebInspector.UserAgentSupport.DeviceOrientation.parseUserInput(this._alphaElement.value, this._betaElement.value, this._gammaElement.value); + if (deviceOrientation) { + this._setDeviceOrientation(deviceOrientation, false, false); + WebInspector.userAgentSupport.toggleDeviceOrientationOverride(true); + } + if (!this._alphaElement.value) + this._alphaElement.focus(); }, _applyDeviceOrientationUserInput: function() diff --git a/Source/WebCore/inspector/front-end/StylesSidebarPane.js b/Source/WebCore/inspector/front-end/StylesSidebarPane.js index 6ce7b7989..e18c6359c 100644 --- a/Source/WebCore/inspector/front-end/StylesSidebarPane.js +++ b/Source/WebCore/inspector/front-end/StylesSidebarPane.js @@ -358,7 +358,6 @@ WebInspector.StylesSidebarPane.prototype = { var usedProperties = {}; this._markUsedProperties(styleRules, usedProperties); this.sections[0] = this._rebuildSectionsForStyleRules(styleRules, usedProperties, 0, null); - var responsesLeft = this.sections[0].length; var anchorElement = this.sections[0].inheritedPropertiesSeparatorElement; if (styles.computedStyle) @@ -381,28 +380,9 @@ WebInspector.StylesSidebarPane.prototype = { usedProperties = {}; this._markUsedProperties(styleRules, usedProperties); this.sections[pseudoId] = this._rebuildSectionsForStyleRules(styleRules, usedProperties, pseudoId, anchorElement); - responsesLeft += this.sections[pseudoId].length; } - // Mark matching selectors in comma-delimited selector groups. - var boundMarkCallback = markCallback.bind(this); - for (var id in this.sections) { - var sectionsForPseudoId = this.sections[id].slice(); - for (var j = 0; j < sectionsForPseudoId.length; ++j) { - var section = sectionsForPseudoId[j]; - if (!section.styleRule || section.isBlank || section.styleRule.computedStyle || section.styleRule.isAttribute) { - boundMarkCallback(); - continue; - } - section._markMatchedSelectorsInGroup(boundMarkCallback); - } - } - - function markCallback() - { - if (!(--responsesLeft)) - this._nodeStylesUpdatedForTest(node, true); - } + this._nodeStylesUpdatedForTest(node, true); }, _nodeStylesUpdatedForTest: function(node, rebuild) @@ -606,8 +586,10 @@ WebInspector.StylesSidebarPane.prototype = { if (computedStyle) var section = new WebInspector.ComputedStylePropertiesSection(this, styleRule, usedProperties); - else + else { var section = new WebInspector.StylePropertiesSection(this, styleRule, editable, styleRule.isInherited, lastWasSeparator); + section._markSelectorMatches(); + } section.expanded = true; if (computedStyle) { @@ -1124,89 +1106,38 @@ WebInspector.StylePropertiesSection.prototype = { return null; }, - /** - * @param {function()=} callback - */ - _markMatchedSelectorsInGroup: function(callback) + _markSelectorMatches: function() { - var self = this; - function mycallback() - { - if (callback) - callback(); - } - - var selectorText = this._selectorElement.textContent; - if (!selectorText || selectorText.indexOf(",") === -1) { - mycallback(); + var rule = this.styleRule.rule; + if (!rule) return; - } - var paneNode = this._parentPane.node; - var relatedNode = this.styleRule.parentNode || paneNode; - if (!relatedNode) { - mycallback(); + var selectors = rule.selectors; + var matchingSelectors = rule.matchingSelectors; + if (selectors.length < 2 || !matchingSelectors) return; - } - - function trim(text) - { - return text.trim(); - } - var selectors = selectorText.split(",").map(trim); - - WebInspector.RemoteObject.resolveNode(relatedNode, "", resolvedCallback); - function resolvedCallback(object) - { - if (!object) { - mycallback(); - return; - } - - for (var i = 0, size = selectors.length; i < size; ++i) { - var selector = selectors[i]; - object.callFunctionJSON(matchesSelector, [{ value: selectors[i] }], matchesCallback.bind(this, i)); - } - } - - function matchesSelector(selector) - { - return this.webkitMatchesSelector(selector); - } - - var result = []; - var matchFound; - function matchesCallback(selectorIndex, matches) - { - var isLast = selectorIndex === selectors.length - 1; - var fragment = document.createDocumentFragment(); - result[selectorIndex] = fragment; + var fragment = document.createDocumentFragment(); + var currentMatch = 0; + for (var i = 0, lastSelectorIndex = selectors.length - 1; i <= lastSelectorIndex ; ++i) { var selectorNode; - if (matches && paneNode === self._parentPane.node) { + var textNode = document.createTextNode(selectors[i]); + if (matchingSelectors[currentMatch] === i) { + ++currentMatch; selectorNode = document.createElement("span"); selectorNode.className = "selector-matches"; - selectorNode.appendChild(document.createTextNode(selectors[selectorIndex])); - matchFound = true; + selectorNode.appendChild(textNode); } else - selectorNode = document.createTextNode(selectors[selectorIndex]); + selectorNode = textNode; fragment.appendChild(selectorNode); - if (!isLast) { + if (i !== lastSelectorIndex) fragment.appendChild(document.createTextNode(", ")); - return; - } - - // This check is here in case the element class has been changed from JS during the roundtrip, - // so the element matches none of the distinct selectors. Fall back to "all selectors match". - if (matchFound) { - self._selectorElement.className = "selector"; - self._selectorElement.removeChildren(); - for (var i = 0; i < result.length; ++i) - self._selectorElement.appendChild(result[i]); - } - mycallback(); } + + this._selectorElement.className = "selector"; + this._selectorElement.removeChildren(); + this._selectorElement.appendChild(fragment); }, _checkWillCancelEditing: function() @@ -1350,32 +1281,27 @@ WebInspector.StylePropertiesSection.prototype = { _moveEditorFromSelector: function(moveDirection) { + this._markSelectorMatches(); - if (!moveDirection) { - this._markMatchedSelectorsInGroup(); + if (!moveDirection) return; - } - - this._markMatchedSelectorsInGroup(markCallback.bind(this)); - function markCallback() { - if (moveDirection === "forward") { - this.expand(); - var firstChild = this.propertiesTreeOutline.children[0]; - while (firstChild && firstChild.inherited) - firstChild = firstChild.nextSibling; - if (!firstChild) - this.addNewBlankProperty().startEditing(); - else - firstChild.startEditing(firstChild.nameElement); - } else { - var previousSection = this.previousEditableSibling(); - if (!previousSection) - return; + if (moveDirection === "forward") { + this.expand(); + var firstChild = this.propertiesTreeOutline.children[0]; + while (firstChild && firstChild.inherited) + firstChild = firstChild.nextSibling; + if (!firstChild) + this.addNewBlankProperty().startEditing(); + else + firstChild.startEditing(firstChild.nameElement); + } else { + var previousSection = this.previousEditableSibling(); + if (!previousSection) + return; - previousSection.expand(); - previousSection.addNewBlankProperty().startEditing(); - } + previousSection.expand(); + previousSection.addNewBlankProperty().startEditing(); } }, @@ -1415,7 +1341,7 @@ WebInspector.StylePropertiesSection.prototype = { { // Do nothing but mark the selectors in group if necessary. // This is overridden by BlankStylePropertiesSection. - this._markMatchedSelectorsInGroup(); + this._markSelectorMatches(); } } diff --git a/Source/WebCore/inspector/front-end/UserAgentSupport.js b/Source/WebCore/inspector/front-end/UserAgentSupport.js index 794d11a96..ebed8079c 100644 --- a/Source/WebCore/inspector/front-end/UserAgentSupport.js +++ b/Source/WebCore/inspector/front-end/UserAgentSupport.js @@ -33,8 +33,10 @@ */ WebInspector.UserAgentSupport = function() { - if (WebInspector.settings.deviceMetrics.get()) - this._deviceMetricsChanged(); + this._deviceMetricsOverrideEnabled = false; + this._geolocationPositionOverrideEnabled = false; + this._deviceOrientationOverrideEnabled = false; + WebInspector.settings.deviceMetrics.addChangeListener(this._deviceMetricsChanged, this); WebInspector.settings.deviceFitWindow.addChangeListener(this._deviceMetricsChanged, this); WebInspector.settings.geolocationOverride.addChangeListener(this._geolocationPositionChanged, this); @@ -305,15 +307,43 @@ WebInspector.UserAgentSupport.DeviceOrientation.clearDeviceOrientationOverride = } WebInspector.UserAgentSupport.prototype = { + toggleDeviceMetricsOverride: function(enabled) + { + if (enabled === this._deviceMetricsOverrideEnabled) + return; + this._deviceMetricsOverrideEnabled = enabled; + this._deviceMetricsChanged(); + }, + + toggleGeolocationPositionOverride: function(enabled) + { + if (enabled === this._geolocationPositionOverrideEnabled) + return; + this._geolocationPositionOverrideEnabled = enabled; + this._geolocationPositionChanged(); + }, + + toggleDeviceOrientationOverride: function(enabled) + { + if (enabled === this._deviceOrientationOverrideEnabled) + return; + this._deviceOrientationOverrideEnabled = enabled; + this._deviceOrientationChanged(); + }, + _deviceMetricsChanged: function() { - var metrics = WebInspector.UserAgentSupport.DeviceMetrics.parseSetting(WebInspector.settings.deviceMetrics.get()); + var metrics = WebInspector.UserAgentSupport.DeviceMetrics.parseSetting(this._deviceMetricsOverrideEnabled ? WebInspector.settings.deviceMetrics.get() : ""); if (metrics.isValid()) PageAgent.setDeviceMetricsOverride(metrics.width, metrics.height, metrics.fontScaleFactor, WebInspector.settings.deviceFitWindow.get()); }, _geolocationPositionChanged: function() { + if (!this._geolocationPositionOverrideEnabled) { + PageAgent.clearGeolocationOverride(); + return; + } var geolocation = WebInspector.UserAgentSupport.GeolocationPosition.parseSetting(WebInspector.settings.geolocationOverride.get()); if (geolocation.error) PageAgent.setGeolocationOverride(); @@ -321,11 +351,12 @@ WebInspector.UserAgentSupport.prototype = { PageAgent.setGeolocationOverride(geolocation.latitude, geolocation.longitude, 150); }, - /** - * @param {WebInspector.Event} event - */ - _deviceOrientationChanged: function(event) + _deviceOrientationChanged: function() { + if (!this._deviceOrientationOverrideEnabled) { + PageAgent.clearDeviceOrientationOverride(); + return; + } var deviceOrientation = WebInspector.UserAgentSupport.DeviceOrientation.parseSetting(WebInspector.settings.deviceOrientationOverride.get()); PageAgent.setDeviceOrientationOverride(deviceOrientation.alpha, deviceOrientation.beta, deviceOrientation.gamma); } diff --git a/Source/WebCore/inspector/front-end/externs.js b/Source/WebCore/inspector/front-end/externs.js index 8cf53d26c..21d61a00a 100644 --- a/Source/WebCore/inspector/front-end/externs.js +++ b/Source/WebCore/inspector/front-end/externs.js @@ -262,6 +262,11 @@ WebInspector.showPanel = function(panel) */ WebInspector.inspectedPageDomain; +/** + * @type {WebInspector.UserAgentSupport} + */ +WebInspector.userAgentSupport; + WebInspector.isCompactMode = function() { return false; } WebInspector.SourceJavaScriptTokenizer = {} diff --git a/Source/WebCore/inspector/front-end/inspector.css b/Source/WebCore/inspector/front-end/inspector.css index d5b13097b..1c126ea8e 100644 --- a/Source/WebCore/inspector/front-end/inspector.css +++ b/Source/WebCore/inspector/front-end/inspector.css @@ -2348,6 +2348,7 @@ li.breakpoint-hit .breakpoint-hit-marker { -webkit-border-radius: 7px; border: 2px solid rgb(169, 172, 203); width: 90%; + pointer-events: auto; } .source-frame-breakpoint-message { diff --git a/Source/WebCore/inspector/front-end/inspector.js b/Source/WebCore/inspector/front-end/inspector.js index ab67c474c..e77a90bfa 100644 --- a/Source/WebCore/inspector/front-end/inspector.js +++ b/Source/WebCore/inspector/front-end/inspector.js @@ -86,7 +86,7 @@ var WebInspector = { if (!WebInspector.WorkerManager.isWorkerFrontend()) { this._nodeSearchButton = new WebInspector.StatusBarButton(WebInspector.UIString("Select an element in the page to inspect it."), "node-search-status-bar-item"); - this._nodeSearchButton.addEventListener("click", this._toggleSearchingForNode, this); + this._nodeSearchButton.addEventListener("click", this.toggleSearchingForNode, this); mainStatusBar.insertBefore(this._nodeSearchButton.element, bottomStatusBarContainer); } @@ -356,7 +356,7 @@ var WebInspector = { InspectorFrontendHost.setZoomFactor(Math.pow(1.2, this._zoomLevel)); }, - _toggleSearchingForNode: function() + toggleSearchingForNode: function() { var enabled = !this._nodeSearchButton.toggled; /** @@ -862,7 +862,7 @@ WebInspector.documentKeyDown = function(event) var isNodeSearchKey = event.ctrlKey && !event.metaKey && !event.altKey && event.shiftKey; if (isNodeSearchKey) { - this._toggleSearchingForNode(); + this.toggleSearchingForNode(); event.consume(true); return; } diff --git a/Source/WebCore/loader/DocumentLoader.cpp b/Source/WebCore/loader/DocumentLoader.cpp index 8368041cf..900af978a 100644 --- a/Source/WebCore/loader/DocumentLoader.cpp +++ b/Source/WebCore/loader/DocumentLoader.cpp @@ -53,6 +53,7 @@ #include "TextResourceDecoder.h" #include "WebCoreMemoryInstrumentation.h" #include <wtf/Assertions.h> +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/text/CString.h> #include <wtf/text/WTFString.h> #include <wtf/unicode/Unicode.h> @@ -368,16 +369,16 @@ void DocumentLoader::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const info.addMember(m_substituteData); info.addMember(m_pageTitle.string()); info.addMember(m_overrideEncoding); - info.addVector(m_responses); + info.addMember(m_responses); info.addMember(m_originalRequest); info.addMember(m_originalRequestCopy); info.addMember(m_request); info.addMember(m_response); info.addMember(m_lastCheckedRequest); - info.addInstrumentedVector(m_responses); + info.addMember(m_responses); info.addHashMap(m_pendingSubstituteResources); info.addInstrumentedHashSet(m_resourcesClientKnowsAbout); - info.addVector(m_resourcesLoadedFromMemoryCacheForClientNotification); + info.addMember(m_resourcesLoadedFromMemoryCacheForClientNotification); info.addMember(m_clientRedirectSourceForHistory); info.addMember(m_mainResourceData); } diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp index b26b6d4cc..89f876242 100644 --- a/Source/WebCore/loader/FrameLoader.cpp +++ b/Source/WebCore/loader/FrameLoader.cpp @@ -647,7 +647,10 @@ void FrameLoader::didBeginDocument(bool dispatch) m_frame->document()->initContentSecurityPolicy(); Settings* settings = m_frame->document()->settings(); - m_frame->document()->cachedResourceLoader()->setAutoLoadImages(settings && settings->loadsImagesAutomatically()); + if (settings) { + m_frame->document()->cachedResourceLoader()->setImagesEnabled(settings->areImagesEnabled()); + m_frame->document()->cachedResourceLoader()->setAutoLoadImages(settings->loadsImagesAutomatically()); + } if (m_documentLoader) { String dnsPrefetchControl = m_documentLoader->response().httpHeaderField("X-DNS-Prefetch-Control"); diff --git a/Source/WebCore/loader/SubresourceLoader.cpp b/Source/WebCore/loader/SubresourceLoader.cpp index ff3be6edf..56de0d341 100644 --- a/Source/WebCore/loader/SubresourceLoader.cpp +++ b/Source/WebCore/loader/SubresourceLoader.cpp @@ -167,11 +167,13 @@ void SubresourceLoader::willSendRequest(ResourceRequest& newRequest, const Resou ResourceLoader::willSendRequest(newRequest, redirectResponse); if (!previousURL.isNull() && !newRequest.isNull() && previousURL != newRequest.url()) { - if (!m_document->cachedResourceLoader()->canRequest(m_resource->type(), newRequest.url())) { - cancel(); - return; + if (m_document->cachedResourceLoader()->canRequest(m_resource->type(), newRequest.url())) { + if (m_resource->type() != CachedResource::ImageResource || !m_document->cachedResourceLoader()->shouldDeferImageLoad(newRequest.url())) { + m_resource->willSendRequest(newRequest, redirectResponse); + return; + } } - m_resource->willSendRequest(newRequest, redirectResponse); + cancel(); } } diff --git a/Source/WebCore/loader/cache/CachedImage.cpp b/Source/WebCore/loader/cache/CachedImage.cpp index 4316616b3..41075a7b3 100644 --- a/Source/WebCore/loader/cache/CachedImage.cpp +++ b/Source/WebCore/loader/cache/CachedImage.cpp @@ -29,7 +29,6 @@ #include "CachedResourceClient.h" #include "CachedResourceClientWalker.h" #include "CachedResourceLoader.h" -#include "Frame.h" #include "FrameLoaderClient.h" #include "FrameLoaderTypes.h" #include "FrameView.h" diff --git a/Source/WebCore/loader/cache/CachedImage.h b/Source/WebCore/loader/cache/CachedImage.h index 4865c7e24..078f7ab1c 100644 --- a/Source/WebCore/loader/cache/CachedImage.h +++ b/Source/WebCore/loader/cache/CachedImage.h @@ -82,8 +82,7 @@ public: virtual bool shouldIgnoreHTTPStatusCodeErrors() const { return true; } virtual bool isImage() const { return true; } - bool stillNeedsLoad() const { return !errorOccurred() && status() == Unknown && !isLoading(); } - void load(); + virtual bool stillNeedsLoad() const OVERRIDE { return !errorOccurred() && status() == Unknown && !isLoading(); } // ImageObserver virtual void decodedSizeChanged(const Image* image, int delta); diff --git a/Source/WebCore/loader/cache/CachedResource.cpp b/Source/WebCore/loader/cache/CachedResource.cpp index 43c3d144f..33d1ba823 100755 --- a/Source/WebCore/loader/cache/CachedResource.cpp +++ b/Source/WebCore/loader/cache/CachedResource.cpp @@ -32,7 +32,6 @@ #include "CachedResourceLoader.h" #include "CrossOriginAccessControl.h" #include "Document.h" -#include "Frame.h" #include "FrameLoaderClient.h" #include "InspectorInstrumentation.h" #include "KURL.h" @@ -390,7 +389,7 @@ void CachedResource::didAddClient(CachedResourceClient* c) m_clients.add(c); m_clientsAwaitingCallback.remove(c); } - if (!isLoading()) + if (!isLoading() && !stillNeedsLoad()) c->notifyFinished(this); } diff --git a/Source/WebCore/loader/cache/CachedResource.h b/Source/WebCore/loader/cache/CachedResource.h index 0cad3ee7c..b739d68af 100644 --- a/Source/WebCore/loader/cache/CachedResource.h +++ b/Source/WebCore/loader/cache/CachedResource.h @@ -45,7 +45,6 @@ class CachedMetadata; class CachedResourceClient; class CachedResourceHandleBase; class CachedResourceLoader; -class Frame; class InspectorResource; class PurgeableBuffer; class SecurityOrigin; @@ -144,6 +143,7 @@ public: bool isLoading() const { return m_loading; } void setLoading(bool b) { m_loading = b; } + virtual bool stillNeedsLoad() const { return false; } SubresourceLoader* loader() { return m_loader.get(); } diff --git a/Source/WebCore/loader/cache/CachedResourceLoader.cpp b/Source/WebCore/loader/cache/CachedResourceLoader.cpp index 353a62aa6..593d532a1 100644 --- a/Source/WebCore/loader/cache/CachedResourceLoader.cpp +++ b/Source/WebCore/loader/cache/CachedResourceLoader.cpp @@ -115,6 +115,7 @@ CachedResourceLoader::CachedResourceLoader(Document* document) , m_requestCount(0) , m_garbageCollectDocumentResourcesTimer(this, &CachedResourceLoader::garbageCollectDocumentResourcesTimerFired) , m_autoLoadImages(true) + , m_imagesEnabled(true) , m_allowStaleResources(false) { } @@ -159,10 +160,7 @@ CachedResourceHandle<CachedImage> CachedResourceLoader::requestImage(ResourceReq return 0; } } - CachedResourceHandle<CachedImage> resource(static_cast<CachedImage*>(requestResource(CachedResource::ImageResource, request, String(), defaultCachedResourceOptions()).get())); - if (autoLoadImages() && resource && resource->stillNeedsLoad()) - resource->load(this, defaultCachedResourceOptions()); - return resource; + return static_cast<CachedImage*>(requestResource(CachedResource::ImageResource, request, String(), defaultCachedResourceOptions(), ResourceLoadPriorityUnresolved, false, clientDefersImage(request.url()) ? DeferredByClient : NoDefer).get()); } CachedResourceHandle<CachedFont> CachedResourceLoader::requestFont(ResourceRequest& request) @@ -362,12 +360,6 @@ bool CachedResourceLoader::canRequest(CachedResource::Type type, const KURL& url case CachedResource::ImageResource: if (!m_document->contentSecurityPolicy()->allowImageFromSource(url)) return false; - - if (frame()) { - Settings* settings = frame()->settings(); - if (!frame()->loader()->client()->allowImage(!settings || settings->areImagesEnabled(), url)) - return false; - } break; case CachedResource::FontResource: { if (!m_document->contentSecurityPolicy()->allowFontFromSource(url)) @@ -401,7 +393,7 @@ bool CachedResourceLoader::canRequest(CachedResource::Type type, const KURL& url return true; } -CachedResourceHandle<CachedResource> CachedResourceLoader::requestResource(CachedResource::Type type, ResourceRequest& request, const String& charset, const ResourceLoaderOptions& options, ResourceLoadPriority priority, bool forPreload) +CachedResourceHandle<CachedResource> CachedResourceLoader::requestResource(CachedResource::Type type, ResourceRequest& request, const String& charset, const ResourceLoaderOptions& options, ResourceLoadPriority priority, bool forPreload, DeferOption defer) { KURL url = request.url(); @@ -430,16 +422,16 @@ CachedResourceHandle<CachedResource> CachedResourceLoader::requestResource(Cache if (request.url() != url) request.setURL(url); - switch (determineRevalidationPolicy(type, request, forPreload, resource.get())) { - case Load: - resource = loadResource(type, request, charset, priority, options); - break; + const RevalidationPolicy policy = determineRevalidationPolicy(type, request, forPreload, resource.get(), defer); + switch (policy) { case Reload: memoryCache()->remove(resource.get()); - resource = loadResource(type, request, charset, priority, options); + // Fall through + case Load: + resource = loadResource(type, request, charset); break; case Revalidate: - resource = revalidateResource(resource.get(), priority, options); + resource = revalidateResource(resource.get()); break; case Use: memoryCache()->resourceAccessed(resource.get()); @@ -450,12 +442,27 @@ CachedResourceHandle<CachedResource> CachedResourceLoader::requestResource(Cache if (!resource) return 0; + resource->setLoadPriority(priority); + if ((policy != Use || resource->stillNeedsLoad()) && NoDefer == defer) { + resource->load(this, options); + + // We don't support immediate loads, but we do support immediate failure. + if (resource->errorOccurred()) { + if (resource->inCache()) + memoryCache()->remove(resource.get()); + return 0; + } + } + + if (!request.url().protocolIsData()) + m_validatedURLs.add(request.url()); + ASSERT(resource->url() == url.string()); m_documentResources.set(resource->url(), resource); return resource; } -CachedResourceHandle<CachedResource> CachedResourceLoader::revalidateResource(CachedResource* resource, ResourceLoadPriority priority, const ResourceLoaderOptions& options) +CachedResourceHandle<CachedResource> CachedResourceLoader::revalidateResource(CachedResource* resource) { ASSERT(resource); ASSERT(resource->inCache()); @@ -465,7 +472,6 @@ CachedResourceHandle<CachedResource> CachedResourceLoader::revalidateResource(Ca // Copy the URL out of the resource to be revalidated in case it gets deleted by the remove() call below. String url = resource->url(); - bool urlProtocolIsData = resource->url().protocolIsData(); CachedResourceHandle<CachedResource> newResource = createResource(resource->type(), resource->resourceRequest(), resource->encoding()); LOG(ResourceLoading, "Resource %p created to revalidate %p", newResource.get(), resource); @@ -473,16 +479,10 @@ CachedResourceHandle<CachedResource> CachedResourceLoader::revalidateResource(Ca memoryCache()->remove(resource); memoryCache()->add(newResource.get()); - - newResource->setLoadPriority(priority); - newResource->load(this, options); - - if (!urlProtocolIsData) - m_validatedURLs.add(url); return newResource; } -CachedResourceHandle<CachedResource> CachedResourceLoader::loadResource(CachedResource::Type type, ResourceRequest& request, const String& charset, ResourceLoadPriority priority, const ResourceLoaderOptions& options) +CachedResourceHandle<CachedResource> CachedResourceLoader::loadResource(CachedResource::Type type, ResourceRequest& request, const String& charset) { ASSERT(!memoryCache()->resourceForURL(request.url())); @@ -490,35 +490,20 @@ CachedResourceHandle<CachedResource> CachedResourceLoader::loadResource(CachedRe CachedResourceHandle<CachedResource> resource = createResource(type, request, charset); - bool inCache = memoryCache()->add(resource.get()); - - resource->setLoadPriority(priority); - resource->load(this, options); - - if (!inCache) + if (!memoryCache()->add(resource.get())) resource->setOwningCachedResourceLoader(this); - - // We don't support immediate loads, but we do support immediate failure. - if (resource->errorOccurred()) { - if (inCache) - memoryCache()->remove(resource.get()); - return 0; - } - - if (!request.url().protocolIsData()) - m_validatedURLs.add(request.url()); return resource; } -CachedResourceLoader::RevalidationPolicy CachedResourceLoader::determineRevalidationPolicy(CachedResource::Type type, ResourceRequest& request, bool forPreload, CachedResource* existingResource) const +CachedResourceLoader::RevalidationPolicy CachedResourceLoader::determineRevalidationPolicy(CachedResource::Type type, ResourceRequest& request, bool forPreload, CachedResource* existingResource, DeferOption defer) const { if (!existingResource) return Load; - + // We already have a preload going for this URL. if (forPreload && existingResource->isPreloaded()) return Use; - + // If the same URL has been loaded as a different type, we need to reload. if (existingResource->type() != type) { LOG(ResourceLoading, "CachedResourceLoader::determineRevalidationPolicy reloading due to type mismatch."); @@ -533,6 +518,11 @@ CachedResourceLoader::RevalidationPolicy CachedResourceLoader::determineRevalida // of things about how revalidation works that manual headers violate, so punt to Reload instead. if (request.isConditional()) return Reload; + + // Do not load from cache if images are not enabled. The load for this image will be blocked + // in CachedImage::load. + if (DeferredByClient == defer) + return Reload; // Don't reload resources while pasting. if (m_allowStaleResources) @@ -629,15 +619,39 @@ void CachedResourceLoader::setAutoLoadImages(bool enable) if (!m_autoLoadImages) return; + reloadImagesIfNotDeferred(); +} + +void CachedResourceLoader::setImagesEnabled(bool enable) +{ + if (enable == m_imagesEnabled) + return; + + m_imagesEnabled = enable; + + if (!m_imagesEnabled) + return; + + reloadImagesIfNotDeferred(); +} + +bool CachedResourceLoader::clientDefersImage(const KURL& url) const +{ + return frame() && !frame()->loader()->client()->allowImage(m_imagesEnabled, url); +} + +bool CachedResourceLoader::shouldDeferImageLoad(const KURL& url) const +{ + return clientDefersImage(url) || !m_autoLoadImages; +} + +void CachedResourceLoader::reloadImagesIfNotDeferred() +{ DocumentResourceMap::iterator end = m_documentResources.end(); for (DocumentResourceMap::iterator it = m_documentResources.begin(); it != end; ++it) { CachedResource* resource = it->second.get(); - if (resource->type() == CachedResource::ImageResource) { - CachedImage* image = const_cast<CachedImage*>(static_cast<const CachedImage*>(resource)); - - if (image->stillNeedsLoad()) - image->load(this, defaultCachedResourceOptions()); - } + if (resource->type() == CachedResource::ImageResource && resource->stillNeedsLoad() && !clientDefersImage(resource->url())) + const_cast<CachedResource*>(resource)->load(this, defaultCachedResourceOptions()); } } diff --git a/Source/WebCore/loader/cache/CachedResourceLoader.h b/Source/WebCore/loader/cache/CachedResourceLoader.h index f4755c22f..b5dc69482 100644 --- a/Source/WebCore/loader/cache/CachedResourceLoader.h +++ b/Source/WebCore/loader/cache/CachedResourceLoader.h @@ -97,6 +97,10 @@ public: bool autoLoadImages() const { return m_autoLoadImages; } void setAutoLoadImages(bool); + + void setImagesEnabled(bool); + + bool shouldDeferImageLoad(const KURL&) const; CachePolicy cachePolicy() const; @@ -122,19 +126,23 @@ public: void reportMemoryUsage(MemoryObjectInfo*) const; private: - CachedResourceHandle<CachedResource> requestResource(CachedResource::Type, ResourceRequest&, const String& charset, const ResourceLoaderOptions&, ResourceLoadPriority = ResourceLoadPriorityUnresolved, bool isPreload = false); - CachedResourceHandle<CachedResource> revalidateResource(CachedResource*, ResourceLoadPriority, const ResourceLoaderOptions&); - CachedResourceHandle<CachedResource> loadResource(CachedResource::Type, ResourceRequest&, const String& charset, ResourceLoadPriority, const ResourceLoaderOptions&); + enum DeferOption { NoDefer, DeferredByClient }; + CachedResourceHandle<CachedResource> requestResource(CachedResource::Type, ResourceRequest&, const String& charset, const ResourceLoaderOptions&, ResourceLoadPriority = ResourceLoadPriorityUnresolved, bool isPreload = false, DeferOption = NoDefer); + CachedResourceHandle<CachedResource> revalidateResource(CachedResource*); + CachedResourceHandle<CachedResource> loadResource(CachedResource::Type, ResourceRequest&, const String& charset); void requestPreload(CachedResource::Type, ResourceRequest&, const String& charset); enum RevalidationPolicy { Use, Revalidate, Reload, Load }; - RevalidationPolicy determineRevalidationPolicy(CachedResource::Type, ResourceRequest&, bool forPreload, CachedResource* existingResource) const; + RevalidationPolicy determineRevalidationPolicy(CachedResource::Type, ResourceRequest&, bool forPreload, CachedResource* existingResource, DeferOption) const; void notifyLoadedFromMemoryCache(CachedResource*); bool checkInsecureContent(CachedResource::Type, const KURL&) const; void garbageCollectDocumentResourcesTimerFired(Timer<CachedResourceLoader>*); void performPostLoadActions(); + + bool clientDefersImage(const KURL&) const; + void reloadImagesIfNotDeferred(); HashSet<String> m_validatedURLs; mutable DocumentResourceMap m_documentResources; @@ -152,8 +160,9 @@ private: Timer<CachedResourceLoader> m_garbageCollectDocumentResourcesTimer; - // 30 bits left + // 29 bits left bool m_autoLoadImages : 1; + bool m_imagesEnabled : 1; bool m_allowStaleResources : 1; }; diff --git a/Source/WebCore/loader/cache/MemoryCache.cpp b/Source/WebCore/loader/cache/MemoryCache.cpp index 66d3201eb..c1af09d69 100644 --- a/Source/WebCore/loader/cache/MemoryCache.cpp +++ b/Source/WebCore/loader/cache/MemoryCache.cpp @@ -45,6 +45,7 @@ #include "WorkerThread.h" #include <stdio.h> #include <wtf/CurrentTime.h> +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/TemporaryChange.h> #include <wtf/text/CString.h> @@ -724,7 +725,7 @@ void MemoryCache::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const info.addMember(i->first); info.addMember(i->second); } - info.addVector(m_allResources); + info.addMember(m_allResources); info.addMember(m_liveDecodedResources); } diff --git a/Source/WebCore/mathml/MathMLMathElement.cpp b/Source/WebCore/mathml/MathMLMathElement.cpp index 80d915700..bc50d9b8a 100644 --- a/Source/WebCore/mathml/MathMLMathElement.cpp +++ b/Source/WebCore/mathml/MathMLMathElement.cpp @@ -47,7 +47,7 @@ Node::InsertionNotificationRequest MathMLMathElement::insertedInto(ContainerNode { // There are sibling rules in the MathML default style. if (insertionPoint->inDocument()) - document()->setUsesSiblingRules(true); + document()->styleSheetCollection()->setUsesSiblingRulesOverride(true); return MathMLInlineContainerElement::insertedInto(insertionPoint); } diff --git a/Source/WebCore/page/FeatureObserver.h b/Source/WebCore/page/FeatureObserver.h index 9096ec596..6a50c53df 100644 --- a/Source/WebCore/page/FeatureObserver.h +++ b/Source/WebCore/page/FeatureObserver.h @@ -48,6 +48,7 @@ public: LegacyWebAudioNoteOn, WebAudioStart, PrefixedContentSecurityPolicy, + UnprefixedIndexedDB, // Add new features above this line. NumberOfFeatures, // This enum value must be last. }; diff --git a/Source/WebCore/page/Page.cpp b/Source/WebCore/page/Page.cpp index cf4d0fec9..62b4c55b5 100644 --- a/Source/WebCore/page/Page.cpp +++ b/Source/WebCore/page/Page.cpp @@ -29,6 +29,7 @@ #include "ContextMenuController.h" #include "DOMWindow.h" #include "DocumentMarkerController.h" +#include "DocumentStyleSheetCollection.h" #include "DragController.h" #include "EditorClient.h" #include "Event.h" @@ -838,7 +839,7 @@ void Page::userStyleSheetLocationChanged() for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) { if (frame->document()) - frame->document()->updatePageUserSheet(); + frame->document()->styleSheetCollection()->updatePageUserSheet(); } } diff --git a/Source/WebCore/page/PageGroup.cpp b/Source/WebCore/page/PageGroup.cpp index 45d25f552..0fed49138 100644 --- a/Source/WebCore/page/PageGroup.cpp +++ b/Source/WebCore/page/PageGroup.cpp @@ -29,6 +29,7 @@ #include "Chrome.h" #include "ChromeClient.h" #include "Document.h" +#include "DocumentStyleSheetCollection.h" #include "Frame.h" #include "GroupSettings.h" #include "Page.h" @@ -391,7 +392,7 @@ void PageGroup::resetUserStyleCacheInAllFrames() HashSet<Page*>::const_iterator end = m_pages.end(); for (HashSet<Page*>::const_iterator it = m_pages.begin(); it != end; ++it) { for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext()) - frame->document()->updatePageGroupUserSheets(); + frame->document()->styleSheetCollection()->updatePageGroupUserSheets(); } } diff --git a/Source/WebCore/page/Settings.cpp b/Source/WebCore/page/Settings.cpp index df425964d..30666c561 100644 --- a/Source/WebCore/page/Settings.cpp +++ b/Source/WebCore/page/Settings.cpp @@ -46,10 +46,12 @@ using namespace std; namespace WebCore { -static void setLoadsImagesAutomaticallyInAllFrames(Page* page) +static void setImageLoadingSettings(Page* page) { - for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) + for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) { + frame->document()->cachedResourceLoader()->setImagesEnabled(page->settings()->areImagesEnabled()); frame->document()->cachedResourceLoader()->setAutoLoadImages(page->settings()->loadsImagesAutomatically()); + } } // Sets the entry in the font map for the given script. If family is the empty string, removes the entry instead. @@ -291,7 +293,7 @@ Settings::Settings(Page* page) , m_windowFocusRestricted(true) , m_diagnosticLoggingEnabled(false) , m_scrollingPerformanceLoggingEnabled(false) - , m_loadsImagesAutomaticallyTimer(this, &Settings::loadsImagesAutomaticallyTimerFired) + , m_setImageLoadingSettingsTimer(this, &Settings::imageLoadingSettingsTimerFired) , m_incrementalRenderingSuppressionTimeoutInSeconds(defaultIncrementalRenderingSuppressionTimeoutInSeconds) { // A Frame may not have been created yet, so we initialize the AtomicString @@ -466,12 +468,12 @@ void Settings::setLoadsImagesAutomatically(bool loadsImagesAutomatically) // Starting these loads synchronously is not important. By putting it on a 0-delay, properly closing the Page cancels them // before they have a chance to really start. // See http://webkit.org/b/60572 for more discussion. - m_loadsImagesAutomaticallyTimer.startOneShot(0); + m_setImageLoadingSettingsTimer.startOneShot(0); } -void Settings::loadsImagesAutomaticallyTimerFired(Timer<Settings>*) +void Settings::imageLoadingSettingsTimerFired(Timer<Settings>*) { - setLoadsImagesAutomaticallyInAllFrames(m_page); + setImageLoadingSettings(m_page); } void Settings::setLoadsSiteIconsIgnoringImageLoadingSetting(bool loadsSiteIcons) @@ -517,6 +519,9 @@ void Settings::setJavaEnabledForLocalFiles(bool isJavaEnabledForLocalFiles) void Settings::setImagesEnabled(bool areImagesEnabled) { m_areImagesEnabled = areImagesEnabled; + + // See comment in setLoadsImagesAutomatically. + m_setImageLoadingSettingsTimer.startOneShot(0); } void Settings::setMediaEnabled(bool isMediaEnabled) diff --git a/Source/WebCore/page/Settings.h b/Source/WebCore/page/Settings.h index 83986f697..c18dfd730 100644 --- a/Source/WebCore/page/Settings.h +++ b/Source/WebCore/page/Settings.h @@ -818,8 +818,8 @@ namespace WebCore { bool m_scrollingPerformanceLoggingEnabled : 1; - Timer<Settings> m_loadsImagesAutomaticallyTimer; - void loadsImagesAutomaticallyTimerFired(Timer<Settings>*); + Timer<Settings> m_setImageLoadingSettingsTimer; + void imageLoadingSettingsTimerFired(Timer<Settings>*); double m_incrementalRenderingSuppressionTimeoutInSeconds; diff --git a/Source/WebCore/page/ValidationMessageClient.h b/Source/WebCore/page/ValidationMessageClient.h index 5c8a3556c..3beaca09f 100644 --- a/Source/WebCore/page/ValidationMessageClient.h +++ b/Source/WebCore/page/ValidationMessageClient.h @@ -26,6 +26,8 @@ #ifndef ValidationMessageClient_h #define ValidationMessageClient_h +#include <wtf/Forward.h> + namespace WebCore { class Element; diff --git a/Source/WebCore/page/mac/EventHandlerMac.mm b/Source/WebCore/page/mac/EventHandlerMac.mm index bd8ee4704..d2020c771 100644 --- a/Source/WebCore/page/mac/EventHandlerMac.mm +++ b/Source/WebCore/page/mac/EventHandlerMac.mm @@ -225,9 +225,10 @@ bool EventHandler::passMouseDownEventToWidget(Widget* pWidget) ASSERT(!m_sendingEventToSubview); m_sendingEventToSubview = true; - RenderWidget::suspendWidgetHierarchyUpdates(); - [view mouseDown:currentNSEvent()]; - RenderWidget::resumeWidgetHierarchyUpdates(); + { + WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; + [view mouseDown:currentNSEvent()]; + } m_sendingEventToSubview = false; diff --git a/Source/WebCore/platform/FractionalLayoutUnit.h b/Source/WebCore/platform/FractionalLayoutUnit.h index 0f3a86a1f..06be89787 100644 --- a/Source/WebCore/platform/FractionalLayoutUnit.h +++ b/Source/WebCore/platform/FractionalLayoutUnit.h @@ -227,6 +227,15 @@ public: #endif } + FractionalLayoutUnit fraction() const + { + // Add the fraction to the size (as opposed to the full location) to avoid overflows. + // Compute fraction using the mod operator to preserve the sign of the value as it may affect rounding. + FractionalLayoutUnit fraction; + fraction.setRawValue(rawValue() % kFixedPointDenominator); + return fraction; + } + #if ENABLE(SUBPIXEL_LAYOUT) static float epsilon() { return 1.0f / kFixedPointDenominator; } #else @@ -807,7 +816,7 @@ inline float& operator/=(float& a, const FractionalLayoutUnit& b) inline int snapSizeToPixel(FractionalLayoutUnit size, FractionalLayoutUnit location) { - FractionalLayoutUnit fraction = location - location.floor(); + FractionalLayoutUnit fraction = location.fraction(); return (fraction + size).round() - fraction.round(); } diff --git a/Source/WebCore/platform/KURLWTFURL.cpp b/Source/WebCore/platform/KURLWTFURL.cpp index f030b8719..9a3484d41 100644 --- a/Source/WebCore/platform/KURLWTFURL.cpp +++ b/Source/WebCore/platform/KURLWTFURL.cpp @@ -26,7 +26,11 @@ #include "config.h" #include "KURL.h" +#include <TextEncoding.h> #include <wtf/DataLog.h> +#include <wtf/text/CString.h> +#include <wtf/url/api/URLBuffer.h> +#include <wtf/url/api/URLQueryCharsetConverter.h> #if USE(WTFURL) @@ -51,29 +55,55 @@ static inline void detach(RefPtr<KURLWTFURLImpl>& urlImpl) KURL::KURL(ParsedURLStringTag, const String& urlString) : m_urlImpl(adoptRef(new KURLWTFURLImpl())) { - m_urlImpl->m_parsedURL = ParsedURL(urlString); + m_urlImpl->m_parsedURL = ParsedURL(urlString, ParsedURL::ParsedURLString); // FIXME: Frame::init() actually create empty URL, investigate why not just null URL. // ASSERT(m_urlImpl->m_parsedURL.isValid()); } +class CharsetConverter : public URLQueryCharsetConverter { +public: + CharsetConverter(const TextEncoding& encoding) + : m_encoding(encoding) + { + } + + virtual void convertFromUTF16(const UChar* input, unsigned inputLength, URLBuffer<char>& output) OVERRIDE + { + CString encoded = m_encoding.encode(input, inputLength, URLEncodedEntitiesForUnencodables); + output.append(encoded.data(), static_cast<int>(encoded.length())); + } + +private: + const TextEncoding& m_encoding; +}; + KURL::KURL(const KURL& baseURL, const String& relative) : m_urlImpl(adoptRef(new KURLWTFURLImpl())) { // FIXME: the case with a null baseURL is common. We should have a separate constructor in KURL. // FIXME: the case of an empty Base is useless, we should get rid of empty URLs. + CharsetConverter charsetConverter(UTF8Encoding()); if (baseURL.isEmpty()) - m_urlImpl->m_parsedURL = ParsedURL(relative); + m_urlImpl->m_parsedURL = ParsedURL(relative, &charsetConverter); else - m_urlImpl->m_parsedURL = ParsedURL(baseURL.m_urlImpl->m_parsedURL, relative); + m_urlImpl->m_parsedURL = ParsedURL(baseURL.m_urlImpl->m_parsedURL, relative, &charsetConverter); if (!m_urlImpl->m_parsedURL.isValid()) m_urlImpl->m_invalidUrlString = relative; } -KURL::KURL(const KURL&, const String&, const TextEncoding&) +KURL::KURL(const KURL& baseURL, const String& relative, const TextEncoding& encoding) + : m_urlImpl(adoptRef(new KURLWTFURLImpl())) { - // FIXME: Add WTFURL Implementation. + CharsetConverter charsetConverter(encoding.encodingForFormSubmission()); + if (baseURL.isEmpty()) + m_urlImpl->m_parsedURL = ParsedURL(relative, &charsetConverter); + else + m_urlImpl->m_parsedURL = ParsedURL(baseURL.m_urlImpl->m_parsedURL, relative, &charsetConverter); + + if (!m_urlImpl->m_parsedURL.isValid()) + m_urlImpl->m_invalidUrlString = relative; } KURL KURL::copy() const @@ -141,7 +171,10 @@ String KURL::host() const bool KURL::hasPort() const { - ASSERT(isValid()); + // This should be an ASSERT. HTMLAnchorElement::port() does not check the validity of the URL. + if (!isValid()) + return false; + return !m_urlImpl->m_parsedURL.port().isNull(); } @@ -164,25 +197,37 @@ unsigned short KURL::port() const String KURL::user() const { - ASSERT(isValid()); + // FIXME: this should be an ASSERT(), call site should not use invalid URLs. + if (!isValid()) + return String(); + return m_urlImpl->m_parsedURL.username(); } String KURL::pass() const { - ASSERT(isValid()); + // FIXME: this should be an ASSERT(), call site should not use invalid URLs. + if (!isValid()) + return String(); + return m_urlImpl->m_parsedURL.password(); } bool KURL::hasPath() const { - ASSERT(isValid()); + // FIXME: this should be an ASSERTION, call site should not use invalid URLs. + if (!isValid()) + return false; + return !path().isEmpty(); } String KURL::path() const { - ASSERT(isValid()); + // FIXME: this should be an ASSERTION, HTMLAnchorElement should not use invalid URLs. + if (!isValid()) + return String(); + return m_urlImpl->m_parsedURL.path(); } @@ -201,7 +246,10 @@ String KURL::lastPathComponent() const String KURL::query() const { - ASSERT(isValid()); + // FIXME: this should be an ASSERTION, HTMLAnchorElement should not use invalid URLs. + if (!isValid()) + return String(); + return m_urlImpl->m_parsedURL.query(); } @@ -221,6 +269,7 @@ String KURL::fragmentIdentifier() const // ASSERT(isValid()); if (!isValid()) return String(); + return m_urlImpl->m_parsedURL.fragment(); } @@ -234,7 +283,7 @@ String KURL::baseAsString() const // FIXME: Get rid of this function from KURL. String KURL::fileSystemPath() const { - return String(); + return string(); } bool KURL::protocolIs(const char* testProtocol) const diff --git a/Source/WebCore/platform/SharedBuffer.cpp b/Source/WebCore/platform/SharedBuffer.cpp index 68c3196a7..de5f71dc2 100644 --- a/Source/WebCore/platform/SharedBuffer.cpp +++ b/Source/WebCore/platform/SharedBuffer.cpp @@ -29,6 +29,7 @@ #include "PlatformMemoryInstrumentation.h" #include "PurgeableBuffer.h" +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/PassOwnPtr.h> #include <wtf/unicode/UTF8.h> #include <wtf/unicode/Unicode.h> @@ -251,8 +252,8 @@ const Vector<char>& SharedBuffer::buffer() const void SharedBuffer::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { MemoryClassInfo info(memoryObjectInfo, this); - info.addVector(m_buffer); - info.addVector(m_segments); + info.addMember(m_buffer); + info.addMember(m_segments); for (unsigned i = 0; i < m_segments.size(); ++i) info.addRawBuffer(m_segments[i], segmentSize); info.addMember(m_purgeableBuffer.get()); diff --git a/Source/WebCore/platform/blackberry/AuthenticationChallengeManager.cpp b/Source/WebCore/platform/blackberry/AuthenticationChallengeManager.cpp deleted file mode 100644 index e40a42b7e..000000000 --- a/Source/WebCore/platform/blackberry/AuthenticationChallengeManager.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (C) 2012 Research In Motion Limited. All rights reserved. - * - * 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 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 - */ - -#include "config.h" -#include "AuthenticationChallengeManager.h" - -#include "Credential.h" -#include "KURL.h" -#include "PageClientBlackBerry.h" -#include "ProtectionSpace.h" - -#include <BlackBerryPlatformAssert.h> -#include <BlackBerryPlatformLog.h> -#include <wtf/Assertions.h> -#include <wtf/HashMap.h> -#include <wtf/Vector.h> -#include <wtf/text/CString.h> - -namespace WebCore { - -typedef HashMap<PageClientBlackBerry*, bool> PageVisibilityMap; - -struct ChallengeInfo { - ChallengeInfo(const KURL&, const ProtectionSpace&, const Credential&, AuthenticationChallengeClient*, PageClientBlackBerry*); - - KURL url; - ProtectionSpace space; - Credential credential; - AuthenticationChallengeClient* authClient; - PageClientBlackBerry* pageClient; - bool blocked; -}; - -ChallengeInfo::ChallengeInfo(const KURL& aUrl, - const ProtectionSpace& aSpace, - const Credential& aCredential, - AuthenticationChallengeClient* anAuthClient, - PageClientBlackBerry* aPageClient) - : url(aUrl) - , space(aSpace) - , credential(aCredential) - , authClient(anAuthClient) - , pageClient(aPageClient) - , blocked(false) -{ -} - -class AuthenticationChallengeManagerPrivate { -public: - AuthenticationChallengeManagerPrivate(); - - bool resumeAuthenticationChallenge(PageClientBlackBerry*); - void startAuthenticationChallenge(ChallengeInfo*); - bool pageExists(PageClientBlackBerry*); - - ChallengeInfo* m_activeChallenge; - PageVisibilityMap m_pageVisibilityMap; - Vector<OwnPtr<ChallengeInfo> > m_challenges; -}; - -AuthenticationChallengeManagerPrivate::AuthenticationChallengeManagerPrivate() - : m_activeChallenge(0) -{ -} - -bool AuthenticationChallengeManagerPrivate::resumeAuthenticationChallenge(PageClientBlackBerry* client) -{ - ASSERT(!m_activeChallenge); - - for (size_t i = 0; i < m_challenges.size(); ++i) { - if (m_challenges[i]->pageClient == client && m_challenges[i]->blocked) { - startAuthenticationChallenge(m_challenges[i].get()); - return true; - } - } - - return false; -} - -void AuthenticationChallengeManagerPrivate::startAuthenticationChallenge(ChallengeInfo* info) -{ - m_activeChallenge = info; - m_activeChallenge->blocked = false; - m_activeChallenge->pageClient->authenticationChallenge(m_activeChallenge->url, - m_activeChallenge->space, - m_activeChallenge->credential); -} - -bool AuthenticationChallengeManagerPrivate::pageExists(PageClientBlackBerry* client) -{ - return m_pageVisibilityMap.find(client) != m_pageVisibilityMap.end(); -} - -AuthenticationChallengeManager::AuthenticationChallengeManager() - : d(adoptPtr(new AuthenticationChallengeManagerPrivate)) -{ -} - -void AuthenticationChallengeManager::pageCreated(PageClientBlackBerry* client) -{ - d->m_pageVisibilityMap.add(client, true); -} - -void AuthenticationChallengeManager::pageDeleted(PageClientBlackBerry* client) -{ - d->m_pageVisibilityMap.remove(client); - - if (d->m_activeChallenge && d->m_activeChallenge->pageClient == client) - d->m_activeChallenge = 0; - - Vector<OwnPtr<ChallengeInfo> > existing; - d->m_challenges.swap(existing); - - for (size_t i = 0; i < existing.size(); ++i) { - if (existing[i]->pageClient != client) - d->m_challenges.append(existing[i].release()); - } -} - -void AuthenticationChallengeManager::pageVisibilityChanged(PageClientBlackBerry* client, bool visible) -{ - PageVisibilityMap::iterator iter = d->m_pageVisibilityMap.find(client); - - ASSERT(iter != d->m_pageVisibilityMap.end()); - if (iter == d->m_pageVisibilityMap.end()) { - d->m_pageVisibilityMap.add(client, visible); - return; - } - - if (iter->second == visible) - return; - - iter->second = visible; - if (!visible) - return; - - if (d->m_activeChallenge) - return; - - d->resumeAuthenticationChallenge(client); -} - -void AuthenticationChallengeManager::authenticationChallenge(const KURL& url, - const ProtectionSpace& space, - const Credential& credential, - AuthenticationChallengeClient* authClient, - PageClientBlackBerry* pageClient) -{ - BLACKBERRY_ASSERT(authClient); - BLACKBERRY_ASSERT(pageClient); - - ChallengeInfo* info = new ChallengeInfo(url, space, credential, authClient, pageClient); - d->m_challenges.append(adoptPtr(info)); - - if (d->m_activeChallenge || !pageClient->isVisible()) { - info->blocked = true; - return; - } - - d->startAuthenticationChallenge(info); -} - -void AuthenticationChallengeManager::cancelAuthenticationChallenge(AuthenticationChallengeClient* client) -{ - BLACKBERRY_ASSERT(client); - - if (d->m_activeChallenge && d->m_activeChallenge->authClient == client) - d->m_activeChallenge = 0; - - Vector<OwnPtr<ChallengeInfo> > existing; - d->m_challenges.swap(existing); - - ChallengeInfo* next = 0; - PageClientBlackBerry* page = 0; - - for (size_t i = 0; i < existing.size(); ++i) { - if (existing[i]->authClient != client) { - if (page && !next && existing[i]->pageClient == page) - next = existing[i].get(); - d->m_challenges.append(existing[i].release()); - } else if (d->m_activeChallenge == existing[i].get()) - page = existing[i]->pageClient; - } - - if (next) - d->startAuthenticationChallenge(next); -} - -void AuthenticationChallengeManager::notifyChallengeResult(const KURL& url, - const ProtectionSpace& space, - AuthenticationChallengeResult result, - const Credential& credential) -{ - d->m_activeChallenge = 0; - - Vector<OwnPtr<ChallengeInfo> > existing; - d->m_challenges.swap(existing); - - ChallengeInfo* next = 0; - PageClientBlackBerry* page = 0; - - for (size_t i = 0; i < existing.size(); ++i) { - if (existing[i]->space != space) { - if (page && !next && existing[i]->pageClient == page) - next = existing[i].get(); - d->m_challenges.append(existing[i].release()); - } else { - page = existing[i]->pageClient; - existing[i]->authClient->notifyChallengeResult(existing[i]->url, space, result, credential); - - // After calling notifyChallengeResult(), page could be destroyed or something. - if (!d->pageExists(page) || !page->isVisible()) - page = 0; - } - } - - if (next) - d->startAuthenticationChallenge(next); -} - -// Keep following code at the end of this file!!! -static AuthenticationChallengeManager* s_manager = 0; - -AuthenticationChallengeManager* AuthenticationChallengeManager::instance() -{ - ASSERT(s_manager); - return s_manager; -} - -void AuthenticationChallengeManager::init() -{ - ASSERT(!s_manager); - s_manager = new AuthenticationChallengeManager(); -} - -// No more code after this line, all new code should come before s_manager declaration!!! - -} // namespace WebCore diff --git a/Source/WebCore/platform/blackberry/AuthenticationChallengeManager.h b/Source/WebCore/platform/blackberry/AuthenticationChallengeManager.h index 20e799bb3..52224f511 100644 --- a/Source/WebCore/platform/blackberry/AuthenticationChallengeManager.h +++ b/Source/WebCore/platform/blackberry/AuthenticationChallengeManager.h @@ -19,13 +19,8 @@ #ifndef AuthenticationChallengeManager_h #define AuthenticationChallengeManager_h -#include <wtf/OwnPtr.h> - -class PageClientBlackBerry; - namespace WebCore { -class AuthenticationChallengeManagerPrivate; class Credential; class KURL; class ProtectionSpace; @@ -40,36 +35,6 @@ public: virtual void notifyChallengeResult(const KURL&, const ProtectionSpace&, AuthenticationChallengeResult, const Credential&) = 0; }; -class AuthenticationChallengeManager { -public: - static void init(); - static AuthenticationChallengeManager* instance(); - - void pageCreated(PageClientBlackBerry*); - void pageDeleted(PageClientBlackBerry*); - void pageVisibilityChanged(PageClientBlackBerry*, bool visible); - - void authenticationChallenge(const KURL&, - const ProtectionSpace&, - const Credential&, - AuthenticationChallengeClient*, - PageClientBlackBerry*); - - void cancelAuthenticationChallenge(AuthenticationChallengeClient*); - - void notifyChallengeResult(const KURL&, - const ProtectionSpace&, - AuthenticationChallengeResult, - const Credential&); - -private: - AuthenticationChallengeManager(); - ~AuthenticationChallengeManager(); - - OwnPtr<AuthenticationChallengeManagerPrivate> d; -}; - - } // namespace WebCore #endif // AuthenticationChallengeManager_h diff --git a/Source/WebCore/platform/blackberry/CookieManager.cpp b/Source/WebCore/platform/blackberry/CookieManager.cpp index 091d7531e..db012bfb4 100644 --- a/Source/WebCore/platform/blackberry/CookieManager.cpp +++ b/Source/WebCore/platform/blackberry/CookieManager.cpp @@ -137,6 +137,17 @@ void CookieManager::setCookies(const KURL& url, const String& value, CookieFilte } } +void CookieManager::setCookies(const KURL& url, const Vector<String>& cookies, CookieFilter filter) +{ + CookieLog("CookieManager - Setting cookies"); + CookieParser parser(url); + for (size_t i = 0; i < cookies.size(); ++i) { + BackingStoreRemovalPolicy treatment = m_privateMode ? DoNotRemoveFromBackingStore : RemoveFromBackingStore; + if (ParsedCookie* parsedCookie = parser.parseOneCookie(cookies[i])) + checkAndTreatCookie(parsedCookie, treatment, filter); + } +} + String CookieManager::getCookie(const KURL& url, CookieFilter filter) const { Vector<ParsedCookie*> rawCookies; diff --git a/Source/WebCore/platform/blackberry/CookieManager.h b/Source/WebCore/platform/blackberry/CookieManager.h index acb2fcd7a..d334e67fd 100644 --- a/Source/WebCore/platform/blackberry/CookieManager.h +++ b/Source/WebCore/platform/blackberry/CookieManager.h @@ -71,6 +71,7 @@ public: void setCanLocalAccessAllCookies(bool enabled) { m_shouldDumpAllCookies = enabled; } void setCookies(const KURL&, const String& value, CookieFilter = WithHttpOnlyCookies); + void setCookies(const KURL&, const Vector<String>& cookies, CookieFilter); void removeAllCookies(BackingStoreRemovalPolicy); void removeCookieWithName(const KURL&, const String& cookieName); diff --git a/Source/WebCore/platform/blackberry/CookieParser.cpp b/Source/WebCore/platform/blackberry/CookieParser.cpp index ff6b871b8..dc3580f2b 100644 --- a/Source/WebCore/platform/blackberry/CookieParser.cpp +++ b/Source/WebCore/platform/blackberry/CookieParser.cpp @@ -103,6 +103,11 @@ Vector<ParsedCookie*> CookieParser::parse(const String& cookies) return parsedCookies; } +ParsedCookie* CookieParser::parseOneCookie(const String& cookie) +{ + return parseOneCookie(cookie, 0, cookie.length() - 1, currentTime()); +} + // The cookie String passed into this method will only contian the name value pairs as well as other related cookie // attributes such as max-age and domain. Set-Cookie should never be part of this string. ParsedCookie* CookieParser::parseOneCookie(const String& cookie, unsigned start, unsigned end, double curTime) diff --git a/Source/WebCore/platform/blackberry/CookieParser.h b/Source/WebCore/platform/blackberry/CookieParser.h index 00fafcfef..aed5e87eb 100644 --- a/Source/WebCore/platform/blackberry/CookieParser.h +++ b/Source/WebCore/platform/blackberry/CookieParser.h @@ -45,6 +45,8 @@ public: // Parses a sequence of "Cookie:" header and return the parsed cookies. Vector<ParsedCookie*> parse(const String& cookies); + ParsedCookie* parseOneCookie(const String& cookie); + private: // FIXME: curTime, start, end parameters should be removed. And this method can be public. ParsedCookie* parseOneCookie(const String& cookie, unsigned start, unsigned end, double curTime); diff --git a/Source/WebCore/platform/blackberry/PageClientBlackBerry.h b/Source/WebCore/platform/blackberry/PageClientBlackBerry.h index f2c7c0e65..bdb2f1607 100644 --- a/Source/WebCore/platform/blackberry/PageClientBlackBerry.h +++ b/Source/WebCore/platform/blackberry/PageClientBlackBerry.h @@ -72,7 +72,7 @@ public: virtual int showAlertDialog(BlackBerry::WebKit::WebPageClient::AlertType) = 0; virtual bool isActive() const = 0; virtual bool isVisible() const = 0; - virtual void authenticationChallenge(const WebCore::KURL&, const WebCore::ProtectionSpace&, const WebCore::Credential&) = 0; + virtual void authenticationChallenge(const WebCore::KURL&, const WebCore::ProtectionSpace&, const WebCore::Credential&, WebCore::AuthenticationChallengeClient*) = 0; virtual SaveCredentialType notifyShouldSaveCredential(bool) = 0; virtual void syncProxyCredential(const WebCore::Credential&) = 0; }; diff --git a/Source/WebCore/platform/cairo/WidgetBackingStoreCairo.cpp b/Source/WebCore/platform/cairo/WidgetBackingStoreCairo.cpp index 1dec7c2e7..69b79efca 100644 --- a/Source/WebCore/platform/cairo/WidgetBackingStoreCairo.cpp +++ b/Source/WebCore/platform/cairo/WidgetBackingStoreCairo.cpp @@ -22,7 +22,7 @@ #include "CairoUtilities.h" #include "RefPtrCairo.h" -#include <cairo/cairo.h> +#include <cairo.h> #if PLATFORM(GTK) #include "GtkVersioning.h" diff --git a/Source/WebCore/platform/chromium/PlatformSupport.h b/Source/WebCore/platform/chromium/PlatformSupport.h index eb1970b8a..7af75b8ef 100644 --- a/Source/WebCore/platform/chromium/PlatformSupport.h +++ b/Source/WebCore/platform/chromium/PlatformSupport.h @@ -49,15 +49,6 @@ typedef struct NPObject NPObject; typedef struct _NPP NPP_t; typedef NPP_t* NPP; -#if OS(DARWIN) -typedef struct CGFont* CGFontRef; -#ifdef __OBJC__ -@class NSFont; -#else -class NSFont; -#endif -#endif // OS(DARWIN) - #if OS(WINDOWS) typedef struct HFONT__* HFONT; #endif @@ -99,9 +90,6 @@ public: #if OS(WINDOWS) static bool ensureFontLoaded(HFONT); #endif -#if OS(DARWIN) - static bool loadFont(NSFont* srcFont, CGFontRef*, uint32_t* fontID); -#endif // IndexedDB ---------------------------------------------------------- static PassRefPtr<IDBFactoryBackendInterface> idbFactory(); diff --git a/Source/WebCore/platform/chromium/ScrollbarThemeChromiumAndroid.cpp b/Source/WebCore/platform/chromium/ScrollbarThemeChromiumAndroid.cpp index 1b9e571b1..6f555fbd1 100644 --- a/Source/WebCore/platform/chromium/ScrollbarThemeChromiumAndroid.cpp +++ b/Source/WebCore/platform/chromium/ScrollbarThemeChromiumAndroid.cpp @@ -26,7 +26,6 @@ #include "config.h" #include "ScrollbarThemeChromiumAndroid.h" -#include "LayoutTestSupport.h" #include "PlatformContextSkia.h" #include "PlatformMouseEvent.h" #include "PlatformSupport.h" @@ -50,21 +49,12 @@ ScrollbarTheme* ScrollbarTheme::nativeTheme() int ScrollbarThemeChromiumAndroid::scrollbarThickness(ScrollbarControlSize controlSize) { - if (isRunningLayoutTest()) { - // Match Chromium-Linux for DumpRenderTree, so the layout test results - // can be shared. The width of scrollbar down arrow should equal the - // width of the vertical scrollbar. - IntSize scrollbarSize = PlatformSupport::getThemePartSize(PlatformSupport::PartScrollbarDownArrow); - return scrollbarSize.width(); - } - return scrollbarWidth + scrollbarMargin; } bool ScrollbarThemeChromiumAndroid::usesOverlayScrollbars() const { - // In layout test mode, match Chromium-Linux. - return !isRunningLayoutTest(); + return true; } int ScrollbarThemeChromiumAndroid::thumbPosition(ScrollbarThemeClient* scrollbar) @@ -92,8 +82,7 @@ int ScrollbarThemeChromiumAndroid::thumbLength(ScrollbarThemeClient* scrollbar) bool ScrollbarThemeChromiumAndroid::hasThumb(ScrollbarThemeClient* scrollbar) { - // In layout test mode, match Chromium-Linux. - return !isRunningLayoutTest(); + return true; } IntRect ScrollbarThemeChromiumAndroid::backButtonRect(ScrollbarThemeClient*, ScrollbarPart, bool) @@ -157,12 +146,4 @@ void ScrollbarThemeChromiumAndroid::paintThumb(GraphicsContext* context, Scrollb fillSmoothEdgedRect(context, thumbRect, Color(128, 128, 128, 128)); } -void ScrollbarThemeChromiumAndroid::paintScrollbarBackground(GraphicsContext* context, ScrollbarThemeClient* scrollbar) -{ - // Paint black background in DumpRenderTree, otherwise the pixels in the scrollbar area depend - // on their previous state, which makes the dumped result undetermined. - if (isRunningLayoutTest()) - context->fillRect(scrollbar->frameRect(), Color::black, ColorSpaceDeviceRGB); -} - } // namespace WebCore diff --git a/Source/WebCore/platform/chromium/ScrollbarThemeChromiumAndroid.h b/Source/WebCore/platform/chromium/ScrollbarThemeChromiumAndroid.h index eab501029..84d647dde 100644 --- a/Source/WebCore/platform/chromium/ScrollbarThemeChromiumAndroid.h +++ b/Source/WebCore/platform/chromium/ScrollbarThemeChromiumAndroid.h @@ -46,7 +46,6 @@ public: virtual IntRect trackRect(ScrollbarThemeClient*, bool painting = false); virtual void paintThumb(GraphicsContext*, ScrollbarThemeClient*, const IntRect&); - virtual void paintScrollbarBackground(GraphicsContext*, ScrollbarThemeClient*); }; } // namespace WebCore diff --git a/Source/WebCore/platform/clutter/GRefPtrClutter.cpp b/Source/WebCore/platform/clutter/GRefPtrClutter.cpp deleted file mode 100644 index 2a34186c2..000000000 --- a/Source/WebCore/platform/clutter/GRefPtrClutter.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2011 Collabora Ltd. - * - * 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 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 - */ - - -#include "config.h" -#include "GRefPtrClutter.h" - -#include <clutter/clutter.h> - -namespace WTF { - -template <> GRefPtr<ClutterActor> adoptGRef(ClutterActor* ptr) -{ - if (g_object_is_floating(ptr)) - g_object_ref_sink(ptr); - - return GRefPtr<ClutterActor>(ptr, GRefPtrAdopt); -} - -template <> ClutterActor* refGPtr<ClutterActor>(ClutterActor* ptr) -{ - if (ptr) { - if (g_object_is_floating(ptr)) - g_object_ref_sink(ptr); - - g_object_ref(ptr); - } - - return ptr; -} - -template <> void derefGPtr<ClutterActor>(ClutterActor* ptr) -{ - if (ptr) - g_object_unref(ptr); -} - -} diff --git a/Source/WebCore/platform/clutter/GRefPtrClutter.h b/Source/WebCore/platform/clutter/GRefPtrClutter.h deleted file mode 100644 index bdec65481..000000000 --- a/Source/WebCore/platform/clutter/GRefPtrClutter.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2011 Collabora Ltd. - * - * 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 GRefPtrClutter_h -#define GRefPtrClutter_h - -#include <wtf/gobject/GRefPtr.h> - -typedef struct _ClutterActor ClutterActor; - -namespace WTF { - -template<> ClutterActor* refGPtr<ClutterActor>(ClutterActor* ptr); -template<> void derefGPtr<ClutterActor>(ClutterActor* ptr); - -} - -#endif diff --git a/Source/WebCore/platform/graphics/BitmapImage.cpp b/Source/WebCore/platform/graphics/BitmapImage.cpp index 0b1168078..d0a2aabd1 100644 --- a/Source/WebCore/platform/graphics/BitmapImage.cpp +++ b/Source/WebCore/platform/graphics/BitmapImage.cpp @@ -34,6 +34,7 @@ #include "PlatformMemoryInstrumentation.h" #include "Timer.h" #include <wtf/CurrentTime.h> +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/Vector.h> #include <wtf/text/WTFString.h> @@ -578,7 +579,7 @@ void BitmapImage::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const Image::reportMemoryUsage(memoryObjectInfo); info.addMember(m_source); info.addMember(m_frameTimer); - info.addVector(m_frames); + info.addMember(m_frames); for (unsigned i = 0; i < m_frameCount; ++i) { #if OS(WINCE) && !PLATFORM(QT) info.addRawBuffer(m_frames[i].m_frame.get(), m_frames[i].m_frameBytes); diff --git a/Source/WebCore/platform/graphics/BitmapImage.h b/Source/WebCore/platform/graphics/BitmapImage.h index 10b372948..3f23dcedf 100644 --- a/Source/WebCore/platform/graphics/BitmapImage.h +++ b/Source/WebCore/platform/graphics/BitmapImage.h @@ -87,7 +87,6 @@ public: // Clear the cached image data on the frame, and (optionally) the metadata. // Returns whether there was cached image data to clear. bool clear(bool clearMetadata); - void reportMemoryUsage(MemoryObjectInfo*) const; NativeImagePtr m_frame; ImageOrientation m_orientation; diff --git a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp index d696ad199..867d8158c 100644 --- a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp +++ b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp @@ -21,7 +21,6 @@ #if ENABLE(VIDEO) #include "MediaPlayerPrivateBlackBerry.h" -#include "AuthenticationChallengeManager.h" #include "CookieManager.h" #include "Credential.h" #include "CredentialStorage.h" @@ -115,7 +114,6 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) , m_userDrivenSeekTimer(this, &MediaPlayerPrivate::userDrivenSeekTimerFired) , m_lastSeekTime(0) , m_lastSeekTimePending(false) - , m_isAuthenticationChallenging(false) , m_waitMetadataTimer(this, &MediaPlayerPrivate::waitMetadataTimerFired) , m_waitMetadataPopDialogCounter(0) { @@ -123,9 +121,6 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) MediaPlayerPrivate::~MediaPlayerPrivate() { - if (m_isAuthenticationChallenging) - AuthenticationChallengeManager::instance()->cancelAuthenticationChallenge(this); - if (isFullscreen()) { m_webCorePlayer->mediaPlayerClient()->mediaPlayerExitFullscreen(); } @@ -352,13 +347,16 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect) return; #if USE(ACCELERATED_COMPOSITING) - // Only process paint calls coming via the accelerated compositing code - // path, where we get called with a null graphics context. See - // LayerCompositingThread::drawTextures(). Ignore calls from the regular - // rendering path. - if (!context) - m_platformPlayer->notifyOutputUpdate(BlackBerry::Platform::IntRect(rect.x(), rect.y(), rect.width(), rect.height())); - return; + if (supportsAcceleratedRendering()) { + // Only process paint calls coming via the accelerated compositing code + // path, where we get called with a null graphics context. See + // LayerCompositingThread::drawTextures(). Ignore calls from the regular + // rendering path. + if (!context) + m_platformPlayer->notifyOutputUpdate(BlackBerry::Platform::IntRect(rect.x(), rect.y(), rect.width(), rect.height())); + + return; + } #endif paintCurrentFrameInContext(context, rect); @@ -545,7 +543,7 @@ void MediaPlayerPrivate::updateStates() m_showBufferingImage = false; m_mediaIsBuffering = false; // Create platform layer for video (create hole punch rect). - if (!m_platformLayer) + if (!m_platformLayer && supportsAcceleratedRendering()) m_platformLayer = VideoLayerWebKitThread::create(m_webCorePlayer); #endif break; @@ -715,18 +713,12 @@ void MediaPlayerPrivate::onAuthenticationNeeded(MMRAuthChallenge& authChallenge) return; } - m_isAuthenticationChallenging = true; - AuthenticationChallengeManager::instance()->authenticationChallenge(url, - protectionSpace, - credential, - this, - m_webCorePlayer->mediaPlayerClient()->mediaPlayerHostWindow()->platformPageClient()); + if (frameView() && frameView()->hostWindow()) + frameView()->hostWindow()->platformPageClient()->authenticationChallenge(url, protectionSpace, credential, this); } void MediaPlayerPrivate::notifyChallengeResult(const KURL& url, const ProtectionSpace& protectionSpace, AuthenticationChallengeResult result, const Credential& credential) { - m_isAuthenticationChallenging = false; - if (result != AuthenticationChallengeSuccess || !url.isValid()) return; @@ -831,6 +823,13 @@ bool MediaPlayerPrivate::isTabVisible() const return m_webCorePlayer->mediaPlayerClient()->mediaPlayerHostWindow()->platformPageClient()->isVisible(); } +bool MediaPlayerPrivate::supportsAcceleratedRendering() const +{ + if (m_platformPlayer) + return m_platformPlayer->supportsAcceleratedRendering(); + return false; +} + #if USE(ACCELERATED_COMPOSITING) static const double BufferingAnimationDelay = 1.0 / 24; static char* s_bufferingImageData = 0; diff --git a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h index 5a083b59e..2629e04f6 100644 --- a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h +++ b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h @@ -96,7 +96,7 @@ public: #if USE(ACCELERATED_COMPOSITING) // Whether accelerated rendering is supported by the media engine for the current media. - virtual bool supportsAcceleratedRendering() const { return true; } + virtual bool supportsAcceleratedRendering() const; // Called when the rendering system flips the into or out of accelerated rendering mode. virtual void acceleratedRenderingStateChanged() { } #endif @@ -174,7 +174,6 @@ private: Timer<MediaPlayerPrivate> m_userDrivenSeekTimer; float m_lastSeekTime; bool m_lastSeekTimePending; - bool m_isAuthenticationChallenging; void waitMetadataTimerFired(Timer<MediaPlayerPrivate>*); Timer<MediaPlayerPrivate> m_waitMetadataTimer; int m_waitMetadataPopDialogCounter; diff --git a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm index c0f10dc6b..a10956366 100644 --- a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm +++ b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm @@ -30,8 +30,10 @@ #import "CrossProcessFontLoading.h" #import "../graphics/FontPlatformData.h" -#import "PlatformSupport.h" +#include "LinkHash.h" #import <AppKit/NSFont.h> +#import <public/Platform.h> +#import <public/mac/WebSandboxSupport.h> #import <wtf/HashMap.h> namespace WebCore { @@ -121,7 +123,15 @@ PassRefPtr<MemoryActivatedFont> loadFontFromBrowserProcess(NSFont* nsFont) CGFontRef tmpCGFont; uint32_t fontID; // Send cross-process request to load font. - if (!PlatformSupport::loadFont(nsFont, &tmpCGFont, &fontID)) + WebKit::WebSandboxSupport* sandboxSupport = WebKit::Platform::current()->sandboxSupport(); + if (!sandboxSupport) { + // This function should only be called in response to an error loading a + // font due to being blocked by the sandbox. + // This by definition shouldn't happen if there is no sandbox support. + ASSERT_NOT_REACHED(); + return 0; + } + if (!sandboxSupport->loadFont(nsFont, &tmpCGFont, &fontID)) return 0; RetainPtr<CGFontRef> cgFont(tmpCGFont); @@ -129,7 +139,7 @@ PassRefPtr<MemoryActivatedFont> loadFontFromBrowserProcess(NSFont* nsFont) // the ID cache. font = fontCacheByFontID().get(fontID); if (font) - // FIXME: PlatformSupport::loadFont() should consult the id cache + // FIXME: WebSandboxSupport::loadFont() should consult the id cache // before activating the font. return font; diff --git a/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.h b/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.h index 42f6b76f9..3e142e487 100644 --- a/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.h +++ b/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.h @@ -29,10 +29,10 @@ #if USE(ACCELERATED_COMPOSITING) -#include "GRefPtrClutter.h" #include "GraphicsLayer.h" #include <clutter/clutter.h> +#include <wtf/gobject/GRefPtr.h> namespace WebCore { diff --git a/Source/WebCore/platform/graphics/clutter/PlatformClutterLayerClient.h b/Source/WebCore/platform/graphics/clutter/PlatformClutterLayerClient.h new file mode 100644 index 000000000..90b56ab6a --- /dev/null +++ b/Source/WebCore/platform/graphics/clutter/PlatformClutterLayerClient.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2011 Collabora Ltd. + * + * 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 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 PlatformClutterLayerClient_h +#define PlatformClutterLayerClient_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "GraphicsContext.h" +#include "GraphicsLayer.h" + +namespace WebCore { + +class PlatformClutterLayerClient { +public: + virtual void platformClutterLayerPaintContents(GraphicsContext&, const IntRect& inClip) = 0; + virtual void platformClutterLayerAnimationStarted(double startTime) = 0; + +protected: + virtual ~PlatformClutterLayerClient() { } +}; + +} + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // PlatformClutterLayerClient_h + diff --git a/Source/WebCore/platform/graphics/clutter/TransformationMatrixClutter.cpp b/Source/WebCore/platform/graphics/clutter/TransformationMatrixClutter.cpp new file mode 100644 index 000000000..d5c3f2ae4 --- /dev/null +++ b/Source/WebCore/platform/graphics/clutter/TransformationMatrixClutter.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2011 Collabora Ltd. + * + * 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 + */ + +#include "config.h" +#include "TransformationMatrix.h" + +#include <cogl/cogl.h> + +namespace WebCore { + +TransformationMatrix::operator CoglMatrix() const +{ + CoglMatrix matrix; + + matrix.xx = m11(); + matrix.xy = m21(); + matrix.xz = m31(); + matrix.xw = m41(); + + matrix.yx = m12(); + matrix.yy = m22(); + matrix.yz = m32(); + matrix.yw = m42(); + + matrix.zx = m13(); + matrix.zy = m23(); + matrix.zz = m33(); + matrix.zw = m43(); + + matrix.wx = m14(); + matrix.wy = m24(); + matrix.wz = m34(); + matrix.ww = m44(); + + return matrix; +} + +} diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp index edc74fbb5..3553a9780 100644 --- a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp +++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp @@ -575,14 +575,8 @@ void ComplexTextController::adjustGlyphsAndAdvances() nextCh = *(m_complexTextRuns[r + 1]->characters() + m_complexTextRuns[r + 1]->indexAt(0)); bool treatAsSpace = Font::treatAsSpace(ch); - CGGlyph glyph = glyphs[i]; - CGSize advance = advances[i]; - // FIXME: We should find a way to substitute spaces for characters that are treated as spaces - // before handing them off to Core Text, so that kerning can be applied as if they were spaces. - if (treatAsSpace && ch != ' ') { - glyph = fontData->spaceGlyph(); - advance.width = spaceWidth; - } + CGGlyph glyph = treatAsSpace ? fontData->spaceGlyph() : glyphs[i]; + CGSize advance = treatAsSpace ? CGSizeMake(spaceWidth, advances[i].height) : advances[i]; if (ch == '\t' && m_run.allowTabs()) advance.width = m_font.tabWidth(*fontData, m_run.tabSize(), m_run.xPos() + m_totalWidth + widthSinceLastCommit); diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp index a3c056591..60f6bfaf3 100644 --- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp @@ -125,7 +125,7 @@ String Extensions3DOpenGLCommon::getTranslatedShaderSourceANGLE(Platform3DObject #if PLATFORM(MAC) const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR)); - if (vendor && (std::strstr(vendor, "ATI") || std::strstr(vendor, "AMD"))) + if (vendor && (std::strstr(vendor, "ATI") || std::strstr(vendor, "AMD") || std::strstr(vendor, "Intel"))) extraCompileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS; #endif diff --git a/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h b/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h index cd1db5e03..9eda74608 100644 --- a/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h +++ b/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h @@ -34,6 +34,9 @@ #if USE(CA) typedef struct CATransform3D CATransform3D; #endif +#if USE(CLUTTER) +typedef struct _CoglMatrix CoglMatrix; +#endif #if USE(CG) typedef struct CGAffineTransform CGAffineTransform; #elif USE(CAIRO) @@ -324,6 +327,9 @@ public: TransformationMatrix(const CATransform3D&); operator CATransform3D() const; #endif +#if USE(CLUTTER) + operator CoglMatrix() const; +#endif #if USE(CG) TransformationMatrix(const CGAffineTransform&); operator CGAffineTransform() const; diff --git a/Source/WebCore/platform/gtk/GtkInputMethodFilter.cpp b/Source/WebCore/platform/gtk/GtkInputMethodFilter.cpp index da0ec7fa0..8696ef37a 100644 --- a/Source/WebCore/platform/gtk/GtkInputMethodFilter.cpp +++ b/Source/WebCore/platform/gtk/GtkInputMethodFilter.cpp @@ -292,7 +292,7 @@ void GtkInputMethodFilter::handleCommit(const char* compositionString) if (!m_enabled) return; - m_confirmedComposition += String::fromUTF8(compositionString); + m_confirmedComposition.append(String::fromUTF8(compositionString)); // If the commit was triggered outside of a key event, just send // the IME event now. If we are handling a key event, we'll decide diff --git a/Source/WebCore/platform/gtk/GtkWidgetBackingStoreX11.cpp b/Source/WebCore/platform/gtk/GtkWidgetBackingStoreX11.cpp index afead805b..60376bc77 100644 --- a/Source/WebCore/platform/gtk/GtkWidgetBackingStoreX11.cpp +++ b/Source/WebCore/platform/gtk/GtkWidgetBackingStoreX11.cpp @@ -22,8 +22,8 @@ #include "GtkVersioning.h" #include "RefPtrCairo.h" #include <X11/Xlib.h> -#include <cairo/cairo-xlib.h> -#include <cairo/cairo.h> +#include <cairo-xlib.h> +#include <cairo.h> #include <gdk/gdkx.h> namespace WebCore { diff --git a/Source/WebCore/platform/mac/KURLMac.mm b/Source/WebCore/platform/mac/KURLMac.mm index 9efbee0d8..d5c25e147 100644 --- a/Source/WebCore/platform/mac/KURLMac.mm +++ b/Source/WebCore/platform/mac/KURLMac.mm @@ -53,7 +53,7 @@ KURL::KURL(NSURL *url) #else m_urlImpl = adoptRef(new KURLWTFURLImpl()); String urlString(bytes, bytesLength); - m_urlImpl->m_parsedURL = ParsedURL(urlString); + m_urlImpl->m_parsedURL = ParsedURL(urlString, 0); if (!m_urlImpl->m_parsedURL.isValid()) m_urlImpl->m_invalidUrlString = urlString; #endif // USE(WTFURL) diff --git a/Source/WebCore/platform/mock/GeolocationClientMock.cpp b/Source/WebCore/platform/mock/GeolocationClientMock.cpp index 276b4a343..9901b66aa 100644 --- a/Source/WebCore/platform/mock/GeolocationClientMock.cpp +++ b/Source/WebCore/platform/mock/GeolocationClientMock.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2012 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 @@ -41,6 +42,7 @@ namespace WebCore { GeolocationClientMock::GeolocationClientMock() : m_controller(0) + , m_hasError(false) , m_controllerTimer(this, &GeolocationClientMock::controllerTimerFired) , m_permissionTimer(this, &GeolocationClientMock::permissionTimerFired) , m_isActive(false) @@ -62,14 +64,15 @@ void GeolocationClientMock::setController(GeolocationController *controller) void GeolocationClientMock::setPosition(PassRefPtr<GeolocationPosition> position) { m_lastPosition = position; - m_lastError = 0; + clearError(); asyncUpdateController(); } -void GeolocationClientMock::setError(PassRefPtr<GeolocationError> error) +void GeolocationClientMock::setPositionUnavailableError(const String& errorMessage) { - m_lastError = error; - m_lastPosition = 0; + m_hasError = true; + m_errorMessage = errorMessage; + m_lastPosition = nullptr; asyncUpdateController(); } @@ -125,7 +128,7 @@ void GeolocationClientMock::permissionTimerFired(WebCore::Timer<GeolocationClien void GeolocationClientMock::reset() { m_lastPosition = 0; - m_lastError = 0; + clearError(); m_permissionState = PermissionStateUnset; } @@ -171,10 +174,19 @@ void GeolocationClientMock::controllerTimerFired(Timer<GeolocationClientMock>* t ASSERT_UNUSED(timer, timer == &m_controllerTimer); ASSERT(m_controller); - if (m_lastPosition.get()) + if (m_lastPosition.get()) { + ASSERT(!m_hasError); m_controller->positionChanged(m_lastPosition.get()); - else if (m_lastError.get()) - m_controller->errorOccurred(m_lastError.get()); + } else if (m_hasError) { + RefPtr<GeolocationError> geolocatioError = GeolocationError::create(GeolocationError::PositionUnavailable, m_errorMessage); + m_controller->errorOccurred(geolocatioError.get()); + } +} + +void GeolocationClientMock::clearError() +{ + m_hasError = false; + m_errorMessage = String(); } } // WebCore diff --git a/Source/WebCore/platform/mock/GeolocationClientMock.h b/Source/WebCore/platform/mock/GeolocationClientMock.h index 8abd5e970..f380c1443 100644 --- a/Source/WebCore/platform/mock/GeolocationClientMock.h +++ b/Source/WebCore/platform/mock/GeolocationClientMock.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2012 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 @@ -42,9 +43,9 @@ namespace WebCore { class GeolocationController; class GeolocationPosition; -class GeolocationError; -// Provides a mock object for the geolocation client +// FIXME: this should not be in WebCore. It should be moved to WebKit. +// Provides a mock object for the geolocation client. class GeolocationClientMock : public GeolocationClient { public: GeolocationClientMock(); @@ -53,8 +54,8 @@ public: void reset(); void setController(GeolocationController*); - void setError(PassRefPtr<GeolocationError>); void setPosition(PassRefPtr<GeolocationPosition>); + void setPositionUnavailableError(const String& errorMessage); void setPermission(bool allowed); int numberOfPendingPermissionRequests() const; @@ -74,9 +75,12 @@ private: void asyncUpdatePermission(); void permissionTimerFired(Timer<GeolocationClientMock>*); + void clearError(); + GeolocationController* m_controller; RefPtr<GeolocationPosition> m_lastPosition; - RefPtr<GeolocationError> m_lastError; + bool m_hasError; + String m_errorMessage; Timer<GeolocationClientMock> m_controllerTimer; Timer<GeolocationClientMock> m_permissionTimer; bool m_isActive; diff --git a/Source/WebCore/platform/network/FormData.cpp b/Source/WebCore/platform/network/FormData.cpp index 45f730248..43a71af1a 100644 --- a/Source/WebCore/platform/network/FormData.cpp +++ b/Source/WebCore/platform/network/FormData.cpp @@ -37,6 +37,7 @@ #include "TextEncoding.h" #include <wtf/Decoder.h> #include <wtf/Encoder.h> +#include <wtf/MemoryInstrumentationVector.h> namespace WebCore { @@ -360,7 +361,7 @@ void FormData::removeGeneratedFilesIfNeeded() void FormData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Loader); - info.addVector(m_boundary); + info.addMember(m_boundary); } static void encode(Encoder& encoder, const FormDataElement& element) diff --git a/Source/WebCore/platform/network/ResourceRequestBase.cpp b/Source/WebCore/platform/network/ResourceRequestBase.cpp index 00f583905..303deaa9c 100644 --- a/Source/WebCore/platform/network/ResourceRequestBase.cpp +++ b/Source/WebCore/platform/network/ResourceRequestBase.cpp @@ -28,6 +28,7 @@ #include "PlatformMemoryInstrumentation.h" #include "ResourceRequest.h" +#include <wtf/MemoryInstrumentationVector.h> using namespace std; @@ -452,7 +453,7 @@ void ResourceRequestBase::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) info.addMember(m_httpMethod); info.addHashMap(m_httpHeaderFields); info.addInstrumentedMapEntries(m_httpHeaderFields); - info.addInstrumentedVector(m_responseContentDispositionEncodingFallbackArray); + info.addMember(m_responseContentDispositionEncodingFallbackArray); info.addMember(m_httpBody); } diff --git a/Source/WebCore/platform/network/blackberry/CredentialBackingStore.cpp b/Source/WebCore/platform/network/blackberry/CredentialBackingStore.cpp index f60c6c212..b08a84110 100644 --- a/Source/WebCore/platform/network/blackberry/CredentialBackingStore.cpp +++ b/Source/WebCore/platform/network/blackberry/CredentialBackingStore.cpp @@ -265,7 +265,7 @@ ProtectionSpace CredentialBackingStore::getProtectionSpace(const KURL& url) int result = m_getLoginByURLStatement->step(); String username = m_getLoginByURLStatement->getColumnText(0); - String password = m_usingCertManager ? "" : m_getLoginByURLStatement->getColumnBlobAsString(1); + String password = certMgrWrapper()->isReady() ? "" : m_getLoginByURLStatement->getColumnBlobAsString(1); String host = m_getLoginByURLStatement->getColumnText(2); int port = m_getLoginByURLStatement->getColumnInt(3); int serviceType = m_getLoginByURLStatement->getColumnInt(4); diff --git a/Source/WebCore/platform/network/blackberry/NetworkJob.cpp b/Source/WebCore/platform/network/blackberry/NetworkJob.cpp index cca89b520..98ebe6059 100644 --- a/Source/WebCore/platform/network/blackberry/NetworkJob.cpp +++ b/Source/WebCore/platform/network/blackberry/NetworkJob.cpp @@ -19,7 +19,6 @@ #include "config.h" #include "NetworkJob.h" -#include "AuthenticationChallengeManager.h" #include "Chrome.h" #include "ChromeClient.h" #include "CookieManager.h" @@ -85,16 +84,9 @@ NetworkJob::NetworkJob() , m_deferredData(*this) , m_deferLoadingCount(0) , m_frame(0) - , m_isAuthenticationChallenging(false) { } -NetworkJob::~NetworkJob() -{ - if (m_isAuthenticationChallenging) - AuthenticationChallengeManager::instance()->cancelAuthenticationChallenge(this); -} - bool NetworkJob::initialize(int playerId, const String& pageGroupName, const KURL& url, @@ -211,8 +203,10 @@ void NetworkJob::handleNotifyStatusReceived(int status, const String& message) m_response.setHTTPStatusText(message); - if (isUnauthorized(m_extendedStatusCode)) + if (isUnauthorized(m_extendedStatusCode)) { purgeCredentials(); + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "Authentication failed, purge the stored credentials for this site."); + } } void NetworkJob::notifyHeadersReceived(BlackBerry::Platform::NetworkRequest::HeaderList& headers) @@ -490,7 +484,6 @@ void NetworkJob::handleNotifyClose(int status) #ifndef NDEBUG m_isRunning = false; #endif - if (!m_cancelled) { if (!m_statusReceived) { // Connection failed before sending notifyStatusReceived: use generic NetworkError. @@ -502,7 +495,6 @@ void NetworkJob::handleNotifyClose(int status) m_extendedStatusCode = BlackBerry::Platform::FilterStream::StatusTooManyRedirects; sendResponseIfNeeded(); - if (isClientAvailable()) { if (isError(status)) m_extendedStatusCode = status; @@ -775,15 +767,7 @@ bool NetworkJob::sendRequestWithCredentials(ProtectionSpaceServerType type, Prot return false; m_handle->getInternal()->m_currentWebChallenge = AuthenticationChallenge(); - - m_isAuthenticationChallenging = true; - updateDeferLoadingCount(1); - - AuthenticationChallengeManager::instance()->authenticationChallenge(newURL, - protectionSpace, - Credential(), - this, - m_frame->page()->chrome()->client()->platformPageClient()); + m_frame->page()->chrome()->client()->platformPageClient()->authenticationChallenge(newURL, protectionSpace, Credential(), this); return true; } @@ -844,17 +828,11 @@ void NetworkJob::fireDeleteJobTimer(Timer<NetworkJob>*) void NetworkJob::notifyChallengeResult(const KURL& url, const ProtectionSpace& protectionSpace, AuthenticationChallengeResult result, const Credential& credential) { - m_isAuthenticationChallenging = false; - if (result != AuthenticationChallengeSuccess || protectionSpace.host().isEmpty() || !url.isValid()) { m_newJobWithCredentialsStarted = false; - updateDeferLoadingCount(-1); return; } - cancelJob(); - updateDeferLoadingCount(-1); - if (m_handle->getInternal()->m_currentWebChallenge.isNull()) m_handle->getInternal()->m_currentWebChallenge = AuthenticationChallenge(protectionSpace, credential, 0, m_response, ResourceError()); diff --git a/Source/WebCore/platform/network/blackberry/NetworkJob.h b/Source/WebCore/platform/network/blackberry/NetworkJob.h index 8bfb46708..3526374ab 100644 --- a/Source/WebCore/platform/network/blackberry/NetworkJob.h +++ b/Source/WebCore/platform/network/blackberry/NetworkJob.h @@ -29,7 +29,6 @@ #include <network/FilterStream.h> #include <wtf/OwnPtr.h> #include <wtf/RefPtr.h> -#include <wtf/Vector.h> #include <wtf/text/WTFString.h> namespace BlackBerry { @@ -50,8 +49,6 @@ class ResourceRequest; class NetworkJob : public AuthenticationChallengeClient, public BlackBerry::Platform::FilterStream { public: NetworkJob(); - ~NetworkJob(); - bool initialize(int playerId, const String& pageGroupName, const KURL&, @@ -174,8 +171,6 @@ private: DeferredData m_deferredData; int m_deferLoadingCount; const Frame* m_frame; - - bool m_isAuthenticationChallenging; }; } // namespace WebCore diff --git a/Source/WebCore/platform/text/mac/LocaleMac.h b/Source/WebCore/platform/text/mac/LocaleMac.h index 26ca6a220..0e48c2e96 100644 --- a/Source/WebCore/platform/text/mac/LocaleMac.h +++ b/Source/WebCore/platform/text/mac/LocaleMac.h @@ -47,6 +47,7 @@ class DateComponents; class LocaleMac : public Localizer { public: static PassOwnPtr<LocaleMac> create(const String&); + static PassOwnPtr<LocaleMac> create(NSLocale*); static LocaleMac* currentLocale(); ~LocaleMac(); double parseDate(const String&); @@ -67,7 +68,6 @@ public: private: explicit LocaleMac(NSLocale*); - explicit LocaleMac(const String&); NSDateFormatter *createShortDateFormatter(); virtual void initializeLocalizerData() OVERRIDE; diff --git a/Source/WebCore/platform/text/mac/LocaleMac.mm b/Source/WebCore/platform/text/mac/LocaleMac.mm index 91ece4d06..e381c022d 100644 --- a/Source/WebCore/platform/text/mac/LocaleMac.mm +++ b/Source/WebCore/platform/text/mac/LocaleMac.mm @@ -45,9 +45,30 @@ using namespace std; namespace WebCore { +static inline String languageFromLocale(const String& locale) +{ + String normalizedLocale = locale; + normalizedLocale.replace('-', '_'); + size_t separatorPosition = normalizedLocale.find('_'); + if (separatorPosition == notFound) + return normalizedLocale; + return normalizedLocale.left(separatorPosition); +} + +static NSLocale* determineLocale(const String& locale) +{ + NSLocale* currentLocale = [NSLocale currentLocale]; + String currentLocaleLanguage = languageFromLocale(String([currentLocale localeIdentifier])); + String localeLanguage = languageFromLocale(locale); + if (equalIgnoringCase(currentLocaleLanguage, localeLanguage)) + return currentLocale; + // It seems initWithLocaleIdentifier accepts dash-separated locale identifier. + return [[NSLocale alloc] initWithLocaleIdentifier:locale]; +} + PassOwnPtr<Localizer> Localizer::create(const AtomicString& locale) { - return LocaleMac::create(locale.string()); + return LocaleMac::create(determineLocale(locale.string())); } static NSDateFormatter* createDateTimeFormatter(NSLocale* locale, NSDateFormatterStyle dateStyle, NSDateFormatterStyle timeStyle) @@ -65,12 +86,6 @@ LocaleMac::LocaleMac(NSLocale* locale) : m_locale(locale) , m_didInitializeNumberData(false) { -} - -LocaleMac::LocaleMac(const String& localeIdentifier) - : m_locale([[NSLocale alloc] initWithLocaleIdentifier:localeIdentifier]) - , m_didInitializeNumberData(false) -{ NSArray* availableLanguages = [NSLocale ISOLanguageCodes]; // NSLocale returns a lower case NSLocaleLanguageCode so we don't have care about case. NSString* language = [m_locale.get() objectForKey:NSLocaleLanguageCode]; @@ -84,33 +99,17 @@ LocaleMac::~LocaleMac() PassOwnPtr<LocaleMac> LocaleMac::create(const String& localeIdentifier) { - return adoptPtr(new LocaleMac(localeIdentifier)); + return adoptPtr(new LocaleMac([[NSLocale alloc] initWithLocaleIdentifier:localeIdentifier])); } -static inline String languageFromLocale(const String& locale) +PassOwnPtr<LocaleMac> LocaleMac::create(NSLocale* locale) { - String normalizedLocale = locale; - normalizedLocale.replace('-', '_'); - size_t separatorPosition = normalizedLocale.find('_'); - if (separatorPosition == notFound) - return normalizedLocale; - return normalizedLocale.left(separatorPosition); -} - -static NSLocale* determineLocale() -{ - NSLocale* currentLocale = [NSLocale currentLocale]; - String currentLocaleLanguage = languageFromLocale(String([currentLocale localeIdentifier])); - String browserLanguage = languageFromLocale(defaultLanguage()); - if (equalIgnoringCase(currentLocaleLanguage, browserLanguage)) - return currentLocale; - // It seems initWithLocaleIdentifier accepts dash-separated locale identifier. - return [[NSLocale alloc] initWithLocaleIdentifier:defaultLanguage()]; + return adoptPtr(new LocaleMac(locale)); } LocaleMac* LocaleMac::currentLocale() { - static LocaleMac* currentLocale = new LocaleMac(determineLocale()); + static LocaleMac* currentLocale = new LocaleMac(determineLocale(defaultLanguage())); return currentLocale; } diff --git a/Source/WebCore/plugins/gtk/PluginViewGtk.cpp b/Source/WebCore/plugins/gtk/PluginViewGtk.cpp index 62f9f8d84..4006040d8 100644 --- a/Source/WebCore/plugins/gtk/PluginViewGtk.cpp +++ b/Source/WebCore/plugins/gtk/PluginViewGtk.cpp @@ -76,7 +76,7 @@ #define Bool int // this got undefined somewhere #define Status int // ditto #include <X11/extensions/Xrender.h> -#include <cairo/cairo-xlib.h> +#include <cairo-xlib.h> #include <gdk/gdkx.h> using JSC::ExecState; diff --git a/Source/WebCore/rendering/ExclusionRectangle.cpp b/Source/WebCore/rendering/ExclusionRectangle.cpp index 78f83b055..3bdde0aee 100644 --- a/Source/WebCore/rendering/ExclusionRectangle.cpp +++ b/Source/WebCore/rendering/ExclusionRectangle.cpp @@ -40,10 +40,10 @@ static inline float ellipseXIntercept(float y, float rx, float ry) return rx * sqrt(1 - (y*y) / (ry*ry)); } -void ExclusionRectangle::getOutsideIntervals(float y1, float y2, Vector<ExclusionInterval>& rv) const +void ExclusionRectangle::getExcludedIntervals(float logicalTop, float logicalBottom, SegmentList& result) const { - if (y1 > y2) - std::swap(y1, y2); + float y1 = minYForLogicalLine(logicalTop, logicalBottom); + float y2 = maxYForLogicalLine(logicalTop, logicalBottom); if (y2 < m_y || y1 >= m_y + m_height) return; @@ -65,15 +65,15 @@ void ExclusionRectangle::getOutsideIntervals(float y1, float y2, Vector<Exclusio } } - rv.append(ExclusionInterval(x1, x2)); + result.append(LineSegment(x1, x2)); } -void ExclusionRectangle::getInsideIntervals(float y1, float y2, Vector<ExclusionInterval>& rv) const +void ExclusionRectangle::getIncludedIntervals(float logicalTop, float logicalBottom, SegmentList& result) const { - if (y1 > y2) - std::swap(y1, y2); + float y1 = minYForLogicalLine(logicalTop, logicalBottom); + float y2 = maxYForLogicalLine(logicalTop, logicalBottom); - if (y1 < m_y || y2 >= m_y + m_height) + if (y1 < m_y || y2 > m_y + m_height) return; float x1 = m_x; @@ -106,7 +106,7 @@ void ExclusionRectangle::getInsideIntervals(float y1, float y2, Vector<Exclusion } } - rv.append(ExclusionInterval(x1, x2)); + result.append(LineSegment(x1, x2)); } } // namespace WebCore diff --git a/Source/WebCore/rendering/ExclusionRectangle.h b/Source/WebCore/rendering/ExclusionRectangle.h index 6af021772..5ca289d86 100644 --- a/Source/WebCore/rendering/ExclusionRectangle.h +++ b/Source/WebCore/rendering/ExclusionRectangle.h @@ -31,6 +31,7 @@ #define ExclusionRectangle_h #include "ExclusionShape.h" +#include "FloatSize.h" #include <wtf/Assertions.h> #include <wtf/Vector.h> @@ -38,20 +39,20 @@ namespace WebCore { class ExclusionRectangle : public ExclusionShape { public: - ExclusionRectangle(float x, float y, float width, float height, float rx = 0, float ry = 0) + ExclusionRectangle(const FloatRect& bounds, const FloatSize& radii) : ExclusionShape() - , m_x(x) - , m_y(y) - , m_width(width) - , m_height(height) - , m_rx(rx) - , m_ry(ry) + , m_x(bounds.x()) + , m_y(bounds.y()) + , m_width(bounds.width()) + , m_height(bounds.height()) + , m_rx(radii.width()) + , m_ry(radii.height()) { } - virtual FloatRect shapeLogicalBoundingBox() const OVERRIDE { return FloatRect(m_x, m_y, m_width, m_height); } - virtual void getOutsideIntervals(float y1, float y2, Vector<ExclusionInterval>&) const OVERRIDE; - virtual void getInsideIntervals(float y1, float y2, Vector<ExclusionInterval>&) const OVERRIDE; + virtual FloatRect shapeLogicalBoundingBox() const OVERRIDE { return internalToLogicalBoundingBox(FloatRect(m_x, m_y, m_width, m_height)); } + virtual void getExcludedIntervals(float logicalTop, float logicalBottom, SegmentList&) const OVERRIDE; + virtual void getIncludedIntervals(float logicalTop, float logicalBottom, SegmentList&) const OVERRIDE; private: float m_x; diff --git a/Source/WebCore/rendering/ExclusionShape.cpp b/Source/WebCore/rendering/ExclusionShape.cpp index 48c88b653..0f430ef04 100644 --- a/Source/WebCore/rendering/ExclusionShape.cpp +++ b/Source/WebCore/rendering/ExclusionShape.cpp @@ -32,6 +32,7 @@ #include "BasicShapeFunctions.h" #include "ExclusionRectangle.h" +#include "FloatSize.h" #include "LengthFunctions.h" #include "NotImplemented.h" #include "WindRule.h" @@ -41,66 +42,93 @@ namespace WebCore { -static PassOwnPtr<ExclusionShape> createExclusionRectangle(float x, float y, float width, float height, float rx, float ry) +static PassOwnPtr<ExclusionShape> createExclusionRectangle(const FloatRect& bounds, const FloatSize& radii) { - ASSERT(width >= 0 && height >= 0 && rx >= 0 && ry >= 0); - return adoptPtr(new ExclusionRectangle(x, y, width, height, rx, ry)); + ASSERT(bounds.width() >= 0 && bounds.height() >= 0 && radii.width() >= 0 && radii.height() >= 0); + return adoptPtr(new ExclusionRectangle(bounds, radii)); } -static PassOwnPtr<ExclusionShape> createExclusionCircle(float cx, float cy, float radius) +static PassOwnPtr<ExclusionShape> createExclusionCircle(const FloatPoint& center, float radius) { ASSERT(radius >= 0); - return adoptPtr(new ExclusionRectangle(cx - radius, cy - radius, cx + radius, cy + radius, radius, radius)); + return adoptPtr(new ExclusionRectangle(FloatRect(center.x() - radius, center.y() - radius, radius*2, radius*2), FloatSize(radius, radius))); } -static PassOwnPtr<ExclusionShape> createExclusionEllipse(float cx, float cy, float rx, float ry) +static PassOwnPtr<ExclusionShape> createExclusionEllipse(const FloatPoint& center, const FloatSize& radii) { - ASSERT(rx >= 0 && ry >= 0); - return adoptPtr(new ExclusionRectangle(cx - rx, cy - ry, cx + rx, cy + ry, rx, ry)); + ASSERT(radii.width() >= 0 && radii.height() >= 0); + return adoptPtr(new ExclusionRectangle(FloatRect(center.x() - radii.width(), center.y() - radii.height(), radii.width()*2, radii.height()*2), radii)); } -PassOwnPtr<ExclusionShape> ExclusionShape::createExclusionShape(const BasicShape* wrapShape, float borderBoxLogicalWidth, float borderBoxLogicalHeight) +// If the writingMode is vertical, then the BasicShape's (physical) x and y coordinates are swapped, so that +// line segments are parallel to the internal coordinate system's X axis. + +PassOwnPtr<ExclusionShape> ExclusionShape::createExclusionShape(const BasicShape* basicShape, float logicalBoxWidth, float logicalBoxHeight, WritingMode writingMode) { - if (!wrapShape) + if (!basicShape) return nullptr; - switch (wrapShape->type()) { + bool horizontalWritingMode = isHorizontalWritingMode(writingMode); + float boxWidth = horizontalWritingMode ? logicalBoxWidth : logicalBoxHeight; + float boxHeight = horizontalWritingMode ? logicalBoxHeight : logicalBoxWidth; + OwnPtr<ExclusionShape> exclusionShape; + + switch (basicShape->type()) { + case BasicShape::BASIC_SHAPE_RECTANGLE: { - const BasicShapeRectangle* rectangle = static_cast<const BasicShapeRectangle*>(wrapShape); - Length rx = rectangle->cornerRadiusX(); - Length ry = rectangle->cornerRadiusY(); - return createExclusionRectangle( - floatValueForLength(rectangle->x(), borderBoxLogicalWidth), - floatValueForLength(rectangle->y(), borderBoxLogicalHeight), - floatValueForLength(rectangle->width(), borderBoxLogicalWidth), - floatValueForLength(rectangle->height(), borderBoxLogicalHeight), - rx.isUndefined() ? 0 : floatValueForLength(rx, borderBoxLogicalWidth), - ry.isUndefined() ? 0 : floatValueForLength(ry, borderBoxLogicalHeight) ); + const BasicShapeRectangle* rectangle = static_cast<const BasicShapeRectangle*>(basicShape); + float x = floatValueForLength(rectangle->x(), boxWidth); + float y = floatValueForLength(rectangle->y(), boxHeight); + float width = floatValueForLength(rectangle->width(), boxWidth); + float height = floatValueForLength(rectangle->height(), boxHeight); + Length radiusXLength = rectangle->cornerRadiusX(); + Length radiusYLength = rectangle->cornerRadiusY(); + float radiusX = radiusXLength.isUndefined() ? 0 : floatValueForLength(radiusXLength, boxWidth); + float radiusY = radiusYLength.isUndefined() ? 0 : floatValueForLength(radiusYLength, boxHeight); + + exclusionShape = horizontalWritingMode + ? createExclusionRectangle(FloatRect(x, y, width, height), FloatSize(radiusX, radiusY)) + : createExclusionRectangle(FloatRect(y, x, height, width), FloatSize(radiusY, radiusX)); + break; } case BasicShape::BASIC_SHAPE_CIRCLE: { - const BasicShapeCircle* circle = static_cast<const BasicShapeCircle*>(wrapShape); - return createExclusionCircle( - floatValueForLength(circle->centerX(), borderBoxLogicalWidth), - floatValueForLength(circle->centerY(), borderBoxLogicalHeight), - floatValueForLength(circle->radius(), std::max(borderBoxLogicalHeight, borderBoxLogicalWidth)) ); + const BasicShapeCircle* circle = static_cast<const BasicShapeCircle*>(basicShape); + float centerX = floatValueForLength(circle->centerX(), boxWidth); + float centerY = floatValueForLength(circle->centerY(), boxHeight); + float radius = floatValueForLength(circle->radius(), std::max(boxHeight, boxWidth)); + + exclusionShape = horizontalWritingMode + ? createExclusionCircle(FloatPoint(centerX, centerY), radius) + : createExclusionCircle(FloatPoint(centerY, centerX), radius); + break; } case BasicShape::BASIC_SHAPE_ELLIPSE: { - const BasicShapeEllipse* ellipse = static_cast<const BasicShapeEllipse*>(wrapShape); - return createExclusionEllipse( - floatValueForLength(ellipse->centerX(), borderBoxLogicalWidth), - floatValueForLength(ellipse->centerY(), borderBoxLogicalHeight), - floatValueForLength(ellipse->radiusX(), borderBoxLogicalWidth), - floatValueForLength(ellipse->radiusY(), borderBoxLogicalHeight) ); + const BasicShapeEllipse* ellipse = static_cast<const BasicShapeEllipse*>(basicShape); + float centerX = floatValueForLength(ellipse->centerX(), boxWidth); + float centerY = floatValueForLength(ellipse->centerY(), boxHeight); + float radiusX = floatValueForLength(ellipse->radiusX(), boxWidth); + float radiusY = floatValueForLength(ellipse->radiusY(), boxHeight); + + exclusionShape = horizontalWritingMode + ? createExclusionEllipse(FloatPoint(centerX, centerY), FloatSize(radiusX, radiusY)) + : createExclusionEllipse(FloatPoint(centerY, centerX), FloatSize(radiusY, radiusX)); + break; } case BasicShape::BASIC_SHAPE_POLYGON: notImplemented(); + + default: + ASSERT_NOT_REACHED(); } - ASSERT_NOT_REACHED(); - return nullptr; + exclusionShape->m_logicalBoxWidth = logicalBoxWidth; + exclusionShape->m_logicalBoxHeight = logicalBoxHeight; + exclusionShape->m_writingMode = writingMode; + + return exclusionShape.release(); } } // namespace WebCore diff --git a/Source/WebCore/rendering/ExclusionShape.h b/Source/WebCore/rendering/ExclusionShape.h index c5de4d705..bb1edc6d1 100644 --- a/Source/WebCore/rendering/ExclusionShape.h +++ b/Source/WebCore/rendering/ExclusionShape.h @@ -31,22 +31,51 @@ #define ExclusionShape_h #include "BasicShapes.h" -#include "ExclusionInterval.h" #include "FloatRect.h" +#include "WritingMode.h" #include <wtf/PassOwnPtr.h> #include <wtf/Vector.h> namespace WebCore { +struct LineSegment { + float logicalLeft; + float logicalRight; + + LineSegment(float logicalLeft, float logicalRight) + : logicalLeft(logicalLeft) + , logicalRight(logicalRight) + { + } +}; + +typedef Vector<LineSegment> SegmentList; + + +// A representation of a BasicShape that enables layout code to determine how to break a line up into segments +// that will fit within or around a shape. The line is defined by a pair of logical Y coordinates and the +// computed segments are returned as pairs of logical X coordinates. The BasicShape itself is defined in +// physical coordinates. + class ExclusionShape { public: - static PassOwnPtr<ExclusionShape> createExclusionShape(const BasicShape*, float borderBoxLogicalWidth, float borderBoxLogicalHeight); + static PassOwnPtr<ExclusionShape> createExclusionShape(const BasicShape*, float logicalBoxWidth, float logicalBoxHeight, WritingMode); virtual ~ExclusionShape() { } virtual FloatRect shapeLogicalBoundingBox() const = 0; - virtual void getInsideIntervals(float logicalTop, float logicalBottom, Vector<ExclusionInterval>&) const = 0; - virtual void getOutsideIntervals(float logicalTop, float logicalBottom, Vector<ExclusionInterval>&) const = 0; + virtual void getIncludedIntervals(float logicalTop, float logicalBottom, SegmentList&) const = 0; + virtual void getExcludedIntervals(float logicalTop, float logicalBottom, SegmentList&) const = 0; + +protected: + float minYForLogicalLine(float logicalTop, float logicalBottom) const { return (m_writingMode == RightToLeftWritingMode) ? m_logicalBoxHeight - logicalBottom : logicalTop; } + float maxYForLogicalLine(float logicalTop, float logicalBottom) const { return (m_writingMode == RightToLeftWritingMode) ? m_logicalBoxHeight - logicalTop : logicalBottom; } + FloatRect internalToLogicalBoundingBox(FloatRect r) const { return (m_writingMode == RightToLeftWritingMode) ? FloatRect(r.x(), m_logicalBoxHeight - r.maxY(), r.width(), r.height()) : r; } + +private: + WritingMode m_writingMode; + float m_logicalBoxWidth; + float m_logicalBoxHeight; }; } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderBR.cpp b/Source/WebCore/rendering/RenderBR.cpp index d80393614..304a27945 100644 --- a/Source/WebCore/rendering/RenderBR.cpp +++ b/Source/WebCore/rendering/RenderBR.cpp @@ -40,7 +40,7 @@ RenderBR::~RenderBR() int RenderBR::lineHeight(bool firstLine) const { - if (firstLine && document()->usesFirstLineRules()) { + if (firstLine && document()->styleSheetCollection()->usesFirstLineRules()) { RenderStyle* s = style(firstLine); if (s != style()) return s->computedLineHeight(view()); diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp index abed66220..4c1371e81 100755 --- a/Source/WebCore/rendering/RenderBlock.cpp +++ b/Source/WebCore/rendering/RenderBlock.cpp @@ -347,7 +347,7 @@ void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldSty m_lineHeight = -1; // Update pseudos for :before and :after now. - if (!isAnonymous() && document()->usesBeforeAfterRules() && canHaveGeneratedChildren()) { + if (!isAnonymous() && document()->styleSheetCollection()->usesBeforeAfterRules() && canHaveGeneratedChildren()) { updateBeforeAfterContent(BEFORE); updateBeforeAfterContent(AFTER); } @@ -602,7 +602,7 @@ void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBoxModelObject* curr = toRenderBoxModelObject(parent()); RenderBoxModelObject* currChild = this; RenderObject* currChildNextSibling = currChild->nextSibling(); - bool documentUsesBeforeAfterRules = document()->usesBeforeAfterRules(); + bool documentUsesBeforeAfterRules = document()->styleSheetCollection()->usesBeforeAfterRules(); // Note: |this| can be destroyed inside this loop if it is an empty anonymous // block and we try to call updateBeforeAfterContent inside which removes the @@ -877,7 +877,7 @@ void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, // content gets properly destroyed. bool isFirstChild = (beforeChild == firstChild()); bool isLastChild = (beforeChild == lastChild()); - if (document()->usesBeforeAfterRules()) + if (document()->styleSheetCollection()->usesBeforeAfterRules()) children()->updateBeforeAfterContent(this, AFTER); if (isLastChild && beforeChild != lastChild()) { // We destroyed the last child, so now we need to update our insertion @@ -6153,7 +6153,7 @@ LayoutUnit RenderBlock::lineHeight(bool firstLine, LineDirectionMode direction, if (isReplaced() && linePositionMode == PositionOnContainingLine) return RenderBox::lineHeight(firstLine, direction, linePositionMode); - if (firstLine && document()->usesFirstLineRules()) { + if (firstLine && document()->styleSheetCollection()->usesFirstLineRules()) { RenderStyle* s = style(firstLine); if (s != style()) return s->computedLineHeight(view()); @@ -6461,7 +6461,7 @@ void RenderBlock::createFirstLetterRenderer(RenderObject* firstLetterBlock, Rend void RenderBlock::updateFirstLetter() { - if (!document()->usesFirstLetterRules()) + if (!document()->styleSheetCollection()->usesFirstLetterRules()) return; // Don't recur if (style()->styleType() == FIRST_LETTER) diff --git a/Source/WebCore/rendering/RenderFlowThread.cpp b/Source/WebCore/rendering/RenderFlowThread.cpp index 0741ea8c8..d5a99b7bb 100644 --- a/Source/WebCore/rendering/RenderFlowThread.cpp +++ b/Source/WebCore/rendering/RenderFlowThread.cpp @@ -222,19 +222,18 @@ void RenderFlowThread::updateLogicalWidth() } } -void RenderFlowThread::updateLogicalHeight() +void RenderFlowThread::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const { - LayoutUnit logicalHeight = 0; + computedValues.m_position = logicalTop; + computedValues.m_extent = 0; - for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) { + for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) { RenderRegion* region = *iter; if (!region->isValid()) continue; ASSERT(!region->needsLayout()); - logicalHeight += region->logicalHeightOfAllFlowThreadContent(); + computedValues.m_extent += region->logicalHeightOfAllFlowThreadContent(); } - - setLogicalHeight(logicalHeight); } void RenderFlowThread::paintFlowThreadPortionInRegion(PaintInfo& paintInfo, RenderRegion* region, LayoutRect flowThreadPortionRect, LayoutRect flowThreadPortionOverflowRect, const LayoutPoint& paintOffset) const diff --git a/Source/WebCore/rendering/RenderFlowThread.h b/Source/WebCore/rendering/RenderFlowThread.h index d09183d95..b942eee57 100644 --- a/Source/WebCore/rendering/RenderFlowThread.h +++ b/Source/WebCore/rendering/RenderFlowThread.h @@ -74,7 +74,7 @@ public: const RenderRegionList& renderRegionList() const { return m_regionList; } virtual void updateLogicalWidth() OVERRIDE; - virtual void updateLogicalHeight() OVERRIDE; + virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE; void paintFlowThreadPortionInRegion(PaintInfo&, RenderRegion*, LayoutRect flowThreadPortionRect, LayoutRect flowThreadPortionOverflowRect, const LayoutPoint&) const; bool hitTestFlowThreadPortionInRegion(RenderRegion*, LayoutRect flowThreadPortionRect, LayoutRect flowThreadPortionOverflowRect, const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) const; diff --git a/Source/WebCore/rendering/RenderInline.cpp b/Source/WebCore/rendering/RenderInline.cpp index 234cea28b..239aba370 100644 --- a/Source/WebCore/rendering/RenderInline.cpp +++ b/Source/WebCore/rendering/RenderInline.cpp @@ -194,7 +194,7 @@ void RenderInline::styleDidChange(StyleDifference diff, const RenderStyle* oldSt } // Update pseudos for :before and :after now. - if (!isAnonymous() && document()->usesBeforeAfterRules()) { + if (!isAnonymous() && document()->styleSheetCollection()->usesBeforeAfterRules()) { children()->updateBeforeAfterContent(this, BEFORE); children()->updateBeforeAfterContent(this, AFTER); } @@ -218,7 +218,7 @@ void RenderInline::updateAlwaysCreateLineBoxes(bool fullLayout) || parentStyle->lineHeight() != style()->lineHeight())) || (inRenderFlowThread() && enclosingRenderFlowThread()->hasRegionsWithStyling()); - if (!alwaysCreateLineBoxes && checkFonts && document()->usesFirstLineRules()) { + if (!alwaysCreateLineBoxes && checkFonts && document()->styleSheetCollection()->usesFirstLineRules()) { // Have to check the first line style as well. parentStyle = parent()->style(true); RenderStyle* childStyle = style(true); @@ -324,7 +324,7 @@ void RenderInline::addChildIgnoringContinuation(RenderObject* newChild, RenderOb // has to move into the inline continuation. Call updateBeforeAfterContent to ensure that our :after // content gets properly destroyed. bool isLastChild = (beforeChild == lastChild()); - if (document()->usesBeforeAfterRules()) + if (document()->styleSheetCollection()->usesBeforeAfterRules()) children()->updateBeforeAfterContent(this, AFTER); if (isLastChild && beforeChild != lastChild()) beforeChild = 0; // We destroyed the last child, so now we need to update our insertion @@ -399,7 +399,7 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock, // Someone may have indirectly caused a <q> to split. When this happens, the :after content // has to move into the inline continuation. Call updateBeforeAfterContent to ensure that the inline's :after // content gets properly destroyed. - if (document()->usesBeforeAfterRules()) + if (document()->styleSheetCollection()->usesBeforeAfterRules()) inlineCurr->children()->updateBeforeAfterContent(inlineCurr, AFTER); // Now we need to take all of the children starting from the first child @@ -1283,7 +1283,7 @@ InlineFlowBox* RenderInline::createAndAppendInlineFlowBox() LayoutUnit RenderInline::lineHeight(bool firstLine, LineDirectionMode /*direction*/, LinePositionMode /*linePositionMode*/) const { - if (firstLine && document()->usesFirstLineRules()) { + if (firstLine && document()->styleSheetCollection()->usesFirstLineRules()) { RenderStyle* s = style(firstLine); if (s != style()) return s->computedLineHeight(view()); diff --git a/Source/WebCore/rendering/RenderMeter.cpp b/Source/WebCore/rendering/RenderMeter.cpp index b539c0a3a..a4b3eca35 100644 --- a/Source/WebCore/rendering/RenderMeter.cpp +++ b/Source/WebCore/rendering/RenderMeter.cpp @@ -55,13 +55,22 @@ HTMLMeterElement* RenderMeter::meterElement() const void RenderMeter::updateLogicalWidth() { RenderBox::updateLogicalWidth(); - setWidth(theme()->meterSizeForBounds(this, pixelSnappedIntRect(frameRect())).width()); + + IntSize frameSize = theme()->meterSizeForBounds(this, pixelSnappedIntRect(frameRect())); + setLogicalWidth(isHorizontalWritingMode() ? frameSize.width() : frameSize.height()); } -void RenderMeter::updateLogicalHeight() +void RenderMeter::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const { - RenderBox::updateLogicalHeight(); - setHeight(theme()->meterSizeForBounds(this, pixelSnappedIntRect(frameRect())).height()); + RenderBox::computeLogicalHeight(logicalHeight, logicalTop, computedValues); + + LayoutRect frame = frameRect(); + if (isHorizontalWritingMode()) + frame.setHeight(computedValues.m_extent); + else + frame.setWidth(computedValues.m_extent); + IntSize frameSize = theme()->meterSizeForBounds(this, pixelSnappedIntRect(frame)); + computedValues.m_extent = isHorizontalWritingMode() ? frameSize.height() : frameSize.width(); } double RenderMeter::valueRatio() const diff --git a/Source/WebCore/rendering/RenderMeter.h b/Source/WebCore/rendering/RenderMeter.h index 9051951d1..b7c3ecee7 100644 --- a/Source/WebCore/rendering/RenderMeter.h +++ b/Source/WebCore/rendering/RenderMeter.h @@ -40,7 +40,7 @@ public: private: virtual void updateLogicalWidth() OVERRIDE; - virtual void updateLogicalHeight() OVERRIDE; + virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE; virtual const char* renderName() const { return "RenderMeter"; } virtual bool isMeter() const { return true; } diff --git a/Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp b/Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp index e553c5401..562506842 100644 --- a/Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp +++ b/Source/WebCore/rendering/RenderMultiColumnFlowThread.cpp @@ -42,4 +42,11 @@ const char* RenderMultiColumnFlowThread::renderName() const return "RenderMultiColumnFlowThread"; } +void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const +{ + // We simply remain at our intrinsic height. + computedValues.m_extent = logicalHeight; + computedValues.m_position = logicalTop; +} + } diff --git a/Source/WebCore/rendering/RenderMultiColumnFlowThread.h b/Source/WebCore/rendering/RenderMultiColumnFlowThread.h index 363cd0771..595222784 100644 --- a/Source/WebCore/rendering/RenderMultiColumnFlowThread.h +++ b/Source/WebCore/rendering/RenderMultiColumnFlowThread.h @@ -39,7 +39,7 @@ public: private: virtual const char* renderName() const OVERRIDE; - virtual void updateLogicalHeight() OVERRIDE { } // We simply remain at our intrinsic height. + virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE; }; } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp index 214970a35..c523d26b6 100755 --- a/Source/WebCore/rendering/RenderObject.cpp +++ b/Source/WebCore/rendering/RenderObject.cpp @@ -2597,7 +2597,7 @@ void RenderObject::layout() PassRefPtr<RenderStyle> RenderObject::uncachedFirstLineStyle(RenderStyle* style) const { - if (!document()->usesFirstLineRules()) + if (!document()->styleSheetCollection()->usesFirstLineRules()) return 0; ASSERT(!isText()); @@ -2618,7 +2618,7 @@ PassRefPtr<RenderStyle> RenderObject::uncachedFirstLineStyle(RenderStyle* style) RenderStyle* RenderObject::firstLineStyleSlowCase() const { - ASSERT(document()->usesFirstLineRules()); + ASSERT(document()->styleSheetCollection()->usesFirstLineRules()); RenderStyle* style = m_style.get(); const RenderObject* renderer = isText() ? parent() : this; diff --git a/Source/WebCore/rendering/RenderObject.h b/Source/WebCore/rendering/RenderObject.h index 0b10b69dc..28cda3ad7 100644 --- a/Source/WebCore/rendering/RenderObject.h +++ b/Source/WebCore/rendering/RenderObject.h @@ -27,6 +27,7 @@ #define RenderObject_h #include "CachedImageClient.h" +#include "DocumentStyleSheetCollection.h" #include "Element.h" #include "FractionalLayoutUnit.h" #include "FloatQuad.h" @@ -735,7 +736,7 @@ public: virtual LayoutUnit maxPreferredLogicalWidth() const { return 0; } RenderStyle* style() const { return m_style.get(); } - RenderStyle* firstLineStyle() const { return document()->usesFirstLineRules() ? firstLineStyleSlowCase() : style(); } + RenderStyle* firstLineStyle() const { return document()->styleSheetCollection()->usesFirstLineRules() ? firstLineStyleSlowCase() : style(); } RenderStyle* style(bool firstLine) const { return firstLine ? firstLineStyle() : style(); } // Used only by Element::pseudoStyleCacheIsInvalid to get a first line style based off of a diff --git a/Source/WebCore/rendering/RenderObjectChildList.cpp b/Source/WebCore/rendering/RenderObjectChildList.cpp index 247f7dda4..c3b4d4831 100644 --- a/Source/WebCore/rendering/RenderObjectChildList.cpp +++ b/Source/WebCore/rendering/RenderObjectChildList.cpp @@ -369,7 +369,7 @@ static RenderObject* ensureBeforeAfterContainer(RenderObject* owner, PseudoId ty void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, PseudoId type, const RenderObject* styledObject) { // Double check that the document did in fact use generated content rules. Otherwise we should not have been called. - ASSERT(owner->document()->usesBeforeAfterRules()); + ASSERT(owner->document()->styleSheetCollection()->usesBeforeAfterRules()); // In CSS2, before/after pseudo-content cannot nest. Check this first. if (owner->style()->styleType() == BEFORE || owner->style()->styleType() == AFTER) diff --git a/Source/WebCore/rendering/RenderTableRow.cpp b/Source/WebCore/rendering/RenderTableRow.cpp index 1f2bd0689..b102f0842 100644 --- a/Source/WebCore/rendering/RenderTableRow.cpp +++ b/Source/WebCore/rendering/RenderTableRow.cpp @@ -55,7 +55,7 @@ void RenderTableRow::willBeRemovedFromTree() void RenderTableRow::updateBeforeAndAfterContent() { - if (!isAnonymous() && document()->usesBeforeAfterRules()) { + if (!isAnonymous() && document()->styleSheetCollection()->usesBeforeAfterRules()) { children()->updateBeforeAfterContent(this, BEFORE); children()->updateBeforeAfterContent(this, AFTER); } diff --git a/Source/WebCore/rendering/RenderWidget.cpp b/Source/WebCore/rendering/RenderWidget.cpp index 9537edf5d..21d0c3ad6 100644 --- a/Source/WebCore/rendering/RenderWidget.cpp +++ b/Source/WebCore/rendering/RenderWidget.cpp @@ -47,53 +47,42 @@ static HashMap<const Widget*, RenderWidget*>& widgetRendererMap() return *staticWidgetRendererMap; } -static unsigned widgetHierarchyUpdateSuspendCount; +unsigned WidgetHierarchyUpdatesSuspensionScope::s_widgetHierarchyUpdateSuspendCount = 0; -typedef HashMap<RefPtr<Widget>, FrameView*> WidgetToParentMap; - -static WidgetToParentMap& widgetNewParentMap() +WidgetHierarchyUpdatesSuspensionScope::WidgetToParentMap& WidgetHierarchyUpdatesSuspensionScope::widgetNewParentMap() { DEFINE_STATIC_LOCAL(WidgetToParentMap, map, ()); return map; } -void RenderWidget::suspendWidgetHierarchyUpdates() +void WidgetHierarchyUpdatesSuspensionScope::moveWidgets() { - widgetHierarchyUpdateSuspendCount++; -} - -void RenderWidget::resumeWidgetHierarchyUpdates() -{ - ASSERT(widgetHierarchyUpdateSuspendCount); - if (widgetHierarchyUpdateSuspendCount == 1) { - WidgetToParentMap map = widgetNewParentMap(); - widgetNewParentMap().clear(); - WidgetToParentMap::iterator end = map.end(); - for (WidgetToParentMap::iterator it = map.begin(); it != end; ++it) { - Widget* child = it->first.get(); - ScrollView* currentParent = child->parent(); - FrameView* newParent = it->second; - if (newParent != currentParent) { - if (currentParent) - currentParent->removeChild(child); - if (newParent) - newParent->addChild(child); - } + WidgetToParentMap map = widgetNewParentMap(); + widgetNewParentMap().clear(); + WidgetToParentMap::iterator end = map.end(); + for (WidgetToParentMap::iterator it = map.begin(); it != end; ++it) { + Widget* child = it->first.get(); + ScrollView* currentParent = child->parent(); + FrameView* newParent = it->second; + if (newParent != currentParent) { + if (currentParent) + currentParent->removeChild(child); + if (newParent) + newParent->addChild(child); } } - widgetHierarchyUpdateSuspendCount--; } static void moveWidgetToParentSoon(Widget* child, FrameView* parent) { - if (!widgetHierarchyUpdateSuspendCount) { + if (!WidgetHierarchyUpdatesSuspensionScope::isSuspended()) { if (parent) parent->addChild(child); else child->removeFromParent(); return; } - widgetNewParentMap().set(child, parent); + WidgetHierarchyUpdatesSuspensionScope::scheduleWidgetToMove(child, parent); } RenderWidget::RenderWidget(Node* node) diff --git a/Source/WebCore/rendering/RenderWidget.h b/Source/WebCore/rendering/RenderWidget.h index b7db3b809..d20123a68 100644 --- a/Source/WebCore/rendering/RenderWidget.h +++ b/Source/WebCore/rendering/RenderWidget.h @@ -28,6 +28,32 @@ namespace WebCore { +class WidgetHierarchyUpdatesSuspensionScope { +public: + WidgetHierarchyUpdatesSuspensionScope() + { + s_widgetHierarchyUpdateSuspendCount++; + } + ~WidgetHierarchyUpdatesSuspensionScope() + { + ASSERT(s_widgetHierarchyUpdateSuspendCount); + if (s_widgetHierarchyUpdateSuspendCount == 1) + moveWidgets(); + s_widgetHierarchyUpdateSuspendCount--; + } + + static bool isSuspended() { return s_widgetHierarchyUpdateSuspendCount; } + static void scheduleWidgetToMove(Widget* widget, FrameView* frame) { widgetNewParentMap().set(widget, frame); } + +private: + typedef HashMap<RefPtr<Widget>, FrameView*> WidgetToParentMap; + static WidgetToParentMap& widgetNewParentMap(); + + void moveWidgets(); + + static unsigned s_widgetHierarchyUpdateSuspendCount; +}; + class RenderWidget : public RenderReplaced, private OverlapTestRequestClient { public: virtual ~RenderWidget(); @@ -42,9 +68,6 @@ public: IntRect windowClipRect() const; void notifyWidget(WidgetNotification); - - static void suspendWidgetHierarchyUpdates(); - static void resumeWidgetHierarchyUpdates(); RenderArena* ref() { ++m_refCount; return renderArena(); } void deref(RenderArena*); diff --git a/Source/WebCore/rendering/RootInlineBox.cpp b/Source/WebCore/rendering/RootInlineBox.cpp index 928fe667e..1f4206700 100644 --- a/Source/WebCore/rendering/RootInlineBox.cpp +++ b/Source/WebCore/rendering/RootInlineBox.cpp @@ -846,7 +846,7 @@ LayoutUnit RootInlineBox::verticalPositionForBox(InlineBox* box, VerticalPositio // This method determines the vertical position for inline elements. bool firstLine = isFirstLineStyle(); - if (firstLine && !renderer->document()->usesFirstLineRules()) + if (firstLine && !renderer->document()->styleSheetCollection()->usesFirstLineRules()) firstLine = false; // Check the cache. diff --git a/Source/WebCore/rendering/WrapShapeInfo.cpp b/Source/WebCore/rendering/WrapShapeInfo.cpp index 0a16cc51f..0ce46e665 100644 --- a/Source/WebCore/rendering/WrapShapeInfo.cpp +++ b/Source/WebCore/rendering/WrapShapeInfo.cpp @@ -71,10 +71,6 @@ WrapShapeInfo* WrapShapeInfo::wrapShapeInfoForRenderBlock(const RenderBlock* blo bool WrapShapeInfo::isWrapShapeInfoEnabledForRenderBlock(const RenderBlock* block) { - // FIXME: Bug 89705: Enable shape inside for vertical writing modes - if (!block->isHorizontalWritingMode()) - return false; - // FIXME: Bug 89707: Enable shape inside for non-rectangular shapes BasicShape* shape = block->style()->wrapShapeInside(); return (shape && shape->type() == BasicShape::BASIC_SHAPE_RECTANGLE); @@ -107,7 +103,7 @@ void WrapShapeInfo::computeShapeSize(LayoutUnit logicalWidth, LayoutUnit logical BasicShape* shape = m_block->style()->wrapShapeInside(); ASSERT(shape); - m_shape = ExclusionShape::createExclusionShape(shape, logicalWidth, logicalHeight); + m_shape = ExclusionShape::createExclusionShape(shape, logicalWidth, logicalHeight, m_block->style()->writingMode()); ASSERT(m_shape); } @@ -118,15 +114,7 @@ bool WrapShapeInfo::computeSegmentsForLine(LayoutUnit lineTop) if (lineState() == LINE_INSIDE_SHAPE) { ASSERT(m_shape); - - Vector<ExclusionInterval> intervals; - m_shape->getInsideIntervals(lineTop, lineTop, intervals); // FIXME: Bug 95479, workaround for now - for (size_t i = 0; i < intervals.size(); i++) { - LineSegment segment; - segment.logicalLeft = intervals[i].x1; - segment.logicalRight = intervals[i].x2; - m_segments.append(segment); - } + m_shape->getIncludedIntervals(lineTop, lineTop, m_segments); // FIXME: Bug 95479, workaround for now } return m_segments.size(); } diff --git a/Source/WebCore/rendering/WrapShapeInfo.h b/Source/WebCore/rendering/WrapShapeInfo.h index 080b842a8..3a2673b4f 100644 --- a/Source/WebCore/rendering/WrapShapeInfo.h +++ b/Source/WebCore/rendering/WrapShapeInfo.h @@ -42,14 +42,6 @@ namespace WebCore { class RenderBlock; -class WrapShapeInfo; - -struct LineSegment { - LayoutUnit logicalLeft; - LayoutUnit logicalRight; -}; - -typedef Vector<LineSegment> SegmentList; class WrapShapeInfo { WTF_MAKE_FAST_ALLOCATED; diff --git a/Source/WebCore/rendering/style/RenderStyle.cpp b/Source/WebCore/rendering/style/RenderStyle.cpp index 0602cfa9b..63d5e0550 100644 --- a/Source/WebCore/rendering/style/RenderStyle.cpp +++ b/Source/WebCore/rendering/style/RenderStyle.cpp @@ -40,6 +40,7 @@ #include "RenderTheme.h" #endif #include "WebCoreMemoryInstrumentation.h" +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/StdLibExtras.h> #include <algorithm> @@ -1615,8 +1616,7 @@ void RenderStyle::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const info.addMember(rareInheritedData); // FIXME: inherited contains StyleImage and Font fields that might need to be instrumented. info.addMember(inherited); - if (m_cachedPseudoStyles) - info.addVectorPtr(m_cachedPseudoStyles.get()); + info.addMember(m_cachedPseudoStyles); #if ENABLE(SVG) info.addMember(m_svgStyle); #endif diff --git a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp index bbe07bfde..ff5c28d9c 100644 --- a/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp +++ b/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp @@ -31,6 +31,7 @@ #include "StyleImage.h" #include "StyleResolver.h" #include "WebCoreMemoryInstrumentation.h" +#include <wtf/MemoryInstrumentationVector.h> namespace WebCore { @@ -306,7 +307,7 @@ void StyleRareNonInheritedData::reportMemoryUsage(MemoryObjectInfo* memoryObject { MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); #if ENABLE(DASHBOARD_SUPPORT) - info.addVector(m_dashboardRegions); + info.addMember(m_dashboardRegions); #endif info.addMember(m_deprecatedFlexibleBox); info.addMember(m_flexibleBox); diff --git a/Source/WebCore/testing/InternalSettings.cpp b/Source/WebCore/testing/InternalSettings.cpp index bd2376607..bb9eed6b1 100755 --- a/Source/WebCore/testing/InternalSettings.cpp +++ b/Source/WebCore/testing/InternalSettings.cpp @@ -100,6 +100,7 @@ InternalSettings::Backup::Backup(Page* page, Settings* settings) , m_canStartMedia(page->canStartMedia()) , m_originalMockScrollbarsEnabled(settings->mockScrollbarsEnabled()) , m_langAttributeAwareFormControlUIEnabled(RuntimeEnabledFeatures::langAttributeAwareFormControlUIEnabled()) + , m_imagesEnabled(settings->areImagesEnabled()) { } @@ -135,6 +136,7 @@ void InternalSettings::Backup::restoreTo(Page* page, Settings* settings) page->setCanStartMedia(m_canStartMedia); settings->setMockScrollbarsEnabled(m_originalMockScrollbarsEnabled); RuntimeEnabledFeatures::setLangAttributeAwareFormControlUIEnabled(m_langAttributeAwareFormControlUIEnabled); + settings->setImagesEnabled(m_imagesEnabled); } InternalSettings* InternalSettings::from(Page* page) @@ -659,4 +661,10 @@ void InternalSettings::setLangAttributeAwareFormControlUIEnabled(bool enabled) RuntimeEnabledFeatures::setLangAttributeAwareFormControlUIEnabled(enabled); } +void InternalSettings::setImagesEnabled(bool enabled, ExceptionCode& ec) +{ + InternalSettingsGuardForSettings(); + settings()->setImagesEnabled(enabled); +} + } diff --git a/Source/WebCore/testing/InternalSettings.h b/Source/WebCore/testing/InternalSettings.h index 2c073df6e..be8810de6 100755 --- a/Source/WebCore/testing/InternalSettings.h +++ b/Source/WebCore/testing/InternalSettings.h @@ -82,6 +82,7 @@ public: bool m_canStartMedia; bool m_originalMockScrollbarsEnabled; bool m_langAttributeAwareFormControlUIEnabled; + bool m_imagesEnabled; }; typedef RefCountedSupplement<Page, InternalSettings> SuperType; @@ -147,6 +148,8 @@ public: void setMemoryInfoEnabled(bool, ExceptionCode&); void setStorageBlockingPolicy(const String&, ExceptionCode&); void setLangAttributeAwareFormControlUIEnabled(bool); + void setImagesEnabled(bool enabled, ExceptionCode&); + private: explicit InternalSettings(Page*); virtual void hostDestroyed() OVERRIDE { m_page = 0; } diff --git a/Source/WebCore/testing/InternalSettings.idl b/Source/WebCore/testing/InternalSettings.idl index 9673d2f1c..d8a8aaf8b 100755 --- a/Source/WebCore/testing/InternalSettings.idl +++ b/Source/WebCore/testing/InternalSettings.idl @@ -82,6 +82,7 @@ module window { #endif void setMemoryInfoEnabled(in boolean enabled) raises(DOMException); void setStorageBlockingPolicy(in DOMString policy) raises(DOMException); + void setImagesEnabled(in boolean enabled) raises(DOMException); }; } diff --git a/Source/WebCore/testing/Internals.cpp b/Source/WebCore/testing/Internals.cpp index 3afb3347a..a213f2faf 100644 --- a/Source/WebCore/testing/Internals.cpp +++ b/Source/WebCore/testing/Internals.cpp @@ -32,6 +32,7 @@ #include "ClientRectList.h" #include "ComposedShadowTreeWalker.h" #include "DOMStringList.h" +#include "DOMWindow.h" #include "Document.h" #include "DocumentMarker.h" #include "DocumentMarkerController.h" @@ -46,9 +47,12 @@ #include "HTMLNames.h" #include "HTMLTextAreaElement.h" #include "HistoryItem.h" +#include "InspectorClient.h" #include "InspectorConsoleAgent.h" #include "InspectorController.h" #include "InspectorCounters.h" +#include "InspectorFrontendChannel.h" +#include "InspectorFrontendClientLocal.h" #include "InspectorInstrumentation.h" #include "InspectorOverlay.h" #include "InstrumentingAgents.h" @@ -105,6 +109,52 @@ namespace WebCore { using namespace HTMLNames; +#if ENABLE(INSPECTOR) +class InspectorFrontendClientDummy : public InspectorFrontendClientLocal { +public: + InspectorFrontendClientDummy(InspectorController*, Page*); + virtual ~InspectorFrontendClientDummy() { } + virtual void attachWindow() OVERRIDE { } + virtual void detachWindow() OVERRIDE { } + + virtual String localizedStringsURL() OVERRIDE { return String(); } + virtual String hiddenPanels() OVERRIDE { return String(); } + + virtual void bringToFront() OVERRIDE { } + virtual void closeWindow() OVERRIDE { } + + virtual void inspectedURLChanged(const String&) OVERRIDE { } + +protected: + virtual void setAttachedWindowHeight(unsigned) OVERRIDE { } +}; + +InspectorFrontendClientDummy::InspectorFrontendClientDummy(InspectorController* controller, Page* page) + : InspectorFrontendClientLocal(controller, page, adoptPtr(new InspectorFrontendClientLocal::Settings())) +{ +} + +class InspectorFrontendChannelDummy : public InspectorFrontendChannel { +public: + explicit InspectorFrontendChannelDummy(Page*); + virtual ~InspectorFrontendChannelDummy() { } + virtual bool sendMessageToFrontend(const String& message) OVERRIDE; + +private: + Page* m_frontendPage; +}; + +InspectorFrontendChannelDummy::InspectorFrontendChannelDummy(Page* page) + : m_frontendPage(page) +{ +} + +bool InspectorFrontendChannelDummy::sendMessageToFrontend(const String& message) +{ + return InspectorClient::doDispatchMessageOnFrontendPage(m_frontendPage, message); +} +#endif // ENABLE(INSPECTOR) + static bool markerTypesFrom(const String& markerType, DocumentMarker::MarkerTypes& result) { if (markerType.isEmpty() || equalIgnoringCase(markerType, "all")) @@ -1061,6 +1111,45 @@ Vector<String> Internals::consoleMessageArgumentCounts(Document* document) const result[i] = String::number(counts[i]); return result; } + +PassRefPtr<DOMWindow> Internals::openDummyInspectorFrontend(const String& url) +{ + Page* page = contextDocument()->frame()->page(); + ASSERT(page); + + DOMWindow* window = page->mainFrame()->document()->domWindow(); + ASSERT(window); + + m_frontendWindow = window->open(url, "", "", window, window); + ASSERT(m_frontendWindow); + + Page* frontendPage = m_frontendWindow->document()->page(); + ASSERT(frontendPage); + + OwnPtr<InspectorFrontendClientDummy> frontendClient = adoptPtr(new InspectorFrontendClientDummy(page->inspectorController(), frontendPage)); + + frontendPage->inspectorController()->setInspectorFrontendClient(frontendClient.release()); + + m_frontendChannel = adoptPtr(new InspectorFrontendChannelDummy(frontendPage)); + + page->inspectorController()->connectFrontend(m_frontendChannel.get()); + + return m_frontendWindow; +} + +void Internals::closeDummyInspectorFrontend() +{ + Page* page = contextDocument()->frame()->page(); + ASSERT(page); + ASSERT(m_frontendWindow); + + page->inspectorController()->disconnectFrontend(); + + m_frontendChannel.release(); + + m_frontendWindow->close(m_frontendWindow->scriptExecutionContext()); + m_frontendWindow.release(); +} #endif // ENABLE(INSPECTOR) bool Internals::hasGrammarMarker(Document* document, int from, int length, ExceptionCode&) diff --git a/Source/WebCore/testing/Internals.h b/Source/WebCore/testing/Internals.h index d2d452ea9..c3c4cb44b 100644 --- a/Source/WebCore/testing/Internals.h +++ b/Source/WebCore/testing/Internals.h @@ -38,10 +38,12 @@ namespace WebCore { class ClientRect; class ClientRectList; class DOMStringList; +class DOMWindow; class Document; class DocumentMarker; class Element; class Frame; +class InspectorFrontendChannelDummy; class InternalSettings; class Node; class PagePopupController; @@ -192,6 +194,8 @@ public: unsigned numberOfLiveNodes() const; unsigned numberOfLiveDocuments() const; Vector<String> consoleMessageArgumentCounts(Document*) const; + PassRefPtr<DOMWindow> openDummyInspectorFrontend(const String& url); + void closeDummyInspectorFrontend(); #endif String counterValue(Element*); @@ -223,6 +227,10 @@ private: Frame* frame() const; DocumentMarker* markerAt(Node*, const String& markerType, unsigned index, ExceptionCode&); +#if ENABLE(INSPECTOR) + RefPtr<DOMWindow> m_frontendWindow; + OwnPtr<InspectorFrontendChannelDummy> m_frontendChannel; +#endif }; } // namespace WebCore diff --git a/Source/WebCore/testing/Internals.idl b/Source/WebCore/testing/Internals.idl index 3bd91299f..f7d0bce70 100644 --- a/Source/WebCore/testing/Internals.idl +++ b/Source/WebCore/testing/Internals.idl @@ -171,6 +171,8 @@ module window { [Conditional=INSPECTOR] unsigned long numberOfLiveNodes(); [Conditional=INSPECTOR] unsigned long numberOfLiveDocuments(); [Conditional=INSPECTOR] sequence<String> consoleMessageArgumentCounts(in Document document); + [Conditional=INSPECTOR] DOMWindow openDummyInspectorFrontend(in DOMString url); + [Conditional=INSPECTOR] void closeDummyInspectorFrontend(); DOMString counterValue(in Element element); long pageNumber(in Element element, in [Optional] float pageWidth, in [Optional] float pageHeight); diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog index 2ed3fd10e..a09e8df0d 100644 --- a/Source/WebKit/ChangeLog +++ b/Source/WebKit/ChangeLog @@ -1,3 +1,16 @@ +2012-09-24 Arvid Nilsson <anilsson@rim.com> + + [BlackBerry] Add cookie database API + https://bugs.webkit.org/show_bug.cgi?id=97102 + + Reviewed by Antonio Gomes. + + Add cookie database file to build system. + + Reviewed internally by Otto D. Cheung. + + * PlatformBlackBerry.cmake: + 2012-09-21 Arvid Nilsson <anilsson@rim.com> [BlackBerry] Remove obsolete compositing surface code diff --git a/Source/WebKit/PlatformBlackBerry.cmake b/Source/WebKit/PlatformBlackBerry.cmake index d75ff91d6..7fdb7eca7 100644 --- a/Source/WebKit/PlatformBlackBerry.cmake +++ b/Source/WebKit/PlatformBlackBerry.cmake @@ -59,6 +59,7 @@ LIST(APPEND WebKit_SOURCES blackberry/Api/BlackBerryGlobal.cpp blackberry/Api/InRegionScroller.cpp blackberry/Api/WebAnimation.cpp + blackberry/Api/WebCookieJar.cpp blackberry/Api/WebKitMIMETypeConverter.cpp blackberry/Api/WebKitTextCodec.cpp blackberry/Api/WebOverlay.cpp diff --git a/Source/WebKit/blackberry/Api/BlackBerryGlobal.cpp b/Source/WebKit/blackberry/Api/BlackBerryGlobal.cpp index d8b5c5124..fc9cd5aae 100644 --- a/Source/WebKit/blackberry/Api/BlackBerryGlobal.cpp +++ b/Source/WebKit/blackberry/Api/BlackBerryGlobal.cpp @@ -20,7 +20,6 @@ #include "BlackBerryGlobal.h" #include "ApplicationCacheStorage.h" -#include "AuthenticationChallengeManager.h" #include "CacheClientBlackBerry.h" #include "CookieManager.h" #include "CrossOriginPreflightResultCache.h" @@ -81,8 +80,6 @@ void globalInitialize() BlackBerry::Platform::Settings* settings = BlackBerry::Platform::Settings::instance(); ImageSource::setMaxPixelsPerDecodedImage(settings->maxPixelsPerDecodedImage()); - - AuthenticationChallengeManager::init(); } void collectJavascriptGarbageNow() diff --git a/Source/WebKit/blackberry/Api/WebCookieJar.cpp b/Source/WebKit/blackberry/Api/WebCookieJar.cpp new file mode 100644 index 000000000..da8964fa8 --- /dev/null +++ b/Source/WebKit/blackberry/Api/WebCookieJar.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + * + * 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 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 + */ + +#include "config.h" + +#include "WebCookieJar.h" + +#include "CookieManager.h" +#include "KURL.h" +#include "WebString.h" + +using namespace WebCore; + +namespace BlackBerry { +namespace WebKit { + +WebCookieJar::WebCookieJar() +{ +} + +std::vector<WebString> WebCookieJar::cookies(const char* url) +{ + KURL kurl = KURL(KURL(), String(url)); + + Vector<ParsedCookie*> rawCookies; + cookieManager().getRawCookies(rawCookies, kurl, WithHttpOnlyCookies); + + std::vector<WebString> result; + for (size_t i = 0; i < rawCookies.size(); ++i) + result.push_back(WebString(rawCookies[i]->toNameValuePair().impl())); + + return result; +} + +void WebCookieJar::setCookies(const char* url, const std::vector<WebString>& cookies) +{ + KURL kurl = KURL(KURL(), String(url)); + Vector<String> coreCookies; + for (size_t i = 0; i < cookies.size(); ++i) + coreCookies.append(String(cookies[i].impl())); + cookieManager().setCookies(kurl, coreCookies, WithHttpOnlyCookies); +} + +} +} diff --git a/Source/WebKit/blackberry/Api/WebCookieJar.h b/Source/WebKit/blackberry/Api/WebCookieJar.h new file mode 100644 index 000000000..0c174e404 --- /dev/null +++ b/Source/WebKit/blackberry/Api/WebCookieJar.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + * + * 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 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 + */ + +#ifndef WebCookieJar_h +#define WebCookieJar_h + +#include "BlackBerryGlobal.h" + +#include <vector> + +namespace BlackBerry { +namespace WebKit { + +class WebPage; +class WebString; + +/** + * Represents the cookie database. + * + * You can obtain an instance of WebCookieJar by calling WebPage::cookieJar(). + */ +class BLACKBERRY_EXPORT WebCookieJar { +public: + /** + * Returns a list of cookies for the URL specified. + * + * All cookies whose domain and path match the provided URL will be returned. + */ + std::vector<WebString> cookies(const char* url); + + /** + * This will add the cookies provided in the list to the cookie database. + * If a cookie with the same name and domain+path as one of the cookies + * provided already exists, it will be replaced. Other cookies that already + * existed will remain. + * + * If no domain and/or path is provided in a cookie, the domain and/or path + * will be inferred from the provided URL. + */ + void setCookies(const char* url, const std::vector<WebString>& cookies); + +private: + friend class WebPage; + + WebCookieJar(); + + // Disable copy constructor and operator=. + WebCookieJar(const WebCookieJar&); + WebCookieJar& operator=(const WebCookieJar&); +}; + +} +} + +#endif // WebCookieJar_h diff --git a/Source/WebKit/blackberry/Api/WebPage.cpp b/Source/WebKit/blackberry/Api/WebPage.cpp index 128075704..78a2858c2 100644 --- a/Source/WebKit/blackberry/Api/WebPage.cpp +++ b/Source/WebKit/blackberry/Api/WebPage.cpp @@ -124,6 +124,7 @@ #include "VibrationClientBlackBerry.h" #endif #include "VisiblePosition.h" +#include "WebCookieJar.h" #if ENABLE(WEBDOM) #include "WebDOMDocument.h" #endif @@ -349,6 +350,7 @@ WebPagePrivate::WebPagePrivate(WebPage* webPage, WebPageClient* client, const In , m_mainFrame(0) // Initialized by init. , m_currentContextNode(0) , m_webSettings(0) // Initialized by init. + , m_cookieJar(0) , m_visible(false) , m_activationState(ActivationActive) , m_shouldResetTilesWhenShown(false) @@ -427,8 +429,6 @@ WebPagePrivate::WebPagePrivate(WebPage* webPage, WebPageClient* client, const In BlackBerry::Platform::DeviceInfo::instance(); defaultUserAgent(); } - - AuthenticationChallengeManager::instance()->pageCreated(this); } WebPage::WebPage(WebPageClient* client, const WebString& pageGroupName, const Platform::IntRect& rect) @@ -440,7 +440,6 @@ WebPage::WebPage(WebPageClient* client, const WebString& pageGroupName, const Pl WebPagePrivate::~WebPagePrivate() { - AuthenticationChallengeManager::instance()->pageDeleted(this); // Hand the backingstore back to another owner if necessary. m_webPage->setVisible(false); if (BackingStorePrivate::currentBackingStoreOwner() == m_webPage) @@ -449,6 +448,9 @@ WebPagePrivate::~WebPagePrivate() delete m_webSettings; m_webSettings = 0; + delete m_cookieJar; + m_cookieJar = 0; + delete m_backingStoreClient; m_backingStoreClient = 0; m_backingStore = 0; @@ -2213,19 +2215,18 @@ bool WebPagePrivate::isActive() const return m_client->isActive(); } -void WebPagePrivate::authenticationChallenge(const KURL& url, const ProtectionSpace& protectionSpace, const Credential& inputCredential) +void WebPagePrivate::authenticationChallenge(const KURL& url, const ProtectionSpace& protectionSpace, const Credential& inputCredential, AuthenticationChallengeClient* client) { WebString username; WebString password; - AuthenticationChallengeManager* authmgr = AuthenticationChallengeManager::instance(); #if !defined(PUBLIC_BUILD) || !PUBLIC_BUILD if (m_dumpRenderTree) { Credential credential(inputCredential, inputCredential.persistence()); if (m_dumpRenderTree->didReceiveAuthenticationChallenge(credential)) - authmgr->notifyChallengeResult(url, protectionSpace, AuthenticationChallengeSuccess, credential); + client->notifyChallengeResult(url, protectionSpace, AuthenticationChallengeSuccess, credential); else - authmgr->notifyChallengeResult(url, protectionSpace, AuthenticationChallengeCancelled, inputCredential); + client->notifyChallengeResult(url, protectionSpace, AuthenticationChallengeCancelled, inputCredential); return; } #endif @@ -2246,9 +2247,9 @@ void WebPagePrivate::authenticationChallenge(const KURL& url, const ProtectionSp #endif if (isConfirmed) - authmgr->notifyChallengeResult(url, protectionSpace, AuthenticationChallengeSuccess, credential); + client->notifyChallengeResult(url, protectionSpace, AuthenticationChallengeSuccess, credential); else - authmgr->notifyChallengeResult(url, protectionSpace, AuthenticationChallengeCancelled, inputCredential); + client->notifyChallengeResult(url, protectionSpace, AuthenticationChallengeCancelled, inputCredential); } PageClientBlackBerry::SaveCredentialType WebPagePrivate::notifyShouldSaveCredential(bool isNew) @@ -3191,6 +3192,14 @@ WebSettings* WebPage::settings() const return d->m_webSettings; } +WebCookieJar* WebPage::cookieJar() const +{ + if (!d->m_cookieJar) + d->m_cookieJar = new WebCookieJar(); + + return d->m_cookieJar; +} + bool WebPage::isVisible() const { return d->m_visible; @@ -3240,7 +3249,6 @@ void WebPage::setVisible(bool visible) return; d->setVisible(visible); - AuthenticationChallengeManager::instance()->pageVisibilityChanged(d, visible); if (!visible) { d->suspendBackingStore(); diff --git a/Source/WebKit/blackberry/Api/WebPage.h b/Source/WebKit/blackberry/Api/WebPage.h index 20c48f00e..31b990808 100644 --- a/Source/WebKit/blackberry/Api/WebPage.h +++ b/Source/WebKit/blackberry/Api/WebPage.h @@ -66,6 +66,7 @@ class BackingStoreClient; class BackingStorePrivate; class InRegionScroller; class RenderQueue; +class WebCookieJar; class WebOverlay; class WebPageClient; class WebPageCompositor; @@ -127,6 +128,8 @@ public: WebSettings* settings() const; + WebCookieJar* cookieJar() const; + void setVisible(bool); bool isVisible() const; diff --git a/Source/WebKit/blackberry/Api/WebPage_p.h b/Source/WebKit/blackberry/Api/WebPage_p.h index bcb7d5009..ca0c180c0 100644 --- a/Source/WebKit/blackberry/Api/WebPage_p.h +++ b/Source/WebKit/blackberry/Api/WebPage_p.h @@ -77,6 +77,7 @@ class InPageSearchManager; class InputHandler; class SelectionHandler; class TouchEventHandler; +class WebCookieJar; class WebPageClient; #if USE(ACCELERATED_COMPOSITING) @@ -201,7 +202,7 @@ public: virtual int showAlertDialog(WebPageClient::AlertType atype); virtual bool isActive() const; virtual bool isVisible() const { return m_visible; } - virtual void authenticationChallenge(const WebCore::KURL&, const WebCore::ProtectionSpace&, const WebCore::Credential&); + virtual void authenticationChallenge(const WebCore::KURL&, const WebCore::ProtectionSpace&, const WebCore::Credential&, WebCore::AuthenticationChallengeClient*); virtual SaveCredentialType notifyShouldSaveCredential(bool); virtual void syncProxyCredential(const WebCore::Credential&); @@ -469,6 +470,7 @@ public: WebCore::Frame* m_mainFrame; RefPtr<WebCore::Node> m_currentContextNode; WebSettings* m_webSettings; + WebCookieJar* m_cookieJar; OwnPtr<WebTapHighlight> m_tapHighlight; WebSelectionOverlay* m_selectionOverlay; diff --git a/Source/WebKit/blackberry/Api/WebString.cpp b/Source/WebKit/blackberry/Api/WebString.cpp index 640b673c9..0e75fc1a6 100644 --- a/Source/WebKit/blackberry/Api/WebString.cpp +++ b/Source/WebKit/blackberry/Api/WebString.cpp @@ -65,6 +65,11 @@ WebString WebString::fromUtf8(const char* utf8) return String::fromUTF8(utf8); } +WebString WebString::fromUtf8(const char* utf8, size_t length) +{ + return String::fromUTF8(utf8, length); +} + WebString& WebString::operator=(const WebString& str) { if (&str == this) diff --git a/Source/WebKit/blackberry/Api/WebString.h b/Source/WebKit/blackberry/Api/WebString.h index fe43c247f..c2af16b79 100644 --- a/Source/WebKit/blackberry/Api/WebString.h +++ b/Source/WebKit/blackberry/Api/WebString.h @@ -41,6 +41,7 @@ public: WebString& operator=(const WebString&); std::string utf8() const; static WebString fromUtf8(const char* utf8); + static WebString fromUtf8(const char* utf8, size_t length); const unsigned short* characters() const; unsigned length() const; bool isEmpty() const; diff --git a/Source/WebKit/blackberry/ChangeLog b/Source/WebKit/blackberry/ChangeLog index ed5687843..c32d3c4f3 100644 --- a/Source/WebKit/blackberry/ChangeLog +++ b/Source/WebKit/blackberry/ChangeLog @@ -1,3 +1,88 @@ +2012-09-24 Mark Lam <mark.lam@apple.com> + + Deleting the classic interpreter and cleaning up some build options. + https://bugs.webkit.org/show_bug.cgi?id=96969. + + Reviewed by Geoffrey Garen. + + * WebCoreSupport/AboutDataEnableFeatures.in: + +2012-09-24 Benjamin Poulain <bpoulain@apple.com> + + Fix Geolocation error reporting in the test support + https://bugs.webkit.org/show_bug.cgi?id=97386 + + Reviewed by Sam Weinig. + + * WebKitSupport/DumpRenderTreeSupport.cpp: + (DumpRenderTreeSupport::setMockGeolocationPositionUnavailableError): + * WebKitSupport/DumpRenderTreeSupport.h: + (DumpRenderTreeSupport): + +2012-09-24 Otto Derek Cheung <otcheung@rim.com> + + [BlackBerry] Reverting implementation for 407 error pages + https://bugs.webkit.org/show_bug.cgi?id=97455 + + Reviewed by Rob Buis. + + Revert "[BlackBerry] Really fix bug 95488 that user can get the + authentication challenge dialog while the other tab has focus." + https://bugs.webkit.org/show_bug.cgi?id=97348 + + This reverts commit 0cffe01961fb80204138505bcec29a83818efb73. + + * Api/BlackBerryGlobal.cpp: + (BlackBerry::WebKit::globalInitialize): + * Api/WebPage.cpp: + (BlackBerry::WebKit::WebPagePrivate::WebPagePrivate): + (BlackBerry::WebKit::WebPagePrivate::~WebPagePrivate): + (BlackBerry::WebKit::WebPagePrivate::authenticationChallenge): + (BlackBerry::WebKit::WebPage::setVisible): + * Api/WebPage_p.h: + (WebPagePrivate): + +2012-09-24 Arvid Nilsson <anilsson@rim.com> + + [BlackBerry] Add cookie database API + https://bugs.webkit.org/show_bug.cgi?id=97102 + + Reviewed by Antonio Gomes. + + The cookie database is exposed through WebCookieJar, which has only two + methods: cookies() and setCookies(). + + Also add a new WebString::fromUTF8 overload that takes a const char* + and a length, in order to avoid a strlen call when converting from + other string classes to WebString. This is useful for callers of the + new cookie API when converting cookies to WebString. + + Reviewed internally by Otto D. Cheung. + + PR 209282 + + * Api/WebCookieJar.cpp: Added. + (WebKit): + (BlackBerry::WebKit::WebCookieJar::WebCookieJar): + (BlackBerry::WebKit::WebCookieJar::cookies): + (BlackBerry::WebKit::WebCookieJar::setCookies): + * Api/WebCookieJar.h: Added. + (WebKit): + * Api/WebPage.cpp: + (BlackBerry::WebKit::WebPagePrivate::WebPagePrivate): + (BlackBerry::WebKit::WebPagePrivate::~WebPagePrivate): + (BlackBerry::WebKit::WebPage::cookieJar): + (WebKit): + * Api/WebPage.h: + (WebKit): + * Api/WebPage_p.h: + (WebKit): + (WebPagePrivate): + * Api/WebString.cpp: + (BlackBerry::WebKit::WebString::fromUtf8): + (WebKit): + * Api/WebString.h: + 2012-09-21 Lianghui Chen <liachen@rim.com> [BlackBerry] Really fix bug 95488 that user can get the authentication challenge dialog while the other tab has focus. diff --git a/Source/WebKit/blackberry/WebCoreSupport/AboutDataEnableFeatures.in b/Source/WebKit/blackberry/WebCoreSupport/AboutDataEnableFeatures.in index 45986026b..6b0ba389d 100644 --- a/Source/WebKit/blackberry/WebCoreSupport/AboutDataEnableFeatures.in +++ b/Source/WebKit/blackberry/WebCoreSupport/AboutDataEnableFeatures.in @@ -12,11 +12,9 @@ BLOB BRANCH_COMPACTION CALENDAR_PICKER CHANNEL_MESSAGING -CLASSIC_INTERPRETER CODEBLOCK_SAMPLING COMPARE_AND_SWAP COMPUTED_GOTO -COMPUTED_GOTO_CLASSIC_INTERPRETER COMPUTED_GOTO_INTERPRETER CONSISTENCY_CHECK CONTEXT_MENUS diff --git a/Source/WebKit/blackberry/WebKitSupport/DumpRenderTreeSupport.cpp b/Source/WebKit/blackberry/WebKitSupport/DumpRenderTreeSupport.cpp index e4e4ef0c0..ea4ac5601 100644 --- a/Source/WebKit/blackberry/WebKitSupport/DumpRenderTreeSupport.cpp +++ b/Source/WebKit/blackberry/WebKitSupport/DumpRenderTreeSupport.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + * Copyright (C) 2012 Apple Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -95,20 +96,10 @@ void DumpRenderTreeSupport::resetGeolocationMock(WebPage* webPage) mockClient->reset(); } -void DumpRenderTreeSupport::setMockGeolocationError(WebPage* webPage, int errorCode, const String message) +void DumpRenderTreeSupport::setMockGeolocationPositionUnavailableError(WebPage* webPage, const String message) { - GeolocationError::ErrorCode code = GeolocationError::PositionUnavailable; - switch (errorCode) { - case PositionError::PERMISSION_DENIED: - code = GeolocationError::PermissionDenied; - break; - case PositionError::POSITION_UNAVAILABLE: - code = GeolocationError::PositionUnavailable; - break; - } - GeolocationClientMock* mockClient = static_cast<GeolocationClientMock*>(GeolocationController::from(corePage(webPage))->client()); - mockClient->setError(GeolocationError::create(code, message)); + mockClient->setPositionUnavailableError(message); } void DumpRenderTreeSupport::setMockGeolocationPermission(WebPage* webPage, bool allowed) diff --git a/Source/WebKit/blackberry/WebKitSupport/DumpRenderTreeSupport.h b/Source/WebKit/blackberry/WebKitSupport/DumpRenderTreeSupport.h index 58fc1b53e..01fe4f83a 100644 --- a/Source/WebKit/blackberry/WebKitSupport/DumpRenderTreeSupport.h +++ b/Source/WebKit/blackberry/WebKitSupport/DumpRenderTreeSupport.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + * Copyright (C) 2012 Apple Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -52,7 +53,7 @@ public: static int numberOfPendingGeolocationPermissionRequests(BlackBerry::WebKit::WebPage*); static void resetGeolocationMock(BlackBerry::WebKit::WebPage*); - static void setMockGeolocationError(BlackBerry::WebKit::WebPage*, int errorCode, const WTF::String message); + static void setMockGeolocationPositionUnavailableError(BlackBerry::WebKit::WebPage*, const WTF::String message); static void setMockGeolocationPermission(BlackBerry::WebKit::WebPage*, bool allowed); static void setMockGeolocationPosition(BlackBerry::WebKit::WebPage*, double latitude, double longitude, double accuracy); static void scalePageBy(BlackBerry::WebKit::WebPage*, float, float, float); diff --git a/Source/WebKit/chromium/ChangeLog b/Source/WebKit/chromium/ChangeLog index 340eed6af..b216df91a 100644 --- a/Source/WebKit/chromium/ChangeLog +++ b/Source/WebKit/chromium/ChangeLog @@ -1,3 +1,121 @@ +2012-09-21 Ilya Tikhonovsky <loislo@chromium.org> + + Web Inspector: extract Vector instrumentation from core NMI code into MemoryInstrumentationVector.h header. + https://bugs.webkit.org/show_bug.cgi?id=96650 + + Reviewed by Vsevolod Vlasov. + + Test for instrumented vector. + + * tests/MemoryInstrumentationTest.cpp: + (WebCore::InstrumentedOwner::InstrumentedOwner): + (WebCore::TEST): + (WebCore): + +2012-09-24 Benjamin Poulain <bpoulain@apple.com> + + Fix Geolocation error reporting in the test support + https://bugs.webkit.org/show_bug.cgi?id=97386 + + Reviewed by Sam Weinig. + + * public/WebGeolocationClientMock.h: + (WebGeolocationClientMock): + * src/WebGeolocationClientMock.cpp: + (WebKit::WebGeolocationClientMock::setMockGeolocationPositionUnavailableError): + +2012-09-24 Kent Tamura <tkent@chromium.org> + + [Chromium] Implement ValidationMessageClient for Chromium + https://bugs.webkit.org/show_bug.cgi?id=97167 + + Reviewed by Hajime Morita. + + Introduce ValidationMessageClientImpl. However actual popup + implementation should be done in WebViewClient. + + * WebKit.gyp: Add ValidationMessageClientImpl.{cpp,h}. + * public/WebViewClient.h: + (WebKit::WebViewClient::showValidationMessage): Added. + (WebKit::WebViewClient::hideValidationMessage): Added. + * src/ValidationMessageClientImpl.cpp: Added. + (WebKit::ValidationMessageClientImpl::ValidationMessageClientImpl): + (WebKit::ValidationMessageClientImpl::create): + (WebKit::ValidationMessageClientImpl::~ValidationMessageClientImpl): + Make sure that a popup is closed. + (WebKit::ValidationMessageClientImpl::showValidationMessage): + Implementataion of ValidationMessageClient::showValidationMessage. + minimumSecondToShowValidationMessage and secondPerCharacter are same as + the corresponding values in the current Shadow DOM implementation. + (WebKit::ValidationMessageClientImpl::hideValidationMessage): + Implementataion of ValidationMessageClient::hideValidationMessage. + (WebKit::ValidationMessageClientImpl::isValidationMessageVisible): + Implementataion of ValidationMessageClient::isValidationMessageVisible. + (WebKit::ValidationMessageClientImpl::hideCurrentValidationMessage): + This is a callback function for the timer. + * src/ValidationMessageClientImpl.h: Added. + + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::WebViewImpl): + - Initialize m_validationMessage. + - Add a comment for PageClients. + * src/WebViewImpl.h: + Add m_validationMessage. + +2012-09-24 Mihai Parparita <mihaip@chromium.org> + + [Chromium] Remove WebRuntimeFeatures::{enablePushState,isPushStateEnabled} + https://bugs.webkit.org/show_bug.cgi?id=97506 + + Reviewed by Adam Barth. + + These methods have been no-ops since r127674. All Chromium code that + called them was removed with http://crrev.com/155205. + + * public/WebRuntimeFeatures.h: + (WebRuntimeFeatures): + * src/WebRuntimeFeatures.cpp: + +2012-09-24 Mark Pilgrim <pilgrim@chromium.org> + + [Chromium][Mac] Remove loadFont from PlatformSupport + https://bugs.webkit.org/show_bug.cgi?id=97360 + + Reviewed by Adam Barth. + + Part of a refactoring series. See tracking bug 82948. + + * src/PlatformSupport.cpp: + (WebCore): + +2012-09-24 Tony Chang <tony@chromium.org> + + Unreviewed. Rolled DEPS. + + * DEPS: + +2012-09-24 Dana Jansens <danakj@chromium.org> + + [chromium] Add setters to WebFilterOperation for IPC pickling + https://bugs.webkit.org/show_bug.cgi?id=97147 + + Reviewed by James Robinson. + + * tests/FilterOperationsTest.cpp: + (WebKit): + (WebKit::TEST): + +2012-09-24 Patrick Gansterer <paroga@webkit.org> + + Remove remaining WTF_DEPRECATED_STRING_OPERATORS from cpp files + https://bugs.webkit.org/show_bug.cgi?id=97412 + + Reviewed by Adam Barth. + + * src/WebPageSerializerImpl.cpp: + (WebKit::WebPageSerializerImpl::openTagToString): Replaced operator+= with StringBuilder::append(). + (WebKit::WebPageSerializerImpl::endTagToString): Ditto. + 2012-09-24 Yury Semikhatsky <yurys@chromium.org> Unreviewed, rolling out r122243. diff --git a/Source/WebKit/chromium/DEPS b/Source/WebKit/chromium/DEPS index 5f3d4b55e..f5ee44aef 100644 --- a/Source/WebKit/chromium/DEPS +++ b/Source/WebKit/chromium/DEPS @@ -32,7 +32,7 @@ vars = { 'chromium_svn': 'http://src.chromium.org/svn/trunk/src', - 'chromium_rev': '158095' + 'chromium_rev': '158289' } deps = { diff --git a/Source/WebKit/chromium/WebKit.gyp b/Source/WebKit/chromium/WebKit.gyp index ad86d1a9e..f4f4c9ece 100644 --- a/Source/WebKit/chromium/WebKit.gyp +++ b/Source/WebKit/chromium/WebKit.gyp @@ -467,6 +467,8 @@ 'src/TextFieldDecoratorImpl.cpp', 'src/UserMediaClientImpl.h', 'src/UserMediaClientImpl.cpp', + 'src/ValidationMessageClientImpl.cpp', + 'src/ValidationMessageClientImpl.h', 'src/WebTextCheckingCompletionImpl.h', 'src/WebTextCheckingCompletionImpl.cpp', 'src/WebTextCheckingResult.cpp', diff --git a/Source/WebKit/chromium/public/WebGeolocationClientMock.h b/Source/WebKit/chromium/public/WebGeolocationClientMock.h index 052a546ad..a04d1ddde 100644 --- a/Source/WebKit/chromium/public/WebGeolocationClientMock.h +++ b/Source/WebKit/chromium/public/WebGeolocationClientMock.h @@ -49,7 +49,7 @@ public: ~WebGeolocationClientMock() { reset(); } WEBKIT_EXPORT void setPosition(double latitude, double longitude, double accuracy); - WEBKIT_EXPORT void setError(int errorCode, const WebString& message); + WEBKIT_EXPORT void setPositionUnavailableError(const WebString& message); WEBKIT_EXPORT void setPermission(bool); WEBKIT_EXPORT int numberOfPendingPermissionRequests() const; WEBKIT_EXPORT void resetMock(); diff --git a/Source/WebKit/chromium/public/WebRuntimeFeatures.h b/Source/WebKit/chromium/public/WebRuntimeFeatures.h index 6d0629fea..64cf829b5 100644 --- a/Source/WebKit/chromium/public/WebRuntimeFeatures.h +++ b/Source/WebKit/chromium/public/WebRuntimeFeatures.h @@ -76,10 +76,6 @@ public: WEBKIT_EXPORT static void enableWebAudio(bool); WEBKIT_EXPORT static bool isWebAudioEnabled(); - // TODO: Remove these (since they're no-ops) once Chromium code stops calling them. - WEBKIT_EXPORT static void enablePushState(bool); - WEBKIT_EXPORT static bool isPushStateEnabled(bool); - WEBKIT_EXPORT static void enableTouch(bool); WEBKIT_EXPORT static bool isTouchEnabled(); diff --git a/Source/WebKit/chromium/public/WebViewClient.h b/Source/WebKit/chromium/public/WebViewClient.h index 88da1416b..da6498d30 100644 --- a/Source/WebKit/chromium/public/WebViewClient.h +++ b/Source/WebKit/chromium/public/WebViewClient.h @@ -293,6 +293,13 @@ public: // Return true to swallow the input event if the embedder will start a disambiguation popup virtual bool didTapMultipleTargets(const WebGestureEvent&, const WebVector<WebRect>& targetRects) { return false; } + // Show a notification popup for the specified form vaidation messages + // besides the anchor rectangle. An implementation of this function should + // not hide the popup until hideValidationMessage call. + virtual void showValidationMessage(const WebRect& anchorInScreen, const WebString& mainText, const WebString& supplementalText, WebTextDirection hint) { } + // Hide notifation popup for form validation messages. + virtual void hideValidationMessage() { } + // Session history ----------------------------------------------------- // Tells the embedder to navigate back or forward in session history by diff --git a/Source/WebKit/chromium/src/PlatformSupport.cpp b/Source/WebKit/chromium/src/PlatformSupport.cpp index 8d0df4d44..7cd6453f6 100644 --- a/Source/WebKit/chromium/src/PlatformSupport.cpp +++ b/Source/WebKit/chromium/src/PlatformSupport.cpp @@ -217,24 +217,6 @@ bool PlatformSupport::ensureFontLoaded(HFONT font) } #endif -#if OS(DARWIN) -bool PlatformSupport::loadFont(NSFont* srcFont, CGFontRef* out, uint32_t* fontID) -{ - WebSandboxSupport* ss = WebKit::Platform::current()->sandboxSupport(); - if (ss) - return ss->loadFont(srcFont, out, fontID); - - // This function should only be called in response to an error loading a - // font due to being blocked by the sandbox. - // This by definition shouldn't happen if there is no sandbox support. - ASSERT_NOT_REACHED(); - *out = 0; - *fontID = 0; - return false; -} -#elif OS(UNIX) -#endif - // Indexed Database ----------------------------------------------------------- PassRefPtr<IDBFactoryBackendInterface> PlatformSupport::idbFactory() diff --git a/Source/WebKit/chromium/src/ValidationMessageClientImpl.cpp b/Source/WebKit/chromium/src/ValidationMessageClientImpl.cpp new file mode 100644 index 000000000..5ea79297f --- /dev/null +++ b/Source/WebKit/chromium/src/ValidationMessageClientImpl.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2012 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 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 "ValidationMessageClientImpl.h" + +#include "Element.h" +#include "FrameView.h" +#include "RenderObject.h" +#include "WebTextDirection.h" +#include "WebViewClient.h" + +using namespace WebCore; + +namespace WebKit { + +ValidationMessageClientImpl::ValidationMessageClientImpl(WebViewClient& client) + : m_client(client) + , m_currentAnchor(0) + , m_timer(this, &ValidationMessageClientImpl::hideCurrentValidationMessage) +{ +} + +PassOwnPtr<ValidationMessageClientImpl> ValidationMessageClientImpl::create(WebViewClient& client) +{ + return adoptPtr(new ValidationMessageClientImpl(client)); +} + +ValidationMessageClientImpl::~ValidationMessageClientImpl() +{ + if (m_currentAnchor) + hideValidationMessage(*m_currentAnchor); +} + +void ValidationMessageClientImpl::showValidationMessage(const Element& anchor, const String& message) +{ + if (message.isEmpty()) { + hideValidationMessage(anchor); + return; + } + if (!anchor.renderBox()) + return; + if (m_currentAnchor) + hideValidationMessage(*m_currentAnchor); + m_currentAnchor = &anchor; + IntRect anchorInScreen = anchor.document()->view()->contentsToScreen(anchor.pixelSnappedBoundingBox()); + WebTextDirection dir = anchor.renderer()->style()->direction() == RTL ? WebTextDirectionRightToLeft : WebTextDirectionLeftToRight; + m_client.showValidationMessage(anchorInScreen, message, anchor.fastGetAttribute(HTMLNames::titleAttr), dir); + + const double minimumSecondToShowValidationMessage = 5.0; + const double secondPerCharacter = 0.05; + m_timer.startOneShot(std::max(minimumSecondToShowValidationMessage, message.length() * secondPerCharacter)); +} + +void ValidationMessageClientImpl::hideValidationMessage(const Element& anchor) +{ + if (!m_currentAnchor || !isValidationMessageVisible(anchor)) + return; + m_timer.stop(); + m_client.hideValidationMessage(); + m_currentAnchor = 0; +} + +bool ValidationMessageClientImpl::isValidationMessageVisible(const Element& anchor) +{ + return m_currentAnchor == &anchor; +} + +void ValidationMessageClientImpl::hideCurrentValidationMessage(Timer<ValidationMessageClientImpl>*) +{ + ASSERT(m_currentAnchor); + hideValidationMessage(*m_currentAnchor); +} + +} diff --git a/Source/WebKit/chromium/src/ValidationMessageClientImpl.h b/Source/WebKit/chromium/src/ValidationMessageClientImpl.h new file mode 100644 index 000000000..0206bba47 --- /dev/null +++ b/Source/WebKit/chromium/src/ValidationMessageClientImpl.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 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 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 ValidationMessageClientImpl_h +#define ValidationMessageClientImpl_h + +#include "Timer.h" +#include "ValidationMessageClient.h" + +namespace WebKit { + +class WebViewClient; + +class ValidationMessageClientImpl : public WebCore::ValidationMessageClient { +public: + static PassOwnPtr<ValidationMessageClientImpl> create(WebViewClient&); + virtual ~ValidationMessageClientImpl(); + +private: + explicit ValidationMessageClientImpl(WebViewClient&); + void hideCurrentValidationMessage(WebCore::Timer<ValidationMessageClientImpl>*); + + virtual void showValidationMessage(const WebCore::Element& anchor, const String& message) OVERRIDE; + virtual void hideValidationMessage(const WebCore::Element& anchor) OVERRIDE; + virtual bool isValidationMessageVisible(const WebCore::Element& anchor) OVERRIDE; + + WebViewClient& m_client; + const WebCore::Element* m_currentAnchor; + WebCore::Timer<ValidationMessageClientImpl> m_timer; +}; + +} + +#endif diff --git a/Source/WebKit/chromium/src/WebDocument.cpp b/Source/WebKit/chromium/src/WebDocument.cpp index 691701715..3486613be 100644 --- a/Source/WebKit/chromium/src/WebDocument.cpp +++ b/Source/WebKit/chromium/src/WebDocument.cpp @@ -35,6 +35,7 @@ #include "CSSParserMode.h" #include "Document.h" #include "DocumentLoader.h" +#include "DocumentStyleSheetCollection.h" #include "DocumentType.h" #include "Element.h" #include "HTMLAllCollection.h" @@ -196,7 +197,7 @@ void WebDocument::insertUserStyleSheet(const WebString& sourceCode, UserStyleLev RefPtr<StyleSheetContents> parsedSheet = StyleSheetContents::create(document.get()); parsedSheet->setIsUserStyleSheet(level == UserStyleUserLevel); parsedSheet->parseString(sourceCode); - document->addUserSheet(parsedSheet.release()); + document->styleSheetCollection()->addUserSheet(parsedSheet.release()); } void WebDocument::cancelFullScreen() diff --git a/Source/WebKit/chromium/src/WebGeolocationClientMock.cpp b/Source/WebKit/chromium/src/WebGeolocationClientMock.cpp index 3d9630707..a7948a78e 100644 --- a/Source/WebKit/chromium/src/WebGeolocationClientMock.cpp +++ b/Source/WebKit/chromium/src/WebGeolocationClientMock.cpp @@ -41,6 +41,7 @@ #include "WebGeolocationError.h" #include "WebGeolocationPermissionRequest.h" #include "WebGeolocationPosition.h" +#include "platform/WebString.h" using namespace WebCore; @@ -58,23 +59,9 @@ void WebGeolocationClientMock::setPosition(double latitude, double longitude, do m_clientMock->setPosition(webPosition); } -void WebGeolocationClientMock::setError(int errorCode, const WebString& message) +void WebGeolocationClientMock::setPositionUnavailableError(const WebString& message) { - WebGeolocationError::Error code; - switch (errorCode) { - case PositionError::PERMISSION_DENIED: - code = WebGeolocationError::ErrorPermissionDenied; - break; - case PositionError::POSITION_UNAVAILABLE: - code = WebGeolocationError::ErrorPositionUnavailable; - break; - default: - ASSERT_NOT_REACHED(); - return; - } - - WebGeolocationError webError(code, message); - m_clientMock->setError(webError); + m_clientMock->setPositionUnavailableError(message); } void WebGeolocationClientMock::setPermission(bool allowed) diff --git a/Source/WebKit/chromium/src/WebPageSerializerImpl.cpp b/Source/WebKit/chromium/src/WebPageSerializerImpl.cpp index 793ca8b83..02a665a11 100644 --- a/Source/WebKit/chromium/src/WebPageSerializerImpl.cpp +++ b/Source/WebKit/chromium/src/WebPageSerializerImpl.cpp @@ -75,8 +75,6 @@ // override the incorrect base URL and make sure we alway load correct local // saved resource files. -#define WTF_DEPRECATED_STRING_OPERATORS - #include "config.h" #include "WebPageSerializerImpl.h" @@ -300,23 +298,24 @@ void WebPageSerializerImpl::encodeAndFlushBuffer( void WebPageSerializerImpl::openTagToString(Element* element, SerializeDomParam* param) { - // FIXME: use StringBuilder instead of String. bool needSkip; + StringBuilder result; // Do pre action for open tag. - String result = preActionBeforeSerializeOpenTag(element, param, &needSkip); + result.append(preActionBeforeSerializeOpenTag(element, param, &needSkip)); if (needSkip) return; // Add open tag - result += "<" + element->nodeName().lower(); + result.append('<'); + result.append(element->nodeName().lower()); // Go through all attributes and serialize them. if (element->hasAttributes()) { unsigned numAttrs = element->attributeCount(); for (unsigned i = 0; i < numAttrs; i++) { - result += " "; + result.append(' '); // Add attribute pair const Attribute *attribute = element->attributeItem(i); - result += attribute->name().toString(); - result += "=\""; + result.append(attribute->name().toString()); + result.appendLiteral("=\""); if (!attribute->value().isEmpty()) { const String& attrValue = attribute->value(); @@ -326,7 +325,7 @@ void WebPageSerializerImpl::openTagToString(Element* element, if (elementHasLegalLinkAttribute(element, attrName)) { // For links start with "javascript:", we do not change it. if (attrValue.startsWith("javascript:", false)) - result += attrValue; + result.append(attrValue); else { // Get the absolute link WebFrameImpl* subFrame = WebFrameImpl::fromFrameOwnerElement(element); @@ -334,20 +333,23 @@ void WebPageSerializerImpl::openTagToString(Element* element, param->document->completeURL(attrValue); // Check whether we have local files for those link. if (m_localLinks.contains(completeURL)) { - if (!param->directoryName.isEmpty()) - result += "./" + param->directoryName + "/"; - result += m_localLinks.get(completeURL); + if (!param->directoryName.isEmpty()) { + result.appendLiteral("./"); + result.append(param->directoryName); + result.append('/'); + } + result.append(m_localLinks.get(completeURL)); } else - result += completeURL; + result.append(completeURL); } } else { if (param->isHTMLDocument) - result += m_htmlEntities.convertEntitiesInString(attrValue); + result.append(m_htmlEntities.convertEntitiesInString(attrValue)); else - result += m_xmlEntities.convertEntitiesInString(attrValue); + result.append(m_xmlEntities.convertEntitiesInString(attrValue)); } } - result += "\""; + result.append('\"'); } } @@ -355,11 +357,11 @@ void WebPageSerializerImpl::openTagToString(Element* element, String addedContents = postActionAfterSerializeOpenTag(element, param); // Complete the open tag for element when it has child/children. if (element->hasChildNodes() || param->haveAddedContentsBeforeEnd) - result += ">"; + result.append('>'); // Append the added contents generate in post action of open tag. - result += addedContents; + result.append(addedContents); // Save the result to data buffer. - saveHTMLContentToBuffer(result, param); + saveHTMLContentToBuffer(result.toString(), param); } // Serialize end tag of an specified element. @@ -367,37 +369,36 @@ void WebPageSerializerImpl::endTagToString(Element* element, SerializeDomParam* param) { bool needSkip; + StringBuilder result; // Do pre action for end tag. - String result = preActionBeforeSerializeEndTag(element, - param, - &needSkip); + result.append(preActionBeforeSerializeEndTag(element, param, &needSkip)); if (needSkip) return; // Write end tag when element has child/children. if (element->hasChildNodes() || param->haveAddedContentsBeforeEnd) { - result += "</"; - result += element->nodeName().lower(); - result += ">"; + result.appendLiteral("</"); + result.append(element->nodeName().lower()); + result.append('>'); } else { // Check whether we have to write end tag for empty element. if (param->isHTMLDocument) { - result += ">"; + result.append('>'); // FIXME: This code is horribly wrong. WebPageSerializerImpl must die. if (!static_cast<const HTMLElement*>(element)->ieForbidsInsertHTML()) { // We need to write end tag when it is required. - result += "</"; - result += element->nodeName().lower(); - result += ">"; + result.appendLiteral("</"); + result.append(element->nodeName().lower()); + result.append('>'); } } else { // For xml base document. - result += " />"; + result.appendLiteral(" />"); } } // Do post action for end tag. - result += postActionAfterSerializeEndTag(element, param); + result.append(postActionAfterSerializeEndTag(element, param)); // Save the result to data buffer. - saveHTMLContentToBuffer(result, param); + saveHTMLContentToBuffer(result.toString(), param); } void WebPageSerializerImpl::buildContentForNode(Node* node, diff --git a/Source/WebKit/chromium/src/WebRuntimeFeatures.cpp b/Source/WebKit/chromium/src/WebRuntimeFeatures.cpp index bcdba86c1..4e64c664b 100644 --- a/Source/WebKit/chromium/src/WebRuntimeFeatures.cpp +++ b/Source/WebKit/chromium/src/WebRuntimeFeatures.cpp @@ -204,15 +204,6 @@ bool WebRuntimeFeatures::isWebAudioEnabled() #endif } -void WebRuntimeFeatures::enablePushState(bool) -{ -} - -bool WebRuntimeFeatures::isPushStateEnabled(bool enable) -{ - return true; -} - void WebRuntimeFeatures::enableTouch(bool enable) { #if ENABLE(TOUCH_EVENTS) diff --git a/Source/WebKit/chromium/src/WebViewImpl.cpp b/Source/WebKit/chromium/src/WebViewImpl.cpp index 764ae6dca..6666571b3 100644 --- a/Source/WebKit/chromium/src/WebViewImpl.cpp +++ b/Source/WebKit/chromium/src/WebViewImpl.cpp @@ -120,6 +120,7 @@ #include "TextIterator.h" #include "Timer.h" #include "TraceEvent.h" +#include "ValidationMessageClientImpl.h" #include "WebAccessibilityObject.h" #include "WebActiveWheelFlingParameters.h" #include "WebAutofillClient.h" @@ -436,6 +437,7 @@ WebViewImpl::WebViewImpl(WebViewClient* client) , m_navigatorContentUtilsClient(NavigatorContentUtilsClientImpl::create(this)) #endif , m_flingModifier(0) + , m_validationMessage(ValidationMessageClientImpl::create(*client)) { // WebKit/win/WebView.cpp does the same thing, except they call the // KJS specific wrapper around this method. We need to have threading @@ -450,6 +452,7 @@ WebViewImpl::WebViewImpl(WebViewClient* client) pageClients.dragClient = &m_dragClientImpl; pageClients.inspectorClient = &m_inspectorClientImpl; pageClients.backForwardClient = BackForwardListChromium::create(this); + // FIXME: Set pageClients.validationMessageClient when Chromium-side implementation is done. m_page = adoptPtr(new Page(pageClients)); #if ENABLE(MEDIA_STREAM) diff --git a/Source/WebKit/chromium/src/WebViewImpl.h b/Source/WebKit/chromium/src/WebViewImpl.h index 865898608..4c1a974a0 100644 --- a/Source/WebKit/chromium/src/WebViewImpl.h +++ b/Source/WebKit/chromium/src/WebViewImpl.h @@ -99,6 +99,7 @@ class PrerendererClientImpl; class SpeechInputClientImpl; class SpeechRecognitionClientProxy; class UserMediaClientImpl; +class ValidationMessageClientImpl; class WebAccessibilityObject; class WebCompositorImpl; class WebDevToolsAgentClient; @@ -862,6 +863,7 @@ private: #if ENABLE(GESTURE_EVENTS) OwnPtr<LinkHighlight> m_linkHighlight; #endif + OwnPtr<ValidationMessageClientImpl> m_validationMessage; }; } // namespace WebKit diff --git a/Source/WebKit/chromium/tests/FilterOperationsTest.cpp b/Source/WebKit/chromium/tests/FilterOperationsTest.cpp index 8a3c5d8a1..873d216cd 100644 --- a/Source/WebKit/chromium/tests/FilterOperationsTest.cpp +++ b/Source/WebKit/chromium/tests/FilterOperationsTest.cpp @@ -89,5 +89,108 @@ TEST(WebFilterOperationsTest, getOutsetsDropShadow) EXPECT_EQ(54, left); } +#define SAVE_RESTORE_AMOUNT(Type, a) \ + { \ + WebFilterOperation op = WebFilterOperation::create##Type##Filter(a); \ + EXPECT_EQ(WebFilterOperation::FilterType##Type, op.type()); \ + EXPECT_EQ(a, op.amount()); \ + \ + WebFilterOperation op2 = WebFilterOperation::createEmptyFilter(); \ + op2.setType(WebFilterOperation::FilterType##Type); \ + \ + EXPECT_NE(a, op2.amount()); \ + \ + op2.setAmount(a); \ + \ + EXPECT_EQ(WebFilterOperation::FilterType##Type, op2.type()); \ + EXPECT_EQ(a, op2.amount()); \ + } + +#define SAVE_RESTORE_OFFSET_AMOUNT_COLOR(Type, a, b, c) \ + { \ + WebFilterOperation op = WebFilterOperation::create##Type##Filter(a, b, c); \ + EXPECT_EQ(WebFilterOperation::FilterType##Type, op.type()); \ + EXPECT_EQ(a, op.dropShadowOffset()); \ + EXPECT_EQ(b, op.amount()); \ + EXPECT_EQ(c, op.dropShadowColor()); \ + \ + WebFilterOperation op2 = WebFilterOperation::createEmptyFilter(); \ + op2.setType(WebFilterOperation::FilterType##Type); \ + \ + EXPECT_NE(a, op2.dropShadowOffset()); \ + EXPECT_NE(b, op2.amount()); \ + EXPECT_NE(c, op2.dropShadowColor()); \ + \ + op2.setDropShadowOffset(a); \ + op2.setAmount(b); \ + op2.setDropShadowColor(c); \ + \ + EXPECT_EQ(WebFilterOperation::FilterType##Type, op2.type()); \ + EXPECT_EQ(a, op2.dropShadowOffset()); \ + EXPECT_EQ(b, op2.amount()); \ + EXPECT_EQ(c, op2.dropShadowColor()); \ + } + +#define SAVE_RESTORE_MATRIX(Type, a) \ + { \ + WebFilterOperation op = WebFilterOperation::create##Type##Filter(a); \ + EXPECT_EQ(WebFilterOperation::FilterType##Type, op.type()); \ + for (unsigned i = 0; i < 20; ++i) \ + EXPECT_EQ(a[i], op.matrix()[i]); \ + \ + WebFilterOperation op2 = WebFilterOperation::createEmptyFilter(); \ + op2.setType(WebFilterOperation::FilterType##Type); \ + \ + for (unsigned i = 0; i < 20; ++i) \ + EXPECT_NE(a[i], op2.matrix()[i]); \ + \ + op2.setMatrix(a); \ + \ + EXPECT_EQ(WebFilterOperation::FilterType##Type, op2.type()); \ + for (unsigned i = 0; i < 20; ++i) \ + EXPECT_EQ(a[i], op.matrix()[i]); \ + } + +#define SAVE_RESTORE_ZOOMRECT_AMOUNT(Type, a, b) \ + { \ + WebFilterOperation op = WebFilterOperation::create##Type##Filter(a, b); \ + EXPECT_EQ(WebFilterOperation::FilterType##Type, op.type()); \ + EXPECT_EQ(a, op.zoomRect()); \ + EXPECT_EQ(b, op.amount()); \ + \ + WebFilterOperation op2 = WebFilterOperation::createEmptyFilter(); \ + op2.setType(WebFilterOperation::FilterType##Type); \ + \ + EXPECT_NE(a, op2.zoomRect()); \ + EXPECT_NE(b, op2.amount()); \ + \ + op2.setZoomRect(a); \ + op2.setAmount(b); \ + \ + EXPECT_EQ(WebFilterOperation::FilterType##Type, op2.type()); \ + EXPECT_EQ(a, op2.zoomRect()); \ + EXPECT_EQ(b, op2.amount()); \ + } + + +TEST(WebFilterOperationsTest, saveAndRestore) +{ + SAVE_RESTORE_AMOUNT(Grayscale, 0.6f); + SAVE_RESTORE_AMOUNT(Sepia, 0.6f); + SAVE_RESTORE_AMOUNT(Saturate, 0.6f); + SAVE_RESTORE_AMOUNT(HueRotate, 0.6f); + SAVE_RESTORE_AMOUNT(Invert, 0.6f); + SAVE_RESTORE_AMOUNT(Brightness, 0.6f); + SAVE_RESTORE_AMOUNT(Contrast, 0.6f); + SAVE_RESTORE_AMOUNT(Opacity, 0.6f); + SAVE_RESTORE_AMOUNT(Blur, 0.6f); + SAVE_RESTORE_OFFSET_AMOUNT_COLOR(DropShadow, WebPoint(3, 4), 0.4f, 0xffffff00); + + SkScalar matrix[20] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; + SAVE_RESTORE_MATRIX(ColorMatrix, matrix); + + SAVE_RESTORE_ZOOMRECT_AMOUNT(Zoom, WebRect(20, 19, 18, 17), 32); +} + } diff --git a/Source/WebKit/chromium/tests/MemoryInstrumentationTest.cpp b/Source/WebKit/chromium/tests/MemoryInstrumentationTest.cpp index 4acf496ad..21ce96316 100644 --- a/Source/WebKit/chromium/tests/MemoryInstrumentationTest.cpp +++ b/Source/WebKit/chromium/tests/MemoryInstrumentationTest.cpp @@ -37,6 +37,7 @@ #include <gtest/gtest.h> #include <wtf/HashSet.h> +#include <wtf/MemoryInstrumentationVector.h> #include <wtf/RefCounted.h> #include <wtf/Vector.h> #include <wtf/text/AtomicString.h> @@ -235,6 +236,7 @@ class InstrumentedOwner { public: template<typename V> InstrumentedOwner(const V& value) : m_value(value) { } + InstrumentedOwner() { } void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM); @@ -367,5 +369,75 @@ TEST(MemoryInstrumentationTest, detectReportMemoryUsageMethod) } } +TEST(MemoryInstrumentationTest, vectorZeroInlineCapacity) +{ + VisitedObjects visitedObjects; + MemoryInstrumentationImpl impl(visitedObjects); + InstrumentedOwner<Vector<int> > vectorOwner(16); + impl.addRootObject(vectorOwner); + EXPECT_EQ(16 * sizeof(int), impl.reportedSizeForAllTypes()); + EXPECT_EQ(1, visitedObjects.size()); +} + +TEST(MemoryInstrumentationTest, vectorFieldWithInlineCapacity) +{ + VisitedObjects visitedObjects; + MemoryInstrumentationImpl impl(visitedObjects); + InstrumentedOwner<Vector<int, 4> > vectorOwner; + impl.addRootObject(vectorOwner); + EXPECT_EQ(static_cast<size_t>(0), impl.reportedSizeForAllTypes()); + EXPECT_EQ(0, visitedObjects.size()); +} + +TEST(MemoryInstrumentationTest, vectorFieldWithInlineCapacityResized) +{ + VisitedObjects visitedObjects; + MemoryInstrumentationImpl impl(visitedObjects); + InstrumentedOwner<Vector<int, 4> > vectorOwner; + vectorOwner.m_value.reserveCapacity(8); + impl.addRootObject(vectorOwner); + EXPECT_EQ(8 * sizeof(int), impl.reportedSizeForAllTypes()); + EXPECT_EQ(1, visitedObjects.size()); +} + +TEST(MemoryInstrumentationTest, heapAllocatedVectorWithInlineCapacity) +{ + VisitedObjects visitedObjects; + MemoryInstrumentationImpl impl(visitedObjects); + InstrumentedOwner<OwnPtr<Vector<int, 4> > > vectorOwner; + vectorOwner.m_value = adoptPtr(new Vector<int, 4>()); + impl.addRootObject(vectorOwner); + EXPECT_EQ(sizeof(Vector<int, 4>), impl.reportedSizeForAllTypes()); + EXPECT_EQ(1, visitedObjects.size()); +} + +TEST(MemoryInstrumentationTest, heapAllocatedVectorWithInlineCapacityResized) +{ + VisitedObjects visitedObjects; + MemoryInstrumentationImpl impl(visitedObjects); + InstrumentedOwner<OwnPtr<Vector<int, 4> > > vectorOwner; + vectorOwner.m_value = adoptPtr(new Vector<int, 4>()); + vectorOwner.m_value->reserveCapacity(8); + impl.addRootObject(vectorOwner); + EXPECT_EQ(8 * sizeof(int) + sizeof(Vector<int, 4>), impl.reportedSizeForAllTypes()); + EXPECT_EQ(2, visitedObjects.size()); +} + +TEST(MemoryInstrumentationTest, vectorWithInstrumentedType) +{ + VisitedObjects visitedObjects; + MemoryInstrumentationImpl impl(visitedObjects); + + typedef Vector<String> StringVector; + OwnPtr<StringVector> value = adoptPtr(new StringVector()); + size_t count = 10; + for (size_t i = 0; i < count; ++i) + value->append("string"); + InstrumentedOwner<StringVector* > root(value.get()); + impl.addRootObject(root); + EXPECT_EQ(sizeof(StringVector) + sizeof(String) * value->capacity() + sizeof(StringImpl) * value->size(), impl.reportedSizeForAllTypes()); + EXPECT_EQ(count + 2, (size_t)visitedObjects.size()); +} + } // namespace diff --git a/Source/WebKit/efl/ChangeLog b/Source/WebKit/efl/ChangeLog index c0d31cae1..137c5c115 100644 --- a/Source/WebKit/efl/ChangeLog +++ b/Source/WebKit/efl/ChangeLog @@ -1,3 +1,15 @@ +2012-09-24 Dominik Röttsches <dominik.rottsches@intel.com> + + [EFL][DRT] Enable Regions support + https://bugs.webkit.org/show_bug.cgi?id=83897 + + Reviewed by Kenneth Rohde Christiansen. + + Activating CSS regions by default for EWK views. + + * ewk/ewk_view.cpp: Switch CSS regions on by default. + (_ewk_view_priv_new): + 2012-09-23 Byungwoo Lee <bw80.lee@gmail.com> Fix build warnings : -Wunused-parameter, -Wparentheses, -Wuninitialized. diff --git a/Source/WebKit/efl/ewk/ewk_view.cpp b/Source/WebKit/efl/ewk/ewk_view.cpp index f0b69673d..b2d6367a5 100644 --- a/Source/WebKit/efl/ewk/ewk_view.cpp +++ b/Source/WebKit/efl/ewk/ewk_view.cpp @@ -793,6 +793,7 @@ static Ewk_View_Private_Data* _ewk_view_priv_new(Ewk_View_Smart_Data* smartData) priv->pageSettings->setSansSerifFontFamily("sans"); priv->pageSettings->setStandardFontFamily("sans"); priv->pageSettings->setHyperlinkAuditingEnabled(false); + priv->pageSettings->setCSSRegionsEnabled(true); priv->pageSettings->setScriptEnabled(true); priv->pageSettings->setPluginsEnabled(true); priv->pageSettings->setLocalStorageEnabled(true); diff --git a/Source/WebKit/gtk/ChangeLog b/Source/WebKit/gtk/ChangeLog index c1afa53ed..e69726d5b 100644 --- a/Source/WebKit/gtk/ChangeLog +++ b/Source/WebKit/gtk/ChangeLog @@ -1,3 +1,44 @@ +2012-09-24 Benjamin Poulain <bpoulain@apple.com> + + Fix Geolocation error reporting in the test support + https://bugs.webkit.org/show_bug.cgi?id=97386 + + Reviewed by Sam Weinig. + + * WebCoreSupport/DumpRenderTreeSupportGtk.cpp: + (DumpRenderTreeSupportGtk::setMockGeolocationPositionUnavailableError): + * WebCoreSupport/DumpRenderTreeSupportGtk.h: + (DumpRenderTreeSupportGtk): + +2012-09-24 Zan Dobersek <zandobersek@gmail.com> + + [Gtk] Unskip the Shadow DOM layout tests + https://bugs.webkit.org/show_bug.cgi?id=90776 + + Reviewed by Ryosuke Niwa. + + Add a method for enabling the Shadow DOM through RuntimeEnabledFeatures. + The method is called from DumpRenderTree when resetting state. + + * WebCoreSupport/DumpRenderTreeSupportGtk.cpp: + (DumpRenderTreeSupportGtk::setShadowDOMEnabled): + * WebCoreSupport/DumpRenderTreeSupportGtk.h: + (DumpRenderTreeSupportGtk): + +2012-09-24 Joone Hur <joone.hur@intel.com> + + [GTK] Implement GraphicsLayer using Clutter + https://bugs.webkit.org/show_bug.cgi?id=73767 + + Reviewed by Martin Robinson. + + This patch is needed for enabling Accelerated Compositing(Clutter backend) + with the patches submitted in bug 92045 and 91940. + + * WebCoreSupport/AcceleratedCompositingContextClutter.cpp: + (WebKit::AcceleratedCompositingContext::scrollNonCompositedContents): Added to fix bulid break. + (WebKit): + 2012-09-19 Danilo Cesar Lemes de Paula <danilo.cesar@collabora.co.uk> [gtk] add enable-media-stream to websettings diff --git a/Source/WebKit/gtk/WebCoreSupport/AcceleratedCompositingContextClutter.cpp b/Source/WebKit/gtk/WebCoreSupport/AcceleratedCompositingContextClutter.cpp index 451117a82..c523bb545 100644 --- a/Source/WebKit/gtk/WebCoreSupport/AcceleratedCompositingContextClutter.cpp +++ b/Source/WebKit/gtk/WebCoreSupport/AcceleratedCompositingContextClutter.cpp @@ -112,6 +112,11 @@ void AcceleratedCompositingContext::resizeRootLayer(const IntSize& size) gtk_widget_size_allocate(GTK_WIDGET(m_rootLayerEmbedder), &allocation); } +void AcceleratedCompositingContext::scrollNonCompositedContents(const IntRect& scrollRect, const IntSize& scrollOffset) +{ + notImplemented(); +} + static gboolean flushAndRenderLayersCallback(AcceleratedCompositingContext* context) { context->flushAndRenderLayers(); diff --git a/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.cpp b/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.cpp index e5d6989d1..b39d5ae75 100644 --- a/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.cpp +++ b/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.cpp @@ -3,6 +3,7 @@ * Copyright (C) 2010 Joone Hur <joone@kldp.org> * Copyright (C) 2009 Google Inc. All rights reserved. * Copyright (C) 2011 Igalia S.L. + * Copyright (C) 2012 Apple Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -60,6 +61,7 @@ #include "RenderTreeAsText.h" #include "RenderView.h" #include "ResourceLoadScheduler.h" +#include "RuntimeEnabledFeatures.h" #include "SchemeRegistry.h" #include "SecurityOrigin.h" #include "SecurityPolicy.h" @@ -658,23 +660,11 @@ void DumpRenderTreeSupportGtk::setMockGeolocationPosition(WebKitWebView* webView #endif } -void DumpRenderTreeSupportGtk::setMockGeolocationError(WebKitWebView* webView, int errorCode, const gchar* errorMessage) +void DumpRenderTreeSupportGtk::setMockGeolocationPositionUnavailableError(WebKitWebView* webView, const gchar* errorMessage) { #if ENABLE(GEOLOCATION) GeolocationClientMock* mock = static_cast<GeolocationClientMock*>(GeolocationController::from(core(webView))->client()); - - GeolocationError::ErrorCode code; - switch (errorCode) { - case PositionError::PERMISSION_DENIED: - code = GeolocationError::PermissionDenied; - break; - case PositionError::POSITION_UNAVAILABLE: - default: - code = GeolocationError::PositionUnavailable; - break; - } - - mock->setError(GeolocationError::create(code, errorMessage)); + mock->setPositionUnavailableError(errorMessage); #endif } @@ -701,6 +691,11 @@ void DumpRenderTreeSupportGtk::setCSSRegionsEnabled(WebKitWebView* webView, bool core(webView)->settings()->setCSSRegionsEnabled(enabled); } +void DumpRenderTreeSupportGtk::setShadowDOMEnabled(bool enabled) +{ + RuntimeEnabledFeatures::setShadowDOMEnabled(enabled); +} + bool DumpRenderTreeSupportGtk::elementDoesAutoCompleteForElementWithId(WebKitWebFrame* frame, JSStringRef id) { Frame* coreFrame = core(frame); diff --git a/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.h b/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.h index 375020d7b..44ac78329 100644 --- a/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.h +++ b/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.h @@ -1,5 +1,6 @@ /* * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * Copyright (C) 2012 Apple Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -111,12 +112,13 @@ public: static void resetGeolocationClientMock(WebKitWebView*); static void setMockGeolocationPermission(WebKitWebView*, bool allowed); static void setMockGeolocationPosition(WebKitWebView*, double latitude, double longitude, double accuracy); - static void setMockGeolocationError(WebKitWebView*, int errorCode, const gchar* errorMessage); + static void setMockGeolocationPositionUnavailableError(WebKitWebView*, const gchar* errorMessage); static int numberOfPendingGeolocationPermissionRequests(WebKitWebView*); static void setPageCacheSupportsPlugins(WebKitWebView*, bool enabled); static void setCSSGridLayoutEnabled(WebKitWebView*, bool enabled); static void setCSSRegionsEnabled(WebKitWebView*, bool enabled); + static void setShadowDOMEnabled(bool enabled); static void deliverAllMutationsIfNecessary(); static void setDomainRelaxationForbiddenForURLScheme(bool forbidden, const char* urlScheme); diff --git a/Source/WebKit/mac/ChangeLog b/Source/WebKit/mac/ChangeLog index 1a1fc1591..7579b6513 100644 --- a/Source/WebKit/mac/ChangeLog +++ b/Source/WebKit/mac/ChangeLog @@ -1,3 +1,24 @@ +2012-09-24 Benjamin Poulain <bpoulain@apple.com> + + Fix Geolocation error reporting in the test support + https://bugs.webkit.org/show_bug.cgi?id=97386 + + Reviewed by Sam Weinig. + + * WebView/WebView.mm: + (-[WebView _geolocationDidFailWithMessage:]): + * WebView/WebViewPrivate.h: + +2012-09-24 Ryosuke Niwa <rniwa@webkit.org> + + suspend/resumeWidgetHierarchyUpdates should be a RAII object + https://bugs.webkit.org/show_bug.cgi?id=96706 + + Reviewed by Simon Fraser. + + * WebView/WebHTMLView.mm: + (-[WebHTMLView _invalidateGStatesForTree]): + 2012-09-21 Chris Rogers <crogers@google.com> Add Web Audio support for deprecated/legacy APIs diff --git a/Source/WebKit/mac/WebView/WebHTMLView.mm b/Source/WebKit/mac/WebView/WebHTMLView.mm index bfede8db6..82716a6c9 100644 --- a/Source/WebKit/mac/WebView/WebHTMLView.mm +++ b/Source/WebKit/mac/WebView/WebHTMLView.mm @@ -3376,9 +3376,8 @@ static void setMenuTargets(NSMenu* menu) // descendants, including plug-in views. This can result in calls out to plug-in code and back into // WebCore via JavaScript, which could normally mutate the NSView tree while it is being traversed. // Defer those mutations while descendants are being traveresed. - RenderWidget::suspendWidgetHierarchyUpdates(); + WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; [super _invalidateGStatesForTree]; - RenderWidget::resumeWidgetHierarchyUpdates(); } - (BOOL)isFlipped diff --git a/Source/WebKit/mac/WebView/WebView.mm b/Source/WebKit/mac/WebView/WebView.mm index c1f0a2d89..80d54174c 100644 --- a/Source/WebKit/mac/WebView/WebView.mm +++ b/Source/WebKit/mac/WebView/WebView.mm @@ -6511,11 +6511,11 @@ static void glibContextIterationCallback(CFRunLoopObserverRef, CFRunLoopActivity #endif // ENABLE(GEOLOCATION) } -- (void)_geolocationDidFailWithError:(NSError *)error +- (void)_geolocationDidFailWithMessage:(NSString *)errorMessage { #if ENABLE(GEOLOCATION) if (_private && _private->page) { - RefPtr<GeolocationError> geolocatioError = GeolocationError::create(GeolocationError::PositionUnavailable, [error localizedDescription]); + RefPtr<GeolocationError> geolocatioError = GeolocationError::create(GeolocationError::PositionUnavailable, errorMessage); WebCore::GeolocationController::from(_private->page)->errorOccurred(geolocatioError.get()); } #endif // ENABLE(GEOLOCATION) diff --git a/Source/WebKit/mac/WebView/WebViewPrivate.h b/Source/WebKit/mac/WebView/WebViewPrivate.h index 826474e41..c46d35e12 100644 --- a/Source/WebKit/mac/WebView/WebViewPrivate.h +++ b/Source/WebKit/mac/WebView/WebViewPrivate.h @@ -728,7 +728,7 @@ Could be worth adding to the API. - (id<WebGeolocationProvider>)_geolocationProvider; - (void)_geolocationDidChangePosition:(WebGeolocationPosition *)position; -- (void)_geolocationDidFailWithError:(NSError *)error; +- (void)_geolocationDidFailWithMessage:(NSString *)errorMessage; @end @interface WebView (WebViewNotification) diff --git a/Source/WebKit/qt/ChangeLog b/Source/WebKit/qt/ChangeLog index 5aa62f179..3d7cedaa7 100644 --- a/Source/WebKit/qt/ChangeLog +++ b/Source/WebKit/qt/ChangeLog @@ -1,3 +1,14 @@ +2012-09-24 Benjamin Poulain <bpoulain@apple.com> + + Fix Geolocation error reporting in the test support + https://bugs.webkit.org/show_bug.cgi?id=97386 + + Reviewed by Sam Weinig. + + * WebCoreSupport/DumpRenderTreeSupportQt.cpp: + (DumpRenderTreeSupportQt::setMockGeolocationPositionUnavailableError): + * WebCoreSupport/DumpRenderTreeSupportQt.h: + 2012-09-20 Csaba Osztrogonác <ossy@webkit.org> [Qt] Enable CSS regions by default diff --git a/Source/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.cpp b/Source/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.cpp index dc823165c..1ec3644e0 100644 --- a/Source/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.cpp +++ b/Source/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.cpp @@ -2,7 +2,7 @@ Copyright (C) 2010 Robert Hogan <robert@roberthogan.net> Copyright (C) 2008,2009,2010 Nokia Corporation and/or its subsidiary(-ies) Copyright (C) 2007 Staikos Computing Services Inc. - Copyright (C) 2007 Apple Inc. + Copyright (C) 2007, 2012 Apple Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -753,23 +753,12 @@ void DumpRenderTreeSupportQt::setMockGeolocationPosition(QWebPage* page, double #endif } -void DumpRenderTreeSupportQt::setMockGeolocationError(QWebPage* page, int errorCode, const QString& message) +void DumpRenderTreeSupportQt::setMockGeolocationPositionUnavailableError(QWebPage* page, const QString& message) { #if ENABLE(GEOLOCATION) Page* corePage = QWebPagePrivate::core(page); - - GeolocationError::ErrorCode code = GeolocationError::PositionUnavailable; - switch (errorCode) { - case PositionError::PERMISSION_DENIED: - code = GeolocationError::PermissionDenied; - break; - case PositionError::POSITION_UNAVAILABLE: - code = GeolocationError::PositionUnavailable; - break; - } - GeolocationClientMock* mockClient = static_cast<GeolocationClientMock*>(GeolocationController::from(corePage)->client()); - mockClient->setError(GeolocationError::create(code, message)); + mockClient->setPositionUnavailableError(message); #endif } diff --git a/Source/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h b/Source/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h index 862213657..cefb9d1c8 100644 --- a/Source/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h +++ b/Source/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h @@ -2,7 +2,7 @@ Copyright (C) 2010 Robert Hogan <robert@roberthogan.net> Copyright (C) 2008,2009,2010 Nokia Corporation and/or its subsidiary(-ies) Copyright (C) 2007 Staikos Computing Services Inc. - Copyright (C) 2007 Apple Inc. + Copyright (C) 2007, 2012 Apple Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -141,7 +141,7 @@ public: static void resetGeolocationMock(QWebPage*); static void setMockGeolocationPermission(QWebPage*, bool allowed); static void setMockGeolocationPosition(QWebPage*, double latitude, double longitude, double accuracy); - static void setMockGeolocationError(QWebPage*, int errorCode, const QString& message); + static void setMockGeolocationPositionUnavailableError(QWebPage*, const QString& message); static int numberOfPendingGeolocationPermissionRequests(QWebPage*); static int workerThreadCount(); diff --git a/Source/WebKit2/ChangeLog b/Source/WebKit2/ChangeLog index 18bdebe61..66240b840 100644 --- a/Source/WebKit2/ChangeLog +++ b/Source/WebKit2/ChangeLog @@ -1,3 +1,320 @@ +2012-09-25 Mikhail Pozdnyakov <mikhail.pozdnyakov@intel.com> + + [WK2][WTR] WTR bundle client loads binary data as text + https://bugs.webkit.org/show_bug.cgi?id=97532 + + Reviewed by Kenneth Rohde Christiansen. + + Added WKBundlePageCanShowMIMEType() function to WKBundlePage private API. + This function is put to WKBundlePage to keep consistency with WebKit::WebPageProxy::canShowMIMEType(). + Actually it does not need anything from page. + + * WebProcess/InjectedBundle/API/c/WKBundlePage.cpp: + (WKBundlePageCanShowMIMEType): + * WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h: + +2012-09-25 Carlos Garcia Campos <cgarcia@igalia.com> + + [GTK] Don't use the C API internally in WebKitWebView + https://bugs.webkit.org/show_bug.cgi?id=96767 + + Reviewed by Gustavo Noronha Silva. + + Using the C++ classes directly instead of the C API wrappers we + avoid a lot of toImpl/toAPI casts, string conversions and + allocations. The code is also a lot simpler and easier to read. + + * UIProcess/API/gtk/WebKitContextMenuClient.cpp: + (getContextMenuFromProposedMenu): + * UIProcess/API/gtk/WebKitResourceLoadClient.cpp: + (didInitiateLoadForResource): + * UIProcess/API/gtk/WebKitUIClient.cpp: + (createNewPage): + (runJavaScriptPrompt): + (mouseDidMoveOverElement): + (printFrame): + * UIProcess/API/gtk/WebKitURIRequest.cpp: + (webkitURIRequestCreateForResourceRequest): + (webkitURIRequestGetResourceRequest): + * UIProcess/API/gtk/WebKitURIRequestPrivate.h: + * UIProcess/API/gtk/WebKitWebView.cpp: + (allowModalDialogsChanged): + (zoomTextOnlyChanged): + (webkitWebViewSetSettings): + (webkitWebViewConstructed): + (webkitWebViewUpdateURI): + (webkitWebViewCreateNewPage): + (webkitWebViewRunJavaScriptPrompt): + (webkitWebViewMouseTargetChanged): + (webkitWebViewPrintFrame): + (webkitWebViewResourceLoadStarted): + (webkitWebViewPopulateContextMenu): + (webkit_web_view_load_uri): + (webkit_web_view_load_html): + (webkit_web_view_load_alternate_html): + (webkit_web_view_load_plain_text): + (webkit_web_view_load_request): + (webkit_web_view_reload): + (webkit_web_view_reload_bypass_cache): + (webkit_web_view_stop_loading): + (webkit_web_view_go_back): + (webkit_web_view_can_go_back): + (webkit_web_view_go_forward): + (webkit_web_view_can_go_forward): + (webkit_web_view_get_custom_charset): + (webkit_web_view_set_custom_charset): + (webkit_web_view_go_to_back_forward_list_item): + (webkit_web_view_set_settings): + (webkit_web_view_set_zoom_level): + (webkit_web_view_get_zoom_level): + (webkit_web_view_can_execute_editing_command): + (webkit_web_view_execute_editing_command): + (webkit_web_view_run_javascript): + (webkit_web_view_get_inspector): + (webkit_web_view_can_show_mime_type): + (ViewSaveAsyncData): + (getContentsAsMHTMLDataCallback): + (webkit_web_view_save): + (webkit_web_view_save_finish): + (webkit_web_view_save_to_file): + * UIProcess/API/gtk/WebKitWebViewBase.cpp: + (webkitWebViewBaseCreate): + (webkitWebViewBaseCreateWebPage): + * UIProcess/API/gtk/WebKitWebViewBasePrivate.h: + * UIProcess/API/gtk/WebKitWebViewPrivate.h: + +2012-09-24 Bo Liu <boliu@chromium.org> + + Reland "Add in-place reload behavior to ImagesEnabled setting" with optimizations + https://bugs.webkit.org/show_bug.cgi?id=97055 + + Reviewed by Adam Barth. + + Relanding 128780, 128676, 128645. Was reverted in 128914 due to + performance regression in Chromium. + + New changes in addition to previously reverted patches: + + Refactored CachedResource::requestResource, loadResource, and + revalidateResource. Moved CachedResource::load method to end of + requestResource so there is one place where load is called for all + resources. + + Added a enum parameter for requestResource and + determineRevalidationPolicy so that FrameLoaderClient::allowImage call + do not need to be called multiple times. + + Removed CachedImage::load call in requestImage so it is not called + twice. + + Removed unnecessary Frame.h includes in CachedResource and + CachedImage. + + Removed dead load() method declaration in CachedImage. + + Updated text expectation for two image-permissions tests to reflect + the removed calls to allowImage. + + * win/WebKit2.def: + +2012-09-24 Sam Weinig <sam@webkit.org> + + WKProcessGroup can't load injected bundle with file URL + <rdar://problem/12322774> + https://bugs.webkit.org/show_bug.cgi?id=97520 + + Reviewed by Anders Carlsson. + + * UIProcess/API/mac/WKProcessGroup.mm: + (-[WKProcessGroup initWithInjectedBundleURL:]): + Fix typo. We need to pass the string as path, not as a URL. + +2012-09-24 Sam Weinig <sam@webkit.org> + + Use NSUserDefaults rather than an environment variable to control whether to use an XPC Service for the WebProcess + https://bugs.webkit.org/show_bug.cgi?id=97514 + + Reviewed by Anders Carlsson. + + * GNUmakefile.list.am: + * PlatformEfl.cmake: + * Target.pri: + Add new files. + + * UIProcess/Launcher/ProcessLauncher.h: + * UIProcess/WebProcessProxy.cpp: + (WebKit::WebProcessProxy::connect): + Move platform specific launch options to a new function, platformConnect. + + * UIProcess/WebProcessProxy.h: + * UIProcess/efl/WebProcessProxyEfl.cpp: Added. + Move Efl specific launch options here. + + (WebKit::WebProcessProxy::platformConnect): + * UIProcess/gtk/WebProcessProxyGtk.cpp: Added. + Add stub. + + (WebKit::WebProcessProxy::platformConnect): + * UIProcess/mac/WebProcessProxyMac.mm: + (WebKit::WebProcessProxy::platformConnect): + Move Mac specific launch option setting here, and switch from + using an environment variable to NSUserDefaults. + + * UIProcess/qt/WebProcessProxyQt.cpp: Added. + (WebKit::WebProcessProxy::platformConnect): + Add stub. + + * UIProcess/win/WebProcessProxyWin.cpp: + (WebKit::WebProcessProxy::platformConnect): + Add stub. + +2012-09-24 Laszlo Gombos <l.gombos@samsung.com> + + [GTK][EFL] Remove cairo prefix from include statements + https://bugs.webkit.org/show_bug.cgi?id=97509 + + Reviewed by Gyuyoung Kim. + + Make the build system consistent by always assuming that directory + that includes the cairo headers is included in the include path. + + * UIProcess/cairo/BackingStoreCairo.cpp: + * WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp: + +2012-09-24 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r129388. + http://trac.webkit.org/changeset/129388 + https://bugs.webkit.org/show_bug.cgi?id=97477 + + Caused an assertion in a WebKit2 unit test (Requested by + abarth on #webkit). + + * win/WebKit2.def: + +2012-09-24 Simon Pena <spena@igalia.com> + + [GTK] Add Select All method to WebKit2 GTK+ API + https://bugs.webkit.org/show_bug.cgi?id=97460 + + Reviewed by Martin Robinson. + + Following the same approach used when added Cut, Copy and Paste, + the Select All method is added to the WebKit2 GTK+ API. + + This introduces a new macro in the WebKitEditingCommands, + updates the documentation, and includes a new unit test. + + * UIProcess/API/gtk/WebKitEditingCommands.h: Add a new macro for + the Select All command. + * UIProcess/API/gtk/docs/webkit2gtk-sections.txt: Include the Select All + command in the documentation. + * UIProcess/API/gtk/tests/TestWebViewEditor.cpp: Cover the new command + with a unit test. + (testWebViewEditorSelectAll): + (beforeAll): + +2012-09-24 Bo Liu <boliu@chromium.org> + + Reland "Add in-place reload behavior to ImagesEnabled setting" with optimizations + https://bugs.webkit.org/show_bug.cgi?id=97055 + + Reviewed by Adam Barth. + + Relanding 128780, 128676, 128645. Was reverted in 128914 due to + performance regression in Chromium. + + New changes in addition to previously reverted patches: + + Refactored CachedResource::requestResource, loadResource, and + revalidateResource. Moved CachedResource::load method to end of + requestResource so there is one place where load is called for all + resources. + + Added a enum parameter for requestResource and + determineRevalidationPolicy so that FrameLoaderClient::allowImage call + do not need to be called multiple times. + + Removed CachedImage::load call in requestImage so it is not called + twice. + + Removed unnecessary Frame.h includes in CachedResource and + CachedImage. + + Removed dead load() method declaration in CachedImage. + + Updated text expectation for two image-permissions tests to reflect + the removed calls to allowImage. + + * win/WebKit2.def: + +2012-09-24 Joone Hur <joone.hur@intel.com>, Gustavo Noronha Silva <gustavo.noronha@collabora.com> + + [GTK] Implement GraphicsLayer using Clutter + https://bugs.webkit.org/show_bug.cgi?id=73767 + + Reviewed by Martin Robinson. + + Fixed link errors by adding Clutter library and header to WebKit2 build. + + * GNUmakefile.am: + +2012-09-24 Carlos Garcia Campos <cgarcia@igalia.com> + + [GTK] WebKitWebView:is-loading is not updated when the is loaded is started by link clicked navigation action + https://bugs.webkit.org/show_bug.cgi?id=97458 + + Reviewed by Xan Lopez. + + WebKitWebView:is-loading is set to TRUE when the load is started + by using the API. We want to make sure that both URI and + is-loading are updated before load-started is emitted, so we can + update both right before emitting load-started. + + * UIProcess/API/gtk/WebKitWebView.cpp: + (webkitWebViewEmitLoadChanged): Update both uri and is-loading + properties before emitting load-changed signal with + WEBKIT_LOAD_STARTED. + (webkit_web_view_load_uri): Don't call + webkitWebViewSetIsLoading(). + (webkit_web_view_load_html): Ditto. + (webkit_web_view_load_alternate_html): Ditto. + (webkit_web_view_load_plain_text): Ditto. + (webkit_web_view_load_request): Ditto. + (webkit_web_view_reload): Ditto. + (webkit_web_view_reload_bypass_cache): Ditto. + (webkit_web_view_go_back): Ditto. + (webkit_web_view_go_forward): Ditto. + (webkit_web_view_go_to_back_forward_list_item): Ditto. + +2012-09-24 Byungwoo Lee <bw80.lee@samsung.com> + + [EFL][WK2] Change the install path for libewk2UnitTestInjectedBundleSample.so. + https://bugs.webkit.org/show_bug.cgi?id=97302 + + Reviewed by Gyuyoung Kim. + + libewk2UnitTestInjectedBundleSample.so file is created under the + Source directory. + Change install directory for the library to under the build directory. + + * PlatformEfl.cmake: + * UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.cpp: + (EWK2UnitTest::EWK2UnitTestEnvironment::injectedBundleSample): + +2012-09-24 Vivek Galatage <vivekgalatage@gmail.com> + + Web Inspector: implement testing harness for pure protocol tests. + https://bugs.webkit.org/show_bug.cgi?id=90675 + + Reviewed by Yury Semikhatsky. + + Adding the export symbol definitions required on Apple Windows and WinCairo + ports to support Inspector Protocol testing harness. + + * win/WebKit2.def: + * win/WebKit2CFLite.def: + 2012-09-24 KwangYong Choi <ky0.choi@samsung.com> [EFL][WK2] Invalid featuring of INPUT_TYPE_COLOR in test_ewk2_view. diff --git a/Source/WebKit2/GNUmakefile.am b/Source/WebKit2/GNUmakefile.am index ba0ac6955..52020862f 100644 --- a/Source/WebKit2/GNUmakefile.am +++ b/Source/WebKit2/GNUmakefile.am @@ -101,6 +101,7 @@ libwebkit2gtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_CPP $(webcore_cppflags) \ $(webcoregtk_cppflags) \ $(javascriptcore_cppflags) \ + $(CLUTTER_CFLAGS) \ $(COVERAGE_CFLAGS) \ $(GEOCLUE_CFLAGS) \ $(GLIB_CFLAGS) \ @@ -162,6 +163,7 @@ libwebkit2gtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_LIB libjavascriptcoregtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \ libWebCoreGtk.la \ $(CAIRO_LIBS) \ + $(CLUTTER_LIBS) \ $(COVERAGE_LDFLAGS) \ $(FARSTREAM_LIBS) \ $(GAIL_LIBS) \ diff --git a/Source/WebKit2/GNUmakefile.list.am b/Source/WebKit2/GNUmakefile.list.am index 6ecb2da8b..5015fb3e2 100644 --- a/Source/WebKit2/GNUmakefile.list.am +++ b/Source/WebKit2/GNUmakefile.list.am @@ -779,6 +779,7 @@ webkit2_sources += \ Source/WebKit2/UIProcess/gtk/WebPopupMenuProxyGtk.cpp \ Source/WebKit2/UIProcess/gtk/WebPopupMenuProxyGtk.h \ Source/WebKit2/UIProcess/gtk/WebPreferencesGtk.cpp \ + Source/WebKit2/UIProcess/gtk/WebProcessProxyGtk.cpp \ Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp \ Source/WebKit2/UIProcess/Launcher/ProcessLauncher.cpp \ Source/WebKit2/UIProcess/Launcher/ProcessLauncher.h \ diff --git a/Source/WebKit2/PlatformEfl.cmake b/Source/WebKit2/PlatformEfl.cmake index 8acb4c730..d3932b6dc 100644 --- a/Source/WebKit2/PlatformEfl.cmake +++ b/Source/WebKit2/PlatformEfl.cmake @@ -76,6 +76,7 @@ LIST(APPEND WebKit2_SOURCES UIProcess/efl/WebPageProxyEfl.cpp UIProcess/efl/WebPopupMenuProxyEfl.cpp UIProcess/efl/WebPreferencesEfl.cpp + UIProcess/efl/WebProcessProxyEfl.cpp UIProcess/soup/WebCookieManagerProxySoup.cpp UIProcess/soup/WebSoupRequestManagerClient.cpp @@ -265,6 +266,7 @@ SET(TEST_RESOURCES_DIR ${WEBKIT2_EFL_TEST_DIR}/resources) SET(TEST_INJECTED_BUNDLE_DIR ${WEBKIT2_EFL_TEST_DIR}/InjectedBundle) ADD_DEFINITIONS(-DTEST_RESOURCES_DIR=\"${TEST_RESOURCES_DIR}\" + -DTEST_LIB_DIR=\"${CMAKE_LIBRARY_OUTPUT_DIRECTORY}\" -DTEST_THEME_DIR=\"${THEME_BINARY_DIR}\" -DGTEST_LINKED_AS_SHARED_LIBRARY=1 -DLIBEXECDIR=\"${CMAKE_INSTALL_PREFIX}/${EXEC_INSTALL_DIR}\" @@ -304,7 +306,6 @@ IF (ENABLE_API_TESTS) ENDFOREACH () ADD_LIBRARY(ewk2UnitTestInjectedBundleSample SHARED ${TEST_INJECTED_BUNDLE_DIR}/injected_bundle_sample.cpp) - SET_TARGET_PROPERTIES(ewk2UnitTestInjectedBundleSample PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${TEST_RESOURCES_DIR}") ENDIF () IF (ENABLE_INSPECTOR) diff --git a/Source/WebKit2/Target.pri b/Source/WebKit2/Target.pri index 81895f04d..15fa0b18a 100644 --- a/Source/WebKit2/Target.pri +++ b/Source/WebKit2/Target.pri @@ -623,6 +623,7 @@ SOURCES += \ UIProcess/qt/WebInspectorProxyQt.cpp \ UIProcess/qt/WebPageProxyQt.cpp \ UIProcess/qt/WebPreferencesQt.cpp \ + UIProcess/qt/WebProcessProxyQt.cpp \ WebProcess/ApplicationCache/WebApplicationCacheManager.cpp \ WebProcess/Authentication/AuthenticationManager.cpp \ WebProcess/Battery/WebBatteryManager.cpp \ diff --git a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.cpp b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.cpp index cd3c55d5f..0b7977f54 100644 --- a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.cpp +++ b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.cpp @@ -45,7 +45,7 @@ const char* EWK2UnitTestEnvironment::defaultTheme() const const char* EWK2UnitTestEnvironment::injectedBundleSample() const { - return TEST_RESOURCES_DIR "/libewk2UnitTestInjectedBundleSample.so"; + return TEST_LIB_DIR "/libewk2UnitTestInjectedBundleSample.so"; } CString EWK2UnitTestEnvironment::urlForResource(const char* resource) diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuClient.cpp index f9d713180..42f90b871 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuClient.cpp @@ -28,7 +28,7 @@ using namespace WebKit; static void getContextMenuFromProposedMenu(WKPageRef, WKArrayRef proposedMenu, WKArrayRef*, WKHitTestResultRef hitTestResult, WKTypeRef userData, const void* clientInfo) { - webkitWebViewPopulateContextMenu(WEBKIT_WEB_VIEW(clientInfo), proposedMenu, hitTestResult); + webkitWebViewPopulateContextMenu(WEBKIT_WEB_VIEW(clientInfo), toImpl(proposedMenu), toImpl(hitTestResult)); } void attachContextMenuClientToView(WebKitWebView* webView) diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitEditingCommands.h b/Source/WebKit2/UIProcess/API/gtk/WebKitEditingCommands.h index f85bf31bd..36c72a0d3 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitEditingCommands.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitEditingCommands.h @@ -62,6 +62,15 @@ G_BEGIN_DECLS */ #define WEBKIT_EDITING_COMMAND_PASTE "Paste" +/** + * WEBKIT_EDITING_COMMAND_SELECT_ALL: + * + * The select all command. Selects all the content of the current text field in + * a #WebKitWebView. + * It is always possible to select all text, no matter wheter the #WebKitWebView content + * is editable or not. You can still check it with webkit_web_view_can_execute_editing_command(). + */ +#define WEBKIT_EDITING_COMMAND_SELECT_ALL "SelectAll" G_END_DECLS diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.cpp index b38161156..4444a1ee7 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.cpp @@ -38,7 +38,7 @@ using namespace WebKit; static void didInitiateLoadForResource(WKPageRef, WKFrameRef wkFrame, uint64_t resourceIdentifier, WKURLRequestRef wkRequest, bool pageIsProvisionallyLoading, const void* clientInfo) { GRefPtr<WebKitURIRequest> request = adoptGRef(webkitURIRequestCreateForResourceRequest(toImpl(wkRequest)->resourceRequest())); - webkitWebViewResourceLoadStarted(WEBKIT_WEB_VIEW(clientInfo), wkFrame, resourceIdentifier, request.get()); + webkitWebViewResourceLoadStarted(WEBKIT_WEB_VIEW(clientInfo), toImpl(wkFrame), resourceIdentifier, request.get()); } static void didSendRequestForResource(WKPageRef, WKFrameRef, uint64_t resourceIdentifier, WKURLRequestRef wkRequest, WKURLResponseRef wkRedirectResponse, const void* clientInfo) diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp index 59d0b0d14..1925e6a21 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp @@ -34,7 +34,7 @@ using namespace WebKit; static WKPageRef createNewPage(WKPageRef page, WKURLRequestRef, WKDictionaryRef wkWindowFeatures, WKEventModifiers, WKEventMouseButton, const void* clientInfo) { - return webkitWebViewCreateNewPage(WEBKIT_WEB_VIEW(clientInfo), wkWindowFeatures); + return static_cast<WKPageRef>(toAPI(webkitWebViewCreateNewPage(WEBKIT_WEB_VIEW(clientInfo), toImpl(wkWindowFeatures)))); } static void showPage(WKPageRef page, const void* clientInfo) @@ -59,8 +59,9 @@ static bool runJavaScriptConfirm(WKPageRef page, WKStringRef message, WKFrameRef static WKStringRef runJavaScriptPrompt(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef, const void* clientInfo) { - return webkitWebViewRunJavaScriptPrompt(WEBKIT_WEB_VIEW(clientInfo), toImpl(message)->string().utf8(), - toImpl(defaultValue)->string().utf8()); + CString result = webkitWebViewRunJavaScriptPrompt(WEBKIT_WEB_VIEW(clientInfo), toImpl(message)->string().utf8(), + toImpl(defaultValue)->string().utf8()); + return WKStringCreateWithUTF8CString(result.data()); } static bool toolbarsAreVisible(WKPageRef page, const void* clientInfo) @@ -131,12 +132,12 @@ static void setWindowFrame(WKPageRef page, WKRect frame, const void* clientInfo) static void mouseDidMoveOverElement(WKPageRef page, WKHitTestResultRef hitTestResult, WKEventModifiers modifiers, WKTypeRef userData, const void* clientInfo) { - webkitWebViewMouseTargetChanged(WEBKIT_WEB_VIEW(clientInfo), hitTestResult, wkEventModifiersToGdkModifiers(modifiers)); + webkitWebViewMouseTargetChanged(WEBKIT_WEB_VIEW(clientInfo), toImpl(hitTestResult), wkEventModifiersToGdkModifiers(modifiers)); } static void printFrame(WKPageRef page, WKFrameRef frame, const void*) { - webkitWebViewPrintFrame(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), frame); + webkitWebViewPrintFrame(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), toImpl(frame)); } static void runOpenPanel(WKPageRef page, WKFrameRef frame, WKOpenPanelParametersRef parameters, WKOpenPanelResultListenerRef listener, const void *clientInfo) diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequest.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequest.cpp index b5c2b4e74..c882cb788 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequest.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequest.cpp @@ -117,13 +117,6 @@ WebKitURIRequest* webkit_uri_request_new(const gchar* uri) return WEBKIT_URI_REQUEST(g_object_new(WEBKIT_TYPE_URI_REQUEST, "uri", uri, NULL)); } -WebKitURIRequest* webkitURIRequestCreateForResourceRequest(const WebCore::ResourceRequest& resourceRequest) -{ - WebKitURIRequest* uriRequest = WEBKIT_URI_REQUEST(g_object_new(WEBKIT_TYPE_URI_REQUEST, NULL)); - uriRequest->priv->resourceRequest = resourceRequest; - return uriRequest; -} - /** * webkit_uri_request_get_uri: * @request: a #WebKitURIRequest @@ -138,3 +131,14 @@ const gchar* webkit_uri_request_get_uri(WebKitURIRequest* request) return request->priv->uri.data(); } +WebKitURIRequest* webkitURIRequestCreateForResourceRequest(const WebCore::ResourceRequest& resourceRequest) +{ + WebKitURIRequest* uriRequest = WEBKIT_URI_REQUEST(g_object_new(WEBKIT_TYPE_URI_REQUEST, NULL)); + uriRequest->priv->resourceRequest = resourceRequest; + return uriRequest; +} + +const WebCore::ResourceRequest& webkitURIRequestGetResourceRequest(WebKitURIRequest* uriRequest) +{ + return uriRequest->priv->resourceRequest; +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequestPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequestPrivate.h index db85242af..3af02a527 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequestPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequestPrivate.h @@ -30,5 +30,6 @@ #include <WebCore/ResourceRequest.h> WebKitURIRequest* webkitURIRequestCreateForResourceRequest(const WebCore::ResourceRequest&); +const WebCore::ResourceRequest& webkitURIRequestGetResourceRequest(WebKitURIRequest*); #endif // WebKitURIRequestPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp index 45c3821b0..301be899c 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp @@ -23,6 +23,7 @@ #include "WebContextMenuItem.h" #include "WebContextMenuItemData.h" +#include "WebData.h" #include "WebKitBackForwardListPrivate.h" #include "WebKitContextMenuClient.h" #include "WebKitContextMenuItemPrivate.h" @@ -43,6 +44,7 @@ #include "WebKitScriptDialogPrivate.h" #include "WebKitSettingsPrivate.h" #include "WebKitUIClient.h" +#include "WebKitURIRequestPrivate.h" #include "WebKitURIResponsePrivate.h" #include "WebKitWebContextPrivate.h" #include "WebKitWebInspectorPrivate.h" @@ -50,7 +52,6 @@ #include "WebKitWebViewBasePrivate.h" #include "WebKitWebViewPrivate.h" #include "WebKitWindowPropertiesPrivate.h" -#include "WebPageProxy.h" #include <JavaScriptCore/APICast.h> #include <WebCore/DragIcon.h> #include <WebCore/GOwnPtrGtk.h> @@ -60,7 +61,6 @@ #include <wtf/gobject/GRefPtr.h> #include <wtf/text/CString.h> -using namespace WebKit; using namespace WebCore; enum { @@ -145,6 +145,11 @@ static guint signals[LAST_SIGNAL] = { 0, }; G_DEFINE_TYPE(WebKitWebView, webkit_web_view, WEBKIT_TYPE_WEB_VIEW_BASE) +static inline WebPageProxy* getPage(WebKitWebView* webView) +{ + return webkitWebViewBaseGetPage(reinterpret_cast<WebKitWebViewBase*>(webView)); +} + static gboolean webkitWebViewLoadFail(WebKitWebView* webView, WebKitLoadEvent, const char* failingURI, GError* error) { if (g_error_matches(error, WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED) @@ -238,28 +243,27 @@ static void allowModalDialogsChanged(WebKitSettings* settings, GParamSpec*, WebK WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); if (!page) return; - page->setCanRunModal(webkit_settings_get_allow_modal_dialogs(settings)); + getPage(webView)->setCanRunModal(webkit_settings_get_allow_modal_dialogs(settings)); } static void zoomTextOnlyChanged(WebKitSettings* settings, GParamSpec*, WebKitWebView* webView) { - WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))); + WebPageProxy* page = getPage(webView); gboolean zoomTextOnly = webkit_settings_get_zoom_text_only(settings); - gdouble pageZoomLevel = zoomTextOnly ? 1 : WKPageGetTextZoomFactor(wkPage); - gdouble textZoomLevel = zoomTextOnly ? WKPageGetPageZoomFactor(wkPage) : 1; - WKPageSetPageAndTextZoomFactors(wkPage, pageZoomLevel, textZoomLevel); + gdouble pageZoomLevel = zoomTextOnly ? 1 : page->textZoomFactor(); + gdouble textZoomLevel = zoomTextOnly ? page->pageZoomFactor() : 1; + page->setPageAndTextZoomFactors(pageZoomLevel, textZoomLevel); } static void userAgentChanged(WebKitSettings* settings, GParamSpec*, WebKitWebView* webView) { - WKRetainPtr<WKStringRef> userAgent = adoptWK(WKStringCreateWithUTF8CString(webkit_settings_get_user_agent(settings))); - WKPageSetCustomUserAgent(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))), userAgent.get()); + getPage(webView)->setCustomUserAgent(String::fromUTF8(webkit_settings_get_user_agent(settings))); } -static void webkitWebViewSetSettings(WebKitWebView* webView, WebKitSettings* settings, WKPageRef wkPage) +static void webkitWebViewSetSettings(WebKitWebView* webView, WebKitSettings* settings) { webView->priv->settings = settings; - webkitSettingsAttachSettingsToPage(webView->priv->settings.get(), wkPage); + webkitSettingsAttachSettingsToPage(webView->priv->settings.get(), toAPI(getPage(webView))); g_signal_connect(settings, "notify::allow-modal-dialogs", G_CALLBACK(allowModalDialogsChanged), webView); g_signal_connect(settings, "notify::zoom-text-only", G_CALLBACK(zoomTextOnlyChanged), webView); g_signal_connect(settings, "notify::user-agent", G_CALLBACK(userAgentChanged), webView); @@ -333,7 +337,7 @@ static void webkitWebViewConstructed(GObject* object) WebKitWebViewPrivate* priv = webView->priv; WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(webView); - webkitWebViewBaseCreateWebPage(webViewBase, webkitWebContextGetWKContext(priv->context), 0); + webkitWebViewBaseCreateWebPage(webViewBase, toImpl(webkitWebContextGetWKContext(priv->context)), 0); attachLoaderClientToView(webView); attachUIClientToView(webView); @@ -343,11 +347,10 @@ static void webkitWebViewConstructed(GObject* object) attachContextMenuClientToView(webView); attachFormClientToView(webView); - WebPageProxy* page = webkitWebViewBaseGetPage(webViewBase); - priv->backForwardList = adoptGRef(webkitBackForwardListCreate(WKPageGetBackForwardList(toAPI(page)))); + priv->backForwardList = adoptGRef(webkitBackForwardListCreate(toAPI(getPage(webView)->backForwardList()))); GRefPtr<WebKitSettings> settings = adoptGRef(webkit_settings_new()); - webkitWebViewSetSettings(webView, settings.get(), toAPI(page)); + webkitWebViewSetSettings(webView, settings.get()); } static void webkitWebViewSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec) @@ -1155,7 +1158,9 @@ static void setCertificateToMainResource(WebKitWebView* webView) static void webkitWebViewEmitLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent) { - if (loadEvent == WEBKIT_LOAD_FINISHED) { + if (loadEvent == WEBKIT_LOAD_STARTED) + webkitWebViewSetIsLoading(webView, true); + else if (loadEvent == WEBKIT_LOAD_FINISHED) { webkitWebViewSetIsLoading(webView, false); webView->priv->waitingForMainResource = false; webkitWebViewDisconnectMainResourceResponseChangedSignalHandler(webView); @@ -1233,12 +1238,7 @@ void webkitWebViewSetEstimatedLoadProgress(WebKitWebView* webView, double estima void webkitWebViewUpdateURI(WebKitWebView* webView) { - WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); - WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKPageCopyActiveURL(toAPI(page))); - CString activeURI; - if (wkURL) - activeURI = toImpl(wkURL.get())->string().utf8(); - + CString activeURI = getPage(webView)->activeURL().utf8(); if (webView->priv->activeURI == activeURI) return; @@ -1246,16 +1246,17 @@ void webkitWebViewUpdateURI(WebKitWebView* webView) g_object_notify(G_OBJECT(webView), "uri"); } -WKPageRef webkitWebViewCreateNewPage(WebKitWebView* webView, WKDictionaryRef wkWindowFeatures) +WebPageProxy* webkitWebViewCreateNewPage(WebKitWebView* webView, ImmutableDictionary* windowFeatures) { WebKitWebView* newWebView; g_signal_emit(webView, signals[CREATE], 0, &newWebView); if (!newWebView) return 0; - webkitWindowPropertiesUpdateFromWKWindowFeatures(newWebView->priv->windowProperties.get(), wkWindowFeatures); + webkitWindowPropertiesUpdateFromWKWindowFeatures(newWebView->priv->windowProperties.get(), toAPI(windowFeatures)); - return static_cast<WKPageRef>(WKRetain(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(newWebView))))); + RefPtr<WebPageProxy> newPage = getPage(newWebView); + return newPage.release().leakRef(); } void webkitWebViewReadyToShowPage(WebKitWebView* webView) @@ -1293,12 +1294,12 @@ bool webkitWebViewRunJavaScriptConfirm(WebKitWebView* webView, const CString& me return dialog.confirmed; } -WKStringRef webkitWebViewRunJavaScriptPrompt(WebKitWebView* webView, const CString& message, const CString& defaultText) +CString webkitWebViewRunJavaScriptPrompt(WebKitWebView* webView, const CString& message, const CString& defaultText) { WebKitScriptDialog dialog(WEBKIT_SCRIPT_DIALOG_PROMPT, message, defaultText); gboolean returnValue; g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, &dialog, &returnValue); - return dialog.text.isNull() ? 0 : WKStringCreateWithUTF8CString(dialog.text.data()); + return dialog.text; } void webkitWebViewMakePolicyDecision(WebKitWebView* webView, WebKitPolicyDecisionType type, WebKitPolicyDecision* decision) @@ -1313,22 +1314,22 @@ void webkitWebViewMakePermissionRequest(WebKitWebView* webView, WebKitPermission g_signal_emit(webView, signals[PERMISSION_REQUEST], 0, request, &returnValue); } -void webkitWebViewMouseTargetChanged(WebKitWebView* webView, WKHitTestResultRef wkHitTestResult, unsigned modifiers) +void webkitWebViewMouseTargetChanged(WebKitWebView* webView, WebHitTestResult* hitTestResult, unsigned modifiers) { - webkitWebViewBaseSetTooltipArea(WEBKIT_WEB_VIEW_BASE(webView), toImpl(wkHitTestResult)->elementBoundingBox()); + webkitWebViewBaseSetTooltipArea(WEBKIT_WEB_VIEW_BASE(webView), hitTestResult->elementBoundingBox()); WebKitWebViewPrivate* priv = webView->priv; if (priv->mouseTargetHitTestResult && priv->mouseTargetModifiers == modifiers - && webkitHitTestResultCompare(priv->mouseTargetHitTestResult.get(), wkHitTestResult)) + && webkitHitTestResultCompare(priv->mouseTargetHitTestResult.get(), toAPI(hitTestResult))) return; priv->mouseTargetModifiers = modifiers; - priv->mouseTargetHitTestResult = adoptGRef(webkitHitTestResultCreate(wkHitTestResult)); + priv->mouseTargetHitTestResult = adoptGRef(webkitHitTestResultCreate(toAPI(hitTestResult))); g_signal_emit(webView, signals[MOUSE_TARGET_CHANGED], 0, priv->mouseTargetHitTestResult.get(), modifiers); } -void webkitWebViewPrintFrame(WebKitWebView* webView, WKFrameRef wkFrame) +void webkitWebViewPrintFrame(WebKitWebView* webView, WebFrameProxy* frame) { GRefPtr<WebKitPrintOperation> printOperation = adoptGRef(webkit_print_operation_new(webView)); gboolean returnValue; @@ -1336,7 +1337,7 @@ void webkitWebViewPrintFrame(WebKitWebView* webView, WKFrameRef wkFrame) if (returnValue) return; - WebKitPrintOperationResponse response = webkitPrintOperationRunDialogForFrame(printOperation.get(), 0, toImpl(wkFrame)); + WebKitPrintOperationResponse response = webkitPrintOperationRunDialogForFrame(printOperation.get(), 0, frame); if (response == WEBKIT_PRINT_OPERATION_RESPONSE_CANCEL) return; g_signal_connect(printOperation.leakRef(), "finished", G_CALLBACK(g_object_unref), 0); @@ -1360,11 +1361,11 @@ static void waitForMainResourceResponseIfWaitingForResource(WebKitWebView* webVi g_signal_connect(priv->mainResource.get(), "notify::response", G_CALLBACK(mainResourceResponseChangedCallback), webView); } -void webkitWebViewResourceLoadStarted(WebKitWebView* webView, WKFrameRef wkFrame, uint64_t resourceIdentifier, WebKitURIRequest* request) +void webkitWebViewResourceLoadStarted(WebKitWebView* webView, WebFrameProxy* frame, uint64_t resourceIdentifier, WebKitURIRequest* request) { WebKitWebViewPrivate* priv = webView->priv; - bool isMainResource = WKFrameIsMainFrame(wkFrame) && !priv->mainResource; - WebKitWebResource* resource = webkitWebResourceCreate(wkFrame, request, isMainResource); + bool isMainResource = frame->isMainFrame() && !priv->mainResource; + WebKitWebResource* resource = webkitWebResourceCreate(toAPI(frame), request, isMainResource); if (isMainResource) { priv->mainResource = resource; waitForMainResourceResponseIfWaitingForResource(webView); @@ -1468,17 +1469,17 @@ static void contextMenuDismissed(GtkMenuShell*, WebKitWebView* webView) g_signal_emit(webView, signals[CONTEXT_MENU_DISMISSED], 0, NULL); } -void webkitWebViewPopulateContextMenu(WebKitWebView* webView, WKArrayRef wkProposedMenu, WKHitTestResultRef wkHitTestResult) +void webkitWebViewPopulateContextMenu(WebKitWebView* webView, ImmutableArray* proposedMenu, WebHitTestResult* webHitTestResult) { WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(webView); WebContextMenuProxyGtk* contextMenuProxy = webkitWebViewBaseGetActiveContextMenuProxy(webViewBase); ASSERT(contextMenuProxy); - GRefPtr<WebKitContextMenu> contextMenu = adoptGRef(webkitContextMenuCreate(wkProposedMenu)); - if (WKHitTestResultIsContentEditable(wkHitTestResult)) + GRefPtr<WebKitContextMenu> contextMenu = adoptGRef(webkitContextMenuCreate(toAPI(proposedMenu))); + if (webHitTestResult->isContentEditable()) webkitWebViewCreateAndAppendInputMethodsMenuItem(webView, contextMenu.get()); - GRefPtr<WebKitHitTestResult> hitTestResult = adoptGRef(webkitHitTestResultCreate(wkHitTestResult)); + GRefPtr<WebKitHitTestResult> hitTestResult = adoptGRef(webkitHitTestResultCreate(toAPI(webHitTestResult))); GOwnPtr<GdkEvent> contextMenuEvent(webkitWebViewBaseTakeContextMenuEvent(webViewBase)); gboolean returnValue; @@ -1558,10 +1559,7 @@ void webkit_web_view_load_uri(WebKitWebView* webView, const gchar* uri) g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); g_return_if_fail(uri); - WKRetainPtr<WKURLRef> url(AdoptWK, WKURLCreateWithUTF8CString(uri)); - WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); - WKPageLoadURL(toAPI(page), url.get()); - webkitWebViewSetIsLoading(webView, true); + getPage(webView)->loadURL(String::fromUTF8(uri)); } /** @@ -1585,11 +1583,7 @@ void webkit_web_view_load_html(WebKitWebView* webView, const gchar* content, con g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); g_return_if_fail(content); - WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); - WKRetainPtr<WKStringRef> contentRef(AdoptWK, WKStringCreateWithUTF8CString(content)); - WKRetainPtr<WKURLRef> baseURIRef = baseURI ? adoptWK(WKURLCreateWithUTF8CString(baseURI)) : 0; - WKPageLoadHTMLString(toAPI(page), contentRef.get(), baseURIRef.get()); - webkitWebViewSetIsLoading(webView, true); + getPage(webView)->loadHTMLString(String::fromUTF8(content), String::fromUTF8(baseURI)); } /** @@ -1611,12 +1605,7 @@ void webkit_web_view_load_alternate_html(WebKitWebView* webView, const gchar* co g_return_if_fail(content); g_return_if_fail(contentURI); - WKRetainPtr<WKStringRef> htmlString(AdoptWK, WKStringCreateWithUTF8CString(content)); - WKRetainPtr<WKURLRef> contentURL(AdoptWK, WKURLCreateWithUTF8CString(contentURI)); - WKRetainPtr<WKURLRef> baseURL = baseURI ? adoptWK(WKURLCreateWithUTF8CString(baseURI)) : 0; - WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); - WKPageLoadAlternateHTMLString(toAPI(page), htmlString.get(), baseURL.get(), contentURL.get()); - webkitWebViewSetIsLoading(webView, true); + getPage(webView)->loadAlternateHTMLString(String::fromUTF8(content), String::fromUTF8(baseURI), String::fromUTF8(contentURI)); } /** @@ -1633,10 +1622,7 @@ void webkit_web_view_load_plain_text(WebKitWebView* webView, const gchar* plainT g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); g_return_if_fail(plainText); - WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); - WKRetainPtr<WKStringRef> plainTextRef(AdoptWK, WKStringCreateWithUTF8CString(plainText)); - WKPageLoadPlainTextString(toAPI(page), plainTextRef.get()); - webkitWebViewSetIsLoading(webView, true); + getPage(webView)->loadPlainTextString(String::fromUTF8(plainText)); } /** @@ -1653,11 +1639,7 @@ void webkit_web_view_load_request(WebKitWebView* webView, WebKitURIRequest* requ g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); g_return_if_fail(WEBKIT_IS_URI_REQUEST(request)); - WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKURLCreateWithUTF8CString(webkit_uri_request_get_uri(request))); - WKRetainPtr<WKURLRequestRef> wkRequest(AdoptWK, WKURLRequestCreateWithWKURL(wkURL.get())); - WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); - WKPageLoadURLRequest(toAPI(page), wkRequest.get()); - webkitWebViewSetIsLoading(webView, true); + getPage(webView)->loadURLRequest(WebURLRequest::create(webkitURIRequestGetResourceRequest(request)).leakRef()); } /** @@ -1688,8 +1670,7 @@ void webkit_web_view_reload(WebKitWebView* webView) { g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); - WKPageReload(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)))); - webkitWebViewSetIsLoading(webView, true); + getPage(webView)->reload(false); } /** @@ -1703,8 +1684,7 @@ void webkit_web_view_reload_bypass_cache(WebKitWebView* webView) { g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); - WKPageReloadFromOrigin(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)))); - webkitWebViewSetIsLoading(webView, true); + getPage(webView)->reload(true); } /** @@ -1721,7 +1701,7 @@ void webkit_web_view_stop_loading(WebKitWebView* webView) { g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); - WKPageStopLoading(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)))); + getPage(webView)->stopLoading(); } /** @@ -1756,8 +1736,7 @@ void webkit_web_view_go_back(WebKitWebView* webView) { g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); - WKPageGoBack(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)))); - webkitWebViewSetIsLoading(webView, true); + getPage(webView)->goBack(); } /** @@ -1772,7 +1751,7 @@ gboolean webkit_web_view_can_go_back(WebKitWebView* webView) { g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE); - return WKPageCanGoBack(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)))); + return getPage(webView)->canGoBack(); } /** @@ -1787,8 +1766,7 @@ void webkit_web_view_go_forward(WebKitWebView* webView) { g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); - WKPageGoForward(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)))); - webkitWebViewSetIsLoading(webView, true); + getPage(webView)->goForward(); } /** @@ -1803,7 +1781,7 @@ gboolean webkit_web_view_can_go_forward(WebKitWebView* webView) { g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE); - return WKPageCanGoForward(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)))); + return getPage(webView)->canGoForward(); } /** @@ -1884,12 +1862,11 @@ const gchar* webkit_web_view_get_custom_charset(WebKitWebView* webView) { g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0); - WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); - WKRetainPtr<WKStringRef> wkCustomEncoding(AdoptWK, WKPageCopyCustomTextEncodingName(toAPI(page))); - if (WKStringIsEmpty(wkCustomEncoding.get())) + String customTextEncoding = getPage(webView)->customTextEncodingName(); + if (customTextEncoding.isEmpty()) return 0; - webView->priv->customTextEncoding = toImpl(wkCustomEncoding.get())->string().utf8(); + webView->priv->customTextEncoding = customTextEncoding.utf8(); return webView->priv->customTextEncoding.data(); } @@ -1908,9 +1885,7 @@ void webkit_web_view_set_custom_charset(WebKitWebView* webView, const gchar* cha { g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); - WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); - WKRetainPtr<WKStringRef> wkEncodingName = charset ? adoptWK(WKStringCreateWithUTF8CString(charset)) : 0; - WKPageSetCustomTextEncodingName(toAPI(page), wkEncodingName.get()); + getPage(webView)->setCustomTextEncodingName(String::fromUTF8(charset)); } /** @@ -1960,9 +1935,7 @@ void webkit_web_view_go_to_back_forward_list_item(WebKitWebView* webView, WebKit g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); g_return_if_fail(WEBKIT_IS_BACK_FORWARD_LIST_ITEM(listItem)); - WKPageGoToBackForwardListItem(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))), - webkitBackForwardListItemGetWKItem(listItem)); - webkitWebViewSetIsLoading(webView, true); + getPage(webView)->goToBackForwardItem(toImpl(webkitBackForwardListItemGetWKItem(listItem))); } /** @@ -1985,7 +1958,7 @@ void webkit_web_view_set_settings(WebKitWebView* webView, WebKitSettings* settin return; webkitWebViewDisconnectSettingsSignalHandlers(webView); - webkitWebViewSetSettings(webView, settings, toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)))); + webkitWebViewSetSettings(webView, settings); } /** @@ -2046,11 +2019,11 @@ void webkit_web_view_set_zoom_level(WebKitWebView* webView, gdouble zoomLevel) if (webkit_web_view_get_zoom_level(webView) == zoomLevel) return; - WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))); + WebPageProxy* page = getPage(webView); if (webkit_settings_get_zoom_text_only(webView->priv->settings.get())) - WKPageSetTextZoomFactor(wkPage, zoomLevel); + page->setTextZoomFactor(zoomLevel); else - WKPageSetPageZoomFactor(wkPage, zoomLevel); + page->setPageZoomFactor(zoomLevel); g_object_notify(G_OBJECT(webView), "zoom-level"); } @@ -2067,9 +2040,9 @@ gdouble webkit_web_view_get_zoom_level(WebKitWebView* webView) { g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 1); - WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))); + WebPageProxy* page = getPage(webView); gboolean zoomTextOnly = webkit_settings_get_zoom_text_only(webView->priv->settings.get()); - return zoomTextOnly ? WKPageGetTextZoomFactor(wkPage) : WKPageGetPageZoomFactor(wkPage); + return zoomTextOnly ? page->textZoomFactor() : page->pageZoomFactor(); } struct ValidateEditingCommandAsyncData { @@ -2114,9 +2087,7 @@ void webkit_web_view_can_execute_editing_command(WebKitWebView* webView, const c data->cancellable = cancellable; g_simple_async_result_set_op_res_gpointer(result, data, reinterpret_cast<GDestroyNotify>(destroyValidateEditingCommandAsyncData)); - WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); - WKRetainPtr<WKStringRef> wkCommand(AdoptWK, WKStringCreateWithUTF8CString(command)); - WKPageValidateCommand(toAPI(page), wkCommand.get(), result, didValidateCommand); + getPage(webView)->validateCommand(String::fromUTF8(command), ValidateCommandCallback::create(result, didValidateCommand)); } /** @@ -2158,9 +2129,7 @@ void webkit_web_view_execute_editing_command(WebKitWebView* webView, const char* g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); g_return_if_fail(command); - WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); - WKRetainPtr<WKStringRef> wkCommand(AdoptWK, WKStringCreateWithUTF8CString(command)); - WKPageExecuteCommand(toAPI(page), wkCommand.get()); + getPage(webView)->executeEditCommand(String::fromUTF8(command)); } /** @@ -2249,14 +2218,14 @@ void webkit_web_view_run_javascript(WebKitWebView* webView, const gchar* script, g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); g_return_if_fail(script); - WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))); - WKRetainPtr<WKStringRef> wkScript = adoptWK(WKStringCreateWithUTF8CString(script)); GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(webView), callback, userData, reinterpret_cast<gpointer>(webkit_web_view_run_javascript)); RunJavaScriptAsyncData* data = createRunJavaScriptAsyncData(); data->cancellable = cancellable; g_simple_async_result_set_op_res_gpointer(result, data, reinterpret_cast<GDestroyNotify>(destroyRunJavaScriptAsyncData)); - WKPageRunJavaScriptInMainFrame(wkPage, wkScript.get(), result, webkitWebViewRunJavaScriptCallback); + + getPage(webView)->runJavaScriptInMainFrame(String::fromUTF8(script), + ScriptValueCallback::create(result, webkitWebViewRunJavaScriptCallback)); } /** @@ -2389,10 +2358,8 @@ WebKitWebInspector* webkit_web_view_get_inspector(WebKitWebView* webView) { g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0); - if (!webView->priv->inspector) { - WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); - webView->priv->inspector = adoptGRef(webkitWebInspectorCreate(toAPI(page->inspector()))); - } + if (!webView->priv->inspector) + webView->priv->inspector = adoptGRef(webkitWebInspectorCreate(toAPI(getPage(webView)->inspector()))); return webView->priv->inspector.get(); } @@ -2411,12 +2378,11 @@ gboolean webkit_web_view_can_show_mime_type(WebKitWebView* webView, const char* g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE); g_return_val_if_fail(mimeType, FALSE); - WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); - return page->canShowMIMEType(String::fromUTF8(mimeType)); + return getPage(webView)->canShowMIMEType(String::fromUTF8(mimeType)); } struct ViewSaveAsyncData { - WKRetainPtr<WKDataRef> wkData; + RefPtr<WebData> webData; GRefPtr<GFile> file; GRefPtr<GCancellable> cancellable; }; @@ -2445,13 +2411,14 @@ static void getContentsAsMHTMLDataCallback(WKDataRef wkData, WKErrorRef, void* c else { // We need to retain the data until the asyncronous process // initiated by the user has finished completely. - data->wkData = wkData; + data->webData = toImpl(wkData); // If we are saving to a file we need to write the data on disk before finishing. if (g_simple_async_result_get_source_tag(result.get()) == webkit_web_view_save_to_file) { ASSERT(G_IS_FILE(data->file.get())); - g_file_replace_contents_async(data->file.get(), reinterpret_cast<const gchar*>(WKDataGetBytes(data->wkData.get())), WKDataGetSize(data->wkData.get()), 0, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, - data->cancellable.get(), fileReplaceContentsCallback, g_object_ref(result.get())); + g_file_replace_contents_async(data->file.get(), reinterpret_cast<const gchar*>(data->webData->bytes()), data->webData->size(), + 0, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, data->cancellable.get(), fileReplaceContentsCallback, + g_object_ref(result.get())); return; } } @@ -2488,8 +2455,7 @@ void webkit_web_view_save(WebKitWebView* webView, WebKitSaveMode saveMode, GCanc data->cancellable = cancellable; g_simple_async_result_set_op_res_gpointer(result, data, reinterpret_cast<GDestroyNotify>(destroyViewSaveAsyncData)); - WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))); - WKPageGetContentsAsMHTMLData(wkPage, false, result, getContentsAsMHTMLDataCallback); + getPage(webView)->getContentsAsMHTMLData(DataCallback::create(result, getContentsAsMHTMLDataCallback), false); } /** @@ -2516,9 +2482,9 @@ GInputStream* webkit_web_view_save_finish(WebKitWebView* webView, GAsyncResult* GInputStream* dataStream = g_memory_input_stream_new(); ViewSaveAsyncData* data = static_cast<ViewSaveAsyncData*>(g_simple_async_result_get_op_res_gpointer(simple)); - gsize length = WKDataGetSize(data->wkData.get()); + gsize length = data->webData->size(); if (length) - g_memory_input_stream_add_data(G_MEMORY_INPUT_STREAM(dataStream), g_memdup(WKDataGetBytes(data->wkData.get()), length), length, g_free); + g_memory_input_stream_add_data(G_MEMORY_INPUT_STREAM(dataStream), g_memdup(data->webData->bytes(), length), length, g_free); return dataStream; } @@ -2555,8 +2521,7 @@ void webkit_web_view_save_to_file(WebKitWebView* webView, GFile* file, WebKitSav data->cancellable = cancellable; g_simple_async_result_set_op_res_gpointer(result, data, reinterpret_cast<GDestroyNotify>(destroyViewSaveAsyncData)); - WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))); - WKPageGetContentsAsMHTMLData(wkPage, false, result, getContentsAsMHTMLDataCallback); + getPage(webView)->getContentsAsMHTMLData(DataCallback::create(result, getContentsAsMHTMLDataCallback), false); } /** diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp index 5338e2bd3..b42b2ee8f 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp @@ -775,7 +775,7 @@ static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebVie WebKitWebViewBase* webkitWebViewBaseCreate(WebContext* context, WebPageGroup* pageGroup) { WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(g_object_new(WEBKIT_TYPE_WEB_VIEW_BASE, NULL)); - webkitWebViewBaseCreateWebPage(webkitWebViewBase, toAPI(context), toAPI(pageGroup)); + webkitWebViewBaseCreateWebPage(webkitWebViewBase, context, pageGroup); return webkitWebViewBase; } @@ -789,11 +789,11 @@ WebPageProxy* webkitWebViewBaseGetPage(WebKitWebViewBase* webkitWebViewBase) return webkitWebViewBase->priv->pageProxy.get(); } -void webkitWebViewBaseCreateWebPage(WebKitWebViewBase* webkitWebViewBase, WKContextRef context, WKPageGroupRef pageGroup) +void webkitWebViewBaseCreateWebPage(WebKitWebViewBase* webkitWebViewBase, WebContext* context, WebPageGroup* pageGroup) { WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv; - priv->pageProxy = toImpl(context)->createWebPage(priv->pageClient.get(), toImpl(pageGroup)); + priv->pageProxy = context->createWebPage(priv->pageClient.get(), pageGroup); priv->pageProxy->initializeWebPage(); #if ENABLE(FULLSCREEN_API) diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h index 8d0f865ff..4bf2886e5 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h @@ -38,7 +38,7 @@ using namespace WebKit; WebKitWebViewBase* webkitWebViewBaseCreate(WebContext*, WebPageGroup*); GtkIMContext* webkitWebViewBaseGetIMContext(WebKitWebViewBase*); WebPageProxy* webkitWebViewBaseGetPage(WebKitWebViewBase*); -void webkitWebViewBaseCreateWebPage(WebKitWebViewBase*, WKContextRef, WKPageGroupRef); +void webkitWebViewBaseCreateWebPage(WebKitWebViewBase*, WebContext*, WebPageGroup*); void webkitWebViewBaseSetTooltipText(WebKitWebViewBase*, const char*); void webkitWebViewBaseSetTooltipArea(WebKitWebViewBase*, const WebCore::IntRect&); void webkitWebViewBaseForwardNextKeyEvent(WebKitWebViewBase*); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h index 5ad2853bb..6aa965d1c 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h @@ -28,33 +28,34 @@ #define WebKitWebViewPrivate_h #include "WebKitWebView.h" -#include <WebKit2/WebKit2_C.h> #include <wtf/text/CString.h> +using namespace WebKit; + void webkitWebViewLoadChanged(WebKitWebView*, WebKitLoadEvent); void webkitWebViewLoadFailed(WebKitWebView*, WebKitLoadEvent, const char* failingURI, GError*); void webkitWebViewSetEstimatedLoadProgress(WebKitWebView*, double estimatedLoadProgress); void webkitWebViewSetTitle(WebKitWebView*, const CString&); void webkitWebViewUpdateURI(WebKitWebView*); -WKPageRef webkitWebViewCreateNewPage(WebKitWebView*, WKDictionaryRef wkWindowFeatures); +WebPageProxy* webkitWebViewCreateNewPage(WebKitWebView*, ImmutableDictionary* windowFeatures); void webkitWebViewReadyToShowPage(WebKitWebView*); void webkitWebViewRunAsModal(WebKitWebView*); void webkitWebViewClosePage(WebKitWebView*); void webkitWebViewRunJavaScriptAlert(WebKitWebView*, const CString& message); bool webkitWebViewRunJavaScriptConfirm(WebKitWebView*, const CString& message); -WKStringRef webkitWebViewRunJavaScriptPrompt(WebKitWebView*, const CString& message, const CString& defaultText); +CString webkitWebViewRunJavaScriptPrompt(WebKitWebView*, const CString& message, const CString& defaultText); void webkitWebViewMakePermissionRequest(WebKitWebView*, WebKitPermissionRequest*); void webkitWebViewMakePolicyDecision(WebKitWebView*, WebKitPolicyDecisionType, WebKitPolicyDecision*); -void webkitWebViewMouseTargetChanged(WebKitWebView*, WKHitTestResultRef, unsigned modifiers); -void webkitWebViewPrintFrame(WebKitWebView*, WKFrameRef); -void webkitWebViewResourceLoadStarted(WebKitWebView*, WKFrameRef, uint64_t resourceIdentifier, WebKitURIRequest*); +void webkitWebViewMouseTargetChanged(WebKitWebView*, WebHitTestResult*, unsigned modifiers); +void webkitWebViewPrintFrame(WebKitWebView*, WebFrameProxy*); +void webkitWebViewResourceLoadStarted(WebKitWebView*, WebFrameProxy*, uint64_t resourceIdentifier, WebKitURIRequest*); void webkitWebViewRunFileChooserRequest(WebKitWebView*, WebKitFileChooserRequest*); WebKitWebResource* webkitWebViewGetLoadingWebResource(WebKitWebView*, uint64_t resourceIdentifier); void webkitWebViewRemoveLoadingWebResource(WebKitWebView*, uint64_t resourceIdentifier); WebKitWebResource* webkitWebViewResourceLoadFinished(WebKitWebView*, uint64_t resourceIdentifier); bool webkitWebViewEnterFullScreen(WebKitWebView*); bool webkitWebViewLeaveFullScreen(WebKitWebView*); -void webkitWebViewPopulateContextMenu(WebKitWebView*, WKArrayRef proposedMenu, WKHitTestResultRef); +void webkitWebViewPopulateContextMenu(WebKitWebView*, ImmutableArray* proposedMenu, WebHitTestResult*); void webkitWebViewSubmitFormRequest(WebKitWebView*, WebKitFormSubmissionRequest*); #endif // WebKitWebViewPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt index 4f5b36c4d..bbf979b64 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt @@ -70,6 +70,7 @@ WebKitSaveMode WEBKIT_EDITING_COMMAND_CUT WEBKIT_EDITING_COMMAND_COPY WEBKIT_EDITING_COMMAND_PASTE +WEBKIT_EDITING_COMMAND_SELECT_ALL <SUBSECTION> webkit_web_view_new diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebViewEditor.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebViewEditor.cpp index 97ebe5b27..93315db68 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebViewEditor.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebViewEditor.cpp @@ -131,10 +131,70 @@ static void testWebViewEditorCutCopyPasteEditable(EditorTest* test, gconstpointe g_assert_cmpstr(clipboardText.get(), ==, "All work and no play make Jack a dull boy."); } +static void testWebViewEditorSelectAllNonEditable(EditorTest* test, gconstpointer) +{ + static const char* selectedSpanHTML = "<html><body contentEditable=\"false\">" + "<span id=\"mainspan\">All work and no play <span id=\"subspan\">make Jack a dull</span> boy.</span>" + "<script>document.getSelection().collapse();\n" + "document.getSelection().selectAllChildren(document.getElementById('subspan'));\n" + "</script></body></html>"; + + g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL)); + + test->loadHtml(selectedSpanHTML, 0); + test->waitUntilLoadFinished(); + + g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL)); + + test->copyClipboard(); + GOwnPtr<char> clipboardText(gtk_clipboard_wait_for_text(test->m_clipboard)); + + // Initially only the subspan is selected. + g_assert_cmpstr(clipboardText.get(), ==, "make Jack a dull"); + + webkit_web_view_execute_editing_command(test->m_webView, WEBKIT_EDITING_COMMAND_SELECT_ALL); + test->copyClipboard(); + clipboardText.set(gtk_clipboard_wait_for_text(test->m_clipboard)); + + // The mainspan should be selected after calling SELECT_ALL. + g_assert_cmpstr(clipboardText.get(), ==, "All work and no play make Jack a dull boy."); +} + +static void testWebViewEditorSelectAllEditable(EditorTest* test, gconstpointer) +{ + static const char* selectedSpanHTML = "<html><body contentEditable=\"true\">" + "<span id=\"mainspan\">All work and no play <span id=\"subspan\">make Jack a dull</span> boy.</span>" + "<script>document.getSelection().collapse();\n" + "document.getSelection().selectAllChildren(document.getElementById('subspan'));\n" + "</script></body></html>"; + + g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL)); + + test->loadHtml(selectedSpanHTML, 0); + test->waitUntilLoadFinished(); + + g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL)); + + test->copyClipboard(); + GOwnPtr<char> clipboardText(gtk_clipboard_wait_for_text(test->m_clipboard)); + + // Initially only the subspan is selected. + g_assert_cmpstr(clipboardText.get(), ==, "make Jack a dull"); + + webkit_web_view_execute_editing_command(test->m_webView, WEBKIT_EDITING_COMMAND_SELECT_ALL); + test->copyClipboard(); + clipboardText.set(gtk_clipboard_wait_for_text(test->m_clipboard)); + + // The mainspan should be selected after calling SELECT_ALL. + g_assert_cmpstr(clipboardText.get(), ==, "All work and no play make Jack a dull boy."); +} + void beforeAll() { EditorTest::add("WebKitWebView", "cut-copy-paste/non-editable", testWebViewEditorCutCopyPasteNonEditable); EditorTest::add("WebKitWebView", "cut-copy-paste/editable", testWebViewEditorCutCopyPasteEditable); + EditorTest::add("WebKitWebView", "select-all/non-editable", testWebViewEditorSelectAllNonEditable); + EditorTest::add("WebKitWebView", "select-all/editable", testWebViewEditorSelectAllEditable); } void afterAll() diff --git a/Source/WebKit2/UIProcess/API/mac/WKProcessGroup.mm b/Source/WebKit2/UIProcess/API/mac/WKProcessGroup.mm index f19381891..8b4770046 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKProcessGroup.mm +++ b/Source/WebKit2/UIProcess/API/mac/WKProcessGroup.mm @@ -83,7 +83,7 @@ static void setUpConnectionClient(WKProcessGroup *processGroup, WKContextRef con _data = [[WKProcessGroupData alloc] init]; if (bundleURL) - _data->_contextRef = adoptWK(WKContextCreateWithInjectedBundlePath(adoptWK(WKStringCreateWithCFString((CFStringRef)[bundleURL absoluteString])).get())); + _data->_contextRef = adoptWK(WKContextCreateWithInjectedBundlePath(adoptWK(WKStringCreateWithCFString((CFStringRef)[bundleURL path])).get())); else _data->_contextRef = adoptWK(WKContextCreate()); diff --git a/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.h b/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.h index 3144a43b6..5945e1e28 100644 --- a/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.h +++ b/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.h @@ -61,9 +61,11 @@ public: bool useXPC; #endif #endif +#if PLATFORM(EFL) #ifndef NDEBUG String processCmdPrefix; #endif +#endif }; static PassRefPtr<ProcessLauncher> create(Client* client, const LaunchOptions& launchOptions) diff --git a/Source/WebKit2/UIProcess/WebProcessProxy.cpp b/Source/WebKit2/UIProcess/WebProcessProxy.cpp index 13ca474f3..579783eed 100644 --- a/Source/WebKit2/UIProcess/WebProcessProxy.cpp +++ b/Source/WebKit2/UIProcess/WebProcessProxy.cpp @@ -108,21 +108,8 @@ void WebProcessProxy::connect() ProcessLauncher::LaunchOptions launchOptions; launchOptions.processType = ProcessLauncher::WebProcess; - -#if PLATFORM(MAC) - // We want the web process to match the architecture of the UI process. - launchOptions.architecture = ProcessLauncher::LaunchOptions::MatchCurrentArchitecture; - launchOptions.executableHeap = false; -#if HAVE(XPC) - launchOptions.useXPC = getenv("WEBKIT_USE_XPC_SERVICE_FOR_WEB_PROCESS"); -#endif -#endif -#ifndef NDEBUG - const char* webProcessCmdPrefix = getenv("WEB_PROCESS_CMD_PREFIX"); - if (webProcessCmdPrefix && *webProcessCmdPrefix) - launchOptions.processCmdPrefix = String::fromUTF8(webProcessCmdPrefix); -#endif - + platformConnect(launchOptions); + m_processLauncher = ProcessLauncher::create(this, launchOptions); } diff --git a/Source/WebKit2/UIProcess/WebProcessProxy.h b/Source/WebKit2/UIProcess/WebProcessProxy.h index 2dc204f89..c4fd3c929 100644 --- a/Source/WebKit2/UIProcess/WebProcessProxy.h +++ b/Source/WebKit2/UIProcess/WebProcessProxy.h @@ -123,6 +123,7 @@ private: // Initializes the process launcher which will begin launching the process. void connect(); + void platformConnect(ProcessLauncher::LaunchOptions&); // Called when the web process has crashed or we know that it will terminate soon. // Will potentially cause the WebProcessProxy object to be freed. diff --git a/Source/WebKit2/UIProcess/cairo/BackingStoreCairo.cpp b/Source/WebKit2/UIProcess/cairo/BackingStoreCairo.cpp index ae0fd3669..4d98f9f0c 100644 --- a/Source/WebKit2/UIProcess/cairo/BackingStoreCairo.cpp +++ b/Source/WebKit2/UIProcess/cairo/BackingStoreCairo.cpp @@ -31,7 +31,7 @@ #include "UpdateInfo.h" #include "WebPageProxy.h" #include <WebCore/GraphicsContext.h> -#include <cairo/cairo.h> +#include <cairo.h> #if PLATFORM(EFL) #include "ewk_view_private.h" diff --git a/Source/WebKit2/UIProcess/efl/WebProcessProxyEfl.cpp b/Source/WebKit2/UIProcess/efl/WebProcessProxyEfl.cpp new file mode 100644 index 000000000..c057e9c34 --- /dev/null +++ b/Source/WebKit2/UIProcess/efl/WebProcessProxyEfl.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2012 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 "WebProcessProxy.h" + +namespace WebKit { + +void WebProcessProxy::platformConnect(ProcessLauncher::LaunchOptions& launchOptions) +{ +#ifndef NDEBUG + const char* webProcessCmdPrefix = getenv("WEB_PROCESS_CMD_PREFIX"); + if (webProcessCmdPrefix && *webProcessCmdPrefix) + launchOptions.processCmdPrefix = String::fromUTF8(webProcessCmdPrefix); +#else + UNUSED_PARAM(launchOptions); +#endif +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/gtk/WebProcessProxyGtk.cpp b/Source/WebKit2/UIProcess/gtk/WebProcessProxyGtk.cpp new file mode 100644 index 000000000..3ad528f27 --- /dev/null +++ b/Source/WebKit2/UIProcess/gtk/WebProcessProxyGtk.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2012 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 "WebProcessProxy.h" + +namespace WebKit { + +void WebProcessProxy::platformConnect(ProcessLauncher::LaunchOptions&) +{ +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/mac/WebProcessProxyMac.mm b/Source/WebKit2/UIProcess/mac/WebProcessProxyMac.mm index 66422a147..73f3ddc02 100644 --- a/Source/WebKit2/UIProcess/mac/WebProcessProxyMac.mm +++ b/Source/WebKit2/UIProcess/mac/WebProcessProxyMac.mm @@ -149,4 +149,15 @@ bool WebProcessProxy::fullKeyboardAccessEnabled() return [WKFullKeyboardAccessWatcher fullKeyboardAccessEnabled]; } +void WebProcessProxy::platformConnect(ProcessLauncher::LaunchOptions& launchOptions) +{ + // We want the web process to match the architecture of the UI process. + launchOptions.architecture = ProcessLauncher::LaunchOptions::MatchCurrentArchitecture; + launchOptions.executableHeap = false; + +#if HAVE(XPC) + launchOptions.useXPC = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKit2UseXPCServiceForWebProcess"]; +#endif +} + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/qt/WebProcessProxyQt.cpp b/Source/WebKit2/UIProcess/qt/WebProcessProxyQt.cpp new file mode 100644 index 000000000..3ad528f27 --- /dev/null +++ b/Source/WebKit2/UIProcess/qt/WebProcessProxyQt.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2012 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 "WebProcessProxy.h" + +namespace WebKit { + +void WebProcessProxy::platformConnect(ProcessLauncher::LaunchOptions&) +{ +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/win/WebProcessProxyWin.cpp b/Source/WebKit2/UIProcess/win/WebProcessProxyWin.cpp index 1856b3b00..fef2c68b3 100644 --- a/Source/WebKit2/UIProcess/win/WebProcessProxyWin.cpp +++ b/Source/WebKit2/UIProcess/win/WebProcessProxyWin.cpp @@ -33,4 +33,8 @@ Vector<HWND> WebProcessProxy::windowsToReceiveSentMessagesWhileWaitingForSyncRep return Vector<HWND>(); } +void WebProcessProxy::platformConnect(ProcessLauncher::LaunchOptions&) +{ +} + } // namespace WebKit diff --git a/Source/WebKit2/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp b/Source/WebKit2/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp index 18247b664..c635e6e84 100644 --- a/Source/WebKit2/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp +++ b/Source/WebKit2/WebProcess/InjectedBundle/API/c/WKBundlePage.cpp @@ -44,6 +44,7 @@ #include <WebCore/AccessibilityObject.h> #include <WebCore/Frame.h> #include <WebCore/KURL.h> +#include <WebCore/MIMETypeRegistry.h> #include <WebCore/Page.h> #if ENABLE(WEB_INTENTS) @@ -413,3 +414,21 @@ void WKBundlePageConfirmCompositionWithText(WKBundlePageRef pageRef, WKStringRef { toImpl(pageRef)->confirmCompositionForTesting(toImpl(text)->string()); } + +bool WKBundlePageCanShowMIMEType(WKBundlePageRef, WKStringRef mimeTypeRef) +{ + using WebCore::MIMETypeRegistry; + + const WTF::String mimeType = toImpl(mimeTypeRef)->string(); + + if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType)) + return true; + + if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType)) + return true; + + if (mimeType.startsWith("text/", false)) + return !MIMETypeRegistry::isUnsupportedTextMIMEType(mimeType); + + return false; +} diff --git a/Source/WebKit2/WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h b/Source/WebKit2/WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h index b7c82b811..c7393ba3f 100644 --- a/Source/WebKit2/WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h +++ b/Source/WebKit2/WebProcess/InjectedBundle/API/c/WKBundlePagePrivate.h @@ -71,8 +71,10 @@ WK_EXPORT bool WKBundlePageHasComposition(WKBundlePageRef page); WK_EXPORT void WKBundlePageConfirmComposition(WKBundlePageRef page); WK_EXPORT void WKBundlePageConfirmCompositionWithText(WKBundlePageRef page, WKStringRef text); +WK_EXPORT bool WKBundlePageCanShowMIMEType(WKBundlePageRef, WKStringRef mimeType); + WK_EXPORT void* WKAccessibilityRootObject(WKBundlePageRef); -WK_EXPORT void* WKAccessibilityFocusedObject(WKBundlePageRef); +WK_EXPORT void* WKAccessibilityFocusedObject(WKBundlePageRef); #ifdef __cplusplus } diff --git a/Source/WebKit2/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp b/Source/WebKit2/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp index da2478d5a..5c9e67872 100644 --- a/Source/WebKit2/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp +++ b/Source/WebKit2/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp @@ -39,7 +39,7 @@ #elif PLATFORM(GTK) #include "PlatformContextCairo.h" #include "RefPtrCairo.h" -#include <cairo/cairo-xlib.h> +#include <cairo-xlib.h> #include <gtk/gtk.h> #ifndef GTK_API_VERSION_2 #include <gtk/gtkx.h> diff --git a/Source/WebKit2/win/WebKit2.def b/Source/WebKit2/win/WebKit2.def index 1cdc404c0..e0b7da9ab 100644 --- a/Source/WebKit2/win/WebKit2.def +++ b/Source/WebKit2/win/WebKit2.def @@ -222,6 +222,7 @@ EXPORTS ?setDOMException@WebCore@@YAXPAVExecState@JSC@@H@Z ?setFantasyFontFamily@Settings@WebCore@@QAEXABVAtomicString@WTF@@W4UScriptCode@@@Z ?setFixedFontFamily@Settings@WebCore@@QAEXABVAtomicString@WTF@@W4UScriptCode@@@Z + ?setImagesEnabled@Settings@WebCore@@QAEX_N@Z ?setMockScrollbarsEnabled@Settings@WebCore@@SAX_N@Z ?mockScrollbarsEnabled@Settings@WebCore@@SA_NXZ ?setUsesOverlayScrollbars@Settings@WebCore@@SAX_N@Z @@ -289,3 +290,23 @@ EXPORTS ?numberOfPages@PrintContext@WebCore@@SAHPAVFrame@2@ABVFloatSize@2@@Z ?pageProperty@PrintContext@WebCore@@SA?AVString@WTF@@PAVFrame@2@PBDH@Z ?pageSizeAndMarginsInPixels@PrintContext@WebCore@@SA?AVString@WTF@@PAVFrame@2@HHHHHHH@Z + ??0InspectorFrontendClientLocal@WebCore@@QAE@PAVInspectorController@1@PAVPage@1@V?$PassOwnPtr@VSettings@InspectorFrontendClientLocal@WebCore@@@WTF@@@Z + ??1InspectorFrontendClientLocal@WebCore@@UAE@XZ + ?changeAttachedWindowHeight@InspectorFrontendClientLocal@WebCore@@UAEXI@Z + ?close@DOMWindow@WebCore@@QAEXPAVScriptExecutionContext@2@@Z + ?connectFrontend@InspectorController@WebCore@@QAEXPAVInspectorFrontendChannel@2@@Z + ?disconnectFrontend@InspectorController@WebCore@@QAEXXZ + ?document@DOMWindow@WebCore@@QBEPAVDocument@2@XZ + ?doDispatchMessageOnFrontendPage@InspectorClient@WebCore@@SA_NPAVPage@2@ABVString@WTF@@@Z + ?frontendLoaded@InspectorFrontendClientLocal@WebCore@@UAEXXZ + ?getProperty@Settings@InspectorFrontendClientLocal@WebCore@@UAE?AVString@WTF@@ABV45@@Z + ?moveWindowBy@InspectorFrontendClientLocal@WebCore@@UAEXMM@Z + ?open@DOMWindow@WebCore@@QAE?AV?$PassRefPtr@VDOMWindow@WebCore@@@WTF@@ABVString@4@ABVAtomicString@4@0PAV12@2@Z + ?openInNewTab@InspectorFrontendClientLocal@WebCore@@UAEXABVString@WTF@@@Z + ?requestAttachWindow@InspectorFrontendClientLocal@WebCore@@UAEXXZ + ?requestDetachWindow@InspectorFrontendClientLocal@WebCore@@UAEXXZ + ?sendMessageToBackend@InspectorFrontendClientLocal@WebCore@@UAEXABVString@WTF@@@Z + ?setInspectorFrontendClient@InspectorController@WebCore@@QAEXV?$PassOwnPtr@VInspectorFrontendClient@WebCore@@@WTF@@@Z + ?setProperty@Settings@InspectorFrontendClientLocal@WebCore@@UAEXABVString@WTF@@0@Z + ?toJS@WebCore@@YA?AVJSValue@JSC@@PAVExecState@3@PAVJSDOMGlobalObject@1@PAVDOMWindow@1@@Z + ?windowObjectCleared@InspectorFrontendClientLocal@WebCore@@UAEXXZ diff --git a/Source/WebKit2/win/WebKit2CFLite.def b/Source/WebKit2/win/WebKit2CFLite.def index 64bf790c0..3675ac250 100644 --- a/Source/WebKit2/win/WebKit2CFLite.def +++ b/Source/WebKit2/win/WebKit2CFLite.def @@ -279,3 +279,23 @@ EXPORTS ?numberOfPages@PrintContext@WebCore@@SAHPAVFrame@2@ABVFloatSize@2@@Z ?pageProperty@PrintContext@WebCore@@SA?AVString@WTF@@PAVFrame@2@PBDH@Z ?pageSizeAndMarginsInPixels@PrintContext@WebCore@@SA?AVString@WTF@@PAVFrame@2@HHHHHHH@Z + ??0InspectorFrontendClientLocal@WebCore@@QAE@PAVInspectorController@1@PAVPage@1@V?$PassOwnPtr@VSettings@InspectorFrontendClientLocal@WebCore@@@WTF@@@Z + ??1InspectorFrontendClientLocal@WebCore@@UAE@XZ + ?changeAttachedWindowHeight@InspectorFrontendClientLocal@WebCore@@UAEXI@Z + ?close@DOMWindow@WebCore@@QAEXPAVScriptExecutionContext@2@@Z + ?connectFrontend@InspectorController@WebCore@@QAEXPAVInspectorFrontendChannel@2@@Z + ?disconnectFrontend@InspectorController@WebCore@@QAEXXZ + ?document@DOMWindow@WebCore@@QBEPAVDocument@2@XZ + ?doDispatchMessageOnFrontendPage@InspectorClient@WebCore@@SA_NPAVPage@2@ABVString@WTF@@@Z + ?frontendLoaded@InspectorFrontendClientLocal@WebCore@@UAEXXZ + ?getProperty@Settings@InspectorFrontendClientLocal@WebCore@@UAE?AVString@WTF@@ABV45@@Z + ?moveWindowBy@InspectorFrontendClientLocal@WebCore@@UAEXMM@Z + ?open@DOMWindow@WebCore@@QAE?AV?$PassRefPtr@VDOMWindow@WebCore@@@WTF@@ABVString@4@ABVAtomicString@4@0PAV12@2@Z + ?openInNewTab@InspectorFrontendClientLocal@WebCore@@UAEXABVString@WTF@@@Z + ?requestAttachWindow@InspectorFrontendClientLocal@WebCore@@UAEXXZ + ?requestDetachWindow@InspectorFrontendClientLocal@WebCore@@UAEXXZ + ?sendMessageToBackend@InspectorFrontendClientLocal@WebCore@@UAEXABVString@WTF@@@Z + ?setInspectorFrontendClient@InspectorController@WebCore@@QAEXV?$PassOwnPtr@VInspectorFrontendClient@WebCore@@@WTF@@@Z + ?setProperty@Settings@InspectorFrontendClientLocal@WebCore@@UAEXABVString@WTF@@0@Z + ?toJS@WebCore@@YA?AVJSValue@JSC@@PAVExecState@3@PAVJSDOMGlobalObject@1@PAVDOMWindow@1@@Z + ?windowObjectCleared@InspectorFrontendClientLocal@WebCore@@UAEXXZ diff --git a/Source/api.pri b/Source/api.pri index b46696fe3..815cd77a9 100644 --- a/Source/api.pri +++ b/Source/api.pri @@ -31,9 +31,12 @@ MODULE = webkit QT_API_DEPENDS = core gui network build?(webkit1): QT_API_DEPENDS += widgets -# We want the QtWebKit API forwarding includes to live in the root build dir. -MODULE_BASE_DIR = $$_PRO_FILE_PWD_ -MODULE_BASE_OUTDIR = $$ROOT_BUILD_DIR +qmakeVersion=$$[QMAKE_VERSION] +equals(qmakeVersion, 3.0) { + # We want the QtWebKit API forwarding includes to live in the root build dir. + MODULE_BASE_DIR = $$_PRO_FILE_PWD_ + MODULE_BASE_OUTDIR = $$ROOT_BUILD_DIR +} # We load the relevant modules here, so that the effects of each module # on the QT variable can be picked up when we later load(qt_module). diff --git a/Source/autotools/symbols.filter b/Source/autotools/symbols.filter index d5d54106a..49676cf18 100644 --- a/Source/autotools/symbols.filter +++ b/Source/autotools/symbols.filter @@ -65,6 +65,7 @@ _ZN7WebCore14FormController22getReferencedFilePathsERKN3WTF6VectorINS1_6StringEL _ZN7WebCore14FrameSelection19absoluteCaretBoundsEv; _ZN7WebCore14SchemeRegistry49registerURLSchemeAsBypassingContentSecurityPolicyERKN3WTF6StringE; _ZN7WebCore14SchemeRegistry57removeURLSchemeRegisteredAsBypassingContentSecurityPolicyERKN3WTF6StringE; +_ZN7WebCore15InspectorClient31doDispatchMessageOnFrontendPageEPNS_4PageERKN3WTF6StringE; _ZN7WebCore15setDOMExceptionEPN3JSC9ExecStateEi; _ZN7WebCore15toDOMStringListEPN3JSC9ExecStateENS0_7JSValueE; _ZN7WebCore16HTMLInputElement17setSuggestedValueERKN3WTF6StringE; @@ -74,6 +75,9 @@ _ZN7WebCore17cacheDOMStructureEPNS_17JSDOMGlobalObjectEPN3JSC9StructureEPKNS2_9C _ZN7WebCore17HistoryController26saveDocumentAndScrollStateEv; _ZN7WebCore17InspectorCounters12counterValueENS0_11CounterTypeE; _ZN7WebCore18HTMLContentElement6createEPNS_8DocumentE; +_ZN7WebCore19InspectorController15connectFrontendEPNS_24InspectorFrontendChannelE; +_ZN7WebCore19InspectorController18disconnectFrontendEv; +_ZN7WebCore19InspectorController26setInspectorFrontendClientEN3WTF10PassOwnPtrINS_23InspectorFrontendClientEEE; _ZN7WebCore19InspectorController39setResourcesDataSizeLimitsFromInternalsEii; _ZN7WebCore20CachedResourceLoader31garbageCollectDocumentResourcesEv; _ZN7WebCore20NodeRenderingContextC1EPNS_4NodeE; @@ -92,10 +96,21 @@ _ZN7WebCore24DocumentMarkerController10markersForEPNS_4NodeENS_14DocumentMarker1 _ZN7WebCore24DocumentMarkerController18addTextMatchMarkerEPKNS_5RangeEb; _ZN7WebCore25computeViewportAttributesENS_17ViewportArgumentsEiiifNS_7IntSizeE; _ZN7WebCore25jsStringWithCacheSlowCaseEPN3JSC9ExecStateERN3WTF7HashMapIPNS3_10StringImplENS0_4WeakINS0_8JSStringEEENS3_7PtrHashIS6_EENS3_10HashTraitsIS6_EENSC_IS9_EEEES6_; +_ZN7WebCore28InspectorFrontendClientLocal12moveWindowByEff; +_ZN7WebCore28InspectorFrontendClientLocal12openInNewTabERKN3WTF6StringE; +_ZN7WebCore28InspectorFrontendClientLocal14frontendLoadedEv; +_ZN7WebCore28InspectorFrontendClientLocal19requestAttachWindowEv; +_ZN7WebCore28InspectorFrontendClientLocal19requestDetachWindowEv; +_ZN7WebCore28InspectorFrontendClientLocal19windowObjectClearedEv; +_ZN7WebCore28InspectorFrontendClientLocal20sendMessageToBackendERKN3WTF6StringE; +_ZN7WebCore28InspectorFrontendClientLocal26changeAttachedWindowHeightEj; +_ZN7WebCore28InspectorFrontendClientLocalC2EPNS_19InspectorControllerEPNS_4PageEN3WTF10PassOwnPtrINS0_8SettingsEEE; +_ZN7WebCore28InspectorFrontendClientLocalD2Ev; _ZN7WebCore30overrideUserPreferredLanguagesERKN3WTF6VectorINS0_6StringELj0EEE; _ZN7WebCore30overrideUserPreferredLanguagesERKN3WTF6VectorINS0_6StringELm0EEE; _ZN7WebCore40restrictMinimumScaleFactorToViewportSizeERNS_18ViewportAttributesENS_7IntSizeE; _ZN7WebCore4toJSEPN3JSC9ExecStateEPNS_17JSDOMGlobalObjectEPNS_13DOMStringListE; +_ZN7WebCore4toJSEPN3JSC9ExecStateEPNS_17JSDOMGlobalObjectEPNS_9DOMWindowE; _ZN7WebCore50restrictScaleFactorToInitialScaleIfNotUserScalableERNS_18ViewportAttributesE; _ZN7WebCore6JSNode10putVirtualEPN3JSC9ExecStateERKNS1_10IdentifierENS1_7JSValueERNS1_15PutPropertySlotE; _ZN7WebCore6JSNode20visitChildrenVirtualERN3JSC11SlotVisitorE; @@ -105,6 +120,8 @@ _ZN7WebCore7Element20removeShadowRootListEv; _ZN7WebCore7Element17setShadowPseudoIdERKN3WTF12AtomicStringERi; _ZN7WebCore7jsArrayEPN3JSC9ExecStateEPNS_17JSDOMGlobalObjectEN3WTF10PassRefPtrINS_13DOMStringListEEE; _ZN7WebCore7toRangeEN3JSC7JSValueE; +_ZN7WebCore9DOMWindow4openERKN3WTF6StringERKNS1_12AtomicStringES4_PS0_S8_; +_ZN7WebCore9DOMWindow5closeEPNS_22ScriptExecutionContextE; _ZN7WebCore9JSElement10putVirtualEPN3JSC9ExecStateERKNS1_10IdentifierENS1_7JSValueERNS1_15PutPropertySlotE; _ZN7WebCore9JSElement6s_infoE; _ZN7WebCore9toElementEN3JSC7JSValueE; @@ -145,6 +162,7 @@ _ZN7WebCore14ScrollableArea28setScrollOffsetFromInternalsERKNS_8IntPointE; _ZN7WebCore10ScrollView23setScrollbarsSuppressedEbb; _ZN7WebCore10ScrollView21setDelegatesScrollingEb; _ZN7WebCore4Node14removedLastRefEv; +_ZN7WebCore8Settings16setImagesEnabledEb; _ZN7WebCore8Settings18setFixedFontFamilyERKN3WTF12AtomicStringE11UScriptCode; _ZN7WebCore8Settings18setSerifFontFamilyERKN3WTF12AtomicStringE11UScriptCode; _ZN7WebCore8Settings20setCursiveFontFamilyERKN3WTF12AtomicStringE11UScriptCode; @@ -182,6 +200,8 @@ _ZN7WebCore26ContextDestructionObserver16contextDestroyedEv; _ZN7WebCore12PrintContext13numberOfPagesEPNS_5FrameERKNS_9FloatSizeE; _ZN7WebCore12PrintContext12pagePropertyEPNS_5FrameEPKci; _ZN7WebCore12PrintContext26pageSizeAndMarginsInPixelsEPNS_5FrameEiiiiiii; +_ZNK7WebCore9DOMWindow8documentEv; +_ZTVN7WebCore28InspectorFrontendClientLocal8SettingsE; local: _Z*; diff --git a/Source/cmake/OptionsEfl.cmake b/Source/cmake/OptionsEfl.cmake index 549056a3e..0ae4eced9 100644 --- a/Source/cmake/OptionsEfl.cmake +++ b/Source/cmake/OptionsEfl.cmake @@ -7,7 +7,7 @@ ADD_DEFINITIONS(-DBUILDING_EFL__=1) ADD_DEFINITIONS(-DWTF_PLATFORM_EFL=1) SET(WTF_PLATFORM_EFL 1) -FIND_PACKAGE(Cairo 1.10 REQUIRED) +FIND_PACKAGE(Cairo 1.10.2 REQUIRED) FIND_PACKAGE(Fontconfig 2.8.0 REQUIRED) FIND_PACKAGE(Sqlite REQUIRED) FIND_PACKAGE(LibXml2 2.6 REQUIRED) @@ -18,7 +18,7 @@ FIND_PACKAGE(JPEG REQUIRED) FIND_PACKAGE(PNG REQUIRED) FIND_PACKAGE(ZLIB REQUIRED) -FIND_PACKAGE(GLIB 2.31.8 REQUIRED COMPONENTS gio gobject gthread) +FIND_PACKAGE(GLIB 2.33.2 REQUIRED COMPONENTS gio gobject gthread) FIND_PACKAGE(LibSoup 2.39.4.1 REQUIRED) SET(ENABLE_GLIB_SUPPORT ON) @@ -77,6 +77,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NAVIGATOR_CONTENT_UTILS ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETSCAPE_PLUGIN_API OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETWORK_INFO ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_PAGE_VISIBILITY_API ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_REGIONS ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_REQUEST_ANIMATION_FRAME ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SHADOW_DOM ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SHARED_WORKERS ON) @@ -104,15 +105,15 @@ IF (ENABLE_ECORE_X) ENDIF () FIND_PACKAGE(Eina 1.2 REQUIRED) -FIND_PACKAGE(Evas 1.0 REQUIRED) +FIND_PACKAGE(Evas 1.2 REQUIRED) FIND_PACKAGE(Ecore 1.2 COMPONENTS Evas File Input ${ECORE_ADDITIONAL_COMPONENTS}) -FIND_PACKAGE(Edje 1.0 REQUIRED) +FIND_PACKAGE(Edje 1.2 REQUIRED) FIND_PACKAGE(Eeze 1.2 REQUIRED) -FIND_PACKAGE(Efreet 1.0 REQUIRED) -FIND_PACKAGE(E_DBus 1.1 COMPONENTS EUKit) +FIND_PACKAGE(Efreet 1.2 REQUIRED) +FIND_PACKAGE(E_DBus 1.2 COMPONENTS EUKit) -FIND_PACKAGE(Freetype REQUIRED) -FIND_PACKAGE(HarfBuzz REQUIRED) +FIND_PACKAGE(Freetype 2.4.2 REQUIRED) +FIND_PACKAGE(HarfBuzz 0.9.2 REQUIRED) SET(WTF_USE_FREETYPE 1) SET(WTF_USE_HARFBUZZ_NG 1) ADD_DEFINITIONS(-DWTF_USE_FREETYPE=1) |