Home | History | Annotate | Download | only in v8
      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