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 45 namespace WebCore { 46 47 int DOMWrapperWorld::isolatedWorldCount = 0; 48 static bool initializingWindow = false; 49 50 void DOMWrapperWorld::setInitializingWindow(bool initializing) 51 { 52 initializingWindow = initializing; 53 } 54 55 PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::createMainWorld() 56 { 57 return adoptRef(new DOMWrapperWorld(mainWorldId, mainWorldExtensionGroup)); 58 } 59 60 DOMWrapperWorld::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 68 DOMWrapperWorld* 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 80 DOMWrapperWorld* 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. 88 DOMWrapperWorld* existingWindowShellWorkaroundWorld() 89 { 90 DEFINE_STATIC_LOCAL(RefPtr<DOMWrapperWorld>, world, (adoptRef(new DOMWrapperWorld(DOMWrapperWorld::mainWorldId - 1, DOMWrapperWorld::mainWorldExtensionGroup - 1)))); 91 return world.get(); 92 } 93 94 bool 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 102 void DOMWrapperWorld::setIsolatedWorldField(v8::Handle<v8::Context> context) 103 { 104 context->SetAlignedPointerInEmbedderData(v8ContextIsolatedWorld, isMainWorld() ? 0 : this); 105 } 106 107 typedef HashMap<int, DOMWrapperWorld*> WorldMap; 108 static WorldMap& isolatedWorldMap() 109 { 110 ASSERT(isMainThread()); 111 DEFINE_STATIC_LOCAL(WorldMap, map, ()); 112 return map; 113 } 114 115 void 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 123 DOMWrapperWorld::~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 143 PassRefPtr<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 164 typedef HashMap<int, RefPtr<SecurityOrigin> > IsolatedWorldSecurityOriginMap; 165 static IsolatedWorldSecurityOriginMap& isolatedWorldSecurityOrigins() 166 { 167 ASSERT(isMainThread()); 168 DEFINE_STATIC_LOCAL(IsolatedWorldSecurityOriginMap, map, ()); 169 return map; 170 } 171 172 SecurityOrigin* 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 180 void 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 189 void DOMWrapperWorld::clearIsolatedWorldSecurityOrigin(int worldID) 190 { 191 ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); 192 isolatedWorldSecurityOrigins().remove(worldID); 193 } 194 195 typedef HashMap<int, bool> IsolatedWorldContentSecurityPolicyMap; 196 static IsolatedWorldContentSecurityPolicyMap& isolatedWorldContentSecurityPolicies() 197 { 198 ASSERT(isMainThread()); 199 DEFINE_STATIC_LOCAL(IsolatedWorldContentSecurityPolicyMap, map, ()); 200 return map; 201 } 202 203 bool 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 211 void 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 220 void DOMWrapperWorld::clearIsolatedWorldContentSecurityPolicy(int worldID) 221 { 222 ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); 223 isolatedWorldContentSecurityPolicies().remove(worldID); 224 } 225 226 typedef HashMap<int, OwnPtr<V8DOMActivityLogger>, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int> > DOMActivityLoggerMap; 227 static DOMActivityLoggerMap& domActivityLoggers() 228 { 229 ASSERT(isMainThread()); 230 DEFINE_STATIC_LOCAL(DOMActivityLoggerMap, map, ()); 231 return map; 232 } 233 234 void DOMWrapperWorld::setActivityLogger(int worldId, PassOwnPtr<V8DOMActivityLogger> logger) 235 { 236 domActivityLoggers().set(worldId, logger); 237 } 238 239 V8DOMActivityLogger* 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