diff options
author | tc@google.com <tc@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-01 22:31:35 +0000 |
---|---|---|
committer | tc@google.com <tc@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-01 22:31:35 +0000 |
commit | de56f378336660dcc848763c80267a5e063ae47d (patch) | |
tree | 7f551b88923b35bc4022ce6ab3a3f602fb60d91c /webkit/port | |
parent | dc4f63c80cb90efe594131030aad6776e5945fcc (diff) | |
download | chromium_src-de56f378336660dcc848763c80267a5e063ae47d.zip chromium_src-de56f378336660dcc848763c80267a5e063ae47d.tar.gz chromium_src-de56f378336660dcc848763c80267a5e063ae47d.tar.bz2 |
Merge the chrome_webkit_merge_branch back on to trunk. This brings us
up to webkit@36102.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2778 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/port')
106 files changed, 5598 insertions, 3559 deletions
diff --git a/webkit/port/DerivedSources.make b/webkit/port/DerivedSources.make index bff0853..b62ceca 100644 --- a/webkit/port/DerivedSources.make +++ b/webkit/port/DerivedSources.make @@ -642,6 +642,7 @@ all : \ V8CSSValueList.h \ V8CanvasGradient.h \ V8CanvasPattern.h \ + V8CanvasPixelArray.h \ V8CanvasRenderingContext2D.h \ V8CharacterData.h \ V8Comment.h \ @@ -663,6 +664,8 @@ all : \ V8Event.h \ V8EventException.h \ V8EventTargetNode.h \ + V8File.h \ + V8FileList.h \ V8HTMLAnchorElement.h \ V8HTMLAppletElement.h \ V8HTMLAreaElement.h \ @@ -724,6 +727,7 @@ all : \ V8HTMLTitleElement.h \ V8HTMLUListElement.h \ V8History.h \ + V8ImageData.h \ V8KeyboardEvent.h \ V8MediaList.h \ V8MessageEvent.h \ @@ -735,6 +739,7 @@ all : \ V8NodeIterator.h \ V8NodeList.h \ V8Notation.h \ + V8NSResolver.h \ V8OverflowEvent.h \ V8ProcessingInstruction.h \ V8ProgressEvent.h \ @@ -878,12 +883,14 @@ all : \ V8StyleSheet.h \ V8StyleSheetList.h \ V8Text.h \ + V8TextMetrics.h \ V8TextEvent.h \ V8TreeWalker.h \ V8UIEvent.h \ V8VoidCallback.h \ V8WheelEvent.h \ V8XMLHttpRequest.h \ + V8XMLHttpRequestUpload.h \ V8XMLHttpRequestException.h \ V8XMLSerializer.h \ V8XPathEvaluator.h \ @@ -918,24 +925,24 @@ ifeq ($(findstring ENABLE_SVG,$(FEATURE_DEFINES)), ENABLE_SVG) CSSPropertyNames.h : css/CSSPropertyNames.in css/SVGCSSPropertyNames.in if sort $< $(WebCore)/css/SVGCSSPropertyNames.in | uniq -d | grep -E '^[^#]'; then echo 'Duplicate value!'; exit 1; fi cat $< $(WebCore)/css/SVGCSSPropertyNames.in > CSSPropertyNames.in - perl "$(WebCore)/../../../webkit/pending/makeprop.pl" + perl "$(WebCore)/css/makeprop.pl" CSSValueKeywords.h : css/CSSValueKeywords.in css/SVGCSSValueKeywords.in # Lower case all the values, as CSS values are case-insensitive perl -ne 'print lc' $(WebCore)/css/SVGCSSValueKeywords.in > SVGCSSValueKeywords.in if sort $< SVGCSSValueKeywords.in | uniq -d | grep -E '^[^#]'; then echo 'Duplicate value!'; exit 1; fi cat $< SVGCSSValueKeywords.in > CSSValueKeywords.in - perl "$(WebCore)/../../../webkit/pending/makevalues.pl" + perl "$(WebCore)/css/makevalues.pl" else -CSSPropertyNames.h : css/CSSPropertyNames.in ../../../webkit/pending/makeprop.pl +CSSPropertyNames.h : css/CSSPropertyNames.in css/makeprop.pl cp $< CSSPropertyNames.in - perl "$(WebCore)/../../../webkit/pending/makeprop.pl" + perl "$(WebCore)/css/makeprop.pl" -CSSValueKeywords.h : css/CSSValueKeywords.in ../../../webkit/pending/makevalues.pl +CSSValueKeywords.h : css/CSSValueKeywords.in css/makevalues.pl cp $< CSSValueKeywords.in - perl "$(WebCore)/../../../pending/makevalues.pl" + perl "$(WebCore)/css/makevalues.pl" endif @@ -1009,62 +1016,79 @@ CharsetData.cpp : platform/text/mac/make-charset-table.pl platform/text/mac/char %Table.cpp: %.cpp $(CREATE_HASH_TABLE) $(CREATE_HASH_TABLE) $< > $@ +# -------- + # HTML tag and attribute names +ifeq ($(findstring ENABLE_VIDEO,$(FEATURE_DEFINES)), ENABLE_VIDEO) + HTML_FLAGS := $(HTML_FLAGS) ENABLE_VIDEO=1 +endif + +ifdef HTML_FLAGS + +HTMLNames.cpp : dom/make_names.pl html/HTMLTagNames.in html/HTMLAttributeNames.in + perl -I $(WebCore)/bindings/scripts $< --tags $(WebCore)/html/HTMLTagNames.in --attrs $(PORTROOT)/../pending/HTMLAttributeNames.in --extraDefines "$(HTML_FLAGS)" + +else + HTMLNames.cpp : dom/make_names.pl html/HTMLTagNames.in html/HTMLAttributeNames.in - perl $< --tags $(WebCore)/html/HTMLTagNames.in --attrs $(WebCore)/html/HTMLAttributeNames.in \ - --namespace HTML --namespacePrefix xhtml --cppNamespace WebCore --namespaceURI "http://www.w3.org/1999/xhtml" --attrsNullNamespace --output . + perl -I $(WebCore)/bindings/scripts $< --tags $(WebCore)/html/HTMLTagNames.in --attrs $(PORTROOT)/../pending/HTMLAttributeNames.in + +endif XMLNames.cpp : dom/make_names.pl xml/xmlattrs.in - perl $< --attrs $(WebCore)/xml/xmlattrs.in \ - --namespace XML --cppNamespace WebCore --namespaceURI "http://www.w3.org/XML/1998/namespace" --output . + perl -I $(WebCore)/bindings/scripts $< --attrs $(WebCore)/xml/xmlattrs.in + +# -------- ifeq ($(findstring ENABLE_SVG,$(FEATURE_DEFINES)), ENABLE_SVG) +WEBCORE_EXPORT_DEPENDENCIES := $(WEBCORE_EXPORT_DEPENDENCIES) WebCore.SVG.exp + ifeq ($(findstring ENABLE_SVG_USE,$(FEATURE_DEFINES)), ENABLE_SVG_USE) - SVG_FLAGS := $(SVG_FLAGS) ENABLE_SVG_USE=1 + SVG_FLAGS := $(SVG_FLAGS) ENABLE_SVG_USE=1 endif ifeq ($(findstring ENABLE_SVG_FONTS,$(FEATURE_DEFINES)), ENABLE_SVG_FONTS) - SVG_FLAGS := $(SVG_FLAGS) ENABLE_SVG_FONTS=1 + SVG_FLAGS := $(SVG_FLAGS) ENABLE_SVG_FONTS=1 endif ifeq ($(findstring ENABLE_SVG_FILTERS,$(FEATURE_DEFINES)), ENABLE_SVG_FILTERS) - SVG_FLAGS := $(SVG_FLAGS) ENABLE_SVG_FILTERS=1 + SVG_FLAGS := $(SVG_FLAGS) ENABLE_SVG_FILTERS=1 + WEBCORE_EXPORT_DEPENDENCIES := $(WEBCORE_EXPORT_DEPENDENCIES) WebCore.SVG.Filters.exp endif ifeq ($(findstring ENABLE_SVG_AS_IMAGE,$(FEATURE_DEFINES)), ENABLE_SVG_AS_IMAGE) - SVG_FLAGS := $(SVG_FLAGS) ENABLE_SVG_AS_IMAGE=1 + SVG_FLAGS := $(SVG_FLAGS) ENABLE_SVG_AS_IMAGE=1 endif - + ifeq ($(findstring ENABLE_SVG_ANIMATION,$(FEATURE_DEFINES)), ENABLE_SVG_ANIMATION) - SVG_FLAGS := $(SVG_FLAGS) ENABLE_SVG_ANIMATION=1 - endif + SVG_FLAGS := $(SVG_FLAGS) ENABLE_SVG_ANIMATION=1 + WEBCORE_EXPORT_DEPENDENCIES := $(WEBCORE_EXPORT_DEPENDENCIES) WebCore.SVG.Animation.exp +endif ifeq ($(findstring ENABLE_SVG_FOREIGN_OBJECT,$(FEATURE_DEFINES)), ENABLE_SVG_FOREIGN_OBJECT) - SVG_FLAGS := $(SVG_FLAGS) ENABLE_SVG_FOREIGN_OBJECT=1 + SVG_FLAGS := $(SVG_FLAGS) ENABLE_SVG_FOREIGN_OBJECT=1 + WEBCORE_EXPORT_DEPENDENCIES := $(WEBCORE_EXPORT_DEPENDENCIES) WebCore.SVG.ForeignObject.exp endif # SVG tag and attribute names (need to pass an extra flag if svg experimental features are enabled) + ifdef SVG_FLAGS + SVGElementFactory.cpp SVGNames.cpp : dom/make_names.pl svg/svgtags.in svg/svgattrs.in - perl $< --tags $(WebCore)/svg/svgtags.in --attrs $(WebCore)/svg/svgattrs.in --extraDefines "$(SVG_FLAGS)" \ - --namespace SVG --cppNamespace WebCore --namespaceURI "http://www.w3.org/2000/svg" --factory --attrsNullNamespace --output . + perl -I $(WebCore)/bindings/scripts $< --tags $(WebCore)/svg/svgtags.in --attrs $(WebCore)/svg/svgattrs.in --extraDefines "$(SVG_FLAGS)" else -# SVG tag and attribute names + SVGElementFactory.cpp SVGNames.cpp : dom/make_names.pl svg/svgtags.in svg/svgattrs.in - perl $< --tags $(WebCore)/svg/svgtags.in --attrs $(WebCore)/svg/svgattrs.in \ - --namespace SVG --cppNamespace WebCore --namespaceURI "http://www.w3.org/2000/svg" --factory --attrsNullNamespace --output . -endif + perl -I $(WebCore)/bindings/scripts $< --tags $(WebCore)/svg/svgtags.in --attrs $(WebCore)/svg/svgattrs.in -XLinkNames.cpp : dom/make_names.pl svg/xlinkattrs.in - perl $< --attrs $(WebCore)/svg/xlinkattrs.in \ - --namespace XLink --cppNamespace WebCore --namespaceURI "http://www.w3.org/1999/xlink" --output . +endif -# Add SVG Symbols to the WebCore exported symbols file +JSSVGElementWrapperFactory.cpp : SVGNames.cpp -WebCore.exp : WebCore.base.exp WebCore.SVG.exp - cat $^ > $@ +XLinkNames.cpp : dom/make_names.pl svg/xlinkattrs.in + perl -I $(WebCore)/bindings/scripts $< --attrs $(WebCore)/svg/xlinkattrs.in else @@ -1077,8 +1101,10 @@ SVGNames.cpp : XLinkNames.cpp : echo > $@ -WebCore.exp : WebCore.base.exp - cat $^ > $@ +# This file is autogenerated by make_names.pl when SVG is enabled. + +JSSVGElementWrapperFactory.cpp : + echo > $@ endif @@ -1110,7 +1136,7 @@ JS%.h : %.idl $(JS_BINDINGS_SCRIPTS) # new-style V8 bindings -V8_BINDINGS_SCRIPTS = \ +V8_SCRIPTS = \ $(PORTROOT)/bindings/scripts/CodeGenerator.pm \ $(PORTROOT)/bindings/scripts/CodeGeneratorV8.pm \ $(PORTROOT)/bindings/scripts/IDLParser.pm \ @@ -1120,7 +1146,7 @@ V8_BINDINGS_SCRIPTS = \ # Sometimes script silently fails (Cygwin problem?), # use a bounded loop to retry if so, but not do so forever. -V8%.h : %.idl $(V8_BINDINGS_SCRIPTS) +V8%.h : %.idl $(V8_SCRIPTS) for i in 1 2 3 4 5 6 7 8 9 10; do \ if test -e $@; then break; fi; \ perl -w -I $(PORTROOT)/bindings/scripts -I $(WebCore)/bindings/scripts $(PORTROOT)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT V8_BINDING" --generator V8 --include ../../../webkit/pending --include ../../../webkit/port/dom --include ../../../webkit/port/html --include ../../../webkit/port/page --include ../../../webkit/port/xml --include svg --include dom --include html --include css --include page --include xml --outputdir . $< ; \ diff --git a/webkit/port/bindings/scripts/CodeGenerator.pm b/webkit/port/bindings/scripts/CodeGenerator.pm index 7d7fe50..d6900ee 100644 --- a/webkit/port/bindings/scripts/CodeGenerator.pm +++ b/webkit/port/bindings/scripts/CodeGenerator.pm @@ -38,6 +38,7 @@ my $verbose = 0; my %primitiveTypeHash = ("int" => 1, "short" => 1, "long" => 1, "unsigned int" => 1, "unsigned short" => 1, "unsigned long" => 1, "float" => 1, + "unsigned long long" => 1, "double" => 1, "boolean" => 1, "void" => 1); my %podTypeHash = ("SVGLength" => 1, "SVGPoint" => 1, "SVGRect" => 1, "SVGNumber" => 1, "SVGMatrix" => 1, "SVGTransform" => 1); diff --git a/webkit/port/bindings/scripts/CodeGeneratorV8.pm b/webkit/port/bindings/scripts/CodeGeneratorV8.pm index f1c235f..7186575 100644 --- a/webkit/port/bindings/scripts/CodeGeneratorV8.pm +++ b/webkit/port/bindings/scripts/CodeGeneratorV8.pm @@ -268,7 +268,7 @@ sub GenerateHeader my $podType = $dataNode->extendedAttributes->{"PODType"}; my $passType = $podType ? "JSSVGPODTypeWrapper<$podType>*" : "$implClassName*"; - push(@headerContent, "#include \"$podType.h\"\n") if $podType and $podType ne "double"; + push(@headerContent, "#include \"$podType.h\"\n") if $podType and ($podType ne "double" and $podType ne "float" and $podType ne "RGBA32"); push(@headerContent, "#include <v8.h>\n"); push(@headerContent, "#include <wtf/HashMap.h>\n"); @@ -304,7 +304,7 @@ sub GenerateSetDOMException my $indent = shift; my $result = ""; - $result .= $indent . "if (ec != 0) {\n"; + $result .= $indent . "if (ec) {\n"; $result .= $indent . " V8Proxy::SetDOMException(ec);\n"; $result .= $indent . " return v8::Handle<v8::Value>();\n"; $result .= $indent . "}\n"; @@ -530,6 +530,9 @@ END } else { $getterString = "imp_instance"; } + if ($nativeType eq "String") { + $getterString = "ToString($getterString)"; + } my $result; my $wrapper; @@ -584,7 +587,7 @@ sub GenerateReplaceableAttrSetter push(@implContentDecls, " static void ${attrName}AttrSetter(v8::Local<v8::String> name," . - " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n"); + " v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n{\n"); push(@implContentDecls, " INC_STATS(L\"DOM.$implClassName.$attrName._set\");\n"); @@ -608,7 +611,7 @@ sub GenerateNormalAttrSetter push(@implContentDecls, " static void ${attrName}AttrSetter(v8::Local<v8::String> name," . - " v8::Local<v8::Value> value, const v8::AccessorInfo& info) {\n"); + " v8::Local<v8::Value> value, const v8::AccessorInfo& info)\n{\n"); push(@implContentDecls, " INC_STATS(L\"DOM.$implClassName.$attrName._set\");\n"); @@ -722,7 +725,7 @@ sub GenerateFunctionCallback my $name = $function->signature->name; push(@implContentDecls, -" static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args) {\n" . +" static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args)\n{\n" . " INC_STATS(L\"DOM.$implClassName.$name\");\n"); my $numParameters = @{$function->parameters}; @@ -871,7 +874,11 @@ sub GenerateImplementation } # Generate the accessor. - GenerateNormalAttrGetter($attribute, $dataNode, $classIndex, $implClassName); + if ($attribute->signature->extendedAttributes->{"CustomGetter"}) { + $implIncludes{"v8_custom.h"} = 1; + } else { + GenerateNormalAttrGetter($attribute, $dataNode, $classIndex, $implClassName); + } if ($attribute->signature->extendedAttributes->{"CustomSetter"}) { $implIncludes{"v8_custom.h"} = 1; } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) { @@ -930,7 +937,7 @@ sub GenerateImplementation } } - my $customAccessor = $attrExt->{"Custom"} || $attrExt->{"CustomSetter"} || ""; + my $customAccessor = $attrExt->{"Custom"} || $attrExt->{"CustomSetter"} || $attrExt->{"CustomGetter"} || ""; if ($customAccessor eq 1) { # use the naming convension, interface + (capitalize) attr name $customAccessor = $interfaceName . WK_ucfirst($attrName); @@ -967,7 +974,12 @@ sub GenerateImplementation } elsif ($attrExt->{"CustomSetter"}) { $getter = "${interfaceName}Internal::${attrName}AttrGetter"; $setter = "V8Custom::v8${customAccessor}AccessorSetter"; - + + # Custom Getter + } elsif ($attrExt->{"CustomGetter"}) { + $getter = "V8Custom::v8${customAccessor}AccessorGetter"; + $setter = "${interfaceName}Internal::${attrName}AttrSetter"; + # Replaceable } elsif ($attrExt->{"Replaceable"}) { # Replaceable accessor is put on instance template with ReadOnly attribute. @@ -1233,9 +1245,15 @@ sub GenerateFunctionCallString() # This is a bit of a hack... we need to convert parameters to methods on SVG lists # of POD types which are items in the list to appropriate SVGList<> instances if ($returnsListItemPodType && $paramType . "List" eq $implClassName) { - $paramName = "new SVGPODListItem<" . GetNativeType($paramType, 1) . ">($paramName)"; + $paramName = "SVGPODListItem<" . GetNativeType($paramType, 1) . ">::copy($paramName)"; + } + + if ($parameter->type eq "NodeFilter") { + $functionString .= "$paramName.get()"; + } else { + $functionString .= $paramName; } - $functionString .= $paramName; + if ($parameter->extendedAttributes->{"Return"}) { $nodeToReturn = $parameter->name; } @@ -1383,6 +1401,7 @@ sub IsRefPtrType return 1 if $type eq "CSSMediaRule"; return 1 if $type eq "CSSFontFaceRule"; return 1 if $type eq "CSSPageRule"; + return 1 if $type eq "CSSPrimitiveValue"; return 1 if $type eq "CSSStyleSheet"; return 1 if $type eq "CSSStyleDeclaration"; return 1 if $type eq "CSSValue"; @@ -1397,21 +1416,25 @@ sub IsRefPtrType return 1 if $type eq "HTMLDocument"; return 1 if $type eq "HTMLElement"; return 1 if $type eq "HTMLOptionsCollection"; + return 1 if $type eq "ImageData"; return 1 if $type eq "Node"; return 1 if $type eq "NodeList"; return 1 if $type eq "NodeFilter"; return 1 if $type eq "NodeIterator"; + return 1 if $type eq "NSResolver"; return 1 if $type eq "ProcessingInstruction"; return 1 if $type eq "Range"; return 1 if $type eq "Text"; + return 1 if $type eq "TextMetrics"; return 1 if $type eq "TreeWalker"; return 1 if $type eq "XPathExpression"; return 1 if $type eq "XPathNSResolver"; return 1 if $type eq "XPathResult"; + return 1 if $type eq "SVGAngle"; return 1 if $type eq "SVGElementInstance"; return 1 if $type eq "SVGElementInstanceList"; - return 1 if $type eq "SVGPathSeg"; + return 1 if $type =~ /^SVGPathSeg/; return 1 if $type =~ /^SVGAnimated/; @@ -1429,6 +1452,7 @@ sub GetNativeType return "int" if $type eq "short" or $type eq "unsigned short"; return "int" if $type eq "long" or $type eq "unsigned long"; + return "unsigned long long" if $type eq "unsigned long long"; return "bool" if $type eq "boolean"; return "String" if $type eq "DOMString"; return "Range::CompareHow" if $type eq "CompareHow"; @@ -1441,12 +1465,16 @@ sub GetNativeType return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType"; return "DOMTimeStamp" if $type eq "DOMTimeStamp"; return "RGBColor" if $type eq "RGBColor"; + return "EventTargetNode*" if $type eq "EventTarget" and $isParameter; return "String" if $type eq "DOMUserData"; # temporary hack, TODO # temporary hack $type = GetImplementationClassName($type); + # temporary hack + return "RefPtr<NodeFilter>" if $type eq "NodeFilter"; + return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter; # Default, assume native type is a pointer with same type name as idl type @@ -1469,6 +1497,7 @@ my %typeCanFailConversion = ( "HTMLOptionElement" => 0, "Node" => 0, "NodeFilter" => 0, + "NSResolver" => 0, "Range" => 0, "SQLResultSet" => 0, "SVGAngle" => 0, @@ -1740,6 +1769,10 @@ sub NativeToJSValue AddIncludesForType($type); # $implIncludes{GetImplementationFileName($type)} = 1 unless AvoidInclusionOfType($type); + if ($type eq "CSSStyleDeclaration") { + $implIncludes{"CSSMutableStyleDeclaration.h"} = 1; + } + # special case for non-DOM node interfaces if (IsDOMNodeType($type)) { return "V8Proxy::NodeToV8Object($value)"; @@ -1770,7 +1803,7 @@ sub NativeToJSValue $value = GenerateReadOnlyPodTypeWrapper($type, $value); } - return "V8Proxy::ToV8Object(V8ClassIndex::$classIndex, static_cast<Peerable*>($value))"; + return "V8Proxy::ToV8Object(V8ClassIndex::$classIndex, $value)"; } } diff --git a/webkit/port/bindings/v8/JSNSResolver.cpp b/webkit/port/bindings/v8/JSNSResolver.cpp new file mode 100644 index 0000000..5251a35 --- /dev/null +++ b/webkit/port/bindings/v8/JSNSResolver.cpp @@ -0,0 +1,99 @@ +// Copyright (c) 2008, 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 "JSNSResolver.h" + +#include "v8_proxy.h" +#include "v8_binding.h" +#include "ExceptionContext.h" +#include "PlatformString.h" + +namespace WebCore { + +JSNSResolver::JSNSResolver(v8::Handle<v8::Object> resolver) + : m_resolver(resolver) +{ +} + +JSNSResolver::~JSNSResolver() +{ +} + +String JSNSResolver::lookupNamespaceURI(ExceptionContext* exceptionContext, + const String& prefix) +{ + v8::Handle<v8::Function> lookupNamespaceURIFunc; + v8::Handle<v8::String> lookupNamespaceURIName = + v8::String::New("lookupNamespaceURI"); + + // Check if the resolver has a function property named lookupNamespaceURI. + if (m_resolver->Has(lookupNamespaceURIName)) { + // In case the property is a getter that throws an error, + // see LayoutTests/fast/dom/SelectorAPI/NSResolver-exceptions.xhtml + ExceptionCatcher exceptionCatcher(exceptionContext); + v8::Handle<v8::Value> lookupNamespaceURI = m_resolver->Get( + lookupNamespaceURIName); + if (exceptionContext->hadException()) + return String(); + if (lookupNamespaceURI->IsFunction()) { + lookupNamespaceURIFunc = v8::Handle<v8::Function>::Cast( + lookupNamespaceURI); + } + } + + if (lookupNamespaceURIFunc.IsEmpty() && !m_resolver->IsFunction()) { + Frame* frame = ScriptController::retrieveActiveFrame(); + log_info(frame, "NSResolver does not have a lookupNamespaceURI method.", + String()); + return String(); + } + + // Catch exceptions from calling the namespace resolver. + ExceptionCatcher exceptionCatcher(exceptionContext); + + const int argc = 1; + v8::Handle<v8::Value> argv[argc] = { v8String(prefix) }; + v8::Handle<v8::Function> function = lookupNamespaceURIFunc.IsEmpty() + ? v8::Handle<v8::Function>::Cast(m_resolver) + : lookupNamespaceURIFunc; + + V8Proxy* proxy = V8Proxy::retrieve(); + v8::Handle<v8::Value> retval = proxy->CallFunction(function, m_resolver, + argc, argv); + + // Eat exceptions from namespace resolver and return an empty string. This + // will cause NAMESPACE_ERR. + if (exceptionContext->hadException()) + return String(); + + return valueToStringWithNullOrUndefinedCheck(retval); +} + +} diff --git a/webkit/port/bindings/v8/JSNSResolver.h b/webkit/port/bindings/v8/JSNSResolver.h new file mode 100644 index 0000000..84bd072 --- /dev/null +++ b/webkit/port/bindings/v8/JSNSResolver.h @@ -0,0 +1,58 @@ +// Copyright (c) 2008, 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. + + +// The wrapper for a JS object that implements NSResolver interface. + +#ifndef JSNSResolver_h +#define JSNSResolver_h + +#include <v8.h> +#include <wtf/RefCounted.h> +#include "NSResolver.h" + +namespace WebCore { + +class ExceptionContext; +class String; + +class JSNSResolver : public NSResolver { +public: + JSNSResolver(v8::Handle<v8::Object>); + virtual ~JSNSResolver(); + + virtual String lookupNamespaceURI(ExceptionContext*, const String&); + +private: + v8::Handle<v8::Object> m_resolver; // Handle to resolver object. +}; + +} + +#endif // !defined(JSNSResolver_h) diff --git a/webkit/port/bindings/v8/V8SVGPODTypeWrapper.h b/webkit/port/bindings/v8/V8SVGPODTypeWrapper.h index 488ab2b..94ddf5d 100644 --- a/webkit/port/bindings/v8/V8SVGPODTypeWrapper.h +++ b/webkit/port/bindings/v8/V8SVGPODTypeWrapper.h @@ -160,11 +160,14 @@ struct PODTypeReadWriteHashInfo { { } // Deleted value - explicit PODTypeReadWriteHashInfo(bool) + explicit PODTypeReadWriteHashInfo(WTF::HashTableDeletedValueType) : creator(reinterpret_cast<PODTypeCreator*>(-1)) - , getter(0) - , setter(0) - { } + { + } + bool isHashTableDeletedValue() const + { + return creator == reinterpret_cast<PODTypeCreator*>(-1); + } PODTypeReadWriteHashInfo(PODTypeCreator* _creator, GetterMethod _getter, SetterMethod _setter) : creator(_creator) @@ -202,19 +205,25 @@ struct PODTypeReadWriteHashInfoHash { template<typename PODType, typename PODTypeCreator> struct PODTypeReadWriteHashInfoTraits : WTF::GenericHashTraits<PODTypeReadWriteHashInfo<PODType, PODTypeCreator> > { + typedef PODTypeReadWriteHashInfo<PODType, PODTypeCreator> CacheInfo; + static const bool emptyValueIsZero = true; static const bool needsDestruction = false; - static const PODTypeReadWriteHashInfo<PODType, PODTypeCreator>& deletedValue() + static const CacheInfo& emptyValue() { - static PODTypeReadWriteHashInfo<PODType, PODTypeCreator> key(true); + static CacheInfo key; return key; } - static const PODTypeReadWriteHashInfo<PODType, PODTypeCreator>& emptyValue() + static void constructDeletedValue(CacheInfo& slot) { - static PODTypeReadWriteHashInfo<PODType, PODTypeCreator> key; - return key; + new (&slot) CacheInfo(WTF::HashTableDeletedValue); + } + + static bool isDeletedValue(const CacheInfo& value) + { + return value.isHashTableDeletedValue(); } }; @@ -260,7 +269,7 @@ public: if (it->second != wrapper) continue; - // It's guaruanteed that there's just one object we need to take care of. + // It's guaranteed that there's just one object we need to take care of. map.remove(it->first); break; } diff --git a/webkit/port/bindings/v8/V8XMLHttpRequestCustom.cpp b/webkit/port/bindings/v8/V8XMLHttpRequestCustom.cpp new file mode 100644 index 0000000..0c2cda0 --- /dev/null +++ b/webkit/port/bindings/v8/V8XMLHttpRequestCustom.cpp @@ -0,0 +1,792 @@ +// Copyright (c) 2008, 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 "v8_binding.h" +#include "v8_custom.h" +#include "v8_events.h" +#include "v8_proxy.h" + +#include "V8Document.h" +#include "V8HTMLDocument.h" + +#include "ExceptionCode.h" +#include "Frame.h" +#include "XMLHttpRequest.h" +#include "XMLHttpRequestUpload.h" + +namespace WebCore { + +CALLBACK_FUNC_DECL(XMLHttpRequestConstructor) { + INC_STATS(L"DOM.XMLHttpRequest.Constructor"); + + if (!args.IsConstructCall()) { + V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, + "DOM object constructor cannot be called as a function."); + return v8::Undefined(); + } + // Expect no parameters. + // Allocate a XMLHttpRequest object as its internal field. + Document* doc = V8Proxy::retrieveFrame()->document(); + RefPtr<XMLHttpRequest> xhr = XMLHttpRequest::create(doc); + V8Proxy::SetDOMWrapper(args.Holder(), + V8ClassIndex::ToInt(V8ClassIndex::XMLHTTPREQUEST), xhr.get()); + // Set object as the peer. + V8Proxy::SetJSWrapperForDOMObject(xhr.get(), + v8::Persistent<v8::Object>::New(args.Holder())); + return args.Holder(); +} + +// XMLHttpRequest -------------------------------------------------------------- + +// Use an array to hold dependents. It works like a ref-counted scheme. +// A value can be added more than once to the xhr object. +static void CreateHiddenXHRDependency(v8::Local<v8::Object> xhr, + v8::Local<v8::Value> value) { + ASSERT(V8Proxy::GetDOMWrapperType(xhr) == V8ClassIndex::XMLHTTPREQUEST || + V8Proxy::GetDOMWrapperType(xhr) == V8ClassIndex::XMLHTTPREQUESTUPLOAD); + v8::Local<v8::Value> cache = + xhr->GetInternalField(V8Custom::kXMLHttpRequestCacheIndex); + if (cache->IsNull() || cache->IsUndefined()) { + cache = v8::Array::New(); + xhr->SetInternalField(V8Custom::kXMLHttpRequestCacheIndex, cache); + } + + v8::Local<v8::Array> cache_array = v8::Local<v8::Array>::Cast(cache); + cache_array->Set(v8::Integer::New(cache_array->Length()), value); +} + +static void RemoveHiddenXHRDependency(v8::Local<v8::Object> xhr, + v8::Local<v8::Value> value) { + ASSERT(V8Proxy::GetDOMWrapperType(xhr) == V8ClassIndex::XMLHTTPREQUEST || + V8Proxy::GetDOMWrapperType(xhr) == V8ClassIndex::XMLHTTPREQUESTUPLOAD); + v8::Local<v8::Value> cache = + xhr->GetInternalField(V8Custom::kXMLHttpRequestCacheIndex); + ASSERT(cache->IsArray()); + v8::Local<v8::Array> cache_array = v8::Local<v8::Array>::Cast(cache); + for (int i = cache_array->Length() - 1; i >= 0; i--) { + v8::Local<v8::Value> cached = cache_array->Get(v8::Integer::New(i)); + if (cached->StrictEquals(value)) { + cache_array->Delete(i); + return; + } + } + + // We should only get here if we try to remove an event listener that was + // never added. +} + +ACCESSOR_GETTER(XMLHttpRequestOnabort) { + INC_STATS(L"DOM.XMLHttpRequest.onabort._get"); + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + if (imp->onAbortListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onAbortListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + return v8_listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(XMLHttpRequestOnabort) { + INC_STATS(L"DOM.XMLHttpRequest.onabort._set"); + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + if (value->IsNull()) { + if (imp->onAbortListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onAbortListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + RemoveHiddenXHRDependency(info.Holder(), v8_listener); + } + + // Clear the listener + imp->setOnAbortListener(0); + } else { + V8Proxy* proxy = V8Proxy::retrieve(imp->document()->frame()); + if (!proxy) + return; + + EventListener* listener = proxy->FindOrCreateXHREventListener(value, false); + if (listener) { + imp->setOnAbortListener(listener); + CreateHiddenXHRDependency(info.Holder(), value); + } + } +} + +ACCESSOR_GETTER(XMLHttpRequestOnerror) { + INC_STATS(L"DOM.XMLHttpRequest.onerror._get"); + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + if (imp->onErrorListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onErrorListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + return v8_listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(XMLHttpRequestOnerror) { + INC_STATS(L"DOM.XMLHttpRequest.onerror._set"); + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + if (value->IsNull()) { + if (imp->onErrorListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onErrorListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + RemoveHiddenXHRDependency(info.Holder(), v8_listener); + } + + // Clear the listener + imp->setOnErrorListener(0); + } else { + V8Proxy* proxy = V8Proxy::retrieve(imp->document()->frame()); + if (!proxy) + return; + + EventListener* listener = proxy->FindOrCreateXHREventListener(value, false); + if (listener) { + imp->setOnErrorListener(listener); + CreateHiddenXHRDependency(info.Holder(), value); + } + } +} + +ACCESSOR_GETTER(XMLHttpRequestOnload) { + INC_STATS(L"DOM.XMLHttpRequest.onload._get"); + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + if (imp->onLoadListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onLoadListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + return v8_listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(XMLHttpRequestOnload) +{ + INC_STATS(L"DOM.XMLHttpRequest.onload._set"); + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + if (value->IsNull()) { + if (imp->onload()) { + V8XHREventListener* listener = static_cast<V8XHREventListener*>(imp->onload()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + RemoveHiddenXHRDependency(info.Holder(), v8_listener); + } + + imp->setOnload(0); + + } else { + V8Proxy* proxy = V8Proxy::retrieve(imp->document()->frame()); + if (!proxy) + return; + + EventListener* listener = proxy->FindOrCreateXHREventListener(value, false); + if (listener) { + imp->setOnload(listener); + CreateHiddenXHRDependency(info.Holder(), value); + } + } +} + +ACCESSOR_GETTER(XMLHttpRequestOnloadstart) { + INC_STATS(L"DOM.XMLHttpRequest.onloadstart._get"); + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + if (imp->onLoadStartListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onLoadStartListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + return v8_listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(XMLHttpRequestOnloadstart) { + INC_STATS(L"DOM.XMLHttpRequest.onloadstart._set"); + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + if (value->IsNull()) { + if (imp->onLoadStartListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onLoadStartListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + RemoveHiddenXHRDependency(info.Holder(), v8_listener); + } + + // Clear the listener + imp->setOnLoadStartListener(0); + } else { + V8Proxy* proxy = V8Proxy::retrieve(imp->document()->frame()); + if (!proxy) + return; + + EventListener* listener = proxy->FindOrCreateXHREventListener(value, false); + if (listener) { + imp->setOnLoadStartListener(listener); + CreateHiddenXHRDependency(info.Holder(), value); + } + } +} + +ACCESSOR_GETTER(XMLHttpRequestOnprogress) { + INC_STATS(L"DOM.XMLHttpRequest.onprogress._get"); + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + if (imp->onProgressListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onProgressListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + return v8_listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(XMLHttpRequestOnprogress) { + INC_STATS(L"DOM.XMLHttpRequest.onprogress._set"); + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + if (value->IsNull()) { + if (imp->onProgressListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onProgressListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + RemoveHiddenXHRDependency(info.Holder(), v8_listener); + } + + // Clear the listener + imp->setOnProgressListener(0); + } else { + V8Proxy* proxy = V8Proxy::retrieve(imp->document()->frame()); + if (!proxy) + return; + + EventListener* listener = proxy->FindOrCreateXHREventListener(value, false); + if (listener) { + imp->setOnProgressListener(listener); + CreateHiddenXHRDependency(info.Holder(), value); + } + } +} + +ACCESSOR_GETTER(XMLHttpRequestOnreadystatechange) { + INC_STATS(L"DOM.XMLHttpRequest.onreadystatechange._get"); + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + if (imp->onReadyStateChangeListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onReadyStateChangeListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + return v8_listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(XMLHttpRequestOnreadystatechange) +{ + INC_STATS(L"DOM.XMLHttpRequest.onreadystatechange._set"); + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + if (value->IsNull()) { + if (imp->onreadystatechange()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onreadystatechange()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + RemoveHiddenXHRDependency(info.Holder(), v8_listener); + } + + // Clear the listener + imp->setOnreadystatechange(0); + } else { + V8Proxy* proxy = V8Proxy::retrieve(imp->document()->frame()); + if (!proxy) + return; + + EventListener* listener = proxy->FindOrCreateXHREventListener(value, false); + if (listener) { + imp->setOnreadystatechange(listener); + CreateHiddenXHRDependency(info.Holder(), value); + } + } +} + +CALLBACK_FUNC_DECL(XMLHttpRequestAddEventListener) +{ + INC_STATS(L"DOM.XMLHttpRequest.addEventListener()"); + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + + V8Proxy* proxy = V8Proxy::retrieve(imp->document()->frame()); + if (!proxy) + return v8::Undefined(); + + EventListener* listener = proxy->FindOrCreateXHREventListener(args[1], false); + if (listener) { + String type = ToWebCoreString(args[0]); + bool useCapture = args[2]->BooleanValue(); + imp->addEventListener(type, listener, useCapture); + + CreateHiddenXHRDependency(args.Holder(), args[1]); + } + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(XMLHttpRequestRemoveEventListener) { + INC_STATS(L"DOM.XMLHttpRequest.removeEventListener()"); + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + + V8Proxy* proxy = V8Proxy::retrieve(imp->document()->frame()); + if (!proxy) + return v8::Undefined(); // probably leaked + + EventListener* listener = + proxy->FindXHREventListener(args[1], false); + + if (listener) { + String type = ToWebCoreString(args[0]); + bool useCapture = args[2]->BooleanValue(); + imp->removeEventListener(type, listener, useCapture); + + RemoveHiddenXHRDependency(args.Holder(), args[1]); + } + + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(XMLHttpRequestOpen) +{ + INC_STATS(L"DOM.XMLHttpRequest.open()"); + // Four cases: + // open(method, url) + // open(method, url, async) + // open(method, url, async, user) + // open(method, url, async, user, passwd) + + if (args.Length() < 2) { + V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments"); + return v8::Undefined(); + } + + // get the implementation + XMLHttpRequest* xhr = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + + // retrieve parameters + String method = ToWebCoreString(args[0]); + String urlstring = ToWebCoreString(args[1]); + V8Proxy* proxy = V8Proxy::retrieve(); + KURL url = proxy->frame()->document()->completeURL(urlstring); + + bool async = (args.Length() < 3) ? true : args[2]->BooleanValue(); + + ExceptionCode ec = 0; + String user, passwd; + if (args.Length() >= 4 && !args[3]->IsUndefined()) { + user = valueToStringWithNullCheck(args[3]); + + if (args.Length() >= 5 && !args[4]->IsUndefined()) { + passwd = valueToStringWithNullCheck(args[4]); + xhr->open(method, url, async, user, passwd, ec); + } else + xhr->open(method, url, async, user, ec); + } else + xhr->open(method, url, async, ec); + + if (ec != 0) { + V8Proxy::SetDOMException(ec); + return v8::Handle<v8::Value>(); + } + + return v8::Undefined(); +} + +static bool IsDocumentType(v8::Handle<v8::Value> value) +{ + // TODO(fqian): add other document types. + return V8Document::HasInstance(value) || V8HTMLDocument::HasInstance(value); +} + +CALLBACK_FUNC_DECL(XMLHttpRequestSend) +{ + INC_STATS(L"DOM.XMLHttpRequest.send()"); + XMLHttpRequest* xhr = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + + ExceptionCode ec = 0; + if (args.Length() < 1) + xhr->send(ec); + else { + v8::Handle<v8::Value> arg = args[0]; + // TODO(eseidel): upstream handles "File" objects too + if (IsDocumentType(arg)) { + v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(arg); + Document* doc = V8Proxy::DOMWrapperToNode<Document>(obj); + ASSERT(doc); + xhr->send(doc, ec); + } else + xhr->send(valueToStringWithNullCheck(arg), ec); + } + + if (ec) { + V8Proxy::SetDOMException(ec); + return v8::Handle<v8::Value>(); + } + + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(XMLHttpRequestSetRequestHeader) { + INC_STATS(L"DOM.XMLHttpRequest.setRequestHeader()"); + if (args.Length() < 2) { + V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments"); + return v8::Undefined(); + } + + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + ExceptionCode ec = 0; + String header = ToWebCoreString(args[0]); + String value = ToWebCoreString(args[1]); + imp->setRequestHeader(header, value, ec); + if (ec != 0) { + V8Proxy::SetDOMException(ec); + return v8::Handle<v8::Value>(); + } + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(XMLHttpRequestGetResponseHeader) { + INC_STATS(L"DOM.XMLHttpRequest.getResponseHeader()"); + if (args.Length() < 1) { + V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments"); + return v8::Undefined(); + } + + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + ExceptionCode ec = 0; + String header = ToWebCoreString(args[0]); + String result = imp->getResponseHeader(header, ec); + if (ec != 0) { + V8Proxy::SetDOMException(ec); + return v8::Handle<v8::Value>(); + } + return v8StringOrNull(result); +} + +CALLBACK_FUNC_DECL(XMLHttpRequestOverrideMimeType) +{ + INC_STATS(L"DOM.XMLHttpRequest.overrideMimeType()"); + if (args.Length() < 1) { + V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments"); + return v8::Undefined(); + } + + XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( + V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + String value = ToWebCoreString(args[0]); + imp->overrideMimeType(value); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(XMLHttpRequestDispatchEvent) +{ + INC_STATS(L"DOM.XMLHttpRequest.dispatchEvent()"); + return v8::Undefined(); +} + + +// XMLHttpRequestUpload -------------------------------------------------------- + +ACCESSOR_GETTER(XMLHttpRequestUploadOnabort) { + INC_STATS(L"DOM.XMLHttpRequestUpload.onabort._get"); + XMLHttpRequestUpload* imp = V8Proxy::ToNativeObject<XMLHttpRequestUpload>( + V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + if (imp->onAbortListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onAbortListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + return v8_listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(XMLHttpRequestUploadOnabort) { + INC_STATS(L"DOM.XMLHttpRequestUpload.onabort._set"); + XMLHttpRequestUpload* imp = V8Proxy::ToNativeObject<XMLHttpRequestUpload>( + V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + if (value->IsNull()) { + if (imp->onAbortListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onAbortListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + RemoveHiddenXHRDependency(info.Holder(), v8_listener); + } + + // Clear the listener + imp->setOnAbortListener(0); + } else { + XMLHttpRequest* xmlhttprequest = imp->associatedXMLHttpRequest(); + V8Proxy* proxy = V8Proxy::retrieve(xmlhttprequest->document()->frame()); + if (!proxy) + return; + + EventListener* listener = proxy->FindOrCreateXHREventListener(value, false); + if (listener) { + imp->setOnAbortListener(listener); + CreateHiddenXHRDependency(info.Holder(), value); + } + } +} + +ACCESSOR_GETTER(XMLHttpRequestUploadOnerror) { + INC_STATS(L"DOM.XMLHttpRequestUpload.onerror._get"); + XMLHttpRequestUpload* imp = V8Proxy::ToNativeObject<XMLHttpRequestUpload>( + V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + if (imp->onErrorListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onErrorListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + return v8_listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(XMLHttpRequestUploadOnerror) { + INC_STATS(L"DOM.XMLHttpRequestUpload.onerror._set"); + XMLHttpRequestUpload* imp = V8Proxy::ToNativeObject<XMLHttpRequestUpload>( + V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + if (value->IsNull()) { + if (imp->onErrorListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onErrorListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + RemoveHiddenXHRDependency(info.Holder(), v8_listener); + } + + // Clear the listener + imp->setOnErrorListener(0); + } else { + XMLHttpRequest* xmlhttprequest = imp->associatedXMLHttpRequest(); + V8Proxy* proxy = V8Proxy::retrieve(xmlhttprequest->document()->frame()); + if (!proxy) + return; + + EventListener* listener = proxy->FindOrCreateXHREventListener(value, false); + if (listener) { + imp->setOnErrorListener(listener); + CreateHiddenXHRDependency(info.Holder(), value); + } + } +} + +ACCESSOR_GETTER(XMLHttpRequestUploadOnload) { + INC_STATS(L"DOM.XMLHttpRequestUpload.onload._get"); + XMLHttpRequestUpload* imp = V8Proxy::ToNativeObject<XMLHttpRequestUpload>( + V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + if (imp->onLoadListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onLoadListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + return v8_listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(XMLHttpRequestUploadOnload) { + INC_STATS(L"DOM.XMLHttpRequestUpload.onload._set"); + XMLHttpRequestUpload* imp = V8Proxy::ToNativeObject<XMLHttpRequestUpload>( + V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + if (value->IsNull()) { + if (imp->onLoadListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onLoadListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + RemoveHiddenXHRDependency(info.Holder(), v8_listener); + } + + // Clear the listener + imp->setOnLoadListener(0); + } else { + XMLHttpRequest* xmlhttprequest = imp->associatedXMLHttpRequest(); + V8Proxy* proxy = V8Proxy::retrieve(xmlhttprequest->document()->frame()); + if (!proxy) + return; + + EventListener* listener = proxy->FindOrCreateXHREventListener(value, false); + if (listener) { + imp->setOnLoadListener(listener); + CreateHiddenXHRDependency(info.Holder(), value); + } + } +} + +ACCESSOR_GETTER(XMLHttpRequestUploadOnloadstart) { + INC_STATS(L"DOM.XMLHttpRequestUpload.onloadstart._get"); + XMLHttpRequestUpload* imp = V8Proxy::ToNativeObject<XMLHttpRequestUpload>( + V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + if (imp->onLoadStartListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onLoadStartListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + return v8_listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(XMLHttpRequestUploadOnloadstart) { + INC_STATS(L"DOM.XMLHttpRequestUpload.onloadstart._set"); + XMLHttpRequestUpload* imp = V8Proxy::ToNativeObject<XMLHttpRequestUpload>( + V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + if (value->IsNull()) { + if (imp->onLoadStartListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onLoadStartListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + RemoveHiddenXHRDependency(info.Holder(), v8_listener); + } + + // Clear the listener + imp->setOnLoadStartListener(0); + } else { + XMLHttpRequest* xmlhttprequest = imp->associatedXMLHttpRequest(); + V8Proxy* proxy = V8Proxy::retrieve(xmlhttprequest->document()->frame()); + if (!proxy) + return; + + EventListener* listener = proxy->FindOrCreateXHREventListener(value, false); + if (listener) { + imp->setOnLoadStartListener(listener); + CreateHiddenXHRDependency(info.Holder(), value); + } + } +} + +ACCESSOR_GETTER(XMLHttpRequestUploadOnprogress) { + INC_STATS(L"DOM.XMLHttpRequestUpload.onprogress._get"); + XMLHttpRequestUpload* imp = V8Proxy::ToNativeObject<XMLHttpRequestUpload>( + V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + if (imp->onProgressListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onProgressListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + return v8_listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(XMLHttpRequestUploadOnprogress) { + INC_STATS(L"DOM.XMLHttpRequestUpload.onprogress._set"); + XMLHttpRequestUpload* imp = V8Proxy::ToNativeObject<XMLHttpRequestUpload>( + V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + if (value->IsNull()) { + if (imp->onProgressListener()) { + V8XHREventListener* listener = + static_cast<V8XHREventListener*>(imp->onProgressListener()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + RemoveHiddenXHRDependency(info.Holder(), v8_listener); + } + + // Clear the listener + imp->setOnProgressListener(0); + } else { + XMLHttpRequest* xmlhttprequest = imp->associatedXMLHttpRequest(); + V8Proxy* proxy = V8Proxy::retrieve(xmlhttprequest->document()->frame()); + if (!proxy) + return; + + EventListener* listener = proxy->FindOrCreateXHREventListener(value, false); + if (listener) { + imp->setOnProgressListener(listener); + CreateHiddenXHRDependency(info.Holder(), value); + } + } +} + +CALLBACK_FUNC_DECL(XMLHttpRequestUploadAddEventListener) { + INC_STATS(L"DOM.XMLHttpRequestUpload.addEventListener()"); + XMLHttpRequestUpload* imp = V8Proxy::ToNativeObject<XMLHttpRequestUpload>( + V8ClassIndex::XMLHTTPREQUESTUPLOAD, args.Holder()); + + XMLHttpRequest* xmlhttprequest = imp->associatedXMLHttpRequest(); + V8Proxy* proxy = V8Proxy::retrieve(xmlhttprequest->document()->frame()); + if (!proxy) + return v8::Undefined(); + + EventListener* listener = proxy->FindOrCreateXHREventListener(args[1], false); + if (listener) { + String type = ToWebCoreString(args[0]); + bool useCapture = args[2]->BooleanValue(); + imp->addEventListener(type, listener, useCapture); + + CreateHiddenXHRDependency(args.Holder(), args[1]); + } + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(XMLHttpRequestUploadRemoveEventListener) { + INC_STATS(L"DOM.XMLHttpRequestUpload.removeEventListener()"); + XMLHttpRequestUpload* imp = V8Proxy::ToNativeObject<XMLHttpRequestUpload>( + V8ClassIndex::XMLHTTPREQUESTUPLOAD, args.Holder()); + + XMLHttpRequest* xmlhttprequest = imp->associatedXMLHttpRequest(); + V8Proxy* proxy = V8Proxy::retrieve(xmlhttprequest->document()->frame()); + if (!proxy) + return v8::Undefined(); // probably leaked + + EventListener* listener = + proxy->FindXHREventListener(args[1], false); + + if (listener) { + String type = ToWebCoreString(args[0]); + bool useCapture = args[2]->BooleanValue(); + imp->removeEventListener(type, listener, useCapture); + + RemoveHiddenXHRDependency(args.Holder(), args[1]); + } + + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(XMLHttpRequestUploadDispatchEvent) { + INC_STATS(L"DOM.XMLHttpRequestUpload.dispatchEvent()"); + V8Proxy::SetDOMException(NOT_SUPPORTED_ERR); + return v8::Undefined(); +} + +} // namespace WebCore diff --git a/webkit/port/bindings/v8/np_v8object.cpp b/webkit/port/bindings/v8/np_v8object.cpp index 3b3be3a..4387180 100644 --- a/webkit/port/bindings/v8/np_v8object.cpp +++ b/webkit/port/bindings/v8/np_v8object.cpp @@ -36,10 +36,10 @@ #include "bindings/npruntime.h" #include "npruntime_priv.h" #include "PlatformString.h" +#include "ScriptController.h" #include "v8_helpers.h" #include "v8_np_utils.h" #include "v8_proxy.h" -#include "V8Bridge.h" #include "DOMWindow.h" using WebCore::V8ClassIndex; @@ -326,7 +326,7 @@ bool NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, NPIdentifierToV8Identifier(propertyName, identifier); obj->Set(v8::String::New(identifier.c_str()), ConvertNPVariantToV8Object(value, - object->root_object->frame()->windowScriptNPObject())); + object->root_object->frame()->script()->windowScriptNPObject())); return true; } diff --git a/webkit/port/bindings/v8/npruntime_internal.h b/webkit/port/bindings/v8/npruntime_internal.h index f5357cd..75bf2b0 100644 --- a/webkit/port/bindings/v8/npruntime_internal.h +++ b/webkit/port/bindings/v8/npruntime_internal.h @@ -25,7 +25,9 @@ * include this file instead of the actual npapi.h or npruntime.h */ +#include "npapi.h" #include "npruntime.h" +#include "npfunctions.h" #ifdef XP_UNIX #include <X11/Xresource.h> diff --git a/webkit/port/bindings/v8/v8_binding.h b/webkit/port/bindings/v8/v8_binding.h index 81d7dde..1239791 100644 --- a/webkit/port/bindings/v8/v8_binding.h +++ b/webkit/port/bindings/v8/v8_binding.h @@ -9,6 +9,7 @@ #include "build/build_config.h" #include <v8.h> +#include "KURL.h" #include "PlatformString.h" #include "MathExtras.h" #include "StringBuffer.h" @@ -131,6 +132,14 @@ inline int ToInt32(v8::Handle<v8::Value> value) { return ToInt32(value, ok); } +inline String ToString(const String& string) { + return string; +} + +inline String ToString(const KURL& url) { + return url.string(); +} + // If a WebCore string length is greater than the threshold, // v8String creates an external string to avoid allocating // the string in the large object space (which has a high memory overhead). diff --git a/webkit/port/bindings/v8/v8_custom.cpp b/webkit/port/bindings/v8/v8_custom.cpp index 604ab14..78a0160 100644 --- a/webkit/port/bindings/v8/v8_custom.cpp +++ b/webkit/port/bindings/v8/v8_custom.cpp @@ -1,11 +1,10 @@ /* - * This file is part of the KDE libraries * Copyright (C) 2000 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) * Copyright (C) 2004-2006 Apple Computer, Inc. * Copyright (C) 2006 James G. Speth (speth@end.com) * Copyright (C) 2006 Samuel Weinig (sam@webkit.org) - * Copyright 2007 Google Inc. All Rights Reserved. + * Copyright 2007, 2008 Google 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 @@ -25,6 +24,7 @@ #include "config.h" #include <Assertions.h> +#include <wtf/ASCIICType.h> #include "v8_proxy.h" #include "v8_events.h" @@ -43,6 +43,7 @@ #include "V8HTMLImageElement.h" #include "V8HTMLOptionElement.h" #include "V8Node.h" +#include "V8NSResolver.h" #include "V8XPathNSResolver.h" #include "V8XPathResult.h" @@ -50,11 +51,12 @@ #include "CanvasPattern.h" #include "CanvasStyle.h" #include "CanvasRenderingContext2D.h" - #include "Clipboard.h" #include "ClipboardEvent.h" +// TODO(tc): Sort these after the merge lands on trunk. #include "Base64.h" +#include "Console.h" #include "FloatRect.h" #include "Frame.h" #include "FrameTree.h" @@ -72,10 +74,8 @@ #include "EventTargetNode.h" #include "EventTarget.h" #include "ExceptionCode.h" -#include "XMLHttpRequest.h" #include "XMLSerializer.h" #include "KURL.h" -#include "DeprecatedString.h" #include "HTMLDocument.h" #include "HTMLNames.h" #include "HTMLBodyElement.h" @@ -101,12 +101,12 @@ #include "Settings.h" #include "StyleSheetList.h" #include "TreeWalker.h" +#include "JSNSResolver.h" #include "WindowFeatures.h" #include "XPathEvaluator.h" #include "JSXPathNSResolver.h" #include "XPathResult.h" #include "XSLTProcessor.h" -#include "V8Bridge.h" #if ENABLE(SVG) #include "V8SVGPODTypeWrapper.h" @@ -124,18 +124,6 @@ static const int kPopupTilePixels = 10; namespace WebCore { -#define CALLBACK_FUNC_DECL(NAME) \ -v8::Handle<v8::Value> V8Custom::v8##NAME##Callback(const v8::Arguments& args) - -#define ACCESSOR_GETTER(NAME) \ -v8::Handle<v8::Value> V8Custom::v8##NAME##AccessorGetter(\ - v8::Local<v8::String> name, const v8::AccessorInfo& info) - -#define ACCESSOR_SETTER(NAME) \ -void V8Custom::v8##NAME##AccessorSetter(v8::Local<v8::String> name, \ - v8::Local<v8::Value> value, \ - const v8::AccessorInfo& info) - #define NAMED_PROPERTY_GETTER(NAME) \ v8::Handle<v8::Value> V8Custom::v8##NAME##NamedPropertyGetter(\ v8::Local<v8::String> name, const v8::AccessorInfo& info) @@ -264,27 +252,6 @@ void V8ScheduledAction::execute(DOMWindow* window) { } -CALLBACK_FUNC_DECL(XMLHttpRequestConstructor) { - INC_STATS(L"DOM.XMLHttpRequest.Constructor"); - - if (!args.IsConstructCall()) { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, - "DOM object constructor cannot be called as a function."); - return v8::Undefined(); - } - // Expect no parameters. - // Allocate a XMLHttpRequest object as its internal field. - Document* doc = V8Proxy::retrieveFrame()->document(); - XMLHttpRequest* xhr = new XMLHttpRequest(doc); - V8Proxy::SetDOMWrapper(args.Holder(), - V8ClassIndex::ToInt(V8ClassIndex::XMLHTTPREQUEST), xhr); - // Set object as the peer. - V8Proxy::SetJSWrapperForDOMObject(xhr, - v8::Persistent<v8::Object>::New(args.Holder())); - return args.Holder(); -} - - CALLBACK_FUNC_DECL(DOMParserConstructor) { INC_STATS(L"DOM.DOMParser.Contructor"); return V8Proxy::ConstructDOMObject<V8ClassIndex::DOMPARSER, @@ -355,10 +322,12 @@ CALLBACK_FUNC_DECL(XSLTProcessorTransformToDocument) { V8ClassIndex::XSLTPROCESSOR, args.Holder()); Node* source = V8Proxy::DOMWrapperToNode<Node>(args[0]); - if (!source) return v8::Undefined(); + if (!source) + return v8::Undefined(); RefPtr<Document> result = imp->transformToDocument(source); // Return undefined if no result was found. - if (!result) return v8::Undefined(); + if (!result) + return v8::Undefined(); return V8Proxy::NodeToV8Object(result.get()); } @@ -404,9 +373,8 @@ CALLBACK_FUNC_DECL(XSLTProcessorGetParameter) { CALLBACK_FUNC_DECL(XSLTProcessorRemoveParameter) { INC_STATS(L"DOM.XSLTProcessor.removeParameter"); // Bail out if localName is null or undefined. - if (args[1]->IsNull() || args[1]->IsUndefined()) { + if (args[1]->IsNull() || args[1]->IsUndefined()) return v8::Undefined(); - } XSLTProcessor* imp = V8Proxy::ToNativeObject<XSLTProcessor>( V8ClassIndex::XSLTPROCESSOR, args.Holder()); @@ -419,33 +387,30 @@ CALLBACK_FUNC_DECL(XSLTProcessorRemoveParameter) { // ---- Canvas support ---- -static v8::Handle<v8::Value> CanvasStyleToV8Object(CanvasStyle* style) { - if (style->gradient()) { - return V8Proxy::ToV8Object(V8ClassIndex::CANVASGRADIENT, - static_cast<Peerable*>(style->gradient())); - } - if (style->pattern()) { - return V8Proxy::ToV8Object(V8ClassIndex::CANVASPATTERN, - static_cast<Peerable*>(style->pattern())); - } - return v8String(style->color()); +static v8::Handle<v8::Value> CanvasStyleToV8Object(CanvasStyle* style) +{ + if (style->canvasGradient()) + return V8Proxy::ToV8Object(V8ClassIndex::CANVASGRADIENT, static_cast<Peerable*>(style->canvasGradient())); + if (style->canvasPattern()) + return V8Proxy::ToV8Object(V8ClassIndex::CANVASPATTERN, static_cast<Peerable*>(style->canvasPattern())); + return v8String(style->color()); } - -static PassRefPtr<CanvasStyle> V8ObjectToCanvasStyle( - v8::Handle<v8::Value> value) { - if (value->IsString()) return new CanvasStyle(ToWebCoreString(value)); +static PassRefPtr<CanvasStyle> V8ObjectToCanvasStyle(v8::Handle<v8::Value> value) +{ + if (value->IsString()) + return CanvasStyle::create(ToWebCoreString(value)); if (V8CanvasGradient::HasInstance(value)) { CanvasGradient* gradient = V8Proxy::DOMWrapperToNative<CanvasGradient>(value); - return new CanvasStyle(gradient); + return CanvasStyle::create(gradient); } if (V8CanvasPattern::HasInstance(value)) { CanvasPattern* pattern = V8Proxy::DOMWrapperToNative<CanvasPattern>(value); - return new CanvasStyle(pattern); + return CanvasStyle::create(pattern); } return 0; @@ -866,16 +831,19 @@ CALLBACK_FUNC_DECL(DOMWindowPostMessage) { DOMWindow* source = V8Proxy::retrieveActiveFrame()->domWindow(); ASSERT(source->frame()); - String domain = source->frame()->loader()->url().host(); String uri = source->frame()->loader()->url().string(); v8::TryCatch try_catch; String message = ToWebCoreString(args[0]); + String domain = ToWebCoreString(args[1]); if (try_catch.HasCaught()) return v8::Undefined(); - window->postMessage(message, domain, uri, source); + ExceptionCode ec; + window->postMessage(message, domain, source, ec); + if (ec) + V8Proxy::SetDOMException(ec); return v8::Undefined(); } @@ -892,7 +860,7 @@ static bool allowPopUp() { Frame* frame = V8Proxy::retrieveActiveFrame(); ASSERT(frame); - if (frame->scriptBridge()->wasRunByUserGesture()) return true; + if (frame->script()->processingUserGesture()) return true; Settings* settings = frame->settings(); return settings && settings->JavaScriptCanOpenWindowsAutomatically(); } @@ -901,7 +869,8 @@ static HashMap<String, String> parseModalDialogFeatures( const String& features_arg) { HashMap<String, String> map; - Vector<String> features = features_arg.split(';'); + Vector<String> features; + features_arg.split(';', features); Vector<String>::const_iterator end = features.end(); for (Vector<String>::const_iterator it = features.begin(); it != end; ++it) { String s = *it; @@ -956,9 +925,8 @@ static Frame* createWindow(Frame* opener_frame, // "_self" or "_parent". Frame* new_frame = active_frame->loader()->createWindow( opener_frame->loader(), frame_request, window_features, created); - if (!new_frame) { + if (!new_frame) return 0; - } new_frame->loader()->setOpener(opener_frame); new_frame->loader()->setOpenedByDOM(); @@ -973,23 +941,20 @@ static Frame* createWindow(Frame* opener_frame, } if (!parseURL(url).startsWith("javascript:", false) || - JSBridge::isSafeScript(new_frame)) { - String completed_url = - url.isEmpty() ? url : active_frame->document()->completeURL(url); - bool user_gesture = active_frame->scriptBridge()->wasRunByUserGesture(); + ScriptController::isSafeScript(new_frame)) { + KURL completed_url = + url.isEmpty() ? KURL("") : active_frame->document()->completeURL(url); + bool user_gesture = active_frame->script()->processingUserGesture(); if (created) { new_frame->loader()->changeLocation( - KURL(completed_url.deprecatedString()), + completed_url, active_frame->loader()->outgoingReferrer(), false, user_gesture); - if (Document* old_doc = opener_frame->document()) { - new_frame->document()->setBaseURL(old_doc->baseURL()); - } } else if (!url.isEmpty()) { new_frame->loader()->scheduleLocationChange( - completed_url, + completed_url.string(), active_frame->loader()->outgoingReferrer(), false, user_gesture); @@ -1149,8 +1114,8 @@ CALLBACK_FUNC_DECL(DOMWindowOpen) { if (!completed_url.isEmpty() && (!parseURL(url_string).startsWith("javascript:", false) || - JSBridge::isSafeScript(frame))) { - bool user_gesture = active_frame->scriptBridge()->wasRunByUserGesture(); + ScriptController::isSafeScript(frame))) { + bool user_gesture = active_frame->script()->processingUserGesture(); frame->loader()->scheduleLocationChange( completed_url, active_frame->loader()->outgoingReferrer(), @@ -1373,7 +1338,8 @@ NAMED_PROPERTY_DELETER(HTMLDocument) { } -NAMED_PROPERTY_SETTER(HTMLDocument) { +NAMED_PROPERTY_SETTER(HTMLDocument) +{ INC_STATS(L"DOM.HTMLDocument.NamedPropertySetter"); // Only handle document.all. We insert the value into the shadow // internal field from which the getter will retrieve it. @@ -1387,50 +1353,45 @@ NAMED_PROPERTY_SETTER(HTMLDocument) { } -NAMED_PROPERTY_GETTER(HTMLDocument) { - INC_STATS(L"DOM.HTMLDocument.NamedPropertyGetter"); - String key = ToWebCoreString(name); +NAMED_PROPERTY_GETTER(HTMLDocument) +{ + INC_STATS(L"DOM.HTMLDocument.NamedPropertyGetter"); + AtomicString key = ToWebCoreString(name); - // Special case for document.all. If the value in the shadow - // internal field is not the marker object, then document.all has - // been temporarily shadowed and we return the value. - if (key == "all") { - ASSERT(info.Holder()->InternalFieldCount() == - kHTMLDocumentInternalFieldCount); - v8::Local<v8::Value> marker = - info.Holder()->GetInternalField(kHTMLDocumentMarkerIndex); - v8::Local<v8::Value> value = - info.Holder()->GetInternalField(kHTMLDocumentShadowIndex); - if (marker != value) { - return value; + // Special case for document.all. If the value in the shadow + // internal field is not the marker object, then document.all has + // been temporarily shadowed and we return the value. + if (key == "all") { + ASSERT(info.Holder()->InternalFieldCount() == kHTMLDocumentInternalFieldCount); + v8::Local<v8::Value> marker = info.Holder()->GetInternalField(kHTMLDocumentMarkerIndex); + v8::Local<v8::Value> value = info.Holder()->GetInternalField(kHTMLDocumentShadowIndex); + if (marker != value) + return value; } - } HTMLDocument* imp = V8Proxy::DOMWrapperToNode<HTMLDocument>(info.Holder()); - // Fast case for named elements that are not there. - if (!imp->hasNamedItem(key) && !imp->hasDocExtraNamedItem(key)) { - return v8::Handle<v8::Value>(); - } - + // Fast case for named elements that are not there. + if (!imp->hasNamedItem(key.impl()) && !imp->hasExtraNamedItem(key.impl())) + return v8::Handle<v8::Value>(); - RefPtr<HTMLCollection> items = imp->documentNamedItems(key); - if (items->length() == 0) return v8::Handle<v8::Value>(); - if (items->length() == 1) { - Node* node = items->firstItem(); - Frame* frame = 0; - if (node->hasTagName(HTMLNames::iframeTag) && - (frame = static_cast<HTMLIFrameElement*>(node)->contentFrame())) { - return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); - } + RefPtr<HTMLCollection> items = imp->documentNamedItems(key); + if (items->length() == 0) + return v8::Handle<v8::Value>(); + if (items->length() == 1) { + Node* node = items->firstItem(); + Frame* frame = 0; + if (node->hasTagName(HTMLNames::iframeTag) && (frame = static_cast<HTMLIFrameElement*>(node)->contentFrame())) + return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); return V8Proxy::NodeToV8Object(node); - } - return V8Proxy::ToV8Object(V8ClassIndex::HTMLCOLLECTION, + } + return V8Proxy::ToV8Object(V8ClassIndex::HTMLCOLLECTION, static_cast<Peerable*>(items.get())); } -NAMED_PROPERTY_GETTER(HTMLFrameSetElement) { +NAMED_PROPERTY_GETTER(HTMLFrameSetElement) +{ INC_STATS(L"DOM.HTMLFrameSetElement.NamedPropertyGetter"); HTMLFrameSetElement* imp = V8Proxy::DOMWrapperToNode<HTMLFrameSetElement>(info.Holder()); @@ -1440,10 +1401,8 @@ NAMED_PROPERTY_GETTER(HTMLFrameSetElement) { Document* doc = static_cast<HTMLFrameElement*>(frame)->contentDocument(); if (doc) { Frame* content_frame = doc->frame(); - if (content_frame) { - return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, - content_frame->domWindow()); - } + if (content_frame) + return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, content_frame->domWindow()); } return v8::Undefined(); } @@ -1598,6 +1557,32 @@ INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection) { return OptionsCollectionSetter(index, value, select); } +// Check for a CSS prefix. +// Passed prefix is all lowercase. +// First character of the prefix within the property name may be upper or lowercase. +// Other characters in the prefix within the property name must be lowercase. +// The prefix within the property name must be followed by a capital letter. +static bool hasCSSPropertyNamePrefix(const String& propertyName, const char* prefix) +{ +#ifndef NDEBUG + ASSERT(*prefix); + for (const char* p = prefix; *p; ++p) + ASSERT(WTF::isASCIILower(*p)); + ASSERT(propertyName.length()); +#endif + + if (WTF::toASCIILower(propertyName[0]) != prefix[0]) + return false; + + unsigned length = propertyName.length(); + for (unsigned i = 1; i < length; ++i) { + if (!prefix[i]) + return WTF::isASCIIUpper(propertyName[i]); + if (propertyName[i] != prefix[i]) + return false; + } + return false; +} // When getting properties on CSSStyleDeclarations, the name used from // Javascript and the actual name of the property are not the same, so @@ -1610,48 +1595,60 @@ INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection) { // Also, certain prefixes such as 'pos', 'css-' and 'pixel-' are stripped // and the pixel_or_pos_prefix out parameter is used to indicate whether or // not the property name was prefixed with 'pos-' or 'pixel-'. -static String CSSPropertyName(const String &p, bool *pixel_or_pos_prefix = 0) { - DeprecatedString prop = p.deprecatedString(); - - int i = prop.length(); - while (--i > 0) { - ::UChar c = prop[i].unicode(); - if (c >= 'A' && c <= 'Z') - prop.insert(i, '-'); - } - - prop = prop.lower(); +static String cssPropertyName(const String& propertyName, bool* hadPixelOrPosPrefix = 0) +{ + if (hadPixelOrPosPrefix) + *hadPixelOrPosPrefix = false; + + unsigned length = propertyName.length(); + if (!length) + return String(); + + Vector<UChar> name; + name.reserveCapacity(length); + + unsigned i = 0; + + if (hasCSSPropertyNamePrefix(propertyName, "css")) + i += 3; + else if (hasCSSPropertyNamePrefix(propertyName, "pixel")) { + i += 5; + if (hadPixelOrPosPrefix) + *hadPixelOrPosPrefix = true; + } else if (hasCSSPropertyNamePrefix(propertyName, "pos")) { + i += 3; + if (hadPixelOrPosPrefix) + *hadPixelOrPosPrefix = true; + } else if (hasCSSPropertyNamePrefix(propertyName, "webkit") + || hasCSSPropertyNamePrefix(propertyName, "khtml") + || hasCSSPropertyNamePrefix(propertyName, "apple")) + name.append('-'); + else { + if (WTF::isASCIIUpper(propertyName[0])) + return String(); + } - if (pixel_or_pos_prefix) - *pixel_or_pos_prefix = false; + name.append(WTF::toASCIILower(propertyName[i++])); - if (prop.startsWith("css-")) { - prop = prop.mid(4); - } else if (prop.startsWith("pixel-")) { - prop = prop.mid(6); - if (pixel_or_pos_prefix) - *pixel_or_pos_prefix = true; - } else if (prop.startsWith("pos-")) { - prop = prop.mid(4); - if (pixel_or_pos_prefix) - *pixel_or_pos_prefix = true; - } else if (prop.startsWith("khtml-") || - prop.startsWith("apple-") || - prop.startsWith("webkit-")) { - prop.insert(0, '-'); - } + for (; i < length; ++i) { + UChar c = propertyName[i]; + if (!WTF::isASCIIUpper(c)) + name.append(c); + else { + name.append('-'); + name.append(WTF::toASCIILower(c)); + } + } - return prop; + return String::adopt(name); } - NAMED_PROPERTY_GETTER(CSSStyleDeclaration) { INC_STATS(L"DOM.CSSStyleDeclaration.NamedPropertyGetter"); // First look for API defined attributes on the style declaration // object. - if (info.Holder()->HasRealNamedCallbackProperty(name)) { + if (info.Holder()->HasRealNamedCallbackProperty(name)) return v8::Handle<v8::Value>(); - } // Search the style declaration. CSSStyleDeclaration* imp = V8Proxy::ToNativeObject<CSSStyleDeclaration>( @@ -1659,7 +1656,7 @@ NAMED_PROPERTY_GETTER(CSSStyleDeclaration) { bool pixel_or_pos; String p = ToWebCoreString(name); - String prop = CSSPropertyName(p, &pixel_or_pos); + String prop = cssPropertyName(p, &pixel_or_pos); // Do not handle non-property names. if (!CSSStyleDeclaration::isPropertyName(prop)) { @@ -1698,7 +1695,7 @@ NAMED_PROPERTY_SETTER(CSSStyleDeclaration) { int ec = 0; bool pixel_or_pos; - String prop = CSSPropertyName(property_name, &pixel_or_pos); + String prop = cssPropertyName(property_name, &pixel_or_pos); if (!CSSStyleDeclaration::isPropertyName(prop)) { return v8::Handle<v8::Value>(); // do not block the call } @@ -1800,6 +1797,9 @@ CALLBACK_FUNC_DECL(CSSPrimitiveValueGetRGBColorValue) { static_cast<Peerable*>(new RGBColor(rgbcolor))); } + +// CanvasRenderingContext2D ---------------------------------------------------- + // Helper macro for converting v8 values into floats (expected by many of the // canvas functions). #define TO_FLOAT(a) static_cast<float>((a)->NumberValue()) @@ -1849,7 +1849,6 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetStrokeColor) { return v8::Undefined(); } - CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetFillColor) { INC_STATS(L"DOM.CanvasRenderingContext2D.steFillColor()"); CanvasRenderingContext2D* context = @@ -1891,39 +1890,31 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetFillColor) { return v8::Undefined(); } - CALLBACK_FUNC_DECL(CanvasRenderingContext2DStrokeRect) { INC_STATS(L"DOM.CanvasRenderingContext2D.strokeRect()"); CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>( V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); - ExceptionCode ec = 0; double x = 0, y = 0, width = 0, height = 0, line_width = 0; if (args.Length() == 5) { context->strokeRect(TO_FLOAT(args[0]), TO_FLOAT(args[1]), TO_FLOAT(args[2]), TO_FLOAT(args[3]), - TO_FLOAT(args[4]), - ec); + TO_FLOAT(args[4])); } else if (args.Length() == 4) { context->strokeRect(TO_FLOAT(args[0]), TO_FLOAT(args[1]), TO_FLOAT(args[2]), - TO_FLOAT(args[3]), - ec); + TO_FLOAT(args[3])); } else { - // Should throw index error - ec = INDEX_SIZE_ERR; - } - if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::SetDOMException(INDEX_SIZE_ERR); return v8::Handle<v8::Value>(); } + return v8::Undefined(); } - CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetShadow) { INC_STATS(L"DOM.CanvasRenderingContext2D.setShadow()"); CanvasRenderingContext2D* context = @@ -1974,7 +1965,6 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetShadow) { return v8::Undefined(); } - CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) { INC_STATS(L"DOM.CanvasRenderingContext2D.drawImage()"); CanvasRenderingContext2D* context = @@ -2060,7 +2050,6 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) { return v8::Handle<v8::Value>(); } - CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImageFromRect) { INC_STATS(L"DOM.CanvasRenderingContext2D.drawImageFromRect()"); CanvasRenderingContext2D* context = @@ -2129,6 +2118,113 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DCreatePattern) { return v8::Handle<v8::Value>(); } +CALLBACK_FUNC_DECL(CanvasRenderingContext2DFillText) { + INC_STATS(L"DOM.CanvasRenderingContext2D.fillText()"); + V8Proxy::SetDOMException(NOT_SUPPORTED_ERR); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(CanvasRenderingContext2DStrokeText) { + INC_STATS(L"DOM.CanvasRenderingContext2D.strokeText()"); + V8Proxy::SetDOMException(NOT_SUPPORTED_ERR); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(CanvasRenderingContext2DPutImageData) { + INC_STATS(L"DOM.CanvasRenderingContext2D.putImageData()"); + V8Proxy::SetDOMException(NOT_SUPPORTED_ERR); + return v8::Undefined(); +} + + +// Console --------------------------------------------------------------------- + +CALLBACK_FUNC_DECL(ConsoleAssert) { + INC_STATS(L"DOM.Console.assert()"); + V8Proxy::SetDOMException(NOT_SUPPORTED_ERR); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(ConsoleCount) { + INC_STATS(L"DOM.Console.count()"); + V8Proxy::SetDOMException(NOT_SUPPORTED_ERR); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(ConsoleDebug) { + INC_STATS(L"DOM.Console.debug()"); + V8Proxy::SetDOMException(NOT_SUPPORTED_ERR); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(ConsoleDir) { + INC_STATS(L"DOM.Console.dir()"); + V8Proxy::SetDOMException(NOT_SUPPORTED_ERR); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(ConsoleError) { + INC_STATS(L"DOM.Console.error()"); + v8::Handle<v8::Value> holder = args.Holder(); + Console* imp = V8Proxy::ToNativeObject<Console>(V8ClassIndex::CONSOLE, holder); + String message = ToWebCoreString(args[0]); + imp->error(message); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(ConsoleGroup) { + INC_STATS(L"DOM.Console.group()"); + V8Proxy::SetDOMException(NOT_SUPPORTED_ERR); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(ConsoleInfo) { + INC_STATS(L"DOM.Console.info()"); + v8::Handle<v8::Value> holder = args.Holder(); + Console* imp = V8Proxy::ToNativeObject<Console>(V8ClassIndex::CONSOLE, holder); + String message = ToWebCoreString(args[0]); + imp->info(message); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(ConsoleLog) { + INC_STATS(L"DOM.Console.log()"); + v8::Handle<v8::Value> holder = args.Holder(); + Console* imp = V8Proxy::ToNativeObject<Console>(V8ClassIndex::CONSOLE, holder); + String message = ToWebCoreString(args[0]); + imp->log(message); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(ConsoleProfile) { + INC_STATS(L"DOM.Console.profile()"); + V8Proxy::SetDOMException(NOT_SUPPORTED_ERR); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(ConsoleProfileEnd) { + INC_STATS(L"DOM.Console.profileEnd()"); + V8Proxy::SetDOMException(NOT_SUPPORTED_ERR); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(ConsoleTimeEnd) { + INC_STATS(L"DOM.Console.timeEnd()"); + V8Proxy::SetDOMException(NOT_SUPPORTED_ERR); + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(ConsoleWarn) { + INC_STATS(L"DOM.Console.warn()"); + v8::Handle<v8::Value> holder = args.Holder(); + Console* imp = V8Proxy::ToNativeObject<Console>(V8ClassIndex::CONSOLE, holder); + String message = ToWebCoreString(args[0]); + imp->warn(message); + return v8::Undefined(); +} + + +// Clipboard ------------------------------------------------------------------- CALLBACK_FUNC_DECL(ClipboardClearData) { INC_STATS(L"DOM.Clipboard.clearData()"); @@ -2215,6 +2311,71 @@ static bool AllowSettingFrameSrcToJavascriptUrl(HTMLFrameElementBase* frame, } +// Element --------------------------------------------------------------------- + +CALLBACK_FUNC_DECL(ElementQuerySelector) { + INC_STATS(L"DOM.Element.querySelector()"); + Element* element = V8Proxy::DOMWrapperToNode<Element>(args.Holder()); + + ExceptionCode ec = 0; + + String selectors = valueToStringWithNullOrUndefinedCheck(args[0]); + + NSResolver* resolver = 0; + if (V8NSResolver::HasInstance(args[1])) { + resolver = V8Proxy::ToNativeObject<NSResolver>( + V8ClassIndex::NSRESOLVER, args[1]); + } else if (args[1]->IsObject()) { + resolver = new JSNSResolver(args[1]->ToObject()); + } else if (!args[1]->IsNull() && !args[1]->IsUndefined()) { + V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); + return v8::Handle<v8::Value>(); + } + OwnPtr<ExceptionContext> context(new ExceptionContext()); + RefPtr<Element> result = WTF::getPtr( + element->querySelector(selectors, resolver, ec, context.get())); + if (ec != 0) { + V8Proxy::SetDOMException(ec); + return v8::Handle<v8::Value>(); + } + if (context->hadException()) { + v8::ThrowException(context->exception()); + return v8::Undefined(); + } + return V8Proxy::ToV8Object(V8ClassIndex::NODE, WTF::getPtr(result)); +} + +CALLBACK_FUNC_DECL(ElementQuerySelectorAll) { + INC_STATS(L"DOM.Element.querySelectorAll()"); + Element* element = V8Proxy::DOMWrapperToNode<Element>(args.Holder()); + ExceptionCode ec = 0; + + String selectors = valueToStringWithNullOrUndefinedCheck(args[0]); + + NSResolver* resolver = 0; + if (V8NSResolver::HasInstance(args[1])) { + resolver = V8Proxy::ToNativeObject<NSResolver>( + V8ClassIndex::NSRESOLVER, args[1]); + } else if (args[1]->IsObject()) { + resolver = new JSNSResolver(args[1]->ToObject()); + } else if (!args[1]->IsNull() && !args[1]->IsUndefined()) { + V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); + return v8::Handle<v8::Value>(); + } + OwnPtr<ExceptionContext> context(new ExceptionContext()); + RefPtr<NodeList> result = WTF::getPtr( + element->querySelectorAll(selectors, resolver, ec, context.get())); + if (ec != 0) { + V8Proxy::SetDOMException(ec); + return v8::Handle<v8::Value>(); + } + if (context->hadException()) { + v8::ThrowException(context->exception()); + return v8::Undefined(); + } + return V8Proxy::ToV8Object(V8ClassIndex::NODELIST, WTF::getPtr(result)); +} + CALLBACK_FUNC_DECL(ElementSetAttribute) { INC_STATS(L"DOM.Element.setAttribute()"); Element* imp = V8Proxy::DOMWrapperToNode<Element>(args.Holder()); @@ -2234,7 +2395,6 @@ CALLBACK_FUNC_DECL(ElementSetAttribute) { return v8::Undefined(); } - CALLBACK_FUNC_DECL(ElementSetAttributeNode) { INC_STATS(L"DOM.Element.setAttributeNode()"); if (!V8Attr::HasInstance(args[0])) { @@ -2258,7 +2418,6 @@ CALLBACK_FUNC_DECL(ElementSetAttributeNode) { return V8Proxy::NodeToV8Object(result.get()); } - CALLBACK_FUNC_DECL(ElementSetAttributeNS) { INC_STATS(L"DOM.Element.setAttributeNS()"); Element* imp = V8Proxy::DOMWrapperToNode<Element>(args.Holder()); @@ -2279,7 +2438,6 @@ CALLBACK_FUNC_DECL(ElementSetAttributeNS) { return v8::Undefined(); } - CALLBACK_FUNC_DECL(ElementSetAttributeNodeNS) { INC_STATS(L"DOM.Element.setAttributeNodeNS()"); if (!V8Attr::HasInstance(args[0])) { @@ -2304,6 +2462,8 @@ CALLBACK_FUNC_DECL(ElementSetAttributeNodeNS) { } +// Attr ------------------------------------------------------------------------ + ACCESSOR_SETTER(AttrValue) { Attr* imp = V8Proxy::DOMWrapperToNode<Attr>(info.Holder()); @@ -2320,6 +2480,8 @@ ACCESSOR_SETTER(AttrValue) { } +// HTMLFrameElement ------------------------------------------------------------ + ACCESSOR_SETTER(HTMLFrameElementSrc) { HTMLFrameElement* imp = V8Proxy::DOMWrapperToNode<HTMLFrameElement>(info.Holder()); @@ -2330,7 +2492,6 @@ ACCESSOR_SETTER(HTMLFrameElementSrc) { imp->setSrc(v); } - ACCESSOR_SETTER(HTMLFrameElementLocation) { HTMLFrameElement* imp = V8Proxy::DOMWrapperToNode<HTMLFrameElement>(info.Holder()); @@ -2342,6 +2503,8 @@ ACCESSOR_SETTER(HTMLFrameElementLocation) { } +// HTMLIFrameElement ----------------------------------------------------------- + ACCESSOR_SETTER(HTMLIFrameElementSrc) { HTMLIFrameElement* imp = V8Proxy::DOMWrapperToNode<HTMLIFrameElement>(info.Holder()); @@ -2419,6 +2582,9 @@ CALLBACK_FUNC_DECL(DOMWindowSetInterval) { return WindowSetTimeoutImpl(args, false); } + +// HTMLDocument ---------------------------------------------------------------- + // Concatenates "args" to a string. If args is empty, returns empty string. // Firefox/Safari/IE support non-standard arguments to document.write, ex: // document.write("a", "b", "c") --> document.write("abc") @@ -2431,23 +2597,22 @@ static String WriteHelper_GetString(const v8::Arguments& args) { return str; } - CALLBACK_FUNC_DECL(HTMLDocumentWrite) { INC_STATS(L"DOM.HTMLDocument.write()"); HTMLDocument* imp = V8Proxy::DOMWrapperToNode<HTMLDocument>(args.Holder()); - imp->write(WriteHelper_GetString(args)); + imp->write(WriteHelper_GetString(args), + V8Proxy::retrieveWindow()->document()); return v8::Undefined(); } - CALLBACK_FUNC_DECL(HTMLDocumentWriteln) { INC_STATS(L"DOM.HTMLDocument.writeln()"); HTMLDocument* imp = V8Proxy::DOMWrapperToNode<HTMLDocument>(args.Holder()); - imp->writeln(WriteHelper_GetString(args)); + imp->writeln(WriteHelper_GetString(args), + V8Proxy::retrieveWindow()->document()); return v8::Undefined(); } - CALLBACK_FUNC_DECL(HTMLDocumentOpen) { INC_STATS(L"DOM.HTMLDocument.open()"); HTMLDocument* imp = V8Proxy::DOMWrapperToNode<HTMLDocument>(args.Holder()); @@ -2487,7 +2652,6 @@ CALLBACK_FUNC_DECL(HTMLDocumentOpen) { return v8::Undefined(); } - CALLBACK_FUNC_DECL(HTMLDocumentClear) { INC_STATS(L"DOM.HTMLDocument.clear()"); // Do nothing (unimplemented) @@ -2500,6 +2664,8 @@ CALLBACK_FUNC_DECL(HTMLDocumentClear) { } +// Document -------------------------------------------------------------------- + CALLBACK_FUNC_DECL(DocumentEvaluate) { INC_STATS(L"DOM.Document.evaluate()"); @@ -2538,6 +2704,133 @@ CALLBACK_FUNC_DECL(DocumentEvaluate) { static_cast<Peerable*>(result.get())); } +CALLBACK_FUNC_DECL(DocumentQuerySelector) { + INC_STATS(L"DOM.Document.querySelector()"); + Document* document = V8Proxy::DOMWrapperToNode<Document>(args.Holder()); + ExceptionCode ec = 0; + + String selectors = valueToStringWithNullOrUndefinedCheck(args[0]); + + NSResolver* resolver = 0; + if (V8NSResolver::HasInstance(args[1])) { + resolver = V8Proxy::ToNativeObject<NSResolver>( + V8ClassIndex::NSRESOLVER, args[1]); + } else if (args[1]->IsObject()) { + resolver = new JSNSResolver(args[1]->ToObject()); + } else if (!args[1]->IsNull() && !args[1]->IsUndefined()) { + V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); + return v8::Handle<v8::Value>(); + } + OwnPtr<ExceptionContext> context(new ExceptionContext()); + RefPtr<Element> result = WTF::getPtr( + document->querySelector(selectors, resolver, ec, context.get())); + if (ec != 0) { + V8Proxy::SetDOMException(ec); + return v8::Handle<v8::Value>(); + } + if (context->hadException()) { + v8::ThrowException(context->exception()); + return v8::Undefined(); + } + return V8Proxy::ToV8Object(V8ClassIndex::NODE, WTF::getPtr(result)); +} + +CALLBACK_FUNC_DECL(DocumentQuerySelectorAll) { + INC_STATS(L"DOM.Document.querySelectorAll()"); + Document* document = V8Proxy::DOMWrapperToNode<Document>(args.Holder()); + ExceptionCode ec = 0; + + String selectors = valueToStringWithNullOrUndefinedCheck(args[0]); + + NSResolver* resolver = 0; + if (V8NSResolver::HasInstance(args[1])) { + resolver = V8Proxy::ToNativeObject<NSResolver>( + V8ClassIndex::NSRESOLVER, args[1]); + } else if (args[1]->IsObject()) { + resolver = new JSNSResolver(args[1]->ToObject()); + } else if (!args[1]->IsNull() && !args[1]->IsUndefined()) { + V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); + return v8::Handle<v8::Value>(); + } + OwnPtr<ExceptionContext> context(new ExceptionContext()); + RefPtr<NodeList> result = WTF::getPtr( + document->querySelectorAll(selectors, resolver, ec, context.get())); + if (ec != 0) { + V8Proxy::SetDOMException(ec); + return v8::Handle<v8::Value>(); + } + if (context->hadException()) { + v8::ThrowException(context->exception()); + return v8::Undefined(); + } + return V8Proxy::ToV8Object(V8ClassIndex::NODELIST, WTF::getPtr(result)); +} + +CALLBACK_FUNC_DECL(DocumentFragmentQuerySelector) { + INC_STATS(L"DOM.DocumentFragment.querySelector()"); + DocumentFragment* fragment = + V8Proxy::DOMWrapperToNode<DocumentFragment>(args.Holder()); + ExceptionCode ec = 0; + + String selectors = valueToStringWithNullOrUndefinedCheck(args[0]); + + NSResolver* resolver = 0; + if (V8NSResolver::HasInstance(args[1])) { + resolver = V8Proxy::ToNativeObject<NSResolver>( + V8ClassIndex::NSRESOLVER, args[1]); + } else if (args[1]->IsObject()) { + resolver = new JSNSResolver(args[1]->ToObject()); + } else if (!args[1]->IsNull() && !args[1]->IsUndefined()) { + V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); + return v8::Handle<v8::Value>(); + } + OwnPtr<ExceptionContext> context(new ExceptionContext()); + RefPtr<Element> result = WTF::getPtr( + fragment->querySelector(selectors, resolver, ec, context.get())); + if (ec != 0) { + V8Proxy::SetDOMException(ec); + return v8::Handle<v8::Value>(); + } + if (context->hadException()) { + v8::ThrowException(context->exception()); + return v8::Undefined(); + } + return V8Proxy::ToV8Object(V8ClassIndex::NODE, WTF::getPtr(result)); +} + +CALLBACK_FUNC_DECL(DocumentFragmentQuerySelectorAll) { + INC_STATS(L"DOM.DocumentFragment.querySelectorAll()"); + DocumentFragment* fragment = + V8Proxy::DOMWrapperToNode<DocumentFragment>(args.Holder()); + ExceptionCode ec = 0; + + String selectors = valueToStringWithNullOrUndefinedCheck(args[0]); + + NSResolver* resolver = 0; + if (V8NSResolver::HasInstance(args[1])) { + resolver = V8Proxy::ToNativeObject<NSResolver>( + V8ClassIndex::NSRESOLVER, args[1]); + } else if (args[1]->IsObject()) { + resolver = new JSNSResolver(args[1]->ToObject()); + } else if (!args[1]->IsNull() && !args[1]->IsUndefined()) { + V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); + return v8::Handle<v8::Value>(); + } + OwnPtr<ExceptionContext> context(new ExceptionContext()); + RefPtr<NodeList> result = WTF::getPtr( + fragment->querySelectorAll(selectors, resolver, ec, context.get())); + if (ec != 0) { + V8Proxy::SetDOMException(ec); + return v8::Handle<v8::Value>(); + } + if (context->hadException()) { + v8::ThrowException(context->exception()); + return v8::Undefined(); + } + return V8Proxy::ToV8Object(V8ClassIndex::NODELIST, WTF::getPtr(result)); +} + +// DOMWindow ------------------------------------------------------------------- static bool IsAscii(const String& str) { for (size_t i = 0; i < str.length(); i++) { @@ -2547,7 +2840,6 @@ static bool IsAscii(const String& str) { return true; } - static v8::Handle<v8::Value> Base64Convert(const String& str, bool encode) { if (!IsAscii(str)) { V8Proxy::SetDOMException(INVALID_CHARACTER_ERR); @@ -2572,7 +2864,6 @@ static v8::Handle<v8::Value> Base64Convert(const String& str, bool encode) { return v8String(String(out.data(), out.size())); } - CALLBACK_FUNC_DECL(DOMWindowAtob) { INC_STATS(L"DOM.DOMWindow.atob()"); DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>( @@ -2595,7 +2886,6 @@ CALLBACK_FUNC_DECL(DOMWindowAtob) { return Base64Convert(str, false); } - CALLBACK_FUNC_DECL(DOMWindowBtoa) { INC_STATS(L"DOM.DOMWindow.btoa()"); DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>( @@ -2618,23 +2908,25 @@ CALLBACK_FUNC_DECL(DOMWindowBtoa) { return Base64Convert(str, true); } - // TODO(fqian): returning string is cheating, and we should // fix this by calling toString function on the receiver. // However, V8 implements toString in JavaScript, which requires // switching context of receiver. I consider it is dangerous. -CALLBACK_FUNC_DECL(DOMWindowToString) { - INC_STATS(L"DOM.DOMWindow.toString()"); - return args.This()->ObjectProtoToString(); +CALLBACK_FUNC_DECL(DOMWindowToString) +{ + INC_STATS(L"DOM.DOMWindow.toString()"); + return args.This()->ObjectProtoToString(); } - -CALLBACK_FUNC_DECL(DOMWindowNOP) { - INC_STATS(L"DOM.DOMWindow.nop()"); - return v8::Undefined(); +CALLBACK_FUNC_DECL(DOMWindowNOP) +{ + INC_STATS(L"DOM.DOMWindow.nop()"); + return v8::Undefined(); } +// EventTargetNode ------------------------------------------------------------- + CALLBACK_FUNC_DECL(EventTargetNodeAddEventListener) { INC_STATS(L"DOM.EventTargetNode.addEventListener()"); EventTargetNode* node = @@ -2654,7 +2946,6 @@ CALLBACK_FUNC_DECL(EventTargetNodeAddEventListener) { return v8::Undefined(); } - CALLBACK_FUNC_DECL(EventTargetNodeRemoveEventListener) { INC_STATS(L"DOM.EventTargetNode.removeEventListener()"); EventTargetNode* node = @@ -2679,365 +2970,164 @@ CALLBACK_FUNC_DECL(EventTargetNodeRemoveEventListener) { } -// ------------------------------------------------------------------ -// Customized XMLHttpRequest binding implementation - -// Use an array to hold dependents. It works like a ref-counted scheme. -// A value can be added more than once to the xhr object. -static void CreateHiddenXHRDependency(v8::Local<v8::Object> xhr, - v8::Local<v8::Value> value) { - ASSERT(V8Proxy::GetDOMWrapperType(xhr) == V8ClassIndex::XMLHTTPREQUEST); - v8::Local<v8::Value> cache = - xhr->GetInternalField(V8Custom::kXMLHttpRequestCacheIndex); - if (cache->IsNull() || cache->IsUndefined()) { - cache = v8::Array::New(); - xhr->SetInternalField(V8Custom::kXMLHttpRequestCacheIndex, cache); - } - - v8::Local<v8::Array> cache_array = v8::Local<v8::Array>::Cast(cache); - cache_array->Set(v8::Integer::New(cache_array->Length()), value); -} - - -static void RemoveHiddenXHRDependency(v8::Local<v8::Object> xhr, - v8::Local<v8::Value> value) { - ASSERT(V8Proxy::GetDOMWrapperType(xhr) == V8ClassIndex::XMLHTTPREQUEST); - v8::Local<v8::Value> cache = - xhr->GetInternalField(V8Custom::kXMLHttpRequestCacheIndex); - ASSERT(cache->IsArray()); - v8::Local<v8::Array> cache_array = v8::Local<v8::Array>::Cast(cache); - for (int i = cache_array->Length() - 1; i >= 0; i--) { - v8::Local<v8::Value> cached = cache_array->Get(v8::Integer::New(i)); - if (cached->StrictEquals(value)) { - cache_array->Delete(i); - return; - } - } - - // Should not reach here. - ASSERT(false); -} - - -ACCESSOR_SETTER(XMLHttpRequestOnreadystatechange) { - XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( - V8ClassIndex::XMLHTTPREQUEST, info.Holder()); - if (value->IsNull()) { - if (imp->onreadystatechange()) { - V8XHREventListener* listener = - static_cast<V8XHREventListener*>(imp->onreadystatechange()); - v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); - RemoveHiddenXHRDependency(info.Holder(), v8_listener); - } - - // Clear the listener - imp->setOnreadystatechange(0); - - } else { - V8Proxy* proxy = V8Proxy::retrieve(imp->document()->frame()); - if (!proxy) - return; - - EventListener* listener = - proxy->FindOrCreateXHREventListener(value, false); - if (listener) { - imp->setOnreadystatechange(listener); - CreateHiddenXHRDependency(info.Holder(), value); - } - } -} - - -ACCESSOR_SETTER(XMLHttpRequestOnload) { - XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( - V8ClassIndex::XMLHTTPREQUEST, info.Holder()); - if (value->IsNull()) { - if (imp->onload()) { - V8XHREventListener* listener = - static_cast<V8XHREventListener*>(imp->onload()); - v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); - RemoveHiddenXHRDependency(info.Holder(), v8_listener); - } - - imp->setOnload(0); - - } else { - V8Proxy* proxy = V8Proxy::retrieve(imp->document()->frame()); - if (!proxy) - return; - - EventListener* listener = - proxy->FindOrCreateXHREventListener(value, false); - if (listener) { - imp->setOnload(listener); - CreateHiddenXHRDependency(info.Holder(), value); - } - } -} - - -CALLBACK_FUNC_DECL(XMLHttpRequestAddEventListener) { - INC_STATS(L"DOM.XMLHttpRequest.addEventListener()"); - XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( - V8ClassIndex::XMLHTTPREQUEST, args.Holder()); - - V8Proxy* proxy = V8Proxy::retrieve(imp->document()->frame()); - if (!proxy) - return v8::Undefined(); - - EventListener* listener = - proxy->FindOrCreateXHREventListener(args[1], false); - if (listener) { - String type = ToWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - imp->addEventListener(type, listener, useCapture); - - CreateHiddenXHRDependency(args.Holder(), args[1]); - } - return v8::Undefined(); -} - - -CALLBACK_FUNC_DECL(XMLHttpRequestRemoveEventListener) { - INC_STATS(L"DOM.XMLHttpRequest.removeEventListener()"); - XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( - V8ClassIndex::XMLHTTPREQUEST, args.Holder()); - - V8Proxy* proxy = V8Proxy::retrieve(imp->document()->frame()); - if (!proxy) - return v8::Undefined(); // probably leaked - - EventListener* listener = - proxy->FindXHREventListener(args[1], false); - - if (listener) { - String type = ToWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - imp->removeEventListener(type, listener, useCapture); - - RemoveHiddenXHRDependency(args.Holder(), args[1]); - } - - return v8::Undefined(); -} - - -CALLBACK_FUNC_DECL(XMLHttpRequestOpen) { - INC_STATS(L"DOM.XMLHttpRequest.open()"); - // Four cases: - // open(method, url) - // open(method, url, async) - // open(method, url, async, user) - // open(method, url, async, user, passwd) - - if (args.Length() < 2) { - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments"); - return v8::Undefined(); - } - - // get the implementation - XMLHttpRequest* xhr = V8Proxy::ToNativeObject<XMLHttpRequest>( - V8ClassIndex::XMLHTTPREQUEST, args.Holder()); - - // retrieve parameters - String method = ToWebCoreString(args[0]); - String urlstring = ToWebCoreString(args[1]); - V8Proxy* proxy = V8Proxy::retrieve(); - KURL url = - proxy->frame()->document()->completeURL(urlstring).deprecatedString(); - - bool async = (args.Length() < 3) ? true : args[2]->BooleanValue(); - - ExceptionCode ec = 0; - String user, passwd; - if (args.Length() >= 4 && !args[3]->IsUndefined()) { - user = valueToStringWithNullCheck(args[3]); - - if (args.Length() >= 5 && !args[4]->IsUndefined()) { - passwd = valueToStringWithNullCheck(args[4]); - xhr->open(method, url, async, user, passwd, ec); - } else { - xhr->open(method, url, async, user, ec); - } - } else { - xhr->open(method, url, async, ec); - } - - if (ec != 0) { - V8Proxy::SetDOMException(ec); - return v8::Handle<v8::Value>(); - } - - return v8::Undefined(); -} - - -static bool IsDocumentType(v8::Handle<v8::Value> value) { - // TODO(fqian): add other document types. - return V8Document::HasInstance(value) || V8HTMLDocument::HasInstance(value); -} - - -CALLBACK_FUNC_DECL(XMLHttpRequestSend) { - INC_STATS(L"DOM.XMLHttpRequest.send()"); - // Two cases: - // send(document) - // send(string) - - // get implementation - XMLHttpRequest* xhr = V8Proxy::ToNativeObject<XMLHttpRequest>( - V8ClassIndex::XMLHTTPREQUEST, args.Holder()); - - String body; - if (args.Length() >= 1) { - v8::Handle<v8::Value> arg = args[0]; - if (IsDocumentType(arg)) { - v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(arg); - Document* doc = V8Proxy::DOMWrapperToNode<Document>(obj); - ASSERT(doc); - body = doc->toString(); - } else { - body = valueToStringWithNullCheck(arg); - } - } - - ExceptionCode ec = 0; - xhr->send(body, ec); - if (ec != 0) { - V8Proxy::SetDOMException(ec); - return v8::Handle<v8::Value>(); - } - - return v8::Undefined(); -} - - -CALLBACK_FUNC_DECL(XMLHttpRequestSetRequestHeader) { - INC_STATS(L"DOM.XMLHttpRequest.setRequestHeader()"); - if (args.Length() < 2) { - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments"); - return v8::Undefined(); - } - - XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( - V8ClassIndex::XMLHTTPREQUEST, args.Holder()); - ExceptionCode ec = 0; - String header = ToWebCoreString(args[0]); - String value = ToWebCoreString(args[1]); - imp->setRequestHeader(header, value, ec); - if (ec != 0) { - V8Proxy::SetDOMException(ec); - return v8::Handle<v8::Value>(); - } - return v8::Undefined(); -} - - -CALLBACK_FUNC_DECL(XMLHttpRequestGetResponseHeader) { - INC_STATS(L"DOM.XMLHttpRequest.getResponseHeader()"); - if (args.Length() < 1) { - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments"); - return v8::Undefined(); - } - - XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( - V8ClassIndex::XMLHTTPREQUEST, args.Holder()); - ExceptionCode ec = 0; - String header = ToWebCoreString(args[0]); - String result = imp->getResponseHeader(header, ec); - if (ec != 0) { - V8Proxy::SetDOMException(ec); - return v8::Handle<v8::Value>(); - } - return v8StringOrNull(result); -} - - -CALLBACK_FUNC_DECL(XMLHttpRequestOverrideMimeType) { - INC_STATS(L"DOM.XMLHttpRequest.overrideMimeType()"); - if (args.Length() < 1) { - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments"); - return v8::Undefined(); - } - - XMLHttpRequest* imp = V8Proxy::ToNativeObject<XMLHttpRequest>( - V8ClassIndex::XMLHTTPREQUEST, args.Holder()); - String value = ToWebCoreString(args[0]); - imp->overrideMIMEType(value); - return v8::Undefined(); -} +// TreeWalker ------------------------------------------------------------------ CALLBACK_FUNC_DECL(TreeWalkerParentNode) { INC_STATS(L"DOM.TreeWalker.parentNode()"); - TreeWalker* imp = V8Proxy::ToNativeObject<TreeWalker>( + TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>( V8ClassIndex::TREEWALKER, args.Holder()); - return V8Proxy::NodeToV8Object(imp->parentNode()); + + OwnPtr<ExceptionContext> context(new ExceptionContext()); + RefPtr<Node> result = treeWalker->parentNode(context.get()); + if (context->hadException()) { + v8::ThrowException(context->exception()); + return v8::Undefined(); + } + if (!result) return v8::Null(); + return V8Proxy::NodeToV8Object(result.get()); } CALLBACK_FUNC_DECL(TreeWalkerFirstChild) { INC_STATS(L"DOM.TreeWalker.firstChild()"); - TreeWalker* imp = V8Proxy::ToNativeObject<TreeWalker>( + TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>( V8ClassIndex::TREEWALKER, args.Holder()); - return V8Proxy::NodeToV8Object(imp->firstChild()); + + OwnPtr<ExceptionContext> context(new ExceptionContext()); + RefPtr<Node> result = treeWalker->firstChild(context.get()); + if (context->hadException()) { + v8::ThrowException(context->exception()); + return v8::Undefined(); + } + if (!result) return v8::Null(); + return V8Proxy::NodeToV8Object(result.get()); } CALLBACK_FUNC_DECL(TreeWalkerLastChild) { INC_STATS(L"DOM.TreeWalker.lastChild()"); - TreeWalker* imp = V8Proxy::ToNativeObject<TreeWalker>( + TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>( V8ClassIndex::TREEWALKER, args.Holder()); - return V8Proxy::NodeToV8Object(imp->lastChild()); + + OwnPtr<ExceptionContext> context(new ExceptionContext()); + RefPtr<Node> result = treeWalker->lastChild(context.get()); + if (context->hadException()) { + v8::ThrowException(context->exception()); + return v8::Undefined(); + } + if (!result) return v8::Null(); + return V8Proxy::NodeToV8Object(result.get()); } CALLBACK_FUNC_DECL(TreeWalkerNextNode) { INC_STATS(L"DOM.TreeWalker.nextNode()"); - TreeWalker* imp = V8Proxy::ToNativeObject<TreeWalker>( + TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>( V8ClassIndex::TREEWALKER, args.Holder()); - return V8Proxy::NodeToV8Object(imp->nextNode()); + + OwnPtr<ExceptionContext> context(new ExceptionContext()); + RefPtr<Node> result = treeWalker->nextNode(context.get()); + if (context->hadException()) { + v8::ThrowException(context->exception()); + return v8::Undefined(); + } + if (!result) return v8::Null(); + return V8Proxy::NodeToV8Object(result.get()); } CALLBACK_FUNC_DECL(TreeWalkerPreviousNode) { INC_STATS(L"DOM.TreeWalker.previousNode()"); - TreeWalker* imp = V8Proxy::ToNativeObject<TreeWalker>( + TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>( V8ClassIndex::TREEWALKER, args.Holder()); - return V8Proxy::NodeToV8Object(imp->previousNode()); + + OwnPtr<ExceptionContext> context(new ExceptionContext()); + RefPtr<Node> result = treeWalker->previousNode(context.get()); + if (context->hadException()) { + v8::ThrowException(context->exception()); + return v8::Undefined(); + } + if (!result) return v8::Null(); + return V8Proxy::NodeToV8Object(result.get()); } CALLBACK_FUNC_DECL(TreeWalkerNextSibling) { INC_STATS(L"DOM.TreeWalker.nextSibling()"); - TreeWalker* imp = V8Proxy::ToNativeObject<TreeWalker>( + TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>( V8ClassIndex::TREEWALKER, args.Holder()); - return V8Proxy::NodeToV8Object(imp->nextSibling()); + + OwnPtr<ExceptionContext> context(new ExceptionContext()); + RefPtr<Node> result = treeWalker->nextSibling(context.get()); + if (context->hadException()) { + v8::ThrowException(context->exception()); + return v8::Undefined(); + } + if (!result) return v8::Null(); + return V8Proxy::NodeToV8Object(result.get()); } CALLBACK_FUNC_DECL(TreeWalkerPreviousSibling) { INC_STATS(L"DOM.TreeWalker.previousSibling()"); - TreeWalker* imp = V8Proxy::ToNativeObject<TreeWalker>( + TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>( V8ClassIndex::TREEWALKER, args.Holder()); - return V8Proxy::NodeToV8Object(imp->previousSibling()); + + OwnPtr<ExceptionContext> context(new ExceptionContext()); + RefPtr<Node> result = treeWalker->previousSibling(context.get()); + if (context->hadException()) { + v8::ThrowException(context->exception()); + return v8::Undefined(); + } + if (!result) return v8::Null(); + return V8Proxy::NodeToV8Object(result.get()); } CALLBACK_FUNC_DECL(NodeIteratorNextNode) { INC_STATS(L"DOM.NodeIterator.nextNode()"); - NodeIterator* imp = V8Proxy::ToNativeObject<NodeIterator>( + NodeIterator* nodeIterator = V8Proxy::ToNativeObject<NodeIterator>( V8ClassIndex::NODEITERATOR, args.Holder()); + ExceptionCode ec = 0; - return V8Proxy::NodeToV8Object(imp->nextNode(ec)); + OwnPtr<ExceptionContext> context(new ExceptionContext()); + RefPtr<Node> result = nodeIterator->nextNode(context.get(), ec); + if (ec != 0) { + V8Proxy::SetDOMException(ec); + return v8::Null(); + } + if (context->hadException()) { + v8::ThrowException(context->exception()); + return v8::Undefined(); + } + if (!result) return v8::Null(); + return V8Proxy::NodeToV8Object(result.get()); } CALLBACK_FUNC_DECL(NodeIteratorPreviousNode) { INC_STATS(L"DOM.NodeIterator.previousNode()"); - NodeIterator* imp = V8Proxy::ToNativeObject<NodeIterator>( + NodeIterator* nodeIterator = V8Proxy::ToNativeObject<NodeIterator>( V8ClassIndex::NODEITERATOR, args.Holder()); + ExceptionCode ec = 0; - return V8Proxy::NodeToV8Object(imp->previousNode(ec)); + OwnPtr<ExceptionContext> context(new ExceptionContext()); + RefPtr<Node> result = nodeIterator->previousNode(context.get(), ec); + if (ec != 0) { + V8Proxy::SetDOMException(ec); + return v8::Null(); + } + if (context->hadException()) { + v8::ThrowException(context->exception()); + return v8::Undefined(); + } + if (!result) return v8::Null(); + return V8Proxy::NodeToV8Object(result.get()); } CALLBACK_FUNC_DECL(NodeFilterAcceptNode) { INC_STATS(L"DOM.NodeFilter.acceptNode()"); - NodeFilter* imp = V8Proxy::ToNativeObject<NodeFilter>( - V8ClassIndex::NODEFILTER, args.Holder()); - Node* node = V8Proxy::DOMWrapperToNode<Node>(args[0]); - return v8::Local<v8::Integer>(v8::Integer::New(imp->acceptNode(node))); + V8Proxy::SetDOMException(NOT_SUPPORTED_ERR); + return v8::Undefined(); +} + +// NSResolver +CALLBACK_FUNC_DECL(NSResolverLookupNamespaceURI) { + INC_STATS(L"DOM.NSResolver.lookupNamespaceURI()"); + V8Proxy::SetDOMException(NOT_SUPPORTED_ERR); + return v8::Undefined(); } ACCESSOR_SETTER(DOMWindowEventHandler) { @@ -3168,6 +3258,21 @@ ACCESSOR_SETTER(HTMLOptionsCollectionLength) { } #if ENABLE(SVG) + +ACCESSOR_GETTER(SVGLengthValue) { + INC_STATS(L"DOM.SVGLength.value"); + V8SVGPODTypeWrapper<SVGLength>* wrapper = V8Proxy::ToNativeObject<V8SVGPODTypeWrapper<SVGLength> >(V8ClassIndex::SVGLENGTH, info.Holder()); + SVGLength imp_instance = *wrapper; + SVGLength* imp = &imp_instance; + return v8::Number::New(imp->value(V8Proxy::GetSVGContext(wrapper))); +} + +CALLBACK_FUNC_DECL(SVGLengthConvertToSpecifiedUnits) { + INC_STATS(L"DOM.SVGLength.convertToSpecifiedUnits"); + V8Proxy::SetDOMException(NOT_SUPPORTED_ERR); + return v8::Undefined(); +} + CALLBACK_FUNC_DECL(SVGMatrixInverse) { INC_STATS(L"DOM.SVGMatrix.inverse()"); AffineTransform imp = @@ -3300,9 +3405,6 @@ NAMED_ACCESS_CHECK(Location) { #undef INDEXED_ACCESS_CHECK #undef NAMED_ACCESS_CHECK -#undef ACCESSOR_GETTER -#undef ACCESSOR_SETTER -#undef CALLBACK_FUNC_DECL #undef NAMED_PROPERTY_GETTER #undef NAMED_PROPERTY_SETTER #undef INDEXED_PROPERTY_GETTER diff --git a/webkit/port/bindings/v8/v8_custom.h b/webkit/port/bindings/v8/v8_custom.h index dae13ab..6c60e33 100644 --- a/webkit/port/bindings/v8/v8_custom.h +++ b/webkit/port/bindings/v8/v8_custom.h @@ -6,9 +6,22 @@ #define V8_CUSTOM_H__ #include <v8.h> +#include "v8_index.h" struct NPObject; +#define CALLBACK_FUNC_DECL(NAME) \ +v8::Handle<v8::Value> V8Custom::v8##NAME##Callback(const v8::Arguments& args) + +#define ACCESSOR_GETTER(NAME) \ +v8::Handle<v8::Value> V8Custom::v8##NAME##AccessorGetter(\ + v8::Local<v8::String> name, const v8::AccessorInfo& info) + +#define ACCESSOR_SETTER(NAME) \ +void V8Custom::v8##NAME##AccessorSetter(v8::Local<v8::String> name, \ + v8::Local<v8::Value> value, \ + const v8::AccessorInfo& info) + namespace WebCore { class Frame; @@ -186,6 +199,10 @@ DECLARE_CALLBACK(HTMLDocumentClear) // Document customized functions DECLARE_CALLBACK(DocumentEvaluate) +DECLARE_CALLBACK(DocumentQuerySelector) +DECLARE_CALLBACK(DocumentQuerySelectorAll) +DECLARE_CALLBACK(DocumentFragmentQuerySelector) +DECLARE_CALLBACK(DocumentFragmentQuerySelectorAll) // Window customized functions DECLARE_CALLBACK(DOMWindowAddEventListener) @@ -225,6 +242,23 @@ DECLARE_CALLBACK(CanvasRenderingContext2DSetShadow) DECLARE_CALLBACK(CanvasRenderingContext2DDrawImage) DECLARE_CALLBACK(CanvasRenderingContext2DDrawImageFromRect) DECLARE_CALLBACK(CanvasRenderingContext2DCreatePattern) +DECLARE_CALLBACK(CanvasRenderingContext2DFillText) +DECLARE_CALLBACK(CanvasRenderingContext2DStrokeText) +DECLARE_CALLBACK(CanvasRenderingContext2DPutImageData) + +// Console customized functions +DECLARE_CALLBACK(ConsoleAssert) +DECLARE_CALLBACK(ConsoleCount) +DECLARE_CALLBACK(ConsoleDebug) +DECLARE_CALLBACK(ConsoleDir) +DECLARE_CALLBACK(ConsoleError) +DECLARE_CALLBACK(ConsoleGroup) +DECLARE_CALLBACK(ConsoleInfo) +DECLARE_CALLBACK(ConsoleLog) +DECLARE_CALLBACK(ConsoleProfile) +DECLARE_CALLBACK(ConsoleProfileEnd) +DECLARE_CALLBACK(ConsoleTimeEnd) +DECLARE_CALLBACK(ConsoleWarn) // Implementation of Clipboard methods. DECLARE_CALLBACK(ClipboardClearData) @@ -232,6 +266,8 @@ DECLARE_CALLBACK(ClipboardGetData) DECLARE_CALLBACK(ClipboardSetData) // Implementation of Element methods. +DECLARE_CALLBACK(ElementQuerySelector) +DECLARE_CALLBACK(ElementQuerySelectorAll) DECLARE_CALLBACK(ElementSetAttribute) DECLARE_CALLBACK(ElementSetAttributeNode) DECLARE_CALLBACK(ElementSetAttributeNS) @@ -243,8 +279,12 @@ DECLARE_CALLBACK(EventTargetNodeAddEventListener) DECLARE_CALLBACK(EventTargetNodeRemoveEventListener) // Custom implementation of XMLHttpRequest properties -DECLARE_PROPERTY_ACCESSOR_SETTER(XMLHttpRequestOnreadystatechange) -DECLARE_PROPERTY_ACCESSOR_SETTER(XMLHttpRequestOnload) +DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnabort) +DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnerror) +DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnload) +DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnloadstart) +DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnprogress) +DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnreadystatechange) DECLARE_CALLBACK(XMLHttpRequestAddEventListener) DECLARE_CALLBACK(XMLHttpRequestRemoveEventListener) DECLARE_CALLBACK(XMLHttpRequestOpen) @@ -252,6 +292,17 @@ DECLARE_CALLBACK(XMLHttpRequestSend) DECLARE_CALLBACK(XMLHttpRequestSetRequestHeader) DECLARE_CALLBACK(XMLHttpRequestGetResponseHeader) DECLARE_CALLBACK(XMLHttpRequestOverrideMimeType) +DECLARE_CALLBACK(XMLHttpRequestDispatchEvent) + +// Custom implementation of XMLHttpRequestUpload properties +DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestUploadOnabort) +DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestUploadOnerror) +DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestUploadOnload) +DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestUploadOnloadstart) +DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestUploadOnprogress) +DECLARE_CALLBACK(XMLHttpRequestUploadAddEventListener) +DECLARE_CALLBACK(XMLHttpRequestUploadRemoveEventListener) +DECLARE_CALLBACK(XMLHttpRequestUploadDispatchEvent) // Custom implementation of TreeWalker functions DECLARE_CALLBACK(TreeWalkerParentNode) @@ -299,8 +350,13 @@ DECLARE_INDEXED_PROPERTY_SETTER(HTMLOptionsCollection) DECLARE_INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection) DECLARE_NAMED_PROPERTY_GETTER(HTMLCollection) +// NSResolver +DECLARE_CALLBACK(NSResolverLookupNamespaceURI) + // SVG custom properties and callbacks #if ENABLE(SVG) +DECLARE_PROPERTY_ACCESSOR_GETTER(SVGLengthValue) +DECLARE_CALLBACK(SVGLengthConvertToSpecifiedUnits) DECLARE_CALLBACK(SVGMatrixInverse) DECLARE_CALLBACK(SVGMatrixRotateFromVector) #endif diff --git a/webkit/port/bindings/v8/v8_events.cpp b/webkit/port/bindings/v8/v8_events.cpp index feb13f53..33bb48f 100644 --- a/webkit/port/bindings/v8/v8_events.cpp +++ b/webkit/port/bindings/v8/v8_events.cpp @@ -223,6 +223,11 @@ v8::Local<v8::Object> V8EventListener::GetThisObject(Event* event, V8ClassIndex::XMLHTTPREQUEST, target->toXMLHttpRequest()); return v8::Local<v8::Object>::New(v8::Handle<v8::Object>::Cast(value)); + } else if (target->toXMLHttpRequestUpload()) { + v8::Handle<v8::Value> value = V8Proxy::ToV8Object( + V8ClassIndex::XMLHTTPREQUESTUPLOAD, target->toXMLHttpRequestUpload()); + return v8::Local<v8::Object>::New(v8::Handle<v8::Object>::Cast(value)); + } else { ASSERT(false); return v8::Local<v8::Object>(); diff --git a/webkit/port/bindings/v8/v8_index.cpp b/webkit/port/bindings/v8/v8_index.cpp index 4cbe7d9..e731b05 100644 --- a/webkit/port/bindings/v8/v8_index.cpp +++ b/webkit/port/bindings/v8/v8_index.cpp @@ -38,6 +38,7 @@ #include "V8CanvasRenderingContext2D.h" #include "V8CanvasGradient.h" #include "V8CanvasPattern.h" +#include "V8CanvasPixelArray.h" #include "V8CDATASection.h" #include "V8CharacterData.h" #include "V8Clipboard.h" @@ -63,6 +64,8 @@ #include "V8Element.h" #include "V8Entity.h" #include "V8EntityReference.h" +#include "V8File.h" +#include "V8FileList.h" #include "V8History.h" #include "V8HTMLCanvasElement.h" #include "V8UndetectableHTMLCollection.h" @@ -127,6 +130,7 @@ #include "V8HTMLTextAreaElement.h" #include "V8HTMLTitleElement.h" #include "V8HTMLUListElement.h" +#include "V8ImageData.h" #include "V8InspectorController.h" #include "V8MediaList.h" #include "V8MessageEvent.h" @@ -135,6 +139,7 @@ #include "V8NodeList.h" #include "V8NodeFilter.h" #include "V8Notation.h" +#include "V8NSResolver.h" #include "V8ProcessingInstruction.h" #include "V8ProgressEvent.h" #include "V8StyleSheet.h" @@ -164,6 +169,7 @@ #include "V8RangeException.h" #include "V8Rect.h" #include "V8NodeIterator.h" +#include "V8TextMetrics.h" #include "V8TreeWalker.h" #include "V8StyleSheetList.h" #include "V8DOMImplementation.h" @@ -172,6 +178,7 @@ #include "V8XPathExpression.h" #include "V8XPathNSResolver.h" #include "V8XMLHttpRequest.h" +#include "V8XMLHttpRequestUpload.h" #include "V8XMLHttpRequestException.h" #include "V8XMLSerializer.h" #include "V8XPathEvaluator.h" diff --git a/webkit/port/bindings/v8/v8_index.h b/webkit/port/bindings/v8/v8_index.h index 8ff9d35..0df22e9 100644 --- a/webkit/port/bindings/v8/v8_index.h +++ b/webkit/port/bindings/v8/v8_index.h @@ -211,6 +211,7 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(BARINFO, BarInfo) \ V(CANVASGRADIENT, CanvasGradient) \ V(CANVASPATTERN, CanvasPattern) \ + V(CANVASPIXELARRAY, CanvasPixelArray) \ V(CANVASRENDERINGCONTEXT2D, CanvasRenderingContext2D) \ V(CLIPBOARD, Clipboard) \ V(CONSOLE, Console) \ @@ -235,10 +236,13 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(DOMWINDOW, DOMWindow) \ V(EVENT, Event) \ V(EVENTEXCEPTION, EventException) \ + V(FILE, File) \ + V(FILELIST, FileList) \ V(HISTORY, History) \ V(UNDETECTABLEHTMLCOLLECTION, UndetectableHTMLCollection) \ V(HTMLCOLLECTION, HTMLCollection) \ V(HTMLOPTIONSCOLLECTION, HTMLOptionsCollection) \ + V(IMAGEDATA, ImageData) \ V(INSPECTORCONTROLLER, InspectorController) \ V(KEYBOARDEVENT, KeyboardEvent) \ V(LOCATION, Location) \ @@ -253,6 +257,7 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(NODEFILTER, NodeFilter) \ V(NODEITERATOR, NodeIterator) \ V(NODELIST, NodeList) \ + V(NSRESOLVER, NSResolver) \ V(OVERFLOWEVENT, OverflowEvent) \ V(PLUGIN, Plugin) \ V(PLUGINARRAY, PluginArray) \ @@ -265,10 +270,12 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(STYLESHEET, StyleSheet) \ V(STYLESHEETLIST, StyleSheetList) \ V(TEXTEVENT, TextEvent) \ + V(TEXTMETRICS, TextMetrics) \ V(TREEWALKER, TreeWalker) \ V(UIEVENT, UIEvent) \ V(WHEELEVENT, WheelEvent) \ V(XMLHTTPREQUEST, XMLHttpRequest) \ + V(XMLHTTPREQUESTUPLOAD, XMLHttpRequestUpload) \ V(XMLHTTPREQUESTEXCEPTION, XMLHttpRequestException) \ V(XMLSERIALIZER, XMLSerializer) \ V(XPATHEVALUATOR, XPathEvaluator) \ diff --git a/webkit/port/bindings/v8/v8_nodefilter.cpp b/webkit/port/bindings/v8/v8_nodefilter.cpp index c8846ab..3f958e5 100644 --- a/webkit/port/bindings/v8/v8_nodefilter.cpp +++ b/webkit/port/bindings/v8/v8_nodefilter.cpp @@ -31,6 +31,7 @@ #include "v8_nodefilter.h" #include "v8_proxy.h" +#include "ExceptionContext.h" #include "NodeFilter.h" #include "Node.h" @@ -51,15 +52,17 @@ V8NodeFilterCondition::~V8NodeFilterCondition() { m_filter.Clear(); } -short V8NodeFilterCondition::acceptNode(Node* node) const { +short V8NodeFilterCondition::acceptNode(ExceptionContext* exception_context, + Node* node) const { ASSERT(v8::Context::InContext()); if (!m_filter->IsFunction()) return NodeFilter::FILTER_ACCEPT; - v8::TryCatch exception_catcher; + ExceptionCatcher exception_catcher(exception_context); v8::Handle<v8::Object> this_obj = v8::Context::GetCurrent()->Global(); - v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(m_filter); + v8::Handle<v8::Function> callback = + v8::Handle<v8::Function>::Cast(m_filter); v8::Handle<v8::Value>* args = new v8::Handle<v8::Value>[1]; args[0] = V8Proxy::ToV8Object(V8ClassIndex::NODE, node); @@ -70,9 +73,7 @@ short V8NodeFilterCondition::acceptNode(Node* node) const { proxy->CallFunction(callback, this_obj, 1, args); delete[] args; - // TODO(fqian): this code can be removed when issue 1042294 is fixed. - // See also 1068243. - if (exception_catcher.HasCaught()) { + if (exception_context->hadException()) { return NodeFilter::FILTER_REJECT; } diff --git a/webkit/port/bindings/v8/v8_nodefilter.h b/webkit/port/bindings/v8/v8_nodefilter.h index cf203eff..ef7906d 100644 --- a/webkit/port/bindings/v8/v8_nodefilter.h +++ b/webkit/port/bindings/v8/v8_nodefilter.h @@ -19,7 +19,8 @@ class V8NodeFilterCondition : public NodeFilterCondition { explicit V8NodeFilterCondition(v8::Handle<v8::Value> filter); virtual ~V8NodeFilterCondition(); - virtual short acceptNode(Node* node) const; + virtual short acceptNode(ExceptionContext* exception_context, + Node* node) const; private: mutable v8::Persistent<v8::Value> m_filter; diff --git a/webkit/port/bindings/v8/v8_proxy.cpp b/webkit/port/bindings/v8/v8_proxy.cpp index 60f0488..ae96b63 100644 --- a/webkit/port/bindings/v8/v8_proxy.cpp +++ b/webkit/port/bindings/v8/v8_proxy.cpp @@ -39,7 +39,6 @@ #include "v8_custom.h" #include "v8_collection.h" #include "v8_nodefilter.h" -#include "V8Bridge.h" #include "RefCounted.h" // for Peerable @@ -65,6 +64,7 @@ #include "Notation.h" #include "Text.h" #include "ProcessingInstruction.h" +#include "Console.h" #include "CharacterData.h" #include "DocumentType.h" #include "DocumentFragment.h" @@ -82,6 +82,7 @@ #include "FrameLoader.h" #include "FrameTree.h" #include "RangeException.h" +#include "ScriptController.h" #include "NodeFilter.h" #include "SecurityOrigin.h" #include "XMLHttpRequestException.h" @@ -97,8 +98,10 @@ #include "XPathEvaluator.h" #endif +#undef LOG #include "base/stats_table.h" #include "base/trace_event.h" +#include "webkit/glue/webkit_glue.h" #include "webkit/glue/glue_util.h" #include "webkit/glue/webkit_glue.h" @@ -154,9 +157,10 @@ namespace WebCore { // typedef HashMap<v8::Value*, GlobalHandleInfo*> GlobalHandleMap; -static GlobalHandleMap& global_handle_map() { - static GlobalHandleMap static_global_handle_map; - return static_global_handle_map; +static GlobalHandleMap& global_handle_map() +{ + static GlobalHandleMap static_global_handle_map; + return static_global_handle_map; } @@ -178,12 +182,12 @@ void V8Proxy::RegisterGlobalHandle(GlobalHandleType type, void* host, } -void V8Proxy::UnregisterGlobalHandle(void* host, - v8::Persistent<v8::Value> handle) { - ASSERT(global_handle_map().contains(*handle)); - GlobalHandleInfo* info = global_handle_map().take(*handle); - ASSERT(info->host_ == host); - delete info; +void V8Proxy::UnregisterGlobalHandle(void* host, v8::Persistent<v8::Value> handle) +{ + ASSERT(global_handle_map().contains(*handle)); + GlobalHandleInfo* info = global_handle_map().take(*handle); + ASSERT(info->host_ == host); + delete info; } #endif // ifndef NDEBUG @@ -293,13 +297,12 @@ static void WeakSVGElementInstanceCallback(v8::Persistent<v8::Object> obj, v8::Handle<v8::Value> V8Proxy::SVGElementInstanceToV8Object( SVGElementInstance* instance) { - if (!instance) return v8::Null(); + if (!instance) + return v8::Null(); - v8::Handle<v8::Object> existing_instance = - dom_svg_element_instance_map().get(instance); - if (!existing_instance.IsEmpty()) { + v8::Handle<v8::Object> existing_instance = dom_svg_element_instance_map().get(instance); + if (!existing_instance.IsEmpty()) return existing_instance; - } instance->ref(); @@ -317,31 +320,34 @@ v8::Handle<v8::Value> V8Proxy::SVGElementInstanceToV8Object( } // SVG non-node elements may have a reference to a context node which -// should be notified when the element is changed +// should be notified when the element is change static void WeakSVGObjectWithContext(v8::Persistent<v8::Object> obj, void* param); // Map of SVG objects with contexts to V8 objects -static DOMWrapperMap<Peerable>& dom_svg_object_with_context_map() { - static DOMPeerableWrapperMap<Peerable> - static_dom_svg_object_with_context_map(&WeakSVGObjectWithContext); - return static_dom_svg_object_with_context_map; +static DOMWrapperMap<Peerable>& dom_svg_object_with_context_map() +{ + static DOMPeerableWrapperMap<Peerable> + static_dom_svg_object_with_context_map(&WeakSVGObjectWithContext); + return static_dom_svg_object_with_context_map; } // Map of SVG objects with contexts to their contexts -static HashMap<void*, SVGElement*>& svg_object_to_context_map() { - static HashMap<void*, SVGElement*> static_svg_object_to_context_map; - return static_svg_object_to_context_map; +static HashMap<void*, SVGElement*>& svg_object_to_context_map() +{ + static HashMap<void*, SVGElement*> static_svg_object_to_context_map; + return static_svg_object_to_context_map; } v8::Handle<v8::Value> V8Proxy::SVGObjectWithContextToV8Object( - Peerable* object, V8ClassIndex::V8WrapperType type) { - if (!object) return v8::Null(); + Peerable* object, V8ClassIndex::V8WrapperType type) +{ + if (!object) + return v8::Null(); // Special case: SVGPathSegs need to be downcast to their real type - if (type == V8ClassIndex::SVGPATHSEG) { + if (type == V8ClassIndex::SVGPATHSEG) type = V8Custom::DowncastSVGPathSeg(object); - } v8::Persistent<v8::Object> result = dom_svg_object_with_context_map().get(object); @@ -372,26 +378,25 @@ static void WeakSVGObjectWithContext(v8::Persistent<v8::Object> obj, dom_svg_object_with_context_map().forget(dom_obj); } -void V8Proxy::SetSVGContext(void* obj, SVGElement* context) { +void V8Proxy::SetSVGContext(void* obj, SVGElement* context) +{ SVGElement* old_context = svg_object_to_context_map().get(obj); - if (old_context == context) { + if (old_context == context) return; - } - if (old_context) { + if (old_context) old_context->deref(); - } - if (context) { + if (context) context->ref(); - } svg_object_to_context_map().set(obj, context); } -SVGElement* V8Proxy::GetSVGContext(void* obj) { - return svg_object_to_context_map().get(obj); +SVGElement* V8Proxy::GetSVGContext(void* obj) +{ + return svg_object_to_context_map().get(obj); } #endif @@ -409,17 +414,17 @@ static void WeakPeerableCallback(v8::Persistent<v8::Object> obj, void* para) { dom_object_map().forget(dom_obj); } - -static void WeakNodeCallback(v8::Persistent<v8::Object> obj, void* param) { +static void WeakNodeCallback(v8::Persistent<v8::Object> obj, void* param) +{ Node* node = static_cast<Node*>(param); ASSERT(dom_node_map().contains(node)); dom_node_map().forget(node); } - // Create object groups for DOM tree nodes. -static void GCPrologue() { +static void GCPrologue() +{ #ifndef NDEBUG // Check that all references in the map are weak. PeerableMap peer_map = dom_object_map().impl(); @@ -448,9 +453,8 @@ static void GCPrologue() { !static_cast<HTMLImageElement*>(node)->haveFiredLoadEvent()) ) { Document* doc = node->document(); v8::Persistent<v8::Object> wrapper = dom_node_map().get(node); - if (!wrapper.IsEmpty()) { + if (!wrapper.IsEmpty()) v8::V8::AddObjectToGroup(doc, wrapper); - } } } } @@ -477,20 +481,23 @@ static void GCEpilogue() { #endif } - // A map from a peerable node to its JS wrapper, the wrapper // is kept as a strong reference to survive GCs. -static PeerableMap& gc_protected_map() { - static PeerableMap static_gc_protected_map; - return static_gc_protected_map; +static PeerableMap& gc_protected_map() +{ + static PeerableMap static_gc_protected_map; + return static_gc_protected_map; } - // static -void V8Proxy::GCProtect(Peerable* dom_object) { - if (!dom_object) return; - if (gc_protected_map().contains(dom_object)) return; - if (!dom_object->peer()) return; +void V8Proxy::GCProtect(Peerable* dom_object) +{ + if (!dom_object) + return; + if (gc_protected_map().contains(dom_object)) + return; + if (!dom_object->peer()) + return; // Create a new (strong) persistent handle for the peer. v8::Persistent<v8::Object> @@ -502,8 +509,10 @@ void V8Proxy::GCProtect(Peerable* dom_object) { // static void V8Proxy::GCUnprotect(Peerable* dom_object) { - if (!dom_object) return; - if (!gc_protected_map().contains(dom_object)) return; + if (!dom_object) + return; + if (!gc_protected_map().contains(dom_object)) + return; // Dispose the strong reference. v8::Persistent<v8::Object> wrapper(gc_protected_map().take(dom_object)); @@ -535,17 +544,13 @@ class JavaScriptConsoleMessage { const unsigned m_lineNumber; }; - -void JavaScriptConsoleMessage::AddToPage(Page* page) const { - ASSERT(page); - Chrome* chrome = page->chrome(); - // Only messages with ErrorMessageLevel are logged when - // calling Chrome::addMessageToConsole(). - chrome->addMessageToConsole(JSMessageSource, ErrorMessageLevel, - m_string, m_lineNumber, m_sourceID); +void JavaScriptConsoleMessage::AddToPage(Page* page) const +{ + ASSERT(page); + Console* console = page->mainFrame()->domWindow()->console(); + console->addMessage(JSMessageSource, ErrorMessageLevel, m_string, m_lineNumber, m_sourceID); } - // The ConsoleMessageManager handles all console messages that stem // from JavaScript. It keeps a list of messages that have been delayed but // it makes sure to add all messages to the console in the right order. @@ -590,21 +595,22 @@ void ConsoleMessageManager::AddMessage( } -void ConsoleMessageManager::AddDelayedMessage( - const JavaScriptConsoleMessage& message) { - if (!m_delayed) { - // Allocate a vector for the delayed messages. Will be - // deallocated when the delayed messages are processed - // in ProcessDelayedMessages(). - m_delayed = new Vector<JavaScriptConsoleMessage>(); - } - m_delayed->append(message); +void ConsoleMessageManager::AddDelayedMessage(const JavaScriptConsoleMessage& message) +{ + if (!m_delayed) + // Allocate a vector for the delayed messages. Will be + // deallocated when the delayed messages are processed + // in ProcessDelayedMessages(). + m_delayed = new Vector<JavaScriptConsoleMessage>(); + m_delayed->append(message); } -void ConsoleMessageManager::ProcessDelayedMessages() { +void ConsoleMessageManager::ProcessDelayedMessages() +{ // If we have a delayed vector it cannot be empty. - if (!m_delayed) return; + if (!m_delayed) + return; ASSERT(!m_delayed->isEmpty()); // Add the delayed messages to the page of the active @@ -613,8 +619,10 @@ void ConsoleMessageManager::ProcessDelayedMessages() { // posting messages. We still deallocate the vector. Frame* frame = V8Proxy::retrieveActiveFrame(); Page* page = NULL; - if (frame) page = frame->page(); - if (!page) m_delayed->clear(); + if (frame) + page = frame->page(); + if (!page) + m_delayed->clear(); // Iterate through all the delayed messages and add them // to the console. @@ -637,23 +645,25 @@ class ConsoleMessageScope { ~ConsoleMessageScope() { ConsoleMessageManager::ProcessDelayedMessages(); } }; - -void log_info(Frame* frame, const String& msg, const String& url) { - Page* page = frame->page(); - if (!page) return; - JavaScriptConsoleMessage message(msg, url, 0); - ConsoleMessageManager::AddMessage(page, message); +void log_info(Frame* frame, const String& msg, const String& url) +{ + Page* page = frame->page(); + if (!page) + return; + JavaScriptConsoleMessage message(msg, url, 0); + ConsoleMessageManager::AddMessage(page, message); } - static void HandleConsoleMessage(v8::Handle<v8::Message> message, v8::Handle<v8::Value> data) { // Use the frame where JavaScript is called from. Frame* frame = V8Proxy::retrieveActiveFrame(); - if (!frame) return; + if (!frame) + return; Page* page = frame->page(); - if (!page) return; + if (!page) + return; v8::Handle<v8::String> errorMessageString = message->Get(); ASSERT(!errorMessageString.IsEmpty()); @@ -679,7 +689,8 @@ enum DelayReporting { static void ReportUnsafeAccessTo(Frame* target, DelayReporting delay) { ASSERT(target); Document* targetDocument = target->document(); - if (!targetDocument) return; + if (!targetDocument) + return; Frame* source = V8Proxy::retrieveActiveFrame(); Document* sourceDocument = source->document(); @@ -690,8 +701,8 @@ static void ReportUnsafeAccessTo(Frame* target, DelayReporting delay) { String str = String::format("Unsafe JavaScript attempt to access frame " "with URL %s from frame with URL %s. Domains, protocols and ports must " "match.\n", - targetDocument->url().utf8().data(), - sourceDocument->url().utf8().data()); + targetDocument->url().string().utf8().data(), + sourceDocument->url().string().utf8().data()); // Build a console message with fake source ID and line number. const String kSourceID = ""; @@ -713,72 +724,72 @@ static void ReportUnsafeAccessTo(Frame* target, DelayReporting delay) { } } - static void ReportUnsafeJavaScriptAccess(v8::Local<v8::Object> host, v8::AccessType type, v8::Local<v8::Value> data) { - // Do not report error if the access type is HAS. - if (type == v8::ACCESS_HAS) return; + // Do not report error if the access type is HAS. + if (type == v8::ACCESS_HAS) + return; - Frame* target = V8Custom::GetTargetFrame(host, data); - if (target) - ReportUnsafeAccessTo(target, REPORT_LATER); + Frame* target = V8Custom::GetTargetFrame(host, data); + if (target) + ReportUnsafeAccessTo(target, REPORT_LATER); } - -static void ReportFatalErrorInV8(const char* location, const char* message) { - // V8 is shutdown, we cannot use V8 api. - // The only thing we can do is to disable JavaScript. - // TODO: clean up V8Proxy and disable JavaScript. - printf("V8 error: %s (%s)\n", message, location); +static void ReportFatalErrorInV8(const char* location, const char* message) +{ + // V8 is shutdown, we cannot use V8 api. + // The only thing we can do is to disable JavaScript. + // TODO: clean up V8Proxy and disable JavaScript. + printf("V8 error: %s (%s)\n", message, location); } - -static void HandleFatalErrorInV8() { - // TODO: We temporarily deal with V8 internal error situations - // such as out-of-memory by crashing the renderer. - CRASH(); +static void HandleFatalErrorInV8() +{ + // TODO: We temporarily deal with V8 internal error situations + // such as out-of-memory by crashing the renderer. + CRASH(); } -V8Proxy::~V8Proxy() { - clear(); - DestroyGlobal(); +V8Proxy::~V8Proxy() +{ + clear(); + DestroyGlobal(); } - -void V8Proxy::DestroyGlobal() { - if (!m_global.IsEmpty()) { +void V8Proxy::DestroyGlobal() +{ + if (!m_global.IsEmpty()) { #ifndef NDEBUG - UnregisterGlobalHandle(this, m_global); + UnregisterGlobalHandle(this, m_global); #endif - m_global.Dispose(); - m_global.Clear(); - } + m_global.Dispose(); + m_global.Clear(); + } } - -void V8Proxy::SetJSWrapperForDOMObject(Peerable* obj, - v8::Persistent<v8::Object> wrapper) { - dom_object_map().set(obj, wrapper); +void V8Proxy::SetJSWrapperForDOMObject(Peerable* obj, v8::Persistent<v8::Object> wrapper) +{ + dom_object_map().set(obj, wrapper); } - -void V8Proxy::SetJSWrapperForDOMNode(Node* node, - v8::Persistent<v8::Object> wrapper) { - dom_node_map().set(node, wrapper); +void V8Proxy::SetJSWrapperForDOMNode(Node* node, v8::Persistent<v8::Object> wrapper) +{ + dom_node_map().set(node, wrapper); } - EventListener* V8Proxy::createHTMLEventHandler(const String& functionName, - const String& code, Node* node) { - return new V8LazyEventListener(m_frame, code, functionName); + const String& code, Node* node) +{ + return new V8LazyEventListener(m_frame, code, functionName); } #if ENABLE(SVG) EventListener* V8Proxy::createSVGEventHandler(const String& functionName, - const String& code, Node* node) { - return new V8LazyEventListener(m_frame, code, functionName); + const String& code, Node* node) +{ + return new V8LazyEventListener(m_frame, code, functionName); } #endif @@ -790,7 +801,8 @@ static V8EventListener* FindEventListenerInList(V8EventListenerList& list, bool html) { ASSERT(v8::Context::InContext()); - if (!listener->IsObject()) return 0; + if (!listener->IsObject()) + return 0; V8EventListenerList::iterator p = list.begin(); while (p != list.end()) { @@ -802,31 +814,31 @@ static V8EventListener* FindEventListenerInList(V8EventListenerList& list, // check using the == operator on the handles. This is much, // much faster than calling StrictEquals through the API in // the negative case. - if (el->isHTMLEventListener() == html && listener == wrapper) { - return el; - } + if (el->isHTMLEventListener() == html && listener == wrapper) + return el; ++p; } return 0; } - // Find an existing wrapper for a JS event listener in the map. V8EventListener* V8Proxy::FindV8EventListener(v8::Local<v8::Value> listener, - bool html) { - return FindEventListenerInList(m_event_listeners, listener, html); + bool html) +{ + return FindEventListenerInList(m_event_listeners, listener, html); } - -V8EventListener* V8Proxy::FindOrCreateV8EventListener(v8::Local<v8::Value> obj, - bool html) { +V8EventListener* V8Proxy::FindOrCreateV8EventListener(v8::Local<v8::Value> obj, bool html) +{ ASSERT(v8::Context::InContext()); - if (!obj->IsObject()) return 0; + if (!obj->IsObject()) + return 0; V8EventListener* wrapper = FindEventListenerInList(m_event_listeners, obj, html); - if (wrapper) return wrapper; + if (wrapper) + return wrapper; // Create a new one, and add to cache. V8EventListener* new_listener = @@ -921,63 +933,63 @@ void V8Proxy::DisconnectEventListeners() { v8::Handle<v8::Script> V8Proxy::CompileScript(v8::Handle<v8::String> code, const String& fileName, - int baseLine) { - const uint16_t* fileNameString = FromWebCoreString(fileName); - v8::Handle<v8::String> name = + int baseLine) +{ + const uint16_t* fileNameString = FromWebCoreString(fileName); + v8::Handle<v8::String> name = v8::String::New(fileNameString, fileName.length()); - v8::Handle<v8::Integer> line = v8::Integer::New(baseLine); - v8::ScriptOrigin origin(name, line); - v8::Handle<v8::Script> script = v8::Script::Compile(code, &origin); - return script; + v8::Handle<v8::Integer> line = v8::Integer::New(baseLine); + v8::ScriptOrigin origin(name, line); + v8::Handle<v8::Script> script = v8::Script::Compile(code, &origin); + return script; } +bool V8Proxy::HandleOutOfMemory() +{ + v8::Local<v8::Context> context = v8::Context::GetCurrent(); -bool V8Proxy::HandleOutOfMemory() { - v8::Local<v8::Context> context = v8::Context::GetCurrent(); - - if (!context->HasOutOfMemoryException()) - return false; + if (!context->HasOutOfMemoryException()) + return false; - // Warning, error, disable JS for this frame? - Frame* frame = V8Proxy::retrieveFrame(context); + // Warning, error, disable JS for this frame? + Frame* frame = V8Proxy::retrieveFrame(context); - V8Proxy* proxy = V8Proxy::retrieve(frame); - // Clean m_context, m_document, and event handlers. - proxy->clear(); - // Destroy the global object. - proxy->DestroyGlobal(); + V8Proxy* proxy = V8Proxy::retrieve(frame); + // Clean m_context, m_document, and event handlers. + proxy->clear(); + // Destroy the global object. + proxy->DestroyGlobal(); - webkit_glue::NotifyJSOutOfMemory(frame); + webkit_glue::NotifyJSOutOfMemory(frame); - // Disable JS. - Settings* settings = frame->settings(); - ASSERT(settings); - settings->setJavaScriptEnabled(false); + // Disable JS. + Settings* settings = frame->settings(); + ASSERT(settings); + settings->setJavaScriptEnabled(false); - return true; + return true; } - v8::Local<v8::Value> V8Proxy::Evaluate(const String& fileName, int baseLine, - const String& str, Node* n) { - ASSERT(v8::Context::InContext()); - - // Compile the script. - v8::Local<v8::String> code = v8ExternalString(str); - TRACE_EVENT_BEGIN("v8.compile", n, ""); - v8::Handle<v8::Script> script = CompileScript(code, fileName, baseLine); - TRACE_EVENT_END("v8.compile", n, ""); - - // Set inlineCode to true for <a href="javascript:doSomething()"> - // and false for <script>doSomething</script>. For some reason, fileName - // gives us this information. - TRACE_EVENT_BEGIN("v8.run", n, ""); - v8::Local<v8::Value> result = RunScript(script, fileName.isNull()); - TRACE_EVENT_END("v8.run", n, ""); - return result; + const String& str, Node* n) +{ + ASSERT(v8::Context::InContext()); + + // Compile the script. + v8::Local<v8::String> code = v8ExternalString(str); + TRACE_EVENT_BEGIN("v8.compile", n, ""); + v8::Handle<v8::Script> script = CompileScript(code, fileName, baseLine); + TRACE_EVENT_END("v8.compile", n, ""); + + // Set inlineCode to true for <a href="javascript:doSomething()"> + // and false for <script>doSomething</script>. For some reason, fileName + // gives us this information. + TRACE_EVENT_BEGIN("v8.run", n, ""); + v8::Local<v8::Value> result = RunScript(script, fileName.isNull()); + TRACE_EVENT_END("v8.run", n, ""); + return result; } - v8::Local<v8::Value> V8Proxy::RunScript(v8::Handle<v8::Script> script, bool inline_code) { if (script.IsEmpty()) @@ -1293,6 +1305,14 @@ v8::Persistent<v8::FunctionTemplate> V8Proxy::GetTemplate( desc->SetCallHandler(USE_CALLBACK(XMLHttpRequestConstructor)); break; } + case V8ClassIndex::XMLHTTPREQUESTUPLOAD: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instance_template = + desc->InstanceTemplate(); + instance_template->SetInternalFieldCount( + V8Custom::kXMLHttpRequestInternalFieldCount); + break; + } case V8ClassIndex::XPATHEVALUATOR: desc->SetCallHandler(USE_CALLBACK(XPathEvaluatorConstructor)); break; @@ -1307,141 +1327,144 @@ v8::Persistent<v8::FunctionTemplate> V8Proxy::GetTemplate( return desc; } - -bool V8Proxy::ContextInitialized() { - return !m_context.IsEmpty(); +bool V8Proxy::ContextInitialized() +{ + return !m_context.IsEmpty(); } - -DOMWindow* V8Proxy::retrieveWindow() { - // TODO: This seems very fragile. How do we know that the global object - // from the current context is something sensible? Do we need to use the - // last entered here? Who calls this? - v8::Handle<v8::Object> global = v8::Context::GetCurrent()->Global(); - if (global.IsEmpty()) return 0; - v8::Handle<v8::Value> window = global->GetPrototype(); - return ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); +DOMWindow* V8Proxy::retrieveWindow() +{ + // TODO: This seems very fragile. How do we know that the global object + // from the current context is something sensible? Do we need to use the + // last entered here? Who calls this? + v8::Handle<v8::Object> global = v8::Context::GetCurrent()->Global(); + if (global.IsEmpty()) + return 0; + v8::Handle<v8::Value> window = global->GetPrototype(); + return ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); } - -Frame* V8Proxy::retrieveFrame(v8::Handle<v8::Context> context) { - v8::Handle<v8::Object> global = context->Global(); - v8::Handle<v8::Value> window_peer = global->GetPrototype(); - DOMWindow* window = - ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window_peer); - return window->frame(); +Frame* V8Proxy::retrieveFrame(v8::Handle<v8::Context> context) +{ + v8::Handle<v8::Object> global = context->Global(); + v8::Handle<v8::Value> window_peer = global->GetPrototype(); + DOMWindow* window = ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window_peer); + return window->frame(); } - -Frame* V8Proxy::retrieveActiveFrame() { - v8::Handle<v8::Context> context = v8::Context::GetEntered(); - if (context.IsEmpty()) - return 0; - return retrieveFrame(context); +Frame* V8Proxy::retrieveActiveFrame() +{ + v8::Handle<v8::Context> context = v8::Context::GetEntered(); + if (context.IsEmpty()) + return 0; + return retrieveFrame(context); } - -Frame* V8Proxy::retrieveFrame() { - DOMWindow* window = retrieveWindow(); - return window ? window->frame() : 0; +Frame* V8Proxy::retrieveFrame() +{ + DOMWindow* window = retrieveWindow(); + return window ? window->frame() : 0; } - -V8Proxy* V8Proxy::retrieve() { - DOMWindow* window = retrieveWindow(); - ASSERT(window); - return retrieve(window->frame()); +V8Proxy* V8Proxy::retrieve() +{ + DOMWindow* window = retrieveWindow(); + ASSERT(window); + return retrieve(window->frame()); } - -V8Proxy* V8Proxy::retrieve(Frame* frame) { - if (!frame) return 0; - V8Bridge* bridge = static_cast<V8Bridge*>(frame->scriptBridge()); - return bridge->isEnabled() ? bridge->proxy() : 0; +V8Proxy* V8Proxy::retrieve(Frame* frame) +{ + if (!frame) + return 0; + return frame->script()->isEnabled() ? frame->script()->proxy() : 0; } +void V8Proxy::disconnectFrame() +{ + // disconnect all event listeners + DisconnectEventListeners(); -void V8Proxy::disconnectFrame() { - // disconnect all event listeners - DisconnectEventListeners(); - - // clear all timeouts. - if (m_frame->domWindow()) - m_frame->domWindow()->clearAllTimeouts(); -} - -bool V8Proxy::isEnabled() { - Settings* settings = m_frame->settings(); - if (!settings) - return false; - - // In the common case, JavaScript is enabled and we're done. - if (settings->isJavaScriptEnabled()) - return true; - - // If JavaScript has been disabled, we need to look at the frame to tell - // whether this script came from the web or the embedder. Scripts from the - // embedder are safe to run, but scripts from the other sources are - // disallowed. - Document* document = m_frame->document(); - if (!document) - return false; - - SecurityOrigin* origin = document->securityOrigin(); - if (origin->protocol().isEmpty()) - return false; // Uninitialized document - - if (origin->protocol() == "http" || origin->protocol() == "https") - return false; // Web site - - if (origin->protocol() == - webkit_glue::StdStringToString(webkit_glue::GetUIResourceProtocol())) - return true; // Embedder's scripts are ok to run - - // If the scheme is ftp: or file:, an empty file name indicates a directory - // listing, which requires JavaScript to function properly. - const char* kDirProtocols[] = { "ftp", "file" }; - GURL url(document->url().utf8().data()); - for (size_t i = 0; i < arraysize(kDirProtocols); ++i) { - if (origin->protocol() == kDirProtocols[i]) { - ASSERT(url.SchemeIs(kDirProtocols[i])); - return url.ExtractFileName().empty(); + // clear all timeouts. + if (m_frame->domWindow()) + m_frame->domWindow()->clearAllTimeouts(); +} + +bool V8Proxy::isEnabled() +{ + Settings* settings = m_frame->settings(); + if (!settings) + return false; + + // In the common case, JavaScript is enabled and we're done. + if (settings->isJavaScriptEnabled()) + return true; + + // If JavaScript has been disabled, we need to look at the frame to tell + // whether this script came from the web or the embedder. Scripts from the + // embedder are safe to run, but scripts from the other sources are + // disallowed. + Document* document = m_frame->document(); + if (!document) + return false; + + SecurityOrigin* origin = document->securityOrigin(); + if (origin->protocol().isEmpty()) + return false; // Uninitialized document + + if (origin->protocol() == "http" || origin->protocol() == "https") + return false; // Web site + + if (origin->protocol() == webkit_glue::StdStringToString(webkit_glue::GetUIResourceProtocol())) + return true; // Embedder's scripts are ok to run + + // If the scheme is ftp: or file:, an empty file name indicates a directory + // listing, which requires JavaScript to function properly. + const char* kDirProtocols[] = { "ftp", "file" }; + GURL url = webkit_glue::KURLToGURL(document->url()); + for (size_t i = 0; i < arraysize(kDirProtocols); ++i) { + if (origin->protocol() == kDirProtocols[i]) { + ASSERT(url.SchemeIs(kDirProtocols[i])); + return url.ExtractFileName().empty(); + } } - } - return false; // Other protocols fall through to here + return false; // Other protocols fall through to here } +void V8Proxy::clearDocumentWrapper() +{ + v8::HandleScope handle_scope; + v8::Local<v8::Context> context = GetContext(); + if (context.IsEmpty()) + return; // not initialize yet -void V8Proxy::clearDocumentWrapper() { - v8::HandleScope handle_scope; - v8::Local<v8::Context> context = GetContext(); - if (context.IsEmpty()) return; // not initialize yet - - if (!m_document.IsEmpty()) { + if (!m_document.IsEmpty()) { #ifndef NDEBUG - UnregisterGlobalHandle(this, m_document); + UnregisterGlobalHandle(this, m_document); #endif - m_document.Dispose(); - m_document.Clear(); - } + m_document.Dispose(); + m_document.Clear(); + } } - // static -void V8Proxy::DomainChanged(Frame* frame) { - V8Proxy* proxy = retrieve(frame); - proxy->ClearSecurityToken(); +void V8Proxy::DomainChanged(Frame* frame) +{ + V8Proxy* proxy = retrieve(frame); + proxy->ClearSecurityToken(); } - -void V8Proxy::ClearSecurityToken() { - m_context->SetSecurityToken(m_global); +void V8Proxy::ClearSecurityToken() +{ + m_context->SetSecurityToken(m_global); } +void V8Proxy::clear() +{ + if (m_context.IsEmpty()) + return; -void V8Proxy::clear() { - if (!m_context.IsEmpty()) { ClearSecurityToken(); if (m_frame->domWindow()) @@ -1452,68 +1475,55 @@ void V8Proxy::clear() { // Corresponds to the context creation in initContextIfNeeded(). m_context.Dispose(); m_context.Clear(); - } } - // Check if two frames are from the same origin. // This function is equivalent to // KJS::Window::allowsAccessFrom(const JSGlobalObject*, // SecurityOrigin::Reason&, String& message) const. -static bool SameOrigin(Frame* source, Frame* target, - SecurityOrigin::Reason& reason, String& message) { - if (!source) { - reason = SecurityOrigin::GenericMismatch; - return false; - } +static bool SameOrigin(Frame* source, Frame* target, String& message) +{ + if (!source || !target) + return false; - if (!target) { - reason = SecurityOrigin::GenericMismatch; - return false; - } - - // Allow access if the frames the windows represent are the same. - if (source == target) - return true; + // Allow access if the frames the windows represent are the same. + if (source == target) + return true; - Document* target_document = target->document(); + Document* target_document = target->document(); - // JS may be attempting to access the "window" object, which should be valid, - // even if the document hasn't been constructed yet. If the document doesn't - // exist yet allow JS to access the window object. - if (!target_document) - return true; + // JS may be attempting to access the "window" object, which should be valid, + // even if the document hasn't been constructed yet. If the document doesn't + // exist yet allow JS to access the window object. + if (!target_document) + return true; - Document* act_document = source->document(); + Document* act_document = source->document(); - const SecurityOrigin* active_security_origin = act_document->securityOrigin(); - const SecurityOrigin* target_security_origin = - target_document->securityOrigin(); + const SecurityOrigin* active_security_origin = act_document->securityOrigin(); + const SecurityOrigin* target_security_origin = target_document->securityOrigin(); - String ui_resource_protocol = - webkit_glue::StdStringToString(webkit_glue::GetUIResourceProtocol()); - if (active_security_origin->protocol() == ui_resource_protocol) { - KURL inspector_url = - webkit_glue::GURLToKURL(webkit_glue::GetInspectorURL()); - ASSERT(inspector_url.protocol() == ui_resource_protocol); - ASSERT(inspector_url.protocol().endsWith("-resource")); + String ui_resource_protocol = webkit_glue::StdStringToString(webkit_glue::GetUIResourceProtocol()); + if (active_security_origin->protocol() == ui_resource_protocol) { + KURL inspector_url = webkit_glue::GURLToKURL(webkit_glue::GetInspectorURL()); + ASSERT(inspector_url.protocol() == ui_resource_protocol); + ASSERT(inspector_url.protocol().endsWith("-resource")); - // The Inspector can access anything. - if (active_security_origin->host() == inspector_url.host()) - return true; + // The Inspector can access anything. + if (active_security_origin->host() == inspector_url.host()) + return true; - // To mitigate XSS vulnerabilities on the browser itself, UI resources - // besides the Inspector can't access other documents. - return false; - } + // To mitigate XSS vulnerabilities on the browser itself, UI resources + // besides the Inspector can't access other documents. + return false; + } - if (active_security_origin->canAccess(target_security_origin, reason)) - return true; + if (active_security_origin->canAccess(target_security_origin)) + return true; - return false; + return false; } - // Check if the current execution context can access a target frame. // First it checks same domain policy using the security context // (where the script is invoked), if domain check failed due to @@ -1521,54 +1531,49 @@ static bool SameOrigin(Frame* source, Frame* target, // to check domain policy. // // This is equivalent to KJS::Window::allowsAccessFrom(ExecState*, String&). -bool V8Proxy::CanAccess(Frame* target) { - SecurityOrigin::Reason reason; - String message; - - // Check dynamic (security) context first. - Frame* source = - V8Proxy::retrieveFrame(v8::Context::GetCurrentSecurityContext()); - if (SameOrigin(source, target, reason, message)) { - return true; - } +bool V8Proxy::CanAccess(Frame* target) +{ + String message; + + // Check dynamic (security) context first. + Frame* source = V8Proxy::retrieveFrame(v8::Context::GetCurrentSecurityContext()); + if (SameOrigin(source, target, message)) + return true; - // Check lexical orgin if the reason is DomainSetInDOM mismatch. - if (reason == SecurityOrigin::DomainSetInDOMMismatch) { source = V8Proxy::retrieveFrame(v8::Context::GetCurrent()); - if (SameOrigin(source, target, reason, message)) { - return true; - } - } + if (SameOrigin(source, target, message)) + return true; - return false; + return false; } +bool V8Proxy::IsFromSameOrigin(Frame* target, bool report_error) +{ + // The subject is detached from a frame, deny accesses. + if (!target) + return false; -bool V8Proxy::IsFromSameOrigin(Frame* target, bool report_error) { - // The subject is detached from a frame, deny accesses. - if (!target) return false; - - if (!CanAccess(target)) { - if (report_error) ReportUnsafeAccessTo(target, REPORT_NOW); - return false; - } - return true; + if (!CanAccess(target)) { + if (report_error) + ReportUnsafeAccessTo(target, REPORT_NOW); + return false; + } + return true; } +bool V8Proxy::CheckNodeSecurity(Node* node) +{ + if (!node) + return false; -bool V8Proxy::CheckNodeSecurity(Node* node) { - if (!node) - return false; + Frame* target = node->document()->frame(); - Frame* target = node->document()->frame(); + if (!target) + return false; - if (!target) - return false; - - return IsFromSameOrigin(target, true); + return IsFromSameOrigin(target, true); } - // Create a new environment and setup the global object. // // The global object corresponds to a DOMWindow instance. However, to @@ -1582,9 +1587,11 @@ bool V8Proxy::CheckNodeSecurity(Node* node) { // from javascript. The javascript object that corresponds to a // DOMWindow instance is the shadow object. When mapping a DOMWindow // instance to a V8 object, we return the shadow object. -void V8Proxy::initContextIfNeeded() { +void V8Proxy::initContextIfNeeded() +{ // Bail out if the context has already been initialized. - if (!m_context.IsEmpty()) return; + if (!m_context.IsEmpty()) + return; // Install counters handler with V8. static bool v8_counters_initialized = false; @@ -1619,7 +1626,8 @@ void V8Proxy::initContextIfNeeded() { return; // Install a security handler with V8. - { v8::Local<v8::External> external = + { + v8::Local<v8::External> external = v8::External::New(reinterpret_cast<void*>(V8ClassIndex::DOMWINDOW)); if (external.IsEmpty()) return; @@ -1674,7 +1682,7 @@ void V8Proxy::initContextIfNeeded() { V8Proxy::retrieveFrame(context)->loader()->dispatchWindowObjectAvailable(); - if (JSBridge::RecordPlaybackMode()) { + if (ScriptController::RecordPlaybackMode()) { // Inject code which overrides a few common JS functions for implementing // randomness. In order to implement effective record & playback of // websites, it is important that the URLs not change. Many popular web @@ -1721,13 +1729,10 @@ v8::Handle<v8::Value> V8Proxy::GenerateSecurityToken( } -void V8Proxy::SetDOMException(int exception_code) { - if (exception_code <= 0) return; - - if (exception_code == XMLHttpRequestException::PERMISSION_DENIED) { - ThrowError(GENERAL_ERROR, "Permission denied"); - return; - } +void V8Proxy::SetDOMException(int exception_code) +{ + if (exception_code <= 0) + return; ExceptionCodeDescription description; getExceptionCodeDescription(exception_code, description); @@ -1736,30 +1741,30 @@ void V8Proxy::SetDOMException(int exception_code) { switch (description.type) { case DOMExceptionType: exception = ToV8Object(V8ClassIndex::DOMCOREEXCEPTION, - new DOMCoreException(description)); + DOMCoreException::create(description)); break; case RangeExceptionType: exception = ToV8Object(V8ClassIndex::RANGEEXCEPTION, - new RangeException(description)); + RangeException::create(description)); break; case EventExceptionType: exception = ToV8Object(V8ClassIndex::EVENTEXCEPTION, - new EventException(description)); + EventException::create(description)); break; case XMLHttpRequestExceptionType: exception = ToV8Object(V8ClassIndex::XMLHTTPREQUESTEXCEPTION, - new XMLHttpRequestException(description)); + XMLHttpRequestException::create(description)); break; #if ENABLE(SVG) case SVGExceptionType: exception = ToV8Object(V8ClassIndex::SVGEXCEPTION, - new SVGException(description)); + SVGException::create(description)); break; #endif #if ENABLE(XPATH) case XPathExceptionType: exception = ToV8Object(V8ClassIndex::XPATHEXCEPTION, - new XPathException(description)); + XPathException::create(description)); break; #endif } @@ -1768,8 +1773,8 @@ void V8Proxy::SetDOMException(int exception_code) { v8::ThrowException(exception); } - -v8::Handle<v8::Value> V8Proxy::ThrowError(ErrorType type, const char* message) { +v8::Handle<v8::Value> V8Proxy::ThrowError(ErrorType type, const char* message) +{ switch (type) { case RANGE_ERROR: return v8::ThrowException(v8::Exception::RangeError(v8String(message))); @@ -1788,24 +1793,23 @@ v8::Handle<v8::Value> V8Proxy::ThrowError(ErrorType type, const char* message) { } } +v8::Local<v8::Context> V8Proxy::GetContext(Frame* frame) +{ + V8Proxy* proxy = retrieve(frame); + if (!proxy) + return v8::Local<v8::Context>(); -v8::Local<v8::Context> V8Proxy::GetContext(Frame* frame) { - V8Proxy* proxy = retrieve(frame); - if (!proxy) - return v8::Local<v8::Context>(); - - proxy->initContextIfNeeded(); - return proxy->GetContext(); + proxy->initContextIfNeeded(); + return proxy->GetContext(); } - -v8::Local<v8::Context> V8Proxy::GetCurrentContext() { - return v8::Context::GetCurrent(); +v8::Local<v8::Context> V8Proxy::GetCurrentContext() +{ + return v8::Context::GetCurrent(); } - -v8::Handle<v8::Value> V8Proxy::ToV8Object(V8ClassIndex::V8WrapperType type, - void* imp) { +v8::Handle<v8::Value> V8Proxy::ToV8Object(V8ClassIndex::V8WrapperType type, void* imp) +{ ASSERT(type != V8ClassIndex::EVENTLISTENER); ASSERT(type != V8ClassIndex::EVENTTARGET); ASSERT(type != V8ClassIndex::EVENT); @@ -1830,13 +1834,9 @@ v8::Handle<v8::Value> V8Proxy::ToV8Object(V8ClassIndex::V8WrapperType type, return WindowToV8Object(static_cast<DOMWindow*>(imp)); #if ENABLE(SVG) SVGNONNODE_WRAPPER_TYPES(MAKE_CASE) - if (type == V8ClassIndex::SVGELEMENTINSTANCE) { - return SVGElementInstanceToV8Object( - static_cast<SVGElementInstance*>(imp)); - } else { - return SVGObjectWithContextToV8Object(static_cast<Peerable*>(imp), - type); - } + if (type == V8ClassIndex::SVGELEMENTINSTANCE) + return SVGElementInstanceToV8Object(static_cast<SVGElementInstance*>(imp)); + return SVGObjectWithContextToV8Object(static_cast<Peerable*>(imp), type); #endif default: break; @@ -1876,29 +1876,28 @@ v8::Handle<v8::Value> V8Proxy::ToV8Object(V8ClassIndex::V8WrapperType type, void V8Proxy::SetHiddenWindowReference(Frame* frame, const int internal_index, v8::Handle<v8::Object> jsobj) { - // Get DOMWindow - if (!frame) return; // Object might be detached from window - v8::Handle<v8::Context> context = GetContext(frame); - if (context.IsEmpty()) return; + // Get DOMWindow + if (!frame) return; // Object might be detached from window + v8::Handle<v8::Context> context = GetContext(frame); + if (context.IsEmpty()) return; - ASSERT(internal_index < V8Custom::kDOMWindowInternalFieldCount); + ASSERT(internal_index < V8Custom::kDOMWindowInternalFieldCount); - v8::Handle<v8::Object> global = context->Global(); - ASSERT(!global.IsEmpty()); - // Look for real DOM wrapper. - global = LookupDOMWrapper(V8ClassIndex::DOMWINDOW, global); - ASSERT(global->GetInternalField(internal_index)->IsUndefined()); - global->SetInternalField(internal_index, jsobj); + v8::Handle<v8::Object> global = context->Global(); + ASSERT(!global.IsEmpty()); + // Look for real DOM wrapper. + global = LookupDOMWrapper(V8ClassIndex::DOMWINDOW, global); + ASSERT(global->GetInternalField(internal_index)->IsUndefined()); + global->SetInternalField(internal_index, jsobj); } -V8ClassIndex::V8WrapperType V8Proxy::GetDOMWrapperType( - v8::Handle<v8::Object> object) { +V8ClassIndex::V8WrapperType V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object> object) +{ ASSERT(MaybeDOMWrapper(object)); - v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex); - return V8ClassIndex::FromInt(type->Int32Value()); + return V8ClassIndex::FromInt(type->Int32Value()); } @@ -1935,36 +1934,39 @@ void* V8Proxy::ToNativeObjectImpl(V8ClassIndex::V8WrapperType type, return DOMWrapperToNative<Peerable>(object); } - v8::Handle<v8::Object> V8Proxy::LookupDOMWrapper( - V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> value) { - if (value.IsEmpty()) return v8::Handle<v8::Object>(); - - v8::Handle<v8::FunctionTemplate> desc = V8Proxy::GetTemplate(type); - while (value->IsObject()) { - v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); - if (desc->HasInstance(object)) - return object; - - value = object->GetPrototype(); - } - return v8::Handle<v8::Object>(); + V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> value) +{ + if (value.IsEmpty()) + return v8::Handle<v8::Object>(); + + v8::Handle<v8::FunctionTemplate> desc = V8Proxy::GetTemplate(type); + while (value->IsObject()) { + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); + if (desc->HasInstance(object)) + return object; + + value = object->GetPrototype(); + } + return v8::Handle<v8::Object>(); } -NodeFilter* V8Proxy::ToNativeNodeFilter(v8::Handle<v8::Value> filter) { - // A NodeFilter is used when walking through a DOM tree or iterating tree - // nodes. - // TODO: we may want to cache NodeFilterCondition and NodeFilter - // object, but it is minor. - // NodeFilter is passed to NodeIterator that has a ref counted pointer - // to NodeFilter. NodeFilter has a ref counted pointer to NodeFilterCondition. - // In NodeFilterCondition, filter object is persisted in its constructor, - // and disposed in its destructor. No need to use peer field in this case. - if (!filter->IsFunction()) return 0; +PassRefPtr<NodeFilter> V8Proxy::ToNativeNodeFilter(v8::Handle<v8::Value> filter) +{ + // A NodeFilter is used when walking through a DOM tree or iterating tree + // nodes. + // TODO: we may want to cache NodeFilterCondition and NodeFilter + // object, but it is minor. + // NodeFilter is passed to NodeIterator that has a ref counted pointer + // to NodeFilter. NodeFilter has a ref counted pointer to NodeFilterCondition. + // In NodeFilterCondition, filter object is persisted in its constructor, + // and disposed in its destructor. No need to use peer field in this case. + if (!filter->IsFunction()) + return 0; - NodeFilterCondition* cond = new V8NodeFilterCondition(filter); - return new NodeFilter(cond); + NodeFilterCondition* cond = new V8NodeFilterCondition(filter); + return NodeFilter::create(cond); } @@ -1981,9 +1983,8 @@ v8::Local<v8::Object> V8Proxy::InstantiateV8Object( // Special case for HTMLInputElements that support selection. if (desc_type == V8ClassIndex::HTMLINPUTELEMENT) { HTMLInputElement* element = static_cast<HTMLInputElement*>(imp); - if (element->canHaveSelection()) { + if (element->canHaveSelection()) desc_type = V8ClassIndex::HTMLSELECTIONINPUTELEMENT; - } } v8::Persistent<v8::FunctionTemplate> desc = GetTemplate(desc_type); @@ -1996,15 +1997,14 @@ v8::Local<v8::Object> V8Proxy::InstantiateV8Object( return instance; } -v8::Handle<v8::Value> V8Proxy::CheckNewLegal(const v8::Arguments& args) { - if (!AllowAllocation::m_current) { - return ThrowError(TYPE_ERROR, "Illegal constructor"); - } else { +v8::Handle<v8::Value> V8Proxy::CheckNewLegal(const v8::Arguments& args) +{ + if (!AllowAllocation::m_current) + return ThrowError(TYPE_ERROR, "Illegal constructor"); + return args.This(); - } } - void V8Proxy::SetDOMWrapper(v8::Handle<v8::Object> obj, int type, void* cptr) { ASSERT(obj->InternalFieldCount() >= 2); obj->SetInternalField(V8Custom::kDOMWrapperObjectIndex, WrapCPointer(cptr)); @@ -2144,7 +2144,8 @@ FOR_EACH_TAG(ADD_TO_HASH_MAP) } V8ClassIndex::V8WrapperType t = map.get(element->localName().impl()); - if (t == 0) return V8ClassIndex::HTMLELEMENT; + if (t == 0) + return V8ClassIndex::HTMLELEMENT; return t; } #undef FOR_EACH_TAG @@ -2274,13 +2275,14 @@ FOR_EACH_TAG(ADD_TO_HASH_MAP) #endif // ENABLE(SVG) -v8::Handle<v8::Value> V8Proxy::EventToV8Object(Event* event) { - if (!event) return v8::Null(); +v8::Handle<v8::Value> V8Proxy::EventToV8Object(Event* event) +{ + if (!event) + return v8::Null(); v8::Handle<v8::Object> peer = dom_object_map().get(event); - if (!peer.IsEmpty()) { + if (!peer.IsEmpty()) return peer; - } V8ClassIndex::V8WrapperType type = V8ClassIndex::EVENT; @@ -2324,24 +2326,22 @@ v8::Handle<v8::Value> V8Proxy::NodeToV8Object(Node* node) { if (!node) return v8::Null(); v8::Handle<v8::Object> peer = dom_node_map().get(node); - if (!peer.IsEmpty()) { + if (!peer.IsEmpty()) return peer; - } bool is_document = false; // document type node has special handling V8ClassIndex::V8WrapperType type; switch (node->nodeType()) { case Node::ELEMENT_NODE: - if (node->isHTMLElement()) { + if (node->isHTMLElement()) type = GetHTMLElementType(static_cast<HTMLElement*>(node)); #if ENABLE(SVG) - } else if (node->isSVGElement()) { + else if (node->isSVGElement()) type = GetSVGElementType(static_cast<SVGElement*>(node)); #endif - } else { + else type = V8ClassIndex::ELEMENT; - } break; case Node::ATTRIBUTE_NODE: type = V8ClassIndex::ATTR; @@ -2364,15 +2364,14 @@ v8::Handle<v8::Value> V8Proxy::NodeToV8Object(Node* node) { case Node::DOCUMENT_NODE: { is_document = true; Document* doc = static_cast<Document*>(node); - if (doc->isHTMLDocument()) { + if (doc->isHTMLDocument()) type = V8ClassIndex::HTMLDOCUMENT; #if ENABLE(SVG) - } else if (doc->isSVGDocument()) { + else if (doc->isSVGDocument()) type = V8ClassIndex::SVGDOCUMENT; #endif - } else { + else type = V8ClassIndex::DOCUMENT; - } break; } case Node::DOCUMENT_TYPE_NODE: @@ -2408,9 +2407,8 @@ v8::Handle<v8::Value> V8Proxy::NodeToV8Object(Node* node) { if (is_document) { Document* doc = static_cast<Document*>(node); V8Proxy* proxy = V8Proxy::retrieve(doc->frame()); - if (proxy) { + if (proxy) proxy->UpdateDocumentHandle(result); - } if (type == V8ClassIndex::HTMLDOCUMENT) { // Create marker object and insert it in two internal fields. @@ -2447,16 +2445,20 @@ void V8Proxy::UpdateDocumentHandle(v8::Local<v8::Object> handle) { // A JS object of type EventTarget can only be two possible types: // 1) EventTargetNode; 2) XMLHttpRequest; -v8::Handle<v8::Value> V8Proxy::EventTargetToV8Object(EventTarget* target) { - if (!target) return v8::Null(); +v8::Handle<v8::Value> V8Proxy::EventTargetToV8Object(EventTarget* target) +{ + if (!target) + return v8::Null(); #if ENABLE(SVG) SVGElementInstance* instance = target->toSVGElementInstance(); - if (instance) return ToV8Object(V8ClassIndex::SVGELEMENTINSTANCE, instance); + if (instance) + return ToV8Object(V8ClassIndex::SVGELEMENTINSTANCE, instance); #endif Node* node = target->toNode(); - if (node) return NodeToV8Object(node); + if (node) + return NodeToV8Object(node); // XMLHttpRequest is created within its JS counterpart. XMLHttpRequest* xhr = target->toXMLHttpRequest(); @@ -2501,12 +2503,12 @@ v8::Handle<v8::Value> V8Proxy::StyleSheetToV8Object(StyleSheet* sheet) { if (!sheet) return v8::Null(); v8::Handle<v8::Object> peer = dom_object_map().get(sheet); - if (!peer.IsEmpty()) { + if (!peer.IsEmpty()) return peer; - } V8ClassIndex::V8WrapperType type = V8ClassIndex::STYLESHEET; - if (sheet->isCSSStyleSheet()) type = V8ClassIndex::CSSSTYLESHEET; + if (sheet->isCSSStyleSheet()) + type = V8ClassIndex::CSSSTYLESHEET; v8::Handle<v8::Object> result = InstantiateV8Object(type, V8ClassIndex::STYLESHEET, sheet); @@ -2519,7 +2521,7 @@ v8::Handle<v8::Value> V8Proxy::StyleSheetToV8Object(StyleSheet* sheet) { Node* owner_node = sheet->ownerNode(); if (owner_node) { v8::Handle<v8::Object> owner = - v8::Handle<v8::Object>::Cast(NodeToV8Object(owner_node)); + v8::Handle<v8::Object>::Cast(NodeToV8Object(owner_node)); result->SetInternalField(V8Custom::kStyleSheetOwnerNodeIndex, owner); } @@ -2531,9 +2533,8 @@ v8::Handle<v8::Value> V8Proxy::CSSValueToV8Object(CSSValue* value) { if (!value) return v8::Null(); v8::Handle<v8::Object> peer = dom_object_map().get(value); - if (!peer.IsEmpty()) { + if (!peer.IsEmpty()) return peer; - } V8ClassIndex::V8WrapperType type; @@ -2552,95 +2553,93 @@ v8::Handle<v8::Value> V8Proxy::CSSValueToV8Object(CSSValue* value) { v8::Handle<v8::Object> result = InstantiateV8Object(type, V8ClassIndex::CSSVALUE, value); - if (!result.IsEmpty()) { + if (!result.IsEmpty()) // Only update the DOM object map if the result is non-empty. dom_object_map().set(value, v8::Persistent<v8::Object>::New(result)); - } return result; } v8::Handle<v8::Value> V8Proxy::CSSRuleToV8Object(CSSRule* rule) { - if (!rule) return v8::Null(); - - v8::Handle<v8::Object> peer = dom_object_map().get(rule); - if (!peer.IsEmpty()) { - return peer; - } - - V8ClassIndex::V8WrapperType type; - - switch (rule->type()) { - case CSSRule::STYLE_RULE: - type = V8ClassIndex::CSSSTYLERULE; - break; - case CSSRule::CHARSET_RULE: - type = V8ClassIndex::CSSCHARSETRULE; - break; - case CSSRule::IMPORT_RULE: - type = V8ClassIndex::CSSIMPORTRULE; - break; - case CSSRule::MEDIA_RULE: - type = V8ClassIndex::CSSMEDIARULE; - break; - case CSSRule::FONT_FACE_RULE: - type = V8ClassIndex::CSSFONTFACERULE; - break; - case CSSRule::PAGE_RULE: - type = V8ClassIndex::CSSPAGERULE; - break; - default: // CSSRule::UNKNOWN_RULE - type = V8ClassIndex::CSSRULE; - } + if (!rule) return v8::Null(); + + v8::Handle<v8::Object> peer = dom_object_map().get(rule); + if (!peer.IsEmpty()) + return peer; + + V8ClassIndex::V8WrapperType type; + + switch (rule->type()) { + case CSSRule::STYLE_RULE: + type = V8ClassIndex::CSSSTYLERULE; + break; + case CSSRule::CHARSET_RULE: + type = V8ClassIndex::CSSCHARSETRULE; + break; + case CSSRule::IMPORT_RULE: + type = V8ClassIndex::CSSIMPORTRULE; + break; + case CSSRule::MEDIA_RULE: + type = V8ClassIndex::CSSMEDIARULE; + break; + case CSSRule::FONT_FACE_RULE: + type = V8ClassIndex::CSSFONTFACERULE; + break; + case CSSRule::PAGE_RULE: + type = V8ClassIndex::CSSPAGERULE; + break; + default: // CSSRule::UNKNOWN_RULE + type = V8ClassIndex::CSSRULE; + } - // Set the peer object for future access. - v8::Handle<v8::Object> result = - InstantiateV8Object(type, V8ClassIndex::CSSRULE, rule); - if (!result.IsEmpty()) { - // Only update the DOM object map if the result is non-empty. - dom_object_map().set(rule, v8::Persistent<v8::Object>::New(result)); - } - return result; + // Set the peer object for future access. + v8::Handle<v8::Object> result = + InstantiateV8Object(type, V8ClassIndex::CSSRULE, rule); + if (!result.IsEmpty()) + // Only update the DOM object map if the result is non-empty. + dom_object_map().set(rule, v8::Persistent<v8::Object>::New(result)); + return result; } v8::Handle<v8::Value> V8Proxy::WindowToV8Object(DOMWindow* window) { - if (!window) return v8::Null(); + if (!window) return v8::Null(); + // Initializes environment of a frame, and return the global object + // of the frame. + Frame* frame = window->frame(); + if (!frame) + return v8::Handle<v8::Object>(); - // Initializes environment of a frame, and return the global object - // of the frame. - Frame* frame = window->frame(); - if (!frame) return v8::Handle<v8::Object>(); + v8::Handle<v8::Context> context = GetContext(frame); + if (context.IsEmpty()) + return v8::Handle<v8::Object>(); - v8::Handle<v8::Context> context = GetContext(frame); - if (context.IsEmpty()) return v8::Handle<v8::Object>(); - - v8::Handle<v8::Object> global = context->Global(); - ASSERT(!global.IsEmpty()); - return global; + v8::Handle<v8::Object> global = context->Global(); + ASSERT(!global.IsEmpty()); + return global; } - void V8Proxy::BindJSObjectToWindow(Frame* frame, const char* name, int type, v8::Handle<v8::FunctionTemplate> desc, - void* imp) { - // Get environment. - v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); - if (context.IsEmpty()) return; // JS not enabled. + void* imp) +{ + // Get environment. + v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); + if (context.IsEmpty()) + return; // JS not enabled. - v8::Context::Scope scope(context); - v8::Handle<v8::Object> instance = desc->GetFunction(); - SetDOMWrapper(instance, type, imp); + v8::Context::Scope scope(context); + v8::Handle<v8::Object> instance = desc->GetFunction(); + SetDOMWrapper(instance, type, imp); - v8::Handle<v8::Object> global = context->Global(); - global->Set(v8::String::New(name), instance); + v8::Handle<v8::Object> global = context->Global(); + global->Set(v8::String::New(name), instance); } - -void V8Proxy::ProcessConsoleMessages() { - ConsoleMessageManager::ProcessDelayedMessages(); +void V8Proxy::ProcessConsoleMessages() +{ + ConsoleMessageManager::ProcessDelayedMessages(); } - } // namespace WebCore diff --git a/webkit/port/bindings/v8/v8_proxy.h b/webkit/port/bindings/v8/v8_proxy.h index 94f0450..784d763 100644 --- a/webkit/port/bindings/v8/v8_proxy.h +++ b/webkit/port/bindings/v8/v8_proxy.h @@ -13,6 +13,7 @@ #include "NodeFilter.h" #include "PlatformString.h" // for WebCore::String #include <wtf/HashMap.h> // for HashMap +#include <wtf/PassRefPtr.h> // so generated bindings don't have to #include <wtf/Assertions.h> #include <iterator> @@ -331,6 +332,11 @@ class V8Proxy { return static_cast<C*>(ExtractCPointer<Node>(wrapper)); } + template<typename T> + static v8::Handle<v8::Value> ToV8Object(V8ClassIndex::V8WrapperType type, PassRefPtr<T> imp) + { + return ToV8Object(type, imp.get()); + } static v8::Handle<v8::Value> ToV8Object(V8ClassIndex::V8WrapperType type, void* imp); // Fast-path for Node objects. @@ -378,7 +384,7 @@ class V8Proxy { DOMImplementation* impl); // Wrap JS node filter in C++ - static NodeFilter* ToNativeNodeFilter(v8::Handle<v8::Value> filter); + static PassRefPtr<NodeFilter> ToNativeNodeFilter(v8::Handle<v8::Value> filter); static v8::Persistent<v8::FunctionTemplate> GetTemplate( V8ClassIndex::V8WrapperType type); @@ -518,10 +524,14 @@ v8::Handle<v8::Value> V8Proxy::ConstructDOMObject(const v8::Arguments& args) { "DOM object constructor cannot be called as a function."); return v8::Undefined(); } - T* obj = new T(); - V8Proxy::SetDOMWrapper(args.Holder(), tag, obj); + + + // Note: it's OK to let this RefPtr go out of scope because we also call + // SetDOMWrapper(), which effectively holds a reference to obj. + RefPtr<T> obj = T::create(); + V8Proxy::SetDOMWrapper(args.Holder(), tag, obj.get()); V8Proxy::SetJSWrapperForDOMObject( - obj, v8::Persistent<v8::Object>::New(args.Holder())); + obj.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); } diff --git a/webkit/port/bridge/ExceptionContextV8.cpp b/webkit/port/bridge/ExceptionContextV8.cpp new file mode 100644 index 0000000..4d8efdc --- /dev/null +++ b/webkit/port/bridge/ExceptionContextV8.cpp @@ -0,0 +1,108 @@ +// Copyright (c) 2008, 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 "ExceptionContext.h" + +#include "Node.h" + +namespace WebCore { + +ExceptionContext::ExceptionContext() + : m_exceptionCatcher(0) + , m_exception() +{ +} + +ExceptionContext::~ExceptionContext() +{ +} + +void ExceptionContext::setExceptionCatcher(ExceptionCatcher* exceptionCatcher) +{ + if (m_exceptionCatcher && exceptionCatcher) + m_exceptionCatcher->detachContext(); + + m_exceptionCatcher = exceptionCatcher; +} + +bool ExceptionContext::hadException() +{ + if (m_exceptionCatcher) + m_exceptionCatcher->updateContext(); + + return !m_exception.IsEmpty(); +} + +ExceptionContext* ExceptionContext::createFromNode(Node*) +{ + // Unlike JSC, which stores exceptions in ExecState that is accessible from + // ScriptController that is retrievable from Node*, V8 uses static chain of + // handlers (encapsulated as v8::TryCatch and here as ExceptionCatcher) + // to track exceptions, so it has no need for Node*. + return new ExceptionContext(); +} + +JSException ExceptionContext::NoException() +{ + return v8::Local<v8::Value>(); +} + +ExceptionCatcher::ExceptionCatcher(ExceptionContext* exceptionContext) + : m_catcher() + , m_context(exceptionContext) +{ + exceptionContext->setExceptionCatcher(this); +} + +void ExceptionCatcher::detachContext() +{ + m_context = 0; +} + +void ExceptionCatcher::updateContext() +{ + ASSERT(m_context); + + if (m_catcher.HasCaught()) + m_context->setException(m_catcher.Exception()); + else + m_context->setException(ExceptionContext::NoException()); +} + +ExceptionCatcher::~ExceptionCatcher() +{ + if (!m_context) + return; + + updateContext(); + m_context->setExceptionCatcher(0); +} + +} // namespace WebCore diff --git a/webkit/port/bridge/FrameWin.cpp b/webkit/port/bridge/FrameWin.cpp index 60892ec..5c29891 100644 --- a/webkit/port/bridge/FrameWin.cpp +++ b/webkit/port/bridge/FrameWin.cpp @@ -27,124 +27,30 @@ #pragma warning(push, 0) #include "Document.h" -#include "EditorClient.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "FrameLoadRequest.h" #include "FramePrivate.h" #include "FrameView.h" -#include "Frame.h" #include "FrameWin.h" -#include "NotImplemented.h" +#include "RenderFrame.h" #include "RenderView.h" +#include "ScriptController.h" -#if USE(JAVASCRIPTCORE_BINDINGS) -#include "JSLock.h" +#if USE(JSC) #include "kjs_proxy.h" -#include "kjs_window.h" #include "NP_jsobject.h" -#include "NotImplemented.h" #include "bindings/npruntime.h" +#include "runtime_root.h" +#include "runtime.h" #endif -#if USE(V8_BINDING) +#if USE(V8) #include "v8_npobject.h" #include "npruntime_priv.h" #endif -#include "Page.h" -#include "RenderFrame.h" -#include "ResourceHandle.h" -#if USE(JAVASCRIPTCORE_BINDINGS) -#include "runtime_root.h" -#include "runtime.h" -#endif -#include "Settings.h" -#include "TextResourceDecoder.h" #include "webkit/glue/webplugin_impl.h" #pragma warning(pop) -// So we can twiddle event member vars -#define private public -#include "PlatformKeyboardEvent.h" -#undef private - -#include "webkit/glue/cache_manager.h" - namespace WebCore { -void Frame::clearPlatformScriptObjects() -{ -} - -#if USE(JAVASCRIPTCORE_BINDINGS) || USE(V8_BINDING) -JSInstance Frame::createScriptInstanceForWidget(Widget* widget) -{ - ASSERT(widget != 0); - - if (widget->isFrameView()) - return JSInstanceHolder::EmptyInstance(); - - // Note: We have to trust that the widget passed to us here - // is a WebPluginImpl. There isn't a way to dynamically verify - // it, since the derived class (Widget) has no identifier. - WebPluginContainer* container = static_cast<WebPluginContainer*>(widget); - if (!container) - return JSInstanceHolder::EmptyInstance(); - - NPObject *npObject = container->GetPluginScriptableObject(); - if (!npObject) - return JSInstanceHolder::EmptyInstance(); - -#if USE(JAVASCRIPTCORE_BINDINGS) - // Register 'widget' with the frame so that we can teardown - // subobjects when the container goes away. - RefPtr<KJS::Bindings::RootObject> root = - createRootObject(widget, scriptProxy()->globalObject()); - KJS::Bindings::Instance *instance = - KJS::Bindings::Instance::createBindingForLanguageInstance( - KJS::Bindings::Instance::CLanguage, npObject, - root.release()); - // GetPluginScriptableObject returns a retained NPObject. - // The caller is expected to release it. - NPN_ReleaseObject(npObject); - return instance; -#else - // Frame Memory Management for NPObjects - // ------------------------------------- - // NPObjects are treated differently than other objects wrapped by JS. - // NPObjects are not Peerable, and cannot be made peerable, since NPObjects - // can be created either by the browser (e.g. the main window object) or by - // the plugin (the main plugin object for a HTMLEmbedElement). Further, - // unlike most DOM Objects, the frame is especially careful to ensure - // NPObjects terminate at frame teardown because if a plugin leaks a - // reference, it could leak its objects (or the browser's objects). - // - // The Frame maintains a list of plugin objects (m_pluginObjects) - // which it can use to quickly find the wrapped embed object. - // - // Inside the NPRuntime, we've added a few methods for registering - // wrapped NPObjects. The purpose of the registration is because - // javascript garbage collection is non-deterministic, yet we need to - // be able to tear down the plugin objects immediately. When an object - // is registered, javascript can use it. When the object is destroyed, - // or when the object's "owning" object is destroyed, the object will - // be un-registered, and the javascript engine must not use it. - // - // Inside the javascript engine, the engine can keep a reference to the - // NPObject as part of its wrapper. However, before accessing the object - // it must consult the NPN_Registry. - - v8::Local<v8::Object> wrapper = CreateV8ObjectForNPObject(npObject, NULL); - - // Track the plugin object. We've been given a reference to the object. - d->m_pluginObjects.set(widget, npObject); - - JSInstance instance = wrapper; - return instance; -#endif -} -#endif // JAVASCRIPTCORE_BINDINGS - void computePageRectsForFrame(WebCore::Frame* frame, const WebCore::IntRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, Vector<IntRect>& pages, int& outPageHeight) { ASSERT(frame); @@ -199,14 +105,10 @@ void computePageRectsForFrame(WebCore::Frame* frame, const WebCore::IntRect& pri DragImageRef Frame::dragImageForSelection() { - if (selectionController()->isRange()) + if (selection()->isRange()) return 0; // TODO(pkasting): http://b/119669 Implement me! return 0; } -void Frame::dashboardRegionsChanged() -{ -} - } // namespace WebCore diff --git a/webkit/port/bridge/JSBridge.h b/webkit/port/bridge/JSBridge.h deleted file mode 100644 index d69521c..0000000 --- a/webkit/port/bridge/JSBridge.h +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// An interface to abstract implementation differences -// for various Javascript engines. - -#ifndef JSBridge_h -#define JSBridge_h - -#include "third_party/npapi/bindings/npruntime.h" -#if USE(JAVASCRIPTCORE_BINDINGS) -#include <kjs/ustring.h> -#endif - -#if USE(V8_BINDING) -#include "v8.h" -//namespace v8 { class Object; } -#endif - -// JavaScript implementations which expose NPObject will need to implement -// these methods. -typedef void (*NPN_ReleaseVariantValueProcPtr) (NPVariant *variant); - -typedef NPIdentifier(*NPN_GetStringIdentifierProcPtr) (const NPUTF8 *name); -typedef void (*NPN_GetStringIdentifiersProcPtr) (const NPUTF8 **names, - int32_t nameCount, - NPIdentifier *identifiers); -typedef NPIdentifier(*NPN_GetIntIdentifierProcPtr) (int32_t intid); -typedef int32_t (*NPN_IntFromIdentifierProcPtr) (NPIdentifier identifier); -typedef bool (*NPN_IdentifierIsStringProcPtr) (NPIdentifier identifier); -typedef NPUTF8 * (*NPN_UTF8FromIdentifierProcPtr) (NPIdentifier identifier); - -typedef NPObject* (*NPN_CreateObjectProcPtr) (NPP, - NPClass *aClass); -typedef NPObject* (*NPN_RetainObjectProcPtr) (NPObject *obj); -typedef void (*NPN_ReleaseObjectProcPtr) (NPObject *obj); -typedef bool (*NPN_InvokeProcPtr) (NPP npp, - NPObject *obj, - NPIdentifier methodName, - const NPVariant *args, - unsigned argCount, - NPVariant *result); -typedef bool (*NPN_InvokeDefaultProcPtr) (NPP npp, - NPObject *obj, - const NPVariant *args, - unsigned argCount, - NPVariant *result); -typedef bool (*NPN_EvaluateProcPtr) (NPP npp, - NPObject *obj, - NPString *script, - NPVariant *result); -typedef bool (*NPN_GetPropertyProcPtr) (NPP npp, - NPObject *obj, - NPIdentifier propertyName, - NPVariant *result); -typedef bool (*NPN_SetPropertyProcPtr) (NPP npp, - NPObject *obj, - NPIdentifier propertyName, - const NPVariant *value); -typedef bool (*NPN_HasPropertyProcPtr) (NPP, - NPObject *npobj, - NPIdentifier propertyName); -typedef bool (*NPN_HasMethodProcPtr) (NPP npp, - NPObject *npobj, - NPIdentifier methodName); -typedef bool (*NPN_RemovePropertyProcPtr) (NPP npp, - NPObject *obj, - NPIdentifier propertyName); -typedef void (*NPN_SetExceptionProcPtr) (NPObject *obj, - const NPUTF8 *message); - -typedef struct _NPRuntimeFunctions { - NPN_GetStringIdentifierProcPtr getStringIdentifier; - NPN_GetStringIdentifiersProcPtr getStringIdentifiers; - NPN_GetIntIdentifierProcPtr getIntIdentifier; - NPN_IdentifierIsStringProcPtr identifierIsString; - NPN_UTF8FromIdentifierProcPtr utf8FromIdentifier; - NPN_IntFromIdentifierProcPtr intFromIdentifier; - NPN_CreateObjectProcPtr createObject; - NPN_RetainObjectProcPtr retainObject; - NPN_ReleaseObjectProcPtr releaseObject; - NPN_InvokeProcPtr invoke; - NPN_InvokeDefaultProcPtr invokeDefault; - NPN_EvaluateProcPtr evaluate; - NPN_GetPropertyProcPtr getProperty; - NPN_SetPropertyProcPtr setProperty; - NPN_RemovePropertyProcPtr removeProperty; - NPN_HasPropertyProcPtr hasProperty; - NPN_HasMethodProcPtr hasMethod; - NPN_ReleaseVariantValueProcPtr releaseVariantValue; - NPN_SetExceptionProcPtr setException; -} NPRuntimeFunctions; - -#if USE(JAVASCRIPTCORE_BINDINGS) -namespace KJS { namespace Bindings { class RootObject; class Instance; } -} -#endif - - -namespace WebCore { -class Document; -class Frame; -class String; -class Node; -class EventListener; -class Event; -class HTMLPlugInElement; -class PausedTimeouts; - -// JSString is the string class used for XMLHttpRequest's -// m_responseText field. -#if USE(JAVASCRIPTCORE_BINDINGS) -typedef KJS::UString JSString; -typedef KJS::Bindings::Instance* JSInstance; -typedef KJS::Bindings::Instance* JSPersistentInstance; -typedef KJS::JSValue* JSException; -typedef KJS::JSValue* JSResult; -#endif - -#if USE(V8_BINDING) -typedef String JSString; -typedef v8::Local<v8::Object> JSInstance; -typedef v8::Persistent<v8::Object> JSPersistentInstance; -typedef v8::Local<v8::Value> JSException; -typedef v8::Persistent<v8::Value> JSResult; -#endif - -class JSBridge { - public: - virtual ~JSBridge() { } - - // Disconnects the proxy from its owner frame. - virtual void disconnectFrame() = 0; - - virtual bool wasRunByUserGesture() = 0; - - - // Evaluate a script file in the environment of this proxy. Used for - // evaluating the code in script tags and for evaluating the code from - // javascript URLs. - // If succeeded, 'succ' is set to true and result is returned - // as a string. - virtual String evaluate(const String& filename, int baseLine, - const String& code, Node*, bool* succ) = 0; - - // Second API function for evaluating a JS code. - // It returns a JSResult which must be disposed by calling - // disposeJSResult. If the result is not disposed, it can cause - // serious memory leak. The caller determines whether the evaluation - // is successful by checking the value of JSResult. - virtual JSResult evaluate(const String& filename, int baseLine, - const String& code, Node*) = 0; - virtual void disposeJSResult(JSResult result) = 0; - - virtual EventListener* createHTMLEventHandler(const String& functionName, - const String& code, Node* node) = 0; - -#if ENABLE(SVG) - virtual EventListener* createSVGEventHandler(const String& functionName, - const String& code, Node* node) = 0; -#endif - - virtual void setEventHandlerLineno(int lineno) = 0; - virtual void finishedWithEvent(Event*) = 0; - - virtual void clear() = 0; - - // Get the Root object - // virtual JSRootObject* getRootObject() = 0; - // Creates a property of the global object of a frame. - virtual void BindToWindowObject(Frame* frame, const String& key, NPObject* object) = 0; - - // Provides access to the NPRuntime functions. - virtual NPRuntimeFunctions *functions() = 0; - - // Create an NPObject for the window object. - virtual NPObject *CreateScriptObject(Frame*) = 0; - - // Create an NPObject for an HTMLPluginElement - virtual NPObject *CreateScriptObject(Frame*, HTMLPlugInElement*) = 0; - - // Create a "NoScript" object (used when JS is unavailable or disabled) - virtual NPObject *CreateNoScriptObject() = 0; - - // Check if the javascript engine has been initialized. - virtual bool haveInterpreter() const = 0; - - virtual bool isEnabled() const = 0; - - virtual void clearDocumentWrapper() = 0; - - virtual void CollectGarbage() = 0; - - // Create a NPObject wrapper for a JSObject - //virtual NPObject *WrapScriptObject(NPP pluginId, JSObject* objectToWrap, - // JSRootObject* originRootObject, - // JSRootObject* rootObject); - - // --- Static methods assume we are running VM in single thread, --- - // --- and there is only one VM instance. --- - - // Returns the frame of the calling code is in. - // Not necessary the frame of this proxy. - // For example, JS code in frame A calls windowB.open(...). - // Window::open method has the frame pointer of B, but - // the execution context is in frame A, so it needs - // frame A's loader to complete URL. - static Frame* retrieveActiveFrame(); - - // Check whether it is safe to access a frame in another domain. - static bool isSafeScript(Frame* target); - - // Tell the proxy that document.domain is set. - static void setDomain(Frame* target, const String& new_domain); - - // Pass flags to the JS engine - static void setFlags(const char* str, int length); - - // Protect and unprotect the JS wrapper from garbage collected. - static void gcProtectJSWrapper(void* dom_object); - static void gcUnprotectJSWrapper(void* dom_Object); - - // Returns a non-exception code object. - static JSException NoException(); - // Returns true if the parameter is a JS exception object. - static bool IsException(JSException exception); - - // Get/Set RecordPlaybackMode flag. - // This is a special mode where JS helps the browser implement - // playback/record mode. Generally, in this mode, some functions - // of client-side randomness are removed. For example, in - // this mode Math.random() and Date.getTime() may not return - // values which vary. - static bool RecordPlaybackMode() { return m_recordPlaybackMode; } - static void setRecordPlaybackMode(bool value) { - m_recordPlaybackMode = value; - } - - // Pause timeouts for a frame. - static PausedTimeouts* pauseTimeouts(Frame* frame); - // Resume timeouts for a frame. - static void resumeTimeouts(Frame* frame, PausedTimeouts* timeouts); - - private: - static bool m_recordPlaybackMode; -}; - -// JSInstance is an abstraction for a wrapped C class. KJS and V8 -// have very different implementations. -class JSInstanceHolder { - public: - JSInstanceHolder(); - JSInstanceHolder(JSInstance instance); - ~JSInstanceHolder(); - // Returns true if the holder is empty. - bool IsEmpty(); - // Get the contained JSInstance. - JSInstance Get(); - // Clear the contained JSInstance. - void Clear(); - JSInstanceHolder& operator=(JSInstance instance); - static JSInstance EmptyInstance(); - private: - JSPersistentInstance m_instance; -}; - -} // namespace WebCore - -#endif // JSBridge_h - diff --git a/webkit/port/bridge/KJSBridge.h b/webkit/port/bridge/KJSBridge.h deleted file mode 100644 index 0704fcd..0000000 --- a/webkit/port/bridge/KJSBridge.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file contains KJS specific bits required to build WebKit. - -#ifndef KJSBridge_h -#define KJSBridge_h - -#include "JSBridge.h" -#include "kjs_binding.h" -#include "kjs_proxy.h" - -namespace WebCore { -class KJSBridge : public JSBridge { - public: - KJSBridge(Frame* frame) : m_proxy(new KJSProxy(frame)) { } - virtual ~KJSBridge() { delete m_proxy; } - - virtual void disconnectFrame(); - virtual bool wasRunByUserGesture(); - // Evaluate a script file in the environment of this proxy. - virtual String evaluate(const String& filename, int baseLine, - const String& code, Node*, bool* succ); - - virtual JSResult evaluate(const String& filename, int baseLine, - const String& code, Node*); - virtual void disposeJSResult(JSResult) { } - - virtual EventListener* createHTMLEventHandler(const String& functionName, - const String& code, Node* node); -#if ENABLE(SVG) - virtual EventListener* createSVGEventHandler(const String& functionName, - const String& code, Node* node); -#endif - - virtual void setEventHandlerLineno(int lineno); - - virtual void finishedWithEvent(Event* evt); - - virtual void clear(); - - // virtual JSRootObject *getRootObject(); - - // Creates a property of the global object of a frame. - virtual void BindToWindowObject(Frame* frame, const String& key, NPObject* object); - virtual NPRuntimeFunctions *functions(); - virtual NPObject *CreateScriptObject(Frame*); - virtual NPObject *CreateScriptObject(Frame*, HTMLPlugInElement*); - virtual NPObject *CreateNoScriptObject(); - - virtual bool haveInterpreter() const { return m_proxy->haveGlobalObject(); } - virtual bool isEnabled() const { return m_proxy->isEnabled(); } - - virtual void clearDocumentWrapper() { m_proxy->clearDocumentWrapper(); } - - virtual void CollectGarbage() { } - - KJSProxy* proxy() { return m_proxy; } - - private: - // Internal call to create an NPObject for a JSValue - NPObject *CreateScriptObject(Frame*, KJS::JSValue*); - - private: - KJSProxy* m_proxy; -}; - -} // namespace WebCore - -#endif - diff --git a/webkit/port/bridge/KJSBridge.cpp b/webkit/port/bridge/ScriptControllerKJS.cpp index ecbb19c..4786b6c 100644 --- a/webkit/port/bridge/KJSBridge.cpp +++ b/webkit/port/bridge/ScriptControllerKJS.cpp @@ -130,9 +130,7 @@ bool KJSBridge::wasRunByUserGesture() { } -// Evaluate a script file in the environment of this proxy. Used for -// evaluating the code in script tags and for evaluating the code from -// javascript URLs. +// Evaluate a script file in the environment of this proxy. String KJSBridge::evaluate(const String& filename, int baseLine, const String& code, Node* node, bool* succ) { *succ = false; diff --git a/webkit/port/bridge/ScriptControllerV8.cpp b/webkit/port/bridge/ScriptControllerV8.cpp new file mode 100644 index 0000000..ce244a4 --- /dev/null +++ b/webkit/port/bridge/ScriptControllerV8.cpp @@ -0,0 +1,588 @@ +// Copyright (c) 2008, 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 "ScriptController.h" + +#include "CString.h" +#include "Document.h" +#include "DOMWindow.h" +#include "Event.h" +#include "EventNames.h" +#include "Frame.h" +#include "Node.h" +#include "NotImplemented.h" +#include "npruntime_priv.h" +#include "np_v8object.h" +#include "Widget.h" + +#include "v8_proxy.h" +#include "v8_binding.h" +#include "v8_npobject.h" + +//TODO(eseidel): We should remove this glue dependency +#undef LOG // glue defines its own LOG macro +#include "glue/webplugin_impl.h" + +NPRuntimeFunctions npruntime_functions = { + NPN_GetStringIdentifier, + NPN_GetStringIdentifiers, + NPN_GetIntIdentifier, + NPN_IdentifierIsString, + NPN_UTF8FromIdentifier, + NPN_IntFromIdentifier, + NPN_CreateObject, + NPN_RetainObject, + NPN_ReleaseObject, + NPN_Invoke, + NPN_InvokeDefault, + NPN_Evaluate, + NPN_GetProperty, + NPN_SetProperty, + NPN_RemoveProperty, + NPN_HasProperty, + NPN_HasMethod, + NPN_ReleaseVariantValue, + NPN_SetException +}; + + +namespace WebCore { + +bool ScriptController::m_recordPlaybackMode = false; + +void ScriptController::setFlags(const char* str, int length) +{ + v8::V8::SetFlagsFromString(str, length); +} + +void ScriptController::setDomain(Frame* frame, const String&) +{ + V8Proxy::DomainChanged(frame); +} + +Frame* ScriptController::retrieveActiveFrame() +{ + return V8Proxy::retrieveActiveFrame(); +} + +bool ScriptController::isSafeScript(Frame* target) +{ + return V8Proxy::IsFromSameOrigin(target, true); +} + +void ScriptController::gcProtectJSWrapper(void* dom_object) +{ + V8Proxy::GCProtect(static_cast<Peerable*>(dom_object)); +} + +void ScriptController::gcUnprotectJSWrapper(void* dom_object) +{ + V8Proxy::GCUnprotect(static_cast<Peerable*>(dom_object)); +} + +void ScriptController::pauseTimeouts(OwnPtr<PausedTimeouts>& result) +{ + DOMWindow* window = m_frame->domWindow(); + if (!window) { + result.clear(); + return; + } + window->pauseTimeouts(result); +} + +void ScriptController::resumeTimeouts(OwnPtr<PausedTimeouts>& timeouts) +{ + DOMWindow* window = m_frame->domWindow(); + if (!window) { + timeouts.clear(); + return; + } + window->resumeTimeouts(timeouts); +} + +ScriptController::ScriptController(Frame* frame) + : m_frame(frame) + , m_sourceURL(0) + , m_processingTimerCallback(false) + , m_paused(false) + , m_proxy(new V8Proxy(frame)) +#if ENABLE(NETSCAPE_PLUGIN_API) + , m_windowScriptNPObject(0) +#endif +{ +} + +ScriptController::~ScriptController() +{ +} + +void ScriptController::clearScriptObjects() +{ + // TODO(eseidel): JSC handles binding root objects here, why don't we? + +#if ENABLE(NETSCAPE_PLUGIN_API) + if (m_windowScriptNPObject) { + // Call _NPN_DeallocateObject() instead of _NPN_ReleaseObject() so that we don't leak if a plugin fails to release the window + // script object properly. + // This shouldn't cause any problems for plugins since they should have already been stopped and destroyed at this point. + _NPN_DeallocateObject(m_windowScriptNPObject); + m_windowScriptNPObject = 0; + } +#endif +} + +void ScriptController::clearPluginObjects() +{ + PluginObjectMap::iterator it = m_pluginObjects.begin(); + for (; it != m_pluginObjects.end(); ++it) { + _NPN_UnregisterObject(it->second); + NPN_ReleaseObject(it->second); + } + m_pluginObjects.clear(); +} + +// Disconnect the proxy from its owner frame; +void ScriptController::disconnectFrame() +{ + m_proxy->disconnectFrame(); +} + +bool ScriptController::processingUserGesture() const +{ + Frame* active_frame = V8Proxy::retrieveActiveFrame(); + // No script is running, must be run by users. + if (!active_frame) + return true; + + V8Proxy* active_proxy = active_frame->script()->proxy(); + + v8::HandleScope handle_scope; + v8::Handle<v8::Context> context = V8Proxy::GetContext(active_frame); + // TODO(fqian): find all cases context can be empty: + // 1) JS is disabled; + // 2) page is NULL; + if (context.IsEmpty()) + return true; + + v8::Context::Scope scope(context); + + v8::Handle<v8::Object> global = context->Global(); + v8::Handle<v8::Value> jsevent = global->Get(v8::String::NewSymbol("event")); + Event* event = V8Proxy::ToNativeEvent(jsevent); + + // Based on code from kjs_bindings.cpp. + // Note: This is more liberal than Firefox's implementation. + if (event) { + const AtomicString& type = event->type(); + bool event_ok = + // mouse events + type == EventNames::clickEvent || + type == EventNames::mousedownEvent || + type == EventNames::mouseupEvent || + type == EventNames::dblclickEvent || + // keyboard events + type == EventNames::keydownEvent || + type == EventNames::keypressEvent || + type == EventNames::keyupEvent || + // other accepted events + type == EventNames::selectEvent || + type == EventNames::changeEvent || + type == EventNames::focusEvent || + type == EventNames::blurEvent || + type == EventNames::submitEvent; + + if (event_ok) + return true; + } else if (active_proxy->inlineCode() && !active_proxy->timerCallback()) + // This is the <a href="javascript:window.open('...')> case -> we let it + // through + return true; + + // This is the <script>window.open(...)</script> case or a timer callback -> + // block it + return false; +} + + +// Evaluate a script file in the environment of this proxy. +String ScriptController::evaluate(const String& filename, int baseLine, + const String& code, Node* node, bool* succ) +{ + if (succ) + *succ = false; + String result; + + v8::HandleScope hs; + v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); + if (context.IsEmpty()) + return result; + + v8::Context::Scope scope(context); + + // HTMLTokenizer used to use base zero line numbers for scripts, now it + // uses base 1. This confuses v8, which uses line offsets from the + // first line. + v8::Local<v8::Value> obj = m_proxy->Evaluate(filename, baseLine - 1, code, + node); + + if (obj.IsEmpty() || obj->IsUndefined()) + return result; + + // If the return value is not a string, return 0 (what KJS does). + if (!obj->IsString()) { + v8::TryCatch exception_block; + obj = obj->ToString(); + if (exception_block.HasCaught()) + obj = v8::String::New(""); + } + + result = ToWebCoreString(obj); + if (succ) + *succ = true; + + return result; +} + +v8::Persistent<v8::Value> ScriptController::evaluate(const String& filename, + int baseLine, + const String& code, + Node* node) +{ + v8::HandleScope hs; + v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); + if (context.IsEmpty()) + return v8::Persistent<v8::Value>(); + + v8::Context::Scope scope(context); + + v8::Local<v8::Value> obj = m_proxy->Evaluate(filename, baseLine, code, node); + + if (obj.IsEmpty()) + return v8::Persistent<v8::Value>(); + + // TODO(fqian): keep track the global handle created. + return v8::Persistent<v8::Value>::New(obj); +} + +void ScriptController::disposeJSResult(v8::Persistent<v8::Value> result) +{ + result.Dispose(); + result.Clear(); +} + +EventListener* ScriptController::createHTMLEventHandler( + const String& functionName, const String& code, Node* node) +{ + return m_proxy->createHTMLEventHandler(functionName, code, node); +} + +#if ENABLE(SVG) +EventListener* ScriptController::createSVGEventHandler( + const String& functionName, const String& code, Node* node) +{ + return m_proxy->createSVGEventHandler(functionName, code, node); +} +#endif + +void ScriptController::setEventHandlerLineno(int lineno) +{ + m_proxy->setEventHandlerLineno(lineno); +} + +void ScriptController::finishedWithEvent(Event* evt) +{ + m_proxy->finishedWithEvent(evt); +} + +void ScriptController::clearDocumentWrapper() +{ + m_proxy->clearDocumentWrapper(); +} + +// Create a V8 object with an interceptor of NPObjectPropertyGetter +void ScriptController::BindToWindowObject(Frame* frame, const String& key, NPObject* object) +{ + v8::HandleScope handle_scope; + + v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); + if (context.IsEmpty()) + return; + + v8::Context::Scope scope(context); + + v8::Handle<v8::Object> value = CreateV8ObjectForNPObject(object, NULL); + + // Attach to the global object + v8::Handle<v8::Object> global = context->Global(); + global->Set(v8String(key), value); +} + +void ScriptController::collectGarbage() +{ + v8::HandleScope hs; + v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); + if (context.IsEmpty()) + return; + + v8::Context::Scope scope(context); + + m_proxy->Evaluate("", 0, "if (window.gc) void(gc());", NULL); +} + +NPRuntimeFunctions* ScriptController::functions() +{ + return &npruntime_functions; +} + + +bool ScriptController::haveInterpreter() const +{ + return m_proxy->ContextInitialized(); +} + +bool ScriptController::isEnabled() const +{ + return m_proxy->isEnabled(); +} + +JSInstance ScriptController::createScriptInstanceForWidget(Widget* widget) +{ + ASSERT(widget != 0); + + if (widget->isFrameView()) + return JSInstanceHolder::EmptyInstance(); + + // Note: We have to trust that the widget passed to us here + // is a WebPluginImpl. There isn't a way to dynamically verify + // it, since the derived class (Widget) has no identifier. + WebPluginContainer* container = static_cast<WebPluginContainer*>(widget); + if (!container) + return JSInstanceHolder::EmptyInstance(); + + NPObject* npObject = container->GetPluginScriptableObject(); + if (!npObject) + return JSInstanceHolder::EmptyInstance(); + +#if USE(JSC) + // Register 'widget' with the frame so that we can teardown + // subobjects when the container goes away. + RefPtr<KJS::Bindings::RootObject> root = script()->createRootObject(widget); + KJS::Bindings::Instance* instance = + KJS::Bindings::Instance::createBindingForLanguageInstance( + KJS::Bindings::Instance::CLanguage, npObject, + root.release()); + // GetPluginScriptableObject returns a retained NPObject. + // The caller is expected to release it. + NPN_ReleaseObject(npObject); + return instance; +#elif USE(V8) + // Frame Memory Management for NPObjects + // ------------------------------------- + // NPObjects are treated differently than other objects wrapped by JS. + // NPObjects are not Peerable, and cannot be made peerable, since NPObjects + // can be created either by the browser (e.g. the main window object) or by + // the plugin (the main plugin object for a HTMLEmbedElement). Further, + // unlike most DOM Objects, the frame is especially careful to ensure + // NPObjects terminate at frame teardown because if a plugin leaks a + // reference, it could leak its objects (or the browser's objects). + // + // The Frame maintains a list of plugin objects (m_pluginObjects) + // which it can use to quickly find the wrapped embed object. + // + // Inside the NPRuntime, we've added a few methods for registering + // wrapped NPObjects. The purpose of the registration is because + // javascript garbage collection is non-deterministic, yet we need to + // be able to tear down the plugin objects immediately. When an object + // is registered, javascript can use it. When the object is destroyed, + // or when the object's "owning" object is destroyed, the object will + // be un-registered, and the javascript engine must not use it. + // + // Inside the javascript engine, the engine can keep a reference to the + // NPObject as part of its wrapper. However, before accessing the object + // it must consult the NPN_Registry. + + v8::Local<v8::Object> wrapper = CreateV8ObjectForNPObject(npObject, NULL); + + // Track the plugin object. We've been given a reference to the object. + m_pluginObjects.set(widget, npObject); + + JSInstance instance = wrapper; + return instance; +#endif +} + +void ScriptController::cleanupScriptObjectsForPlugin(void* nativeHandle) +{ + PluginObjectMap::iterator it = m_pluginObjects.find(nativeHandle); + if (it == m_pluginObjects.end()) + return; + _NPN_UnregisterObject(it->second); + NPN_ReleaseObject(it->second); + m_pluginObjects.remove(it); +} + +static NPObject* createNoScriptObject() +{ + notImplemented(); + return 0; +} + +static NPObject* createScriptObject(Frame* frame) +{ + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); + if (context.IsEmpty()) + return createNoScriptObject(); + + v8::Context::Scope scope(context); + DOMWindow* window = frame->domWindow(); + v8::Handle<v8::Value> global = V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, window); + ASSERT(global->IsObject()); + return NPN_CreateScriptObject(0, v8::Handle<v8::Object>::Cast(global), window); +} + +NPObject* ScriptController::windowScriptNPObject() +{ + if (m_windowScriptNPObject) + return m_windowScriptNPObject; + + if (isEnabled()) { + // JavaScript is enabled, so there is a JavaScript window object. + // Return an NPObject bound to the window object. + m_windowScriptNPObject = createScriptObject(m_frame); + _NPN_RegisterObject(m_windowScriptNPObject, NULL); + } else { + // JavaScript is not enabled, so we cannot bind the NPObject to the + // JavaScript window object. Instead, we create an NPObject of a + // different class, one which is not bound to a JavaScript object. + m_windowScriptNPObject = createNoScriptObject(); + } + return m_windowScriptNPObject; +} + +NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement* plugin) +{ + // Can't create NPObjects when JavaScript is disabled + if (!isEnabled()) + return createNoScriptObject(); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame); + if (context.IsEmpty()) + return createNoScriptObject(); + v8::Context::Scope scope(context); + + DOMWindow* window = m_frame->domWindow(); + v8::Handle<v8::Value> v8plugin = V8Proxy::ToV8Object(V8ClassIndex::HTMLEMBEDELEMENT, plugin); + if (!v8plugin->IsObject()) + return createNoScriptObject(); + + return NPN_CreateScriptObject(0, v8::Handle<v8::Object>::Cast(v8plugin), window); +} + + +void ScriptController::clearWindowShell() +{ + // TODO(eseidel): we don't yet have a split window implementation + // we need to clear the window object here. + m_proxy->clear(); +} + +void ScriptController::attachDebugger(void*) +{ + notImplemented(); +} + +void ScriptController::updateDocument() +{ + // TODO(eseidel): Should update document property on current window object + // and all previous window objects which may still be alive. + notImplemented(); +} + + +JSInstanceHolder::JSInstanceHolder() +{ +} + +JSInstanceHolder::JSInstanceHolder(JSInstance instance) +{ + *this = instance; +} + +JSInstanceHolder::~JSInstanceHolder() +{ + Clear(); +} + +bool JSInstanceHolder::IsEmpty() +{ + return m_instance.IsEmpty(); +} + +JSInstance JSInstanceHolder::Get() +{ + return v8::Local<v8::Object>::New(m_instance); +} + +void JSInstanceHolder::Clear() +{ + if (m_instance.IsEmpty()) + return; + v8::HandleScope scope; + v8::Persistent<v8::Object> handle(m_instance); +#ifndef NDEBUG + V8Proxy::UnregisterGlobalHandle(this, handle); +#endif + handle.Dispose(); + m_instance.Clear(); +} + +JSInstance JSInstanceHolder::EmptyInstance() +{ + return v8::Local<v8::Object>(); +} + +JSInstanceHolder& JSInstanceHolder::operator=(JSInstance instance) +{ + Clear(); + if (instance.IsEmpty()) + return *this; + + v8::Persistent<v8::Object> handle = + v8::Persistent<v8::Object>::New(instance); + m_instance = handle; +#ifndef NDEBUG + V8Proxy::RegisterGlobalHandle(JSINSTANCE, this, handle); +#endif + return *this; +} + +} // namespace WebCpre diff --git a/webkit/port/bridge/V8Bridge.cpp b/webkit/port/bridge/V8Bridge.cpp deleted file mode 100644 index a3a51ae..0000000 --- a/webkit/port/bridge/V8Bridge.cpp +++ /dev/null @@ -1,429 +0,0 @@ -// Copyright (c) 2008, 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. - -#define max max // windef.h overrides this, and it breaks us. -#include "config.h" -#include "V8Bridge.h" -#include "v8_proxy.h" -#include "v8_binding.h" -#include "CString.h" -#include "Event.h" -#include "EventNames.h" -#include "Frame.h" -#include "Node.h" -#include "DOMWindow.h" -#include "Document.h" -#include "np_v8object.h" -#include "v8_npobject.h" - -NPRuntimeFunctions npruntime_functions = { - NPN_GetStringIdentifier, - NPN_GetStringIdentifiers, - NPN_GetIntIdentifier, - NPN_IdentifierIsString, - NPN_UTF8FromIdentifier, - NPN_IntFromIdentifier, - NPN_CreateObject, - NPN_RetainObject, - NPN_ReleaseObject, - NPN_Invoke, - NPN_InvokeDefault, - NPN_Evaluate, - NPN_GetProperty, - NPN_SetProperty, - NPN_RemoveProperty, - NPN_HasProperty, - NPN_HasMethod, - NPN_ReleaseVariantValue, - NPN_SetException -}; - - - -namespace WebCore { - -bool JSBridge::m_recordPlaybackMode = false; - -// Implements static function declared in JSBridge. -void JSBridge::setFlags(const char* str, int length) { - v8::V8::SetFlagsFromString(str, length); -} - -// static -void JSBridge::setDomain(Frame* frame, const String&) { - V8Proxy::DomainChanged(frame); -} - -// static -Frame* JSBridge::retrieveActiveFrame() { - return V8Proxy::retrieveActiveFrame(); -} - -// static -bool JSBridge::isSafeScript(Frame* target) { - return V8Proxy::IsFromSameOrigin(target, true); -} - -// static -void JSBridge::gcProtectJSWrapper(void* dom_object) { - V8Proxy::GCProtect(static_cast<Peerable*>(dom_object)); -} - -// static -void JSBridge::gcUnprotectJSWrapper(void* dom_object) { - V8Proxy::GCUnprotect(static_cast<Peerable*>(dom_object)); -} - -// static -JSException JSBridge::NoException() { - return v8::Local<v8::Value>(); -} - -// static -bool JSBridge::IsException(JSException exception) { - return !exception.IsEmpty(); -} - -// static -PausedTimeouts* JSBridge::pauseTimeouts(Frame* frame) { - if (!frame) return NULL; - DOMWindow* window = frame->domWindow(); - if (!window) return NULL; - return window->pauseTimeouts(); -} - -// static -void JSBridge::resumeTimeouts(Frame* frame, PausedTimeouts* timeouts) { - if (!frame) return; - DOMWindow* window = frame->domWindow(); - if (!window) return; - window->resumeTimeouts(timeouts); -} - - -// --------------------------------------------------------------------------- -// V8 implementation of JSBridge. - -V8Bridge::V8Bridge(Frame* frame) { - m_proxy = new V8Proxy(frame); -} - -V8Bridge::~V8Bridge() { - delete m_proxy; -} - -// Disconnect the proxy from its owner frame; -void V8Bridge::disconnectFrame() { - m_proxy->disconnectFrame(); -} - -bool V8Bridge::wasRunByUserGesture() { - Frame* active_frame = V8Proxy::retrieveActiveFrame(); - // No script is running, must be run by users. - if (!active_frame) - return true; - - V8Proxy* active_proxy = - static_cast<V8Bridge*>(active_frame->scriptBridge())->proxy(); - - v8::HandleScope handle_scope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(active_frame); - // TODO(fqian): find all cases context can be empty: - // 1) JS is disabled; - // 2) page is NULL; - if (context.IsEmpty()) - return true; - - v8::Context::Scope scope(context); - - v8::Handle<v8::Object> global = context->Global(); - v8::Handle<v8::Value> jsevent = global->Get(v8::String::NewSymbol("event")); - Event* event = V8Proxy::ToNativeEvent(jsevent); - - // Based on code from kjs_bindings.cpp. - // Note: This is more liberal than Firefox's implementation. - if (event) { - const AtomicString& type = event->type(); - bool event_ok = - // mouse events - type == EventNames::clickEvent || - type == EventNames::mousedownEvent || - type == EventNames::mouseupEvent || - type == EventNames::dblclickEvent || - // keyboard events - type == EventNames::keydownEvent || - type == EventNames::keypressEvent || - type == EventNames::keyupEvent || - // other accepted events - type == EventNames::selectEvent || - type == EventNames::changeEvent || - type == EventNames::focusEvent || - type == EventNames::blurEvent || - type == EventNames::submitEvent; - - if (event_ok) - return true; - } else { // no event - if (active_proxy->inlineCode() && - !active_proxy->timerCallback()) { - // This is the <a href="javascript:window.open('...')> case -> we let it - // through - return true; - } - // This is the <script>window.open(...)</script> case or a timer callback -> - // block it - } - - return false; -} - - -// Evaluate a script file in the environment of this proxy. Used for -// evaluating the code in script tags and for evaluating the code from -// javascript URLs. -String V8Bridge::evaluate(const String& filename, int baseLine, - const String& code, Node* node, bool* succ) { - *succ = false; - String result; - - v8::HandleScope hs; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); - if (context.IsEmpty()) - return result; - - v8::Context::Scope scope(context); - - v8::Local<v8::Value> obj; - { - // Isolate exceptions that occur when executing the code. These - // exceptions should not interfere with javascript code we might - // evaluate from C++ when returning from here. - v8::TryCatch exception_block; - exception_block.SetVerbose(true); - obj = m_proxy->Evaluate(filename, baseLine, code, node); - } - - if (obj.IsEmpty() || obj->IsUndefined()) - return result; - - // If the return value is not a string, return 0 (what KJS does). - if (!obj->IsString()) { - v8::TryCatch exception_block; - obj = obj->ToString(); - if (exception_block.HasCaught()) - obj = v8::String::New(""); - } - - result = ToWebCoreString(obj); - *succ = true; - - return result; -} - -v8::Persistent<v8::Value> V8Bridge::evaluate(const String& filename, - int baseLine, - const String& code, - Node* node) { - v8::HandleScope hs; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); - if (context.IsEmpty()) - return v8::Persistent<v8::Value>(); - - v8::Context::Scope scope(context); - - v8::Local<v8::Value> obj = m_proxy->Evaluate(filename, baseLine, code, node); - - if (obj.IsEmpty()) return v8::Persistent<v8::Value>(); - - // TODO(fqian): keep track the global handle created. - return v8::Persistent<v8::Value>::New(obj); -} - -void V8Bridge::disposeJSResult(v8::Persistent<v8::Value> result) { - result.Dispose(); - result.Clear(); -} - -EventListener* V8Bridge::createHTMLEventHandler( - const String& functionName, const String& code, Node* node) { - return m_proxy->createHTMLEventHandler(functionName, code, node); -} - -#if ENABLE(SVG) -EventListener* V8Bridge::createSVGEventHandler( - const String& functionName, const String& code, Node* node) { - return m_proxy->createSVGEventHandler(functionName, code, node); -} -#endif - -void V8Bridge::setEventHandlerLineno(int lineno) { - m_proxy->setEventHandlerLineno(lineno); -} - -void V8Bridge::finishedWithEvent(Event* evt) { - m_proxy->finishedWithEvent(evt); -} - -void V8Bridge::clear() { - m_proxy->clear(); -} - -void V8Bridge::clearDocumentWrapper() { - m_proxy->clearDocumentWrapper(); -} - -// Create a V8 object with an interceptor of NPObjectPropertyGetter -void V8Bridge::BindToWindowObject(Frame* frame, const String& key, - NPObject* object) { - v8::HandleScope handle_scope; - - v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); - if (context.IsEmpty()) - return; - - v8::Context::Scope scope(context); - - v8::Handle<v8::Object> value = CreateV8ObjectForNPObject(object, NULL); - - // Attach to the global object - v8::Handle<v8::Object> global = context->Global(); - global->Set(v8String(key), value); -} - - -void V8Bridge::CollectGarbage() { - v8::HandleScope hs; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); - if (context.IsEmpty()) return; - - v8::Context::Scope scope(context); - - m_proxy->Evaluate("", 0, "if (window.gc) void(gc());", NULL); -} - - -NPRuntimeFunctions *V8Bridge::functions() { - return &npruntime_functions; -} - - -NPObject *V8Bridge::CreateScriptObject(Frame* frame) { - v8::HandleScope handle_scope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); - if (context.IsEmpty()) - return 0; - - v8::Context::Scope scope(context); - DOMWindow *window = frame->domWindow(); - v8::Handle<v8::Value> global = - V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, window); - ASSERT(global->IsObject()); - return NPN_CreateScriptObject(0, v8::Handle<v8::Object>::Cast(global), - window); -} - -NPObject *V8Bridge::CreateScriptObject(Frame* frame, - HTMLPlugInElement* element) { - v8::HandleScope handle_scope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); - if (context.IsEmpty()) - return 0; - v8::Context::Scope scope(context); - - DOMWindow *window = frame->domWindow(); - v8::Handle<v8::Value> dom_win = - V8Proxy::ToV8Object(V8ClassIndex::HTMLEMBEDELEMENT, element); - if (dom_win->IsObject()) { - return NPN_CreateScriptObject(0, v8::Handle<v8::Object>::Cast(dom_win), - window); - } else { - return 0; - } -} - -NPObject *V8Bridge::CreateNoScriptObject() { - return 0; // implement me -} - -bool V8Bridge::haveInterpreter() const { - return m_proxy->ContextInitialized(); -} - -bool V8Bridge::isEnabled() const { - return m_proxy->isEnabled(); -} - -JSInstanceHolder::JSInstanceHolder() : m_instance() { } - -JSInstanceHolder::JSInstanceHolder(JSInstance instance) { - *this = instance; -} - -JSInstanceHolder::~JSInstanceHolder() { - Clear(); -} - -bool JSInstanceHolder::IsEmpty() { - return m_instance.IsEmpty(); -} - -JSInstance JSInstanceHolder::Get() { - return v8::Local<v8::Object>::New(m_instance); -} - -void JSInstanceHolder::Clear() { - if (!m_instance.IsEmpty()) { - v8::HandleScope scope; - v8::Persistent<v8::Object> handle(m_instance); -#ifndef NDEBUG - V8Proxy::UnregisterGlobalHandle(this, handle); -#endif - handle.Dispose(); - m_instance.Clear(); - } -} - -JSInstance JSInstanceHolder::EmptyInstance() { - return v8::Local<v8::Object>(); -} - -JSInstanceHolder& JSInstanceHolder::operator=(JSInstance instance) { - Clear(); - if (!instance.IsEmpty()) { - v8::Persistent<v8::Object> handle = - v8::Persistent<v8::Object>::New(instance); - m_instance = handle; -#ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(JSINSTANCE, this, handle); -#endif - } - return *this; -} - -} // namespace WebCpre diff --git a/webkit/port/bridge/V8Bridge.h b/webkit/port/bridge/V8Bridge.h deleted file mode 100644 index 12458f6..0000000 --- a/webkit/port/bridge/V8Bridge.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file contains V8 specific bits that's necessary to build WebKit. - -#ifndef V8_BRIDGE_H__ -#define V8_BRIDGE_H__ - -#include "v8.h" -#include "JSBridge.h" - -namespace WebCore { -class Frame; -class Node; -class V8Proxy; - -class V8Bridge : public JSBridge { - public: - explicit V8Bridge(Frame* frame); - virtual ~V8Bridge(); - - virtual void disconnectFrame(); - virtual bool wasRunByUserGesture(); - // Evaluate a script file in the environment of this proxy. - // When succeed, sets the 'succ' parameter to true and - // returns the result as a string. - virtual String evaluate(const String& filename, int baseLine, - const String& code, Node* node, bool* succ); - - // Evaluate a script in the environment of this proxy. - // Returns a v8::Persistent handle. If the evaluation fails, - // it returns an empty handle. The caller must check - // whether the return value is empty. - virtual JSResult evaluate(const String& filename, int baseLine, - const String& code, Node* node); - virtual void disposeJSResult(JSResult result); - - virtual EventListener* createHTMLEventHandler(const String& functionName, - const String& code, Node* node); -#if ENABLE(SVG) - virtual EventListener* createSVGEventHandler(const String& functionName, - const String& code, Node* node); -#endif - virtual void setEventHandlerLineno(int lineno); - virtual void finishedWithEvent(Event* evt); - virtual void clear(); - - V8Proxy* proxy() { return m_proxy; } - - // virtual JSRootObject *getRootObject(); - - virtual void BindToWindowObject(Frame* frame, const String& key, - NPObject* object); - virtual NPRuntimeFunctions *functions(); - virtual NPObject *CreateScriptObject(Frame* frame); - virtual NPObject *CreateScriptObject(Frame* frame, HTMLPlugInElement* pe); - virtual NPObject *CreateNoScriptObject(); - - virtual bool haveInterpreter() const; - virtual bool isEnabled() const; - - virtual void clearDocumentWrapper(); - - virtual void CollectGarbage(); - - private: - V8Proxy* m_proxy; -}; - -} // namespace WebCore -#endif // V8_BRIDGE_H__ - diff --git a/webkit/port/css/RGBColor.cpp b/webkit/port/css/RGBColor.cpp index 526a23a..601b5c1 100644 --- a/webkit/port/css/RGBColor.cpp +++ b/webkit/port/css/RGBColor.cpp @@ -31,19 +31,19 @@ namespace WebCore { -CSSPrimitiveValue* RGBColor::red() { +PassRefPtr<CSSPrimitiveValue> RGBColor::red() { unsigned int value = (m_rgbcolor >> 16) & 0xFF; - return new CSSPrimitiveValue(value, CSSPrimitiveValue::CSS_NUMBER); + return CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER); } -CSSPrimitiveValue* RGBColor::green() { +PassRefPtr<CSSPrimitiveValue> RGBColor::green() { unsigned int value = (m_rgbcolor >> 8) & 0xFF; - return new CSSPrimitiveValue(value, CSSPrimitiveValue::CSS_NUMBER); + return CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER); } -CSSPrimitiveValue* RGBColor::blue() { +PassRefPtr<CSSPrimitiveValue> RGBColor::blue() { unsigned int value = m_rgbcolor & 0xFF; - return new CSSPrimitiveValue(value, CSSPrimitiveValue::CSS_NUMBER); + return CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER); } } // namespace WebCore diff --git a/webkit/port/css/RGBColor.h b/webkit/port/css/RGBColor.h index 7538272..e537e8d 100644 --- a/webkit/port/css/RGBColor.h +++ b/webkit/port/css/RGBColor.h @@ -15,9 +15,9 @@ class RGBColor : public RefCounted<RGBColor> { public: RGBColor(unsigned rgbcolor) : m_rgbcolor(rgbcolor) { } - CSSPrimitiveValue* red(); - CSSPrimitiveValue* green(); - CSSPrimitiveValue* blue(); + PassRefPtr<CSSPrimitiveValue> red(); + PassRefPtr<CSSPrimitiveValue> green(); + PassRefPtr<CSSPrimitiveValue> blue(); private: unsigned m_rgbcolor; diff --git a/webkit/port/dom/Document.idl b/webkit/port/dom/Document.idl index 75c280d..cd3bfde 100644 --- a/webkit/port/dom/Document.idl +++ b/webkit/port/dom/Document.idl @@ -227,9 +227,9 @@ module core { NodeList getElementsByClassName(in DOMString tagname); // DocumentSelector - Selector API - Element querySelector(in [ConvertUndefinedOrNullToNullString] DOMString selectors) + [Custom] Element querySelector(in [ConvertUndefinedOrNullToNullString] DOMString selectors, in NSResolver resolver) raises(DOMException); - NodeList querySelectorAll(in [ConvertUndefinedOrNullToNullString] DOMString selectors) + [Custom] NodeList querySelectorAll(in [ConvertUndefinedOrNullToNullString] DOMString selectors, in NSResolver resolver) raises(DOMException); }; diff --git a/webkit/port/dom/NSResolver.idl b/webkit/port/dom/NSResolver.idl new file mode 100644 index 0000000..5927331 --- /dev/null +++ b/webkit/port/dom/NSResolver.idl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module core { + + interface NSResolver { + [Custom] DOMString lookupNamespaceURI(in DOMString prefix); + }; + +} diff --git a/webkit/port/history/BackForwardList.h b/webkit/port/history/BackForwardList.h index ec54818..e796913 100644 --- a/webkit/port/history/BackForwardList.h +++ b/webkit/port/history/BackForwardList.h @@ -26,9 +26,10 @@ #ifndef BackForwardList_h #define BackForwardList_h -#include <wtf/RefCounted.h> #include <wtf/Forward.h> #include <wtf/HashSet.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> #include <wtf/Vector.h> namespace WebCore { @@ -68,7 +69,10 @@ public: class BackForwardList : public RefCounted<BackForwardList> { public: - BackForwardList(Page*); + static PassRefPtr<BackForwardList> create(Page* page) + { + return adoptRef(new BackForwardList(page)); + } ~BackForwardList(); Page* page() { return m_page; } @@ -119,6 +123,8 @@ public: bool isPreviousItemFake() const { return m_previousItemFake; } private: + BackForwardList(Page*); + // Sets m_previousItemFake to the value of m_currentItemFake and // m_currentItemFake to false. This is called internally at various points // when m_currenItem is being updated. diff --git a/webkit/port/loader/IconDatabaseNone.cpp b/webkit/port/loader/IconDatabaseNone.cpp index 734e119..c76a2c4 100644 --- a/webkit/port/loader/IconDatabaseNone.cpp +++ b/webkit/port/loader/IconDatabaseNone.cpp @@ -99,7 +99,7 @@ void IconDatabase::readIconForPageURLFromDisk(const String&) } -Image* IconDatabase::iconForPageURL(const String& pageURL, const IntSize& size, bool cache) +Image* IconDatabase::iconForPageURL(const String& pageURL, const IntSize& size) { return defaultIcon(size); } diff --git a/webkit/port/page/AccessibilityObjectWin.cpp b/webkit/port/page/AccessibilityObjectWin.cpp new file mode 100644 index 0000000..e309ac8 --- /dev/null +++ b/webkit/port/page/AccessibilityObjectWin.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "config.h" +#include "AccessibilityObject.h" + +namespace WebCore { + +bool AccessibilityObject::accessibilityIgnoreAttachment() const +{ + return false; +} + +} // namespace WebCore diff --git a/webkit/port/page/Console.cpp b/webkit/port/page/Console.cpp new file mode 100644 index 0000000..66b53cd --- /dev/null +++ b/webkit/port/page/Console.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Console.h" + +#include "ChromeClient.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "InspectorController.h" +#include "NotImplemented.h" +#include "Page.h" + +namespace WebCore { + +Console::Console(Frame* frame) + : m_frame(frame) +{ +} + +void Console::disconnectFrame() +{ + m_frame = 0; +} + +void Console::debug(const String& message) +{ + // In Firebug, console.debug has the same behavior as console.log. So we'll + // do the same. + log(message); +} + +void Console::error(const String& message) +{ + // TODO(erg): For all of these methods which call addMessageToConsole(), we + // always assume the line number of the console.error(...) was called on + // line 0. To fix this, we need to modify the V8 version of the Console + // interface to also pass in the current line number, which will be hard + // since it looks like that information isn't publicly accessible with the + // current v8 interface. <http://crbug.com/2960> + // + // This will fix this currently broken test: + // LayoutTests/fast/dom/Window/console-functions.html + + if (!m_frame) + return; + + Page* page = m_frame->page(); + if (!page) + return; + + const KURL& url = m_frame->loader()->url(); + String prettyURL = url.prettyURL(); + + page->chrome()->client()->addMessageToConsole(message, 0, prettyURL); + page->inspectorController()->addMessageToConsole(JSMessageSource, ErrorMessageLevel, message, 0, url.string()); +} + +void Console::info(const String& message) +{ + if (!m_frame) + return; + + Page* page = m_frame->page(); + if (!page) + return; + + const KURL& url = m_frame->loader()->url(); + String prettyURL = url.prettyURL(); + + page->chrome()->client()->addMessageToConsole(message, 0, prettyURL); + page->inspectorController()->addMessageToConsole(JSMessageSource, LogMessageLevel, message, 0, url.string()); +} + +void Console::log(const String& message) +{ + if (!m_frame) + return; + + Page* page = m_frame->page(); + if (!page) + return; + + const KURL& url = m_frame->loader()->url(); + String prettyURL = url.prettyURL(); + + page->chrome()->client()->addMessageToConsole(message, 0, prettyURL); + page->inspectorController()->addMessageToConsole(JSMessageSource, LogMessageLevel, message, 0, url.string()); +} + +void Console::warn(const String& message) +{ + if (!m_frame) + return; + + Page* page = m_frame->page(); + if (!page) + return; + + const KURL& url = m_frame->loader()->url(); + String prettyURL = url.prettyURL(); + + page->chrome()->client()->addMessageToConsole(message, 0, prettyURL); + page->inspectorController()->addMessageToConsole(JSMessageSource, WarningMessageLevel, message, 0, url.string()); +} + +void Console::addMessage(MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL) +{ + Page* page = this->page(); + if (!page) + return; + + if (source == JSMessageSource) + page->chrome()->client()->addMessageToConsole(message, lineNumber, sourceURL); + + page->inspectorController()->addMessageToConsole(source, level, message, lineNumber, sourceURL); +} + +void Console::time(const String& title) +{ + notImplemented(); +} + +void Console::groupEnd() +{ + notImplemented(); +} + +Page* Console::page() const +{ + if (!m_frame) + return 0; + + return m_frame->page(); +} + +} // namespace WebCore diff --git a/webkit/port/page/DOMWindow.idl b/webkit/port/page/DOMWindow.idl index c667167..c606de8 100644 --- a/webkit/port/page/DOMWindow.idl +++ b/webkit/port/page/DOMWindow.idl @@ -121,6 +121,10 @@ module window { attribute [Replaceable] Console console; + // cross-document messaging + [DoNotCheckDomainSecurity, Custom] void postMessage(in DOMString message, in DOMString targetOrigin) + raises(DOMException); + #if defined(V8_BINDING) [Custom] DOMWindow open(in DOMString url, in DOMString name, diff --git a/webkit/port/page/EventHandlerWin.cpp b/webkit/port/page/EventHandlerWin.cpp index 37f989f..3e7476e5 100644 --- a/webkit/port/page/EventHandlerWin.cpp +++ b/webkit/port/page/EventHandlerWin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Don Gibson <dgibson77@gmail.com> + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,12 +27,14 @@ #include "EventHandler.h" #include "ClipboardWin.h" +#include "Cursor.h" +#include "FloatPoint.h" #include "FocusController.h" -#include "Frame.h" #include "FrameView.h" -#include "KeyboardEvent.h" +#include "Frame.h" +#include "HitTestRequest.h" +#include "HitTestResult.h" #include "MouseEventWithHitTestResults.h" -#include "NotImplemented.h" #include "Page.h" #include "PlatformKeyboardEvent.h" #include "PlatformScrollBar.h" @@ -40,15 +42,14 @@ #include "RenderWidget.h" #include "SelectionController.h" #include "WCDataObject.h" +#include "NotImplemented.h" namespace WebCore { -// On Windows, clicking and moving the mouse on selected text should always -// initiate a drag. -const double EventHandler::TextDragDelay = 0.0; - unsigned EventHandler::s_accessKeyModifiers = PlatformKeyboardEvent::AltKey; +const double EventHandler::TextDragDelay = 0.0; + bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe) { // If we're clicking into a frame that is selected, the frame will appear @@ -56,12 +57,12 @@ bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& m // really strange (having the whole frame be greyed out), so we deselect the // selection. IntPoint p = m_frame->view()->windowToContents(mev.event().pos()); - if (m_frame->selectionController()->contains(p)) { + if (m_frame->selection()->contains(p)) { VisiblePosition visiblePos( mev.targetNode()->renderer()->positionForPoint(mev.localPoint())); Selection newSelection(visiblePos); if (m_frame->shouldChangeSelection(newSelection)) - m_frame->selectionController()->setSelection(newSelection); + m_frame->selection()->setSelection(newSelection); } subframe->eventHandler()->handleMousePressEvent(mev.event()); @@ -99,8 +100,7 @@ bool EventHandler::passWheelEventToWidget(PlatformWheelEvent& wheelEvent, Widget return static_cast<FrameView*>(widget)->frame()->eventHandler()->handleWheelEvent(wheelEvent); } -bool EventHandler::passMousePressEventToScrollbar(MouseEventWithHitTestResults& mev, - PlatformScrollbar* scrollbar) +bool EventHandler::passMousePressEventToScrollbar(MouseEventWithHitTestResults& mev, PlatformScrollbar* scrollbar) { if (!scrollbar || !scrollbar->isEnabled()) return false; @@ -116,11 +116,6 @@ bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestR return passMouseDownEventToWidget(static_cast<RenderWidget*>(event.targetNode()->renderer())->widget()); } -bool EventHandler::passWidgetMouseDownEventToWidget(RenderWidget* renderWidget) -{ - return passMouseDownEventToWidget(renderWidget->widget()); -} - bool EventHandler::passMouseDownEventToWidget(Widget* widget) { notImplemented(); @@ -132,18 +127,18 @@ bool EventHandler::tabsToAllControls(KeyboardEvent*) const return true; } -bool EventHandler::eventActivatedView(const PlatformMouseEvent&) const +bool EventHandler::eventActivatedView(const PlatformMouseEvent& event) const { // TODO(darin): Apple's EventHandlerWin.cpp does the following: // return event.activatedWebView(); return false; } -Clipboard* EventHandler::createDraggingClipboard() const +PassRefPtr<Clipboard> EventHandler::createDraggingClipboard() const { COMPtr<WCDataObject> dataObject; WCDataObject::createInstance(&dataObject); - return new ClipboardWin(true, dataObject.get(), ClipboardWritable); + return ClipboardWin::create(true, dataObject.get(), ClipboardWritable); } void EventHandler::focusDocumentView() @@ -154,4 +149,9 @@ void EventHandler::focusDocumentView() page->focusController()->setFocusedFrame(m_frame); } +bool EventHandler::passWidgetMouseDownEventToWidget(RenderWidget* renderWidget) +{ + return passMouseDownEventToWidget(renderWidget->widget()); +} + } diff --git a/webkit/port/page/Location.cpp b/webkit/port/page/Location.cpp index 934cf86..d5ab0b3 100644 --- a/webkit/port/page/Location.cpp +++ b/webkit/port/page/Location.cpp @@ -30,10 +30,10 @@ #include "config.h" #include "Location.h" #include "PlatformString.h" -#include "DeprecatedString.h" #include "KURL.h" #include "Document.h" #include "FrameLoader.h" +#include "ScriptController.h" #include "CSSHelper.h" namespace { @@ -64,11 +64,11 @@ void Location::ChangeLocationTo(const KURL& url, bool lock_history) { if (url.isEmpty()) return; - Frame* active_frame = JSBridge::retrieveActiveFrame(); + Frame* active_frame = ScriptController::retrieveActiveFrame(); if (!active_frame) return; - bool user_gesture = active_frame->scriptBridge()->wasRunByUserGesture(); + bool user_gesture = active_frame->script()->processingUserGesture(); String referrer = active_frame->loader()->outgoingReferrer(); m_frame->loader()->scheduleLocationChange(url.string(), referrer, lock_history, user_gesture); @@ -76,7 +76,7 @@ void Location::ChangeLocationTo(const KURL& url, bool lock_history) { String Location::hash() { KURL url = GetFrameUrl(m_frame); - return url.ref().isNull() ? "" : "#" + url.ref(); // convert DeprecatedString to String + return url.ref().isNull() ? "" : "#" + url.ref(); } void Location::setHash(const String& hash) { @@ -84,10 +84,10 @@ void Location::setHash(const String& hash) { return; KURL url = m_frame->loader()->url(); - DeprecatedString str = hash.deprecatedString(); - + String str = hash; + if (str.startsWith("#")) - str = str.mid(1); + str = str.substring(1); if (url.ref() == str) return; url.setRef(str); @@ -98,10 +98,10 @@ void Location::setHash(const String& hash) { String Location::host() { KURL url = GetFrameUrl(m_frame); - DeprecatedString str = url.host(); - if (url.port()) { - str += ":" + DeprecatedString::number((int)url.port()); - } + String str = url.host(); + if (url.port()) + str += ":" + String::number((int)url.port()); + return str; } @@ -110,9 +110,9 @@ void Location::setHost(const String& host) { return; KURL url = m_frame->loader()->url(); - DeprecatedString str = host.deprecatedString(); - DeprecatedString newhost = str.left(str.find(":")); - DeprecatedString newport = str.mid(str.find(":") + 1); + String str = host; + String newhost = str.left(str.find(":")); + String newport = str.substring(str.find(":") + 1); url.setHost(newhost); url.setPort(newport.toUInt()); @@ -128,9 +128,8 @@ void Location::setHostname(const String& hostname) { if (!m_frame) return; - KURL url = m_frame->loader()->url(); - DeprecatedString str = hostname.deprecatedString(); - url.setHost(str); + KURL url = m_frame->loader()->url(); + url.setHost(hostname); ChangeLocationTo(url, false); } @@ -147,7 +146,7 @@ void Location::setHref(const String& value) { if (!m_frame) return; - Frame* active_frame = JSBridge::retrieveActiveFrame(); + Frame* active_frame = ScriptController::retrieveActiveFrame(); if (!active_frame) return; @@ -156,7 +155,7 @@ void Location::setHref(const String& value) { // Allows cross domain access except javascript url. if (!parseURL(value).startsWith("javascript:", false) || - JSBridge::isSafeScript(m_frame)) { + ScriptController::isSafeScript(m_frame)) { ChangeLocationTo(active_frame->loader()->completeURL(value), false); } } @@ -171,8 +170,7 @@ void Location::setPathname(const String& pathname) { return; KURL url = m_frame->loader()->url(); - DeprecatedString str = pathname.deprecatedString(); - url.setPath(str); + url.setPath(pathname); ChangeLocationTo(url, false); } @@ -187,8 +185,7 @@ void Location::setPort(const String& port) { return; KURL url = m_frame->loader()->url(); - DeprecatedString str = port.deprecatedString(); - url.setPort(str.toUInt()); + url.setPort(port.toUInt()); ChangeLocationTo(url, false); } @@ -202,9 +199,8 @@ void Location::setProtocol(const String& protocol) { if (!m_frame) return; - KURL url = m_frame->loader()->url(); - DeprecatedString str = protocol.deprecatedString(); - url.setProtocol(str); + KURL url = m_frame->loader()->url(); + url.setProtocol(protocol); ChangeLocationTo(url, false); } @@ -218,31 +214,33 @@ void Location::setSearch(const String& query) { if (!m_frame) return; - KURL url = m_frame->loader()->url(); - DeprecatedString str = query.deprecatedString(); - url.setQuery(str); + KURL url = m_frame->loader()->url(); + url.setQuery(query); ChangeLocationTo(url, false); } -void Location::reload(bool forceget) { - if (!m_frame) - return; +void Location::reload(bool forceget) +{ + if (!m_frame) + return; - Frame* active_frame = JSBridge::retrieveActiveFrame(); - if (!active_frame) - return; + Frame* active_frame = ScriptController::retrieveActiveFrame(); + if (!active_frame) + return; - if (JSBridge::isSafeScript(m_frame)) { - m_frame->loader()->scheduleRefresh(active_frame->scriptBridge()->wasRunByUserGesture()); - } + if (!ScriptController::isSafeScript(m_frame)) + return; + + bool userGesture = active_frame->script()->processingUserGesture(); + m_frame->loader()->scheduleRefresh(userGesture); } void Location::replace(const String& url) { if (!m_frame) return; - Frame* active_frame = JSBridge::retrieveActiveFrame(); + Frame* active_frame = ScriptController::retrieveActiveFrame(); if (!active_frame) return; @@ -251,7 +249,7 @@ void Location::replace(const String& url) { // Allows cross domain access except javascript url. if (!parseURL(url).startsWith("javascript:", false) || - JSBridge::isSafeScript(m_frame)) { + ScriptController::isSafeScript(m_frame)) { ChangeLocationTo(active_frame->loader()->completeURL(url), true); } } @@ -260,7 +258,7 @@ void Location::assign(const String& url) { if (!m_frame) return; - Frame* active_frame = JSBridge::retrieveActiveFrame(); + Frame* active_frame = ScriptController::retrieveActiveFrame(); if (!active_frame) return; @@ -268,7 +266,7 @@ void Location::assign(const String& url) { return; if (!parseURL(url).startsWith("javascript:", false) || - JSBridge::isSafeScript(m_frame)) { + ScriptController::isSafeScript(m_frame)) { ChangeLocationTo(active_frame->loader()->completeURL(url), false); } } diff --git a/webkit/port/page/Location.h b/webkit/port/page/Location.h index a6fa362..ef77651 100644 --- a/webkit/port/page/Location.h +++ b/webkit/port/page/Location.h @@ -13,7 +13,10 @@ namespace WebCore { class Location : public RefCounted<Location> { public: - Location(Frame* frame) : m_frame(frame) { } + static PassRefPtr<Location> create(Frame* frame) + { + return adoptRef(new Location(frame)); + } Frame* frame() { return m_frame; } @@ -50,6 +53,8 @@ class Location : public RefCounted<Location> { void disconnectFrame() { m_frame = 0; } private: + Location(Frame* frame) : m_frame(frame) { } + Frame* m_frame; friend class WindowV8; diff --git a/webkit/port/page/Navigator.h b/webkit/port/page/Navigator.h index 983daea..40e3a9b 100644 --- a/webkit/port/page/Navigator.h +++ b/webkit/port/page/Navigator.h @@ -8,8 +8,8 @@ #include "Language.h" #include "CookieJar.h" #include "Frame.h" -#include "Document.h" #include "FrameLoader.h" +#include "Document.h" #include "Settings.h" #include "PluginInfoStore.h" #include <wtf/RefCounted.h> @@ -177,7 +177,10 @@ class PluginArray : public ArrayOf<Plugin>, public RefCounted<PluginArray> { class Navigator : public RefCounted<Navigator> { public: - explicit Navigator(Frame* frame); + static PassRefPtr<Navigator> create(Frame* frame) + { + return adoptRef(new Navigator(frame)); + } ~Navigator(); String appCodeName() const { return "Mozilla"; } String appName() const { return "Netscape"; } @@ -248,6 +251,8 @@ class Navigator : public RefCounted<Navigator> { void disconnectFrame() { m_frame = NULL; } private: + Navigator(Frame* frame); + Frame* m_frame; RefPtr<MimeTypeArray> m_mimetypes; RefPtr<PluginArray> m_plugins; diff --git a/webkit/port/page/inspector/InspectorController.cpp b/webkit/port/page/inspector/InspectorController.cpp index a34ad33..4a74d4d 100644 --- a/webkit/port/page/inspector/InspectorController.cpp +++ b/webkit/port/page/inspector/InspectorController.cpp @@ -56,13 +56,13 @@ #include "GraphicsContext.h" #include "HTMLFrameOwnerElement.h" #include "InspectorClient.h" -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) #include "JSDOMWindow.h" #include "JSInspectedObjectWrapper.h" #include "JSInspectorCallbackWrapper.h" #include "JSNode.h" #include "JSRange.h" -#elif USE(V8_BINDING) +#elif USE(V8) #include "v8_proxy.h" #include "v8_binding.h" #endif @@ -79,7 +79,7 @@ #include "SystemTime.h" #include "TextEncoding.h" #include "TextIterator.h" -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) #include "kjs_proxy.h" #include <JavaScriptCore/APICast.h> #include <JavaScriptCore/JSLock.h> @@ -94,7 +94,7 @@ #include "JSDatabase.h" #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) using namespace KJS; using namespace std; #endif @@ -139,7 +139,7 @@ namespace bug1228513 { } } // namespace bug1228513 -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) // TODO(ojan): We probably need to implement these functions to get the wrapped JS calls // to the DOM working. static JSRetainPtr<JSStringRef> jsStringRef(const char* str) @@ -192,7 +192,7 @@ struct ConsoleMessage { { } -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) // TODO(ojan): I think we'll need something like this when we wrap JS calls to the DOM ConsoleMessage(MessageSource s, MessageLevel l, ExecState* exec, const List& args, unsigned li, const String& u) : source(s) @@ -210,7 +210,7 @@ struct ConsoleMessage { MessageSource source; MessageLevel level; String message; -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) Vector<ProtectedPtr<JSValue> > wrappedArguments; #endif unsigned line; @@ -220,7 +220,7 @@ struct ConsoleMessage { #pragma mark - #pragma mark XMLHttpRequestResource Class -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) struct XMLHttpRequestResource { XMLHttpRequestResource(KJS::UString& sourceString) { @@ -236,7 +236,7 @@ struct XMLHttpRequestResource { RefPtr<KJS::UString::Rep> sourceString; }; -#elif USE(V8_BINDING) +#elif USE(V8) struct XMLHttpRequestResource { XMLHttpRequestResource(const String& str) { @@ -274,9 +274,9 @@ struct InspectorResource : public RefCounted<InspectorResource> { ~InspectorResource() { -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) setScriptObject(0, 0); -#elif USE(V8_BINDING) +#elif USE(V8) setScriptObject(v8::Handle<v8::Object>()); #endif } @@ -313,7 +313,7 @@ struct InspectorResource : public RefCounted<InspectorResource> { } } -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) void setScriptObject(JSContextRef context, JSObjectRef newScriptObject) { if (scriptContext && scriptObject) @@ -326,7 +326,7 @@ struct InspectorResource : public RefCounted<InspectorResource> { if (context && newScriptObject) JSValueProtect(context, newScriptObject); } -#elif USE(V8_BINDING) +#elif USE(V8) void setScriptObject(v8::Handle<v8::Object> newScriptObject) { //XXXMB - the InspectorController and InspectorResource both maintain persistent handles @@ -343,12 +343,12 @@ struct InspectorResource : public RefCounted<InspectorResource> { // TODO(ojan): XHR requests show up in the inspector, but not their contents. // Something is wrong obviously, but not sure what. Not the highest priority // thing the inspector needs fixed right now though. -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) void setXMLHttpRequestProperties(KJS::UString& data) { xmlHttpRequestResource.set(new XMLHttpRequestResource(data)); } -#elif USE(V8_BINDING) +#elif USE(V8) void setXMLHttpRequestProperties(String& data) { xmlHttpRequestResource.set(new XMLHttpRequestResource(data)); @@ -358,9 +358,9 @@ struct InspectorResource : public RefCounted<InspectorResource> { String sourceString() const { if (xmlHttpRequestResource) { -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) return KJS::UString(xmlHttpRequestResource->sourceString); -#elif USE(V8_BINDING) +#elif USE(V8) return xmlHttpRequestResource->sourceString; #endif } @@ -389,7 +389,7 @@ struct InspectorResource : public RefCounted<InspectorResource> { { CachedCSSStyleSheet *sheet = reinterpret_cast<CachedCSSStyleSheet*>(cachedResource); - sourceString = sheet->sheet(); + sourceString = sheet->sheetText(); } break; case CachedResource::Script: @@ -423,10 +423,10 @@ struct InspectorResource : public RefCounted<InspectorResource> { HTTPHeaderMap responseHeaderFields; String mimeType; String suggestedFilename; -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) JSContextRef scriptContext; JSObjectRef scriptObject; -#elif USE(V8_BINDING) +#elif USE(V8) v8::Persistent<v8::Object> scriptObject; #endif long long expectedContentLength; @@ -440,9 +440,9 @@ struct InspectorResource : public RefCounted<InspectorResource> { double endTime; // Helper function to determine when the script object is initialized -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) inline bool hasScriptObject() const { return scriptObject; } -#elif USE(V8_BINDING) +#elif USE(V8) inline bool hasScriptObject() { return !scriptObject.IsEmpty(); } #endif @@ -455,7 +455,7 @@ protected: , loader(documentLoader) , frame(frame) , xmlHttpRequestResource(0) -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) , scriptContext(0) , scriptObject(0) #endif @@ -524,7 +524,7 @@ private: #pragma mark - #pragma mark JavaScript Callbacks -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef addSourceToFrame(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { JSValueRef undefined = JSValueMakeUndefined(ctx); @@ -583,7 +583,7 @@ static JSValueRef addSourceToFrame(JSContextRef ctx, JSObjectRef /*function*/, J return undefined; } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::addSourceToFrame(unsigned long identifier, Node* node) { RefPtr<InspectorResource> resource = this->resources().get(identifier); @@ -627,7 +627,7 @@ void InspectorController::addSourceToFrame(unsigned long identifier, Node* node) } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef getResourceDocumentNode(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { JSValueRef undefined = JSValueMakeUndefined(ctx); @@ -664,7 +664,7 @@ static JSValueRef getResourceDocumentNode(JSContextRef ctx, JSObjectRef /*functi JSValueRef documentValue = toRef(JSInspectedObjectWrapper::wrap(exec, toJS(exec, document))); return documentValue; } -#elif USE(V8_BINDING) +#elif USE(V8) Node* InspectorController::getResourceDocumentNode(unsigned long identifier) { RefPtr<InspectorResource> resource = this->resources().get(identifier); ASSERT(resource); @@ -684,7 +684,7 @@ Node* InspectorController::getResourceDocumentNode(unsigned long identifier) { } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef highlightDOMNode(JSContextRef context, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/) { JSValueRef undefined = JSValueMakeUndefined(context); @@ -704,7 +704,7 @@ static JSValueRef highlightDOMNode(JSContextRef context, JSObjectRef /*function* return undefined; } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::highlightDOMNode(Node* node) { if (!enabled()) @@ -715,7 +715,7 @@ void InspectorController::highlightDOMNode(Node* node) } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef hideDOMNodeHighlight(JSContextRef context, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* /*exception*/) { JSValueRef undefined = JSValueMakeUndefined(context); @@ -728,7 +728,7 @@ static JSValueRef hideDOMNodeHighlight(JSContextRef context, JSObjectRef /*funct return undefined; } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::hideDOMNodeHighlight() { if (!enabled()) @@ -738,7 +738,7 @@ void InspectorController::hideDOMNodeHighlight() } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef loaded(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/) { InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject)); @@ -748,13 +748,13 @@ static JSValueRef loaded(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef controller->scriptObjectReady(); return JSValueMakeUndefined(ctx); } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::loaded() { scriptObjectReady(); } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef unloading(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/) { InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject)); @@ -764,12 +764,12 @@ static JSValueRef unloading(JSContextRef ctx, JSObjectRef /*function*/, JSObject controller->close(); return JSValueMakeUndefined(ctx); } -#elif USE(V8_BINDING) +#elif USE(V8) // We don't need to implement this because we just map windowUnloading to // InspectorController::close in the IDL file. #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef attach(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/) { InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject)); @@ -779,13 +779,13 @@ static JSValueRef attach(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef controller->attachWindow(); return JSValueMakeUndefined(ctx); } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::attach() { attachWindow(); } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef detach(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/) { InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject)); @@ -795,13 +795,13 @@ static JSValueRef detach(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef controller->detachWindow(); return JSValueMakeUndefined(ctx); } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::detach() { detachWindow(); } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef search(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject)); @@ -868,7 +868,7 @@ static JSValueRef search(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef return result; } -#elif USE(V8_BINDING) +#elif USE(V8) // TODO(ojan): See when/if this works. We should either make it work or remove it. void InspectorController::search(Node* node, const String& target) { v8::HandleScope handle_scope; @@ -963,7 +963,7 @@ static JSValueRef databaseTableNames(JSContextRef ctx, JSObjectRef /*function*/, } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef inspectedWindow(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/) { InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject)); @@ -974,7 +974,7 @@ static JSValueRef inspectedWindow(JSContextRef ctx, JSObjectRef /*function*/, JS JSLock lock; return toRef(JSInspectedObjectWrapper::wrap(inspectedWindow->globalExec(), inspectedWindow)); } -#elif USE(V8_BINDING) +#elif USE(V8) DOMWindow* InspectorController::inspectedWindow() { // Can be null if page was already destroyed. if (!m_inspectedPage) @@ -983,7 +983,7 @@ DOMWindow* InspectorController::inspectedWindow() { } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef localizedStrings(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/) { InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject)); @@ -996,11 +996,11 @@ static JSValueRef localizedStrings(JSContextRef ctx, JSObjectRef /*function*/, J return JSValueMakeString(ctx, jsStringRef(url).get()); } -#elif USE(V8_BINDING) +#elif USE(V8) // TODO(ojan): Figure out how/if to implement this function. #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef platform(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments[]*/, JSValueRef* /*exception*/) { #if PLATFORM(MAC) @@ -1025,13 +1025,13 @@ static JSValueRef platform(JSContextRef ctx, JSObjectRef /*function*/, JSObjectR return platformValue; } -#elif USE(V8_BINDING) +#elif USE(V8) String InspectorController::platform() const { return String("windows"); } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef moveByUnrestricted(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject)); @@ -1053,11 +1053,11 @@ static JSValueRef moveByUnrestricted(JSContextRef ctx, JSObjectRef /*function*/, return JSValueMakeUndefined(ctx); } -#elif USE(V8_BINDING) +#elif USE(V8) // TODO(ojan): Figure out how/if to implement this function. #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef wrapCallback(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject)); @@ -1070,12 +1070,12 @@ static JSValueRef wrapCallback(JSContextRef ctx, JSObjectRef /*function*/, JSObj JSLock lock; return toRef(JSInspectorCallbackWrapper::wrap(toJS(ctx), toJS(arguments[0]))); } -#elif USE(V8_BINDING) +#elif USE(V8) // TODO(ojan): Figure out how to wrap JS calls to the DOM with V8. // Eventually, get it working over IPC. #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef startDebuggingAndReloadInspectedPage(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/) { InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject)); @@ -1086,11 +1086,11 @@ static JSValueRef startDebuggingAndReloadInspectedPage(JSContextRef ctx, JSObjec return JSValueMakeUndefined(ctx); } -#elif USE(V8_BINDING) +#elif USE(V8) // TODO(ojan): Figure out how/if to implement this function. #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef stopDebugging(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/) { InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject)); @@ -1101,11 +1101,11 @@ static JSValueRef stopDebugging(JSContextRef ctx, JSObjectRef /*function*/, JSOb return JSValueMakeUndefined(ctx); } -#elif USE(V8_BINDING) +#elif USE(V8) // TODO(ojan): Figure out how/if to implement this function. #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSValueRef debuggerAttached(JSContextRef ctx, JSObjectRef /*function*/, JSObjectRef thisObject, size_t /*argumentCount*/, const JSValueRef[] /*arguments*/, JSValueRef* /*exception*/) { InspectorController* controller = reinterpret_cast<InspectorController*>(JSObjectGetPrivate(thisObject)); @@ -1113,7 +1113,7 @@ static JSValueRef debuggerAttached(JSContextRef ctx, JSObjectRef /*function*/, J return JSValueMakeUndefined(ctx); return JSValueMakeBoolean(ctx, controller->debuggerAttached()); } -#elif USE(V8_BINDING) +#elif USE(V8) // TODO(ojan): Figure out how/if to implement this function. #endif @@ -1125,14 +1125,14 @@ InspectorController::InspectorController(Page* page, InspectorClient* client) , m_inspectedPage(page) , m_client(client) , m_page(0) -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) , m_scriptObject(0) // is an uninitialized V8 object , m_controllerScriptObject(0) // is equivalent to |this| , m_scriptContext(0) // isn't necessary for V8 #endif , m_windowVisible(false) , m_debuggerAttached(false) - , m_showAfterVisible(FocusedNodeDocumentPanel) + , m_showAfterVisible(ElementsPanel) , m_nextIdentifier(-2) , m_trackResources(false) { @@ -1145,7 +1145,7 @@ InspectorController::~InspectorController() m_bug1228513_inspectorState = bug1228513::DELETED; m_client->inspectorDestroyed(); -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) if (m_scriptContext) { JSValueRef exception = 0; @@ -1215,7 +1215,7 @@ void InspectorController::inspect(Node* node) m_nodeToFocus = node; if (!hasScriptObject()) { - m_showAfterVisible = FocusedNodeDocumentPanel; + m_showAfterVisible = ElementsPanel; return; } @@ -1223,7 +1223,7 @@ void InspectorController::inspect(Node* node) focusNode(); } -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) void InspectorController::focusNode() { if (!enabled()) @@ -1263,7 +1263,7 @@ void InspectorController::focusNode() JSObjectCallAsFunction(m_scriptContext, function, m_scriptObject, 1, &arg0, &exception); HANDLE_EXCEPTION(exception); } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::focusNode() { if (!enabled() || !m_nodeToFocus) @@ -1320,10 +1320,10 @@ void InspectorController::setWindowVisible(bool visible) m_windowVisible = visible; -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) if (!m_scriptContext || !m_scriptObject) return; -#elif USE(V8_BINDING) +#elif USE(V8) if (!hasScriptObject()) return; #endif @@ -1334,12 +1334,12 @@ void InspectorController::setWindowVisible(bool visible) focusNode(); if (m_showAfterVisible == ConsolePanel) showConsole(); - else if (m_showAfterVisible == TimelinePanel) + else if (m_showAfterVisible == ResourcesPanel) showTimeline(); } else resetScriptObjects(); - m_showAfterVisible = FocusedNodeDocumentPanel; + m_showAfterVisible = ElementsPanel; } void InspectorController::enableTrackResources(bool trackResources) @@ -1357,7 +1357,7 @@ void InspectorController::enableTrackResources(bool trackResources) } -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) void InspectorController::addMessageToConsole(MessageSource source, MessageLevel level, ExecState* exec, const List& arguments, unsigned lineNumber, const String& sourceURL) { if (!enabled()) @@ -1412,7 +1412,7 @@ void InspectorController::detachWindow() m_client->detachWindow(); } -#if USE(V8_BINDING) +#if USE(V8) void InspectorController::setScriptObject(v8::Handle<v8::Object> newScriptObject) { if (hasScriptObject()) { @@ -1425,7 +1425,35 @@ void InspectorController::setScriptObject(v8::Handle<v8::Object> newScriptObject } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) +void InspectorController::inspectedWindowScriptObjectCleared(Frame* frame) +{ + if (!enabled() || !m_scriptContext || !m_scriptObject) + return; + + JSDOMWindow* win = toJSDOMWindow(frame); + ExecState* exec = win->globalExec(); + + JSValueRef arg0; + + { + KJS::JSLock lock(false); + arg0 = toRef(JSInspectedObjectWrapper::wrap(exec, win)); + } + + JSValueRef exception = 0; + callFunction(m_scriptContext, m_scriptObject, "inspectedWindowCleared", 1, &arg0, exception); +} +#elif USE(V8) +void InspectorController::inspectedWindowScriptObjectCleared(Frame* frame) +{ + // TODO(tc): We need to call inspectedWindowCleared, but that won't matter + // until we merge in inspector.js as well. + notImplemented(); +} +#endif + +#if USE(JSC) void InspectorController::windowScriptObjectAvailable() { if (!m_page || !enabled()) @@ -1473,7 +1501,7 @@ void InspectorController::windowScriptObjectAvailable() JSObjectSetProperty(m_scriptContext, global, jsStringRef("InspectorController").get(), m_controllerScriptObject, kJSPropertyAttributeNone, 0); } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::windowScriptObjectAvailable() { if (!m_page || !enabled()) @@ -1490,7 +1518,7 @@ void InspectorController::windowScriptObjectAvailable() } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) void InspectorController::scriptObjectReady() { ASSERT(m_scriptContext); @@ -1521,7 +1549,7 @@ void InspectorController::scriptObjectReady() // Make sure our window is visible now that the page loaded showWindow(); } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::scriptObjectReady() { if (!m_page || !enabled()) @@ -1572,9 +1600,9 @@ void InspectorController::showConsole() return; } -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) callSimpleFunction(m_scriptContext, m_scriptObject, "showConsole"); -#elif USE(V8_BINDING) +#elif USE(V8) if (windowVisible()) { v8::HandleScope handle_scope; v8::Handle<v8::Context> context = V8Proxy::GetContext(m_page->mainFrame()); @@ -1600,13 +1628,13 @@ void InspectorController::showTimeline() show(); if (!hasScriptObject()) { - m_showAfterVisible = TimelinePanel; + m_showAfterVisible = ResourcesPanel; return; } -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) callSimpleFunction(m_scriptContext, m_scriptObject, "showTimeline"); -#elif USE(V8_BINDING) +#elif USE(V8) if (windowVisible()) { v8::HandleScope handle_scope; v8::Handle<v8::Context> context = V8Proxy::GetContext(m_page->mainFrame()); @@ -1633,7 +1661,7 @@ void InspectorController::close() closeWindow(); if (m_page) { m_page->setParentInspectorController(0); -#if USE(V8_BINDING) +#if USE(V8) v8::HandleScope handle_scope; v8::Handle<v8::Context> context = V8Proxy::GetContext(m_page->mainFrame()); v8::Context::Scope scope(context); @@ -1641,13 +1669,13 @@ void InspectorController::close() #endif } -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) ASSERT(m_scriptContext && m_scriptObject); JSValueUnprotect(m_scriptContext, m_scriptObject); #endif m_page = 0; -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) m_scriptObject = 0; m_scriptContext = 0; #endif @@ -1666,7 +1694,7 @@ void InspectorController::closeWindow() m_client->closeWindow(); } -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static void addHeaders(JSContextRef context, JSObjectRef object, const HTTPHeaderMap& headers, JSValueRef* exception) { ASSERT_ARG(context, context); @@ -1680,7 +1708,7 @@ static void addHeaders(JSContextRef context, JSObjectRef object, const HTTPHeade return; } } -#elif USE(V8_BINDING) +#elif USE(V8) static void addHeaders(v8::Handle<v8::Object> object, const HTTPHeaderMap& headers) { ASSERT_ARG(object, !object.IsEmpty()); @@ -1692,7 +1720,7 @@ static void addHeaders(v8::Handle<v8::Object> object, const HTTPHeaderMap& heade } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSObjectRef scriptObjectForRequest(JSContextRef context, const InspectorResource* resource, JSValueRef* exception) { ASSERT_ARG(context, context); @@ -1702,7 +1730,7 @@ static JSObjectRef scriptObjectForRequest(JSContextRef context, const InspectorR return object; } -#elif USE(V8_BINDING) +#elif USE(V8) static v8::Handle<v8::Object> scriptObjectForRequest(const InspectorResource* resource) { v8::Handle<v8::Object> object = v8::Object::New(); @@ -1711,7 +1739,7 @@ static v8::Handle<v8::Object> scriptObjectForRequest(const InspectorResource* re } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) static JSObjectRef scriptObjectForResponse(JSContextRef context, const InspectorResource* resource, JSValueRef* exception) { ASSERT_ARG(context, context); @@ -1721,7 +1749,7 @@ static JSObjectRef scriptObjectForResponse(JSContextRef context, const Inspector return object; } -#elif USE(V8_BINDING) +#elif USE(V8) static v8::Handle<v8::Object> scriptObjectForResponse(const InspectorResource* resource) { v8::Handle<v8::Object> object = v8::Object::New(); @@ -1730,7 +1758,7 @@ static v8::Handle<v8::Object> scriptObjectForResponse(const InspectorResource* r } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) JSObjectRef InspectorController::addScriptResource(InspectorResource* resource) { ASSERT_ARG(resource, resource); @@ -1791,7 +1819,7 @@ JSObjectRef InspectorController::addScriptResource(InspectorResource* resource) return resource->scriptObject; } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::addScriptResource(InspectorResource* resource) { ASSERT_ARG(resource, resource); @@ -1833,7 +1861,7 @@ void InspectorController::addScriptResource(InspectorResource* resource) } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) JSObjectRef InspectorController::addAndUpdateScriptResource(InspectorResource* resource) { ASSERT_ARG(resource, resource); @@ -1848,7 +1876,7 @@ JSObjectRef InspectorController::addAndUpdateScriptResource(InspectorResource* r updateScriptResource(resource, resource->finished, resource->failed); return scriptResource; } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::addAndUpdateScriptResource(InspectorResource* resource) { ASSERT_ARG(resource, resource); @@ -1862,7 +1890,7 @@ void InspectorController::addAndUpdateScriptResource(InspectorResource* resource } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) void InspectorController::removeScriptResource(InspectorResource* resource) { ASSERT(m_scriptContext); @@ -1892,7 +1920,7 @@ void InspectorController::removeScriptResource(InspectorResource* resource) JSObjectCallAsFunction(m_scriptContext, removeResourceFunction, m_scriptObject, 1, arguments, &exception); HANDLE_EXCEPTION(exception); } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::removeScriptResource(InspectorResource* resource) { ASSERT(hasScriptObject()); @@ -1932,7 +1960,7 @@ static void updateResourceResponse(InspectorResource* resource, const ResourceRe resource->suggestedFilename = response.suggestedFilename(); } -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) void InspectorController::updateScriptResourceRequest(InspectorResource* resource) { ASSERT(resource->scriptObject); @@ -1976,7 +2004,7 @@ void InspectorController::updateScriptResourceRequest(InspectorResource* resourc JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("mainResource").get(), mainResourceValue, kJSPropertyAttributeNone, &exception); HANDLE_EXCEPTION(exception); } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::updateScriptResourceRequest(InspectorResource* resource) { ASSERT(resource->hasScriptObject()); @@ -1998,7 +2026,7 @@ void InspectorController::updateScriptResourceRequest(InspectorResource* resourc } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) void InspectorController::updateScriptResourceResponse(InspectorResource* resource) { ASSERT(resource->scriptObject); @@ -2043,7 +2071,7 @@ void InspectorController::updateScriptResourceResponse(InspectorResource* resour JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("type").get(), typeValue, kJSPropertyAttributeNone, &exception); HANDLE_EXCEPTION(exception); } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::updateScriptResourceResponse(InspectorResource* resource) { ASSERT(resource->hasScriptObject()); @@ -2065,7 +2093,7 @@ void InspectorController::updateScriptResourceResponse(InspectorResource* resour } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) void InspectorController::updateScriptResource(InspectorResource* resource, int length) { ASSERT(resource->scriptObject); @@ -2080,7 +2108,7 @@ void InspectorController::updateScriptResource(InspectorResource* resource, int JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("contentLength").get(), lengthValue, kJSPropertyAttributeNone, &exception); HANDLE_EXCEPTION(exception); } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::updateScriptResource(InspectorResource* resource, int length) { ASSERT(resource->hasScriptObject()); @@ -2097,7 +2125,7 @@ void InspectorController::updateScriptResource(InspectorResource* resource, int } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) void InspectorController::updateScriptResource(InspectorResource* resource, bool finished, bool failed) { ASSERT(resource->scriptObject); @@ -2117,7 +2145,7 @@ void InspectorController::updateScriptResource(InspectorResource* resource, bool JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("finished").get(), finishedValue, kJSPropertyAttributeNone, &exception); HANDLE_EXCEPTION(exception); } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::updateScriptResource(InspectorResource* resource, bool finished, bool failed) { ASSERT(resource->hasScriptObject()); @@ -2134,7 +2162,7 @@ void InspectorController::updateScriptResource(InspectorResource* resource, bool } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) void InspectorController::updateScriptResource(InspectorResource* resource, double startTime, double responseReceivedTime, double endTime) { ASSERT(resource->scriptObject); @@ -2159,7 +2187,7 @@ void InspectorController::updateScriptResource(InspectorResource* resource, doub JSObjectSetProperty(m_scriptContext, resource->scriptObject, jsStringRef("endTime").get(), endTimeValue, kJSPropertyAttributeNone, &exception); HANDLE_EXCEPTION(exception); } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::updateScriptResource(InspectorResource* resource, double startTime, double responseReceivedTime, double endTime) { ASSERT(resource->hasScriptObject()); @@ -2177,7 +2205,7 @@ void InspectorController::updateScriptResource(InspectorResource* resource, doub } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) void InspectorController::populateScriptObjects() { ASSERT(m_scriptContext); @@ -2198,7 +2226,7 @@ void InspectorController::populateScriptObjects() addDatabaseScriptResource((*it).get()); #endif } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::populateScriptObjects() { ResourcesMap::iterator resourcesEnd = m_resources.end(); @@ -2307,7 +2335,7 @@ void InspectorController::removeDatabaseScriptResource(InspectorDatabaseResource } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) void InspectorController::addScriptConsoleMessage(const ConsoleMessage* message) { ASSERT_ARG(message, message); @@ -2363,7 +2391,7 @@ void InspectorController::addScriptConsoleMessage(const ConsoleMessage* message) JSObjectCallAsFunction(m_scriptContext, addMessage, m_scriptObject, 1, &messageObject, &exception); HANDLE_EXCEPTION(exception); } -#elif USE(V8_BINDING) +#elif USE(V8) void InspectorController::addScriptConsoleMessage(const ConsoleMessage* message) { ASSERT_ARG(message, message); @@ -2415,10 +2443,10 @@ void InspectorController::addScriptConsoleMessage(const ConsoleMessage* message) void InspectorController::resetScriptObjects() { -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) if (!m_scriptContext || !m_scriptObject) return; -#elif USE(V8_BINDING) +#elif USE(V8) if (!hasScriptObject()) return; #endif @@ -2426,9 +2454,9 @@ void InspectorController::resetScriptObjects() ResourcesMap::iterator resourcesEnd = m_resources.end(); for (ResourcesMap::iterator it = m_resources.begin(); it != resourcesEnd; ++it) { InspectorResource* resource = it->second.get(); -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) resource->setScriptObject(0, 0); -#elif USE(V8_BINDING) +#elif USE(V8) resource->setScriptObject(v8::Handle<v8::Object>()); #endif } @@ -2441,9 +2469,9 @@ void InspectorController::resetScriptObjects() } #endif -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) callSimpleFunction(m_scriptContext, m_scriptObject, "reset"); -#elif USE(V8_BINDING) +#elif USE(V8) v8::HandleScope handle_scope; v8::Handle<v8::Context> context = V8Proxy::GetContext(m_page->mainFrame()); v8::Context::Scope scope(context); @@ -2709,7 +2737,7 @@ void InspectorController::didFailLoading(DocumentLoader* loader, unsigned long i } } -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) void InspectorController::resourceRetrievedByXMLHttpRequest(unsigned long identifier, KJS::UString& sourceString) { if (!enabled()) @@ -2721,8 +2749,11 @@ void InspectorController::resourceRetrievedByXMLHttpRequest(unsigned long identi resource->setXMLHttpRequestProperties(sourceString); } -#elif USE(V8_BINDING) +#elif USE(V8) // TODO(ojan): Implement! +void InspectorController::resourceRetrievedByXMLHttpRequest(unsigned long identifier, String& sourceString) +{ +} #endif @@ -2858,7 +2889,7 @@ void InspectorController::drawNodeHighlight(GraphicsContext& context) const drawHighlightForBoxes(context, lineBoxRects, contentBox, paddingBox, borderBox, marginBox); } -#if USE(JAVASCRIPTCORE_BINDINGS) +#if USE(JSC) bool InspectorController::handleException(JSValueRef exception, unsigned lineNumber) const { if (!exception) @@ -2901,7 +2932,7 @@ void InspectorController::exceptionWasRaised(ExecState*, int /*sourceID*/, int / { } -#elif USE(V8_BINDING) +#elif USE(V8) // TODO(ojan): Implement! #endif diff --git a/webkit/port/platform/ClipboardUtilitiesWin.cpp b/webkit/port/platform/ClipboardUtilitiesWin.cpp index a35794f..f23c2fe 100644 --- a/webkit/port/platform/ClipboardUtilitiesWin.cpp +++ b/webkit/port/platform/ClipboardUtilitiesWin.cpp @@ -41,6 +41,20 @@ namespace WebCore { +FORMATETC* cfHDropFormat() +{ + static FORMATETC urlFormat = {CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + return &urlFormat; +} + +//Firefox text/html +static FORMATETC* texthtmlFormat() +{ + static UINT cf = RegisterClipboardFormat(L"text/html"); + static FORMATETC texthtmlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + return &texthtmlFormat; +} + HGLOBAL createGlobalData(const KURL& url, const String& title) { String mutableURL(url.string()); @@ -56,77 +70,86 @@ HGLOBAL createGlobalData(const KURL& url, const String& title) return cbData; } -HGLOBAL createGlobalData(String str) -{ - SIZE_T size = (str.length() + 1) * sizeof(UChar); - HGLOBAL cbData = ::GlobalAlloc(GPTR, size); - if (cbData) { - void* buffer = ::GlobalLock(cbData); - memcpy(buffer, str.charactersWithNullTermination(), size); - ::GlobalUnlock(cbData); - } - return cbData; +HGLOBAL createGlobalData(const String& str) +{ + HGLOBAL globalData = ::GlobalAlloc(GPTR, (str.length() + 1) * sizeof(UChar)); + if (!globalData) + return 0; + UChar* buffer = static_cast<UChar*>(::GlobalLock(globalData)); + memcpy(buffer, str.characters(), str.length() * sizeof(UChar)); + buffer[str.length()] = 0; + ::GlobalUnlock(globalData); + return globalData; } -HGLOBAL createGlobalData(CString str) +HGLOBAL createGlobalData(const Vector<char>& vector) { - SIZE_T size = str.length() * sizeof(char); - HGLOBAL cbData = ::GlobalAlloc(GPTR, size + 1); - if (cbData) { - char* buffer = static_cast<char*>(::GlobalLock(cbData)); - memcpy(buffer, str.data(), size); - buffer[size] = 0; - ::GlobalUnlock(cbData); - } - return cbData; + HGLOBAL globalData = ::GlobalAlloc(GPTR, vector.size() + 1); + if (!globalData) + return 0; + char* buffer = static_cast<char*>(::GlobalLock(globalData)); + memcpy(buffer, vector.data(), vector.size()); + buffer[vector.size()] = 0; + ::GlobalUnlock(globalData); + return globalData; +} + +static void append(Vector<char>& vector, const char* string) +{ + vector.append(string, strlen(string)); +} + +static void append(Vector<char>& vector, const CString& string) +{ + vector.append(string.data(), string.length()); } // Documentation for the CF_HTML format is available at http://msdn.microsoft.com/workshop/networking/clipboard/htmlclipboard.asp -DeprecatedCString markupToCF_HTML(const String& markup, const String& srcURL) +void markupToCF_HTML(const String& markup, const String& srcURL, Vector<char>& result) { - if (!markup.length()) - return DeprecatedCString(); + if (markup.isEmpty()) + return; - DeprecatedCString cf_html ("Version:0.9"); - DeprecatedCString startHTML ("\nStartHTML:"); - DeprecatedCString endHTML ("\nEndHTML:"); - DeprecatedCString startFragment ("\nStartFragment:"); - DeprecatedCString endFragment ("\nEndFragment:"); - DeprecatedCString sourceURL ("\nSourceURL:"); + #define MAX_DIGITS 10 + #define MAKE_NUMBER_FORMAT_1(digits) MAKE_NUMBER_FORMAT_2(digits) + #define MAKE_NUMBER_FORMAT_2(digits) "%0" #digits "u" + #define NUMBER_FORMAT MAKE_NUMBER_FORMAT_1(MAX_DIGITS) - bool shouldFillSourceURL = !srcURL.isEmpty() && (srcURL != "about:blank"); - if (shouldFillSourceURL) - sourceURL.append(srcURL.utf8().data()); + const char* header = "Version:0.9\n" + "StartHTML:" NUMBER_FORMAT "\n" + "EndHTML:" NUMBER_FORMAT "\n" + "StartFragment:" NUMBER_FORMAT "\n" + "EndFragment:" NUMBER_FORMAT "\n"; + const char* sourceURLPrefix = "SourceURL:"; - DeprecatedCString startMarkup ("\n<HTML>\n<BODY>\n<!--StartFragment-->\n"); - DeprecatedCString endMarkup ("\n<!--EndFragment-->\n</BODY>\n</HTML>"); + const char* startMarkup = "<HTML>\n<BODY>\n<!--StartFragment-->\n"; + const char* endMarkup = "\n<!--EndFragment-->\n</BODY>\n</HTML>"; - // calculate offsets - const unsigned UINT_MAXdigits = 10; // number of digits in UINT_MAX in base 10 - unsigned startHTMLOffset = cf_html.length() + startHTML.length() + endHTML.length() + startFragment.length() + endFragment.length() + (shouldFillSourceURL ? sourceURL.length() : 0) + (4*UINT_MAXdigits); - unsigned startFragmentOffset = startHTMLOffset + startMarkup.length(); + CString sourceURLUTF8 = srcURL == blankURL() ? "" : srcURL.utf8(); CString markupUTF8 = markup.utf8(); - unsigned endFragmentOffset = startFragmentOffset + markupUTF8.length(); - unsigned endHTMLOffset = endFragmentOffset + endMarkup.length(); - - // fill in needed data - startHTML.append(String::format("%010u", startHTMLOffset).deprecatedString().utf8()); - endHTML.append(String::format("%010u", endHTMLOffset).deprecatedString().utf8()); - startFragment.append(String::format("%010u", startFragmentOffset).deprecatedString().utf8()); - endFragment.append(String::format("%010u", endFragmentOffset).deprecatedString().utf8()); - startMarkup.append(markupUTF8.data()); - // create full cf_html string from the fragments - cf_html.append(startHTML); - cf_html.append(endHTML); - cf_html.append(startFragment); - cf_html.append(endFragment); - if (shouldFillSourceURL) - cf_html.append(sourceURL); - cf_html.append(startMarkup); - cf_html.append(endMarkup); + // calculate offsets + unsigned startHTMLOffset = strlen(header) - strlen(NUMBER_FORMAT) * 4 + MAX_DIGITS * 4; + if (sourceURLUTF8.length()) + startHTMLOffset += strlen(sourceURLPrefix) + sourceURLUTF8.length() + 1; + unsigned startFragmentOffset = startHTMLOffset + strlen(startMarkup); + unsigned endFragmentOffset = startFragmentOffset + markupUTF8.length(); + unsigned endHTMLOffset = endFragmentOffset + strlen(endMarkup); - return cf_html; + append(result, String::format(header, startHTMLOffset, endHTMLOffset, startFragmentOffset, endFragmentOffset).utf8()); + if (sourceURLUTF8.length()) { + append(result, sourceURLPrefix); + append(result, sourceURLUTF8); + result.append('\n'); + } + append(result, startMarkup); + append(result, markupUTF8); + append(result, endMarkup); + + #undef MAX_DIGITS + #undef MAKE_NUMBER_FORMAT_1 + #undef MAKE_NUMBER_FORMAT_2 + #undef NUMBER_FORMAT } String urlToMarkup(const KURL& url, const String& title) @@ -156,7 +179,7 @@ String urlToImageMarkup(const KURL& url, const String& altStr) { void replaceNewlinesWithWindowsStyleNewlines(String& str) { static const UChar Newline = '\n'; - static const String WindowsNewline("\r\n"); + static const char* const WindowsNewline("\r\n"); str.replace(Newline, WindowsNewline); } @@ -167,6 +190,60 @@ void replaceNBSPWithSpace(String& str) str.replace(NonBreakingSpaceCharacter, SpaceCharacter); } +FORMATETC* urlWFormat() +{ + static UINT cf = RegisterClipboardFormat(L"UniformResourceLocatorW"); + static FORMATETC urlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + return &urlFormat; +} + +FORMATETC* urlFormat() +{ + static UINT cf = RegisterClipboardFormat(L"UniformResourceLocator"); + static FORMATETC urlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + return &urlFormat; +} + +FORMATETC* plainTextFormat() +{ + static FORMATETC textFormat = {CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + return &textFormat; +} + +FORMATETC* plainTextWFormat() +{ + static FORMATETC textFormat = {CF_UNICODETEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + return &textFormat; +} + +FORMATETC* filenameWFormat() +{ + static UINT cf = RegisterClipboardFormat(L"FileNameW"); + static FORMATETC urlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + return &urlFormat; +} + +FORMATETC* filenameFormat() +{ + static UINT cf = RegisterClipboardFormat(L"FileName"); + static FORMATETC urlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + return &urlFormat; +} + +//MSIE HTML Format +FORMATETC* htmlFormat() +{ + static UINT cf = RegisterClipboardFormat(L"HTML Format"); + static FORMATETC htmlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + return &htmlFormat; +} + +FORMATETC* smartPasteFormat() +{ + static UINT cf = RegisterClipboardFormat(L"WebKit Smart Paste Format"); + static FORMATETC htmlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + return &htmlFormat; +} PassRefPtr<DocumentFragment> fragmentFromFilenames(Document*, const IDataObject*) { diff --git a/webkit/port/platform/ClipboardUtilitiesWin.h b/webkit/port/platform/ClipboardUtilitiesWin.h index 7cfe569..bc8fb0a 100644 --- a/webkit/port/platform/ClipboardUtilitiesWin.h +++ b/webkit/port/platform/ClipboardUtilitiesWin.h @@ -32,17 +32,25 @@ namespace WebCore { -class CString; -class DeprecatedCString; class Document; class KURL; class String; -HGLOBAL createGlobalData(String str); -HGLOBAL createGlobalData(CString str); +HGLOBAL createGlobalData(const String&); +HGLOBAL createGlobalData(const Vector<char>&); HGLOBAL createGlobalData(const KURL& url, const String& title); -DeprecatedCString markupToCF_HTML(const String& markup, const String& srcURL); +FORMATETC* urlWFormat(); +FORMATETC* urlFormat(); +FORMATETC* plainTextWFormat(); +FORMATETC* plainTextFormat(); +FORMATETC* filenameWFormat(); +FORMATETC* filenameFormat(); +FORMATETC* htmlFormat(); +FORMATETC* cfHDropFormat(); +FORMATETC* smartPasteFormat(); + +void markupToCF_HTML(const String& markup, const String& srcURL, Vector<char>& result); String urlToMarkup(const KURL& url, const String& title); String urlToImageMarkup(const KURL& url, const String& altStr); diff --git a/webkit/port/platform/ClipboardWin.cpp b/webkit/port/platform/ClipboardWin.cpp index a3b83f9..0383610 100644 --- a/webkit/port/platform/ClipboardWin.cpp +++ b/webkit/port/platform/ClipboardWin.cpp @@ -33,9 +33,9 @@ #include "ClipboardUtilitiesWin.h" #include "csshelper.h" #include "CString.h" -#include "DeprecatedString.h" #include "Document.h" #include "DragData.h" +#include "Editor.h" #include "Element.h" #include "EventHandler.h" #include "Frame.h" @@ -52,11 +52,13 @@ #include "Range.h" #include "RenderImage.h" #include "ResourceResponse.h" +#include "StringBuilder.h" #include "StringHash.h" #include "WCDataObject.h" #include <wtf/RefPtr.h> #pragma warning(pop) +#undef LOG #include "base/clipboard_util.h" #include "base/string_util.h" #include "googleurl/src/gurl.h" @@ -133,7 +135,7 @@ static String filesystemPathFromUrlOrTitle(const String& url, const String& titl // The filename for any content based drag should be the last element of // the path. If we can't find it, or we're coming up with the name for a link // we just use the entire url. - KURL kurl(url.deprecatedString()); + KURL kurl(url); String lastComponent; if (!isLink && !(lastComponent = kurl.lastPathComponent()).isEmpty()) { len = min<DWORD>(MAX_PATH - 1, lastComponent.length()); @@ -219,11 +221,10 @@ static HGLOBAL createGlobalHDropContent(const KURL& url, String& fileName, Share WCHAR filePath[MAX_PATH]; if (url.isLocalFile()) { - DeprecatedString path = url.path(); + String localPath = url.path(); // windows does not enjoy a leading slash on paths - if (path[0] == '/') - path = path.mid(1); - String localPath = path.ascii(); + if (localPath[0] == '/') + localPath = localPath.substring(1); LPCTSTR localPathStr = localPath.charactersWithNullTermination(); if (wcslen(localPathStr) + 1 < MAX_PATH) wcscpy_s(filePath, MAX_PATH, localPathStr); @@ -310,6 +311,9 @@ static HGLOBAL createGlobalUrlFileDescriptor(const String& url, const String& ti static HGLOBAL createGlobalImageFileDescriptor(const String& url, const String& title, CachedImage* image) { + ASSERT_ARG(image, image); + ASSERT(image->image()->data()); + HRESULT hr = S_OK; HGLOBAL memObj = 0; String fsPath; @@ -323,11 +327,8 @@ static HGLOBAL createGlobalImageFileDescriptor(const String& url, const String& fgd->fgd[0].dwFlags = FD_FILESIZE; fgd->fgd[0].nFileSizeLow = image->image()->data()->size(); - // Note: We fail to get the extension if we're running in the sandbox. - String extension = WebCore::MIMETypeRegistry::getPreferredExtensionForMIMEType( - image->response().mimeType()); - if (!extension.isEmpty()) - extension = "." + extension; + String extension("."); + extension += WebCore::MIMETypeRegistry::getPreferredExtensionForMIMEType(image->response().mimeType()); const String& preferredTitle = title.isEmpty() ? image->response().suggestedFilename() : title; fsPath = filesystemPathFromUrlOrTitle(url, preferredTitle, extension.isEmpty() ? 0 : (TCHAR*)extension.charactersWithNullTermination(), false); @@ -406,14 +407,23 @@ ClipboardWin::~ClipboardWin() { } +PassRefPtr<ClipboardWin> ClipboardWin::create(bool isForDragging, IDataObject* dataObject, ClipboardAccessPolicy policy) +{ + return adoptRef(new ClipboardWin(isForDragging, dataObject, policy)); +} + +PassRefPtr<ClipboardWin> ClipboardWin::create(bool isForDragging, WCDataObject* dataObject, ClipboardAccessPolicy policy) +{ + return adoptRef(new ClipboardWin(isForDragging, dataObject, policy)); +} + static bool writeURL(WCDataObject *data, const KURL& url, String title, bool withPlainText, bool withHTML) { ASSERT(data); - ASSERT(!url.isEmpty()); - - if (!url.isValid()) - return false; + if (url.isEmpty()) + return false; + if (title.isEmpty()) { title = url.lastPathComponent(); if (title.isEmpty()) @@ -431,8 +441,10 @@ static bool writeURL(WCDataObject *data, const KURL& url, String title, bool wit success = true; if (withHTML) { - medium.hGlobal = createGlobalData(markupToCF_HTML(urlToMarkup(url, title), "")); - if (medium.hGlobal && FAILED(data->SetData(ClipboardUtil::GetHtmlFormat(), &medium, TRUE))) + Vector<char> cfhtmlData; + markupToCF_HTML(urlToMarkup(url, title), "", cfhtmlData); + medium.hGlobal = createGlobalData(cfhtmlData); + if (medium.hGlobal && FAILED(data->SetData(htmlFormat(), &medium, TRUE))) ::GlobalFree(medium.hGlobal); else success = true; @@ -516,21 +528,19 @@ String ClipboardWin::getData(const String& type, bool& success) const return ""; } -bool ClipboardWin::setData(const String &type, const String &data) +bool ClipboardWin::setData(const String& type, const String& data) { - //FIXME: Need to be able to write to the system clipboard <rdar://problem/5015941> + // FIXME: Need to be able to write to the system clipboard <rdar://problem/5015941> ASSERT(isForDragging()); if (policy() != ClipboardWritable || !m_writableDataObject) return false; ClipboardDataType winType = clipboardTypeFromMIMEType(type); - if (winType == ClipboardDataTypeURL) { - KURL url = data.deprecatedString(); - if (!url.isValid()) - return false; - return WebCore::writeURL(m_writableDataObject.get(), url, String(), false, true); - } else if ( winType == ClipboardDataTypeText) { + if (winType == ClipboardDataTypeURL) + return WebCore::writeURL(m_writableDataObject.get(), KURL(data), String(), false, true); + + if (winType == ClipboardDataTypeText) { STGMEDIUM medium = {0}; medium.tymed = TYMED_HGLOBAL; medium.hGlobal = createGlobalData(data); @@ -595,10 +605,10 @@ void ClipboardWin::setDragImage(CachedImage* image, Node *node, const IntPoint & return; if (m_dragImage) - m_dragImage->deref(this); + m_dragImage->removeClient(this); m_dragImage = image; if (m_dragImage) - m_dragImage->ref(this); + m_dragImage->addClient(this); m_dragLoc = loc; m_dragImageElement = node; @@ -627,7 +637,8 @@ DragImageRef ClipboardWin::createDragImage(IntPoint& loc) const static String imageToMarkup(const String& url, Element* element) { - String markup("<img src=\""); + StringBuilder markup; + markup.append("<img src=\""); markup.append(url); markup.append("\""); // Copy over attributes. If we are dragging an image, we expect things like @@ -641,12 +652,14 @@ static String imageToMarkup(const String& url, Element* element) markup.append(" "); markup.append(attr->localName()); markup.append("=\""); - markup.append(attr->value().deprecatedString().replace("\"", """)); + String escapedAttr = attr->value(); + escapedAttr.replace("\"", """); + markup.append(escapedAttr); markup.append("\""); } markup.append("/>"); - return markup; + return markup.toString(); } static CachedImage* getCachedImage(Element* element) @@ -672,7 +685,7 @@ static void writeImageToDataObject(IDataObject* dataObject, Element* element, co return; SharedBuffer* imageBuffer = cachedImage->image()->data(); - if (!imageBuffer->size()) + if (!imageBuffer || !imageBuffer->size()) return; HGLOBAL imageFileDescriptor = createGlobalImageFileDescriptor(url.string(), element->getAttribute(altAttr), cachedImage); @@ -691,8 +704,6 @@ static void writeImageToDataObject(IDataObject* dataObject, Element* element, co HGLOBAL hDropContent = createGlobalHDropContent(url, fileName, imageBuffer); writeFileToDataObject(dataObject, imageFileDescriptor, imageFileContent, hDropContent); - // TODO(tc): Also write the mime type to the dataObject so we can - // fix the filename once we're back in the browser process. } void ClipboardWin::declareAndWriteDragImage(Element* element, const KURL& url, const String& title, Frame* frame) @@ -716,8 +727,10 @@ void ClipboardWin::declareAndWriteDragImage(Element* element, const KURL& url, c ExceptionCode ec = 0; // Put img tag on the clipboard referencing the image - medium.hGlobal = createGlobalData(markupToCF_HTML(imageToMarkup(fullURL, element), "")); - if (medium.hGlobal && FAILED(m_writableDataObject->SetData(ClipboardUtil::GetHtmlFormat(), &medium, TRUE))) + Vector<char> data; + markupToCF_HTML(imageToMarkup(fullURL, element), "", data); + medium.hGlobal = createGlobalData(data); + if (medium.hGlobal && FAILED(m_writableDataObject->SetData(htmlFormat(), &medium, TRUE))) ::GlobalFree(medium.hGlobal); } @@ -751,16 +764,23 @@ void ClipboardWin::writeRange(Range* selectedRange, Frame* frame) medium.tymed = TYMED_HGLOBAL; ExceptionCode ec = 0; - medium.hGlobal = createGlobalData(markupToCF_HTML(createMarkup(selectedRange, 0, AnnotateForInterchange), selectedRange->startContainer(ec)->document()->url())); - if (medium.hGlobal && FAILED(m_writableDataObject->SetData(ClipboardUtil::GetHtmlFormat(), &medium, TRUE))) + Vector<char> data; + markupToCF_HTML(createMarkup(selectedRange, 0, AnnotateForInterchange), + selectedRange->startContainer(ec)->document()->url().string(), data); + medium.hGlobal = createGlobalData(data); + if (medium.hGlobal && FAILED(m_writableDataObject->SetData(htmlFormat(), &medium, TRUE))) ::GlobalFree(medium.hGlobal); String str = frame->selectedText(); replaceNewlinesWithWindowsStyleNewlines(str); replaceNBSPWithSpace(str); medium.hGlobal = createGlobalData(str); - if (medium.hGlobal && FAILED(m_writableDataObject->SetData(ClipboardUtil::GetPlainTextWFormat(), &medium, TRUE))) + if (medium.hGlobal && FAILED(m_writableDataObject->SetData(plainTextWFormat(), &medium, TRUE))) ::GlobalFree(medium.hGlobal); + + medium.hGlobal = 0; + if (frame->editor()->canSmartCopyOrDelete()) + m_writableDataObject->SetData(smartPasteFormat(), &medium, TRUE); } bool ClipboardWin::hasData() diff --git a/webkit/port/platform/ClipboardWin.h b/webkit/port/platform/ClipboardWin.h index 0d6e448..a52c242 100644 --- a/webkit/port/platform/ClipboardWin.h +++ b/webkit/port/platform/ClipboardWin.h @@ -43,9 +43,10 @@ namespace WebCore { // State available during IE's events for drag and drop and copy/paste class ClipboardWin : public Clipboard, public CachedResourceClient { public: - ClipboardWin(bool isForDragging, IDataObject* dataObject, ClipboardAccessPolicy policy); - ClipboardWin(bool isForDragging, WCDataObject* dataObject, ClipboardAccessPolicy policy); ~ClipboardWin(); + + static PassRefPtr<ClipboardWin> create(bool isForDragging, IDataObject*, ClipboardAccessPolicy); + static PassRefPtr<ClipboardWin> create(bool isForDragging, WCDataObject*, ClipboardAccessPolicy); void clearData(const String& type); void clearAllData(); @@ -67,6 +68,9 @@ namespace WebCore { COMPtr<IDataObject> dataObject() { return m_dataObject; } private: + ClipboardWin(bool isForDragging, IDataObject*, ClipboardAccessPolicy); + ClipboardWin(bool isForDragging, WCDataObject*, ClipboardAccessPolicy); + void resetFromClipboard(); void setDragImage(CachedImage*, Node*, const IntPoint&); COMPtr<IDataObject> m_dataObject; diff --git a/webkit/port/platform/Cursor.h b/webkit/port/platform/Cursor.h index 7dd4700..c976ea9 100644 --- a/webkit/port/platform/Cursor.h +++ b/webkit/port/platform/Cursor.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,11 +27,14 @@ #define Cursor_h #include <wtf/Platform.h> -#include "webkit/glue/webcursor.h" #if PLATFORM(WIN) +#include "webkit/glue/webcursor.h" typedef struct HICON__* HICON; typedef HICON HCURSOR; +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> #elif PLATFORM(GTK) #include <gdk/gdk.h> #elif PLATFORM(QT) @@ -46,6 +49,10 @@ class NSCursor; #endif #endif +#if PLATFORM(WX) +class wxCursor; +#endif + namespace WebCore { class Image; @@ -59,6 +66,8 @@ namespace WebCore { typedef GdkCursor* PlatformCursor; #elif PLATFORM(QT) && !defined(QT_NO_CURSOR) typedef QCursor PlatformCursor; +#elif PLATFORM(WX) + typedef wxCursor* PlatformCursor; #else typedef void* PlatformCursor; #endif @@ -66,14 +75,10 @@ namespace WebCore { class Cursor { public: Cursor() -#if !PLATFORM(QT) - : m_impl(WebCursor::ARROW) -#endif { } Cursor(Image*, const IntPoint& hotspot); Cursor(const Cursor&); - ~Cursor(); Cursor& operator=(const Cursor&); @@ -81,7 +86,7 @@ namespace WebCore { PlatformCursor impl() const { return m_impl; } private: - WebCursor m_impl; + PlatformCursor m_impl; }; const Cursor& pointerCursor(); @@ -105,6 +110,15 @@ namespace WebCore { const Cursor& northWestSouthEastResizeCursor(); const Cursor& columnResizeCursor(); const Cursor& rowResizeCursor(); + const Cursor& middlePanningCursor(); + const Cursor& eastPanningCursor(); + const Cursor& northPanningCursor(); + const Cursor& northEastPanningCursor(); + const Cursor& northWestPanningCursor(); + const Cursor& southPanningCursor(); + const Cursor& southEastPanningCursor(); + const Cursor& southWestPanningCursor(); + const Cursor& westPanningCursor(); const Cursor& verticalTextCursor(); const Cursor& cellCursor(); const Cursor& contextMenuCursor(); diff --git a/webkit/port/platform/CursorWin.cpp b/webkit/port/platform/CursorWin.cpp index e5b31eb..884c464d 100644 --- a/webkit/port/platform/CursorWin.cpp +++ b/webkit/port/platform/CursorWin.cpp @@ -29,7 +29,10 @@ #include "Image.h" #include "IntPoint.h" #include "NativeImageSkia.h" +#include "NotImplemented.h" + #include "webkit/glue/webkit_resources.h" +#include "webkit/glue/webkit_glue.h" #define ALPHA_CURSORS @@ -42,14 +45,15 @@ Cursor::Cursor(const Cursor& other) Cursor::Cursor(Image* img, const IntPoint& hotspot) { - // If we don't have a valid bitmap, then fallback to the default - // cursor (ARROW). - NativeImageSkia* bitmap = img->getBitmap(); - if (bitmap) { + // If we don't have a valid bitmap, then fallback to the default + // cursor (ARROW). + NativeImageSkia* bitmap = img->nativeImageForCurrentFrame(); + if (!bitmap) + return; + m_impl.set_type(WebCursor::CUSTOM); m_impl.set_hotspot(hotspot.x(), hotspot.y()); m_impl.set_bitmap(*bitmap); - } } Cursor::~Cursor() @@ -187,6 +191,69 @@ const Cursor& rowResizeCursor() return c; } +const Cursor& middlePanningCursor() +{ + SkBitmap* bitmap = webkit_glue::GetBitmapResource(IDC_PAN_MIDDLE); + static Cursor c = WebCursor(bitmap, 7, 7); + return c; +} + +const Cursor& eastPanningCursor() +{ + SkBitmap* bitmap = webkit_glue::GetBitmapResource(IDC_PAN_EAST); + static Cursor c = WebCursor(bitmap, 7, 7); + return c; +} + +const Cursor& northPanningCursor() +{ + SkBitmap* bitmap = webkit_glue::GetBitmapResource(IDC_PAN_NORTH); + static Cursor c = WebCursor(bitmap, 7, 7); + return c; +} + +const Cursor& northEastPanningCursor() +{ + SkBitmap* bitmap = webkit_glue::GetBitmapResource(IDC_PAN_NORTH_EAST); + static Cursor c = WebCursor(bitmap, 7, 7); + return c; +} + +const Cursor& northWestPanningCursor() +{ + SkBitmap* bitmap = webkit_glue::GetBitmapResource(IDC_PAN_NORTH_WEST); + static Cursor c = WebCursor(bitmap, 7, 7); + return c; +} + +const Cursor& southPanningCursor() +{ + SkBitmap* bitmap = webkit_glue::GetBitmapResource(IDC_PAN_SOUTH); + static Cursor c = WebCursor(bitmap, 7, 7); + return c; +} + +const Cursor& southEastPanningCursor() +{ + SkBitmap* bitmap = webkit_glue::GetBitmapResource(IDC_PAN_SOUTH_EAST); + static Cursor c = WebCursor(bitmap, 7, 7); + return c; +} + +const Cursor& southWestPanningCursor() +{ + SkBitmap* bitmap = webkit_glue::GetBitmapResource(IDC_PAN_SOUTH_WEST); + static Cursor c = WebCursor(bitmap, 7, 7); + return c; +} + +const Cursor& westPanningCursor() +{ + SkBitmap* bitmap = webkit_glue::GetBitmapResource(IDC_PAN_WEST); + static Cursor c = WebCursor(bitmap, 7, 7); + return c; +} + const Cursor& moveCursor() { static Cursor c = WebCursor::SIZEALL; diff --git a/webkit/port/platform/DragDataWin.cpp b/webkit/port/platform/DragDataWin.cpp index 6a374b8..8deca48 100644 --- a/webkit/port/platform/DragDataWin.cpp +++ b/webkit/port/platform/DragDataWin.cpp @@ -37,6 +37,7 @@ #include "Markup.h" #include "WCDataObject.h" +#undef LOG #include "base/file_util.h" #include "base/string_util.h" #include "net/base/base64.h" @@ -62,16 +63,16 @@ WebDropData* dropData(DragDataRef dragData) { namespace WebCore { -Clipboard* DragData::createClipboard(ClipboardAccessPolicy policy) const +PassRefPtr<Clipboard> DragData::createClipboard(ClipboardAccessPolicy policy) const { WCDataObject* data; WCDataObject::createInstance(&data); - ClipboardWin* clipboard = new ClipboardWin(true, data, policy); + RefPtr<ClipboardWin> clipboard = ClipboardWin::create(true, data, policy); // The clipboard keeps a reference to the WCDataObject, so we can release // our reference to it. data->Release(); - return clipboard; + return clipboard.release(); } bool DragData::containsURL() const diff --git a/webkit/port/platform/EditorWin.cpp b/webkit/port/platform/EditorWin.cpp index 8839f42..8ffcf9a 100644 --- a/webkit/port/platform/EditorWin.cpp +++ b/webkit/port/platform/EditorWin.cpp @@ -46,7 +46,7 @@ PassRefPtr<Clipboard> Editor::newGeneralClipboard(ClipboardAccessPolicy policy) if (!SUCCEEDED(OleGetClipboard(&clipboardData))) clipboardData = 0; - return new ClipboardWin(false, clipboardData.get(), policy); + return ClipboardWin::create(false, clipboardData.get(), policy); } } // namespace WebCore diff --git a/webkit/port/platform/FileChooserWin.cpp b/webkit/port/platform/FileChooserWin.cpp index 96ef4e4..8497372 100644 --- a/webkit/port/platform/FileChooserWin.cpp +++ b/webkit/port/platform/FileChooserWin.cpp @@ -39,17 +39,6 @@ namespace WebCore { -FileChooser::FileChooser(FileChooserClient* client, const String& filename) - : m_client(client) - , m_filename(filename) - , m_icon(chooseIcon(filename)) -{ -} - -FileChooser::~FileChooser() -{ -} - void FileChooser::openFileChooser(Document* document) { Frame* frame = document->frame(); diff --git a/webkit/port/platform/GKURL.cpp b/webkit/port/platform/GKURL.cpp index bf71fda..f809109 100644 --- a/webkit/port/platform/GKURL.cpp +++ b/webkit/port/platform/GKURL.cpp @@ -35,21 +35,17 @@ #ifdef USE_GOOGLE_URL_LIBRARY +#undef LOG #include "base/string_util.h" #include "googleurl/src/url_canon_internal.h" #include "googleurl/src/url_util.h" +using namespace WTF; + namespace WebCore { namespace { -// For getting the UTF-16 wchar_t pointer out of a DeprecatedString, which -// uses weird character types that happen to be the same as a wchar_t. -const wchar_t* UnicodeForString(const DeprecatedString& s) -{ - return reinterpret_cast<const wchar_t*>(s.unicode()); -} - // Wraps WebKit's text encoding in a character set converter for the // canonicalizer. class WebCoreCharsetConverter : public url_canon::CharsetConverter { @@ -63,10 +59,7 @@ public: virtual void ConvertFromUTF16(const url_parse::UTF16Char* input, int input_len, url_canon::CanonOutput* output) { - // When we merge to WebCore > r31089, this call should change into: - // CString encoded = m_encoding.encode(inupt, input_len, - // URLEncodedEntitiesForUnencodables); - CString encoded = m_encoding->encode(input, input_len); + CString encoded = m_encoding->encode(input, input_len, URLEncodedEntitiesForUnencodables); output->Append(encoded.data(), static_cast<int>(encoded.length())); } @@ -74,6 +67,30 @@ private: const TextEncoding* m_encoding; }; +// Note that this function must be named differently than the one in KURL.cpp +// since our unit tests evilly include both files, and their local definition +// will be ambiguous. +inline void AssertProtocolIsGood(const char* protocol) +{ +#ifndef NDEBUG + const char* p = protocol; + while (*p) { + ASSERT(*p > ' ' && *p < 0x7F && !(*p >= 'A' && *p <= 'Z')); + ++p; + } +#endif +} + +// Returns the characters for the given string, or a pointer to a static empty +// string if the input string is NULL. This will always ensure we have a non- +// NULL character pointer since ReplaceComponents has special meaning for NULL. +inline const url_parse::UTF16Char* CharactersOrEmpty(const String& str) { + static const url_parse::UTF16Char zero = 0; + return str.characters() ? + reinterpret_cast<const url_parse::UTF16Char*>(str.characters()) : + &zero; +} + } // namespace // KURL::URLString ------------------------------------------------------------- @@ -81,7 +98,6 @@ private: KURL::URLString::URLString() : m_utf8IsASCII(true) , m_stringIsValid(false) - , m_deprecatedStringIsValid(false) { } @@ -104,14 +120,12 @@ void KURL::URLString::setUtf8(const char* data, int data_len) m_utf8 = CString(data, data_len); m_stringIsValid = false; - m_deprecatedStringIsValid = false; } void KURL::URLString::setAscii(const char* data, int data_len) { m_utf8 = CString(data, data_len); m_utf8IsASCII = true; m_stringIsValid = false; - m_deprecatedStringIsValid = false; } const String& KURL::URLString::string() const @@ -131,38 +145,8 @@ const String& KURL::URLString::string() const return m_string; } -const DeprecatedString KURL::URLString::deprecatedString() const -{ - if (!m_deprecatedStringIsValid) { - // Must special case the NULL case, since constructing the - // string like we do below will generate an empty rather than - // a NULL string. - if (m_utf8.isNull()) { - m_deprecatedString = DeprecatedString(); - } else if (m_utf8IsASCII) { - // This is not just an optimization. equalIgnoringCase will - // treat two strings as different if their 8/16-bitedness - // doesn't match, even if a conversion would make them match. - m_deprecatedString = DeprecatedString(m_utf8.data(), - m_utf8.length()); - } else { - // DeprecatedString has a fromUTF8 function, but internally - // it will convert to a string! We use this opportunity to - // re-use the old String conversion or save the new one - // to our cache. - m_deprecatedString = string().deprecatedString(); - } - m_deprecatedStringIsValid = true; - } - return m_deprecatedString; -} - // KURL ------------------------------------------------------------------------ -KURL::KURL() : m_isValid(false) -{ -} - // Creates with NULL-terminated string input representing an absolute URL. // WebCore generally calls this only with hardcoded strings, so the input is // ASCII. We treat is as UTF-8 just in case. @@ -184,31 +168,21 @@ KURL::KURL(const char *url) // to a string and then converted back. In this case, the URL is already // canonical and in proper escaped form so needs no encoding. We treat it was // UTF-8 just in case. -KURL::KURL(const DeprecatedString& url) -{ - init(KURL(), url, NULL); - - if (m_url.utf8String().isNull()) { - // See FIXME above. - // - // Bug-for-bug KURL compatibility for WebKit bug: - // http://bugs.webkit.org/show_bug.cgi?id=16487 - // - // URLs created with NULL depricated strings should be changed to be - // empty rather than NULL. This masks some crashes in WebKit. This - // special case should be removed when we bring in a WebKit version - // newer than r31089 which fixes - // http://bugs.webkit.org/show_bug.cgi?id=16485 - // - // This extends to any DeprecatedString, even if it is invalid, and even - // though KURL(KURL(), <same string>) would give a NULL string. Gaa! - m_url.setUtf8("", 0); +KURL::KURL(const String& url) +{ + if (!url.isNull()) { + init(KURL(), url, NULL); + } else { + // WebKit expects us to preserve the nullness of strings when this + // constructor is used. In all other cases, it expects a non-null + // empty string, which is what init() will create. + m_isValid = false; } } // Constructs a new URL given a base URL and a possibly relative input URL. // This assumes UTF-8 encoding. -KURL::KURL(const KURL& base, const DeprecatedString& relative) +KURL::KURL(const KURL& base, const String& relative) { init(base, relative, NULL); } @@ -216,7 +190,7 @@ KURL::KURL(const KURL& base, const DeprecatedString& relative) // Constructs a new URL given a base URL and a possibly relative input URL. // Any query portion of the relative URL will be encoded in the given encoding. KURL::KURL(const KURL& base, - const DeprecatedString& relative, + const String& relative, const TextEncoding& encoding) { init(base, relative, &encoding); @@ -235,10 +209,15 @@ KURL::KURL(const char* canonical_spec, int canonical_spec_len, m_url.setAscii(canonical_spec, canonical_spec_len); } -DeprecatedString KURL::componentString(const url_parse::Component& comp) const +String KURL::componentString(const url_parse::Component& comp) const { - if (!m_isValid || comp.len <= 0) - return DeprecatedString(); + if (!m_isValid || comp.len <= 0) { + // KURL returns a NULL string if the URL is itself a NULL string, and an + // empty string for other nonexistant entities. + if (isNull()) + return String(); + return String("", 0); + } // begin and len are in terms of bytes which do not match // if urlString is UTF-16 and input contains non-ASCII characters. // However, the only part in urlString that can contain non-ASCII @@ -247,40 +226,20 @@ DeprecatedString KURL::componentString(const url_parse::Component& comp) const // byte) will be longer than what's needed by 'mid'. However, mid // truncates len to avoid go past the end of a string so that we can // get away withtout doing anything here. - return m_url.deprecatedString().mid(comp.begin, comp.len); + return m_url.string().substring(comp.begin, comp.len); } void KURL::init(const KURL& base, - const DeprecatedString& relative, + const String& relative, const TextEncoding* query_encoding) { - if (relative.hasFastLatin1()) { - // Use the UTF-8 version when possible. This probably means that the - // URL is all ASCII already, so we can run faster. - init(base, relative.ascii(), relative.length(), query_encoding); - } else { - init(base, reinterpret_cast<const UChar*>(relative.unicode()), - relative.length(), query_encoding); - } + init(base, relative.characters(), relative.length(), query_encoding); } // Note: code mostly duplicated below. void KURL::init(const KURL& base, const char* rel, int rel_len, const TextEncoding* query_encoding) { - // Resolving an empty string on the original URL should return the original. - // This will be handled by the relative URL resolver below, of course, but - // it will not preserve the isNull()ness of the source URL, so we special - // case it here. - // - // Note that resolving a string with just whitespace on am empty URL will - // not preserve the isNullness since this case won't get triggered, but this - // seems like it will be OK. - if (rel_len == 0) { - *this = base; - return; - } - // As a performance optimization, we only use the charset converter if the // encoding is not UTF-8. The URL canonicalizer will be more efficient with // no charset converter object because it can do UTF-8 internally with no @@ -314,6 +273,9 @@ void KURL::init(const KURL& base, const char* rel, int rel_len, m_url.setUtf8(output.data(), output.length()); else m_url.setAscii(output.data(), output.length()); + } else { + // WebKit expects resolved URLs to be empty rather than NULL. + m_url.setUtf8("", 0); } } @@ -321,11 +283,6 @@ void KURL::init(const KURL& base, const char* rel, int rel_len, void KURL::init(const KURL& base, const UChar* rel, int rel_len, const TextEncoding* query_encoding) { - if (rel_len == 0) { - *this = base; - return; - } - WebCoreCharsetConverter charset_converter_object(query_encoding); WebCoreCharsetConverter* charset_converter = (!query_encoding || *query_encoding == UTF8Encoding()) ? 0 : @@ -343,6 +300,8 @@ void KURL::init(const KURL& base, const UChar* rel, int rel_len, m_url.setUtf8(output.data(), output.length()); else m_url.setAscii(output.data(), output.length()); + } else { + m_url.setUtf8("", 0); } } @@ -355,7 +314,7 @@ bool KURL::hasPath() const // We handle "parameters" separated be a semicolon, while the old KURL does // not, which can lead to different results in some cases. -DeprecatedString KURL::lastPathComponent() const +String KURL::lastPathComponent() const { // When the output ends in a slash, WebKit has different expectations than // our library. For "/foo/bar/" the library will return the empty string, @@ -366,15 +325,20 @@ DeprecatedString KURL::lastPathComponent() const url_parse::Component file; url_parse::ExtractFileName(m_url.utf8String().data(), path, &file); + + // Bug: https://bugs.webkit.org/show_bug.cgi?id=21015 this function returns + // a null string when the path is empty, which we duplicate here. + if (!file.is_nonempty()) + return String(); return componentString(file); } -DeprecatedString KURL::protocol() const +String KURL::protocol() const { return componentString(m_parsed.scheme); } -DeprecatedString KURL::host() const +String KURL::host() const { // Note: WebKit decode_string()s here. return componentString(m_parsed.host); @@ -396,21 +360,32 @@ unsigned short int KURL::port() const } // Returns the empty string if there is no password. -DeprecatedString KURL::pass() const +String KURL::pass() const { + // Bug: https://bugs.webkit.org/show_bug.cgi?id=21015 this function returns + // a null string when the password is empty, which we duplicate here. + if (!m_parsed.password.is_nonempty()) + return String(); + // Note: WebKit decode_string()s here. return componentString(m_parsed.password); } // Returns the empty string if there is no username. -DeprecatedString KURL::user() const +String KURL::user() const { // Note: WebKit decode_string()s here. return componentString(m_parsed.username); } -DeprecatedString KURL::ref() const +String KURL::ref() const { + // Empty but present refs ("foo.com/bar#") should result in the empty + // string, which componentString will produce. Nonexistant refs should be + // the NULL string. + if (!m_parsed.ref.is_valid()) + return String(); + // Note: WebKit decode_string()s here. return componentString(m_parsed.ref); } @@ -422,7 +397,7 @@ bool KURL::hasRef() const return m_parsed.ref.len >= 0; } -DeprecatedString KURL::query() const +String KURL::query() const { if (m_parsed.query.len >= 0) { // KURL's query() includes the question mark, even though the reference @@ -433,49 +408,50 @@ DeprecatedString KURL::query() const query_comp.len++; return componentString(query_comp); } - return DeprecatedString(); + + // Bug: https://bugs.webkit.org/show_bug.cgi?id=21015 this function returns + // an empty string when the query is empty rather than a null (not sure + // which is right). + return String("", 0); } -DeprecatedString KURL::path() const +String KURL::path() const { // Note: WebKit decode_string()s here. return componentString(m_parsed.path); } -void KURL::setProtocol(const DeprecatedString& protocol) +void KURL::setProtocol(const String& protocol) { Replacements replacements; - replacements.SetScheme( - reinterpret_cast<const wchar_t*>(protocol.unicode()), - url_parse::Component(0, protocol.length())); + replacements.SetScheme(CharactersOrEmpty(protocol), + url_parse::Component(0, protocol.length())); replaceComponents(replacements); } -void KURL::setHost(const DeprecatedString& host) +void KURL::setHost(const String& host) { Replacements replacements; - replacements.SetHost( - reinterpret_cast<const wchar_t*>(host.unicode()), - url_parse::Component(0, host.length())); + replacements.SetHost(CharactersOrEmpty(host), + url_parse::Component(0, host.length())); replaceComponents(replacements); } -// This function is used only in the KJS build. -void KURL::setHostAndPort(const DeprecatedString& s) { - DeprecatedString newhost = s.left(s.find(":")); - DeprecatedString newport = s.mid(s.find(":") + 1); +// This function is used only in the JSC build. +void KURL::setHostAndPort(const String& s) { + String newhost = s.left(s.find(":")); + String newport = s.substring(s.find(":") + 1); Replacements replacements; - replacements.SetHost( // Host can't be removed, so we always set. - reinterpret_cast<const wchar_t*>(newhost.unicode()), - url_parse::Component(0, newhost.length())); + // Host can't be removed, so we always set. + replacements.SetHost(CharactersOrEmpty(newhost), + url_parse::Component(0, newhost.length())); if (newport.isEmpty()) { // Port may be removed, so we support clearing. replacements.ClearPort(); } else { - replacements.SetPort( - reinterpret_cast<const wchar_t*>(newport.unicode()), - url_parse::Component(0, newport.length())); + replacements.SetPort(CharactersOrEmpty(newport), + url_parse::Component(0, newport.length())); } replaceComponents(replacements); } @@ -483,11 +459,11 @@ void KURL::setHostAndPort(const DeprecatedString& s) { void KURL::setPort(unsigned short i) { Replacements replacements; - DeprecatedString portStr; + String portStr; if (i > 0) { - portStr = DeprecatedString::number(static_cast<int>(i)); + portStr = String::number(static_cast<int>(i)); replacements.SetPort( - reinterpret_cast<const wchar_t*>(portStr.unicode()), + reinterpret_cast<const wchar_t*>(portStr.characters()), url_parse::Component(0, portStr.length())); } else { @@ -497,7 +473,7 @@ void KURL::setPort(unsigned short i) replaceComponents(replacements); } -void KURL::setUser(const DeprecatedString& user) +void KURL::setUser(const String& user) { // This function is commonly called to clear the username, which we // normally don't have, so we optimize this case. @@ -507,13 +483,12 @@ void KURL::setUser(const DeprecatedString& user) // The canonicalizer will clear any usernames that are empty, so we // don't have to explicitly call ClearUsername() here. Replacements replacements; - replacements.SetUsername( - reinterpret_cast<const wchar_t*>(user.unicode()), - url_parse::Component(0, user.length())); + replacements.SetUsername(CharactersOrEmpty(user), + url_parse::Component(0, user.length())); replaceComponents(replacements); } -void KURL::setPass(const DeprecatedString& pass) +void KURL::setPass(const String& pass) { // This function is commonly called to clear the password, which we // normally don't have, so we optimize this case. @@ -523,13 +498,12 @@ void KURL::setPass(const DeprecatedString& pass) // The canonicalizer will clear any passwords that are empty, so we // don't have to explicitly call ClearUsername() here. Replacements replacements; - replacements.SetPassword( - reinterpret_cast<const wchar_t*>(pass.unicode()), - url_parse::Component(0, pass.length())); + replacements.SetPassword(CharactersOrEmpty(pass), + url_parse::Component(0, pass.length())); replaceComponents(replacements); } -void KURL::setRef(const DeprecatedString& ref) +void KURL::setRef(const String& ref) { // This function is commonly called to clear the ref, which we // normally don't have, so we optimize this case. @@ -540,57 +514,92 @@ void KURL::setRef(const DeprecatedString& ref) if (ref.isNull()) { replacements.ClearRef(); } else { - replacements.SetRef( - reinterpret_cast<const wchar_t*>(ref.unicode()), - url_parse::Component(0, ref.length())); + replacements.SetRef(CharactersOrEmpty(ref), + url_parse::Component(0, ref.length())); } replaceComponents(replacements); } -void KURL::setQuery(const DeprecatedString& query) +void KURL::removeRef() +{ + Replacements replacements; + replacements.ClearRef(); + replaceComponents(replacements); +} + +void KURL::setQuery(const String& query) { Replacements replacements; if (query.isNull()) { // WebKit sets to NULL to clear any query. replacements.ClearQuery(); - } else if (query.length() > 0 && query.ascii()[0] == '?') { + } else if (query.length() > 0 && query[0] == '?') { // WebKit expects the query string to begin with a question mark, but // our library doesn't. So we trim off the question mark when setting. - replacements.SetQuery( - reinterpret_cast<const wchar_t*>(query.unicode()), - url_parse::Component(1, query.length() - 1)); + replacements.SetQuery(CharactersOrEmpty(query), + url_parse::Component(1, query.length() - 1)); } else { // When set with the empty string or something that doesn't begin with // a question mark, WebKit will add a question mark for you. The only // way this isn't compatible is if you call this function with an empty // string. Old KURL will leave a '?' with nothing following it in the // URL, whereas we'll clear it. - replacements.SetQuery( - reinterpret_cast<const wchar_t*>(query.unicode()), - url_parse::Component(0, query.length())); + replacements.SetQuery(CharactersOrEmpty(query), + url_parse::Component(0, query.length())); } replaceComponents(replacements); } -void KURL::setPath(const DeprecatedString& path) +void KURL::setPath(const String& path) { // Empty paths will be canonicalized to "/", so we don't have to worry // about calling ClearPath(). Replacements replacements; - replacements.SetPath( - reinterpret_cast<const wchar_t*>(path.unicode()), - url_parse::Component(0, path.length())); + replacements.SetPath(CharactersOrEmpty(path), + url_parse::Component(0, path.length())); replaceComponents(replacements); } // On Mac, this just seems to return the same URL, but with "/foo/bar" for // file: URLs instead of file:///foo/bar. We don't bother with any of this, // at least for now. -DeprecatedString KURL::prettyURL() const +String KURL::prettyURL() const { if (!m_isValid) - return DeprecatedString(); - return m_url.deprecatedString(); + return String(); + return m_url.string(); +} + +// Copy the KURL version here on Sept 12, 2008 while doing the webkit merge. +// +// TODO(erg): Somehow share this with KURL? Like we'd theoretically merge +// with decodeURLEscapeSequences below? +#ifdef KURL_DECORATE_GLOBALS +String KURL::mimeTypeFromDataURL(const String& url) +#else +String mimeTypeFromDataURL(const String& url) +#endif +{ + ASSERT(protocolIs(url, "data")); + int index = url.find(';'); + if (index == -1) + index = url.find(','); + if (index != -1) { + int len = index - 5; + if (len > 0) + return url.substring(5, len); + return "text/plain"; // Data URLs with no MIME type are considered text/plain. + } + return ""; +} + +#ifdef KURL_DECORATE_GLOBALS +String KURL::decodeURLEscapeSequences(const String& str) +#else +String decodeURLEscapeSequences(const String& str) +#endif +{ + return decodeURLEscapeSequences(str, UTF8Encoding()); } // In WebKit's implementation, this is called by every component getter. @@ -605,14 +614,28 @@ DeprecatedString KURL::prettyURL() const // IE doesn't unescape %00, forcing you to use \x00 in JS strings, so we do // the same. This also eliminates NULL-related problems should a consumer // incorrectly call this function for non-JavaScript. -DeprecatedString KURL::decode_string(const DeprecatedString& urlString) +// +// TODO(brettw) these should be merged to the regular KURL implementation. +#ifdef KURL_DECORATE_GLOBALS +String KURL::decodeURLEscapeSequences(const String& str, const TextEncoding& encoding) +#else +String decodeURLEscapeSequences(const String& str, const TextEncoding& encoding) +#endif { - // First unescape all input. WebKit's implementation seems to assume the - // input is 8-bit, so we do as well. - ASSERT(urlString.isAllLatin1()); - - const char* input = urlString.latin1(); - int input_length = urlString.length(); + // TODO(brettw) We can probably use KURL's version of this function + // without modification. However, I'm concerned about + // https://bugs.webkit.org/show_bug.cgi?id=20559 so am keeping this old + // custom code for now. Using their version will also fix the bug that + // we ignore the encoding. + // + // TODO(brettw) bug 1350291: This does not get called very often. We just + // convert first to 8-bit UTF-8, then unescape, then back to 16-bit. This + // kind of sucks, and we don't use the encoding properly, which will make + // some obscure anchor navigations fail. + CString cstr = str.utf8(); + + const char* input = cstr.data(); + int input_length = cstr.length(); url_canon::RawCanonOutputT<char> unescaped; for (int i = 0; i < input_length; i++) { if (input[i] == '%') { @@ -631,7 +654,7 @@ DeprecatedString KURL::decode_string(const DeprecatedString& urlString) unescaped.push_back('%'); } } else { - // Regular non-escaped character. + // Regular non-escaped 8-bit character. unescaped.push_back(input[i]); } } @@ -668,17 +691,10 @@ DeprecatedString KURL::decode_string(const DeprecatedString& urlString) } } - return DeprecatedString(reinterpret_cast<DeprecatedChar*>(utf16.data()), + return String(reinterpret_cast<UChar*>(utf16.data()), utf16.length()); } -// The encoding parameter to this function is currently never used. -DeprecatedString KURL::decode_string(const DeprecatedString& urlString, - const TextEncoding& encoding) -{ - return decode_string(urlString); -} - void KURL::replaceComponents(const Replacements& replacements) { url_canon::RawCanonOutputT<char> output; @@ -694,19 +710,20 @@ void KURL::replaceComponents(const Replacements& replacements) m_url.setAscii(output.data(), output.length()); } -bool KURL::schemeIs(const char* lower_ascii_scheme) const +bool KURL::protocolIs(const char* protocol) const { + AssertProtocolIsGood(protocol); if (m_parsed.scheme.len <= 0) - return lower_ascii_scheme == NULL; + return protocol == NULL; return LowerCaseEqualsASCII( m_url.utf8String().data() + m_parsed.scheme.begin, m_url.utf8String().data() + m_parsed.scheme.end(), - lower_ascii_scheme); + protocol); } bool KURL::isLocalFile() const { - return schemeIs("file"); + return protocolIs("file"); } // This is called to escape a URL string. It is only used externally when @@ -718,11 +735,16 @@ bool KURL::isLocalFile() const // ways, and may expect to get a valid URL string. The dangerous thing we want // to protect against here is accidentally getting NULLs in a string that is // not supposed to have NULLs. Therefore, we escape NULLs here to prevent this. -DeprecatedString KURL::encode_string(const DeprecatedString& notEncodedString) +#ifdef KURL_DECORATE_GLOBALS +String KURL::encodeWithURLEscapeSequences(const String& notEncodedString) +#else +String encodeWithURLEscapeSequences(const String& notEncodedString) +#endif { CString utf8 = UTF8Encoding().encode( - reinterpret_cast<const UChar*>(notEncodedString.unicode()), - notEncodedString.length()); + reinterpret_cast<const UChar*>(notEncodedString.characters()), + notEncodedString.length(), + URLEncodedEntitiesForUnencodables); const char* input = utf8.data(); int input_len = utf8.length(); @@ -733,7 +755,7 @@ DeprecatedString KURL::encode_string(const DeprecatedString& notEncodedString) else buffer.append(input[i]); } - return DeprecatedString(buffer.data(), buffer.size()); + return String(buffer.data(), buffer.size()); } bool KURL::isHierarchical() const @@ -753,9 +775,11 @@ void KURL::print() const } #endif -bool operator==(const KURL &a, const KURL &b) +void KURL::invalidate() { - return a.m_url.utf8String() == b.m_url.utf8String(); + // This is only called from the constructor so resetting the (automatically + // initialized) string and parsed structure would be a waste of time. + m_isValid = false; } // Equal up to reference fragments, if any. @@ -776,6 +800,71 @@ bool equalIgnoringRef(const KURL& a, const KURL& b) strncmp(a.m_url.utf8String().data(), b.m_url.utf8String().data(), a_len) == 0; } +unsigned KURL::hostStart() const +{ + return m_parsed.CountCharactersBefore(url_parse::Parsed::HOST, false); +} + +unsigned KURL::hostEnd() const +{ + return m_parsed.CountCharactersBefore(url_parse::Parsed::PORT, true); +} + +unsigned KURL::pathStart() const +{ + return m_parsed.CountCharactersBefore(url_parse::Parsed::PATH, false); +} + +unsigned KURL::pathEnd() const +{ + return m_parsed.CountCharactersBefore(url_parse::Parsed::QUERY, true); +} + +unsigned KURL::pathAfterLastSlash() const +{ + // When there's no path, ask for what would be the beginning of it. + if (!m_parsed.path.is_valid()) + return m_parsed.CountCharactersBefore(url_parse::Parsed::PATH, false); + + url_parse::Component filename; + url_parse::ExtractFileName(m_url.utf8String().data(), m_parsed.path, + &filename); + return filename.begin; +} + +#ifdef KURL_DECORATE_GLOBALS +const KURL& KURL::blankURL() +#else +const KURL& blankURL() +#endif +{ + static KURL staticBlankURL("about:blank"); + return staticBlankURL; +} + +#ifdef KURL_DECORATE_GLOBALS +bool KURL::protocolIs(const String& url, const char* protocol) +#else +bool protocolIs(const String& url, const char* protocol) +#endif +{ + // Do the comparison without making a new string object. + AssertProtocolIsGood(protocol); + for (int i = 0; ; ++i) { + if (!protocol[i]) + return url[i] == ':'; + if (toASCIILower(url[i]) != protocol[i]) + return false; + } +} + +#ifndef KURL_DECORATE_GLOBALS +inline bool KURL::protocolIs(const String& string, const char* protocol) +{ + return WebCore::protocolIs(string, protocol); +} +#endif + } // namespace WebCore #endif // USE_GOOGLE_URL_LIBRARY diff --git a/webkit/port/platform/GKURL_unittest.cpp b/webkit/port/platform/GKURL_unittest.cpp index 5f525d1..46c91e8 100644 --- a/webkit/port/platform/GKURL_unittest.cpp +++ b/webkit/port/platform/GKURL_unittest.cpp @@ -46,6 +46,8 @@ // This evil preprocessor hack allows us to run both the original KURL and our // KURL code at the same time regardless of build options. +#define KURL_DECORATE_GLOBALS + // Old KURL #undef USE_GOOGLE_URL_LIBRARY #define KURL WebKitKURL @@ -79,9 +81,11 @@ struct ComponentCase { // Output stream operator so gTest's macros work with WebCore strings. std::ostream& operator<<(std::ostream& out, - const WebCore::DeprecatedString& str) { + const WebCore::String& str) { + if (str.isEmpty()) + return out; return out << WideToUTF8(std::wstring( - reinterpret_cast<const wchar_t*>(str.unicode()), str.length())); + reinterpret_cast<const wchar_t*>(str.characters()), str.length())); } } // namespace @@ -114,8 +118,8 @@ TEST(GKURL, SameGetters) { // UTF-16 std::wstring wstr(UTF8ToWide(cases[i])); - WebCore::DeprecatedString utf16( - reinterpret_cast<const WebCore::DeprecatedChar*>(wstr.c_str()), + WebCore::String utf16( + reinterpret_cast<const ::UChar*>(wstr.c_str()), static_cast<int>(wstr.length())); kurl = WebCore::WebKitKURL(utf16); gurl = WebCore::GoogleKURL(utf16); @@ -140,17 +144,17 @@ TEST(GKURL, DifferentGetters) { // Old WebKit allows references and queries in what we call "path" URLs // like javascript, so the path here will only consist of "hello!". - {"javascript:hello!?#/\\world", "javascript", NULL, 0, NULL, NULL, "hello!?#/\\world", "world", NULL, NULL}, + {"javascript:hello!?#/\\world", "javascript", "", 0, "", NULL, "hello!?#/\\world", "world", "", NULL}, // Old WebKit doesn't handle "parameters" in paths, so will // disagree with us about where the path is for this URL. - {"http://a.com/hello;world", "http", "a.com", 0, NULL, NULL, "/hello;world", "hello", NULL, NULL}, + {"http://a.com/hello;world", "http", "a.com", 0, "", NULL, "/hello;world", "hello", "", NULL}, // WebKit doesn't like UTF-8 or UTF-16 input. - {"http://\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xbd\xa0\xe5\xa5\xbd/", "http", "xn--6qqa088eba", 0, NULL, NULL, "/", NULL, NULL, NULL}, + {"http://\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xbd\xa0\xe5\xa5\xbd/", "http", "xn--6qqa088eba", 0, "", NULL, "/", NULL, "", NULL}, // WebKit %-escapes non-ASCII characters in reference, but we don't. - {"http://www.google.com/foo/blah?bar=baz#\xce\xb1\xce\xb2", "http", "www.google.com", 0, NULL, NULL, "/foo/blah/", "blah", "?bar=baz", "\xce\xb1\xce\xb2"} + {"http://www.google.com/foo/blah?bar=baz#\xce\xb1\xce\xb2", "http", "www.google.com", 0, "", NULL, "/foo/blah/", "blah", "?bar=baz", "\xce\xb1\xce\xb2"} }; for (int i = 0; i < arraysize(cases); i++) { @@ -163,13 +167,12 @@ TEST(GKURL, DifferentGetters) { EXPECT_EQ(cases[i].pass, gurl.pass()); EXPECT_EQ(cases[i].last_path, gurl.lastPathComponent()); EXPECT_EQ(cases[i].query, gurl.query()); - if (cases[i].ref == NULL) { - EXPECT_EQ(cases[i].ref, gurl.ref()); + // Want to compare UCS-16 refs (or to NULL). + if (cases[i].ref) { + EXPECT_EQ(webkit_glue::StdWStringToString(UTF8ToWide(cases[i].ref)), + gurl.ref()); } else { - // We can't compare cases[i].ref and gurl.ref() directly - // because operator==(const char*, const DeprecatedString&) invoked - // in CmpHelperEQ does not treat 'char *' as UTF-8. - EXPECT_STREQ(cases[i].ref, gurl.ref().utf8()); + EXPECT_TRUE(gurl.ref().isNull()); } } } @@ -181,12 +184,12 @@ TEST(GKURL, UTF8) { WebCore::GoogleKURL ascii_gurl(ascii_url); EXPECT_TRUE(ascii_gurl.string() == WebCore::String(ascii_url)); - // When the result is ASCII, we should get an ASCII DeprecatedString. Some - // code depends on being able to compare the result of the .deprecatedString() - // getter with another deprecatedString, and the isASCIIness of the two + // When the result is ASCII, we should get an ASCII String. Some + // code depends on being able to compare the result of the .string() + // getter with another String, and the isASCIIness of the two // strings must match for these functions (like equalIgnoringCase). - EXPECT_TRUE(WebCore::equalIgnoringCase(ascii_gurl.deprecatedString(), - WebCore::DeprecatedString(ascii_url))); + EXPECT_TRUE(WebCore::equalIgnoringCase(ascii_gurl, + WebCore::String(ascii_url))); // Reproduce code path in FrameLoader.cpp -- equalIgnoringCase implicitly // expects gkurl.protocol() to have been created as ascii. @@ -218,42 +221,42 @@ TEST(GKURL, Setters) { WebCore::GoogleKURL gurl(cases[i].url); WebCore::WebKitKURL kurl(cases[i].url); - EXPECT_EQ(kurl.deprecatedString(), gurl.deprecatedString()); + EXPECT_EQ(kurl.string(), gurl.string()); kurl.setProtocol(cases[i].protocol); gurl.setProtocol(cases[i].protocol); - EXPECT_EQ(kurl.deprecatedString(), gurl.deprecatedString()); + EXPECT_EQ(kurl.string(), gurl.string()); kurl.setHost(cases[i].host); gurl.setHost(cases[i].host); - EXPECT_EQ(kurl.deprecatedString(), gurl.deprecatedString()); + EXPECT_EQ(kurl.string(), gurl.string()); kurl.setPort(cases[i].port); gurl.setPort(cases[i].port); - EXPECT_EQ(kurl.deprecatedString(), gurl.deprecatedString()); + EXPECT_EQ(kurl.string(), gurl.string()); kurl.setUser(cases[i].user); gurl.setUser(cases[i].user); - EXPECT_EQ(kurl.deprecatedString(), gurl.deprecatedString()); + EXPECT_EQ(kurl.string(), gurl.string()); kurl.setPass(cases[i].pass); gurl.setPass(cases[i].pass); - EXPECT_EQ(kurl.deprecatedString(), gurl.deprecatedString()); + EXPECT_EQ(kurl.string(), gurl.string()); kurl.setPath(cases[i].path); gurl.setPath(cases[i].path); - EXPECT_EQ(kurl.deprecatedString(), gurl.deprecatedString()); + EXPECT_EQ(kurl.string(), gurl.string()); kurl.setQuery(cases[i].query); gurl.setQuery(cases[i].query); - EXPECT_EQ(kurl.deprecatedString(), gurl.deprecatedString()); + EXPECT_EQ(kurl.string(), gurl.string()); // Refs are tested below. On the Safari 3.1 branch, we don't match their // KURL since we integrated a fix from their trunk. } } -// Tests that KURL::decode_string works as expected +// Tests that KURL::decodeURLEscapeSequences works as expected TEST(GKURL, Decode) { const char* decode_cases[] = { "hello, world", @@ -270,41 +273,41 @@ TEST(GKURL, Decode) { }; for (int i = 0; i < arraysize(decode_cases); i++) { - WebCore::DeprecatedString input(decode_cases[i]); - WebCore::DeprecatedString webkit = WebCore::WebKitKURL::decode_string(input); - WebCore::DeprecatedString google = WebCore::GoogleKURL::decode_string(input); + WebCore::String input(decode_cases[i]); + WebCore::String webkit = WebCore::WebKitKURL::decodeURLEscapeSequences(input); + WebCore::String google = WebCore::GoogleKURL::decodeURLEscapeSequences(input); EXPECT_TRUE(webkit == google); } // Our decode should not decode %00 - WebCore::DeprecatedString zero = WebCore::GoogleKURL::decode_string("%00"); - EXPECT_STREQ("%00", zero.ascii()); + WebCore::String zero = WebCore::GoogleKURL::decodeURLEscapeSequences("%00"); + EXPECT_STREQ("%00", zero.utf8().data()); // Test the error behavior for invalid UTF-8 (we differ from WebKit here). - WebCore::DeprecatedString invalid = WebCore::GoogleKURL::decode_string( + WebCore::String invalid = WebCore::GoogleKURL::decodeURLEscapeSequences( "%e4%a0%e5%a5%bd"); - WebCore::DeprecatedString invalid_expected( - reinterpret_cast<const WebCore::DeprecatedChar*>(L"\x00e4\x00a0\x597d"), + WebCore::String invalid_expected( + reinterpret_cast<const ::UChar*>(L"\x00e4\x00a0\x597d"), 3); EXPECT_EQ(invalid_expected, invalid); } TEST(GKURL, Encode) { // Also test that it gets converted to UTF-8 properly. - WebCore::DeprecatedString wide_input( - reinterpret_cast<const WebCore::DeprecatedChar*>(L"\x4f60\x597d"), 2); - WebCore::DeprecatedString wide_reference("\xe4\xbd\xa0\xe5\xa5\xbd", 6); - WebCore::DeprecatedString wide_output = - WebCore::GoogleKURL::encode_string(wide_input); + WebCore::String wide_input( + reinterpret_cast<const ::UChar*>(L"\x4f60\x597d"), 2); + WebCore::String wide_reference("\xe4\xbd\xa0\xe5\xa5\xbd", 6); + WebCore::String wide_output = + WebCore::GoogleKURL::encodeWithURLEscapeSequences(wide_input); EXPECT_EQ(wide_reference, wide_output); // Our encode only escapes NULLs for safety (see the implementation for // more), so we only bother to test a few cases. - WebCore::DeprecatedString input( + WebCore::String input( "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", 16); - WebCore::DeprecatedString reference( + WebCore::String reference( "%00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", 18); - WebCore::DeprecatedString output = WebCore::GoogleKURL::encode_string(input); + WebCore::String output = WebCore::GoogleKURL::encodeWithURLEscapeSequences(input); EXPECT_EQ(reference, output); } @@ -316,7 +319,7 @@ TEST(GKURL, ResolveEmpty) { const char abs[] = "http://www.google.com/"; WebCore::GoogleKURL resolve_abs(empty_base, abs); EXPECT_TRUE(resolve_abs.isValid()); - EXPECT_STREQ(abs, resolve_abs.deprecatedString().ascii()); + EXPECT_STREQ(abs, resolve_abs.string().utf8().data()); // Resolving a non-relative URL agains the empty one should still error. const char rel[] = "foo.html"; @@ -332,7 +335,7 @@ TEST(GKURL, ReplaceInvalid) { EXPECT_EQ(kurl.isValid(), gurl.isValid()); EXPECT_EQ(kurl.isEmpty(), gurl.isEmpty()); - EXPECT_STREQ(kurl.deprecatedString().ascii(), gurl.deprecatedString().ascii()); + EXPECT_STREQ(kurl.string().utf8().data(), gurl.string().utf8().data()); gurl.setProtocol("http"); kurl.setProtocol("http"); @@ -344,27 +347,27 @@ TEST(GKURL, ReplaceInvalid) { // differently if there is only a scheme. We check the results here to make // it more obvious what is going on, but it shouldn't be a big deal if these // change. - EXPECT_STREQ("http:", gurl.deprecatedString().ascii()); - EXPECT_STREQ("http:/", kurl.deprecatedString().ascii()); + EXPECT_STREQ("http:", gurl.string().utf8().data()); + EXPECT_STREQ("http:/", kurl.string().utf8().data()); gurl.setHost("www.google.com"); kurl.setHost("www.google.com"); EXPECT_EQ(kurl.isValid(), gurl.isValid()); EXPECT_EQ(kurl.isEmpty(), gurl.isEmpty()); - EXPECT_STREQ(kurl.deprecatedString().ascii(), gurl.deprecatedString().ascii()); + EXPECT_STREQ(kurl.string().utf8().data(), gurl.string().utf8().data()); gurl.setPort(8000); kurl.setPort(8000); EXPECT_EQ(kurl.isValid(), gurl.isValid()); EXPECT_EQ(kurl.isEmpty(), gurl.isEmpty()); - EXPECT_STREQ(kurl.deprecatedString().ascii(), gurl.deprecatedString().ascii()); + EXPECT_STREQ(kurl.string().utf8().data(), gurl.string().utf8().data()); gurl.setPath("/favicon.ico"); kurl.setPath("/favicon.ico"); EXPECT_EQ(kurl.isValid(), gurl.isValid()); EXPECT_EQ(kurl.isEmpty(), gurl.isEmpty()); - EXPECT_STREQ(kurl.deprecatedString().ascii(), gurl.deprecatedString().ascii()); - EXPECT_STREQ("http://www.google.com:8000/favicon.ico", gurl.deprecatedString().ascii()); + EXPECT_STREQ(kurl.string().utf8().data(), gurl.string().utf8().data()); + EXPECT_STREQ("http://www.google.com:8000/favicon.ico", gurl.string().utf8().data()); // Now let's test that giving an invalid replacement still fails. gurl.setProtocol("f/sj#@"); @@ -377,12 +380,12 @@ TEST(GKURL, Path) { WebCore::WebKitKURL kurl(initial); // Clear by setting a NULL string. - WebCore::DeprecatedString null_string; + WebCore::String null_string; EXPECT_TRUE(null_string.isNull()); gurl.setPath(null_string); kurl.setPath(null_string); - EXPECT_STREQ(kurl.deprecatedString().ascii(), gurl.deprecatedString().ascii()); - EXPECT_STREQ("http://www.google.com/", gurl.deprecatedString().ascii()); + EXPECT_STREQ(kurl.string().utf8().data(), gurl.string().utf8().data()); + EXPECT_STREQ("http://www.google.com/", gurl.string().utf8().data()); } // Test that setting the query to different things works. Thq query is handled @@ -393,32 +396,32 @@ TEST(GKURL, Query) { WebCore::WebKitKURL kurl(initial); // Clear by setting a NULL string. - WebCore::DeprecatedString null_string; + WebCore::String null_string; EXPECT_TRUE(null_string.isNull()); gurl.setQuery(null_string); kurl.setQuery(null_string); - EXPECT_STREQ(kurl.deprecatedString().ascii(), gurl.deprecatedString().ascii()); + EXPECT_STREQ(kurl.string().utf8().data(), gurl.string().utf8().data()); // Clear by setting an empty string. gurl = WebCore::GoogleKURL(initial); kurl = WebCore::WebKitKURL(initial); - WebCore::DeprecatedString empty_string(""); + WebCore::String empty_string(""); EXPECT_FALSE(empty_string.isNull()); gurl.setQuery(empty_string); kurl.setQuery(empty_string); - EXPECT_STREQ(kurl.deprecatedString().ascii(), gurl.deprecatedString().ascii()); + EXPECT_STREQ(kurl.string().utf8().data(), gurl.string().utf8().data()); // Set with something that begins in a question mark. const char question[] = "?foo=bar"; gurl.setQuery(question); kurl.setQuery(question); - EXPECT_STREQ(kurl.deprecatedString().ascii(), gurl.deprecatedString().ascii()); + EXPECT_STREQ(kurl.string().utf8().data(), gurl.string().utf8().data()); // Set with something that doesn't begin in a question mark. const char query[] = "foo=bar"; gurl.setQuery(query); kurl.setQuery(query); - EXPECT_STREQ(kurl.deprecatedString().ascii(), gurl.deprecatedString().ascii()); + EXPECT_STREQ(kurl.string().utf8().data(), gurl.string().utf8().data()); } TEST(GKURL, Ref) { @@ -427,26 +430,26 @@ TEST(GKURL, Ref) { // Basic ref setting. WebCore::GoogleKURL cur("http://foo/bar"); cur.setRef("asdf"); - EXPECT_STREQ(cur.deprecatedString().ascii(), "http://foo/bar#asdf"); + EXPECT_STREQ("http://foo/bar#asdf", cur.string().utf8().data()); cur = gurl; cur.setRef("asdf"); - EXPECT_STREQ(cur.deprecatedString().ascii(), "http://foo/bar#asdf"); + EXPECT_STREQ("http://foo/bar#asdf", cur.string().utf8().data()); // Setting a ref to the empty string will set it to "#". cur = WebCore::GoogleKURL("http://foo/bar"); - cur.setRef(WebCore::DeprecatedString("")); - EXPECT_STREQ("http://foo/bar#", cur.deprecatedString().ascii()); + cur.setRef(""); + EXPECT_STREQ("http://foo/bar#", cur.string().utf8().data()); cur = gurl; - cur.setRef(WebCore::DeprecatedString("")); - EXPECT_STREQ("http://foo/bar#", cur.deprecatedString().ascii()); + cur.setRef(""); + EXPECT_STREQ("http://foo/bar#", cur.string().utf8().data()); // Setting the ref to the null string will clear it altogether. cur = WebCore::GoogleKURL("http://foo/bar"); - cur.setRef(WebCore::DeprecatedString()); - EXPECT_STREQ("http://foo/bar", cur.deprecatedString().ascii()); + cur.setRef(WebCore::String()); + EXPECT_STREQ("http://foo/bar", cur.string().utf8().data()); cur = gurl; - cur.setRef(WebCore::DeprecatedString()); - EXPECT_STREQ("http://foo/bar", cur.deprecatedString().ascii()); + cur.setRef(WebCore::String()); + EXPECT_STREQ("http://foo/bar", cur.string().utf8().data()); } TEST(GKURL, Empty) { @@ -456,31 +459,43 @@ TEST(GKURL, Empty) { // First test that regular empty URLs are the same. EXPECT_EQ(kurl.isEmpty(), gurl.isEmpty()); EXPECT_EQ(kurl.isValid(), gurl.isValid()); + EXPECT_EQ(kurl.isNull(), gurl.isNull()); EXPECT_EQ(kurl.string().isNull(), gurl.string().isNull()); EXPECT_EQ(kurl.string().isEmpty(), gurl.string().isEmpty()); - // Now test that resolved empty URLs are the same. + // Test resolving a NULL URL on an empty string. WebCore::GoogleKURL gurl2(gurl, ""); WebCore::WebKitKURL kurl2(kurl, ""); + EXPECT_EQ(kurl2.isNull(), gurl2.isNull()); EXPECT_EQ(kurl2.isEmpty(), gurl2.isEmpty()); EXPECT_EQ(kurl2.isValid(), gurl2.isValid()); EXPECT_EQ(kurl2.string().isNull(), gurl2.string().isNull()); EXPECT_EQ(kurl2.string().isEmpty(), gurl2.string().isEmpty()); - EXPECT_EQ(kurl2.deprecatedString().isNull(), gurl2.deprecatedString().isNull()); - EXPECT_EQ(kurl2.deprecatedString().isEmpty(), gurl2.deprecatedString().isEmpty()); + EXPECT_EQ(kurl2.string().isNull(), gurl2.string().isNull()); + EXPECT_EQ(kurl2.string().isEmpty(), gurl2.string().isEmpty()); - // Now test that non-hierarchical schemes are resolved the same. + // Resolve the NULL URL on a NULL string. + WebCore::GoogleKURL gurl22(gurl, WebCore::String()); + WebCore::WebKitKURL kurl22(kurl, WebCore::String()); + EXPECT_EQ(kurl2.isNull(), gurl2.isNull()); + EXPECT_EQ(kurl2.isEmpty(), gurl2.isEmpty()); + EXPECT_EQ(kurl2.isValid(), gurl2.isValid()); + EXPECT_EQ(kurl2.string().isNull(), gurl2.string().isNull()); + EXPECT_EQ(kurl2.string().isEmpty(), gurl2.string().isEmpty()); + EXPECT_EQ(kurl2.string().isNull(), gurl2.string().isNull()); + EXPECT_EQ(kurl2.string().isEmpty(), gurl2.string().isEmpty()); + + // Test non-hierarchical schemes resolving. The actual URLs will be different. + // WebKit's one will set the string to "something.gif" and we'll set it to an + // empty string. I think either is OK, so we just check our behavior. WebCore::GoogleKURL gurl3(WebCore::GoogleKURL("data:foo"), "something.gif"); - WebCore::WebKitKURL kurl3(WebCore::WebKitKURL("data:foo"), "something.gif"); - EXPECT_EQ(kurl3.isEmpty(), gurl3.isEmpty()); - EXPECT_EQ(kurl3.isValid(), gurl3.isValid()); - EXPECT_EQ(kurl3.string().isNull(), gurl3.string().isNull()); - EXPECT_EQ(kurl3.string().isEmpty(), gurl3.string().isEmpty()); + EXPECT_TRUE(gurl3.isEmpty()); + EXPECT_FALSE(gurl3.isValid()); // Test for weird isNull string input, // see: http://bugs.webkit.org/show_bug.cgi?id=16487 - WebCore::GoogleKURL gurl4(gurl.deprecatedString()); - WebCore::WebKitKURL kurl4(kurl.deprecatedString()); + WebCore::GoogleKURL gurl4(gurl.string()); + WebCore::WebKitKURL kurl4(kurl.string()); EXPECT_EQ(kurl4.isEmpty(), gurl4.isEmpty()); EXPECT_EQ(kurl4.isValid(), gurl4.isValid()); EXPECT_EQ(kurl4.string().isNull(), gurl4.string().isNull()); @@ -489,10 +504,11 @@ TEST(GKURL, Empty) { // Resolving an empty URL on an invalid string. WebCore::GoogleKURL gurl5(WebCore::GoogleKURL(), "foo.js"); WebCore::WebKitKURL kurl5(WebCore::WebKitKURL(), "foo.js"); - EXPECT_EQ(kurl5.isEmpty(), gurl5.isEmpty()); + // We'll be empty in this case, but KURL won't be. Should be OK. + // EXPECT_EQ(kurl5.isEmpty(), gurl5.isEmpty()); + // EXPECT_EQ(kurl5.string().isEmpty(), gurl5.string().isEmpty()); EXPECT_EQ(kurl5.isValid(), gurl5.isValid()); EXPECT_EQ(kurl5.string().isNull(), gurl5.string().isNull()); - EXPECT_EQ(kurl5.string().isEmpty(), gurl5.string().isEmpty()); // Empty string as input WebCore::GoogleKURL gurl6(""); @@ -534,3 +550,35 @@ TEST(GKURL, UserPass) { kurl.setUser(""); EXPECT_TRUE(kurl.string() == gurl.string()); } + +TEST(GKURL, Offsets) { + const char* src1 = "http://user:pass@google.com/foo/bar.html?baz=query#ref"; + WebCore::GoogleKURL gurl1(src1); + WebCore::WebKitKURL kurl1(src1); + + EXPECT_TRUE(kurl1.hostStart() == gurl1.hostStart()); + EXPECT_TRUE(kurl1.hostEnd() == gurl1.hostEnd()); + EXPECT_TRUE(kurl1.pathStart() == gurl1.pathStart()); + EXPECT_TRUE(kurl1.pathEnd() == gurl1.pathEnd()); + EXPECT_TRUE(kurl1.pathAfterLastSlash() == gurl1.pathAfterLastSlash()); + + const char* src2 = "http://google.com/foo/"; + WebCore::GoogleKURL gurl2(src2); + WebCore::WebKitKURL kurl2(src2); + + EXPECT_TRUE(kurl2.hostStart() == gurl2.hostStart()); + EXPECT_TRUE(kurl2.hostEnd() == gurl2.hostEnd()); + EXPECT_TRUE(kurl2.pathStart() == gurl2.pathStart()); + EXPECT_TRUE(kurl2.pathEnd() == gurl2.pathEnd()); + EXPECT_TRUE(kurl2.pathAfterLastSlash() == gurl2.pathAfterLastSlash()); + + const char* src3 = "javascript:foobar"; + WebCore::GoogleKURL gurl3(src3); + WebCore::WebKitKURL kurl3(src3); + + EXPECT_TRUE(kurl3.hostStart() == gurl3.hostStart()); + EXPECT_TRUE(kurl3.hostEnd() == gurl3.hostEnd()); + EXPECT_TRUE(kurl3.pathStart() == gurl3.pathStart()); + EXPECT_TRUE(kurl3.pathEnd() == gurl3.pathEnd()); + EXPECT_TRUE(kurl3.pathAfterLastSlash() == gurl3.pathAfterLastSlash()); +}
\ No newline at end of file diff --git a/webkit/port/platform/MIMETypeRegistry.cpp b/webkit/port/platform/MIMETypeRegistry.cpp index 6c936d1..1c3f38b 100644 --- a/webkit/port/platform/MIMETypeRegistry.cpp +++ b/webkit/port/platform/MIMETypeRegistry.cpp @@ -43,11 +43,17 @@ namespace WebCore // (and will give linker error if used): // HashSet<String> &MIMETypeRegistry::getSupportedImageMIMETypes() // HashSet<String> &MIMETypeRegistry::getSupportedImageResourceMIMETypes() -// HashSet<String> &MIMETypeRegistry::getSupportedNonImageMIMETypes() // These methods are referenced by WebKit but not WebCore. // Therefore defering their implementation until necessary. // Since the returned HashSet is mutable, chrome would need to synchronize -// the mime type registry between renderer/browser. +// the mime type registry between renderer/browser. This one is called, but we +// currently stub it out until this can be resolved. +HashSet<String>& MIMETypeRegistry::getSupportedNonImageMIMETypes() +{ + static HashSet<String> supportedNonImageMIMETypes; + return supportedNonImageMIMETypes; +} + // Checks if any of the plugins handle this extension, and if so returns the // plugin's mime type for this extension. Otherwise returns an empty string. @@ -74,6 +80,12 @@ bool MIMETypeRegistry::isSupportedImageMIMEType(const String& mimeType) && net::IsSupportedImageMimeType(mimeType.latin1().data()); } +bool MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(const String& mimeType) +{ + // TODO(brettw) fill this out. See: http://trac.webkit.org/changeset/30888 + return isSupportedImageMIMEType(mimeType); +} + bool MIMETypeRegistry::isSupportedJavaScriptMIMEType(const String& mimeType) { return !mimeType.isEmpty() diff --git a/webkit/port/platform/MimeTypeRegistryWin.cpp b/webkit/port/platform/MimeTypeRegistryWin.cpp index 0b214b8..a4eaa9f 100644 --- a/webkit/port/platform/MimeTypeRegistryWin.cpp +++ b/webkit/port/platform/MimeTypeRegistryWin.cpp @@ -59,8 +59,6 @@ String MIMETypeRegistry::getPreferredExtensionForMIMEType(const String& type) return webkit_glue::StdWStringToString(ext); } -// NOTE: This does not work in the sandbox because the renderer doesn't have -// access to the Windows Registry. String MIMETypeRegistry::getMIMETypeForExtension(const String &ext) { if (ext.isEmpty()) diff --git a/webkit/port/platform/PasteboardWin.cpp b/webkit/port/platform/PasteboardWin.cpp index dae2ab5..f22b85f 100644 --- a/webkit/port/platform/PasteboardWin.cpp +++ b/webkit/port/platform/PasteboardWin.cpp @@ -28,7 +28,6 @@ #include "ClipboardUtilitiesWin.h" #include "CString.h" -#include "DeprecatedString.h" #include "DocumentFragment.h" #include "Document.h" #include "Element.h" @@ -82,7 +81,7 @@ void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, webkit_glue::ClipboardWriteHTML( webkit_glue::StringToStdWString( createMarkup(selectedRange, 0, AnnotateForInterchange)), - GURL(webkit_glue::DeprecatedStringToStdWString( + GURL(webkit_glue::StringToStdWString( selectedRange->startContainer(ec)->document()->url()))); // Put plain string on the pasteboard. CF_UNICODETEXT covers CF_TEXT as well @@ -117,7 +116,7 @@ void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame) webkit_glue::ClipboardWriteHTML(link, GURL()); // bare-bones CF_UNICODETEXT support - std::wstring spec(webkit_glue::DeprecatedStringToStdWString(url.deprecatedString())); + std::wstring spec(webkit_glue::StringToStdWString(url)); webkit_glue::ClipboardWriteText(spec); } @@ -131,7 +130,7 @@ void Pasteboard::writeImage(Node* node, const KURL& url, const String& title) ASSERT(image); clear(); - NativeImageSkia* bitmap = image->getBitmap(); + NativeImageSkia* bitmap = image->nativeImageForCurrentFrame(); if (bitmap) webkit_glue::ClipboardWriteBitmap(*bitmap); if (!url.isEmpty()) { @@ -146,7 +145,7 @@ void Pasteboard::writeImage(Node* node, const KURL& url, const String& title) webkit_glue::ClipboardWriteHTML(markup, GURL()); // bare-bones CF_UNICODETEXT support - std::wstring spec(webkit_glue::DeprecatedStringToStdWString(url.deprecatedString())); + std::wstring spec(webkit_glue::StringToStdWString(url.string())); webkit_glue::ClipboardWriteText(spec); } } diff --git a/webkit/port/platform/PlatformScrollBar.h b/webkit/port/platform/PlatformScrollBar.h index ee619e1..4b3c17b 100644 --- a/webkit/port/platform/PlatformScrollBar.h +++ b/webkit/port/platform/PlatformScrollBar.h @@ -59,8 +59,10 @@ namespace WebCore { class PlatformScrollbar : public Widget, public Scrollbar { public: - PlatformScrollbar(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize); - + static PassRefPtr<PlatformScrollbar> create(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize size) + { + return adoptRef(new PlatformScrollbar(client, orientation, size)); + } virtual ~PlatformScrollbar(); virtual bool isWidget() const { return true; } @@ -105,6 +107,8 @@ protected: virtual void updateThumbProportion(); private: + PlatformScrollbar(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize); + // Scroll bar segment identifiers enum Segment { Arrow1 = 0, diff --git a/webkit/port/platform/PlatformScrollBarWin.cpp b/webkit/port/platform/PlatformScrollBarWin.cpp index c921e97..723d321 100644 --- a/webkit/port/platform/PlatformScrollBarWin.cpp +++ b/webkit/port/platform/PlatformScrollBarWin.cpp @@ -189,17 +189,16 @@ void PlatformScrollbar::DrawTickmarks(GraphicsContext* context) const // will not be serialized, i.e. composition is done in the renderer and // never in the browser. // Prepare the bitmap for drawing the tickmarks on the scroll bar. - gfx::PlatformCanvasWin* canvas = PlatformContextToPlatformContextSkia( - context->platformContext())->canvas(); + gfx::PlatformCanvas* canvas = context->platformContext()->canvas(); // Load the image for the tickmark. - static Image* dashImg = Image::loadPlatformResource("tickmarkDash"); + static RefPtr<Image> dashImg = Image::loadPlatformResource("tickmarkDash"); DCHECK(dashImg); if (dashImg->isNull()) { ASSERT_NOT_REACHED(); return; } - const NativeImageSkia* dash = dashImg->getBitmap(); + const NativeImageSkia* dash = dashImg->nativeImageForCurrentFrame(); for (Vector<RefPtr<Range> >::const_iterator i = tickmarks.begin(); @@ -237,10 +236,9 @@ void PlatformScrollbar::paint(GraphicsContext* gc, const IntRect& damageRect) layout(); - HDC hdc = gc->getWindowsContext(); + HDC hdc = gc->getWindowsContext(damageRect); const bool horz = orientation() == HorizontalScrollbar; - const PlatformContextSkia* const skia = - PlatformContextToPlatformContextSkia(gc->platformContext()); + const PlatformContextSkia* const skia = gc->platformContext(); const gfx::NativeTheme* const nativeTheme = skia->nativeTheme(); gfx::PlatformCanvasWin* const canvas = skia->canvas(); @@ -308,7 +306,7 @@ void PlatformScrollbar::paint(GraphicsContext* gc, const IntRect& damageRect) DFCS_SCROLLRIGHT : DFCS_SCROLLDOWN) | getClassicThemeState(Arrow2), &m_segmentRects[Arrow2]); - gc->releaseWindowsContext(hdc); + gc->releaseWindowsContext(hdc, damageRect); gc->restore(); } diff --git a/webkit/port/platform/PopupMenuWin.cpp b/webkit/port/platform/PopupMenuWin.cpp index 145e0fb..ae0e407c 100644 --- a/webkit/port/platform/PopupMenuWin.cpp +++ b/webkit/port/platform/PopupMenuWin.cpp @@ -757,7 +757,7 @@ Font PopupListBox::getRowFont(int rowIndex) if (m_popupClient->itemIsLabel(rowIndex)) { // Bold-ify labels (ie, an <optgroup> heading). FontDescription d = itemFont.fontDescription(); - d.setBold(true); + d.setWeight(FontWeightBold); Font font(d, itemFont.letterSpacing(), itemFont.wordSpacing()); font.update(0); return font; diff --git a/webkit/port/platform/ScrollViewWin.cpp b/webkit/port/platform/ScrollViewWin.cpp index 6761073..6964f82 100644 --- a/webkit/port/platform/ScrollViewWin.cpp +++ b/webkit/port/platform/ScrollViewWin.cpp @@ -69,6 +69,8 @@ public: , m_hScrollbarMode(ScrollbarAuto) , m_visible(false) , m_attachedToWindow(false) + , m_panScrollIconPoint(0,0) + , m_drawPanScrollIcon(false) { } @@ -126,13 +128,17 @@ public: HashSet<Widget*> m_children; bool m_visible; bool m_attachedToWindow; + IntPoint m_panScrollIconPoint; + bool m_drawPanScrollIcon; }; +const int panIconSizeLength = 20; + void ScrollView::ScrollViewPrivate::setHasHorizontalScrollbar(bool hasBar) { if (Scrollbar::hasPlatformScrollbars()) { if (hasBar && !m_hBar) { - m_hBar = new PlatformScrollbar(this, HorizontalScrollbar, RegularScrollbar); + m_hBar = PlatformScrollbar::create(this, HorizontalScrollbar, RegularScrollbar); m_view->addChild(m_hBar.get()); } else if (!hasBar && m_hBar) { m_view->removeChild(m_hBar.get()); @@ -145,7 +151,7 @@ void ScrollView::ScrollViewPrivate::setHasVerticalScrollbar(bool hasBar) { if (Scrollbar::hasPlatformScrollbars()) { if (hasBar && !m_vBar) { - m_vBar = new PlatformScrollbar(this, VerticalScrollbar, RegularScrollbar); + m_vBar = PlatformScrollbar::create(this, VerticalScrollbar, RegularScrollbar); m_view->addChild(m_vBar.get()); } else if (!hasBar && m_vBar) { m_view->removeChild(m_vBar.get()); @@ -314,8 +320,7 @@ void ScrollView::ScrollViewPrivate::highlightMatches( // will not be serialized, i.e. composition is done in the renderer and // never in the browser. // Prepare for drawing the arrows along the scroll bar. - gfx::PlatformCanvasWin* canvas = PlatformContextToPlatformContextSkia( - context->platformContext())->canvas(); + gfx::PlatformCanvas* canvas = context->platformContext()->canvas(); int horz_start = 0; int horz_end = m_view->width(); @@ -338,7 +343,8 @@ void ScrollView::ScrollViewPrivate::highlightMatches( vert_end -= PlatformScrollbar::horizontalScrollbarHeight() + 1; } - HDC hdc = context->getWindowsContext(); + IntRect view_rect(IntPoint(), m_view->size()); + HDC hdc = context->getWindowsContext(view_rect); // We create a memory DC, copy the bits we want to highlight to the DC and // then MERGE_COPY pieces of it back with a yellow brush selected (which @@ -391,7 +397,7 @@ void ScrollView::ScrollViewPrivate::highlightMatches( DeleteDC(mem_dc); - context->releaseWindowsContext(hdc); + context->releaseWindowsContext(hdc, view_rect); context->restore(); } @@ -421,12 +427,7 @@ void ScrollView::ScrollViewPrivate::highlightInspectedNode( // TODO(ojan): http://b/1143975 Draw the padding/border/margin boxes in // different colors. - SkRect destRect; - WebCoreRectToSkiaRect(inspected_node->getRect(), &destRect); - - PlatformContextSkia* skia = PlatformContextToPlatformContextSkia( - context->platformContext()); - skia->paintSkPaint(destRect, paint); + context->platformContext()->paintSkPaint(inspected_node->getRect(), paint); } void ScrollView::ScrollViewPrivate::highlightRange(HDC hdc, HDC mem_dc, @@ -531,8 +532,15 @@ void ScrollView::updateContents(const IntRect& rect, bool now) if (containingWindowRect.y() < 0) containingWindowRect.setY(0); + updateWindowRect(containingWindowRect, now); +} + +void ScrollView::updateWindowRect(const IntRect& rect, bool now) +{ + // TODO(dglazkov): make sure this is actually the right way to do this + // Cache the dirty spot. - addToDirtyRegion(containingWindowRect); + addToDirtyRegion(rect); // since painting always happens asynchronously, we don't have a way to // honor the "now" parameter. it is unclear if it matters. @@ -1196,4 +1204,24 @@ bool ScrollView::allowsScrolling() const return m_data->allowsScrolling(); } +void ScrollView::printPanScrollIcon(const IntPoint& iconPosition) +{ + m_data->m_drawPanScrollIcon = true; + m_data->m_panScrollIconPoint = IntPoint(iconPosition.x() - panIconSizeLength / 2 , iconPosition.y() - panIconSizeLength / 2) ; + + updateWindowRect(IntRect(m_data->m_panScrollIconPoint, IntSize(panIconSizeLength,panIconSizeLength)), true); +} + +void ScrollView::removePanScrollIcon() +{ + m_data->m_drawPanScrollIcon = false; + + updateWindowRect(IntRect(m_data->m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)), true); +} + +bool ScrollView::isScrollable() +{ + return m_data->m_vBar != 0 || m_data->m_hBar != 0; +} + } // namespace WebCore diff --git a/webkit/port/platform/cairo.h b/webkit/port/platform/cairo.h deleted file mode 100644 index 71786e4..0000000 --- a/webkit/port/platform/cairo.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// We compile WebKit with PLATFORM(CAIRO) defined. This only affects a few -// places in the shared headers. Therefore, we provide this replacement -// <cairo.h> that defines the Cairo types used in these shared headers to be -// the types that we desire. - -#ifndef CHROME_WEBKIT_PORT_PLATFORM_CAIRO_H__ -#define CHROME_WEBKIT_PORT_PLATFORM_CAIRO_H__ - -#include "SkMatrix.h" - -// For AffineTransform.h, this allows us to define the internal matrix type -// to be the Skia one we use internally. -typedef SkMatrix cairo_matrix_t; - -// For GlyphBuffer.h -struct cairo_glyph_t { - // Cairo defines this to be an unsigned long. PLATFORM(CG) in GlyphBuffer.h - // defines the glyph to be an unsigned short, so we do the same here. - unsigned short index; - - // Totally unused. This is defined by Cairo and set in GlyphBuffer.h to 0, - // so we define it. We use unsigned short so that the size of this structure - // is padded out to 4 bytes. - unsigned short y; - - // Cairo also defines an |x| here, but it's never used by the shared headers. -}; - -#endif // CHROME_WEBKIT_PORT_PLATFORM_CAIRO_H__ - diff --git a/webkit/port/platform/graphics/AffineTransformSkia.cpp b/webkit/port/platform/graphics/AffineTransformSkia.cpp index ed4942a..30d87d3 100644 --- a/webkit/port/platform/graphics/AffineTransformSkia.cpp +++ b/webkit/port/platform/graphics/AffineTransformSkia.cpp @@ -78,26 +78,18 @@ void AffineTransform::map(double x, double y, double *x2, double *y2) const *y2 = SkScalarToDouble(dst.fY); } -IntRect AffineTransform::mapRect(const IntRect &rect) const +IntRect AffineTransform::mapRect(const IntRect& src) const { - SkRect src, dst; - SkIRect ir; - - WebCoreRectToSkiaRect(rect, &src); + SkRect dst; m_transform.mapRect(&dst, src); - dst.round(&ir); - - return IntRect(ir.fLeft, ir.fTop, ir.width(), ir.height()); + return enclosingIntRect(dst); } -FloatRect AffineTransform::mapRect(const FloatRect &rect) const +FloatRect AffineTransform::mapRect(const FloatRect& src) const { - SkRect src, dst; - - WebCoreRectToSkiaRect(rect, &src); + SkRect dst; m_transform.mapRect(&dst, src); - - return FloatRect(dst.fLeft, dst.fTop, dst.width(), dst.height()); + return dst; } bool AffineTransform::isIdentity() const @@ -152,18 +144,18 @@ AffineTransform::operator SkMatrix() const return m_transform; } -bool AffineTransform::operator==(const AffineTransform &m2) const +bool AffineTransform::operator==(const AffineTransform& m2) const { return m_transform == m2.m_transform; } -AffineTransform &AffineTransform::operator*= (const AffineTransform &m2) +AffineTransform &AffineTransform::operator*=(const AffineTransform& m2) { m_transform.setConcat(m2.m_transform, m_transform); return *this; } -AffineTransform AffineTransform::operator* (const AffineTransform &m2) +AffineTransform AffineTransform::operator*(const AffineTransform& m2) { AffineTransform cat; @@ -171,46 +163,58 @@ AffineTransform AffineTransform::operator* (const AffineTransform &m2) return cat; } -double AffineTransform::a() const { +double AffineTransform::a() const +{ return SkScalarToDouble(m_transform.getScaleX()); } -void AffineTransform::setA(double a) { +void AffineTransform::setA(double a) +{ m_transform.setScaleX(WebCoreDoubleToSkScalar(a)); } -double AffineTransform::b() const { +double AffineTransform::b() const +{ return SkScalarToDouble(m_transform.getSkewY()); } -void AffineTransform::setB(double b) { +void AffineTransform::setB(double b) +{ m_transform.setSkewY(WebCoreDoubleToSkScalar(b)); } -double AffineTransform::c() const { +double AffineTransform::c() const +{ return SkScalarToDouble(m_transform.getSkewX()); } -void AffineTransform::setC(double c) { +void AffineTransform::setC(double c) +{ m_transform.setSkewX(WebCoreDoubleToSkScalar(c)); } -double AffineTransform::d() const { +double AffineTransform::d() const +{ return SkScalarToDouble(m_transform.getScaleY()); } -void AffineTransform::setD(double d) { +void AffineTransform::setD(double d) +{ m_transform.setScaleY(WebCoreDoubleToSkScalar(d)); } -double AffineTransform::e() const { +double AffineTransform::e() const +{ return SkScalarToDouble(m_transform.getTranslateX()); } -void AffineTransform::setE(double e) { +void AffineTransform::setE(double e) +{ m_transform.setTranslateX(WebCoreDoubleToSkScalar(e)); } -double AffineTransform::f() const { +double AffineTransform::f() const +{ return SkScalarToDouble(m_transform.getTranslateY()); } -void AffineTransform::setF(double f) { +void AffineTransform::setF(double f) +{ m_transform.setTranslateY(WebCoreDoubleToSkScalar(f)); } -} +} // namespace WebCore diff --git a/webkit/port/platform/graphics/ColorSkia.cpp b/webkit/port/platform/graphics/ColorSkia.cpp new file mode 100644 index 0000000..23c5eb0 --- /dev/null +++ b/webkit/port/platform/graphics/ColorSkia.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2008 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Color.h" + +#include "SkColor.h" + +#include <wtf/Assertions.h> + +namespace WebCore { + +COMPILE_ASSERT(SK_ColorBLACK == Color::black, SkColorAndColorAreLaidOutTheSame); + +} // namespace WebCore diff --git a/webkit/port/platform/graphics/FloatPointSkia.cpp b/webkit/port/platform/graphics/FloatPointSkia.cpp new file mode 100644 index 0000000..01c94ef --- /dev/null +++ b/webkit/port/platform/graphics/FloatPointSkia.cpp @@ -0,0 +1,47 @@ +/*
+ * Copyright (C) 2008 Google, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FloatPoint.h"
+
+#include "SkPoint.h"
+#include "SkiaUtils.h"
+
+namespace WebCore {
+
+FloatPoint::FloatPoint(const SkPoint& p)
+ : m_x(p.fX)
+ , m_y(p.fY)
+{
+}
+
+FloatPoint::operator SkPoint() const
+{
+ SkPoint p = { WebCoreFloatToSkScalar(m_x), WebCoreFloatToSkScalar(m_y) };
+ return p;
+}
+
+} // namespace WebCore
+
diff --git a/webkit/port/bridge/HistoryWin.cpp b/webkit/port/platform/graphics/FloatRectSkia.cpp index 0a835ba..4676983 100644 --- a/webkit/port/bridge/HistoryWin.cpp +++ b/webkit/port/platform/graphics/FloatRectSkia.cpp @@ -1,49 +1,46 @@ -/* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "History.h" - -#include "CString.h" -#include "DeprecatedString.h" -#include "Document.h" -#include "PlatformString.h" -#include "SecurityOrigin.h" - -#include "webkit/glue/webkit_glue.h" - -namespace WebCore { - -bool historyContains(const UChar* characters, unsigned length, - Document* document) { - // check the document's DNS prefetch settings and pass up to the renderer - CString document_host = document->securityOrigin()->host().utf8(); - return webkit_glue::HistoryContains( - reinterpret_cast<const char16*>(characters), length, - document_host.data(), document_host.length(), - document->isDNSPrefetchEnabled()); -} - -} +/*
+ * Copyright (C) 2008 Google, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FloatRect.h"
+
+#include "SkRect.h"
+
+namespace WebCore {
+
+FloatRect::FloatRect(const SkRect& r)
+ : m_location(r.fLeft, r.fTop)
+ , m_size(r.width(), r.height())
+{
+}
+
+FloatRect::operator SkRect() const
+{
+ SkRect rect = { x(), y(), right(), bottom() };
+ return rect;
+}
+
+} // namespace WebCore
+
diff --git a/webkit/port/platform/graphics/FontCacheWin.cpp b/webkit/port/platform/graphics/FontCacheWin.cpp index 29fe120..e4b2c65 100644 --- a/webkit/port/platform/graphics/FontCacheWin.cpp +++ b/webkit/port/platform/graphics/FontCacheWin.cpp @@ -29,6 +29,7 @@ #include "config.h" #include "FontCache.h" #include "Font.h" +#include "HashSet.h" #include "SimpleFontData.h" #include "StringHash.h" #include <algorithm> @@ -555,6 +556,22 @@ FontPlatformData* FontCache::getLastResortFallbackFont( return getCachedFontPlatformData(description, fontStr); } +static LONG toGDIFontWeight(FontWeight fontWeight) +{ + static LONG gdiFontWeights[] = { + FW_THIN, // FontWeight100 + FW_EXTRALIGHT, // FontWeight200 + FW_LIGHT, // FontWeight300 + FW_NORMAL, // FontWeight400 + FW_MEDIUM, // FontWeight500 + FW_SEMIBOLD, // FontWeight600 + FW_BOLD, // FontWeight700 + FW_EXTRABOLD, // FontWeight800 + FW_HEAVY // FontWeight900 + }; + return gdiFontWeights[fontWeight]; +} + // TODO(jungshik): This may not be the best place to put this function. See // TODO in pending/FontCache.h. AtomicString FontCache::getGenericFontForScript(UScriptCode script, const FontDescription& description) @@ -584,16 +601,7 @@ static void FillLogFont(const FontDescription& fontDescription, LOGFONT* winfont : DEFAULT_QUALITY; // Honor user's desktop settings. winfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; winfont->lfItalic = fontDescription.italic(); - - // FIXME: Support weights for real. Do our own enumeration of the available weights. - // We can't rely on Windows here, since we need to follow the CSS2 algorithm for how to fill in - // gaps in the weight list. - // fontExists() used to hardcod Lucida Grande. According to FIXME comment, - // that's because it uses different weights than typical Win32 fonts - // (500/600 instead of 400/700). However, createFontPlatformData - // didn't. Special-casing Lucida Grande in a refactored function - // led to massive webkit test failure. - winfont->lfWeight = fontDescription.bold() ? 700 : 400; + winfont->lfWeight = toGDIFontWeight(fontDescription.weight()); } bool FontCache::fontExists(const FontDescription& fontDescription, const AtomicString& family) @@ -618,6 +626,55 @@ bool FontCache::fontExists(const FontDescription& fontDescription, const AtomicS return LookupAltName(family, altName) && equalIgnoringCase(altName, winName); } +struct TraitsInFamilyProcData { + TraitsInFamilyProcData(const AtomicString& familyName) + : m_familyName(familyName) + { + } + + const AtomicString& m_familyName; + HashSet<unsigned> m_traitsMasks; +}; + +static int CALLBACK traitsInFamilyEnumProc(CONST LOGFONT* logFont, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam) +{ + TraitsInFamilyProcData* procData = reinterpret_cast<TraitsInFamilyProcData*>(lParam); + + unsigned traitsMask = 0; + traitsMask |= logFont->lfItalic ? FontStyleItalicMask : FontStyleNormalMask; + traitsMask |= FontVariantNormalMask; + LONG weight = logFont->lfWeight; + traitsMask |= weight == FW_THIN ? FontWeight100Mask : + weight == FW_EXTRALIGHT ? FontWeight200Mask : + weight == FW_LIGHT ? FontWeight300Mask : + weight == FW_NORMAL ? FontWeight400Mask : + weight == FW_MEDIUM ? FontWeight500Mask : + weight == FW_SEMIBOLD ? FontWeight600Mask : + weight == FW_BOLD ? FontWeight700Mask : + weight == FW_EXTRABOLD ? FontWeight800Mask : + FontWeight900Mask; + procData->m_traitsMasks.add(traitsMask); + return 1; +} + +void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks) +{ + HDC hdc = GetDC(0); + + LOGFONT logFont; + logFont.lfCharSet = DEFAULT_CHARSET; + unsigned familyLength = min(familyName.length(), static_cast<unsigned>(LF_FACESIZE - 1)); + memcpy(logFont.lfFaceName, familyName.characters(), familyLength * sizeof(UChar)); + logFont.lfFaceName[familyLength] = 0; + logFont.lfPitchAndFamily = 0; + + TraitsInFamilyProcData procData(familyName); + EnumFontFamiliesEx(hdc, &logFont, traitsInFamilyEnumProc, reinterpret_cast<LPARAM>(&procData), 0); + copyToVector(procData.m_traitsMasks, traitsMasks); + + ReleaseDC(0, hdc); +} + FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) { LOGFONT winfont = {0}; @@ -631,8 +688,8 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD if (!hfont) return 0; - // TODO(pamg): Do we need to use predefined fonts "guaranteed" to exist - // when we're running in layout-test mode? + // TODO(pamg): Do we need to use predefined fonts "guaranteed" to exist + // when we're running in layout-test mode? if (!equalIgnoringCase(family, winName)) { // For CJK fonts with both English and native names, // GetTextFace returns a native name under the font's "locale" diff --git a/webkit/port/platform/graphics/FontPlatformData.h b/webkit/port/platform/graphics/FontPlatformData.h index ff0d863..25938dc 100644 --- a/webkit/port/platform/graphics/FontPlatformData.h +++ b/webkit/port/platform/graphics/FontPlatformData.h @@ -25,6 +25,7 @@ #define FontPlatformData_H #include "StringImpl.h" +#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> typedef struct HFONT__ *HFONT; @@ -36,21 +37,13 @@ class FontDescription; class FontPlatformData { public: - class Deleted {}; - // Used for deleted values in the font cache's hash tables. The hash table // will create us with this structure, and it will compare other values // to this "Deleted" one. It expects the Deleted one to be differentiable // from the NULL one (created with the empty constructor), so we can't just // set everything to NULL. - // - // NOTE: On WebKit trunk now, this is changed to the new value - // WTF::HashTableDeletedValue (declared in RefPtr.h). When we merge to a - // version with that, we should use it and remove our "Deleted" version. - // We would just assign the magic WTF::HashTableDeletedValue to our - // m_font RefPtr. - FontPlatformData(Deleted) - : m_font(RefCountedHFONT::createDeleted()) + FontPlatformData(WTF::HashTableDeletedValueType) + : m_font(hashTableDeletedFontValue()) , m_size(-1) , m_isMLangFont(false) {} @@ -65,6 +58,8 @@ public: bool isMLangFont); FontPlatformData(float size, bool bold, bool oblique); + bool isHashTableDeletedValue() const { return m_font == hashTableDeletedFontValue(); } + ~FontPlatformData(); HFONT hfont() const { return m_font ? m_font->hfont() : 0; } @@ -87,8 +82,10 @@ private: // don't really want to re-create the HFONT. class RefCountedHFONT : public RefCounted<RefCountedHFONT> { public: - static PassRefPtr<RefCountedHFONT> create(HFONT hfont) { return adoptRef(new RefCountedHFONT(hfont)); } - static PassRefPtr<RefCountedHFONT> createDeleted() { return adoptRef(new RefCountedHFONT(reinterpret_cast<HFONT>(-1))); } + static PassRefPtr<RefCountedHFONT> create(HFONT hfont) + { + return adoptRef(new RefCountedHFONT(hfont)); + } ~RefCountedHFONT(); @@ -102,14 +99,15 @@ private: // The create() function assumes there is already a refcount of one // so it can do adoptRef. RefCountedHFONT(HFONT hfont) - : RefCounted<RefCountedHFONT>(1) - , m_hfont(hfont) + : m_hfont(hfont) { } HFONT m_hfont; }; + static RefCountedHFONT* hashTableDeletedFontValue(); + RefPtr<RefCountedHFONT> m_font; float m_size; // Point size of the font in pixels. diff --git a/webkit/port/platform/graphics/FontPlatformDataWin.cpp b/webkit/port/platform/graphics/FontPlatformDataWin.cpp index 53ade3e..2aad126 100644 --- a/webkit/port/platform/graphics/FontPlatformDataWin.cpp +++ b/webkit/port/platform/graphics/FontPlatformDataWin.cpp @@ -55,4 +55,11 @@ FontPlatformData::RefCountedHFONT::~RefCountedHFONT() DeleteObject(m_hfont); } +FontPlatformData::RefCountedHFONT* FontPlatformData::hashTableDeletedFontValue() +{ + static RefPtr<RefCountedHFONT> deletedValue = + RefCountedHFONT::create(reinterpret_cast<HFONT>(-1)); + return deletedValue.get(); +} + } diff --git a/webkit/port/platform/graphics/FontWin.cpp b/webkit/port/platform/graphics/FontWin.cpp index 0287d3f..9bd5a7a 100644 --- a/webkit/port/platform/graphics/FontWin.cpp +++ b/webkit/port/platform/graphics/FontWin.cpp @@ -47,8 +47,6 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const FloatPoint& point) const { PlatformGraphicsContext* context = graphicsContext->platformContext(); - SkPoint origin; - WebCorePointToSkiaPoint(point, &origin); // Max buffer length passed to the underlying windows API. const int kMaxBufferLength = 1024; @@ -84,7 +82,7 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, // the 'point' represents the baseline, so we need to move it up to the // top of the bounding square by subtracting the ascent - SkPoint origin2 = origin; + SkPoint origin2 = point; origin2.fY -= font->ascent(); origin2.fX += chunk_x; @@ -135,10 +133,7 @@ void Font::drawComplexText(GraphicsContext* context, int to) const { UniscribeStateTextRun state(run, *this); - PlatformContextSkia* skia = PlatformContextToPlatformContextSkia(context->platformContext()); - SkPoint p; - WebCorePointToSkiaPoint(point, &p); - skia->paintComplexText(state, p, from, to, ascent()); + context->platformContext()->paintComplexText(state, point, from, to, ascent()); } float Font::floatWidthForComplexText(const TextRun& run) const @@ -161,4 +156,4 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includ return char_index; } -} +} // namespace WebCore diff --git a/webkit/port/platform/graphics/GradientSkia.cpp b/webkit/port/platform/graphics/GradientSkia.cpp new file mode 100644 index 0000000..b287bde --- /dev/null +++ b/webkit/port/platform/graphics/GradientSkia.cpp @@ -0,0 +1,142 @@ +/*
+ * Copyright (C) 2008 Google, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Gradient.h"
+
+#include "CSSParser.h"
+#include "GraphicsContext.h"
+#include "NotImplemented.h"
+
+#include "SkGradientShader.h"
+#include "SkiaUtils.h"
+
+namespace WebCore {
+
+void Gradient::platformDestroy()
+{
+ if (m_gradient)
+ m_gradient->safeUnref();
+ m_gradient = 0;
+}
+
+static inline U8CPU F2B(float x)
+{
+ return static_cast<int>(x * 255);
+}
+
+static SkColor makeSkColor(float a, float r, float g, float b)
+{
+ return SkColorSetARGB(F2B(a), F2B(r), F2B(g), F2B(b));
+}
+
+// Determine the total number of stops needed, including pseudo-stops at the
+// ends as necessary.
+static size_t total_stops_needed(const Gradient::ColorStop* stopData, size_t count)
+{
+ const Gradient::ColorStop* stop = stopData;
+ size_t count_used = count;
+ if (count < 1 || stop->stop > 0.0)
+ count_used++;
+ stop += count - 1;
+ if (count < 2 || stop->stop < 1.0)
+ count_used++;
+ return count_used;
+}
+
+// Collect sorted stop position and color information into the pos and colors
+// buffers, ensuring stops at both 0.0 and 1.0. The buffers must be large
+// enough to hold information for all stops, including the new endpoints if
+// stops at 0.0 and 1.0 aren't already included.
+static void fill_stops(const Gradient::ColorStop* stopData,
+ size_t count, SkScalar* pos, SkColor* colors)
+{
+ const Gradient::ColorStop* stop = stopData;
+ size_t start = 0;
+ if (count < 1) {
+ // A gradient with no stops must be transparent black.
+ pos[0] = WebCoreFloatToSkScalar(0.0);
+ colors[0] = makeSkColor(0.0, 0.0, 0.0, 0.0);
+ start = 1;
+ } else if (stop->stop > 0.0) {
+ // Copy the first stop to 0.0. The first stop position may have a slight
+ // rounding error, but we don't care in this float comparison, since
+ // 0.0 comes through cleanly and people aren't likely to want a gradient
+ // with a stop at (0 + epsilon).
+ pos[0] = WebCoreFloatToSkScalar(0.0);
+ colors[0] = makeSkColor(stop->alpha, stop->red, stop->green, stop->blue);
+ start = 1;
+ }
+
+ for (size_t i = start; i < start + count; i++) {
+ pos[i] = WebCoreFloatToSkScalar(stop->stop);
+ colors[i] = makeSkColor(stop->alpha, stop->red, stop->green, stop->blue);
+ ++stop;
+ }
+
+ // Copy the last stop to 1.0 if needed. See comment above about this float
+ // comparison.
+ if (count < 1 || (--stop)->stop < 1.0) {
+ pos[start + count] = WebCoreFloatToSkScalar(1.0);
+ colors[start + count] = colors[start + count - 1];
+ }
+}
+
+SkShader* Gradient::platformGradient()
+{
+ if (m_gradient)
+ return m_gradient;
+
+ size_t count_used = total_stops_needed(m_stops.data(), m_stops.size());
+ ASSERT(count_used >= 2);
+ ASSERT(count_used >= m_stops.size());
+
+ // FIXME: Why is all this manual pointer math needed?!
+ SkAutoMalloc storage(count_used * (sizeof(SkColor) + sizeof(SkScalar)));
+ SkColor* colors = (SkColor*)storage.get();
+ SkScalar* pos = (SkScalar*)(colors + count_used);
+
+ fill_stops(m_stops.data(), m_stops.size(), pos, colors);
+
+ if (m_radial) {
+ m_gradient = SkGradientShader::CreateRadial(m_p1,
+ WebCoreFloatToSkScalar(m_r1), colors, pos,
+ static_cast<int>(count_used), SkShader::kClamp_TileMode);
+ } else {
+ SkPoint pts[2] = { m_p0, m_p1 };
+ m_gradient = SkGradientShader::CreateLinear(pts, colors, pos,
+ static_cast<int>(count_used), SkShader::kClamp_TileMode);
+ }
+
+ return m_gradient;
+}
+
+void Gradient::fill(GraphicsContext* context, const FloatRect& rect)
+{
+ // Until this is filled, we don't support CSSGradients
+ notImplemented();
+}
+
+} // namespace WebCore
diff --git a/webkit/port/platform/graphics/GraphicsContextPrivate.cpp b/webkit/port/platform/graphics/GraphicsContextPlatformPrivate.cpp index d06ee33..7f28d19 100644 --- a/webkit/port/platform/graphics/GraphicsContextPrivate.cpp +++ b/webkit/port/platform/graphics/GraphicsContextPlatformPrivate.cpp @@ -19,9 +19,8 @@ #include "config.h" -#include "GraphicsContextPrivate.h" - #include "GraphicsContext.h" +#include "GraphicsContextPlatformPrivate.h" #include "PlatformContextSkia.h" namespace WebCore { diff --git a/webkit/port/platform/graphics/GraphicsContextPrivate.h b/webkit/port/platform/graphics/GraphicsContextPlatformPrivate.h index 70e3d60..77f5e89 100644 --- a/webkit/port/platform/graphics/GraphicsContextPrivate.h +++ b/webkit/port/platform/graphics/GraphicsContextPlatformPrivate.h @@ -30,9 +30,7 @@ public: GraphicsContextPlatformPrivate(PlatformContextSkia* pgc); ~GraphicsContextPlatformPrivate(); - PlatformContextSkia* platformContext() { - return m_context; - } + PlatformContextSkia* platformContext() { return m_context; } void setShouldDelete(bool should_delete) { m_should_delete = should_delete; diff --git a/webkit/port/platform/graphics/GraphicsContextSkia.cpp b/webkit/port/platform/graphics/GraphicsContextSkia.cpp index 90eb7ea..d282555 100644 --- a/webkit/port/platform/graphics/GraphicsContextSkia.cpp +++ b/webkit/port/platform/graphics/GraphicsContextSkia.cpp @@ -18,20 +18,22 @@ #include "config.h" #include "GraphicsContext.h" +#include "GraphicsContextPlatformPrivate.h" #include "GraphicsContextPrivate.h" #include "wtf/MathExtras.h" #include "Assertions.h" #include "AffineTransform.h" +#include "FloatRect.h" +#include "Gradient.h" +#include "IntRect.h" #include "NativeImageSkia.h" +#include "NotImplemented.h" #include "SkBlurDrawLooper.h" #include "SkCornerPathEffect.h" #include "SkiaUtils.h" -#ifdef ANDROID_CANVAS_IMPL -# include "SkBitmap.h" -# include "SkGradientShader.h" -#endif +#include "SkBitmap.h" #include "base/gfx/platform_canvas_win.h" @@ -165,70 +167,6 @@ void add_corner_arc(SkPath* path, const SkRect& rect, const IntSize& size, int s path->arcTo(r, SkIntToScalar(startAngle), SkIntToScalar(90), false); } -U8CPU F2B(float x) -{ - return (int)(x * 255); -} - -SkColor make_color(float a, float r, float g, float b) -{ - return SkColorSetARGB(F2B(a), F2B(r), F2B(g), F2B(b)); -} - -// Determine the total number of stops needed, including pseudo-stops at the -// ends as necessary. -size_t total_stops_needed(const WebCore::CanvasGradient::ColorStop* stopData, - size_t count) -{ - const WebCore::CanvasGradient::ColorStop* stop = stopData; - size_t count_used = count; - if (count < 1 || stop->stop > 0.0) - count_used++; - stop += count - 1; - if (count < 2 || stop->stop < 1.0) - count_used++; - return count_used; -} - -// Collect sorted stop position and color information into the pos and colors -// buffers, ensuring stops at both 0.0 and 1.0. The buffers must be large -// enough to hold information for all stops, including the new endpoints if -// stops at 0.0 and 1.0 aren't already included. -void fill_stops(const WebCore::CanvasGradient::ColorStop* stopData, - size_t count, SkScalar* pos, SkColor* colors) -{ - const WebCore::CanvasGradient::ColorStop* stop = stopData; - size_t start = 0; - if (count < 1) { - // A gradient with no stops must be transparent black. - pos[0] = WebCoreFloatToSkScalar(0.0); - colors[0] = make_color(0.0, 0.0, 0.0, 0.0); - start = 1; - } else if (stop->stop > 0.0) { - // Copy the first stop to 0.0. The first stop position may have a slight - // rounding error, but we don't care in this float comparison, since - // 0.0 comes through cleanly and people aren't likely to want a gradient - // with a stop at (0 + epsilon). - pos[0] = WebCoreFloatToSkScalar(0.0); - colors[0] = make_color(stop->alpha, stop->red, stop->green, stop->blue); - start = 1; - } - - for (size_t i = start; i < start + count; i++) - { - pos[i] = WebCoreFloatToSkScalar(stop->stop); - colors[i] = make_color(stop->alpha, stop->red, stop->green, stop->blue); - ++stop; - } - - // Copy the last stop to 1.0 if needed. See comment above about this float - // comparison. - if (count < 1 || (--stop)->stop < 1.0) { - pos[start + count] = WebCoreFloatToSkScalar(1.0); - colors[start + count] = colors[start + count - 1]; - } -} - COMPILE_ASSERT(GraphicsContextPlatformPrivate::NoStroke == NoStroke, AssertNoStroke); COMPILE_ASSERT(GraphicsContextPlatformPrivate::SolidStroke == SolidStroke, AssertSolidStroke); COMPILE_ASSERT(GraphicsContextPlatformPrivate::DottedStroke == DottedStroke, AssertDottedStroke); @@ -248,7 +186,7 @@ GraphicsContextPlatformPrivate::StrokeStyle StrokeStyle2StrokeStyle(StrokeStyle // no painting. GraphicsContext::GraphicsContext(PlatformGraphicsContext *gc) : m_common(createGraphicsContextPrivate()) - , m_data(new GraphicsContextPlatformPrivate(PlatformContextToPlatformContextSkia(gc))) + , m_data(new GraphicsContextPlatformPrivate(gc)) { setPaintingDisabled(!m_data->canvas()); } @@ -277,9 +215,8 @@ void GraphicsContext::drawRect(const IntRect& rect) if (paintingDisabled()) return; - SkRect r; - WebCoreRectToSkiaRect(rect, &r); - if (!IsRectReasonable(m_data->canvas()->getTotalMatrix(), r)) { + SkRect r = rect; + if (!IsRectReasonable(getCTM(), r)) { // See the fillRect below. ClipRectToCanvas(*m_data->canvas(), r, &r); } @@ -298,21 +235,17 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) return; SkPaint paint; - SkPoint pts[2]; - - WebCorePointToSkiaPoint(point1, &pts[0]); - WebCorePointToSkiaPoint(point2, &pts[1]); - if (!IsPointReasonable(m_data->canvas()->getTotalMatrix(), pts[0]) || - !IsPointReasonable(m_data->canvas()->getTotalMatrix(), pts[1])) + SkPoint pts[2] = { (SkPoint)point1, (SkPoint)point2 }; + if (!IsPointReasonable(getCTM(), pts[0]) || + !IsPointReasonable(getCTM(), pts[1])) return; //we know these are vertical or horizontal lines, so the length will just be the sum of the //displacement component vectors give or take 1 - probably worth the speed up of no square //root, which also won't be exact - SkPoint disp = pts[1]-pts[0]; - int length = SkScalarRound(disp.fX+disp.fY); - //int length = SkScalarRound(disp.length()); - int width = m_data->setup_paint_stroke(&paint, NULL, length); + SkPoint disp = pts[1] - pts[0]; + int length = SkScalarRound(disp.fX + disp.fY); + int width = m_data->setup_paint_stroke(&paint, 0, length); // "borrowed" this comment and idea from GraphicsContextCG.cpp // For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic @@ -324,12 +257,10 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) if (width & 1) //odd { - if (isVerticalLine) - { + if (isVerticalLine) { pts[0].fX = pts[0].fX + SK_ScalarHalf; pts[1].fX = pts[0].fX; - } - else //Horizontal line + } else //Horizontal line { pts[0].fY = pts[0].fY + SK_ScalarHalf; pts[1].fY = pts[0].fY; @@ -439,26 +370,24 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& pt, } // This method is only used to draw the little circles used in lists. -void GraphicsContext::drawEllipse(const IntRect& rect) +void GraphicsContext::drawEllipse(const IntRect& elipseRect) { if (paintingDisabled()) return; - SkPaint paint; - SkRect oval; - - WebCoreRectToSkiaRect(rect, &oval); - if (!IsRectReasonable(m_data->canvas()->getTotalMatrix(), oval)) + SkRect rect = elipseRect; + if (!IsRectReasonable(getCTM(), rect)) return; + SkPaint paint; if (fillColor().rgb() & 0xFF000000) { m_data->setup_paint_fill(&paint); - m_data->canvas()->drawOval(oval, paint); + m_data->canvas()->drawOval(rect, paint); } if (strokeStyle() != NoStroke) { paint.reset(); - m_data->setup_paint_stroke(&paint, &oval, 0); - m_data->canvas()->drawOval(oval, paint); + m_data->setup_paint_stroke(&paint, &rect, 0); + m_data->canvas()->drawOval(rect, paint); } } @@ -478,27 +407,23 @@ void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan) if (paintingDisabled()) return; - SkPath path; SkPaint paint; - SkRect oval; - - WebCoreRectToSkiaRect(r, &oval); + SkRect oval = r; if (strokeStyle() == NoStroke) { m_data->setup_paint_fill(&paint); // we want the fill color paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(WebCoreFloatToSkScalar(strokeThickness())); - } - else { + } else m_data->setup_paint_stroke(&paint, NULL, 0); - } // we do this before converting to scalar, so we don't overflow SkFixed startAngle = fast_mod(startAngle, 360); angleSpan = fast_mod(angleSpan, 360); + SkPath path; path.addArc(oval, SkIntToScalar(-startAngle), SkIntToScalar(-angleSpan)); - if (!IsPathReasonable(m_data->canvas()->getTotalMatrix(), path)) + if (!IsPathReasonable(getCTM(), path)) return; m_data->canvas()->drawPath(path, paint); } @@ -511,7 +436,6 @@ void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* poin if (numPoints <= 1) return; - SkPaint paint; SkPath path; path.incReserve(numPoints); @@ -519,9 +443,10 @@ void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* poin for (size_t i = 1; i < numPoints; i++) path.lineTo(WebCoreFloatToSkScalar(points[i].x()), WebCoreFloatToSkScalar(points[i].y())); - if (!IsPathReasonable(m_data->canvas()->getTotalMatrix(), path)) + if (!IsPathReasonable(getCTM(), path)) return; + SkPaint paint; if (fillColor().rgb() & 0xFF000000) { m_data->setup_paint_fill(&paint); m_data->canvas()->drawPath(path, paint); @@ -534,171 +459,115 @@ void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* poin } } -#ifdef ANDROID_CANVAS_IMPL - -static void check_set_shader(SkPaint* paint, SkShader* s0, SkShader* s1) -{ - if (s0) { - paint->setShader(s0); - } - else if (s1) { - paint->setShader(s1); - } -} - - -void GraphicsContext::fillPath(const Path& webCorePath, PlatformGradient* grad, PlatformPattern* pat) -{ - fillPath(PathToSkPath(webCorePath), grad, pat); -} - -void GraphicsContext::fillPath(PlatformPath* path, PlatformGradient* grad, PlatformPattern* pat) +void GraphicsContext::fillPath() { if (paintingDisabled()) return; - if (!IsPathReasonable(m_data->canvas()->getTotalMatrix(), *path)) + const SkPath& path = *m_data->currentPath(); + if (!IsPathReasonable(getCTM(), path)) return; - SkPaint paint; + const GraphicsContextState& state = m_common->state; + ColorSpace colorSpace = state.fillColorSpace; - m_data->setup_paint_fill(&paint); - check_set_shader(&paint, grad, pat); + if (colorSpace == SolidColorSpace && !fillColor().alpha()) + return; - m_data->canvas()->drawPath(*path, paint); -} + SkPaint paint; + m_data->setup_paint_fill(&paint); + if (colorSpace == PatternColorSpace) { + SkShader* pat = state.fillPattern->createPlatformPattern(getCTM()); + paint.setShader(pat); + pat->unref(); + } else if (colorSpace == GradientColorSpace) + paint.setShader(state.fillGradient->platformGradient()); -void GraphicsContext::strokePath(const Path& webCorePath, PlatformGradient* grad, PlatformPattern* pat) -{ - strokePath(PathToSkPath(webCorePath), grad, pat); + m_data->canvas()->drawPath(path, paint); } -void GraphicsContext::strokePath(PlatformPath* path, PlatformGradient* grad, PlatformPattern* pat) +void GraphicsContext::strokePath() { if (paintingDisabled()) return; - if (!IsPathReasonable(m_data->canvas()->getTotalMatrix(), *path)) + const SkPath& path = *m_data->currentPath(); + if (!IsPathReasonable(getCTM(), path)) return; - SkPaint paint; + const GraphicsContextState& state = m_common->state; + ColorSpace colorSpace = state.strokeColorSpace; + + if (colorSpace == SolidColorSpace && !strokeColor().alpha()) + return; + SkPaint paint; m_data->setup_paint_stroke(&paint, NULL, 0); - check_set_shader(&paint, grad, pat); - m_data->canvas()->drawPath(*path, paint); + if (colorSpace == PatternColorSpace) { + SkShader* pat = state.strokePattern->createPlatformPattern(getCTM()); + paint.setShader(pat); + pat->unref(); + } else if (colorSpace == GradientColorSpace) + paint.setShader(state.strokeGradient->platformGradient()); + + m_data->canvas()->drawPath(path, paint); } -void GraphicsContext::fillRect(const FloatRect& rect, PlatformGradient* grad, PlatformPattern* pat) +void GraphicsContext::fillRect(const FloatRect& rect) { if (paintingDisabled()) return; - SkPaint paint; - m_data->setup_paint_fill(&paint); - check_set_shader(&paint, grad, pat); - - SkRect r; - WebCoreRectToSkiaRect(rect, &r); - if (!IsRectReasonable(m_data->canvas()->getTotalMatrix(), r)) { + SkRect r = rect; + if (!IsRectReasonable(getCTM(), r)) { // See the other version of fillRect below. ClipRectToCanvas(*m_data->canvas(), r, &r); } - m_data->canvas()->drawRect(r, paint); -} + const GraphicsContextState& state = m_common->state; + ColorSpace colorSpace = state.fillColorSpace; -void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth, PlatformGradient* grad, PlatformPattern* pat) -{ - if (paintingDisabled()) + if (colorSpace == SolidColorSpace && !fillColor().alpha()) return; SkPaint paint; - m_data->setup_paint_stroke(&paint, NULL, 0); - paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth)); - check_set_shader(&paint, grad, pat); + m_data->setup_paint_fill(&paint); - SkRect r; - WebCoreRectToSkiaRect(rect, &r); - if (!IsRectReasonable(m_data->canvas()->getTotalMatrix(), r)) - return; + if (colorSpace == PatternColorSpace) { + SkShader* pat = state.fillPattern->createPlatformPattern(getCTM()); + paint.setShader(pat); + pat->unref(); + } else if (colorSpace == GradientColorSpace) + paint.setShader(state.fillGradient->platformGradient()); m_data->canvas()->drawRect(r, paint); } -PlatformGradient* GraphicsContext::newPlatformLinearGradient(const FloatPoint& p0, - const FloatPoint& p1, - const WebCore::CanvasGradient::ColorStop* stopData, size_t count) +void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) { - SkPoint pts[2]; - WebCorePointToSkiaPoint(p0, &pts[0]); - WebCorePointToSkiaPoint(p1, &pts[1]); - - size_t count_used = total_stops_needed(stopData, count); - ASSERT(count_used >= 2); - ASSERT(count_used >= count); - - SkAutoMalloc storage(count_used * (sizeof(SkColor) + sizeof(SkScalar))); - SkColor* colors = (SkColor*)storage.get(); - SkScalar* pos = (SkScalar*)(colors + count_used); - - fill_stops(stopData, count, pos, colors); - return SkGradientShader::CreateLinear(pts, colors, pos, - static_cast<int>(count_used), - SkShader::kClamp_TileMode); -} - -PlatformGradient* GraphicsContext::newPlatformRadialGradient(const FloatPoint& p0, float r0, - const FloatPoint& p1, float r1, - const WebCore::CanvasGradient::ColorStop* stopData, size_t count) -{ - SkPoint center; - WebCorePointToSkiaPoint(p1, ¢er); - SkMatrix identity; - identity.reset(); - if (!IsPointReasonable(identity, center)) { - center.fX = 0; - center.fY = 0; - } - - size_t count_used = total_stops_needed(stopData, count); - ASSERT(count_used >= 2); - ASSERT(count_used >= count); - - SkAutoMalloc storage(count_used * (sizeof(SkColor) + sizeof(SkScalar))); - SkColor* colors = (SkColor*)storage.get(); - SkScalar* pos = (SkScalar*)(colors + count_used); - - fill_stops(stopData, count, pos, colors); - return SkGradientShader::CreateRadial(center, WebCoreFloatToSkScalar(r1), - colors, pos, - static_cast<int>(count_used), - SkShader::kClamp_TileMode); -} + if (paintingDisabled()) + return; + if (!IsRectReasonable(getCTM(), rect)) + return; -void GraphicsContext::freePlatformGradient(PlatformGradient* shader) -{ - shader->safeUnref(); -} + const GraphicsContextState& state = m_common->state; + ColorSpace colorSpace = state.strokeColorSpace; -PlatformPattern* GraphicsContext::newPlatformPattern(Image* image, - Image::TileRule hRule, - Image::TileRule vRule) -{ - if (NULL == image) - return NULL; + if (colorSpace == SolidColorSpace && !strokeColor().alpha()) + return; - NativeImageSkia* bm = image->getBitmap(); - if (NULL == bm) - return NULL; + SkPaint paint; + m_data->setup_paint_stroke(&paint, NULL, 0); + paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth)); - return SkShader::CreateBitmapShader(*bm, - WebCoreTileToSkiaTile(hRule), - WebCoreTileToSkiaTile(vRule)); -} + if (colorSpace == PatternColorSpace) { + SkShader* pat = state.strokePattern->createPlatformPattern(getCTM()); + paint.setShader(pat); + pat->unref(); + } else if (colorSpace == GradientColorSpace) + paint.setShader(state.strokeGradient->platformGradient()); -void GraphicsContext::freePlatformPattern(PlatformPattern* shader) -{ - shader->safeUnref(); + m_data->canvas()->drawRect(rect, paint); } GraphicsContext* GraphicsContext::createOffscreenContext(int width, int height) @@ -725,21 +594,20 @@ void GraphicsContext::drawOffscreenContext(GraphicsContext* ctx, const FloatRect if (paintingDisabled() || ctx->paintingDisabled()) return; - const SkBitmap& bm = ctx->m_data->canvas()->getDevice()->accessBitmap(false); - SkIRect src; - SkRect dst; - SkPaint paint; + SkIRect src; if (srcRect) { - WebCoreRectToSkiaRect(*srcRect, &src); - // FIXME(brettw) FIX THIS YOU RETARD! + src = enclosingIntRect(*srcRect); + if (!IsRectReasonable(getCTM(), *srcRect)) + return; } - - WebCoreRectToSkiaRect(dstRect, &dst); - if (!IsRectReasonable(m_data->canvas()->getTotalMatrix(), dst)) + SkRect dst = dstRect; + if (!IsRectReasonable(getCTM(), dst)) return; + SkPaint paint; paint.setFilterBitmap(true); + const SkBitmap& bm = ctx->m_data->canvas()->getDevice()->accessBitmap(false); m_data->canvas()->drawBitmapRect(bm, srcRect ? &src : NULL, dst, @@ -749,38 +617,33 @@ void GraphicsContext::drawOffscreenContext(GraphicsContext* ctx, const FloatRect FloatRect GraphicsContext::getClipLocalBounds() const { SkRect r; - if (!m_data->canvas()->getClipBounds(&r)) r.setEmpty(); - return FloatRect(SkScalarToFloat(r.fLeft), SkScalarToFloat(r.fTop), - SkScalarToFloat(r.width()), SkScalarToFloat(r.height())); + return r; } -FloatRect GraphicsContext::getPathBoundingBox(const Path& path) const +FloatRect GraphicsContext::getBoundingBoxForCurrentPath(bool includeStroke) const { - SkRect r; - SkPaint paint; - m_data->setup_paint_stroke(&paint, NULL, 0); - SkPath boundingPath; - paint.getFillPath(*path.platformPath(), &boundingPath); + if (includeStroke) { + SkPaint paint; + m_data->setup_paint_stroke(&paint, NULL, 0); + paint.getFillPath(*m_data->currentPath(), &boundingPath); + } else + boundingPath = *m_data->currentPath(); + + SkRect r; boundingPath.computeBounds(&r, SkPath::kExact_BoundsType); - return FloatRect( - SkScalarToFloat(r.fLeft), - SkScalarToFloat(r.fTop), - SkScalarToFloat(r.width()), - SkScalarToFloat(r.height())); + return r; } bool GraphicsContext::strokeContains(const Path& path, const FloatPoint& point) const { - SkRegion rgn, clip; SkPaint paint; - m_data->setup_paint_stroke(&paint, NULL, 0); SkPath strokePath; @@ -789,33 +652,14 @@ bool GraphicsContext::strokeContains(const Path& path, const FloatPoint& point) return SkPathContainsPoint(&strokePath, point, SkPath::kWinding_FillType); } - -#endif // ANDROID_CANVAS_IMPL - -#if 0 -static int getBlendedColorComponent(int c, int a) -{ - // We use white. - float alpha = (float)(a) / 255; - int whiteBlend = 255 - a; - c -= whiteBlend; - return (int)(c/alpha); -} -#endif - -void GraphicsContext::fillRect(const IntRect& rect, const Color& color) +void GraphicsContext::fillRect(const FloatRect& rect, const Color& color) { if (paintingDisabled()) return; if (color.rgb() & 0xFF000000) { - SkPaint paint; - SkRect r; - - WebCoreRectToSkiaRect(rect, &r); - - static const float kMaxCoord = 32767; - if (!IsRectReasonable(m_data->canvas()->getTotalMatrix(), r)) { + SkRect r = rect; + if (!IsRectReasonable(getCTM(), r)) { // Special case when the rectangle overflows fixed point. This is a // workaround to fix bug 1212844. When the input rectangle is very // large, it can overflow Skia's internal fixed point rect. This @@ -829,27 +673,7 @@ void GraphicsContext::fillRect(const IntRect& rect, const Color& color) ClipRectToCanvas(*m_data->canvas(), r, &r); } - m_data->setup_paint_common(&paint); - paint.setColor(color.rgb()); - m_data->canvas()->drawRect(r, paint); - } -} - -void GraphicsContext::fillRect(const FloatRect& rect, const Color& color) -{ - if (paintingDisabled()) - return; - - if (color.rgb() & 0xFF000000) { SkPaint paint; - SkRect r; - - WebCoreRectToSkiaRect(rect, &r); - if (!IsRectReasonable(m_data->canvas()->getTotalMatrix(), r)) { - // See other fillRect() above. - ClipRectToCanvas(*m_data->canvas(), r, &r); - } - m_data->setup_paint_common(&paint); paint.setColor(color.rgb()); m_data->canvas()->drawRect(r, paint); @@ -862,34 +686,31 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef if (paintingDisabled()) return; - SkRect r; - WebCoreRectToSkiaRect(rect, &r); - if (!IsRectReasonable(m_data->canvas()->getTotalMatrix(), r)) { + SkRect r = rect; + if (!IsRectReasonable(getCTM(), r)) { // See fillRect(). ClipRectToCanvas(*m_data->canvas(), r, &r); } - SkPaint paint; SkPath path; - add_corner_arc(&path, r, topRight, 270); add_corner_arc(&path, r, bottomRight, 0); add_corner_arc(&path, r, bottomLeft, 90); add_corner_arc(&path, r, topLeft, 180); + SkPaint paint; m_data->setup_paint_fill(&paint); m_data->canvas()->drawPath(path, paint); return fillRect(rect, color); } -void GraphicsContext::clip(const IntRect& rect) +void GraphicsContext::clip(const FloatRect& rect) { if (paintingDisabled()) return; - SkRect r; - WebCoreRectToSkiaRect(rect, &r); - if (!IsRectReasonable(m_data->canvas()->getTotalMatrix(), r)) + SkRect r(rect); + if (!IsRectReasonable(getCTM(), r)) return; m_data->canvas()->clipRect(r); @@ -900,8 +721,8 @@ void GraphicsContext::clip(const Path& path) if (paintingDisabled()) return; - const SkPath& p = *PathToSkPath(path); - if (!IsPathReasonable(m_data->canvas()->getTotalMatrix(), p)) + const SkPath& p = *path.platformPath(); + if (!IsPathReasonable(getCTM(), p)) return; m_data->canvas()->clipPath(p); @@ -911,16 +732,15 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness { if (paintingDisabled()) return; - SkPath path; - SkRect r; - WebCoreRectToSkiaRect(rect, &r); - if (!IsRectReasonable(m_data->canvas()->getTotalMatrix(), r)) + + SkRect r(rect); + if (!IsRectReasonable(getCTM(), r)) return; + SkPath path; path.addOval(r, SkPath::kCW_Direction); // only perform the inset if we won't invert r - if (2*thickness < rect.width() && 2*thickness < rect.height()) - { + if (2*thickness < rect.width() && 2*thickness < rect.height()) { r.inset(SkIntToScalar(thickness) ,SkIntToScalar(thickness)); path.addOval(r, SkPath::kCCW_Direction); } @@ -932,9 +752,9 @@ void GraphicsContext::clipOut(const IntRect& rect) { if (paintingDisabled()) return; - SkRect r; - WebCoreRectToSkiaRect(rect, &r); - if (!IsRectReasonable(m_data->canvas()->getTotalMatrix(), r)) + + SkRect r(rect); + if (!IsRectReasonable(getCTM(), r)) return; m_data->canvas()->clipRect(r, SkRegion::kDifference_Op); @@ -944,13 +764,12 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect) { if (paintingDisabled()) return; - SkRect oval; - SkPath path; - WebCoreRectToSkiaRect(rect, &oval); - if (!IsRectReasonable(m_data->canvas()->getTotalMatrix(), oval)) + SkRect oval(rect); + if (!IsRectReasonable(getCTM(), oval)) return; + SkPath path; path.addOval(oval, SkPath::kCCW_Direction); m_data->canvas()->clipPath(path, SkRegion::kDifference_Op); } @@ -960,18 +779,12 @@ void GraphicsContext::clipOut(const Path& p) if (paintingDisabled()) return; - const SkPath& path = *PathToSkPath(p); - if (!IsPathReasonable(m_data->canvas()->getTotalMatrix(), path)) + const SkPath& path = *p.platformPath(); + if (!IsPathReasonable(getCTM(), path)) return; - m_data->canvas()->clipPath(path, SkRegion::kDifference_Op); -} -#if SVG_SUPPORT -KRenderingDeviceContext* GraphicsContext::createRenderingDeviceContext() -{ - return new KRenderingDeviceContextQuartz(platformContext()); + m_data->canvas()->clipPath(path, SkRegion::kDifference_Op); } -#endif void GraphicsContext::beginTransparencyLayer(float opacity) { @@ -1001,13 +814,17 @@ void GraphicsContext::endTransparencyLayer() m_data->canvas()->restore(); } -void GraphicsContext::setShadow(const IntSize& size, int blur, const Color& color) +void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& stroke) +{ + m_data->setStrokeStyle(StrokeStyle2StrokeStyle(stroke)); +} + +void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color) { if (paintingDisabled()) return; - if (blur > 0) - { + if (blur > 0) { SkColor c; if (color.isValid()) @@ -1020,16 +837,12 @@ void GraphicsContext::setShadow(const IntSize& size, int blur, const Color& colo SkIntToScalar(size.height()), c); m_data->setDrawLooper(dl)->unref(); - } - else + } else m_data->setDrawLooper(NULL); } -void GraphicsContext::clearShadow() +void GraphicsContext::clearPlatformShadow() { - if (paintingDisabled()) - return; - m_data->setDrawLooper(NULL); } @@ -1044,10 +857,8 @@ void GraphicsContext::drawFocusRing(const Color& color) SkRegion exterior_region; const SkScalar exterior_offset = WebCoreFloatToSkScalar(0.5); - for (unsigned i = 0; i < rectCount; i++) - { - SkIRect r; - WebCoreRectToSkiaRect(rects[i], &r); + for (unsigned i = 0; i < rectCount; i++) { + SkIRect r = rects[i]; r.inset(-exterior_offset, -exterior_offset); exterior_region.op(r, SkRegion::kUnion_Op); } @@ -1090,31 +901,13 @@ void GraphicsContext::clearRect(const FloatRect& rect) if (paintingDisabled()) return; - SkPaint paint; - SkRect r; - WebCoreRectToSkiaRect(rect, &r); - if (!IsRectReasonable(m_data->canvas()->getTotalMatrix(), r)) + SkRect r = rect; + if (!IsRectReasonable(getCTM(), r)) ClipRectToCanvas(*m_data->canvas(), r, &r); - m_data->setup_paint_fill(&paint); - paint.setPorterDuffXfermode(SkPorterDuff::kClear_Mode); - m_data->canvas()->drawRect(r, paint); -} - -void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) -{ - if (paintingDisabled()) - return; - SkPaint paint; - SkRect r; - - WebCoreRectToSkiaRect(rect, &r); - if (!IsRectReasonable(m_data->canvas()->getTotalMatrix(), r)) - return; - m_data->setup_paint_fill(&paint); - paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth)); + paint.setPorterDuffXfermode(SkPorterDuff::kClear_Mode); m_data->canvas()->drawRect(r, paint); } @@ -1154,21 +947,6 @@ void GraphicsContext::setLineJoin(LineJoin join) } } -void GraphicsContext::setFillRule(WindRule rule) -{ - switch (rule) { - case RULE_NONZERO: - m_data->setFillRule(SkPath::kWinding_FillType); - break; - case RULE_EVENODD: - m_data->setFillRule(SkPath::kEvenOdd_FillType); - break; - default: - SkDEBUGF(("GraphicsContext::setFillRule: unknown WindRule %d\n", rule)); - break; - } -} - void GraphicsContext::scale(const FloatSize& size) { if (paintingDisabled()) @@ -1200,15 +978,16 @@ AffineTransform GraphicsContext::getCTM() const return m_data->canvas()->getTotalMatrix(); } - -HDC GraphicsContext::getWindowsContext(bool supportAlphaBlend, const IntRect*) { +HDC GraphicsContext::getWindowsContext(const IntRect&, bool supportAlphaBlend, bool mayCreateBitmap) +{ if (paintingDisabled()) - return NULL; + return 0; // No need to ever call endPlatformPaint() since it is a noop. return m_data->canvas()->beginPlatformPaint(); } -void GraphicsContext::releaseWindowsContext(HDC hdc, bool supportAlphaBlend, const IntRect*) { +void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect&, bool supportAlphaBlend, bool mayCreateBitmap) +{ // noop, the DC will be lazily freed by the bitmap when no longer needed } @@ -1267,10 +1046,14 @@ void GraphicsContext::setPlatformFillColor(const Color& color) m_data->setFillColor(color.rgb()); } +/* +TODO(brettw): WebKit's implementation of this function moved into the cross- +platform file GraphicsContext.cpp. We need to figure out how to hook this up +properly once everything links. void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle & strokestyle) { m_data->setStrokeStyle(StrokeStyle2StrokeStyle(strokestyle)); -} +}*/ void GraphicsContext::setPlatformStrokeColor(const Color& strokecolor) { @@ -1284,7 +1067,7 @@ void GraphicsContext::setPlatformStrokeThickness(float thickness) void GraphicsContext::addPath(const Path& path) { - m_data->addPath(*PathToSkPath(path)); + m_data->addPath(*path.platformPath()); } void GraphicsContext::beginPath() @@ -1305,9 +1088,36 @@ void GraphicsContext::setShouldDelete(bool should_delete) m_data->setShouldDelete(should_delete); } -PlatformPath* GraphicsContext::currentPath() +// TODO(eseidel): This is needed for image masking and complex text fills +void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer* imageBuffer) +{ + if (paintingDisabled()) + return; + + notImplemented(); +} + +void GraphicsContext::setImageInterpolationQuality(InterpolationQuality) +{ + notImplemented(); +} + +// Skia platform gradients and patterns are handled at draw time +// Upstream is considering removing these methods anyway +void GraphicsContext::setPlatformStrokePattern(Pattern* pattern) +{ +} + +void GraphicsContext::setPlatformFillPattern(Pattern* pattern) +{ +} + +void GraphicsContext::setPlatformStrokeGradient(Gradient*) +{ +} + +void GraphicsContext::setPlatformFillGradient(Gradient*) { - return m_data->currentPath(); } } diff --git a/webkit/port/platform/graphics/IconWin.cpp b/webkit/port/platform/graphics/IconWin.cpp index b348f45..6c17a53 100644 --- a/webkit/port/platform/graphics/IconWin.cpp +++ b/webkit/port/platform/graphics/IconWin.cpp @@ -31,11 +31,6 @@ namespace WebCore { -Icon::Icon() - : m_hIcon(0) -{ -} - Icon::Icon(HICON icon) : m_hIcon(icon) { @@ -56,9 +51,7 @@ PassRefPtr<Icon> Icon::newIconForFile(const String& filename) if (!SHGetFileInfo(tmpFilename.charactersWithNullTermination(), 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_SHELLICONSIZE | SHGFI_SMALLICON)) return 0; - Icon* icon = new Icon(); - icon->m_hIcon = sfi.hIcon; - return icon; + return adoptRef(new Icon(sfi.hIcon)); } void Icon::paint(GraphicsContext* context, const IntRect& r) @@ -66,9 +59,7 @@ void Icon::paint(GraphicsContext* context, const IntRect& r) if (context->paintingDisabled()) return; - SkIRect rect; - WebCoreRectToSkiaRect(r, &rect); - PlatformContextToPlatformContextSkia(context->platformContext())->paintIcon(m_hIcon, rect); + context->platformContext()->paintIcon(m_hIcon, r); } -} +} // namespace WebCore diff --git a/webkit/port/platform/graphics/ImageBufferSkia.cpp b/webkit/port/platform/graphics/ImageBufferSkia.cpp index dcad45a..e1d9c90 100644 --- a/webkit/port/platform/graphics/ImageBufferSkia.cpp +++ b/webkit/port/platform/graphics/ImageBufferSkia.cpp @@ -30,13 +30,12 @@ #include "config.h" #include "ImageBuffer.h" +#include "BitmapImage.h" #include "GraphicsContext.h" -#include "PlatformContextSkia.h" -#include <cairo.h> - -#include "SkBitmap.h" - +#include "ImageData.h" #include "NotImplemented.h" +#include "PlatformContextSkia.h" +#include "SkiaUtils.h" using namespace std; @@ -44,26 +43,50 @@ namespace WebCore { auto_ptr<ImageBuffer> ImageBuffer::create(const IntSize& size, bool) { - return auto_ptr<ImageBuffer>(new ImageBuffer(size)); + return auto_ptr<ImageBuffer>(new ImageBuffer(size)); +} + +GraphicsContext* ImageBuffer::context() const +{ + return m_context.get(); } -const SkBitmap* ImageBuffer::image() const +Image* ImageBuffer::image() const { - return m_context.get()->platformContext()->bitmap(); + if (!m_image) { + // It's assumed that if image() is called, the actual rendering to + // the GraphicsContext must be done. + ASSERT(context()); + const SkBitmap* bitmap = context()->platformContext()->bitmap(); + m_image = BitmapImage::create(); + // TODO(tc): This is inefficient because we serialize then re-interpret + // the image. If this matters for performance, we should add another + // BitmapImage::create method that takes a SkBitmap (similar to what + // CoreGraphics does). + m_image->setData(SerializeSkBitmap(*bitmap), true); + } + return m_image.get(); } -cairo_surface_t* ImageBuffer::surface() const +PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect&) const { notImplemented(); - return NULL; + return 0; } -GraphicsContext* ImageBuffer::context() const +void ImageBuffer::putImageData(ImageData*, const IntRect&, const IntPoint&) { - return m_context.get(); + notImplemented(); +} + +String ImageBuffer::toDataURL(const String&) const +{ + notImplemented(); + return String(); } ImageBuffer::ImageBuffer(const IntSize& size) : + m_data(0), m_size(size), m_context(GraphicsContext::createOffscreenContext(size.width(), size.height())) { diff --git a/webkit/port/platform/graphics/ImageSkia.cpp b/webkit/port/platform/graphics/ImageSkia.cpp index 359f6c0..1989eba8 100644 --- a/webkit/port/platform/graphics/ImageSkia.cpp +++ b/webkit/port/platform/graphics/ImageSkia.cpp @@ -77,42 +77,6 @@ void TransformDimensions(const SkMatrix& matrix, *dest_height = SkScalarToFloat((dest_points[2] - dest_points[0]).length()); } -// Constructs a BMP V4 bitmap from an SkBitmap. -PassRefPtr<SharedBuffer> SerializeBitmap(const SkBitmap& bitmap) -{ - int width = bitmap.width(); - int height = bitmap.height(); - - // Create a BMP v4 header that we can serialize. - BITMAPV4HEADER v4Header; - gfx::CreateBitmapV4Header(width, height, &v4Header); - v4Header.bV4SizeImage = width * sizeof(uint32_t) * height; - - // Serialize the bitmap. - BITMAPFILEHEADER fileHeader; - fileHeader.bfType = 0x4d42; // "BM" header - fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + v4Header.bV4Size; - fileHeader.bfSize = fileHeader.bfOffBits + v4Header.bV4SizeImage; - fileHeader.bfReserved1 = fileHeader.bfReserved2 = 0; - - // Write BITMAPFILEHEADER - RefPtr<SharedBuffer> buffer(new SharedBuffer( - reinterpret_cast<const char*>(&fileHeader), - sizeof(BITMAPFILEHEADER))); - - // Write BITMAPINFOHEADER - buffer->append(reinterpret_cast<const char*>(&v4Header), - sizeof(BITMAPV4HEADER)); - - // Write the image body. - SkAutoLockPixels bitmap_lock(bitmap); - buffer->append(reinterpret_cast<const char*>(bitmap.getAddr32(0, 0)), - v4Header.bV4SizeImage); - - return buffer; -} - - // Creates an Image for the text area resize corner. We do this by drawing the // theme native control into a memory buffer then converting the memory buffer // into a BMP byte stream, then feeding it into the Image object. We have to @@ -120,9 +84,9 @@ PassRefPtr<SharedBuffer> SerializeBitmap(const SkBitmap& bitmap) // us to directly manipulate the image data. We don't bother caching this // image because the caller holds onto a static copy (see // WebCore/rendering/RenderLayer.cpp). -void GetTextAreaResizeCorner(Image* image) +static PassRefPtr<Image> GetTextAreaResizeCorner() { - ASSERT(image); + RefPtr<Image> image = BitmapImage::create(); // Get the size of the resizer. const int width = PlatformScrollbar::verticalScrollbarWidth(); @@ -139,12 +103,8 @@ void GetTextAreaResizeCorner(Image* image) gfx::NativeTheme::instance()->PaintStatusGripper(hdc, SP_GRIPPER, 0, 0, &widgetRect); device.postProcessGDI(0, 0, width, height); - image->setData(SerializeBitmap(device.accessBitmap(false)), true); -} - -// Convert from what WebKit thinks the type is, to what it is for our port -inline NativeImageSkia* ToSkiaFrame(NativeImagePtr native) { - return reinterpret_cast<NativeImageSkia*>(native); + image->setData(SerializeSkBitmap(device.accessBitmap(false)), true); + return image.release(); } } // namespace @@ -157,91 +117,83 @@ void FrameData::clear() m_hasAlpha = true; } +static inline PassRefPtr<Image> loadImageWithResourceId(int resourceId) +{ + RefPtr<Image> image = BitmapImage::create(); + // Load the desired resource. + std::string data(webkit_glue::GetDataResource(resourceId)); + RefPtr<SharedBuffer> buffer(SharedBuffer::create(data.data(), data.length())); + image->setData(buffer, true); + return image.release(); +} + // static -Image* Image::loadPlatformResource(const char *name) +PassRefPtr<Image> Image::loadPlatformResource(const char *name) { - Image* image = new BitmapImage; - - // Figure out which resource ID the caller wanted. - int resource_id; - if (!strcmp(name, "missingImage")) { - resource_id = IDR_BROKENIMAGE; - } else if (!strcmp(name, "tickmarkDash")) { - resource_id = IDR_TICKMARK_DASH; - } else if (!strcmp(name, "textAreaResizeCorner")) { - GetTextAreaResizeCorner(image); - return image; - } else if (!strcmp(name, "deleteButton") || - !strcmp(name, "deleteButtonPressed")) { + if (!strcmp(name, "missingImage")) + return loadImageWithResourceId(IDR_BROKENIMAGE); + if (!strcmp(name, "tickmarkDash")) + return loadImageWithResourceId(IDR_TICKMARK_DASH); + if (!strcmp(name, "textAreaResizeCorner")) + return GetTextAreaResizeCorner(); + if (!strcmp(name, "deleteButton") || !strcmp(name, "deleteButtonPressed")) { LOG(NotYetImplemented, "Image resource %s does not yet exist\n", name); - return image; - } else { - LOG(NotYetImplemented, "Unknown image resource %s requested\n", name); - return image; + return Image::nullImage(); } - // Load the desired resource. - std::string data(webkit_glue::GetDataResource(resource_id)); - RefPtr<SharedBuffer> buffer(new SharedBuffer(data.data(), data.length())); - image->setData(buffer, true); - return image; + LOG(NotYetImplemented, "Unknown image resource %s requested\n", name); + return Image::nullImage(); } -static bool subsetBitmap(SkBitmap* dst, const SkBitmap& src, const FloatRect& r) +static bool subsetBitmap(SkBitmap* dst, const SkBitmap& src, const FloatRect& clip) { - SkIRect bounds, clip; - bounds.set(0, 0, src.width(), src.height()); - WebCoreRectToSkiaRect(r, &clip); - + FloatRect floatBounds(0, 0, src.width(), src.height()); + if (!floatBounds.intersects(clip)) + return false; + SkAutoLockPixels src_lock(src); - if (bounds.intersect(clip)) - { - void* addr; - switch (src.getConfig()) { - case SkBitmap::kIndex8_Config: - case SkBitmap::kA8_Config: - addr = (void*)src.getAddr8(bounds.fLeft, bounds.fTop); - break; - case SkBitmap::kRGB_565_Config: - addr = (void*)src.getAddr16(bounds.fLeft, bounds.fTop); - break; - case SkBitmap::kARGB_8888_Config: - addr = (void*)src.getAddr32(bounds.fLeft, bounds.fTop); - break; - default: - SkDEBUGF(("subset_bitmap: can't subset this bitmap config %d\n", src.getConfig())); - return false; - } - dst->setConfig(src.getConfig(), bounds.width(), bounds.height(), src.rowBytes()); - dst->setPixels(addr); + IntRect bounds(floatBounds); + void* addr; + switch (src.getConfig()) { + case SkBitmap::kIndex8_Config: + case SkBitmap::kA8_Config: + addr = (void*)src.getAddr8(bounds.x(), bounds.y()); + break; + case SkBitmap::kRGB_565_Config: + addr = (void*)src.getAddr16(bounds.x(), bounds.y()); + break; + case SkBitmap::kARGB_8888_Config: + addr = (void*)src.getAddr32(bounds.x(), bounds.y()); + break; + default: + SkDEBUGF(("subset_bitmap: can't subset this bitmap config %d\n", src.getConfig())); + return false; } + dst->setConfig(src.getConfig(), bounds.width(), bounds.height(), src.rowBytes()); + dst->setPixels(addr); return false; } void Image::drawPattern(GraphicsContext* context, - const FloatRect& srcRect, + const FloatRect& floatSrcRect, const AffineTransform& patternTransform, const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& destRect) { - if (destRect.isEmpty() || srcRect.isEmpty()) + if (destRect.isEmpty() || floatSrcRect.isEmpty()) return; // nothing to draw - NativeImageSkia* bitmap = ToSkiaFrame(nativeImageForCurrentFrame()); + NativeImageSkia* bitmap = nativeImageForCurrentFrame(); if (!bitmap) return; - PlatformContextSkia* skia = PlatformContextToPlatformContextSkia( - context->platformContext()); - // This is a very inexpensive operation. It will generate a new bitmap but // it will internally reference the old bitmap's pixels, adjusting the row // stride so the extra pixels appear as padding to the subsetted bitmap. - SkIRect srcSkIRect; - WebCoreRectToSkiaRect(srcRect, &srcSkIRect); SkBitmap src_subset; - bitmap->extractSubset(&src_subset, srcSkIRect); + SkIRect srcRect = enclosingIntRect(floatSrcRect); + bitmap->extractSubset(&src_subset, srcRect); SkBitmap resampled; SkShader* shader; @@ -255,9 +207,9 @@ void Image::drawPattern(GraphicsContext* context, // Compute the resampling mode. PlatformContextSkia::ResamplingMode resampling; - if (context->platformContext()->IsPrinting()) { + if (context->platformContext()->IsPrinting()) resampling = PlatformContextSkia::RESAMPLE_LINEAR; - } else { + else { resampling = PlatformContextSkia::computeResamplingMode( *bitmap, srcRect.width(), srcRect.height(), @@ -299,9 +251,7 @@ void Image::drawPattern(GraphicsContext* context, paint.setPorterDuffXfermode(WebCoreCompositeToSkiaComposite(compositeOp)); paint.setFilterBitmap(resampling == PlatformContextSkia::RESAMPLE_LINEAR); - SkRect dstR; - WebCoreRectToSkiaRect(destRect, &dstR); - skia->paintSkPaint(dstR, paint); + context->platformContext()->paintSkPaint(destRect, paint); } // ================================================ @@ -327,7 +277,7 @@ void BitmapImage::checkForSolidColor() bool BitmapImage::getHBITMAP(HBITMAP bmp) { - NativeImageSkia* bm = getBitmap(); + NativeImageSkia* bm = nativeImageForCurrentFrame(); if (!bm) return false; @@ -347,11 +297,6 @@ bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size) return false; } -NativeImageSkia* BitmapImage::getBitmap() -{ - return ToSkiaFrame(nativeImageForCurrentFrame()); -} - void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext*, const FloatRect& dstRect, const IntSize& srcSize, @@ -366,23 +311,17 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, if (!m_source.initialized()) return; - const NativeImageSkia* bm = getBitmap(); + const NativeImageSkia* bm = nativeImageForCurrentFrame(); if (!bm) return; // It's too early and we don't have an image yet. - SkIRect source_rect; - WebCoreRectToSkiaRect(srcRect, &source_rect); - SkRect dest_rect; - WebCoreRectToSkiaRect(dstRect, &dest_rect); - if (source_rect.isEmpty() || dest_rect.isEmpty()) + if (srcRect.isEmpty() || dstRect.isEmpty()) return; // Nothing to draw. - PlatformContextSkia* skia = PlatformContextToPlatformContextSkia( - ctxt->platformContext()); - skia->paintSkBitmap(*bm, source_rect, dest_rect, - WebCoreCompositeToSkiaComposite(compositeOp)); + ctxt->platformContext()->paintSkBitmap(*bm, enclosingIntRect(srcRect), + enclosingIntRect(dstRect), WebCoreCompositeToSkiaComposite(compositeOp)); startAnimation(); } -} +} // namespace WebCore diff --git a/webkit/port/platform/graphics/ImageSourceSkia.cpp b/webkit/port/platform/graphics/ImageSourceSkia.cpp index 48db176..fda00ab 100644 --- a/webkit/port/platform/graphics/ImageSourceSkia.cpp +++ b/webkit/port/platform/graphics/ImageSourceSkia.cpp @@ -139,6 +139,12 @@ IntSize ImageSource::size() const return m_decoder->size(); } +IntSize ImageSource::frameSizeAtIndex(size_t) const +{ + // TODO(brettw) do we need anything here? + return size(); +} + int ImageSource::repetitionCount() { if (!m_decoder) diff --git a/webkit/port/platform/graphics/IntPointSkia.cpp b/webkit/port/platform/graphics/IntPointSkia.cpp new file mode 100644 index 0000000..21e110e --- /dev/null +++ b/webkit/port/platform/graphics/IntPointSkia.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008 Google, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "IntPoint.h" +#include "SkPoint.h" + +namespace WebCore { + +IntPoint::IntPoint(const SkIPoint& p) + : m_x(p.fX) + , m_y(p.fY) +{ +} + +IntPoint::operator SkIPoint() const +{ + SkIPoint p = { m_x, m_y }; + return p; +} + +IntPoint::operator SkPoint() const +{ + SkPoint p = { SkIntToScalar(m_x), SkIntToScalar(m_y) }; + return p; +} + +} // namespace WebCore diff --git a/webkit/port/platform/graphics/IntPointWin.cpp b/webkit/port/platform/graphics/IntPointWin.cpp index a6ce0bb..91ffe02 100644 --- a/webkit/port/platform/graphics/IntPointWin.cpp +++ b/webkit/port/platform/graphics/IntPointWin.cpp @@ -53,4 +53,4 @@ IntPoint::operator POINTS() const return p; } -} +} // namespace WebCore diff --git a/webkit/port/platform/graphics/IntRectSkia.cpp b/webkit/port/platform/graphics/IntRectSkia.cpp new file mode 100644 index 0000000..e3186e2 --- /dev/null +++ b/webkit/port/platform/graphics/IntRectSkia.cpp @@ -0,0 +1,54 @@ +/*
+ * Copyright (C) 2008 Google, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "IntRect.h"
+
+#include "SkRect.h"
+
+namespace WebCore {
+
+IntRect::operator SkIRect() const
+{
+ SkIRect rect = { x(), y(), right(), bottom() };
+ return rect;
+}
+
+IntRect::operator SkRect() const
+{
+ SkRect rect;
+ rect.set(SkIntToScalar(x()), SkIntToScalar(y()),
+ SkIntToScalar(right()), SkIntToScalar(bottom()));
+ return rect;
+}
+
+IntRect::IntRect(const SkIRect& r)
+ : m_location(r.fLeft, r.fTop)
+ , m_size(r.width(), r.height())
+{
+}
+
+}
+
diff --git a/webkit/port/platform/graphics/IntRectWin.cpp b/webkit/port/platform/graphics/IntRectWin.cpp index 6228be8..a156039 100644 --- a/webkit/port/platform/graphics/IntRectWin.cpp +++ b/webkit/port/platform/graphics/IntRectWin.cpp @@ -30,7 +30,8 @@ namespace WebCore { IntRect::IntRect(const RECT& r) - : m_location(IntPoint(r.left, r.top)), m_size(IntSize(r.right-r.left, r.bottom-r.top)) + : m_location(IntPoint(r.left, r.top)) + , m_size(IntSize(r.right-r.left, r.bottom-r.top)) { } @@ -40,4 +41,4 @@ IntRect::operator RECT() const return rect; } -} +} // namespace WebCore diff --git a/webkit/port/platform/graphics/IntSizeWin.cpp b/webkit/port/platform/graphics/IntSizeWin.cpp index 8a27cdb..b8156e5 100644 --- a/webkit/port/platform/graphics/IntSizeWin.cpp +++ b/webkit/port/platform/graphics/IntSizeWin.cpp @@ -41,4 +41,4 @@ IntSize::operator SIZE() const return s; } -} +} // namespace WebCore diff --git a/webkit/port/platform/graphics/PathSkia.cpp b/webkit/port/platform/graphics/PathSkia.cpp index b88d11d..d8b5b75 100644 --- a/webkit/port/platform/graphics/PathSkia.cpp +++ b/webkit/port/platform/graphics/PathSkia.cpp @@ -47,7 +47,6 @@ Path::Path() Path::Path(const Path& other) { m_path = new SkPath(*other.m_path); - m_rule = other.m_rule; } Path::~Path() @@ -159,16 +158,12 @@ void Path::addArc(const FloatPoint& p, float r, float sa, float ea, void Path::addRect(const FloatRect& rect) { - SkRect r; - WebCoreRectToSkiaRect(rect, &r); - m_path->addRect(r); + m_path->addRect(rect); } void Path::addEllipse(const FloatRect& rect) { - SkRect r; - WebCoreRectToSkiaRect(rect, &r); - m_path->addOval(r); + m_path->addOval(rect); } void Path::clear() @@ -243,23 +238,23 @@ String Path::debugString() const verb = iter.next(pts); switch (verb) { case SkPath::kMove_Verb: - result += String::format("M%.2f,%.2f", pts[0].fX, pts[0].fY); + result += String::format("M%.2f,%.2f ", pts[0].fX, pts[0].fY); numPoints -= 1; break; case SkPath::kLine_Verb: if (!iter.isCloseLine()) { - result += String::format("L%.2f,%.2f", pts[1].fX, pts[1].fY); + result += String::format("L%.2f,%.2f ", pts[1].fX, pts[1].fY); numPoints -= 1; } break; case SkPath::kQuad_Verb: - result += String::format("Q%.2f,%.2f,%.2f,%.2f", + result += String::format("Q%.2f,%.2f,%.2f,%.2f ", pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY); numPoints -= 2; break; case SkPath::kCubic_Verb: - result += String::format("C%.2f,%.2f,%.2f,%.2f,%.2f,%.2f", + result += String::format("C%.2f,%.2f,%.2f,%.2f,%.2f,%.2f ", pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY, pts[3].fX, pts[3].fY); @@ -278,10 +273,10 @@ String Path::debugString() const if (numPoints) { ASSERT(numPoints==1); m_path->getLastPt(pts); - result += String::format("M%.2f,%.2f", pts[0].fX, pts[0].fY); + result += String::format("M%.2f,%.2f ", pts[0].fX, pts[0].fY); } - return result; + return result.stripWhiteSpace(); } -} +} // namespace WebCore diff --git a/webkit/port/platform/graphics/PatternSkia.cpp b/webkit/port/platform/graphics/PatternSkia.cpp new file mode 100644 index 0000000..d80d3ec --- /dev/null +++ b/webkit/port/platform/graphics/PatternSkia.cpp @@ -0,0 +1,57 @@ +/*
+ * Copyright (C) 2008 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Pattern.h"
+
+#include "AffineTransform.h"
+#include "Image.h"
+#include "NativeImageSkia.h"
+
+#include "SkShader.h"
+
+namespace WebCore {
+
+static inline SkShader::TileMode shaderRule(bool shouldRepeat)
+{
+ // FIXME: Skia does not have a "draw the tile only once" option
+ // Clamp draws the last line of the image after stopping repeating
+ return shouldRepeat ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
+}
+
+PlatformPatternPtr Pattern::createPlatformPattern(const AffineTransform& patternTransform) const
+{
+ SkBitmap* bm = m_tileImage->nativeImageForCurrentFrame();
+ SkShader* shader = SkShader::CreateBitmapShader(*bm,
+ shaderRule(m_repeatX),
+ shaderRule(m_repeatY));
+ shader->setLocalMatrix(patternTransform);
+ return shader;
+}
+
+} // namespace WebCore
diff --git a/webkit/port/platform/graphics/PlatformGraphics.h b/webkit/port/platform/graphics/PlatformGraphics.h index b3d83dc..6669dae 100644 --- a/webkit/port/platform/graphics/PlatformGraphics.h +++ b/webkit/port/platform/graphics/PlatformGraphics.h @@ -5,8 +5,8 @@ #ifndef PlatformGraphics_d #define PlatformGraphics_d -typedef class SkShader PlatformGradient; -typedef class SkShader PlatformPattern; +typedef class SkShader* PlatformGradient; +typedef class SkShader* PlatformPattern; #endif diff --git a/webkit/port/platform/graphics/SkGraphicsContext.cpp b/webkit/port/platform/graphics/SkGraphicsContext.cpp index 3a1b3c7..d89dbd0 100644 --- a/webkit/port/platform/graphics/SkGraphicsContext.cpp +++ b/webkit/port/platform/graphics/SkGraphicsContext.cpp @@ -27,6 +27,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include "config.h" #include "SkGraphicsContext.h" #include <vssym32.h> @@ -35,7 +36,7 @@ #include "base/gfx/native_theme.h" #include "base/gfx/platform_canvas_win.h" #include "base/gfx/skia_utils.h" -#include "GraphicsContextPrivate.h" +#include "GraphicsContextPlatformPrivate.h" #include "NativeImageSkia.h" #include "SkBitmap.h" diff --git a/webkit/port/platform/graphics/SkiaUtils.cpp b/webkit/port/platform/graphics/SkiaUtils.cpp index 27779c7..aa8aef0 100644 --- a/webkit/port/platform/graphics/SkiaUtils.cpp +++ b/webkit/port/platform/graphics/SkiaUtils.cpp @@ -31,15 +31,13 @@ #include "SkiaUtils.h" +#include "SharedBuffer.h" #include "SkCanvas.h" #include "SkColorPriv.h" #include "SkMatrix.h" #include "SkRegion.h" -void WebCorePointToSkiaPoint(const WebCore::IntPoint& src, SkPoint* dst) -{ - dst->set(SkIntToScalar(src.x()), SkIntToScalar(src.y())); -} +#include "base/gfx/bitmap_header.h" void WebCorePointToSkiaPoint(const WebCore::FloatPoint& src, SkPoint* dst) { @@ -112,15 +110,6 @@ SkPorterDuff::Mode WebCoreCompositeToSkiaComposite(WebCore::CompositeOperator op return SkPorterDuff::kSrcOver_Mode; // fall-back } -SkShader::TileMode WebCoreTileToSkiaTile(WebCore::Image::TileRule rule) -{ - // StretchTile, RoundTile, RepeatTile - // hack!!!! what does stretch and round mean??? - - return SkShader::kRepeat_TileMode; -} - - static U8CPU InvScaleByte(U8CPU component, uint32_t scale) { SkASSERT(component == (uint8_t)component); @@ -144,9 +133,7 @@ static SkColor SkPMColorToColor(SkPMColor pm) WebCore::Color SkPMColorToWebCoreColor(SkPMColor pm) { - SkColor c = SkPMColorToColor(pm); - - return WebCore::Color(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c), SkColorGetA(c)); + return SkPMColorToColor(pm); } void IntersectRectAndRegion(const SkRegion& region, const SkRect& src_rect, @@ -239,3 +226,37 @@ bool SkPathContainsPoint(SkPath* orig_path, WebCore::FloatPoint point, SkPath::F orig_path->setFillType(orig_ft); // restore return contains; } + +PassRefPtr<WebCore::SharedBuffer> SerializeSkBitmap(const SkBitmap& bitmap) +{ + int width = bitmap.width(); + int height = bitmap.height(); + + // Create a BMP v4 header that we can serialize. + BITMAPV4HEADER v4Header; + gfx::CreateBitmapV4Header(width, height, &v4Header); + v4Header.bV4SizeImage = width * sizeof(uint32_t) * height; + + // Serialize the bitmap. + BITMAPFILEHEADER fileHeader; + fileHeader.bfType = 0x4d42; // "BM" header + fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + v4Header.bV4Size; + fileHeader.bfSize = fileHeader.bfOffBits + v4Header.bV4SizeImage; + fileHeader.bfReserved1 = fileHeader.bfReserved2 = 0; + + // Write BITMAPFILEHEADER + RefPtr<WebCore::SharedBuffer> buffer(WebCore::SharedBuffer::create( + reinterpret_cast<const char*>(&fileHeader), + sizeof(BITMAPFILEHEADER))); + + // Write BITMAPINFOHEADER + buffer->append(reinterpret_cast<const char*>(&v4Header), + sizeof(BITMAPV4HEADER)); + + // Write the image body. + SkAutoLockPixels bitmap_lock(bitmap); + buffer->append(reinterpret_cast<const char*>(bitmap.getAddr32(0, 0)), + v4Header.bV4SizeImage); + + return buffer; +} diff --git a/webkit/port/platform/graphics/SkiaUtils.h b/webkit/port/platform/graphics/SkiaUtils.h index 28d43be..617b8c8 100644 --- a/webkit/port/platform/graphics/SkiaUtils.h +++ b/webkit/port/platform/graphics/SkiaUtils.h @@ -7,46 +7,23 @@ #ifndef SkiaUtils_h #define SkiaUtils_h +#include <wtf/PassRefPtr.h> #include "base/float_util.h" #include "GraphicsContext.h" #include "SkPath.h" #include "SkShader.h" #include "PlatformContextSkia.h" +class WebCore::SharedBuffer; class SkRegion; -// Converts the given WebCore point to a Skia point. -void WebCorePointToSkiaPoint(const WebCore::IntPoint& src, SkPoint* dst); -void WebCorePointToSkiaPoint(const WebCore::FloatPoint& src, SkPoint* dst); - -// Converts from various types of WebCore rectangles to the corresponding -// Skia rectangle types. -void WebCoreRectToSkiaRect(const WebCore::IntRect& src, SkRect* dst); -void WebCoreRectToSkiaRect(const WebCore::FloatRect& src, SkRect* dst); -void WebCoreRectToSkiaRect(const WebCore::IntRect& src, SkIRect* dst); -void WebCoreRectToSkiaRect(const WebCore::FloatRect& src, SkIRect* dst); - -// Converts a WebCore |Path| to an SkPath. -inline SkPath* PathToSkPath(const WebCore::Path& path) { - return reinterpret_cast<SkPath*>(path.platformPath()); -} - // Converts a WebCore composit operation (WebCore::Composite*) to the // corresponding Skia type. SkPorterDuff::Mode WebCoreCompositeToSkiaComposite(WebCore::CompositeOperator); -// Converts a WebCore tiling rule to the corresponding Skia tiling mode. -SkShader::TileMode WebCoreTileToSkiaTile(WebCore::Image::TileRule); - // Converts Android colors to WebKit ones. WebCore::Color SkPMColorToWebCoreColor(SkPMColor pm); -// A platform graphics context is actually a PlatformContextSkia. -inline PlatformContextSkia* PlatformContextToPlatformContextSkia( - PlatformGraphicsContext* context) { - return reinterpret_cast<PlatformContextSkia*>(context); -} - // Skia has problems when passed infinite, etc floats, filter them to 0. inline SkScalar WebCoreFloatToSkScalar(const float& f) { return SkFloatToScalar(base::IsFinite(f) ? f : 0); @@ -74,5 +51,7 @@ void ClipRectToCanvas(const SkCanvas& canvas, const SkRect& src_rect, // Determine if a given WebKit point is contained in a path bool SkPathContainsPoint(SkPath* orig_path, WebCore::FloatPoint point, SkPath::FillType ft); -#endif // SkiaUtils_h +// Constructs a BMP V4 bitmap from an SkBitmap. +PassRefPtr<WebCore::SharedBuffer> SerializeSkBitmap(const SkBitmap&); +#endif // SkiaUtils_h diff --git a/webkit/port/platform/graphics/svg/SVGPaintServerGradientSkia.cpp b/webkit/port/platform/graphics/svg/SVGPaintServerGradientSkia.cpp index 84c445b..76b2370 100644 --- a/webkit/port/platform/graphics/svg/SVGPaintServerGradientSkia.cpp +++ b/webkit/port/platform/graphics/svg/SVGPaintServerGradientSkia.cpp @@ -35,6 +35,7 @@ #include "SVGPaintServerRadialGradient.h" #include "GraphicsContext.h" +#include "Path.h" #include "RenderObject.h" #include "RenderPath.h" #include "RenderStyle.h" @@ -156,17 +157,15 @@ bool SVGPaintServerGradient::setup(GraphicsContext*& context, SkMatrix matrix; // Calculate a matrix to transform a gradient to fit the bounding box - if(boundingBoxMode()) { + if (boundingBoxMode()) { matrix.reset(); - SkRect rc; - context->currentPath()->computeBounds(&rc, SkPath::kExact_BoundsType); + SkRect rc = context->getBoundingBoxForCurrentPath(true); matrix.preTranslate(rc.fLeft, rc.fTop); matrix.preScale(rc.width(), rc.height()); matrix.preConcat(gradientTransform()); - } else { + } else matrix = gradientTransform(); - } if (this->type() == LinearGradientPaintServer) { const SVGPaintServerLinearGradient* linear = diff --git a/webkit/port/platform/graphics/svg/SVGPaintServerPatternSkia.cpp b/webkit/port/platform/graphics/svg/SVGPaintServerPatternSkia.cpp index f9b97a6..8400633 100644 --- a/webkit/port/platform/graphics/svg/SVGPaintServerPatternSkia.cpp +++ b/webkit/port/platform/graphics/svg/SVGPaintServerPatternSkia.cpp @@ -33,6 +33,7 @@ #include "GraphicsContext.h" #include "ImageBuffer.h" #include "RenderObject.h" +#include "Pattern.h" #include "SVGPatternElement.h" #include "SVGPaintServerPattern.h" #include "SkiaSupport.h" @@ -59,20 +60,19 @@ bool SVGPaintServerPattern::setup(GraphicsContext*& context, const RenderObject* if (!tile()) return false; - SkShader* shader = SkShader::CreateBitmapShader(*tile()->image(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); + AffineTransform transform = patternTransform(); + transform.translate(patternBoundaries().x(), patternBoundaries().y()); - SkMatrix matrix = patternTransform(); - matrix.preTranslate(patternBoundaries().x(), patternBoundaries().y()); - - shader->setLocalMatrix(matrix); - context->platformContext()->setPattern(shader); + RefPtr<Pattern> pattern(Pattern::create(tile()->image(), true, true)); if ((type & ApplyToFillTargetType) && style->svgStyle()->hasFill()) { + context->setFillPattern(pattern); if (isPaintingText) context->setTextDrawingMode(cTextFill); } if ((type & ApplyToStrokeTargetType) && style->svgStyle()->hasStroke()) { + context->setStrokePattern(pattern); applyStrokeStyleToContext(context, style, object); if (isPaintingText) context->setTextDrawingMode(cTextStroke); diff --git a/webkit/port/platform/graphics/svg/SVGPaintServerSkia.cpp b/webkit/port/platform/graphics/svg/SVGPaintServerSkia.cpp index 7684396..4acd0f9 100644 --- a/webkit/port/platform/graphics/svg/SVGPaintServerSkia.cpp +++ b/webkit/port/platform/graphics/svg/SVGPaintServerSkia.cpp @@ -36,9 +36,6 @@ #include "RenderPath.h" #include "SkiaUtils.h" -#include "SkDashPathEffect.h" - -#include "NotImplemented.h" namespace WebCore { @@ -53,22 +50,17 @@ void SVGPaintServer::draw(GraphicsContext*& context, const RenderObject* object, void SVGPaintServer::teardown(GraphicsContext*& context, const RenderObject*, SVGPaintTargetType, bool isPaintingText) const { - context->beginPath(); - context->platformContext()->setGradient(NULL); - context->platformContext()->setPattern(NULL); } void SVGPaintServer::renderPath(GraphicsContext*& context, const RenderObject* object, SVGPaintTargetType type) const { RenderStyle* renderStyle = object ? object->style() : NULL; - SkPath* path = context->currentPath(); - if ((type & ApplyToFillTargetType) && (!renderStyle || renderStyle->svgStyle()->hasFill())) - context->fillPath(path, NULL, NULL); + context->fillPath(); if ((type & ApplyToStrokeTargetType) && (!renderStyle || renderStyle->svgStyle()->hasStroke())) - context->strokePath(path, NULL, NULL); + context->strokePath(); } } // namespace WebCore diff --git a/webkit/port/platform/graphics/svg/SkiaSupport.cpp b/webkit/port/platform/graphics/svg/SkiaSupport.cpp index fbc752b..2df8841 100644 --- a/webkit/port/platform/graphics/svg/SkiaSupport.cpp +++ b/webkit/port/platform/graphics/svg/SkiaSupport.cpp @@ -55,12 +55,11 @@ void applyStrokeStyleToContext(GraphicsContext* context, const RenderStyle* styl context->setLineCap(svgStyle->capStyle()); context->setLineJoin(svgStyle->joinStyle()); - if(svgStyle->joinStyle() == MiterJoin) { + if (svgStyle->joinStyle() == MiterJoin) context->setMiterLimit(svgStyle->strokeMiterLimit()); - } - const DashArray& dashes = WebCore::dashArrayFromRenderingStyle(style); - double dashOffset = SVGRenderStyle::cssPrimitiveToLength(object, style->svgStyle()->strokeDashOffset(), 0.0); + const DashArray& dashes = dashArrayFromRenderingStyle(style); + float dashOffset = SVGRenderStyle::cssPrimitiveToLength(object, style->svgStyle()->strokeDashOffset(), 0.0); unsigned int dashLength = !dashes.isEmpty() ? dashes.size() : 0; if(dashLength) { @@ -79,9 +78,8 @@ void applyStrokeStyleToContext(GraphicsContext* context, const RenderStyle* styl GraphicsContext* scratchContext() { static GraphicsContext* scratch = NULL; - if (!scratch) { + if (!scratch) scratch = GraphicsContext::createOffscreenContext(1, 1); - } return scratch; } @@ -90,8 +88,10 @@ FloatRect strokeBoundingBox(const Path& path, RenderStyle* style, const RenderOb GraphicsContext* scratch = scratchContext(); scratch->save(); + scratch->beginPath(); + scratch->addPath(path); applyStrokeStyleToContext(scratch, style, object); - FloatRect bbox = scratch->getPathBoundingBox(path); + FloatRect bbox = scratch->getBoundingBoxForCurrentPath(true); scratch->restore(); return bbox; diff --git a/webkit/port/platform/image-decoders/gif/GIFImageDecoder.cpp b/webkit/port/platform/image-decoders/gif/GIFImageDecoder.cpp index 68f42dd..678e080 100644 --- a/webkit/port/platform/image-decoders/gif/GIFImageDecoder.cpp +++ b/webkit/port/platform/image-decoders/gif/GIFImageDecoder.cpp @@ -421,4 +421,3 @@ void GIFImageDecoder::gifComplete() } } - diff --git a/webkit/port/platform/image-decoders/ico/ICOImageDecoder.cpp b/webkit/port/platform/image-decoders/ico/ICOImageDecoder.cpp index cd740b4..f102b22 100644 --- a/webkit/port/platform/image-decoders/ico/ICOImageDecoder.cpp +++ b/webkit/port/platform/image-decoders/ico/ICOImageDecoder.cpp @@ -217,8 +217,8 @@ void ICOImageDecoder::decodePNG(SharedBuffer* data) // offset the perceived start of |data| by |m_dirEntry.dwImageOffset| when // passing it to setData()... RefPtr<SharedBuffer> pngData( - new SharedBuffer(&data->data()[m_dirEntry.dwImageOffset], - data->size() - m_dirEntry.dwImageOffset)); + SharedBuffer::create(&data->data()[m_dirEntry.dwImageOffset], + data->size() - m_dirEntry.dwImageOffset)); m_pngDecoder.setData(pngData.get(), true); // Decode PNG as a side effect of asking for the frame. Strangely, it's diff --git a/webkit/port/platform/image-decoders/ico/ICOImageDecoder_unittest.cpp b/webkit/port/platform/image-decoders/ico/ICOImageDecoder_unittest.cpp index f17fd2c..d49706a 100644 --- a/webkit/port/platform/image-decoders/ico/ICOImageDecoder_unittest.cpp +++ b/webkit/port/platform/image-decoders/ico/ICOImageDecoder_unittest.cpp @@ -69,7 +69,7 @@ TEST_F(ICOImageDecoderTest, FaviconSize) { // Decode, preferring the favicon size. scoped_ptr<WebCore::ImageDecoder> decoder(new WebCore::ICOImageDecoder( WebCore::IntSize(kFavIconSize, kFavIconSize))); - RefPtr<WebCore::SharedBuffer> shared_contents(new WebCore::SharedBuffer); + RefPtr<WebCore::SharedBuffer> shared_contents(WebCore::SharedBuffer::create()); shared_contents->append(image_contents.data(), static_cast<int>(image_contents.size())); decoder->setData(shared_contents.get(), true); diff --git a/webkit/port/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/webkit/port/platform/image-decoders/jpeg/JPEGImageDecoder.cpp index 3c05d46..ebdbbaf 100644 --- a/webkit/port/platform/image-decoders/jpeg/JPEGImageDecoder.cpp +++ b/webkit/port/platform/image-decoders/jpeg/JPEGImageDecoder.cpp @@ -509,4 +509,3 @@ void JPEGImageDecoder::jpegComplete() } } - diff --git a/webkit/port/platform/image-decoders/png/PNGImageDecoder.cpp b/webkit/port/platform/image-decoders/png/PNGImageDecoder.cpp index 4ee7a67..7f62f63 100644 --- a/webkit/port/platform/image-decoders/png/PNGImageDecoder.cpp +++ b/webkit/port/platform/image-decoders/png/PNGImageDecoder.cpp @@ -409,4 +409,3 @@ void PNGImageDecoder::pngComplete() } } - diff --git a/webkit/port/platform/network/AuthenticationChallenge.cpp b/webkit/port/platform/network/AuthenticationChallenge.cpp new file mode 100644 index 0000000..f6831cf --- /dev/null +++ b/webkit/port/platform/network/AuthenticationChallenge.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2008 Google, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */
+
+#include "config.h"
+#include "AuthenticationChallenge.h"
+
+namespace WebCore {
+
+bool AuthenticationChallenge::platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b)
+{
+ return true;
+}
+
+} // namespace WebCore
diff --git a/webkit/port/platform/network/AuthenticationChallenge.h b/webkit/port/platform/network/AuthenticationChallenge.h new file mode 100644 index 0000000..b1db6cf --- /dev/null +++ b/webkit/port/platform/network/AuthenticationChallenge.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2008 Google, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef AuthenticationChallenge_h +#define AuthenticationChallenge_h + +#include "AuthenticationChallengeBase.h" +#include "ResourceHandle.h" + +#include <wtf/RefPtr.h> + +namespace WebCore { + +class ResourceHandle; + +class AuthenticationChallenge : public AuthenticationChallengeBase { +public: + AuthenticationChallenge() {} + AuthenticationChallenge(const ProtectionSpace& protectionSpace, const Credential& proposedCredential, unsigned previousFailureCount, const ResourceResponse& response, const ResourceError& error); + + ResourceHandle* sourceHandle() const { return m_sourceHandle.get(); } + +private: + friend class AuthenticationChallengeBase; + static bool platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b); + + RefPtr<ResourceHandle> m_sourceHandle; +}; + +} + +#endif diff --git a/webkit/port/platform/network/CookieJarWin.cpp b/webkit/port/platform/network/CookieJarWin.cpp index cb68d81..9d2ec62 100644 --- a/webkit/port/platform/network/CookieJarWin.cpp +++ b/webkit/port/platform/network/CookieJarWin.cpp @@ -30,7 +30,6 @@ #include "KURL.h" #include "PlatformString.h" #include "CString.h" -#include "DeprecatedString.h" #include "Vector.h" #pragma warning(pop) @@ -44,7 +43,7 @@ void setCookies(Document* document, const KURL& url, const KURL& policyURL, cons { // We ignore the policyURL and compute it directly ourselves to ensure // consistency with the cookies() method below. - KURL policyBaseURL(document->policyBaseURL().deprecatedString()); + KURL policyBaseURL = document->policyBaseURL(); WebCore::CString utf8value = value.utf8(); webkit_glue::SetCookie( webkit_glue::KURLToGURL(url), @@ -54,7 +53,7 @@ void setCookies(Document* document, const KURL& url, const KURL& policyURL, cons String cookies(const Document* document, const KURL& url) { - KURL policyBaseURL(document->policyBaseURL().deprecatedString()); + KURL policyBaseURL = document->policyBaseURL(); std::string result = webkit_glue::GetCookies(webkit_glue::KURLToGURL(url), webkit_glue::KURLToGURL(policyBaseURL)); diff --git a/webkit/port/platform/network/DNS.cpp b/webkit/port/platform/network/DNS.cpp new file mode 100644 index 0000000..a11d236 --- /dev/null +++ b/webkit/port/platform/network/DNS.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2008 Collin Jackson <collinj@webkit.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DNS.h" + +#include "webkit/glue/glue_util.h" +#include "webkit/glue/webkit_glue.h" + +namespace WebCore { + +void prefetchDNS(const String& hostname) +{ + webkit_glue::PrefetchDns(webkit_glue::StringToStdString(hostname)); +} + +}
\ No newline at end of file diff --git a/webkit/port/platform/network/NetworkStateNotifierWin.cpp b/webkit/port/platform/network/NetworkStateNotifierWin.cpp new file mode 100644 index 0000000..3f5edbb --- /dev/null +++ b/webkit/port/platform/network/NetworkStateNotifierWin.cpp @@ -0,0 +1,114 @@ +/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "NetworkStateNotifier.h"
+
+#include <wtf/MainThread.h>
+#include <wtf/Vector.h>
+
+#include <winsock2.h>
+#include <iphlpapi.h>
+
+namespace WebCore {
+
+void NetworkStateNotifier::updateState()
+{
+ // Assume that we're online until proven otherwise.
+ m_isOnLine = true;
+
+ Vector<char> buffer;
+ DWORD size = 0;
+
+ if (::GetAdaptersAddresses(AF_UNSPEC, 0, 0, 0, &size) != ERROR_BUFFER_OVERFLOW)
+ return;
+
+ buffer.resize(size);
+ PIP_ADAPTER_ADDRESSES addresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(buffer.data());
+
+ if (::GetAdaptersAddresses(AF_UNSPEC, 0, 0, addresses, &size) != ERROR_SUCCESS) {
+ // We couldn't determine whether we're online or not, so assume that we are.
+ return;
+ }
+
+ for (; addresses; addresses = addresses->Next) {
+ if (addresses->IfType == MIB_IF_TYPE_LOOPBACK)
+ continue;
+
+ if (addresses->OperStatus != IfOperStatusUp)
+ continue;
+
+ // We found an interface that was up.
+ return;
+ }
+
+ // We didn't find any valid interfaces, so we must be offline.
+ m_isOnLine = false;
+}
+
+void NetworkStateNotifier::addressChanged()
+{
+ bool oldOnLine = m_isOnLine;
+
+ updateState();
+
+ if (m_isOnLine == oldOnLine)
+ return;
+
+ if (m_networkStateChangedFunction)
+ m_networkStateChangedFunction();
+}
+
+void NetworkStateNotifier::callAddressChanged(void* context)
+{
+ static_cast<NetworkStateNotifier*>(context)->addressChanged();
+}
+
+void CALLBACK NetworkStateNotifier::addrChangeCallback(void* context, BOOLEAN timedOut)
+{
+ callOnMainThread(callAddressChanged, context);
+}
+
+void NetworkStateNotifier::registerForAddressChange()
+{
+ HANDLE handle;
+ ::NotifyAddrChange(&handle, &m_overlapped);
+}
+
+NetworkStateNotifier::NetworkStateNotifier()
+ : m_isOnLine(false)
+{
+ updateState();
+
+ memset(&m_overlapped, 0, sizeof(m_overlapped));
+
+ m_overlapped.hEvent = ::CreateEvent(0, false, false, 0);
+
+ ::RegisterWaitForSingleObject(&m_waitHandle, m_overlapped.hEvent, addrChangeCallback, this, INFINITE, 0);
+
+ registerForAddressChange();
+}
+
+}
diff --git a/webkit/port/platform/network/ResourceError.h b/webkit/port/platform/network/ResourceError.h new file mode 100644 index 0000000..a71b302 --- /dev/null +++ b/webkit/port/platform/network/ResourceError.h @@ -0,0 +1,52 @@ +// -*- mode: c++; c-basic-offset: 4 -*- +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2008 Google, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ResourceError_h +#define ResourceError_h + +#include "ResourceErrorBase.h" + +namespace WebCore { + +class ResourceError : public ResourceErrorBase { +public: + ResourceError() + { + } + + ResourceError(const String& domain, int errorCode, const String& failingURL, const String& localizedDescription) + : ResourceErrorBase(domain, errorCode, failingURL, localizedDescription) + { + } + +private: + friend class ResourceErrorBase; +}; + +} // namespace WebCore + +#endif // ResourceError_h_ diff --git a/webkit/port/platform/network/ResourceRequest.h b/webkit/port/platform/network/ResourceRequest.h index 19c401d..6420d5d 100644 --- a/webkit/port/platform/network/ResourceRequest.h +++ b/webkit/port/platform/network/ResourceRequest.h @@ -40,7 +40,7 @@ namespace WebCore { class ResourceRequest : public ResourceRequestBase { public: ResourceRequest(const String& url) - : ResourceRequestBase(KURL(url.deprecatedString()), UseProtocolCachePolicy) + : ResourceRequestBase(KURL(url), UseProtocolCachePolicy) , m_frame(0) , m_originPid(0) , m_resourceType(ResourceType::SUB_RESOURCE) diff --git a/webkit/port/plugins/PluginDataChromium.cpp b/webkit/port/plugins/PluginDataChromium.cpp new file mode 100644 index 0000000..c289464 --- /dev/null +++ b/webkit/port/plugins/PluginDataChromium.cpp @@ -0,0 +1,55 @@ +// Copyright (c) 2008 The Chromium Authors. All rights reserved. Use of this +// source code is governed by a BSD-style license that can be found in the +// LICENSE file. + +#include "config.h" +#include "PluginData.h" + +#undef LOG +#include "webkit/glue/glue_util.h" +#include "webkit/glue/webkit_glue.h" + +namespace WebCore { + +static bool refreshData = false; + +void PluginData::initPlugins() +{ + std::vector<WebPluginInfo> plugins; + if (!webkit_glue::GetPlugins(refreshData, &plugins)) + return; + refreshData = false; + + for (size_t i = 0; i < plugins.size(); ++i) { + const WebPluginInfo& sourceInfo = plugins[i]; + + PluginInfo* info = new PluginInfo; + info->name = webkit_glue::StdWStringToString(sourceInfo.name); + info->file = webkit_glue::StdWStringToString(sourceInfo.file); + info->desc = webkit_glue::StdWStringToString(sourceInfo.desc); + + for (size_t j = 0; j < sourceInfo.mime_types.size(); ++j) { + const WebPluginMimeType& mimeType = sourceInfo.mime_types[j]; + + MimeClassInfo* mime = new MimeClassInfo; + mime->type = webkit_glue::StdStringToString(mimeType.mime_type); + mime->desc = webkit_glue::StdWStringToString(mimeType.description); + + for (size_t k = 0; k < mimeType.file_extensions.size(); ++k) { + if (k > 0) + mime->suffixes += ","; + mime->suffixes += webkit_glue::StdStringToString(mimeType.file_extensions[k]); + } + info->mimes.append(mime); + } + m_plugins.append(info); + } +} + +void PluginData::refresh() +{ + // When next we initialize a PluginData, it'll be fresh. + refreshData = true; +} + +} diff --git a/webkit/port/rendering/RenderThemeWin.cpp b/webkit/port/rendering/RenderThemeWin.cpp index ea0eb73..d1bc89c 100644 --- a/webkit/port/rendering/RenderThemeWin.cpp +++ b/webkit/port/rendering/RenderThemeWin.cpp @@ -250,7 +250,7 @@ static wchar_t* defaultGUIFont(Document* document) if (dominantScript != USCRIPT_LATIN && dominantScript != USCRIPT_CYRILLIC && dominantScript != USCRIPT_GREEK && dominantScript != USCRIPT_INVALID_CODE) { family = gfx::GetFontFamilyForScript(dominantScript, - gfx::GenericFamilyType::GENERIC_FAMILY_NONE); + gfx::GENERIC_FAMILY_NONE); if (family) return const_cast<wchar_t*>(family); } @@ -293,7 +293,7 @@ void RenderThemeWin::systemFont(int propId, Document* document, FontDescription& wchar_t* faceName = 0; float fontSize = 0; switch (propId) { - case CSS_VAL_SMALL_CAPTION: + case CSSValueSmallCaption: cachedDesc = &SmallSystemFont; if (!SmallSystemFont.isAbsoluteSize()) { if (webkit_glue::IsLayoutTestMode()) { @@ -306,7 +306,7 @@ void RenderThemeWin::systemFont(int propId, Document* document, FontDescription& } } break; - case CSS_VAL_MENU: + case CSSValueMenu: cachedDesc = &MenuFont; if (!MenuFont.isAbsoluteSize()) { if (webkit_glue::IsLayoutTestMode()) { @@ -319,7 +319,7 @@ void RenderThemeWin::systemFont(int propId, Document* document, FontDescription& } } break; - case CSS_VAL_STATUS_BAR: + case CSSValueStatusBar: cachedDesc = &LabelFont; if (!LabelFont.isAbsoluteSize()) { if (webkit_glue::IsLayoutTestMode()) { @@ -332,7 +332,7 @@ void RenderThemeWin::systemFont(int propId, Document* document, FontDescription& } } break; - case CSS_VAL__WEBKIT_MINI_CONTROL: + case CSSValueWebkitMiniControl: if (webkit_glue::IsLayoutTestMode()) { fontSize = systemFontSizeForControlSize(MiniControlSize); } else { @@ -342,7 +342,7 @@ void RenderThemeWin::systemFont(int propId, Document* document, FontDescription& fontSize = DefaultFontSize - pointsToPixels(2); } break; - case CSS_VAL__WEBKIT_SMALL_CONTROL: + case CSSValueWebkitSmallControl: if (webkit_glue::IsLayoutTestMode()) { fontSize = systemFontSizeForControlSize(SmallControlSize); } else { @@ -350,7 +350,7 @@ void RenderThemeWin::systemFont(int propId, Document* document, FontDescription& fontSize = DefaultFontSize - pointsToPixels(2); } break; - case CSS_VAL__WEBKIT_CONTROL: + case CSSValueWebkitControl: if (webkit_glue::IsLayoutTestMode()) { fontSize = systemFontSizeForControlSize(RegularControlSize); } else { @@ -381,7 +381,7 @@ void RenderThemeWin::systemFont(int propId, Document* document, FontDescription& cachedDesc->setIsAbsoluteSize(true); cachedDesc->setGenericFamily(FontDescription::NoFamily); cachedDesc->setSpecifiedSize(fontSize); - cachedDesc->setBold(false); + cachedDesc->setWeight(FontWeightNormal); cachedDesc->setItalic(false); } fontDescription = *cachedDesc; @@ -477,10 +477,7 @@ ThemeData RenderThemeWin::getThemeData(RenderObject* o) bool RenderThemeWin::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { // Get the correct theme data for a button and paint the button. - PlatformContextSkia* skia = PlatformContextToPlatformContextSkia(i.context->platformContext()); - SkIRect rect; - WebCoreRectToSkiaRect(r, &rect); - skia->paintButton(rect, getThemeData(o)); + i.context->platformContext()->paintButton(r, getThemeData(o)); return false; } @@ -554,10 +551,7 @@ bool RenderThemeWin::paintTextFieldInternal(RenderObject* o, const RenderObject: return false; // Get the correct theme data for a textfield and paint the text field. - PlatformContextSkia* skia = PlatformContextToPlatformContextSkia(i.context->platformContext()); - SkIRect rect; - WebCoreRectToSkiaRect(r, &rect); - skia->paintTextField(rect, getThemeData(o), o->style()->backgroundColor().rgb(), drawEdges); + i.context->platformContext()->paintTextField(r, getThemeData(o), o->style()->backgroundColor().rgb(), drawEdges); return false; } @@ -634,10 +628,7 @@ bool RenderThemeWin::paintMenuList(RenderObject* o, const RenderObject::PaintInf r.height() - (spacingTop + spacingBottom)); // Get the correct theme data for a textfield and paint the menu. - PlatformContextSkia* skia = PlatformContextToPlatformContextSkia(i.context->platformContext()); - SkIRect rect; - WebCoreRectToSkiaRect(buttonRect, &rect); - skia->paintMenuListArrowButton(rect, determineState(o), determineClassicState(o)); + i.context->platformContext()->paintMenuListArrowButton(buttonRect, determineState(o), determineClassicState(o)); return false; } diff --git a/webkit/port/xml/XMLHttpRequest.idl b/webkit/port/xml/XMLHttpRequest.idl deleted file mode 100644 index cc4527c..0000000 --- a/webkit/port/xml/XMLHttpRequest.idl +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2008, 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. - -module core { - -interface XMLHttpRequest { - attribute [CustomSetter] EventListener onreadystatechange; - attribute [CustomSetter] EventListener onload; - readonly attribute unsigned short readyState; - readonly attribute DOMString responseText - getter raises(DOMExcecption); - readonly attribute Document responseXML - getter raises(DOMExcecption); - readonly attribute unsigned short status - getter raises(DOMExcecption); - readonly attribute DOMString statusText - getter raises(DOMExcecption); - - [Custom] void open(in DOMString method, in DOMString url, in boolean async, in DOMString users, in DOMString passwd); - [Custom] void send(in DOMString data); - void abort(); - [Custom] void setRequestHeader(in DOMString header, in DOMString value) - raises (DOMException); - [ConvertNullStringTo=Null] DOMString getAllResponseHeaders() - raises(DOMException); - [Custom] DOMString getResponseHeader(in DOMString header) - raises(DOMException); - - [Custom] void overrideMimeType(in DOMString value); - - [Custom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [Custom] void removeEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - boolean dispatchEvent(in Event event) - raises(EventException); -}; - -} |