Home | History | Annotate | Download | only in web
      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 "public/web/WebKit.h"
     33 
     34 #include "bindings/core/v8/V8Binding.h"
     35 #include "bindings/core/v8/V8GCController.h"
     36 #include "bindings/core/v8/V8Initializer.h"
     37 #include "core/Init.h"
     38 #include "core/animation/AnimationClock.h"
     39 #include "core/dom/Microtask.h"
     40 #include "core/frame/Settings.h"
     41 #include "core/page/Page.h"
     42 #include "core/workers/WorkerGlobalScopeProxy.h"
     43 #include "gin/public/v8_platform.h"
     44 #include "modules/InitModules.h"
     45 #include "platform/LayoutTestSupport.h"
     46 #include "platform/Logging.h"
     47 #include "platform/RuntimeEnabledFeatures.h"
     48 #include "platform/graphics/ImageDecodingStore.h"
     49 #include "platform/graphics/media/MediaPlayer.h"
     50 #include "platform/heap/Heap.h"
     51 #include "platform/heap/glue/MessageLoopInterruptor.h"
     52 #include "platform/heap/glue/PendingGCRunner.h"
     53 #include "platform/scheduler/Scheduler.h"
     54 #include "public/platform/Platform.h"
     55 #include "public/platform/WebPrerenderingSupport.h"
     56 #include "public/platform/WebThread.h"
     57 #include "web/IndexedDBClientImpl.h"
     58 #include "web/WebMediaPlayerClientImpl.h"
     59 #include "wtf/Assertions.h"
     60 #include "wtf/CryptographicallyRandomNumber.h"
     61 #include "wtf/MainThread.h"
     62 #include "wtf/WTF.h"
     63 #include "wtf/text/AtomicString.h"
     64 #include "wtf/text/TextEncoding.h"
     65 #include <v8.h>
     66 
     67 namespace blink {
     68 
     69 namespace {
     70 
     71 class EndOfTaskRunner : public WebThread::TaskObserver {
     72 public:
     73     virtual void willProcessTask() OVERRIDE
     74     {
     75         AnimationClock::notifyTaskStart();
     76     }
     77     virtual void didProcessTask() OVERRIDE
     78     {
     79         Microtask::performCheckpoint();
     80         V8GCController::reportDOMMemoryUsageToV8(mainThreadIsolate());
     81     }
     82 };
     83 
     84 } // namespace
     85 
     86 static WebThread::TaskObserver* s_endOfTaskRunner = 0;
     87 static WebThread::TaskObserver* s_pendingGCRunner = 0;
     88 static ThreadState::Interruptor* s_messageLoopInterruptor = 0;
     89 static ThreadState::Interruptor* s_isolateInterruptor = 0;
     90 
     91 // Make sure we are not re-initialized in the same address space.
     92 // Doing so may cause hard to reproduce crashes.
     93 static bool s_webKitInitialized = false;
     94 
     95 void initialize(Platform* platform)
     96 {
     97     initializeWithoutV8(platform);
     98 
     99     V8Initializer::initializeMainThreadIfNeeded();
    100 
    101     s_isolateInterruptor = new V8IsolateInterruptor(V8PerIsolateData::mainThreadIsolate());
    102     ThreadState::current()->addInterruptor(s_isolateInterruptor);
    103 
    104     // currentThread will always be non-null in production, but can be null in Chromium unit tests.
    105     if (WebThread* currentThread = platform->currentThread()) {
    106         ASSERT(!s_endOfTaskRunner);
    107         s_endOfTaskRunner = new EndOfTaskRunner;
    108         currentThread->addTaskObserver(s_endOfTaskRunner);
    109     }
    110 }
    111 
    112 v8::Isolate* mainThreadIsolate()
    113 {
    114     return V8PerIsolateData::mainThreadIsolate();
    115 }
    116 
    117 static double currentTimeFunction()
    118 {
    119     return Platform::current()->currentTime();
    120 }
    121 
    122 static double monotonicallyIncreasingTimeFunction()
    123 {
    124     return Platform::current()->monotonicallyIncreasingTime();
    125 }
    126 
    127 static void cryptographicallyRandomValues(unsigned char* buffer, size_t length)
    128 {
    129     Platform::current()->cryptographicallyRandomValues(buffer, length);
    130 }
    131 
    132 static void callOnMainThreadFunction(WTF::MainThreadFunction function, void* context)
    133 {
    134     Scheduler::shared()->postTask(FROM_HERE, bind(function, context));
    135 }
    136 
    137 void initializeWithoutV8(Platform* platform)
    138 {
    139     ASSERT(!s_webKitInitialized);
    140     s_webKitInitialized = true;
    141 
    142     ASSERT(platform);
    143     Platform::initialize(platform);
    144 
    145     WTF::setRandomSource(cryptographicallyRandomValues);
    146     WTF::initialize(currentTimeFunction, monotonicallyIncreasingTimeFunction);
    147     WTF::initializeMainThread(callOnMainThreadFunction);
    148     Heap::init();
    149     Scheduler::initializeOnMainThread();
    150 
    151     ThreadState::attachMainThread();
    152     // currentThread will always be non-null in production, but can be null in Chromium unit tests.
    153     if (WebThread* currentThread = platform->currentThread()) {
    154         ASSERT(!s_pendingGCRunner);
    155         s_pendingGCRunner = new PendingGCRunner;
    156         currentThread->addTaskObserver(s_pendingGCRunner);
    157 
    158         ASSERT(!s_messageLoopInterruptor);
    159         s_messageLoopInterruptor = new MessageLoopInterruptor(currentThread);
    160         ThreadState::current()->addInterruptor(s_messageLoopInterruptor);
    161     }
    162 
    163     DEFINE_STATIC_LOCAL(ModulesInitializer, initializer, ());
    164     initializer.init();
    165 
    166     // There are some code paths (for example, running WebKit in the browser
    167     // process and calling into LocalStorage before anything else) where the
    168     // UTF8 string encoding tables are used on a background thread before
    169     // they're set up.  This is a problem because their set up routines assert
    170     // they're running on the main WebKitThread.  It might be possible to make
    171     // the initialization thread-safe, but given that so many code paths use
    172     // this, initializing this lazily probably doesn't buy us much.
    173     WTF::UTF8Encoding();
    174 
    175     setIndexedDBClientCreateFunction(IndexedDBClientImpl::create);
    176 
    177     MediaPlayer::setMediaEngineCreateFunction(WebMediaPlayerClientImpl::create);
    178 }
    179 
    180 void shutdown()
    181 {
    182     // currentThread will always be non-null in production, but can be null in Chromium unit tests.
    183     if (Platform::current()->currentThread()) {
    184         // We don't need to (cannot) remove s_endOfTaskRunner from the current
    185         // message loop, because the message loop is already destructed before
    186         // the shutdown() is called.
    187         delete s_endOfTaskRunner;
    188         s_endOfTaskRunner = 0;
    189     }
    190 
    191     ASSERT(s_isolateInterruptor);
    192     ThreadState::current()->removeInterruptor(s_isolateInterruptor);
    193 
    194     // currentThread will always be non-null in production, but can be null in Chromium unit tests.
    195     if (Platform::current()->currentThread()) {
    196         ASSERT(s_pendingGCRunner);
    197         delete s_pendingGCRunner;
    198         s_pendingGCRunner = 0;
    199 
    200         ASSERT(s_messageLoopInterruptor);
    201         ThreadState::current()->removeInterruptor(s_messageLoopInterruptor);
    202         delete s_messageLoopInterruptor;
    203         s_messageLoopInterruptor = 0;
    204     }
    205 
    206     v8::Isolate* isolate = V8PerIsolateData::mainThreadIsolate();
    207     V8PerIsolateData::willBeDestroyed(isolate);
    208 
    209     // Detach the main thread before starting the shutdown sequence
    210     // so that the main thread won't get involved in a GC during the shutdown.
    211     ThreadState::detachMainThread();
    212 
    213     V8PerIsolateData::destroy(isolate);
    214 
    215     shutdownWithoutV8();
    216 }
    217 
    218 void shutdownWithoutV8()
    219 {
    220     ASSERT(!s_endOfTaskRunner);
    221     CoreInitializer::shutdown();
    222     Scheduler::shutdown();
    223     Heap::shutdown();
    224     WTF::shutdown();
    225     Platform::shutdown();
    226     WebPrerenderingSupport::shutdown();
    227 }
    228 
    229 void setLayoutTestMode(bool value)
    230 {
    231     LayoutTestSupport::setIsRunningLayoutTest(value);
    232 }
    233 
    234 bool layoutTestMode()
    235 {
    236     return LayoutTestSupport::isRunningLayoutTest();
    237 }
    238 
    239 void setFontAntialiasingEnabledForTest(bool value)
    240 {
    241     LayoutTestSupport::setFontAntialiasingEnabledForTest(value);
    242 }
    243 
    244 bool fontAntialiasingEnabledForTest()
    245 {
    246     return LayoutTestSupport::isFontAntialiasingEnabledForTest();
    247 }
    248 
    249 void enableLogChannel(const char* name)
    250 {
    251 #if !LOG_DISABLED
    252     WTFLogChannel* channel = getChannelFromName(name);
    253     if (channel)
    254         channel->state = WTFLogChannelOn;
    255 #endif // !LOG_DISABLED
    256 }
    257 
    258 void resetPluginCache(bool reloadPages)
    259 {
    260     Page::refreshPlugins(reloadPages);
    261 }
    262 
    263 } // namespace blink
    264