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
62namespace WebKit {
63
64namespace {
65
66class EndOfTaskRunner : public WebThread::TaskObserver {
67public:
68    virtual void willProcessTask() { }
69    virtual void didProcessTask()
70    {
71        WebCore::Microtask::performCheckpoint();
72    }
73};
74
75} // namespace
76
77static 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.
81static bool s_webKitInitialized = false;
82
83static 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
93static void assertV8RecursionScope()
94{
95    ASSERT(!isMainThread() || WebCore::V8RecursionScope::properlyUsed());
96}
97#endif
98
99void 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
121static double currentTimeFunction()
122{
123    return Platform::current()->currentTime();
124}
125
126static double monotonicallyIncreasingTimeFunction()
127{
128    return Platform::current()->monotonicallyIncreasingTime();
129}
130
131static void cryptographicallyRandomValues(unsigned char* buffer, size_t length)
132{
133    Platform::current()->cryptographicallyRandomValues(buffer, length);
134}
135
136static void callOnMainThreadFunction(WTF::MainThreadFunction function, void* context)
137{
138    Platform::current()->callOnMainThread(function, context);
139}
140
141void 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
172void 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
191void shutdownWithoutV8()
192{
193    ASSERT(!s_endOfTaskRunner);
194    WebCore::ImageDecodingStore::shutdown();
195    WebCore::shutdown();
196    WTF::shutdown();
197    Platform::shutdown();
198    WebPrerenderingSupport::shutdown();
199}
200
201void setLayoutTestMode(bool value)
202{
203    WebCore::setIsRunningLayoutTest(value);
204}
205
206bool layoutTestMode()
207{
208    return WebCore::isRunningLayoutTest();
209}
210
211void 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
222void resetPluginCache(bool reloadPages)
223{
224    WebCore::Page::refreshPlugins(reloadPages);
225}
226
227} // namespace WebKit
228