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/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