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 67namespace blink { 68 69namespace { 70 71class EndOfTaskRunner : public WebThread::TaskObserver { 72public: 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 86static WebThread::TaskObserver* s_endOfTaskRunner = 0; 87static WebThread::TaskObserver* s_pendingGCRunner = 0; 88static ThreadState::Interruptor* s_messageLoopInterruptor = 0; 89static 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. 93static bool s_webKitInitialized = false; 94 95void 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 112v8::Isolate* mainThreadIsolate() 113{ 114 return V8PerIsolateData::mainThreadIsolate(); 115} 116 117static double currentTimeFunction() 118{ 119 return Platform::current()->currentTime(); 120} 121 122static double monotonicallyIncreasingTimeFunction() 123{ 124 return Platform::current()->monotonicallyIncreasingTime(); 125} 126 127static void cryptographicallyRandomValues(unsigned char* buffer, size_t length) 128{ 129 Platform::current()->cryptographicallyRandomValues(buffer, length); 130} 131 132static void callOnMainThreadFunction(WTF::MainThreadFunction function, void* context) 133{ 134 Scheduler::shared()->postTask(FROM_HERE, bind(function, context)); 135} 136 137void 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 180void 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 218void 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 229void setLayoutTestMode(bool value) 230{ 231 LayoutTestSupport::setIsRunningLayoutTest(value); 232} 233 234bool layoutTestMode() 235{ 236 return LayoutTestSupport::isRunningLayoutTest(); 237} 238 239void setFontAntialiasingEnabledForTest(bool value) 240{ 241 LayoutTestSupport::setFontAntialiasingEnabledForTest(value); 242} 243 244bool fontAntialiasingEnabledForTest() 245{ 246 return LayoutTestSupport::isFontAntialiasingEnabledForTest(); 247} 248 249void 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 258void resetPluginCache(bool reloadPages) 259{ 260 Page::refreshPlugins(reloadPages); 261} 262 263} // namespace blink 264