Changeset 125146 in webkit
- Timestamp:
- Aug 8, 2012 8:52:41 PM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r125145 r125146 1 2012-08-08 Adam Barth <abarth@webkit.org> 2 3 Implement JSDOMWindow*::allowsAccessFrom* in terms of BindingSecurity 4 https://bugs.webkit.org/show_bug.cgi?id=93407 5 6 Reviewed by Eric Seidel. 7 8 This patch removes allowsAccessFrom and implements the security checks 9 in terms of shouldAllowAccessToFrame directly. There shouldn't be any 10 change in behavior. 11 12 * bindings/js/JSDOMWindowBase.cpp: 13 (WebCore): 14 (WebCore::shouldAllowAccessFrom): 15 * bindings/js/JSDOMWindowBase.h: 16 (JSDOMWindowBase): 17 * bindings/js/JSDOMWindowCustom.cpp: 18 (WebCore::namedItemGetter): 19 (WebCore::JSDOMWindow::getOwnPropertySlot): 20 (WebCore::JSDOMWindow::getOwnPropertyDescriptor): 21 (WebCore::JSDOMWindow::put): 22 (WebCore::JSDOMWindow::deleteProperty): 23 (WebCore::JSDOMWindow::getPropertyNames): 24 (WebCore::JSDOMWindow::getOwnPropertyNames): 25 (WebCore::JSDOMWindow::defineOwnProperty): 26 (WebCore::JSDOMWindow::setLocation): 27 * bindings/js/JSDOMWindowCustom.h: 28 * bindings/js/JSInjectedScriptManager.cpp: 29 (WebCore::InjectedScriptManager::canAccessInspectedWindow): 30 * bindings/objc/WebScriptObject.mm: 31 (-[WebScriptObject _isSafeScript]): 32 * bindings/scripts/CodeGeneratorJS.pm: 33 (GenerateGetOwnPropertyDescriptorBody): 34 (GenerateImplementation): 35 * bindings/scripts/test/JS/JSTestActiveDOMObject.cpp: 36 (WebCore::jsTestActiveDOMObjectExcitingAttr): 37 (WebCore::jsTestActiveDOMObjectConstructor): 38 (WebCore::jsTestActiveDOMObjectPrototypeFunctionExcitingFunction): 39 1 40 2012-08-08 Sheriff Bot <webkit.review.bot@gmail.com> 2 41 -
trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp
r123013 r125146 43 43 namespace WebCore { 44 44 45 // FIXME: This function should call shouldAllowAccessToDocument once there is a predictable 46 // way to get a Document* from a DOMWindow*. 47 static bool shouldAllowAccessFrom(const JSGlobalObject* thisObject, ExecState* exec) 48 { 49 DOMWindow* active = activeDOMWindow(exec); 50 DOMWindow* target = asJSDOMWindow(thisObject)->impl(); 51 52 if (active->securityOrigin()->canAccess(target->securityOrigin())) 53 return true; 54 55 printErrorMessageForFrame(target->frame(), target->crossDomainAccessErrorMessage(active)); 56 return false; 57 } 58 45 59 const ClassInfo JSDOMWindowBase::s_info = { "Window", &JSDOMGlobalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSDOMWindowBase) }; 46 60 47 const GlobalObjectMethodTable JSDOMWindowBase::s_globalObjectMethodTable = { & allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled };61 const GlobalObjectMethodTable JSDOMWindowBase::s_globalObjectMethodTable = { &shouldAllowAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled }; 48 62 49 63 JSDOMWindowBase::JSDOMWindowBase(JSGlobalData& globalData, Structure* structure, PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell) … … 84 98 } 85 99 86 String JSDOMWindowBase::crossDomainAccessErrorMessage(const JSGlobalObject* other) const87 {88 return m_shell->window()->impl()->crossDomainAccessErrorMessage(asJSDOMWindow(other)->impl());89 }90 91 100 void JSDOMWindowBase::printErrorMessage(const String& message) const 92 101 { 93 102 printErrorMessageForFrame(impl()->frame(), message); 94 }95 96 // This method checks whether accesss to *this* global object is permitted from97 // the given context; this differs from allowsAccessFromPrivate, since that98 // method checks whether the given context is permitted to access the current99 // window the shell is referencing (which may come from a different security100 // origin to this global object).101 bool JSDOMWindowBase::allowsAccessFrom(const JSGlobalObject* thisObject, ExecState* exec)102 {103 JSGlobalObject* otherObject = exec->lexicalGlobalObject();104 105 const JSDOMWindow* originWindow = asJSDOMWindow(otherObject);106 const JSDOMWindow* targetWindow = asJSDOMWindow(thisObject);107 108 if (originWindow == targetWindow)109 return true;110 111 const SecurityOrigin* originSecurityOrigin = originWindow->impl()->securityOrigin();112 const SecurityOrigin* targetSecurityOrigin = targetWindow->impl()->securityOrigin();113 114 if (originSecurityOrigin->canAccess(targetSecurityOrigin))115 return true;116 117 targetWindow->printErrorMessage(targetWindow->crossDomainAccessErrorMessage(otherObject));118 return false;119 103 } 120 104 -
trunk/Source/WebCore/bindings/js/JSDOMWindowBase.h
r118018 r125146 65 65 static bool shouldInterruptScript(const JSC::JSGlobalObject*); 66 66 static bool javaScriptExperimentsEnabled(const JSC::JSGlobalObject*); 67 static bool allowsAccessFrom(const JSC::JSGlobalObject*, JSC::ExecState*); 68 69 bool allowsAccessFrom(JSC::ExecState*) const; 70 bool allowsAccessFromNoErrorMessage(JSC::ExecState*) const; 71 bool allowsAccessFrom(JSC::ExecState*, String& message) const; 67 72 68 void printErrorMessage(const String&) const; 73 74 // Don't call this version of allowsAccessFrom -- it's a slightly incorrect implementation used only by WebScriptObject75 bool allowsAccessFrom(const JSC::JSGlobalObject*) const;76 69 77 70 static JSC::JSObject* toThisObject(JSC::JSCell*, JSC::ExecState*); … … 83 76 RefPtr<DOMWindow> m_impl; 84 77 JSDOMWindowShell* m_shell; 85 86 bool allowsAccessFromPrivate(const JSC::JSGlobalObject*) const;87 String crossDomainAccessErrorMessage(const JSC::JSGlobalObject*) const;88 78 }; 89 79 -
trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
r122115 r125146 113 113 Document* document = thisObj->impl()->frame()->document(); 114 114 115 ASSERT( thisObj->allowsAccessFrom(exec));115 ASSERT(shouldAllowAccessToFrame(exec, thisObj->impl()->frame())); 116 116 ASSERT(document); 117 117 ASSERT(document->isHTMLDocument()); … … 159 159 // is allowed. 160 160 String errorMessage; 161 bool allowsAccess = thisObject->allowsAccessFrom(exec, errorMessage);161 bool allowsAccess = shouldAllowAccessToFrame(exec, thisObject->impl()->frame(), errorMessage); 162 162 163 163 // Look for overrides before looking at any of our own properties, but ignore overrides completely … … 167 167 168 168 // We need this code here because otherwise JSDOMWindowBase will stop the search before we even get to the 169 // prototype due to the blanket same origin (allowsAccessFrom)check at the end of getOwnPropertySlot.169 // prototype due to the blanket same origin check at the end of getOwnPropertySlot. 170 170 // Also, it's important to get the implementation straight out of the DOMWindow prototype regardless of 171 171 // what prototype is actually set on this object. … … 273 273 JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object); 274 274 // Never allow cross-domain getOwnPropertyDescriptor 275 if (! thisObject->allowsAccessFrom(exec))275 if (!shouldAllowAccessToFrame(exec, thisObject->impl()->frame())) 276 276 return false; 277 277 … … 350 350 // Optimization: access JavaScript global variables directly before involving the DOM. 351 351 if (thisObject->JSGlobalObject::hasOwnPropertyForWrite(exec, propertyName)) { 352 if ( thisObject->allowsAccessFrom(exec))352 if (shouldAllowAccessToFrame(exec, thisObject->impl()->frame())) 353 353 JSGlobalObject::put(thisObject, exec, propertyName, value, slot); 354 354 return; … … 358 358 return; 359 359 360 if ( thisObject->allowsAccessFrom(exec))360 if (shouldAllowAccessToFrame(exec, thisObject->impl()->frame())) 361 361 Base::put(thisObject, exec, propertyName, value, slot); 362 362 } … … 366 366 JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell); 367 367 // Only allow deleting properties by frames in the same origin. 368 if (! thisObject->allowsAccessFrom(exec))368 if (!shouldAllowAccessToFrame(exec, thisObject->impl()->frame())) 369 369 return false; 370 370 return Base::deleteProperty(thisObject, exec, propertyName); … … 375 375 JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object); 376 376 // Only allow the window to enumerated by frames in the same origin. 377 if (! thisObject->allowsAccessFrom(exec))377 if (!shouldAllowAccessToFrame(exec, thisObject->impl()->frame())) 378 378 return; 379 379 Base::getPropertyNames(thisObject, exec, propertyNames, mode); … … 384 384 JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object); 385 385 // Only allow the window to enumerated by frames in the same origin. 386 if (! thisObject->allowsAccessFrom(exec))386 if (!shouldAllowAccessToFrame(exec, thisObject->impl()->frame())) 387 387 return; 388 388 Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode); … … 393 393 JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object); 394 394 // Only allow defining properties in this way by frames in the same origin, as it allows setters to be introduced. 395 if (! thisObject->allowsAccessFrom(exec))395 if (!shouldAllowAccessToFrame(exec, thisObject->impl()->frame())) 396 396 return false; 397 397 … … 413 413 if (Settings* settings = activeFrame->settings()) { 414 414 if (settings->usesDashboardBackwardCompatibilityMode() && !activeFrame->tree()->parent()) { 415 if ( allowsAccessFrom(exec))415 if (shouldAllowAccessToFrame(exec, impl()->frame())) 416 416 putDirect(exec->globalData(), Identifier(exec, "location"), value); 417 417 return; -
trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.h
r113387 r125146 37 37 } 38 38 39 inline bool JSDOMWindowBase::allowsAccessFrom(const JSGlobalObject* other) const40 {41 if (allowsAccessFromPrivate(other))42 return true;43 printErrorMessage(crossDomainAccessErrorMessage(other));44 return false;45 }46 47 inline bool JSDOMWindowBase::allowsAccessFrom(JSC::ExecState* exec) const48 {49 if (allowsAccessFromPrivate(exec->lexicalGlobalObject()))50 return true;51 printErrorMessage(crossDomainAccessErrorMessage(exec->lexicalGlobalObject()));52 return false;53 }54 55 inline bool JSDOMWindowBase::allowsAccessFromNoErrorMessage(JSC::ExecState* exec) const56 {57 return allowsAccessFromPrivate(exec->lexicalGlobalObject());58 }59 60 inline bool JSDOMWindowBase::allowsAccessFrom(JSC::ExecState* exec, String& message) const61 {62 if (allowsAccessFromPrivate(exec->lexicalGlobalObject()))63 return true;64 message = crossDomainAccessErrorMessage(exec->lexicalGlobalObject());65 return false;66 }67 68 ALWAYS_INLINE bool JSDOMWindowBase::allowsAccessFromPrivate(const JSGlobalObject* other) const69 {70 const JSDOMWindow* originWindow = asJSDOMWindow(other);71 const JSDOMWindow* targetWindow = m_shell->window();72 73 if (originWindow == targetWindow)74 return true;75 76 const SecurityOrigin* originSecurityOrigin = originWindow->impl()->securityOrigin();77 const SecurityOrigin* targetSecurityOrigin = targetWindow->impl()->securityOrigin();78 79 return originSecurityOrigin->canAccess(targetSecurityOrigin);80 }81 82 39 } 83 40 -
trunk/Source/WebCore/bindings/js/JSInjectedScriptManager.cpp
r121381 r125146 37 37 #include "InjectedScriptManager.h" 38 38 39 #include "BindingSecurity.h" 39 40 #include "ExceptionCode.h" 40 41 #include "JSDOMWindow.h" … … 86 87 if (!inspectedWindow) 87 88 return false; 88 return inspectedWindow->allowsAccessFromNoErrorMessage(scriptState);89 return BindingSecurity::shouldAllowAccessToFrame(scriptState, inspectedWindow->impl()->frame(), DoNotReportSecurityError); 89 90 } 90 91 -
trunk/Source/WebCore/bindings/objc/WebScriptObject.mm
r122635 r125146 242 242 return false; 243 243 244 return jsCast<JSDOMWindowBase*>(root->globalObject())->allowsAccessFrom(_private->originRootObject->globalObject()); 244 // It's not actually correct to call shouldAllowAccessToFrame in this way because 245 // JSDOMWindowBase* isn't the right object to represent the currently executing 246 // JavaScript. Instead, we should use ExecState, like we do elsewhere. 247 JSDOMWindowBase* target = jsCast<JSDOMWindowBase*>(root->globalObject()); 248 return shouldAllowAccessToFrame(_private->originRootObject->globalObject()->globalExec(), target->impl()->frame()); 245 249 } 246 250 -
trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
r125042 r125146 486 486 my @getOwnPropertyDescriptorImpl = (); 487 487 if ($dataNode->extendedAttributes->{"CheckSecurity"}) { 488 if ($interfaceName eq "DOMWindow") { 489 push(@implContent, " if (!thisObject->allowsAccessFrom(exec))\n"); 490 } else { 491 push(@implContent, " if (!shouldAllowAccessToFrame(exec, thisObject->impl()->frame()))\n"); 492 } 488 push(@implContent, " if (!shouldAllowAccessToFrame(exec, thisObject->impl()->frame()))\n"); 493 489 push(@implContent, " return false;\n"); 494 490 } … … 1781 1777 !$attribute->signature->extendedAttributes->{"DoNotCheckSecurity"} && 1782 1778 !$attribute->signature->extendedAttributes->{"DoNotCheckSecurityOnGetter"}) { 1783 push(@implContent, " if (! castedThis->allowsAccessFrom(exec))\n");1779 push(@implContent, " if (!shouldAllowAccessToFrame(exec, castedThis->impl()->frame()))\n"); 1784 1780 push(@implContent, " return jsUndefined();\n"); 1785 1781 } … … 1896 1892 1897 1893 if ($dataNode->extendedAttributes->{"CheckSecurity"}) { 1898 push(@implContent, " if (! domObject->allowsAccessFrom(exec))\n");1894 push(@implContent, " if (!shouldAllowAccessToFrame(exec, domObject->impl()->frame()))\n"); 1899 1895 push(@implContent, " return jsUndefined();\n"); 1900 1896 } … … 1970 1966 1971 1967 if ($dataNode->extendedAttributes->{"CheckSecurity"} && !$attribute->signature->extendedAttributes->{"DoNotCheckSecurity"}) { 1972 if ($interfaceName eq "DOMWindow") { 1973 push(@implContent, " if (!jsCast<$className*>(thisObject)->allowsAccessFrom(exec))\n"); 1974 } else { 1975 push(@implContent, " if (!shouldAllowAccessToFrame(exec, jsCast<$className*>(thisObject)->impl()->frame()))\n"); 1976 } 1968 push(@implContent, " if (!shouldAllowAccessToFrame(exec, jsCast<$className*>(thisObject)->impl()->frame()))\n"); 1977 1969 push(@implContent, " return;\n"); 1978 1970 } … … 2099 2091 push(@implContent, "{\n"); 2100 2092 if ($dataNode->extendedAttributes->{"CheckSecurity"}) { 2101 if ($interfaceName eq "DOMWindow") { 2102 push(@implContent, " if (!jsCast<$className*>(thisObject)->allowsAccessFrom(exec))\n"); 2103 } else { 2104 push(@implContent, " if (!shouldAllowAccessToFrame(exec, jsCast<$className*>(thisObject)->impl()->frame()))\n"); 2105 } 2093 push(@implContent, " if (!shouldAllowAccessToFrame(exec, jsCast<$className*>(thisObject)->impl()->frame()))\n"); 2106 2094 push(@implContent, " return;\n"); 2107 2095 } … … 2207 2195 if ($dataNode->extendedAttributes->{"CheckSecurity"} and 2208 2196 !$function->signature->extendedAttributes->{"DoNotCheckSecurity"}) { 2209 push(@implContent, " if (! castedThis->allowsAccessFrom(exec))\n");2197 push(@implContent, " if (!shouldAllowAccessToFrame(exec, castedThis->impl()->frame()))\n"); 2210 2198 push(@implContent, " return JSValue::encode(jsUndefined());\n"); 2211 2199 } -
trunk/Source/WebCore/bindings/scripts/test/JS/JSTestActiveDOMObject.cpp
r118651 r125146 154 154 { 155 155 JSTestActiveDOMObject* castedThis = jsCast<JSTestActiveDOMObject*>(asObject(slotBase)); 156 if (! castedThis->allowsAccessFrom(exec))156 if (!shouldAllowAccessToFrame(exec, castedThis->impl()->frame())) 157 157 return jsUndefined(); 158 158 UNUSED_PARAM(exec); … … 166 166 { 167 167 JSTestActiveDOMObject* domObject = jsCast<JSTestActiveDOMObject*>(asObject(slotBase)); 168 if (! domObject->allowsAccessFrom(exec))168 if (!shouldAllowAccessToFrame(exec, domObject->impl()->frame())) 169 169 return jsUndefined(); 170 170 return JSTestActiveDOMObject::getConstructor(exec, domObject->globalObject()); … … 183 183 JSTestActiveDOMObject* castedThis = jsCast<JSTestActiveDOMObject*>(asObject(thisValue)); 184 184 ASSERT_GC_OBJECT_INHERITS(castedThis, &JSTestActiveDOMObject::s_info); 185 if (! castedThis->allowsAccessFrom(exec))185 if (!shouldAllowAccessToFrame(exec, castedThis->impl()->frame())) 186 186 return JSValue::encode(jsUndefined()); 187 187 TestActiveDOMObject* impl = static_cast<TestActiveDOMObject*>(castedThis->impl());
Note: See TracChangeset
for help on using the changeset viewer.