/* * Copyright (C) 2008 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "JSInspectedObjectWrapper.h" #include "JSInspectorCallbackWrapper.h" #include #include using namespace JSC; namespace WebCore { ASSERT_CLASS_FITS_IN_CELL(JSInspectedObjectWrapper); typedef HashMap WrapperMap; typedef HashMap GlobalObjectWrapperMap; static GlobalObjectWrapperMap& wrappers() { DEFINE_STATIC_LOCAL(GlobalObjectWrapperMap, map, ()); return map; } const ClassInfo JSInspectedObjectWrapper::s_info = { "JSInspectedObjectWrapper", &JSQuarantinedObjectWrapper::s_info, 0, 0 }; JSValuePtr JSInspectedObjectWrapper::wrap(ExecState* unwrappedExec, JSValuePtr unwrappedValue) { if (!unwrappedValue.isObject()) return unwrappedValue; JSObject* unwrappedObject = asObject(unwrappedValue); if (unwrappedObject->inherits(&JSInspectedObjectWrapper::s_info)) return unwrappedObject; if (WrapperMap* wrapperMap = wrappers().get(unwrappedExec->lexicalGlobalObject())) if (JSInspectedObjectWrapper* wrapper = wrapperMap->get(unwrappedObject)) return wrapper; JSValuePtr prototype = unwrappedObject->prototype(); ASSERT(prototype.isNull() || prototype.isObject()); if (prototype.isNull()) return new (unwrappedExec) JSInspectedObjectWrapper(unwrappedExec, unwrappedObject, JSQuarantinedObjectWrapper::createStructure(jsNull())); return new (unwrappedExec) JSInspectedObjectWrapper(unwrappedExec, unwrappedObject, JSQuarantinedObjectWrapper::createStructure(asObject(wrap(unwrappedExec, prototype)))); } JSInspectedObjectWrapper::JSInspectedObjectWrapper(ExecState* unwrappedExec, JSObject* unwrappedObject, PassRefPtr structure) : JSQuarantinedObjectWrapper(unwrappedExec, unwrappedObject, structure) { WrapperMap* wrapperMap = wrappers().get(unwrappedGlobalObject()); if (!wrapperMap) { wrapperMap = new WrapperMap; wrappers().set(unwrappedGlobalObject(), wrapperMap); } ASSERT(!wrapperMap->contains(unwrappedObject)); wrapperMap->set(unwrappedObject, this); } JSInspectedObjectWrapper::~JSInspectedObjectWrapper() { ASSERT(wrappers().contains(unwrappedGlobalObject())); WrapperMap* wrapperMap = wrappers().get(unwrappedGlobalObject()); ASSERT(wrapperMap->contains(unwrappedObject())); wrapperMap->remove(unwrappedObject()); if (wrapperMap->isEmpty()) { wrappers().remove(unwrappedGlobalObject()); delete wrapperMap; } } JSValuePtr JSInspectedObjectWrapper::prepareIncomingValue(ExecState*, JSValuePtr value) const { // The Inspector is only allowed to pass primitive values and wrapped objects to objects from the inspected page. if (!value.isObject()) return value; JSQuarantinedObjectWrapper* wrapper = asWrapper(value); ASSERT_WITH_MESSAGE(wrapper, "Objects passed to JSInspectedObjectWrapper must be wrapped"); if (!wrapper) return jsUndefined(); if (wrapper->allowsUnwrappedAccessFrom(unwrappedExecState())) { ASSERT_WITH_MESSAGE(wrapper->inherits(&s_info), "A wrapper contains an object from the inspected page but is not a JSInspectedObjectWrapper"); if (!wrapper->inherits(&s_info)) return jsUndefined(); // Return the unwrapped object so the inspected page never sees one of its own objects in wrapped form. return wrapper->unwrappedObject(); } ASSERT_WITH_MESSAGE(wrapper->inherits(&JSInspectorCallbackWrapper::s_info), "A wrapper that was not from the inspected page and is not an Inspector callback was passed to a JSInspectedObjectWrapper"); if (!wrapper->inherits(&JSInspectorCallbackWrapper::s_info)) return jsUndefined(); return wrapper; } } // namespace WebCore