diff options
author | Andrei Popescu <andreip@google.com> | 2009-06-08 17:39:30 +0100 |
---|---|---|
committer | Andrei Popescu <andreip@google.com> | 2009-06-08 17:40:48 +0100 |
commit | 595f429f16d56891f697a15c3ec2fd2ec9647c5f (patch) | |
tree | 0567454fd15ccfac8f82047ce0203a0878c186f6 | |
parent | 91637c8ca6b8baa16edf528ee009b228d6e6c053 (diff) | |
download | external_webkit-595f429f16d56891f697a15c3ec2fd2ec9647c5f.zip external_webkit-595f429f16d56891f697a15c3ec2fd2ec9647c5f.tar.gz external_webkit-595f429f16d56891f697a15c3ec2fd2ec9647c5f.tar.bz2 |
Make AppCache work with v8:
-- Most changes follow Chrome's changes in the same area
-- I needed to update the CodeGeneratorV8.pm to the latest version
-- I needed to deprecate v8_utility.h and replace it with V8Utilities.h/cpp
-rw-r--r-- | V8Binding/V8Binding.derived.mk | 15 | ||||
-rw-r--r-- | V8Binding/scripts/CodeGeneratorV8.pm | 76 | ||||
-rw-r--r-- | V8Binding/v8/DOMObjectsInclude.h | 1 | ||||
-rw-r--r-- | V8Binding/v8/V8Utilities.cpp | 110 | ||||
-rw-r--r-- | V8Binding/v8/V8Utilities.h | 131 | ||||
-rw-r--r-- | V8Binding/v8/v8_custom.h | 14 | ||||
-rw-r--r-- | V8Binding/v8/v8_index.cpp | 4 | ||||
-rw-r--r-- | V8Binding/v8/v8_index.h | 8 | ||||
-rw-r--r-- | V8Binding/v8/v8_proxy.cpp | 16 | ||||
-rw-r--r-- | V8Binding/v8/v8_proxy.h | 2 | ||||
-rw-r--r-- | V8Binding/v8/v8_utility.h | 58 | ||||
-rw-r--r-- | WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp | 142 | ||||
-rw-r--r-- | WebCore/loader/appcache/DOMApplicationCache.cpp | 45 | ||||
-rw-r--r-- | WebCore/loader/appcache/DOMApplicationCache.h | 10 |
14 files changed, 552 insertions, 80 deletions
diff --git a/V8Binding/V8Binding.derived.mk b/V8Binding/V8Binding.derived.mk index ce32839..67f5d06 100644 --- a/V8Binding/V8Binding.derived.mk +++ b/V8Binding/V8Binding.derived.mk @@ -56,6 +56,7 @@ WEBCORE_SRC_FILES := \ bindings/v8/custom/V8DOMStringListCustom.cpp \ bindings/v8/custom/V8DOMWindowCustom.cpp \ bindings/v8/custom/V8DocumentCustom.cpp \ + bindings/v8/custom/V8DOMApplicationCacheCustom.cpp \ bindings/v8/custom/V8ElementCustom.cpp \ bindings/v8/custom/V8EventCustom.cpp \ bindings/v8/custom/V8HTMLCanvasElementCustom.cpp \ @@ -113,6 +114,7 @@ LOCAL_SRC_FILES := \ v8/V8MessagePortCustom.cpp \ v8/V8NPObject.cpp \ v8/V8NPUtils.cpp \ + v8/V8Utilities.cpp \ v8/V8WorkerContextCustom.cpp \ v8/V8WorkerCustom.cpp \ v8/npruntime.cpp \ @@ -137,7 +139,7 @@ js_binding_scripts := \ $(WEBCORE_PATH)/bindings/scripts/IDLStructure.pm \ $(LOCAL_PATH)/scripts/generate-bindings.pl -FEATURE_DEFINES := ANDROID_ORIENTATION_SUPPORT ENABLE_TOUCH_EVENTS=1 V8_BINDING ENABLE_DATABASE=1 +FEATURE_DEFINES := ANDROID_ORIENTATION_SUPPORT ENABLE_TOUCH_EVENTS=1 V8_BINDING ENABLE_DATABASE=1 ENABLE_OFFLINE_WEB_APPLICATIONS=1 GEN := \ $(intermediates)/css/V8CSSCharsetRule.h \ @@ -316,6 +318,17 @@ LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) # above rules. Specifying this explicitly makes -j2 work. $(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/html/%.cpp : $(intermediates)/html/%.h +GEN := \ + $(intermediates)/loader/appcache/V8DOMApplicationCache.h + +$(GEN): PRIVATE_CUSTOM_TOOL = SOURCE_ROOT=$(WEBCORE_PATH) perl -I$(v8binding_dir)/scripts -I$(WEBCORE_PATH)/bindings/scripts $(v8binding_dir)/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator V8 --include dom --include html --outputdir $(dir $@) $< +$(GEN): $(intermediates)/loader/appcache/V8%.h : $(WEBCORE_PATH)/loader/appcache/%.idl $(js_binding_scripts) + $(transform-generated-source) +LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp) + +# We also need the .cpp files, which are generated as side effects of the +# above rules. Specifying this explicitly makes -j2 work. +$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/loader/appcache/%.cpp : $(intermediates)/loader/appcache/%.h GEN := \ $(intermediates)/page/V8BarInfo.h \ diff --git a/V8Binding/scripts/CodeGeneratorV8.pm b/V8Binding/scripts/CodeGeneratorV8.pm index 541d17b..37a9f74 100644 --- a/V8Binding/scripts/CodeGeneratorV8.pm +++ b/V8Binding/scripts/CodeGeneratorV8.pm @@ -4,7 +4,7 @@ # Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org> # Copyright (C) 2006 Apple Computer, Inc. -# Copyright (C) 2007 Google Inc. +# Copyright (C) 2007, 2008, 2009 Google Inc. # # This file is part of the KDE project # @@ -314,6 +314,8 @@ END push(@headerContent, "}\n\n"); push(@headerContent, "#endif // $className" . "_H\n"); + push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditional; + if ($className =~ /^V8SVG/) { push(@headerContent, "\n#endif // ENABLE(SVG)\n"); } elsif (IsVideoClassName($className)) { @@ -321,8 +323,6 @@ END } elsif (IsWorkerClassName($className)) { push(@headerContent, "\n#endif // ENABLE(WORKERS)\n"); } - - push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditional; } @@ -450,10 +450,11 @@ END return WorkerContextExecutionProxy::retrieve()->GetConstructor(type); END } else { - push(@implContentDecls, " return V8Proxy::retrieve()->GetConstructor(type);"); + push(@implContentDecls, " return v8::Undefined();"); } push(@implContentDecls, <<END); + } END @@ -931,6 +932,7 @@ sub GenerateBatchedAttributeData my $getter; my $setter; my $propAttr = "v8::None"; + my $hasCustomSetter = 0; # Check attributes. if ($attrExt->{"DontEnum"}) { @@ -954,13 +956,24 @@ sub GenerateBatchedAttributeData $propAttr = "v8::ReadOnly"; # EventListeners - } elsif ($attrExt->{"ProtectedListener"}) { + } elsif ($attribute->signature->type eq "EventListener") { if ($interfaceName eq "DOMWindow") { $getter = "V8Custom::v8DOMWindowEventHandlerAccessorGetter"; $setter = "V8Custom::v8DOMWindowEventHandlerAccessorSetter"; - } else { + } elsif ($interfaceName eq "DOMApplicationCache") { + $getter = "V8Custom::v8DOMApplicationCacheEventHandlerAccessorGetter"; + $setter = "V8Custom::v8DOMApplicationCacheEventHandlerAccessorSetter"; + } elsif ($interfaceName eq "Node" || $interfaceName eq "SVGElementInstance") { $getter = "V8Custom::v8ElementEventHandlerAccessorGetter"; $setter = "V8Custom::v8ElementEventHandlerAccessorSetter"; + } else { + $getter = "V8Custom::v8${customAccessor}AccessorGetter"; + if ($interfaceName eq "WorkerContext" and $attrName eq "self") { + $setter = "0"; + $propAttr = "v8::ReadOnly"; + } else { + $setter = "V8Custom::v8${customAccessor}AccessorSetter"; + } } # Custom Getter and Setter @@ -970,11 +983,13 @@ sub GenerateBatchedAttributeData $setter = "0"; $propAttr = "v8::ReadOnly"; } else { + $hasCustomSetter = 1; $setter = "V8Custom::v8${customAccessor}AccessorSetter"; } # Custom Setter } elsif ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"}) { + $hasCustomSetter = 1; $getter = "${interfaceName}Internal::${attrName}AttrGetter"; $setter = "V8Custom::v8${customAccessor}AccessorSetter"; @@ -988,14 +1003,28 @@ sub GenerateBatchedAttributeData # Replaceable accessor is put on instance template with ReadOnly attribute. $getter = "${interfaceName}Internal::${attrName}AttrGetter"; $setter = "0"; - $propAttr .= "|v8::ReadOnly"; - + + # Mark to avoid duplicate v8::ReadOnly flags in output. + $hasCustomSetter = 1; + + # Handle the special case of window.top being marked upstream as Replaceable. + # TODO(dglazkov): Investigate why [Replaceable] is not marked as ReadOnly + # upstream and reach parity. + if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) { + $propAttr .= "|v8::ReadOnly"; + } + # Normal } else { $getter = "${interfaceName}Internal::${attrName}AttrGetter"; $setter = "${interfaceName}Internal::${attrName}AttrSetter"; } + if ($attrExt->{"Replaceable"} && !$hasCustomSetter) { + $setter = "0"; + $propAttr .= "|v8::ReadOnly"; + } + # Read only attributes if ($attribute->type =~ /^readonly/ || $attrExt->{"V8ReadOnly"}) { $setter = "0"; @@ -1052,7 +1081,7 @@ sub GenerateImplementation } elsif (IsWorkerClassName($className)) { push(@implFixedHeader, "#if ENABLE(WORKERS)\n\n"); } - + my $conditionalString; if ($conditional) { $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; @@ -1388,6 +1417,7 @@ END } elsif (IsWorkerClassName($className)) { push(@implContent, "\n#endif // ENABLE(WORKERS)\n"); } + push(@implContent, "\n#endif // ${conditionalString}\n") if $conditional; } @@ -1684,6 +1714,7 @@ sub GetNativeType return $type } + return "int" if $type eq "int"; 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"; @@ -1698,6 +1729,7 @@ sub GetNativeType return "double" if $type eq "SVGNumber"; return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType"; return "DOMTimeStamp" if $type eq "DOMTimeStamp"; + return "unsigned" if $type eq "unsigned int"; return "unsigned" if $type eq "RGBColor"; return "Node*" if $type eq "EventTarget" and $isParameter; @@ -1724,7 +1756,6 @@ my %typeCanFailConversion = ( "Event" => 0, "EventListener" => 0, "EventTarget" => 0, - "Geoposition" => 0, "HTMLElement" => 0, "HTMLOptionElement" => 0, "Node" => 0, @@ -1736,14 +1767,14 @@ my %typeCanFailConversion = ( "SQLResultSet" => 0, "SVGAngle" => 0, "SVGElement" => 0, - "SVGLength" => 0, - "SVGMatrix" => 0, + "SVGLength" => 1, + "SVGMatrix" => 1, "SVGNumber" => 0, "SVGPaintType" => 0, "SVGPathSeg" => 0, - "SVGPoint" => 0, - "SVGRect" => 0, - "SVGTransform" => 0, + "SVGPoint" => 1, + "SVGRect" => 1, + "SVGTransform" => 1, "TouchList" => 0, "VoidCallback" => 1, "WebKitCSSMatrix" => 0, @@ -1759,7 +1790,6 @@ my %typeCanFailConversion = ( "unsigned short" => 0, ); - sub TranslateParameter { my $signature = shift; @@ -1772,7 +1802,14 @@ sub TranslateParameter sub BasicTypeCanFailConversion { - # As can been seen from the above, no basic types can fail conversion. + my $signature = shift; + my $type = $codeGenerator->StripModule($signature->type); + + return 1 if $type eq "SVGLength"; + return 1 if $type eq "SVGMatrix"; + return 1 if $type eq "SVGPoint"; + return 1 if $type eq "SVGRect"; + return 1 if $type eq "SVGTransform"; return 0; } @@ -1856,8 +1893,7 @@ sub JSValueToNative my $nativeType = GetNativeType($type); $implIncludes{"V8SVGPODTypeWrapper.h"} = 1; - # TODO(jhass): perform type checking like others??? - return "*V8Proxy::ToNativeObject<V8SVGPODTypeWrapper<${nativeType}> >(V8ClassIndex::${classIndex}, $value)" + return "V8SVGPODTypeUtil::ToSVGPODType<${nativeType}>(V8ClassIndex::${classIndex}, $value${maybeOkParam})" } $implIncludes{"V8${type}.h"} = 1; @@ -2037,7 +2073,7 @@ sub NativeToJSValue return "V8Proxy::ToV8Object(V8ClassIndex::RGBCOLOR, new RGBColor($value))"; } - if ($type eq "WorkerLocation" or $type eq "WorkerNavigator") { + if ($type eq "WorkerContext" or $type eq "WorkerLocation" or $type eq "WorkerNavigator") { $implIncludes{"WorkerContextExecutionProxy.h"} = 1; my $classIndex = uc($type); diff --git a/V8Binding/v8/DOMObjectsInclude.h b/V8Binding/v8/DOMObjectsInclude.h index b7b941e..0268bca 100644 --- a/V8Binding/v8/DOMObjectsInclude.h +++ b/V8Binding/v8/DOMObjectsInclude.h @@ -32,6 +32,7 @@ #include "Database.h" #include "DocumentType.h" #include "DocumentFragment.h" +#include "DOMApplicationCache.h" #include "DOMCoreException.h" #include "DOMImplementation.h" #include "DOMParser.h" diff --git a/V8Binding/v8/V8Utilities.cpp b/V8Binding/v8/V8Utilities.cpp new file mode 100644 index 0000000..8853506 --- /dev/null +++ b/V8Binding/v8/V8Utilities.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2008, 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "V8Utilities.h" + +#include <v8.h> + +#include "V8CustomBinding.h" +#include "V8Proxy.h" + +#include <wtf/Assertions.h> +#include "Frame.h" + +namespace WebCore { + +// Use an array to hold dependents. It works like a ref-counted scheme. +// A value can be added more than once to the DOM object. +void createHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex) +{ + v8::Local<v8::Value> cache = object->GetInternalField(cacheIndex); + if (cache->IsNull() || cache->IsUndefined()) { + cache = v8::Array::New(); + object->SetInternalField(cacheIndex, cache); + } + + v8::Local<v8::Array> cacheArray = v8::Local<v8::Array>::Cast(cache); + cacheArray->Set(v8::Integer::New(cacheArray->Length()), value); +} + +void removeHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex) +{ + v8::Local<v8::Value> cache = object->GetInternalField(cacheIndex); + ASSERT(cache->IsArray()); + v8::Local<v8::Array> cacheArray = v8::Local<v8::Array>::Cast(cache); + for (int i = cacheArray->Length() - 1; i >= 0; --i) { + v8::Local<v8::Value> cached = cacheArray->Get(v8::Integer::New(i)); + if (cached->StrictEquals(value)) { + cacheArray->Delete(i); + return; + } + } + + // We should only get here if we try to remove an event listener that was never added. + ASSERT_NOT_REACHED(); +} + +#if PLATFORM(ANDROID) + // The functions below are not needed on Android. +#else +bool processingUserGesture() +{ + Frame* frame = V8Proxy::retrieveFrameForEnteredContext(); + return frame && frame->script()->processingUserGesture(); +} + +bool shouldAllowNavigation(Frame* frame) +{ + Frame* callingFrame = V8Proxy::retrieveFrameForCallingContext(); + return callingFrame && callingFrame->loader()->shouldAllowNavigation(frame); +} + +KURL completeURL(const String& relativeURL) +{ + // For histoical reasons, we need to complete the URL using the dynamic frame. + Frame* frame = V8Proxy::retrieveFrameForEnteredContext(); + if (!frame) + return KURL(); + return frame->loader()->completeURL(relativeURL); +} + +void navigateIfAllowed(Frame* frame, const KURL& url, bool lockHistory, bool lockBackForwardList) +{ + Frame* callingFrame = V8Proxy::retrieveFrameForCallingContext(); + if (!callingFrame) + return; + + if (!protocolIsJavaScript(url) || ScriptController::isSafeScript(frame)) + frame->loader()->scheduleLocationChange(url.string(), callingFrame->loader()->outgoingReferrer(), lockHistory, lockBackForwardList, processingUserGesture()); +} +#endif // PLATFORM(ANDROID) + +} // namespace WebCore diff --git a/V8Binding/v8/V8Utilities.h b/V8Binding/v8/V8Utilities.h new file mode 100644 index 0000000..f4346f6 --- /dev/null +++ b/V8Binding/v8/V8Utilities.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef V8Utilities_h +#define V8Utilities_h + +// FIXME: Remove once chromium dependencies on v8_utility.h are removed. +#define V8UTILITIES_DEFINED 1 + +#include <v8.h> + +namespace WebCore { + + class Frame; + class KURL; + class String; + + // Use an array to hold dependents. It works like a ref-counted scheme. A value can be added more than once to the DOM object. + void createHiddenDependency(v8::Local<v8::Object>, v8::Local<v8::Value>, int cacheIndex); + void removeHiddenDependency(v8::Local<v8::Object>, v8::Local<v8::Value>, int cacheIndex); + +#if PLATFORM(ANDROID) + // The functions below are not needed (yet) on Android. +#else + bool processingUserGesture(); + bool shouldAllowNavigation(Frame*); + KURL completeURL(const String& relativeURL); + void navigateIfAllowed(Frame*, const KURL&, bool lockHistory, bool lockBackForwardList); +#endif // PLATFORM(ANDROID) + + class AllowAllocation { + public: + inline AllowAllocation() + { + m_previous = m_current; + m_current = true; + } + + inline ~AllowAllocation() + { + m_current = m_previous; + } + + static bool m_current; + + private: + bool m_previous; + }; + + class SafeAllocation { + public: + static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>); + static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::ObjectTemplate>); + static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); + + // FIXME: These NewInstance functions are here to ease upstreaming. Remove along with V8UTILITIES_DEFINED once chromium dependencies on v8_utility.h are removed. + static inline v8::Local<v8::Object> NewInstance(v8::Handle<v8::Function>); + static inline v8::Local<v8::Object> NewInstance(v8::Handle<v8::ObjectTemplate>); + static inline v8::Local<v8::Object> NewInstance(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); + }; + + v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::Function> function) + { + if (function.IsEmpty()) + return v8::Local<v8::Object>(); + AllowAllocation allow; + return function->NewInstance(); + } + + v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::ObjectTemplate> objectTemplate) + { + if (objectTemplate.IsEmpty()) + return v8::Local<v8::Object>(); + AllowAllocation allow; + return objectTemplate->NewInstance(); + } + + v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) + { + if (function.IsEmpty()) + return v8::Local<v8::Object>(); + AllowAllocation allow; + return function->NewInstance(argc, argv); + } + + // FIXME: These NewInstance functions are here to ease upstreaming. Remove along with V8UTILITIES_DEFINED once chromium dependencies on v8_utility.h are removed. + v8::Local<v8::Object> SafeAllocation::NewInstance(v8::Handle<v8::Function> function) + { + return newInstance(function); + } + + v8::Local<v8::Object> SafeAllocation::NewInstance(v8::Handle<v8::ObjectTemplate> objectTemplate) + { + return newInstance(objectTemplate); + } + + v8::Local<v8::Object> SafeAllocation::NewInstance(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) + { + return newInstance(function, argc, argv); + } + +} // namespace WebCore + +#endif // V8Utilities_h diff --git a/V8Binding/v8/v8_custom.h b/V8Binding/v8/v8_custom.h index a891e2e..caeac41 100644 --- a/V8Binding/v8/v8_custom.h +++ b/V8Binding/v8/v8_custom.h @@ -135,6 +135,13 @@ class V8Custom { static const int kStyleSheetInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + static const int kDOMApplicationCacheCacheIndex = + kDefaultWrapperInternalFieldCount + 0; + static const int kDOMApplicationCacheFieldCount = + kDefaultWrapperInternalFieldCount + 1; +#endif + #define DECLARE_PROPERTY_ACCESSOR_GETTER(NAME) \ static v8::Handle<v8::Value> v8##NAME##AccessorGetter(\ v8::Local<v8::String> name, const v8::AccessorInfo& info); @@ -503,6 +510,13 @@ DECLARE_CALLBACK(WorkerContextAddEventListener) DECLARE_CALLBACK(WorkerContextRemoveEventListener) #endif +// AppCache +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +DECLARE_PROPERTY_ACCESSOR(DOMApplicationCacheEventHandler) +DECLARE_CALLBACK(DOMApplicationCacheAddEventListener) +DECLARE_CALLBACK(DOMApplicationCacheRemoveEventListener) +#endif + #undef DECLARE_INDEXED_ACCESS_CHECK #undef DECLARE_NAMED_ACCESS_CHECK diff --git a/V8Binding/v8/v8_index.cpp b/V8Binding/v8/v8_index.cpp index fcc75e9..df138dc 100644 --- a/V8Binding/v8/v8_index.cpp +++ b/V8Binding/v8/v8_index.cpp @@ -392,6 +392,10 @@ #include "V8VoidCallback.h" #endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +#include "V8DOMApplicationCache.h" +#endif + namespace WebCore { FunctionTemplateFactory V8ClassIndex::GetFactory(V8WrapperType type) { diff --git a/V8Binding/v8/v8_index.h b/V8Binding/v8/v8_index.h index b8d76ed..71453c3 100644 --- a/V8Binding/v8/v8_index.h +++ b/V8Binding/v8/v8_index.h @@ -39,6 +39,13 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #define WORKER_NONNODE_WRAPPER_TYPES(V) #endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +#define APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) \ + V(DOMAPPLICATIONCACHE, DOMApplicationCache) +#else +#define APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) +#endif + #define DOM_NODE_TYPES(V) \ V(ATTR, Attr) \ V(CHARACTERDATA, CharacterData) \ @@ -328,6 +335,7 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(XMLHTTPREQUESTPROGRESSEVENT, XMLHttpRequestProgressEvent) \ V(XMLSERIALIZER, XMLSerializer) \ ACTIVE_DOM_OBJECT_TYPES(V) \ + APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) \ VIDEO_NONNODE_TYPES(V) \ WORKER_NONNODE_WRAPPER_TYPES(V) diff --git a/V8Binding/v8/v8_proxy.cpp b/V8Binding/v8/v8_proxy.cpp index 204b2bc..45b56d7 100644 --- a/V8Binding/v8/v8_proxy.cpp +++ b/V8Binding/v8/v8_proxy.cpp @@ -1658,6 +1658,16 @@ v8::Persistent<v8::FunctionTemplate> V8Proxy::GetTemplate( } #endif // WORKERS +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + case V8ClassIndex::DOMAPPLICATIONCACHE: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instance_template = + desc->InstanceTemplate(); + instance_template->SetInternalFieldCount( + V8Custom::kDOMApplicationCacheFieldCount); + break; + } +#endif // The following objects are created from JavaScript. case V8ClassIndex::DOMPARSER: @@ -3065,6 +3075,12 @@ v8::Handle<v8::Value> V8Proxy::EventTargetToV8Object(EventTarget* target) return ToV8Object(V8ClassIndex::WORKER, worker); #endif // WORKERS +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + DOMApplicationCache* app_cache = target->toDOMApplicationCache(); + if (app_cache) + return ToV8Object(V8ClassIndex::DOMAPPLICATIONCACHE, app_cache); +#endif + Node* node = target->toNode(); if (node) return NodeToV8Object(node); diff --git a/V8Binding/v8/v8_proxy.h b/V8Binding/v8/v8_proxy.h index 45f9f39..17a2d1b 100644 --- a/V8Binding/v8/v8_proxy.h +++ b/V8Binding/v8/v8_proxy.h @@ -8,7 +8,7 @@ #include <v8.h> #include "v8_index.h" #include "v8_custom.h" -#include "v8_utility.h" +#include "V8Utilities.h" #include "Node.h" #include "NodeFilter.h" #include "PlatformString.h" // for WebCore::String diff --git a/V8Binding/v8/v8_utility.h b/V8Binding/v8/v8_utility.h deleted file mode 100644 index 620c04c..0000000 --- a/V8Binding/v8/v8_utility.h +++ /dev/null @@ -1,58 +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. - -#ifndef V8_UTILITY_H__ -#define V8_UTILITY_H__ - -namespace WebCore { - -class AllowAllocation { - public: - inline AllowAllocation() { - m_prev = m_current; - m_current = true; - } - inline ~AllowAllocation() { - m_current = m_prev; - } - static bool m_current; - private: - bool m_prev; -}; - -class SafeAllocation { - public: - static inline v8::Local<v8::Object> NewInstance( - v8::Handle<v8::Function> fun); - static inline v8::Local<v8::Object> NewInstance( - v8::Handle<v8::ObjectTemplate> templ); - static inline v8::Local<v8::Object> NewInstance( - v8::Handle<v8::Function> fun, int argc, v8::Handle<v8::Value> argv[]); -}; - -v8::Local<v8::Object> SafeAllocation::NewInstance( - v8::Handle<v8::Function> fun) { - if (fun.IsEmpty()) - return v8::Local<v8::Object>(); - AllowAllocation allow; - return fun->NewInstance(); -} - -v8::Local<v8::Object> SafeAllocation::NewInstance( - v8::Handle<v8::ObjectTemplate> templ) { - if (templ.IsEmpty()) return v8::Local<v8::Object>(); - AllowAllocation allow; - return templ->NewInstance(); -} - -v8::Local<v8::Object> SafeAllocation::NewInstance( - v8::Handle<v8::Function> fun, int argc, v8::Handle<v8::Value> argv[]) { - if (fun.IsEmpty()) return v8::Local<v8::Object>(); - AllowAllocation allow; - return fun->NewInstance(argc, argv); -} - -} // namespace WebCore - -#endif // V8_UTILITY_H__ diff --git a/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp b/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp new file mode 100644 index 0000000..b0789e5 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2008, 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DOMApplicationCache.h" + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + +#include "V8Binding.h" +#include "V8Document.h" +#include "V8CustomBinding.h" +#include "V8ObjectEventListener.h" +#include "V8Proxy.h" +#include "V8Utilities.h" +#include "WorkerContextExecutionProxy.h" + +namespace WebCore { + +static const bool kFindOnly = true; +static const bool kFindOrCreate = false; + +static PassRefPtr<EventListener> argumentToEventListener(DOMApplicationCache* appcache, v8::Local<v8::Value> value, bool findOnly) +{ +#if 0 && ENABLE(WORKERS) + // FIXME: this is not tested yet + WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); + if (workerContextProxy) + return workerContextProxy->findOrCreateObjectEventListener(value, false, findOnly); +#endif + + V8Proxy* proxy = V8Proxy::retrieve(appcache->scriptExecutionContext()); + if (proxy) + return findOnly ? proxy->FindObjectEventListener(value, false) + : proxy->FindOrCreateObjectEventListener(value, false); + return 0; +} + +static v8::Local<v8::Object> eventListenerToV8Object(EventListener* listener) +{ + return (static_cast<V8ObjectEventListener*>(listener))->getListenerObject(); +} + +static inline String toEventType(v8::Local<v8::String> value) +{ + String key = toWebCoreString(value); + ASSERT(key.startsWith("on")); + return key.substring(2); +} + +// Handles appcache.onfooevent attribute getting +ACCESSOR_GETTER(DOMApplicationCacheEventHandler) +{ + INC_STATS("DOMApplicationCache.onevent_getter"); + DOMApplicationCache* appcache = V8Proxy::ToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, info.Holder()); + EventListener* listener = appcache->getAttributeEventListener(toEventType(name)); + return eventListenerToV8Object(listener); +} + +// Handles appcache.onfooevent attribute setting +ACCESSOR_SETTER(DOMApplicationCacheEventHandler) +{ + INC_STATS("DOMApplicationCache.onevent_setter"); + DOMApplicationCache* appcache = V8Proxy::ToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, info.Holder()); + String eventType = toEventType(name); + + if (EventListener* oldListener = appcache->getAttributeEventListener(eventType)) { + v8::Local<v8::Object> object = eventListenerToV8Object(oldListener); + removeHiddenDependency(info.Holder(), object, V8Custom::kDOMApplicationCacheCacheIndex); + appcache->clearAttributeEventListener(eventType); + } + + if (value->IsFunction()) { + RefPtr<EventListener> newListener = argumentToEventListener(appcache, value, kFindOrCreate); + if (newListener) { + createHiddenDependency(info.Holder(), value, V8Custom::kDOMApplicationCacheCacheIndex); + appcache->setAttributeEventListener(eventType, newListener); + } + } +} + +// Handles appcache.addEventListner(name, func, capture) method calls +CALLBACK_FUNC_DECL(DOMApplicationCacheAddEventListener) +{ + INC_STATS("DOMApplicationCache.addEventListener()"); + DOMApplicationCache* appcache = V8Proxy::ToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, args.Holder()); + + RefPtr<EventListener> listener = argumentToEventListener(appcache, args[1], kFindOrCreate); + if (listener) { + createHiddenDependency(args.Holder(), args[1], V8Custom::kDOMApplicationCacheCacheIndex); + String eventType = toWebCoreString(args[0]); + bool useCapture = args[2]->BooleanValue(); + appcache->addEventListener(eventType, listener, useCapture); + } + return v8::Undefined(); +} + +// Handles appcache.removeEventListner(name, func, capture) method calls +CALLBACK_FUNC_DECL(DOMApplicationCacheRemoveEventListener) +{ + INC_STATS("DOMApplicationCache.removeEventListener()"); + DOMApplicationCache* appcache = V8Proxy::ToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, args.Holder()); + + RefPtr<EventListener> listener = argumentToEventListener(appcache, args[1], kFindOnly); + if (listener) { + removeHiddenDependency(args.Holder(), args[1], V8Custom::kDOMApplicationCacheCacheIndex); + String eventType = toWebCoreString(args[0]); + bool useCapture = args[2]->BooleanValue(); + appcache->removeEventListener(eventType, listener.get(), useCapture); + } + return v8::Undefined(); +} + +} // namespace WebCore + +#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) diff --git a/WebCore/loader/appcache/DOMApplicationCache.cpp b/WebCore/loader/appcache/DOMApplicationCache.cpp index 90d2930..12d86a7 100644 --- a/WebCore/loader/appcache/DOMApplicationCache.cpp +++ b/WebCore/loader/appcache/DOMApplicationCache.cpp @@ -298,6 +298,51 @@ void DOMApplicationCache::callObsoleteListener() callListener(eventNames().obsoleteEvent, m_onObsoleteListener.get()); } +#if USE(V8) +RefPtr<EventListener>* DOMApplicationCache::getAttributeEventListenerStorage(const AtomicString& eventType) +{ + if (eventType == eventNames().checkingEvent) + return &m_onCheckingListener; + else if (eventType == eventNames().errorEvent) + return &m_onErrorListener; + else if (eventType == eventNames().noupdateEvent) + return &m_onNoUpdateListener; + else if (eventType == eventNames().downloadingEvent) + return &m_onDownloadingListener; + else if (eventType == eventNames().progressEvent) + return &m_onProgressListener; + else if (eventType == eventNames().updatereadyEvent) + return &m_onUpdateReadyListener; + else if (eventType == eventNames().cachedEvent) + return &m_onCachedListener; + else if (eventType == eventNames().obsoleteEvent) + return &m_onObsoleteListener; + else + return 0; +} + +EventListener* DOMApplicationCache::getAttributeEventListener(const AtomicString& eventType) +{ + RefPtr<EventListener>* storage = getAttributeEventListenerStorage(eventType); + ASSERT(storage); + return (*storage).get(); +} + +void DOMApplicationCache::setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener) +{ + RefPtr<EventListener>* storage = getAttributeEventListenerStorage(eventType); + ASSERT(storage); + (*storage) = listener; +} + +void DOMApplicationCache::clearAttributeEventListener(const AtomicString& eventType) +{ + RefPtr<EventListener>* storage = getAttributeEventListenerStorage(eventType); + ASSERT(storage); + (*storage) = 0; +} +#endif + } // namespace WebCore #endif // ENABLE(OFFLINE_WEB_APPLICATIONS) diff --git a/WebCore/loader/appcache/DOMApplicationCache.h b/WebCore/loader/appcache/DOMApplicationCache.h index b76542d..57b37bc 100644 --- a/WebCore/loader/appcache/DOMApplicationCache.h +++ b/WebCore/loader/appcache/DOMApplicationCache.h @@ -115,6 +115,12 @@ public: void callUpdateReadyListener(); void callCachedListener(); void callObsoleteListener(); + +#if USE(V8) + EventListener* getAttributeEventListener(const AtomicString& eventType); + void setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener); + void clearAttributeEventListener(const AtomicString& eventType); +#endif private: DOMApplicationCache(Frame*); @@ -125,6 +131,10 @@ private: ApplicationCache* associatedCache() const; bool swapCache(); + +#if USE(V8) + RefPtr<EventListener>* getAttributeEventListenerStorage(const AtomicString& eventType); +#endif RefPtr<EventListener> m_onCheckingListener; RefPtr<EventListener> m_onErrorListener; |