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