diff options
-rw-r--r-- | DEPS | 2 | ||||
-rw-r--r-- | webkit/port/bindings/scripts/CodeGeneratorV8.pm | 6 | ||||
-rw-r--r-- | webkit/port/bindings/v8/ScriptController.cpp | 6 | ||||
-rw-r--r-- | webkit/port/bindings/v8/ScriptController.h | 1 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_collection.h | 14 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_custom.cpp | 78 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_index.h | 4 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_proxy.cpp | 474 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_proxy.h | 31 |
9 files changed, 353 insertions, 263 deletions
@@ -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); |