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 "WebKit.h" 33 34 #include "IDBFactoryBackendProxy.h" 35 #include "RuntimeEnabledFeatures.h" 36 #include "WebMediaPlayerClientImpl.h" 37 #include "bindings/v8/V8Binding.h" 38 #include "bindings/v8/V8Initializer.h" 39 #include "bindings/v8/V8RecursionScope.h" 40 #include "core/Init.h" 41 #include "core/dom/Microtask.h" 42 #include "core/page/Page.h" 43 #include "core/frame/Settings.h" 44 #include "core/workers/WorkerGlobalScopeProxy.h" 45 #include "platform/LayoutTestSupport.h" 46 #include "platform/Logging.h" 47 #include "platform/graphics/ImageDecodingStore.h" 48 #include "platform/graphics/media/MediaPlayer.h" 49 #include "public/platform/Platform.h" 50 #include "public/platform/WebPrerenderingSupport.h" 51 #include "public/platform/WebThread.h" 52 #include "wtf/Assertions.h" 53 #include "wtf/CryptographicallyRandomNumber.h" 54 #include "wtf/MainThread.h" 55 #include "wtf/WTF.h" 56 #include "wtf/text/AtomicString.h" 57 #include "wtf/text/TextEncoding.h" 58 #include <v8.h> 59 60 namespace blink { 61 62 namespace { 63 64 class EndOfTaskRunner : public WebThread::TaskObserver { 65 public: 66 virtual void willProcessTask() { } 67 virtual void didProcessTask() 68 { 69 WebCore::Microtask::performCheckpoint(); 70 } 71 }; 72 73 } // namespace 74 75 static WebThread::TaskObserver* s_endOfTaskRunner = 0; 76 77 // Make sure we are not re-initialized in the same address space. 78 // Doing so may cause hard to reproduce crashes. 79 static bool s_webKitInitialized = false; 80 81 static bool generateEntropy(unsigned char* buffer, size_t length) 82 { 83 if (Platform::current()) { 84 Platform::current()->cryptographicallyRandomValues(buffer, length); 85 return true; 86 } 87 return false; 88 } 89 90 #ifndef NDEBUG 91 static void assertV8RecursionScope() 92 { 93 ASSERT(!isMainThread() || WebCore::V8RecursionScope::properlyUsed()); 94 } 95 #endif 96 97 void initialize(Platform* platform) 98 { 99 initializeWithoutV8(platform); 100 101 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 102 WebCore::V8Initializer::initializeMainThreadIfNeeded(isolate); 103 v8::V8::SetEntropySource(&generateEntropy); 104 v8::V8::SetArrayBufferAllocator(WebCore::v8ArrayBufferAllocator()); 105 v8::V8::Initialize(); 106 WebCore::setMainThreadIsolate(isolate); 107 WebCore::V8PerIsolateData::ensureInitialized(isolate); 108 109 // currentThread will always be non-null in production, but can be null in Chromium unit tests. 110 if (WebThread* currentThread = platform->currentThread()) { 111 #ifndef NDEBUG 112 v8::V8::AddCallCompletedCallback(&assertV8RecursionScope); 113 #endif 114 ASSERT(!s_endOfTaskRunner); 115 s_endOfTaskRunner = new EndOfTaskRunner; 116 currentThread->addTaskObserver(s_endOfTaskRunner); 117 } 118 } 119 120 v8::Isolate* mainThreadIsolate() 121 { 122 return WebCore::mainThreadIsolate(); 123 } 124 125 static double currentTimeFunction() 126 { 127 return Platform::current()->currentTime(); 128 } 129 130 static double monotonicallyIncreasingTimeFunction() 131 { 132 return Platform::current()->monotonicallyIncreasingTime(); 133 } 134 135 static void cryptographicallyRandomValues(unsigned char* buffer, size_t length) 136 { 137 Platform::current()->cryptographicallyRandomValues(buffer, length); 138 } 139 140 static void callOnMainThreadFunction(WTF::MainThreadFunction function, void* context) 141 { 142 Platform::current()->callOnMainThread(function, context); 143 } 144 145 void initializeWithoutV8(Platform* platform) 146 { 147 ASSERT(!s_webKitInitialized); 148 s_webKitInitialized = true; 149 150 ASSERT(platform); 151 Platform::initialize(platform); 152 153 WTF::setRandomSource(cryptographicallyRandomValues); 154 WTF::initialize(currentTimeFunction, monotonicallyIncreasingTimeFunction); 155 WTF::initializeMainThread(callOnMainThreadFunction); 156 WebCore::init(); 157 WebCore::ImageDecodingStore::initializeOnce(); 158 159 // There are some code paths (for example, running WebKit in the browser 160 // process and calling into LocalStorage before anything else) where the 161 // UTF8 string encoding tables are used on a background thread before 162 // they're set up. This is a problem because their set up routines assert 163 // they're running on the main WebKitThread. It might be possible to make 164 // the initialization thread-safe, but given that so many code paths use 165 // this, initializing this lazily probably doesn't buy us much. 166 WTF::UTF8Encoding(); 167 168 WebCore::setIDBFactoryBackendInterfaceCreateFunction(blink::IDBFactoryBackendProxy::create); 169 170 WebCore::MediaPlayer::setMediaEngineCreateFunction(blink::WebMediaPlayerClientImpl::create); 171 } 172 173 void shutdown() 174 { 175 // currentThread will always be non-null in production, but can be null in Chromium unit tests. 176 if (Platform::current()->currentThread()) { 177 ASSERT(s_endOfTaskRunner); 178 #ifndef NDEBUG 179 v8::V8::RemoveCallCompletedCallback(&assertV8RecursionScope); 180 #endif 181 Platform::current()->currentThread()->removeTaskObserver(s_endOfTaskRunner); 182 delete s_endOfTaskRunner; 183 s_endOfTaskRunner = 0; 184 } 185 186 WebCore::V8PerIsolateData::dispose(WebCore::mainThreadIsolate()); 187 WebCore::setMainThreadIsolate(0); 188 v8::V8::Dispose(); 189 190 shutdownWithoutV8(); 191 } 192 193 void shutdownWithoutV8() 194 { 195 ASSERT(!s_endOfTaskRunner); 196 WebCore::ImageDecodingStore::shutdown(); 197 WebCore::shutdown(); 198 WTF::shutdown(); 199 Platform::shutdown(); 200 WebPrerenderingSupport::shutdown(); 201 } 202 203 void setLayoutTestMode(bool value) 204 { 205 WebCore::setIsRunningLayoutTest(value); 206 } 207 208 bool layoutTestMode() 209 { 210 return WebCore::isRunningLayoutTest(); 211 } 212 213 void enableLogChannel(const char* name) 214 { 215 #if !LOG_DISABLED 216 WTFLogChannel* channel = WebCore::getChannelFromName(name); 217 if (channel) 218 channel->state = WTFLogChannelOn; 219 #endif // !LOG_DISABLED 220 } 221 222 void resetPluginCache(bool reloadPages) 223 { 224 WebCore::Page::refreshPlugins(reloadPages); 225 } 226 227 } // namespace blink 228