diff --git a/JavaScriptCore/runtime/JSGlobalObject.cpp b/JavaScriptCore/runtime/JSGlobalObject.cpp index 89c32fd..16760cb 100644 --- a/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -198,12 +198,21 @@ void JSGlobalObject::reset(JSValue* prototype) { ExecState* exec = JSGlobalObject::globalExec(); + //SecToken + RefPtr token = new SecurityToken(); + + RefPtr funcProtoID = FunctionPrototype::createStructureID(jsNull()); // The real prototype will be set once ObjectPrototype is created. + RefPtr objProtoID = ObjectPrototype::createStructureID(jsNull()); + + funcProtoID->replaceSecurityToken(token.get()); + objProtoID->replaceSecurityToken(token.get()); + // Prototypes - d()->functionPrototype = new (exec) FunctionPrototype(exec, FunctionPrototype::createStructureID(jsNull())); // The real prototype will be set once ObjectPrototype is created. + d()->functionPrototype = new (exec) FunctionPrototype(exec, funcProtoID); d()->prototypeFunctionStructure = PrototypeFunction::createStructureID(d()->functionPrototype); d()->functionPrototype->addFunctionProperties(exec, d()->prototypeFunctionStructure.get()); - d()->objectPrototype = new (exec) ObjectPrototype(exec, ObjectPrototype::createStructureID(jsNull()), d()->prototypeFunctionStructure.get()); + d()->objectPrototype = new (exec) ObjectPrototype(exec, objProtoID, d()->prototypeFunctionStructure.get()); d()->functionPrototype->structureID()->setPrototypeWithoutTransition(d()->objectPrototype); d()->emptyObjectStructure = d()->objectPrototype->inheritorID(); @@ -334,6 +343,8 @@ void JSGlobalObject::reset(JSValue* prototype) #endif resetPrototype(prototype); + //SecToken + replaceSecurityToken(token.get()); } // Set prototype, and also insert the object prototype at the end of the chain. diff --git a/JavaScriptCore/runtime/JSGlobalObject.h b/JavaScriptCore/runtime/JSGlobalObject.h index d8a072a..43ee755 100644 --- a/JavaScriptCore/runtime/JSGlobalObject.h +++ b/JavaScriptCore/runtime/JSGlobalObject.h @@ -136,6 +136,7 @@ namespace JSC { RefPtr globalData; HashSet codeBlocks; + }; public: diff --git a/JavaScriptCore/runtime/JSObject.cpp b/JavaScriptCore/runtime/JSObject.cpp index 0723d1c..91eee73 100644 --- a/JavaScriptCore/runtime/JSObject.cpp +++ b/JavaScriptCore/runtime/JSObject.cpp @@ -103,6 +103,10 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue* val ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); + //SecToken + if (!allowAccessFrom(exec)) + return; + if (propertyName == exec->propertyNames().underscoreProto) { JSObject* proto = value->getObject(); @@ -169,17 +173,29 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue* val void JSObject::put(ExecState* exec, unsigned propertyName, JSValue* value) { + //SecToken + if (!allowAccessFrom(exec)) + return; + PutPropertySlot slot; put(exec, Identifier::from(exec, propertyName), value, slot); } -void JSObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes) +void JSObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue* value, unsigned attributes) { + //SecToken + if (!allowAccessFrom(exec)) + return; + putDirect(propertyName, value, attributes); } void JSObject::putWithAttributes(ExecState* exec, unsigned propertyName, JSValue* value, unsigned attributes) { + //SecToken + if (!allowAccessFrom(exec)) + return; + putWithAttributes(exec, Identifier::from(exec, propertyName), value, attributes); } @@ -481,11 +497,19 @@ void JSObject::removeDirect(const Identifier& propertyName) void JSObject::putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr) { + //SecToken + if (!allowAccessFrom(exec)) + return; + putDirect(Identifier(exec, function->name(&exec->globalData())), function, attr); } void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr) { + //SecToken + if (!allowAccessFrom(exec)) + return; + putDirectWithoutTransition(Identifier(exec, function->name(&exec->globalData())), function, attr); } diff --git a/JavaScriptCore/runtime/JSObject.h b/JavaScriptCore/runtime/JSObject.h index d280b64..8048bf3 100644 --- a/JavaScriptCore/runtime/JSObject.h +++ b/JavaScriptCore/runtime/JSObject.h @@ -38,6 +38,8 @@ namespace JSC { class InternalFunction; class PropertyNameArray; class StructureID; + //SecToken + class SecurityToken; struct HashEntry; struct HashTable; @@ -190,6 +192,12 @@ namespace JSC { return StructureID::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot)); } + //SecToken + SecurityToken* securityToken() { return m_structureID->securityToken(); } + void replaceSecurityToken(SecurityToken* token) { m_structureID->replaceSecurityToken(token); } + void updateSecurityToken(SecurityToken* token) { m_structureID->updateSecurityToken(token); } + bool allowAccessFrom(ExecState*); + protected: bool getOwnPropertySlotForWrite(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable); @@ -273,8 +281,28 @@ inline bool JSValue::isObject(const ClassInfo* classInfo) const return !JSImmediate::isImmediate(asValue()) && asCell()->isObject(classInfo); } +//SecToken +ALWAYS_INLINE bool JSObject::allowAccessFrom(ExecState* exec) +{ + //Use of the lexical global object appears to be slightly faster, but not + //too significantly. + JSObject* global = reinterpret_cast(exec->lexicalGlobalObject()); + + if (!global->securityToken()) + return true; + + return global->securityToken()->canAccess(securityToken()); +} + ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { + //SecToken + //Return true, but just pretend that the property doesn't exist. + if (!allowAccessFrom(exec)) { + slot.setUndefined(); + return true; + } + if (JSValue** location = getDirectLocation(propertyName)) { if (m_structureID->hasGetterSetterProperties() && location[0]->isGetterSetter()) fillGetterPropertySlot(slot, location); diff --git a/JavaScriptCore/runtime/Lookup.h b/JavaScriptCore/runtime/Lookup.h index 356c918..a5f1f9d 100644 --- a/JavaScriptCore/runtime/Lookup.h +++ b/JavaScriptCore/runtime/Lookup.h @@ -154,6 +154,11 @@ namespace JSC { if (!entry) // not found, forward to parent return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot); + if(!thisObj->allowAccessFrom(exec)) { + slot.setUndefined(); + return true; + } + if (entry->attributes() & Function) setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); else @@ -177,6 +182,11 @@ namespace JSC { if (!entry) return false; + if(!thisObj->allowAccessFrom(exec)) { + slot.setUndefined(); + return true; + } + setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); return true; } @@ -193,6 +203,11 @@ namespace JSC { if (!entry) // not found, forward to parent return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot); + if(!thisObj->allowAccessFrom(exec)) { + slot.setUndefined(); + return true; + } + ASSERT(!(entry->attributes() & Function)); slot.setCustom(thisObj, entry->propertyGetter()); diff --git a/JavaScriptCore/runtime/StructureID.cpp b/JavaScriptCore/runtime/StructureID.cpp index e14ca38..0696414 100644 --- a/JavaScriptCore/runtime/StructureID.cpp +++ b/JavaScriptCore/runtime/StructureID.cpp @@ -130,6 +130,10 @@ StructureID::StructureID(JSValue* prototype, const TypeInfo& typeInfo) ASSERT(m_prototype); ASSERT(m_prototype->isObject() || m_prototype->isNull()); + //SecToken + if (m_prototype->isObject()) + m_securityToken = m_prototype->getObject()->securityToken(); + m_transitions.singleTransition = 0; #ifndef NDEBUG diff --git a/JavaScriptCore/runtime/StructureID.h b/JavaScriptCore/runtime/StructureID.h index 7e8ca73..28dd2fc 100644 --- a/JavaScriptCore/runtime/StructureID.h +++ b/JavaScriptCore/runtime/StructureID.h @@ -50,6 +50,33 @@ namespace JSC { class PropertyNameArray; class PropertyNameArrayData; + + //SecToken + class SecurityToken : public RefCounted { + public: + SecurityToken() + { + } + + SecurityToken(Identifier token) + : m_token(token) + { + } + + void update(const SecurityToken* token) + { + m_token = token->m_token; + } + + bool canAccess(const SecurityToken* securityToken) + { + return (securityToken == NULL) || (securityToken->m_token == m_token); + } + + private: + Identifier m_token; + }; + class StructureID : public RefCounted { public: @@ -116,6 +143,11 @@ namespace JSC { bool isEmpty() const { return !m_propertyTable; } + //SecToken + SecurityToken* securityToken() { return m_securityToken.get(); } + void replaceSecurityToken(SecurityToken* securityToken) { m_securityToken = securityToken; } + void updateSecurityToken(SecurityToken* securityToken) { m_securityToken->update(securityToken); } + private: StructureID(JSValue* prototype, const TypeInfo&); @@ -165,6 +197,9 @@ namespace JSC { bool m_hasGetterSetterProperties : 1; bool m_usingSingleTransitionSlot : 1; unsigned m_attributesInPrevious : 5; + + //SecToken + RefPtr m_securityToken; }; inline size_t StructureID::get(const Identifier& propertyName) const diff --git a/WebCore/bindings/js/JSDOMWindowBase.cpp b/WebCore/bindings/js/JSDOMWindowBase.cpp index 2212391..a01c094 100644 --- a/WebCore/bindings/js/JSDOMWindowBase.cpp +++ b/WebCore/bindings/js/JSDOMWindowBase.cpp @@ -990,6 +990,21 @@ void JSDOMWindowBase::disconnectFrame() clearAllTimeouts(); } +//SecToken +void JSDOMWindowBase::securityOriginUpdated() +{ + Document *document = d()->impl->document(); + + RefPtr token; + + if (document == NULL) + token = new SecurityToken(); + else + token = new SecurityToken(Identifier(globalExec(), document->securityOrigin()->toString())); + + updateSecurityToken(token.get()); +} + void DOMWindowTimer::fired() { timerNestingLevel = m_nestingLevel; diff --git a/WebCore/bindings/js/JSDOMWindowBase.h b/WebCore/bindings/js/JSDOMWindowBase.h index 62ecdb5..ddcd7b4 100644 --- a/WebCore/bindings/js/JSDOMWindowBase.h +++ b/WebCore/bindings/js/JSDOMWindowBase.h @@ -52,9 +52,13 @@ namespace WebCore { protected: JSDOMWindowBase(PassRefPtr, PassRefPtr, JSDOMWindowShell*); + public: virtual ~JSDOMWindowBase(); + //SecToken + void securityOriginUpdated(); + void updateDocument(); DOMWindow* impl() const { return d()->impl.get(); } @@ -85,7 +89,7 @@ namespace WebCore { static const JSC::ClassInfo s_info; virtual JSC::ExecState* globalExec(); - + virtual bool supportsProfiling() const; virtual bool shouldInterruptScript() const; diff --git a/WebCore/bindings/js/ScriptController.cpp b/WebCore/bindings/js/ScriptController.cpp index 37d08f9..eb4c853 100644 --- a/WebCore/bindings/js/ScriptController.cpp +++ b/WebCore/bindings/js/ScriptController.cpp @@ -231,6 +231,8 @@ void ScriptController::updateDocument() HashSet::iterator end = m_liveFormerWindows.end(); for (HashSet::iterator it = m_liveFormerWindows.begin(); it != end; ++it) (*it)->updateDocument(); + + securityOriginUpdated(); } @@ -368,4 +370,13 @@ void ScriptController::resumeTimeouts(OwnPtr& pausedTimeouts) windowShell()->window()->resumeTimeouts(pausedTimeouts); } +//SecToken +void ScriptController::securityOriginUpdated() +{ + if (!haveWindowShell()) + return; + + windowShell()->window()->securityOriginUpdated(); +} + } // namespace WebCore diff --git a/WebCore/bindings/js/ScriptController.h b/WebCore/bindings/js/ScriptController.h index ab7af91..6b86444 100644 --- a/WebCore/bindings/js/ScriptController.h +++ b/WebCore/bindings/js/ScriptController.h @@ -112,6 +112,9 @@ public: PassRefPtr createRootObject(void* nativeHandle); + //SecToken + void securityOriginUpdated(); + #if PLATFORM(MAC) #if ENABLE(MAC_JAVA_BRIDGE) static void initJavaJSBindings(); diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp index 4f80482..8341b09 100644 --- a/WebCore/dom/Document.cpp +++ b/WebCore/dom/Document.cpp @@ -4059,6 +4059,10 @@ void Document::setSecurityOrigin(SecurityOrigin* securityOrigin) { m_securityOrigin = securityOrigin; initDNSPrefetch(); + + //SecToken + if (frame()) + frame()->script()->securityOriginUpdated(); } void Document::updateFocusAppearanceSoon()