summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormbelshe@google.com <mbelshe@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-26 21:32:08 +0000
committermbelshe@google.com <mbelshe@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-26 21:32:08 +0000
commit25a873babf94d9e1647a9722d313b4e52286220d (patch)
treeca3d81c12b6b9e3a4e9ffbb676e5299c7db6ca5c
parentf3cabe366bd51e6d82381e130125d1bbf9f6e9ae (diff)
downloadchromium_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.vcproj28
-rw-r--r--webkit/port/bindings/v8/extensions/GCController.cpp24
-rw-r--r--webkit/port/bindings/v8/extensions/GCController.h22
-rw-r--r--webkit/port/bindings/v8/extensions/Interval.cpp51
-rw-r--r--webkit/port/bindings/v8/extensions/Interval.h22
-rw-r--r--webkit/port/bindings/v8/extensions/Playback.cpp29
-rw-r--r--webkit/port/bindings/v8/extensions/Playback.h33
-rw-r--r--webkit/port/bindings/v8/v8_proxy.cpp67
-rw-r--r--webkit/port/bindings/v8/v8_proxy.h8
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>