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