diff options
author | mbelshe@google.com <mbelshe@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-26 21:32:08 +0000 |
---|---|---|
committer | mbelshe@google.com <mbelshe@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-26 21:32:08 +0000 |
commit | 25a873babf94d9e1647a9722d313b4e52286220d (patch) | |
tree | ca3d81c12b6b9e3a4e9ffbb676e5299c7db6ca5c | |
parent | f3cabe366bd51e6d82381e130125d1bbf9f6e9ae (diff) | |
download | chromium_src-25a873babf94d9e1647a9722d313b4e52286220d.zip chromium_src-25a873babf94d9e1647a9722d313b4e52286220d.tar.gz chromium_src-25a873babf94d9e1647a9722d313b4e52286220d.tar.bz2 |
Add a new interface to JS for access to a microsecond timer (Interval).
Reorganize the extensions in v8 (currently there was only one for GC debugging).
Review URL: http://codereview.chromium.org/18731
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8662 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | webkit/build/V8Bindings/V8Bindings.vcproj | 28 | ||||
-rw-r--r-- | webkit/port/bindings/v8/extensions/GCController.cpp | 24 | ||||
-rw-r--r-- | webkit/port/bindings/v8/extensions/GCController.h | 22 | ||||
-rw-r--r-- | webkit/port/bindings/v8/extensions/Interval.cpp | 51 | ||||
-rw-r--r-- | webkit/port/bindings/v8/extensions/Interval.h | 22 | ||||
-rw-r--r-- | webkit/port/bindings/v8/extensions/Playback.cpp | 29 | ||||
-rw-r--r-- | webkit/port/bindings/v8/extensions/Playback.h | 33 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_proxy.cpp | 67 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_proxy.h | 8 |
9 files changed, 247 insertions, 37 deletions
diff --git a/webkit/build/V8Bindings/V8Bindings.vcproj b/webkit/build/V8Bindings/V8Bindings.vcproj index 4e8da10..726a348 100644 --- a/webkit/build/V8Bindings/V8Bindings.vcproj +++ b/webkit/build/V8Bindings/V8Bindings.vcproj @@ -2456,6 +2456,34 @@ > </File> </Filter> + <Filter + Name="extensions" + > + <File + RelativePath="..\..\port\bindings\v8\extensions\GCController.cpp" + > + </File> + <File + RelativePath="..\..\port\bindings\v8\extensions\GCController.h" + > + </File> + <File + RelativePath="..\..\port\bindings\v8\extensions\Interval.cpp" + > + </File> + <File + RelativePath="..\..\port\bindings\v8\extensions\Interval.h" + > + </File> + <File + RelativePath="..\..\port\bindings\v8\extensions\Playback.cpp" + > + </File> + <File + RelativePath="..\..\port\bindings\v8\extensions\Playback.h" + > + </File> + </Filter> <File RelativePath="..\..\port\bindings\v8\dom_wrapper_map.h" > diff --git a/webkit/port/bindings/v8/extensions/GCController.cpp b/webkit/port/bindings/v8/extensions/GCController.cpp new file mode 100644 index 0000000..1b514f5 --- /dev/null +++ b/webkit/port/bindings/v8/extensions/GCController.cpp @@ -0,0 +1,24 @@ +// 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. + +#include "GCController.h" + +namespace WebCore { + +const char* kGCExtensionName = "v8/GCController"; + +v8::Extension* GCExtension::Get() { + v8::Extension* extension = new v8::Extension( + kGCExtensionName, + "(function () {" + " var v8_gc;" + " if (gc) v8_gc = gc;" + " GCController = new Object();" + " GCController.collect =" + " function() {if (v8_gc) v8_gc(); };" + " })()"); + return extension; +} + +} diff --git a/webkit/port/bindings/v8/extensions/GCController.h b/webkit/port/bindings/v8/extensions/GCController.h new file mode 100644 index 0000000..d0a1b3d --- /dev/null +++ b/webkit/port/bindings/v8/extensions/GCController.h @@ -0,0 +1,22 @@ +// 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. + +// The GCExtension is a v8 extension to expose a method into JS for triggering +// garbage collection. This should only be used for debugging. + +#ifndef GC_EXTENSION_H__ +#define GC_EXTENSION_H__ + +#include "v8.h" + +namespace WebCore { + +class GCExtension { + public: + static v8::Extension* Get(); +}; + +} + +#endif // GC_EXTENSION_H__ diff --git a/webkit/port/bindings/v8/extensions/Interval.cpp b/webkit/port/bindings/v8/extensions/Interval.cpp new file mode 100644 index 0000000..a0c88e3 --- /dev/null +++ b/webkit/port/bindings/v8/extensions/Interval.cpp @@ -0,0 +1,51 @@ +// 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. + +#include "Interval.h" +#include "WTF/CurrentTime.h" + +namespace WebCore { + +const char* kIntervalExtensionName = "v8/Interval"; + +class IntervalExtensionWrapper : public v8::Extension { +public: + IntervalExtensionWrapper() : + v8::Extension(kIntervalExtensionName, + "native function HiResTime();" + "function Interval() {" + " var start_ = 0;" + " var stop_ = 0;" + " this.start = function() {" + " start_ = HiResTime();" + " };" + " this.stop = function() {" + " stop_ = HiResTime();" + " if (start_ == 0)" + " stop_ = 0;" + " };" + " this.microseconds = function() {" + " if (stop_ == 0)" + " stop();" + " return Math.ceil((stop_ - start_) * 1000000);" + " };" + "}") {}; + + virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(v8::Handle<v8::String> name) { + if (name->Equals(v8::String::New("HiResTime"))) + return v8::FunctionTemplate::New(HiResTime); + return v8::Handle<v8::FunctionTemplate>(); + } + + static v8::Handle<v8::Value> HiResTime(const v8::Arguments& args) { + return v8::Number::New(WTF::currentTime()); + } +}; + +v8::Extension* IntervalExtension::Get() { + return new IntervalExtensionWrapper(); +} + +} + diff --git a/webkit/port/bindings/v8/extensions/Interval.h b/webkit/port/bindings/v8/extensions/Interval.h new file mode 100644 index 0000000..60144d6 --- /dev/null +++ b/webkit/port/bindings/v8/extensions/Interval.h @@ -0,0 +1,22 @@ +// 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. + +// The IntervalExtension is a v8 extension to implement a simple interval +// class for measuring microsecond intervals. + +#ifndef INTERVAL_EXTENSION_H__ +#define INTERVAL_EXTENSION_H__ + +#include "v8.h" + +namespace WebCore { + +class IntervalExtension { + public: + static v8::Extension* Get(); +}; + +} + +#endif // INTERVAL_EXTENSION_H__
\ No newline at end of file diff --git a/webkit/port/bindings/v8/extensions/Playback.cpp b/webkit/port/bindings/v8/extensions/Playback.cpp new file mode 100644 index 0000000..b585ccf --- /dev/null +++ b/webkit/port/bindings/v8/extensions/Playback.cpp @@ -0,0 +1,29 @@ +// 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. + +#include "Playback.h" + +namespace WebCore { + +const char* kPlaybackExtensionName = "v8/PlaybackMode"; + +v8::Extension* PlaybackExtension::Get() { + v8::Extension* extension = new v8::Extension( + kPlaybackExtensionName, + "(function () {" + " var orig_date = Date;" + " Math.random = function() {" + " return 0.5;" + " };" + " Date.__proto__.now = function() {" + " return new orig_date(1204251968254);" + " };" + " Date = function() {" + " return Date.now();" + " };" + "})()"); + return extension; +} + +} diff --git a/webkit/port/bindings/v8/extensions/Playback.h b/webkit/port/bindings/v8/extensions/Playback.h new file mode 100644 index 0000000..f83af0d --- /dev/null +++ b/webkit/port/bindings/v8/extensions/Playback.h @@ -0,0 +1,33 @@ +// 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. + +// The IntervalExtension is a v8 extension to implement a simple interval +// class for measuring microsecond intervals. + +#ifndef PLAYBACK_EXTENSION_H__ +#define PLAYBACK_EXTENSION_H__ + +#include "v8.h" + +namespace WebCore { + +// 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 +// based apps use randomness in URLs to unique-ify urls for proxies. +// Unfortunately, this breaks playback. +// To work around this, we take the two most common client-side randomness +// generators and make them constant. They really need to be constant +// (rather than a constant seed followed by constant change) +// because the playback mode wants flexibility in how it plays them back +// and cannot always guarantee that requests for randomness are played back +// in exactly the same order in which they were recorded. +class PlaybackExtension { + public: + static v8::Extension* Get(); +}; + +} + +#endif // PLAYBACK_EXTENSION_H__ diff --git a/webkit/port/bindings/v8/v8_proxy.cpp b/webkit/port/bindings/v8/v8_proxy.cpp index 913bad2..1344543 100644 --- a/webkit/port/bindings/v8/v8_proxy.cpp +++ b/webkit/port/bindings/v8/v8_proxy.cpp @@ -201,6 +201,11 @@ #include "XPathEvaluator.h" #endif +#include "extensions/GCController.h" +#include "extensions/Interval.h" +#include "extensions/Playback.h" + + namespace WebCore { @@ -234,6 +239,9 @@ namespace WebCore { // Static utility context. v8::Persistent<v8::Context> V8Proxy::m_utilityContext; +// Static list of registered extensions +V8ExtensionList V8Proxy::m_extensions; + // A helper class for undetectable document.all class UndetectableHTMLCollection : public HTMLCollection { @@ -2274,6 +2282,13 @@ void V8Proxy::InitContextIfNeeded() v8::V8::SetFailedAccessCheckCallbackFunction(ReportUnsafeJavaScriptAccess); + // Register known extensions + RegisterExtension(IntervalExtension::Get()); + if (ScriptController::shouldExposeGCController()) + RegisterExtension(GCExtension::Get()); + if (ScriptController::RecordPlaybackMode()) + RegisterExtension(PlaybackExtension::Get()); + v8_initialized = true; } @@ -2290,22 +2305,18 @@ void V8Proxy::InitContextIfNeeded() V8Custom::v8DOMWindowIndexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW)); - if (ScriptController::shouldExposeGCController()) { - v8::RegisterExtension(new v8::Extension("v8/GCController", - "(function v8_GCController() {" - " var v8_gc;" - " if (gc) v8_gc = gc;" - " GCController = new Object();" - " GCController.collect =" - " function() {if (v8_gc) v8_gc(); };" - " })()")); - const char* extension_names[] = { "v8/GCController" }; - v8::ExtensionConfiguration extensions(1, extension_names); - // Create a new context. - m_context = v8::Context::New(&extensions, global_template, m_global); - } else { - m_context = v8::Context::New(NULL, global_template, m_global); + // Dynamically tell v8 about our extensions now. + const char** extension_names = new const char*[m_extensions.size()]; + int index = 0; + V8ExtensionList::iterator it = m_extensions.begin(); + while (it != m_extensions.end()) { + extension_names[index++] = (*it)->name(); + ++it; } + v8::ExtensionConfiguration extensions(m_extensions.size(), extension_names); + m_context = v8::Context::New(&extensions, global_template, m_global); + delete extension_names; + extension_names = 0; if (m_context.IsEmpty()) return; @@ -2386,27 +2397,6 @@ void V8Proxy::InitContextIfNeeded() SetSecurityToken(); m_frame->loader()->dispatchWindowObjectAvailable(); - - 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 - // based apps use randomness in URLs to unique-ify urls for proxies. - // Unfortunately, this breaks playback. - // To work around this, we take the two most common client-side randomness - // generators and make them constant. They really need to be constant - // (rather than a constant seed followed by constant change) - // because the playback mode wants flexibility in how it plays them back - // and cannot always guarantee that requests for randomness are played back - // in exactly the same order in which they were recorded. - String script( - "Math.random = function() { return 0.5; };" - "__ORIGDATE__ = Date;" - "Date.__proto__.now = function() { " - " return new __ORIGDATE__(1204251968254); };" - "Date = function() { return Date.now(); };"); - this->Evaluate(String(), 0, script, 0); - } } @@ -3488,4 +3478,9 @@ String V8Proxy::GetSourceName() { return ToWebCoreString(v8::Debug::Call(frame_source_name)); } +void V8Proxy::RegisterExtension(v8::Extension* extension) { + v8::RegisterExtension(extension); + m_extensions.push_back(extension); +} + } // namespace WebCore diff --git a/webkit/port/bindings/v8/v8_proxy.h b/webkit/port/bindings/v8/v8_proxy.h index c38cae6..31bdc40 100644 --- a/webkit/port/bindings/v8/v8_proxy.h +++ b/webkit/port/bindings/v8/v8_proxy.h @@ -14,7 +14,6 @@ #include "NodeFilter.h" #include "SecurityOrigin.h" // for WebCore::SecurityOrigin #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> @@ -73,6 +72,7 @@ class SVGElementInstance; class V8EventListener; class V8ObjectEventListener; typedef std::list<V8EventListener*> V8EventListenerList; +typedef std::list<v8::Extension*> V8ExtensionList; // TODO(fqian): use standard logging facilities in WebCore. void log_info(Frame* frame, const String& msg, const String& url); @@ -431,6 +431,9 @@ class V8Proxy { static String GetSourceName(); private: + // Register extensions before initializing the context. Once the context + // is initialized, extensions cannot be registered. + static void RegisterExtension(v8::Extension* extension); void InitContextIfNeeded(); void DisconnectEventListeners(); void SetSecurityToken(); @@ -564,6 +567,9 @@ class V8Proxy { // engine allows much more recursion than KJS does so we need to guard against // excessive recursion in the binding layer. int m_recursion; + + // List of extensions registered with the context. + static V8ExtensionList m_extensions; }; template <int tag, typename T> |