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/ScriptController.h" 37 #include "bindings/v8/V8Binding.h" 38 #include "bindings/v8/V8DOMActivityLogger.h" 39 #include "bindings/v8/V8DOMWrapper.h" 40 #include "bindings/v8/V8WindowShell.h" 41 #include "bindings/v8/WrapperTypeInfo.h" 42 #include "core/dom/ExecutionContext.h" 43 #include "wtf/HashTraits.h" 44 #include "wtf/MainThread.h" 45 #include "wtf/StdLibExtras.h" 46 47 namespace WebCore { 48 49 unsigned DOMWrapperWorld::isolatedWorldCount = 0; 50 static bool initializingWindow = false; 51 52 void DOMWrapperWorld::setInitializingWindow(bool initializing) 53 { 54 initializingWindow = initializing; 55 } 56 57 PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::createMainWorld() 58 { 59 return adoptRef(new DOMWrapperWorld(MainWorldId, mainWorldExtensionGroup)); 60 } 61 62 DOMWrapperWorld::DOMWrapperWorld(int worldId, int extensionGroup) 63 : m_worldId(worldId) 64 , m_extensionGroup(extensionGroup) 65 { 66 if (isIsolatedWorld()) 67 m_domDataStore = adoptPtr(new DOMDataStore(IsolatedWorld)); 68 } 69 70 DOMWrapperWorld* DOMWrapperWorld::current() 71 { 72 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 73 ASSERT(isolate->InContext()); 74 v8::Handle<v8::Context> context = isolate->GetCurrentContext(); 75 if (!V8DOMWrapper::isWrapperOfType(toInnerGlobalObject(context), &V8Window::wrapperTypeInfo)) 76 return 0; 77 ASSERT(isMainThread()); 78 if (DOMWrapperWorld* world = isolatedWorld(context)) 79 return world; 80 return mainThreadNormalWorld(); 81 } 82 83 DOMWrapperWorld* mainThreadNormalWorld() 84 { 85 ASSERT(isMainThread()); 86 DEFINE_STATIC_REF(DOMWrapperWorld, cachedNormalWorld, (DOMWrapperWorld::createMainWorld())); 87 return cachedNormalWorld; 88 } 89 90 // FIXME: Remove this function. There is currently an issue with the inspector related to the call to dispatchDidClearWindowObjectInWorld in ScriptController::windowShell. 91 DOMWrapperWorld* existingWindowShellWorkaroundWorld() 92 { 93 DEFINE_STATIC_REF(DOMWrapperWorld, world, (adoptRef(new DOMWrapperWorld(MainWorldId - 1, DOMWrapperWorld::mainWorldExtensionGroup - 1)))); 94 return world; 95 } 96 97 bool DOMWrapperWorld::contextHasCorrectPrototype(v8::Handle<v8::Context> context) 98 { 99 ASSERT(isMainThread()); 100 if (initializingWindow) 101 return true; 102 return V8DOMWrapper::isWrapperOfType(toInnerGlobalObject(context), &V8Window::wrapperTypeInfo); 103 } 104 105 void DOMWrapperWorld::setIsolatedWorldField(v8::Handle<v8::Context> context) 106 { 107 V8PerContextDataHolder::from(context)->setIsolatedWorld(isMainWorld() ? 0 : this); 108 } 109 110 typedef HashMap<int, DOMWrapperWorld*> WorldMap; 111 static WorldMap& isolatedWorldMap() 112 { 113 ASSERT(isMainThread()); 114 DEFINE_STATIC_LOCAL(WorldMap, map, ()); 115 return map; 116 } 117 118 void DOMWrapperWorld::getAllWorlds(Vector<RefPtr<DOMWrapperWorld> >& worlds) 119 { 120 worlds.append(mainThreadNormalWorld()); 121 WorldMap& isolatedWorlds = isolatedWorldMap(); 122 for (WorldMap::iterator it = isolatedWorlds.begin(); it != isolatedWorlds.end(); ++it) 123 worlds.append(it->value); 124 } 125 126 DOMWrapperWorld::~DOMWrapperWorld() 127 { 128 ASSERT(!isMainWorld()); 129 130 if (!isIsolatedWorld()) 131 return; 132 133 WorldMap& map = isolatedWorldMap(); 134 WorldMap::iterator i = map.find(m_worldId); 135 if (i == map.end()) { 136 ASSERT_NOT_REACHED(); 137 return; 138 } 139 ASSERT(i->value == this); 140 141 map.remove(i); 142 isolatedWorldCount--; 143 ASSERT(map.size() == isolatedWorldCount); 144 } 145 146 PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::ensureIsolatedWorld(int worldId, int extensionGroup) 147 { 148 ASSERT(worldId > MainWorldId); 149 150 WorldMap& map = isolatedWorldMap(); 151 WorldMap::AddResult result = map.add(worldId, 0); 152 RefPtr<DOMWrapperWorld> world = result.iterator->value; 153 if (world) { 154 ASSERT(world->worldId() == worldId); 155 ASSERT(world->extensionGroup() == extensionGroup); 156 return world.release(); 157 } 158 159 world = adoptRef(new DOMWrapperWorld(worldId, extensionGroup)); 160 result.iterator->value = world.get(); 161 isolatedWorldCount++; 162 ASSERT(map.size() == isolatedWorldCount); 163 164 return world.release(); 165 } 166 167 v8::Handle<v8::Context> DOMWrapperWorld::context(ScriptController& controller) 168 { 169 return controller.windowShell(this)->context(); 170 } 171 172 typedef HashMap<int, RefPtr<SecurityOrigin> > IsolatedWorldSecurityOriginMap; 173 static IsolatedWorldSecurityOriginMap& isolatedWorldSecurityOrigins() 174 { 175 ASSERT(isMainThread()); 176 DEFINE_STATIC_LOCAL(IsolatedWorldSecurityOriginMap, map, ()); 177 return map; 178 } 179 180 SecurityOrigin* DOMWrapperWorld::isolatedWorldSecurityOrigin() 181 { 182 ASSERT(this->isIsolatedWorld()); 183 IsolatedWorldSecurityOriginMap& origins = isolatedWorldSecurityOrigins(); 184 IsolatedWorldSecurityOriginMap::iterator it = origins.find(worldId()); 185 return it == origins.end() ? 0 : it->value.get(); 186 } 187 188 void DOMWrapperWorld::setIsolatedWorldSecurityOrigin(int worldID, PassRefPtr<SecurityOrigin> securityOrigin) 189 { 190 ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); 191 if (securityOrigin) 192 isolatedWorldSecurityOrigins().set(worldID, securityOrigin); 193 else 194 isolatedWorldSecurityOrigins().remove(worldID); 195 } 196 197 void DOMWrapperWorld::clearIsolatedWorldSecurityOrigin(int worldID) 198 { 199 ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); 200 isolatedWorldSecurityOrigins().remove(worldID); 201 } 202 203 typedef HashMap<int, bool> IsolatedWorldContentSecurityPolicyMap; 204 static IsolatedWorldContentSecurityPolicyMap& isolatedWorldContentSecurityPolicies() 205 { 206 ASSERT(isMainThread()); 207 DEFINE_STATIC_LOCAL(IsolatedWorldContentSecurityPolicyMap, map, ()); 208 return map; 209 } 210 211 bool DOMWrapperWorld::isolatedWorldHasContentSecurityPolicy() 212 { 213 ASSERT(this->isIsolatedWorld()); 214 IsolatedWorldContentSecurityPolicyMap& policies = isolatedWorldContentSecurityPolicies(); 215 IsolatedWorldContentSecurityPolicyMap::iterator it = policies.find(worldId()); 216 return it == policies.end() ? false : it->value; 217 } 218 219 void DOMWrapperWorld::setIsolatedWorldContentSecurityPolicy(int worldID, const String& policy) 220 { 221 ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); 222 if (!policy.isEmpty()) 223 isolatedWorldContentSecurityPolicies().set(worldID, true); 224 else 225 isolatedWorldContentSecurityPolicies().remove(worldID); 226 } 227 228 void DOMWrapperWorld::clearIsolatedWorldContentSecurityPolicy(int worldID) 229 { 230 ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); 231 isolatedWorldContentSecurityPolicies().remove(worldID); 232 } 233 234 typedef HashMap<int, OwnPtr<V8DOMActivityLogger>, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int> > DOMActivityLoggerMap; 235 static DOMActivityLoggerMap& domActivityLoggers() 236 { 237 ASSERT(isMainThread()); 238 DEFINE_STATIC_LOCAL(DOMActivityLoggerMap, map, ()); 239 return map; 240 } 241 242 void DOMWrapperWorld::setActivityLogger(int worldId, PassOwnPtr<V8DOMActivityLogger> logger) 243 { 244 domActivityLoggers().set(worldId, logger); 245 } 246 247 V8DOMActivityLogger* DOMWrapperWorld::activityLogger(int worldId) 248 { 249 DOMActivityLoggerMap& loggers = domActivityLoggers(); 250 DOMActivityLoggerMap::iterator it = loggers.find(worldId); 251 return it == loggers.end() ? 0 : it->value.get(); 252 } 253 254 } // namespace WebCore 255