1 /* 2 * Copyright (C) 2009 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #include "config.h" 26 #include "WebKitDLL.h" 27 #include "WebScriptWorld.h" 28 29 #include <JavaScriptCore/APICast.h> 30 #include <WebCore/JSDOMBinding.h> 31 #include <WebCore/ScriptController.h> 32 33 using namespace WebCore; 34 35 typedef HashMap<DOMWrapperWorld*, WebScriptWorld*> WorldMap; 36 static WorldMap& allWorlds() 37 { 38 static WorldMap& map = *new WorldMap; 39 return map; 40 } 41 42 inline WebScriptWorld::WebScriptWorld(PassRefPtr<DOMWrapperWorld> world) 43 : m_refCount(0) 44 , m_world(world) 45 { 46 ASSERT_ARG(world, m_world); 47 48 ASSERT_ARG(world, !allWorlds().contains(m_world.get())); 49 allWorlds().add(m_world.get(), this); 50 51 ++gClassCount; 52 gClassNameCount.add("WebScriptWorld"); 53 } 54 55 WebScriptWorld::~WebScriptWorld() 56 { 57 ASSERT(allWorlds().contains(m_world.get())); 58 allWorlds().remove(m_world.get()); 59 60 --gClassCount; 61 gClassNameCount.remove("WebScriptWorld"); 62 } 63 64 WebScriptWorld* WebScriptWorld::standardWorld() 65 { 66 static WebScriptWorld* standardWorld = createInstance(mainThreadNormalWorld()).releaseRef(); 67 return standardWorld; 68 } 69 70 COMPtr<WebScriptWorld> WebScriptWorld::createInstance() 71 { 72 return createInstance(ScriptController::createWorld()); 73 } 74 75 COMPtr<WebScriptWorld> WebScriptWorld::createInstance(PassRefPtr<DOMWrapperWorld> world) 76 { 77 return new WebScriptWorld(world); 78 } 79 80 COMPtr<WebScriptWorld> WebScriptWorld::findOrCreateWorld(DOMWrapperWorld* world) 81 { 82 if (world == mainThreadNormalWorld()) 83 return standardWorld(); 84 85 if (WebScriptWorld* existingWorld = allWorlds().get(world)) 86 return existingWorld; 87 88 return createInstance(world); 89 } 90 91 ULONG WebScriptWorld::AddRef() 92 { 93 return ++m_refCount; 94 } 95 96 ULONG WebScriptWorld::Release() 97 { 98 ULONG newRefCount = --m_refCount; 99 if (!newRefCount) 100 delete this; 101 return newRefCount; 102 } 103 104 HRESULT WebScriptWorld::QueryInterface(REFIID riid, void** ppvObject) 105 { 106 if (!ppvObject) 107 return E_POINTER; 108 *ppvObject = 0; 109 110 if (IsEqualIID(riid, __uuidof(WebScriptWorld))) 111 *ppvObject = this; 112 else if (IsEqualIID(riid, __uuidof(IWebScriptWorld))) 113 *ppvObject = static_cast<IWebScriptWorld*>(this); 114 else if (IsEqualIID(riid, IID_IUnknown)) 115 *ppvObject = static_cast<IUnknown*>(this); 116 else 117 return E_NOINTERFACE; 118 119 AddRef(); 120 return S_OK; 121 } 122 123 HRESULT WebScriptWorld::standardWorld(IWebScriptWorld** outWorld) 124 { 125 if (!outWorld) 126 return E_POINTER; 127 128 *outWorld = standardWorld(); 129 (*outWorld)->AddRef(); 130 return S_OK; 131 } 132 133 HRESULT WebScriptWorld::scriptWorldForGlobalContext(JSGlobalContextRef context, IWebScriptWorld** outWorld) 134 { 135 if (!outWorld) 136 return E_POINTER; 137 return findOrCreateWorld(currentWorld(toJS(context))).copyRefTo(outWorld); 138 } 139 140 HRESULT WebScriptWorld::unregisterWorld() 141 { 142 m_world->clearWrappers(); 143 return S_OK; 144 } 145