summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DEPS2
-rw-r--r--webkit/port/bindings/scripts/CodeGeneratorV8.pm6
-rw-r--r--webkit/port/bindings/v8/ScriptController.cpp6
-rw-r--r--webkit/port/bindings/v8/ScriptController.h1
-rw-r--r--webkit/port/bindings/v8/v8_collection.h14
-rw-r--r--webkit/port/bindings/v8/v8_custom.cpp78
-rw-r--r--webkit/port/bindings/v8/v8_index.h4
-rw-r--r--webkit/port/bindings/v8/v8_proxy.cpp474
-rw-r--r--webkit/port/bindings/v8/v8_proxy.h31
9 files changed, 353 insertions, 263 deletions
diff --git a/DEPS b/DEPS
index a92f067..126e1f4 100644
--- a/DEPS
+++ b/DEPS
@@ -27,7 +27,7 @@ deps = {
"/trunk/deps/third_party/svn@3230",
"src/v8":
- "http://v8.googlecode.com/svn/branches/bleeding_edge@539",
+ "http://v8.googlecode.com/svn/branches/bleeding_edge@557",
"src/webkit/data/layout_tests/LayoutTests":
"http://svn.webkit.org/repository/webkit/trunk/LayoutTests@36102",
diff --git a/webkit/port/bindings/scripts/CodeGeneratorV8.pm b/webkit/port/bindings/scripts/CodeGeneratorV8.pm
index 2121862..99e447c 100644
--- a/webkit/port/bindings/scripts/CodeGeneratorV8.pm
+++ b/webkit/port/bindings/scripts/CodeGeneratorV8.pm
@@ -374,7 +374,7 @@ END
HolderToNative($dataNode, $implClassName, $classIndex);
push(@implContentDecls, <<END);
- if (!V8Proxy::IsFromSameOrigin(imp->frame(), false)) {
+ if (!V8Proxy::CanAccessFrame(imp->frame(), false)) {
static v8::Persistent<v8::FunctionTemplate> shared_template =
v8::Persistent<v8::FunctionTemplate>::New($newTemplateString);
return shared_template->GetFunction();
@@ -765,7 +765,7 @@ END
&& !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
# We have not find real use cases yet.
push(@implContentDecls,
-" if (!V8Proxy::IsFromSameOrigin(imp->frame(), true)) {\n".
+" if (!V8Proxy::CanAccessFrame(imp->frame(), true)) {\n".
" return v8::Undefined();\n" .
" }\n");
}
@@ -1056,7 +1056,7 @@ END
my $access_check = "/* no access check */";
if ($dataNode->extendedAttributes->{"CheckDomainSecurity"}) {
- $access_check = "instance->SetAccessCheckCallbacks(V8Custom::v8${interfaceName}NamedSecurityCheck, V8Custom::v8${interfaceName}IndexedSecurityCheck, v8::External::New((void*)V8ClassIndex::${classIndex}));";
+ $access_check = "instance->SetAccessCheckCallbacks(V8Custom::v8${interfaceName}NamedSecurityCheck, V8Custom::v8${interfaceName}IndexedSecurityCheck, v8::Integer::New(V8ClassIndex::ToInt(V8ClassIndex::${classIndex})));";
}
# Generate the template configuration method
diff --git a/webkit/port/bindings/v8/ScriptController.cpp b/webkit/port/bindings/v8/ScriptController.cpp
index 6dfde2a..b0e356a 100644
--- a/webkit/port/bindings/v8/ScriptController.cpp
+++ b/webkit/port/bindings/v8/ScriptController.cpp
@@ -96,7 +96,7 @@ Frame* ScriptController::retrieveActiveFrame()
bool ScriptController::isSafeScript(Frame* target)
{
- return V8Proxy::IsFromSameOrigin(target, true);
+ return V8Proxy::CanAccessFrame(target, true);
}
void ScriptController::gcProtectJSWrapper(void* dom_object)
@@ -512,9 +512,7 @@ NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement
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();
+ m_proxy->clearForNavigation();
}
void ScriptController::attachDebugger(void*)
diff --git a/webkit/port/bindings/v8/ScriptController.h b/webkit/port/bindings/v8/ScriptController.h
index 19eb533..aa4a46b 100644
--- a/webkit/port/bindings/v8/ScriptController.h
+++ b/webkit/port/bindings/v8/ScriptController.h
@@ -231,6 +231,7 @@ public:
void clearWindowShell();
void updateDocument();
+ void notifyDOMWindowReady() { m_proxy->domWindowReady(); }
void pauseTimeouts(OwnPtr<PausedTimeouts>&);
void resumeTimeouts(OwnPtr<PausedTimeouts>&);
diff --git a/webkit/port/bindings/v8/v8_collection.h b/webkit/port/bindings/v8/v8_collection.h
index ef0b3c5..86718c7 100644
--- a/webkit/port/bindings/v8/v8_collection.h
+++ b/webkit/port/bindings/v8/v8_collection.h
@@ -12,10 +12,11 @@
namespace WebCore {
static v8::Handle<v8::Value> GetV8Object(
- void * result,
+ void* result,
v8::Local<v8::Value> data) {
if (!result) return v8::Handle<v8::Value>();
- V8ClassIndex::V8WrapperType type = V8ClassIndex::ToWrapperType(data);
+ V8ClassIndex::V8WrapperType type =
+ V8ClassIndex::FromInt(data->Int32Value());
if (type == V8ClassIndex::NODE)
return V8Proxy::NodeToV8Object(static_cast<Node*>(result));
else
@@ -161,7 +162,7 @@ static void SetCollectionIndexedGetter(v8::Handle<v8::FunctionTemplate> desc,
0,
0,
CollectionIndexedPropertyEnumerator<T>,
- v8::External::New(reinterpret_cast<void*>(type)));
+ v8::Integer::New(V8ClassIndex::ToInt(type)));
}
@@ -175,7 +176,7 @@ static void SetCollectionNamedGetter(v8::Handle<v8::FunctionTemplate> desc,
0,
0,
0,
- v8::External::New(reinterpret_cast<void*>(type)));
+ v8::Integer::New(V8ClassIndex::ToInt(type)));
}
@@ -192,14 +193,14 @@ static void SetCollectionIndexedAndNamedGetters(
0,
0,
0,
- v8::External::New(reinterpret_cast<void*>(type)));
+ v8::Integer::New(V8ClassIndex::ToInt(type)));
desc->InstanceTemplate()->SetIndexedPropertyHandler(
CollectionIndexedPropertyGetter<T, D>,
0,
0,
0,
CollectionIndexedPropertyEnumerator<T>,
- v8::External::New(reinterpret_cast<void*>(type)));
+ v8::Integer::New(V8ClassIndex::ToInt(type)));
}
@@ -220,4 +221,3 @@ static void SetCollectionStringOrNullIndexedGetter(
} // namespace WebCore
#endif // V8_PROPERTY_H__
-
diff --git a/webkit/port/bindings/v8/v8_custom.cpp b/webkit/port/bindings/v8/v8_custom.cpp
index 0904839..827323a 100644
--- a/webkit/port/bindings/v8/v8_custom.cpp
+++ b/webkit/port/bindings/v8/v8_custom.cpp
@@ -514,7 +514,7 @@ ACCESSOR_SETTER(DOMWindowOpener) {
DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(
V8ClassIndex::DOMWINDOW, info.Holder());
- if (!V8Proxy::IsFromSameOrigin(imp->frame(), true))
+ if (!V8Proxy::CanAccessFrame(imp->frame(), true))
return;
// Opener can be shadowed if it is in the same domain.
@@ -787,11 +787,8 @@ CALLBACK_FUNC_DECL(DOMWindowAddEventListener) {
DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(
V8ClassIndex::DOMWINDOW, args.Holder());
- // Fast check This argument with the global object of security context.
- if ((args.This() != v8::Context::GetCurrentSecurityContext()->Global()) &&
- !V8Proxy::IsFromSameOrigin(imp->frame(), true)) {
+ if (!V8Proxy::CanAccessFrame(imp->frame(), true))
return v8::Undefined();
- }
if (!imp->frame())
return v8::Undefined(); // DOMWindow could be disconnected from the frame
@@ -823,11 +820,8 @@ CALLBACK_FUNC_DECL(DOMWindowRemoveEventListener) {
DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(
V8ClassIndex::DOMWINDOW, args.Holder());
- // Fast check This argument with the global object of security context.
- if ((args.This() != v8::Context::GetCurrentSecurityContext()->Global()) &&
- !V8Proxy::IsFromSameOrigin(imp->frame(), true)) {
+ if (!V8Proxy::CanAccessFrame(imp->frame(), true))
return v8::Undefined();
- }
if (!imp->frame())
return v8::Undefined();
@@ -1089,14 +1083,9 @@ CALLBACK_FUNC_DECL(DOMWindowOpen) {
DOMWindow* parent = V8Proxy::ToNativeObject<DOMWindow>(
V8ClassIndex::DOMWINDOW, args.Holder());
Frame* frame = parent->frame();
- if (!frame)
- return v8::Undefined();
- // Fast check This argument with the global object of security context.
- if ((args.This() != v8::Context::GetCurrentSecurityContext()->Global()) &&
- !V8Proxy::IsFromSameOrigin(frame, true)) {
+ if (!V8Proxy::CanAccessFrame(frame, true))
return v8::Undefined();
- }
Frame* active_frame = V8Proxy::retrieveActiveFrame();
if (!active_frame)
@@ -2711,11 +2700,8 @@ v8::Handle<v8::Value> V8Custom::WindowSetTimeoutImpl(const v8::Arguments& args,
DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(
V8ClassIndex::DOMWINDOW, args.Holder());
- // Fast check This argument with the global object of security context.
- if ((args.This() != v8::Context::GetCurrentSecurityContext()->Global()) &&
- !V8Proxy::IsFromSameOrigin(imp->frame(), true)) {
+ if (!V8Proxy::CanAccessFrame(imp->frame(), true))
return v8::Undefined();
- }
v8::Handle<v8::Value> function = args[0];
@@ -3046,11 +3032,8 @@ CALLBACK_FUNC_DECL(DOMWindowAtob) {
DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(
V8ClassIndex::DOMWINDOW, args.Holder());
- // Fast check This argument with the global object of security context.
- if ((args.This() != v8::Context::GetCurrentSecurityContext()->Global()) &&
- !V8Proxy::IsFromSameOrigin(imp->frame(), true)) {
+ if (!V8Proxy::CanAccessFrame(imp->frame(), true))
return v8::Undefined();
- }
if (args.Length() < 1) {
V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments");
@@ -3068,11 +3051,8 @@ CALLBACK_FUNC_DECL(DOMWindowBtoa) {
DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(
V8ClassIndex::DOMWINDOW, args.Holder());
- // Fast check This argument with the global object of security context.
- if ((args.This() != v8::Context::GetCurrentSecurityContext()->Global()) &&
- !V8Proxy::IsFromSameOrigin(imp->frame(), true)) {
+ if (!V8Proxy::CanAccessFrame(imp->frame(), true))
return v8::Undefined();
- }
if (args.Length() < 1) {
V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments");
@@ -3534,8 +3514,12 @@ CALLBACK_FUNC_DECL(SVGMatrixRotateFromVector) {
// --------------- Security Checks -------------------------
NAMED_ACCESS_CHECK(DOMWindow) {
- ASSERT(V8ClassIndex::ToWrapperType(data) == V8ClassIndex::DOMWINDOW);
- v8::Handle<v8::Value> window = host->GetPrototype();
+ ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW);
+ v8::Handle<v8::Value> window =
+ V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, host);
+ if (window.IsEmpty())
+ return false; // the frame is gone.
+
DOMWindow* target_win =
V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window);
@@ -3555,13 +3539,17 @@ NAMED_ACCESS_CHECK(DOMWindow) {
}
}
- return V8Proxy::CanAccess(target);
+ return V8Proxy::CanAccessFrame(target, false);
}
INDEXED_ACCESS_CHECK(DOMWindow) {
- ASSERT(V8ClassIndex::ToWrapperType(data) == V8ClassIndex::DOMWINDOW);
- v8::Handle<v8::Value> window = host->GetPrototype();
+ ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW);
+ v8::Handle<v8::Value> window =
+ V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, host);
+ if (window.IsEmpty())
+ return false;
+
DOMWindow* target_win =
V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window);
@@ -3577,43 +3565,43 @@ INDEXED_ACCESS_CHECK(DOMWindow) {
return true;
}
- return V8Proxy::CanAccess(target);
+ return V8Proxy::CanAccessFrame(target, false);
}
INDEXED_ACCESS_CHECK(History) {
- ASSERT(V8ClassIndex::ToWrapperType(data) == V8ClassIndex::HISTORY);
+ ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::HISTORY);
// Only allow same origin access
History* imp =
V8Proxy::ToNativeObject<History>(V8ClassIndex::HISTORY, host);
- return V8Proxy::IsFromSameOrigin(imp->frame(), false);
+ return V8Proxy::CanAccessFrame(imp->frame(), false);
}
NAMED_ACCESS_CHECK(History) {
- ASSERT(V8ClassIndex::ToWrapperType(data) == V8ClassIndex::HISTORY);
+ ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::HISTORY);
// Only allow same origin access
History* imp =
V8Proxy::ToNativeObject<History>(V8ClassIndex::HISTORY, host);
- return V8Proxy::IsFromSameOrigin(imp->frame(), false);
+ return V8Proxy::CanAccessFrame(imp->frame(), false);
}
INDEXED_ACCESS_CHECK(Location) {
- ASSERT(V8ClassIndex::ToWrapperType(data) == V8ClassIndex::LOCATION);
+ ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::LOCATION);
// Only allow same origin access
Location* imp =
V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, host);
- return V8Proxy::IsFromSameOrigin(imp->frame(), false);
+ return V8Proxy::CanAccessFrame(imp->frame(), false);
}
NAMED_ACCESS_CHECK(Location) {
- ASSERT(V8ClassIndex::ToWrapperType(data) == V8ClassIndex::LOCATION);
+ ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::LOCATION);
// Only allow same origin access
Location* imp =
V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, host);
- return V8Proxy::IsFromSameOrigin(imp->frame(), false);
+ return V8Proxy::CanAccessFrame(imp->frame(), false);
}
@@ -3629,9 +3617,13 @@ NAMED_ACCESS_CHECK(Location) {
Frame* V8Custom::GetTargetFrame(v8::Local<v8::Object> host,
v8::Local<v8::Value> data) {
Frame* target = 0;
- switch (V8ClassIndex::ToWrapperType(data)) {
+ switch (V8ClassIndex::FromInt(data->Int32Value())) {
case V8ClassIndex::DOMWINDOW: {
- v8::Handle<v8::Value> window = host->GetPrototype();
+ v8::Handle<v8::Value> window =
+ V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, host);
+ if (window.IsEmpty())
+ return target;
+
DOMWindow* target_win =
V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window);
target = target_win->frame();
diff --git a/webkit/port/bindings/v8/v8_index.h b/webkit/port/bindings/v8/v8_index.h
index 28c59d8..109f702 100644
--- a/webkit/port/bindings/v8/v8_index.h
+++ b/webkit/port/bindings/v8/v8_index.h
@@ -393,10 +393,6 @@ ALL_WRAPPER_TYPES(DEFINE_ENUM)
#undef DEFINE_ENUM
CLASSINDEX_END,
};
- static inline V8WrapperType ToWrapperType(v8::Handle<v8::Value> obj) {
- return static_cast<V8WrapperType>(
- reinterpret_cast<int>(v8::Handle<v8::External>::Cast(obj)->Value()));
- }
static int ToInt(V8WrapperType type) { return static_cast<int>(type); }
diff --git a/webkit/port/bindings/v8/v8_proxy.cpp b/webkit/port/bindings/v8/v8_proxy.cpp
index 81df91f..fe67a22 100644
--- a/webkit/port/bindings/v8/v8_proxy.cpp
+++ b/webkit/port/bindings/v8/v8_proxy.cpp
@@ -114,6 +114,7 @@
namespace WebCore {
+
// DOM binding algorithm:
//
// There are two kinds of DOM objects:
@@ -179,7 +180,8 @@ static inline void USE_VAR(T) { }
// The function is the place to set the break point to inspect
// live global handles. Leaks are often come from leaked global handles.
-static void EnumerateGlobalHandles() {
+static void EnumerateGlobalHandles()
+{
for (GlobalHandleMap::iterator it = global_handle_map().begin(),
end = global_handle_map().end(); it != end; ++it) {
GlobalHandleInfo* info = it->second;
@@ -190,7 +192,8 @@ static void EnumerateGlobalHandles() {
}
void V8Proxy::RegisterGlobalHandle(GlobalHandleType type, void* host,
- v8::Persistent<v8::Value> handle) {
+ v8::Persistent<v8::Value> handle)
+{
ASSERT(!global_handle_map().contains(*handle));
global_handle_map().set(*handle, new GlobalHandleInfo(host, type));
}
@@ -208,7 +211,8 @@ void V8Proxy::UnregisterGlobalHandle(void* host, v8::Persistent<v8::Value> handl
void BatchConfigureAttributes(v8::Handle<v8::ObjectTemplate> inst,
v8::Handle<v8::ObjectTemplate> proto,
const BatchedAttribute* attrs,
- size_t num_attrs) {
+ size_t num_attrs)
+{
for (size_t i = 0; i < num_attrs; ++i) {
const BatchedAttribute* a = &attrs[i];
(a->on_proto ? proto : inst)->SetAccessor(
@@ -226,7 +230,8 @@ void BatchConfigureAttributes(v8::Handle<v8::ObjectTemplate> inst,
void BatchConfigureConstants(v8::Handle<v8::FunctionTemplate> desc,
v8::Handle<v8::ObjectTemplate> proto,
const BatchedConstant* consts,
- size_t num_consts) {
+ size_t num_consts)
+{
for (size_t i = 0; i < num_consts; ++i) {
const BatchedConstant* c = &consts[i];
desc->Set(v8::String::New(c->name),
@@ -250,20 +255,23 @@ class DOMPeerableWrapperMap : public DOMWrapperMap<T> {
DOMWrapperMap<T>(callback) { }
// Get the JS wrapper object of an object.
- v8::Persistent<v8::Object> get(T* obj) {
+ v8::Persistent<v8::Object> get(T* obj)
+ {
v8::Object* peer = static_cast<v8::Object*>(obj->peer());
ASSERT(peer == this->map_.get(obj));
return peer ? v8::Persistent<v8::Object>(peer)
: v8::Persistent<v8::Object>();
}
- void set(T* obj, v8::Persistent<v8::Object> peer_handle) {
+ void set(T* obj, v8::Persistent<v8::Object> peer_handle)
+ {
ASSERT(obj->peer() == 0);
obj->setPeer(*peer_handle);
DOMWrapperMap<T>::set(obj, peer_handle);
}
- void forget(T* obj) {
+ void forget(T* obj)
+ {
v8::Object* peer = static_cast<v8::Object*>(obj->peer());
ASSERT(peer == this->map_.get(obj));
if (peer)
@@ -276,14 +284,16 @@ class DOMPeerableWrapperMap : public DOMWrapperMap<T> {
static void WeakPeerableCallback(v8::Persistent<v8::Object> obj, void* para);
static void WeakNodeCallback(v8::Persistent<v8::Object> obj, void* para);
// A map from DOM node to its JS wrapper.
-static DOMWrapperMap<Node>& dom_node_map() {
+static DOMWrapperMap<Node>& dom_node_map()
+{
static DOMPeerableWrapperMap<Node> static_dom_node_map(&WeakNodeCallback);
return static_dom_node_map;
}
// A map from a non-DOM node (peerable) to its JS wrapper.
-static DOMWrapperMap<Peerable>& dom_object_map() {
+static DOMWrapperMap<Peerable>& dom_object_map()
+{
static DOMPeerableWrapperMap<Peerable>
static_dom_object_map(&WeakPeerableCallback);
return static_dom_object_map;
@@ -294,14 +304,16 @@ static void WeakSVGElementInstanceCallback(v8::Persistent<v8::Object> obj,
void* param);
// A map for SVGElementInstances, which are not peerable
-static DOMWrapperMap<SVGElementInstance>& dom_svg_element_instance_map() {
+static DOMWrapperMap<SVGElementInstance>& dom_svg_element_instance_map()
+{
static DOMWrapperMap<SVGElementInstance>
static_dom_svg_element_instance_map(&WeakSVGElementInstanceCallback);
return static_dom_svg_element_instance_map;
}
static void WeakSVGElementInstanceCallback(v8::Persistent<v8::Object> obj,
- void* param) {
+ void* param)
+{
SVGElementInstance* instance = static_cast<SVGElementInstance*>(param);
ASSERT(dom_svg_element_instance_map().contains(instance));
@@ -310,7 +322,8 @@ static void WeakSVGElementInstanceCallback(v8::Persistent<v8::Object> obj,
}
v8::Handle<v8::Value> V8Proxy::SVGElementInstanceToV8Object(
- SVGElementInstance* instance) {
+ SVGElementInstance* instance)
+{
if (!instance)
return v8::Null();
@@ -377,7 +390,8 @@ v8::Handle<v8::Value> V8Proxy::SVGObjectWithContextToV8Object(
}
static void WeakSVGObjectWithContext(v8::Persistent<v8::Object> obj,
- void* param) {
+ void* param)
+{
Peerable* dom_obj = static_cast<Peerable*>(param);
ASSERT(dom_svg_object_with_context_map().contains(dom_obj));
@@ -419,7 +433,8 @@ SVGElement* V8Proxy::GetSVGContext(void* obj)
// Called when obj is near death (not reachable from JS roots)
// It is time to remove the entry from the table and dispose
// the handle.
-static void WeakPeerableCallback(v8::Persistent<v8::Object> obj, void* para) {
+static void WeakPeerableCallback(v8::Persistent<v8::Object> obj, void* para)
+{
Peerable* dom_obj = static_cast<Peerable*>(para);
ASSERT(dom_object_map().contains(dom_obj));
@@ -484,7 +499,8 @@ static void GCPrologue()
}
-static void GCEpilogue() {
+static void GCEpilogue()
+{
#ifndef NDEBUG
// Check all survivals are weak.
PeerableMap peer_map = dom_object_map().impl();
@@ -536,7 +552,8 @@ void V8Proxy::GCProtect(Peerable* dom_object)
// static
-void V8Proxy::GCUnprotect(Peerable* dom_object) {
+void V8Proxy::GCUnprotect(Peerable* dom_object)
+{
if (!dom_object)
return;
if (!gc_protected_map().contains(dom_object))
@@ -615,7 +632,8 @@ Vector<JavaScriptConsoleMessage>* ConsoleMessageManager::m_delayed = NULL;
void ConsoleMessageManager::AddMessage(
Page* page,
- const JavaScriptConsoleMessage& message) {
+ const JavaScriptConsoleMessage& message)
+{
// Process any delayed messages to make sure that messages
// appear in the right order in the console.
ProcessDelayedMessages();
@@ -636,32 +654,32 @@ void ConsoleMessageManager::AddDelayedMessage(const JavaScriptConsoleMessage& me
void ConsoleMessageManager::ProcessDelayedMessages()
{
- // If we have a delayed vector it cannot be empty.
- if (!m_delayed)
- return;
- ASSERT(!m_delayed->isEmpty());
-
- // Add the delayed messages to the page of the active
- // context. If that for some bizarre reason does not
- // exist, we clear the list of delayed messages to avoid
- // 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 we have a delayed vector it cannot be empty.
+ if (!m_delayed)
+ return;
+ ASSERT(!m_delayed->isEmpty());
+
+ // Add the delayed messages to the page of the active
+ // context. If that for some bizarre reason does not
+ // exist, we clear the list of delayed messages to avoid
+ // posting messages. We still deallocate the vector.
+ Frame* frame = V8Proxy::retrieveActiveFrame();
+ Page* page = NULL;
+ if (frame)
+ page = frame->page();
+ if (!page)
+ m_delayed->clear();
- // Iterate through all the delayed messages and add them
- // to the console.
- const int size = m_delayed->size();
- for (int i = 0; i < size; i++) {
- m_delayed->at(i).AddToPage(page);
- }
+ // Iterate through all the delayed messages and add them
+ // to the console.
+ const int size = m_delayed->size();
+ for (int i = 0; i < size; i++) {
+ m_delayed->at(i).AddToPage(page);
+ }
- // Deallocate the delayed vector.
- delete m_delayed;
- m_delayed = NULL;
+ // Deallocate the delayed vector.
+ delete m_delayed;
+ m_delayed = NULL;
}
@@ -683,7 +701,8 @@ void log_info(Frame* frame, const String& msg, const String& url)
}
static void HandleConsoleMessage(v8::Handle<v8::Message> message,
- v8::Handle<v8::Value> data) {
+ v8::Handle<v8::Value> data)
+{
// Use the frame where JavaScript is called from.
Frame* frame = V8Proxy::retrieveActiveFrame();
if (!frame)
@@ -714,21 +733,24 @@ enum DelayReporting {
};
-static void ReportUnsafeAccessTo(Frame* target, DelayReporting delay) {
+static void ReportUnsafeAccessTo(Frame* target, DelayReporting delay)
+{
ASSERT(target);
Document* targetDocument = target->document();
if (!targetDocument)
return;
Frame* source = V8Proxy::retrieveActiveFrame();
+ if (!source || !source->document())
+ return; // Ignore error if the source document is gone.
+
Document* sourceDocument = source->document();
- ASSERT(sourceDocument);
// FIXME: This error message should contain more specifics of why the same
// origin check has failed.
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",
+ "with URL %s from frame with URL %s. "
+ "Domains, protocols and ports must match.\n",
targetDocument->url().string().utf8().data(),
sourceDocument->url().string().utf8().data());
@@ -754,7 +776,8 @@ static void ReportUnsafeAccessTo(Frame* target, DelayReporting delay) {
static void ReportUnsafeJavaScriptAccess(v8::Local<v8::Object> host,
v8::AccessType type,
- v8::Local<v8::Value> data) {
+ v8::Local<v8::Value> data)
+{
// Do not report error if the access type is HAS.
if (type == v8::ACCESS_HAS)
return;
@@ -782,7 +805,7 @@ static void HandleFatalErrorInV8()
V8Proxy::~V8Proxy()
{
- clear();
+ clearForClose();
DestroyGlobal();
}
@@ -827,7 +850,8 @@ PassRefPtr<EventListener> V8Proxy::createSVGEventHandler(const String& functionN
static V8EventListener* FindEventListenerInList(V8EventListenerList& list,
v8::Local<v8::Value> listener,
- bool html) {
+ bool html)
+{
ASSERT(v8::Context::InContext());
if (!listener->IsObject())
@@ -895,15 +919,16 @@ PassRefPtr<V8EventListener> V8Proxy::FindOrCreateV8EventListener(v8::Local<v8::V
// The persistent reference is made weak in the constructor
// of V8XHREventListener.
-PassRefPtr<V8EventListener> V8Proxy::FindXHREventListener(v8::Local<v8::Value> listener,
- bool html) {
+PassRefPtr<V8EventListener> V8Proxy::FindXHREventListener(
+ v8::Local<v8::Value> listener, bool html)
+{
return FindEventListenerInList(m_xhr_listeners, listener, html);
}
-PassRefPtr<V8EventListener>
-V8Proxy::FindOrCreateXHREventListener(v8::Local<v8::Value> obj,
- bool html) {
+PassRefPtr<V8EventListener> V8Proxy::FindOrCreateXHREventListener(
+ v8::Local<v8::Value> obj, bool html)
+{
ASSERT(v8::Context::InContext());
if (!obj->IsObject()) return 0;
@@ -922,7 +947,8 @@ V8Proxy::FindOrCreateXHREventListener(v8::Local<v8::Value> obj,
static void RemoveEventListenerFromList(V8EventListenerList& list,
- V8EventListener* listener) {
+ V8EventListener* listener)
+{
V8EventListenerList::iterator p = list.begin();
while (p != list.end()) {
if (*p == listener) {
@@ -934,17 +960,20 @@ static void RemoveEventListenerFromList(V8EventListenerList& list,
}
-void V8Proxy::RemoveV8EventListener(V8EventListener* listener) {
+void V8Proxy::RemoveV8EventListener(V8EventListener* listener)
+{
RemoveEventListenerFromList(m_event_listeners, listener);
}
-void V8Proxy::RemoveXHREventListener(V8XHREventListener* listener) {
+void V8Proxy::RemoveXHREventListener(V8XHREventListener* listener)
+{
RemoveEventListenerFromList(m_xhr_listeners, listener);
}
-static void DisconnectEventListenersInList(V8EventListenerList& list) {
+static void DisconnectEventListenersInList(V8EventListenerList& list)
+{
V8EventListenerList::iterator p = list.begin();
while (p != list.end()) {
(*p)->disconnectFrame();
@@ -954,7 +983,8 @@ static void DisconnectEventListenersInList(V8EventListenerList& list) {
}
-void V8Proxy::DisconnectEventListeners() {
+void V8Proxy::DisconnectEventListeners()
+{
DisconnectEventListenersInList(m_event_listeners);
DisconnectEventListenersInList(m_xhr_listeners);
}
@@ -985,7 +1015,7 @@ bool V8Proxy::HandleOutOfMemory()
V8Proxy* proxy = V8Proxy::retrieve(frame);
// Clean m_context, m_document, and event handlers.
- proxy->clear();
+ proxy->clearForClose();
// Destroy the global object.
proxy->DestroyGlobal();
@@ -1020,7 +1050,8 @@ v8::Local<v8::Value> V8Proxy::Evaluate(const String& fileName, int baseLine,
}
v8::Local<v8::Value> V8Proxy::RunScript(v8::Handle<v8::Script> script,
- bool inline_code) {
+ bool inline_code)
+{
if (script.IsEmpty())
return v8::Local<v8::Value>();
@@ -1082,7 +1113,8 @@ v8::Local<v8::Value> V8Proxy::RunScript(v8::Handle<v8::Script> script,
v8::Local<v8::Value> V8Proxy::CallFunction(v8::Handle<v8::Function> function,
v8::Handle<v8::Object> receiver,
int argc,
- v8::Handle<v8::Value> args[]) {
+ v8::Handle<v8::Value> args[])
+{
// For now, we don't put any artificial limitations on the depth
// of recursion that stems from calling functions. This is in
// contrast to the script evaluations.
@@ -1108,7 +1140,8 @@ v8::Local<v8::Value> V8Proxy::CallFunction(v8::Handle<v8::Function> function,
v8::Persistent<v8::FunctionTemplate> V8Proxy::GetTemplate(
- V8ClassIndex::V8WrapperType type) {
+ V8ClassIndex::V8WrapperType type)
+{
v8::Persistent<v8::FunctionTemplate>* cache_cell =
V8ClassIndex::GetCache(type);
if (!(*cache_cell).IsEmpty()) return *cache_cell;
@@ -1165,14 +1198,14 @@ v8::Persistent<v8::FunctionTemplate> V8Proxy::GetTemplate(
0,
0,
0,
- v8::External::New(reinterpret_cast<void*>(V8ClassIndex::NODE)));
+ v8::Integer::New(V8ClassIndex::NODE));
desc->InstanceTemplate()->SetIndexedPropertyHandler(
NodeCollectionIndexedPropertyGetter<HTMLSelectElement>,
USE_INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection),
0,
0,
NodeCollectionIndexedPropertyEnumerator<HTMLSelectElement>,
- v8::External::New(reinterpret_cast<void*>(V8ClassIndex::NODE)));
+ v8::Integer::New(V8ClassIndex::NODE));
break;
case V8ClassIndex::HTMLDOCUMENT: {
desc->InstanceTemplate()->SetNamedPropertyHandler(
@@ -1238,7 +1271,7 @@ v8::Persistent<v8::FunctionTemplate> V8Proxy::GetTemplate(
0,
0,
NodeCollectionIndexedPropertyEnumerator<HTMLFormElement>,
- v8::External::New(reinterpret_cast<void*>(V8ClassIndex::NODE)));
+ v8::Integer::New(V8ClassIndex::NODE));
break;
case V8ClassIndex::CANVASPIXELARRAY:
desc->InstanceTemplate()->SetIndexedPropertyHandler(
@@ -1274,7 +1307,7 @@ v8::Persistent<v8::FunctionTemplate> V8Proxy::GetTemplate(
0,
0,
CollectionIndexedPropertyEnumerator<NamedNodeMap>,
- v8::External::New(reinterpret_cast<void*>(V8ClassIndex::NODE)));
+ v8::Integer::New(V8ClassIndex::NODE));
break;
case V8ClassIndex::NODELIST:
SetCollectionIndexedGetter<NodeList, Node>(desc, V8ClassIndex::NODE);
@@ -1324,7 +1357,16 @@ v8::Persistent<v8::FunctionTemplate> V8Proxy::GetTemplate(
v8::Local<v8::ObjectTemplate> instance_template =
desc->InstanceTemplate();
instance_template->SetInternalFieldCount(
- V8Custom::kDOMWindowInternalFieldCount);
+ V8Custom::kDOMWindowInternalFieldCount);
+
+ // Set access check callbacks, but turned off initially.
+ // When a context is detached from a frame, turn on the access check.
+ // Turning on checks also invalidates inline caches of the object.
+ instance_template->SetAccessCheckCallbacks(
+ V8Custom::v8DOMWindowNamedSecurityCheck,
+ V8Custom::v8DOMWindowIndexedSecurityCheck,
+ v8::Integer::New(V8ClassIndex::DOMWINDOW),
+ false);
break;
}
case V8ClassIndex::LOCATION: {
@@ -1374,31 +1416,36 @@ v8::Persistent<v8::FunctionTemplate> V8Proxy::GetTemplate(
return desc;
}
+
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);
+ ASSERT(!global.IsEmpty());
+ global = LookupDOMWrapper(V8ClassIndex::DOMWINDOW, global);
+ ASSERT(!global.IsEmpty());
+ return ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, global);
}
+
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);
+ global = LookupDOMWrapper(V8ClassIndex::DOMWINDOW, global);
+ ASSERT(!global.IsEmpty());
+ DOMWindow* window = ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, global);
return window->frame();
}
+
Frame* V8Proxy::retrieveActiveFrame()
{
v8::Handle<v8::Context> context = v8::Context::GetEntered();
@@ -1407,12 +1454,14 @@ Frame* V8Proxy::retrieveActiveFrame()
return retrieveFrame(context);
}
+
Frame* V8Proxy::retrieveFrame()
{
DOMWindow* window = retrieveWindow();
return window ? window->frame() : 0;
}
+
V8Proxy* V8Proxy::retrieve()
{
DOMWindow* window = retrieveWindow();
@@ -1432,11 +1481,12 @@ void V8Proxy::disconnectFrame()
// disconnect all event listeners
DisconnectEventListeners();
- // clear all timeouts.
+ // remove all timeouts
if (m_frame->domWindow())
- m_frame->domWindow()->clearAllTimeouts();
+ m_frame->domWindow()->clearAllTimeouts();
}
+
bool V8Proxy::isEnabled()
{
Settings* settings = m_frame->settings();
@@ -1481,7 +1531,6 @@ bool V8Proxy::isEnabled()
void V8Proxy::clearDocumentWrapper()
{
- v8::HandleScope handle_scope;
v8::Local<v8::Context> context = GetContext();
if (context.IsEmpty())
return; // not initialize yet
@@ -1499,56 +1548,90 @@ void V8Proxy::clearDocumentWrapper()
void V8Proxy::DomainChanged(Frame* frame)
{
V8Proxy* proxy = retrieve(frame);
- proxy->ClearSecurityToken();
+ // Restore to default security token.
+ proxy->m_context->UseDefaultSecurityToken();
}
-void V8Proxy::ClearSecurityToken()
+
+void V8Proxy::clearForClose()
{
- m_context->SetSecurityToken(m_global);
+ if (m_context.IsEmpty())
+ return;
+
+ { v8::HandleScope handle_scope;
+ clearDocumentWrapper();
+ }
+
+ m_context.Dispose();
+ m_context.Clear();
}
-void V8Proxy::clear()
+
+void V8Proxy::clearForNavigation()
{
if (m_context.IsEmpty())
return;
- ClearSecurityToken();
+ { v8::HandleScope handle;
+ clearDocumentWrapper();
- if (m_frame->domWindow())
- m_frame->domWindow()->clearAllTimeouts();
+ // Turn on access check on the old DOMWindow wrapper.
+ v8::Handle<v8::Object> wrapper =
+ LookupDOMWrapper(V8ClassIndex::DOMWINDOW, m_global);
+ ASSERT(!wrapper.IsEmpty());
+ wrapper->TurnOnAccessCheck();
- clearDocumentWrapper();
+ // Clear all timeouts.
+ DOMWindow* domWindow =
+ ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, wrapper);
+ domWindow->clearAllTimeouts();
+
+ // Separate the context from its global object.
+ m_context->DetachGlobal();
+ }
// 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, String& message)
+
+void V8Proxy::domWindowReady()
{
- if (!source || !target)
- return false;
+ // Reinitialize context so the global object is reused by
+ // the new context.
+ if (!m_global.IsEmpty() && m_context.IsEmpty()) {
+ v8::HandleScope scope;
+ initContextIfNeeded();
+ }
+}
- // Allow access if the frames the windows represent are the same.
- if (source == target)
- return true;
- Document* target_document = target->document();
+// Check if the current execution context can access a target frame.
+// First it checks same domain policy using the lexical context
+//
+// This is equivalent to KJS::Window::allowsAccessFrom(ExecState*, String&).
+bool V8Proxy::CanAccessPrivate(DOMWindow* target_window)
+{
+ ASSERT(target_window);
+
+ String message;
- // 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)
+ DOMWindow* origin_window = retrieveWindow();
+ if (origin_window == target_window)
return true;
- Document* act_document = source->document();
+ if (!origin_window)
+ return false;
+
+ // 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 (!origin_window->document())
+ return true;
- const SecurityOrigin* active_security_origin = act_document->securityOrigin();
- const SecurityOrigin* target_security_origin = target_document->securityOrigin();
+ const SecurityOrigin* active_security_origin = origin_window->securityOrigin();
+ const SecurityOrigin* target_security_origin = target_window->securityOrigin();
String ui_resource_protocol = webkit_glue::StdStringToString(webkit_glue::GetUIResourceProtocol());
if (active_security_origin->protocol() == ui_resource_protocol) {
@@ -1568,39 +1651,23 @@ static bool SameOrigin(Frame* source, Frame* target, String& message)
if (active_security_origin->canAccess(target_security_origin))
return true;
- 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
-// setting document.domain, using the lexical context of the function
-// to check domain policy.
-//
-// This is equivalent to KJS::Window::allowsAccessFrom(ExecState*, String&).
-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;
-
- source = V8Proxy::retrieveFrame(v8::Context::GetCurrent());
- if (SameOrigin(source, target, message))
+ // Allow access to a "about:blank" page if the dynamic context is a
+ // detached context of the same frame as the blank page.
+ if (target_security_origin->isEmpty() &&
+ origin_window->frame() == target_window->frame())
return true;
return false;
}
-bool V8Proxy::IsFromSameOrigin(Frame* target, bool report_error)
+
+bool V8Proxy::CanAccessFrame(Frame* target, bool report_error)
{
// The subject is detached from a frame, deny accesses.
if (!target)
return false;
- if (!CanAccess(target)) {
+ if (!CanAccessPrivate(target->domWindow())) {
if (report_error)
ReportUnsafeAccessTo(target, REPORT_NOW);
return false;
@@ -1608,6 +1675,7 @@ bool V8Proxy::IsFromSameOrigin(Frame* target, bool report_error)
return true;
}
+
bool V8Proxy::CheckNodeSecurity(Node* node)
{
if (!node)
@@ -1618,9 +1686,39 @@ bool V8Proxy::CheckNodeSecurity(Node* node)
if (!target)
return false;
- return IsFromSameOrigin(target, true);
+ return CanAccessFrame(target, true);
}
+
+static void GenerateSecurityToken(v8::Local<v8::Context> context)
+{
+ Document* document = V8Proxy::retrieveFrame(context)->document();
+ if (!document) {
+ context->UseDefaultSecurityToken();
+ return;
+ }
+
+ // Ask the document's SecurityOrigin to generate a security token.
+ // If two tokens are equal, then the SecurityOrigins canAccess each other.
+ // If two tokens are not equal, then we have to call canAccess.
+ String token = document->securityOrigin()->securityToken();
+
+ // An empty token means we always have to call canAccess. In this case, we
+ // use the global object as the security token to avoid calling canAccess
+ // when a script accesses its own objects.
+ if (token.isEmpty()) {
+ context->UseDefaultSecurityToken();
+ return;
+ }
+
+ CString utf8_token = token.utf8();
+ // NOTE: V8 does identity comparison in fast path, must use a symbol
+ // as the security token.
+ context->SetSecurityToken(
+ v8::String::NewSymbol(utf8_token.data(), utf8_token.length()));
+}
+
+
// Create a new environment and setup the global object.
//
// The global object corresponds to a DOMWindow instance. However, to
@@ -1634,6 +1732,29 @@ 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.
+//
+// To implement split-window, see
+// 1) https://bugs.webkit.org/show_bug.cgi?id=17249
+// 2) https://wiki.mozilla.org/Gecko:SplitWindow
+// 3) https://bugzilla.mozilla.org/show_bug.cgi?id=296639
+// we need to split the shadow object further into two objects:
+// an outer window and an inner window. The inner window is the hidden
+// prototype of the outer window. The inner window is the default
+// global object of the context. A variable declared in the global
+// scope is a property of the inner window.
+//
+// The outer window sticks to a Frame, it is exposed to JavaScript
+// via window.window, window.self, window.parent, etc. The outer window
+// has a security token which is the domain. The outer window cannot
+// have its own properties. window.foo = 'x' is delegated to the
+// inner window.
+//
+// When a frame navigates to a new page, the inner window is cut off
+// the outer window, and the outer window identify is preserved for
+// the frame. However, a new inner window is created for the new page.
+// If there are JS code holds a closure to the old inner window,
+// it won't be able to reach the outer window via its global object.
+
void V8Proxy::initContextIfNeeded()
{
// Bail out if the context has already been initialized.
@@ -1673,18 +1794,12 @@ void V8Proxy::initContextIfNeeded()
return;
// Install a security handler with V8.
- {
- v8::Local<v8::External> external =
- v8::External::New(reinterpret_cast<void*>(V8ClassIndex::DOMWINDOW));
- if (external.IsEmpty())
- return;
-
- global_template->SetAccessCheckCallbacks(
- V8Custom::v8DOMWindowNamedSecurityCheck,
- V8Custom::v8DOMWindowIndexedSecurityCheck,
- external);
- }
+ global_template->SetAccessCheckCallbacks(
+ V8Custom::v8DOMWindowNamedSecurityCheck,
+ V8Custom::v8DOMWindowIndexedSecurityCheck,
+ v8::Integer::New(V8ClassIndex::DOMWINDOW));
+ // Create a new context.
m_context = v8::Context::New(NULL, global_template, m_global);
if (m_context.IsEmpty())
return;
@@ -1712,9 +1827,6 @@ void V8Proxy::initContextIfNeeded()
DOMWindow* window = m_frame->domWindow();
- // Get rid of the old window peer object if one exists.
- dom_object_map().forget(window);
-
// Setup the peer object for the DOM window.
dom_object_map().set(window, v8::Persistent<v8::Object>::New(window_peer));
// Wrap the window.
@@ -1725,7 +1837,8 @@ void V8Proxy::initContextIfNeeded()
v8::Handle<v8::Object> v8_global = context->Global();
v8_global->Set(v8::String::New("__proto__"), window_peer);
- context->SetSecurityToken(GenerateSecurityToken(context));
+ // Setup security origin and security token
+ GenerateSecurityToken(context);
V8Proxy::retrieveFrame(context)->loader()->dispatchWindowObjectAvailable();
@@ -1752,30 +1865,6 @@ void V8Proxy::initContextIfNeeded()
}
-v8::Handle<v8::Value> V8Proxy::GenerateSecurityToken(
- v8::Local<v8::Context> context) {
- Document* document = V8Proxy::retrieveFrame(context)->document();
- if (!document)
- return context->Global();
-
- // Ask the document's SecurityOrigin to generate a security token.
- // If two tokens are equal, then the SecurityOrigins canAccess each other.
- // If two tokens are not equal, then we have to call canAccess.
- String token = document->securityOrigin()->securityToken();
-
- // An empty token means we always have to call canAccess. In this case, we
- // use the global object as the security token to avoid calling canAccess
- // when a script accesses its own objects.
- if (token.isEmpty())
- return context->Global();
-
- CString utf8_token = token.utf8();
- // NOTE: V8 does identity comparison in fast path, must use a symbol
- // as the security token.
- return v8::String::NewSymbol(utf8_token.data(), utf8_token.length());
-}
-
-
void V8Proxy::SetDOMException(int exception_code)
{
if (exception_code <= 0)
@@ -1922,7 +2011,8 @@ v8::Handle<v8::Value> V8Proxy::ToV8Object(V8ClassIndex::V8WrapperType type, void
void V8Proxy::SetHiddenWindowReference(Frame* frame,
const int internal_index,
- v8::Handle<v8::Object> jsobj) {
+ v8::Handle<v8::Object> jsobj)
+{
// Get DOMWindow
if (!frame) return; // Object might be detached from window
v8::Handle<v8::Context> context = GetContext(frame);
@@ -1931,9 +2021,9 @@ void V8Proxy::SetHiddenWindowReference(Frame* frame,
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.IsEmpty());
ASSERT(global->GetInternalField(internal_index)->IsUndefined());
global->SetInternalField(internal_index, jsobj);
}
@@ -1949,7 +2039,8 @@ V8ClassIndex::V8WrapperType V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object> ob
void* V8Proxy::ToNativeObjectImpl(V8ClassIndex::V8WrapperType type,
- v8::Handle<v8::Value> object) {
+ v8::Handle<v8::Value> object)
+{
// Native event listener is per frame, it cannot be handled
// by this generic function.
ASSERT(type != V8ClassIndex::EVENTLISTENER);
@@ -2020,7 +2111,8 @@ PassRefPtr<NodeFilter> V8Proxy::ToNativeNodeFilter(v8::Handle<v8::Value> filter)
v8::Local<v8::Object> V8Proxy::InstantiateV8Object(
V8ClassIndex::V8WrapperType desc_type,
V8ClassIndex::V8WrapperType cptr_type,
- void* imp) {
+ void* imp)
+{
// Make a special case for document.all
if (desc_type == V8ClassIndex::HTMLCOLLECTION &&
static_cast<HTMLCollection*>(imp)->type() == HTMLCollection::DocAll) {
@@ -2052,7 +2144,8 @@ v8::Handle<v8::Value> V8Proxy::CheckNewLegal(const v8::Arguments& args)
return args.This();
}
-void V8Proxy::SetDOMWrapper(v8::Handle<v8::Object> obj, int type, void* cptr) {
+void V8Proxy::SetDOMWrapper(v8::Handle<v8::Object> obj, int type, void* cptr)
+{
ASSERT(obj->InternalFieldCount() >= 2);
obj->SetInternalField(V8Custom::kDOMWrapperObjectIndex, WrapCPointer(cptr));
obj->SetInternalField(V8Custom::kDOMWrapperTypeIndex, v8::Integer::New(type));
@@ -2060,7 +2153,8 @@ void V8Proxy::SetDOMWrapper(v8::Handle<v8::Object> obj, int type, void* cptr) {
#ifndef NDEBUG
-bool V8Proxy::MaybeDOMWrapper(v8::Handle<v8::Value> value) {
+bool V8Proxy::MaybeDOMWrapper(v8::Handle<v8::Value> value)
+{
if (value.IsEmpty() || !value->IsObject()) return false;
v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(value);
@@ -2084,14 +2178,16 @@ bool V8Proxy::MaybeDOMWrapper(v8::Handle<v8::Value> value) {
#endif
-bool V8Proxy::IsDOMEventWrapper(v8::Handle<v8::Value> value) {
+bool V8Proxy::IsDOMEventWrapper(v8::Handle<v8::Value> value)
+{
// All kinds of events use EVENT as dom type in JS wrappers.
// See EventToV8Object
return IsWrapperOfType(value, V8ClassIndex::EVENT);
}
bool V8Proxy::IsWrapperOfType(v8::Handle<v8::Value> value,
- V8ClassIndex::V8WrapperType classType) {
+ V8ClassIndex::V8WrapperType classType)
+{
if (value.IsEmpty() || !value->IsObject()) return false;
v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(value);
@@ -2186,7 +2282,8 @@ bool V8Proxy::IsWrapperOfType(v8::Handle<v8::Value> value,
macro(ul, ULIST) \
macro(xmp, PRE)
-V8ClassIndex::V8WrapperType V8Proxy::GetHTMLElementType(HTMLElement* element) {
+V8ClassIndex::V8WrapperType V8Proxy::GetHTMLElementType(HTMLElement* element)
+{
static HashMap<String, V8ClassIndex::V8WrapperType> map;
if (map.isEmpty()) {
#define ADD_TO_HASH_MAP(tag, name) \
@@ -2311,7 +2408,8 @@ FOR_EACH_TAG(ADD_TO_HASH_MAP)
macro(view, VIEW) \
// end of macro
-V8ClassIndex::V8WrapperType V8Proxy::GetSVGElementType(SVGElement* element) {
+V8ClassIndex::V8WrapperType V8Proxy::GetSVGElementType(SVGElement* element)
+{
static HashMap<String, V8ClassIndex::V8WrapperType> map;
if (map.isEmpty()) {
#define ADD_TO_HASH_MAP(tag, name) \
@@ -2389,7 +2487,8 @@ v8::Handle<v8::Value> V8Proxy::EventToV8Object(Event* event)
// Caller checks node is not null.
-v8::Handle<v8::Value> V8Proxy::NodeToV8Object(Node* node) {
+v8::Handle<v8::Value> V8Proxy::NodeToV8Object(Node* node)
+{
if (!node) return v8::Null();
v8::Handle<v8::Object> peer = dom_node_map().get(node);
@@ -2511,7 +2610,8 @@ v8::Handle<v8::Value> V8Proxy::NodeToV8Object(Node* node) {
}
-void V8Proxy::UpdateDocumentHandle(v8::Local<v8::Object> handle) {
+void V8Proxy::UpdateDocumentHandle(v8::Local<v8::Object> handle)
+{
// If the old handle is not empty, release it.
if (!m_document.IsEmpty()) {
#ifndef NDEBUG
@@ -2559,7 +2659,8 @@ v8::Handle<v8::Value> V8Proxy::EventTargetToV8Object(EventTarget* target)
v8::Handle<v8::Value> V8Proxy::EventListenerToV8Object(
- EventListener* listener) {
+ EventListener* listener)
+{
if (listener == 0) return v8::Null();
// TODO(fqian): can a user take a lazy event listener and set to other places?
@@ -2570,7 +2671,8 @@ v8::Handle<v8::Value> V8Proxy::EventListenerToV8Object(
v8::Handle<v8::Value> V8Proxy::DOMImplementationToV8Object(
- DOMImplementation* impl) {
+ DOMImplementation* impl)
+{
v8::Handle<v8::Object> result =
InstantiateV8Object(V8ClassIndex::DOMIMPLEMENTATION,
V8ClassIndex::DOMIMPLEMENTATION,
@@ -2584,7 +2686,8 @@ v8::Handle<v8::Value> V8Proxy::DOMImplementationToV8Object(
}
-v8::Handle<v8::Value> V8Proxy::StyleSheetToV8Object(StyleSheet* sheet) {
+v8::Handle<v8::Value> V8Proxy::StyleSheetToV8Object(StyleSheet* sheet)
+{
if (!sheet) return v8::Null();
v8::Handle<v8::Object> peer = dom_object_map().get(sheet);
@@ -2614,7 +2717,8 @@ v8::Handle<v8::Value> V8Proxy::StyleSheetToV8Object(StyleSheet* sheet) {
}
-v8::Handle<v8::Value> V8Proxy::CSSValueToV8Object(CSSValue* value) {
+v8::Handle<v8::Value> V8Proxy::CSSValueToV8Object(CSSValue* value)
+{
if (!value) return v8::Null();
v8::Handle<v8::Object> peer = dom_object_map().get(value);
@@ -2647,7 +2751,8 @@ v8::Handle<v8::Value> V8Proxy::CSSValueToV8Object(CSSValue* value) {
}
-v8::Handle<v8::Value> V8Proxy::CSSRuleToV8Object(CSSRule* rule) {
+v8::Handle<v8::Value> V8Proxy::CSSRuleToV8Object(CSSRule* rule)
+{
if (!rule) return v8::Null();
v8::Handle<v8::Object> peer = dom_object_map().get(rule);
@@ -2698,7 +2803,8 @@ v8::Handle<v8::Value> V8Proxy::CSSRuleToV8Object(CSSRule* rule) {
return result;
}
-v8::Handle<v8::Value> V8Proxy::WindowToV8Object(DOMWindow* window) {
+v8::Handle<v8::Value> V8Proxy::WindowToV8Object(DOMWindow* window)
+{
if (!window) return v8::Null();
// Initializes environment of a frame, and return the global object
// of the frame.
diff --git a/webkit/port/bindings/v8/v8_proxy.h b/webkit/port/bindings/v8/v8_proxy.h
index 0923570..f1b558f 100644
--- a/webkit/port/bindings/v8/v8_proxy.h
+++ b/webkit/port/bindings/v8/v8_proxy.h
@@ -11,6 +11,7 @@
#include "v8_utility.h"
#include "Node.h"
#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
@@ -157,18 +158,20 @@ class V8Proxy {
~V8Proxy();
- // Clear security token by setting the security token
- // for the context to the global object.
- void ClearSecurityToken();
+ Frame* frame() { return m_frame; }
+
+ // Clear page-specific data, but keep the global object identify.
+ void clearForNavigation();
- // Clear page-specific data, exception keep the global object identify.
- void clear();
+ // Clear data before closing the frame.
+ void clearForClose();
+
+ // Notify that a new DOMWindow object is ready.
+ void domWindowReady();
// Destroy the global object.
void DestroyGlobal();
- Frame* frame() { return m_frame; }
-
// TODO(mpcomplete): Need comment. User Gesture related.
bool inlineCode() const { return m_inlineCode; }
void setInlineCode(bool value) { m_inlineCode = value; }
@@ -262,21 +265,13 @@ class V8Proxy {
// is disabled and it returns true.
static bool HandleOutOfMemory();
- // Generate the security token for a context.
- static v8::Handle<v8::Value> GenerateSecurityToken(
- v8::Local<v8::Context> context);
-
- // Check if the active execution context is from the same origin
- // as the target frame.
- static bool IsFromSameOrigin(Frame* target, bool report_error);
+ // Check if the active execution context can access the target frame.
+ static bool CanAccessFrame(Frame* target, bool report_error);
// Check if it is safe to access the given node from the
// current security context.
static bool CheckNodeSecurity(Node* node);
- // Return true if the current security context can access the target frame.
- static bool CanAccess(Frame* target);
-
static v8::Handle<v8::Value> CheckNewLegal(const v8::Arguments& args);
// Create a V8 wrapper for a C pointer
@@ -421,6 +416,8 @@ class V8Proxy {
void initContextIfNeeded();
void DisconnectEventListeners();
+ static bool CanAccessPrivate(DOMWindow* target);
+
// Check whether a V8 value is a DOM Event wrapper
static bool IsDOMEventWrapper(v8::Handle<v8::Value> obj);