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