1/* 2 * Copyright (C) 2009 Google 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 are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "config.h" 32#include "bindings/v8/DOMWrapperWorld.h" 33 34#include "V8Window.h" 35#include "bindings/v8/DOMDataStore.h" 36#include "bindings/v8/V8Binding.h" 37#include "bindings/v8/V8DOMActivityLogger.h" 38#include "bindings/v8/V8DOMWrapper.h" 39#include "bindings/v8/WrapperTypeInfo.h" 40#include "core/dom/ScriptExecutionContext.h" 41#include "wtf/HashTraits.h" 42#include "wtf/MainThread.h" 43#include "wtf/StdLibExtras.h" 44 45namespace WebCore { 46 47int DOMWrapperWorld::isolatedWorldCount = 0; 48static bool initializingWindow = false; 49 50void DOMWrapperWorld::setInitializingWindow(bool initializing) 51{ 52 initializingWindow = initializing; 53} 54 55PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::createMainWorld() 56{ 57 return adoptRef(new DOMWrapperWorld(mainWorldId, mainWorldExtensionGroup)); 58} 59 60DOMWrapperWorld::DOMWrapperWorld(int worldId, int extensionGroup) 61 : m_worldId(worldId) 62 , m_extensionGroup(extensionGroup) 63{ 64 if (isIsolatedWorld()) 65 m_domDataStore = adoptPtr(new DOMDataStore(IsolatedWorld)); 66} 67 68DOMWrapperWorld* DOMWrapperWorld::current() 69{ 70 ASSERT(v8::Context::InContext()); 71 v8::Handle<v8::Context> context = v8::Context::GetCurrent(); 72 if (!V8DOMWrapper::isWrapperOfType(toInnerGlobalObject(context), &V8Window::info)) 73 return 0; 74 ASSERT(isMainThread()); 75 if (DOMWrapperWorld* world = isolatedWorld(context)) 76 return world; 77 return mainThreadNormalWorld(); 78} 79 80DOMWrapperWorld* mainThreadNormalWorld() 81{ 82 ASSERT(isMainThread()); 83 DEFINE_STATIC_LOCAL(RefPtr<DOMWrapperWorld>, cachedNormalWorld, (DOMWrapperWorld::createMainWorld())); 84 return cachedNormalWorld.get(); 85} 86 87// FIXME: Remove this function. There is currently an issue with the inspector related to the call to dispatchDidClearWindowObjectInWorld in ScriptController::windowShell. 88DOMWrapperWorld* existingWindowShellWorkaroundWorld() 89{ 90 DEFINE_STATIC_LOCAL(RefPtr<DOMWrapperWorld>, world, (adoptRef(new DOMWrapperWorld(DOMWrapperWorld::mainWorldId - 1, DOMWrapperWorld::mainWorldExtensionGroup - 1)))); 91 return world.get(); 92} 93 94bool DOMWrapperWorld::contextHasCorrectPrototype(v8::Handle<v8::Context> context) 95{ 96 ASSERT(isMainThread()); 97 if (initializingWindow) 98 return true; 99 return V8DOMWrapper::isWrapperOfType(toInnerGlobalObject(context), &V8Window::info); 100} 101 102void DOMWrapperWorld::setIsolatedWorldField(v8::Handle<v8::Context> context) 103{ 104 context->SetAlignedPointerInEmbedderData(v8ContextIsolatedWorld, isMainWorld() ? 0 : this); 105} 106 107typedef HashMap<int, DOMWrapperWorld*> WorldMap; 108static WorldMap& isolatedWorldMap() 109{ 110 ASSERT(isMainThread()); 111 DEFINE_STATIC_LOCAL(WorldMap, map, ()); 112 return map; 113} 114 115void DOMWrapperWorld::getAllWorlds(Vector<RefPtr<DOMWrapperWorld> >& worlds) 116{ 117 worlds.append(mainThreadNormalWorld()); 118 WorldMap& isolatedWorlds = isolatedWorldMap(); 119 for (WorldMap::iterator it = isolatedWorlds.begin(); it != isolatedWorlds.end(); ++it) 120 worlds.append(it->value); 121} 122 123DOMWrapperWorld::~DOMWrapperWorld() 124{ 125 ASSERT(!isMainWorld()); 126 127 if (!isIsolatedWorld()) 128 return; 129 130 WorldMap& map = isolatedWorldMap(); 131 WorldMap::iterator i = map.find(m_worldId); 132 if (i == map.end()) { 133 ASSERT_NOT_REACHED(); 134 return; 135 } 136 ASSERT(i->value == this); 137 138 map.remove(i); 139 isolatedWorldCount--; 140 ASSERT(map.size() == isolatedWorldCount); 141} 142 143PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::ensureIsolatedWorld(int worldId, int extensionGroup) 144{ 145 ASSERT(worldId > mainWorldId); 146 147 WorldMap& map = isolatedWorldMap(); 148 WorldMap::AddResult result = map.add(worldId, 0); 149 RefPtr<DOMWrapperWorld> world = result.iterator->value; 150 if (world) { 151 ASSERT(world->worldId() == worldId); 152 ASSERT(world->extensionGroup() == extensionGroup); 153 return world.release(); 154 } 155 156 world = adoptRef(new DOMWrapperWorld(worldId, extensionGroup)); 157 result.iterator->value = world.get(); 158 isolatedWorldCount++; 159 ASSERT(map.size() == isolatedWorldCount); 160 161 return world.release(); 162} 163 164typedef HashMap<int, RefPtr<SecurityOrigin> > IsolatedWorldSecurityOriginMap; 165static IsolatedWorldSecurityOriginMap& isolatedWorldSecurityOrigins() 166{ 167 ASSERT(isMainThread()); 168 DEFINE_STATIC_LOCAL(IsolatedWorldSecurityOriginMap, map, ()); 169 return map; 170} 171 172SecurityOrigin* DOMWrapperWorld::isolatedWorldSecurityOrigin() 173{ 174 ASSERT(this->isIsolatedWorld()); 175 IsolatedWorldSecurityOriginMap& origins = isolatedWorldSecurityOrigins(); 176 IsolatedWorldSecurityOriginMap::iterator it = origins.find(worldId()); 177 return it == origins.end() ? 0 : it->value.get(); 178} 179 180void DOMWrapperWorld::setIsolatedWorldSecurityOrigin(int worldID, PassRefPtr<SecurityOrigin> securityOrigin) 181{ 182 ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); 183 if (securityOrigin) 184 isolatedWorldSecurityOrigins().set(worldID, securityOrigin); 185 else 186 isolatedWorldSecurityOrigins().remove(worldID); 187} 188 189void DOMWrapperWorld::clearIsolatedWorldSecurityOrigin(int worldID) 190{ 191 ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); 192 isolatedWorldSecurityOrigins().remove(worldID); 193} 194 195typedef HashMap<int, bool> IsolatedWorldContentSecurityPolicyMap; 196static IsolatedWorldContentSecurityPolicyMap& isolatedWorldContentSecurityPolicies() 197{ 198 ASSERT(isMainThread()); 199 DEFINE_STATIC_LOCAL(IsolatedWorldContentSecurityPolicyMap, map, ()); 200 return map; 201} 202 203bool DOMWrapperWorld::isolatedWorldHasContentSecurityPolicy() 204{ 205 ASSERT(this->isIsolatedWorld()); 206 IsolatedWorldContentSecurityPolicyMap& policies = isolatedWorldContentSecurityPolicies(); 207 IsolatedWorldContentSecurityPolicyMap::iterator it = policies.find(worldId()); 208 return it == policies.end() ? false : it->value; 209} 210 211void DOMWrapperWorld::setIsolatedWorldContentSecurityPolicy(int worldID, const String& policy) 212{ 213 ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); 214 if (!policy.isEmpty()) 215 isolatedWorldContentSecurityPolicies().set(worldID, true); 216 else 217 isolatedWorldContentSecurityPolicies().remove(worldID); 218} 219 220void DOMWrapperWorld::clearIsolatedWorldContentSecurityPolicy(int worldID) 221{ 222 ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); 223 isolatedWorldContentSecurityPolicies().remove(worldID); 224} 225 226typedef HashMap<int, OwnPtr<V8DOMActivityLogger>, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int> > DOMActivityLoggerMap; 227static DOMActivityLoggerMap& domActivityLoggers() 228{ 229 ASSERT(isMainThread()); 230 DEFINE_STATIC_LOCAL(DOMActivityLoggerMap, map, ()); 231 return map; 232} 233 234void DOMWrapperWorld::setActivityLogger(int worldId, PassOwnPtr<V8DOMActivityLogger> logger) 235{ 236 domActivityLoggers().set(worldId, logger); 237} 238 239V8DOMActivityLogger* DOMWrapperWorld::activityLogger(int worldId) 240{ 241 DOMActivityLoggerMap& loggers = domActivityLoggers(); 242 DOMActivityLoggerMap::iterator it = loggers.find(worldId); 243 return it == loggers.end() ? 0 : it->value.get(); 244} 245 246} // namespace WebCore 247