1 /* 2 * Copyright 2009, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #define LOG_TAG "webcoreglue" 27 28 #include "config.h" 29 30 #include "BackForwardList.h" 31 #include "ChromeClientAndroid.h" 32 #include "ContextMenuClientAndroid.h" 33 #include "CookieClient.h" 34 #include "DragClientAndroid.h" 35 #include "EditorClientAndroid.h" 36 #include "Frame.h" 37 #include "FrameLoader.h" 38 #include "FrameLoaderClientAndroid.h" 39 #include "FrameView.h" 40 #include "GraphicsContext.h" 41 #include "HistoryItem.h" 42 #include "InspectorClientAndroid.h" 43 #include "IntRect.h" 44 #include "JavaSharedClient.h" 45 #include "Page.h" 46 #include "PlatformGraphicsContext.h" 47 #include "ResourceRequest.h" 48 #include "ScriptController.h" 49 #include "SecurityOrigin.h" 50 #include "SelectionController.h" 51 #include "Settings.h" 52 #include "SharedBuffer.h" 53 #include "SkBitmap.h" 54 #include "SkCanvas.h" 55 #include "SkImageEncoder.h" 56 #include "SubstituteData.h" 57 #include "TimerClient.h" 58 #include "TextEncoding.h" 59 #include "WebCoreViewBridge.h" 60 #include "WebFrameView.h" 61 #include "WebViewCore.h" 62 #include "benchmark/Intercept.h" 63 #include "benchmark/MyJavaVM.h" 64 65 #include <JNIUtility.h> 66 #include <jni.h> 67 #include <utils/Log.h> 68 69 namespace android { 70 71 extern int register_webframe(JNIEnv*); 72 extern int register_javabridge(JNIEnv*); 73 extern int register_resource_loader(JNIEnv*); 74 extern int register_webviewcore(JNIEnv*); 75 extern int register_webhistory(JNIEnv*); 76 extern int register_webicondatabase(JNIEnv*); 77 extern int register_websettings(JNIEnv*); 78 extern int register_webview(JNIEnv*); 79 #if ENABLE(DATABASE) 80 extern int register_webstorage(JNIEnv*); 81 #endif 82 extern int register_geolocation_permissions(JNIEnv*); 83 extern int register_mock_geolocation(JNIEnv*); 84 #if ENABLE(VIDEO) 85 extern int register_mediaplayer_audio(JNIEnv*); 86 extern int register_mediaplayer_video(JNIEnv*); 87 #endif 88 89 } 90 91 struct RegistrationMethod { 92 const char* name; 93 int (*func)(JNIEnv*); 94 }; 95 96 static RegistrationMethod gWebCoreRegMethods[] = { 97 { "JavaBridge", android::register_javabridge }, 98 { "WebFrame", android::register_webframe }, 99 { "WebCoreResourceLoader", android::register_resource_loader }, 100 { "WebViewCore", android::register_webviewcore }, 101 { "WebHistory", android::register_webhistory }, 102 { "WebIconDatabase", android::register_webicondatabase }, 103 { "WebSettings", android::register_websettings }, 104 #if ENABLE(DATABASE) 105 { "WebStorage", android::register_webstorage }, 106 #endif 107 { "WebView", android::register_webview }, 108 { "GeolocationPermissions", android::register_geolocation_permissions }, 109 { "MockGeolocation", android::register_mock_geolocation }, 110 #if ENABLE(VIDEO) 111 { "HTML5Audio", android::register_mediaplayer_audio }, 112 { "HTML5VideoViewProxy", android::register_mediaplayer_video }, 113 #endif 114 }; 115 116 EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) 117 { 118 // Save the JavaVM pointer for use globally. 119 JSC::Bindings::setJavaVM(vm); 120 121 JNIEnv* env = NULL; 122 jint result = -1; 123 124 if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { 125 LOGE("GetEnv failed!"); 126 return result; 127 } 128 LOG_ASSERT(env, "Could not retrieve the env!"); 129 130 const RegistrationMethod* method = gWebCoreRegMethods; 131 const RegistrationMethod* end = method + sizeof(gWebCoreRegMethods)/sizeof(RegistrationMethod); 132 while (method != end) { 133 if (method->func(env) < 0) { 134 LOGE("%s registration failed!", method->name); 135 return result; 136 } 137 method++; 138 } 139 140 // Initialize rand() function. The rand() function is used in 141 // FileSystemAndroid to create a random temporary filename. 142 srand(time(NULL)); 143 144 return JNI_VERSION_1_4; 145 } 146 147 class MyJavaSharedClient : public TimerClient, public CookieClient { 148 public: 149 MyJavaSharedClient() : m_hasTimer(false) {} 150 virtual void setSharedTimer(long long timemillis) { m_hasTimer = true; } 151 virtual void stopSharedTimer() { m_hasTimer = false; } 152 virtual void setSharedTimerCallback(void (*f)()) { m_func = f; } 153 virtual void signalServiceFuncPtrQueue() {} 154 155 // Cookie methods that do nothing. 156 virtual void setCookies(const KURL&, const String&) {} 157 virtual String cookies(const KURL&) { return ""; } 158 virtual bool cookiesEnabled() { return false; } 159 160 bool m_hasTimer; 161 void (*m_func)(); 162 }; 163 164 static void historyItemChanged(HistoryItem* i) { 165 if (i->bridge()) 166 i->bridge()->updateHistoryItem(i); 167 } 168 169 namespace android { 170 171 EXPORT void benchmark(const char* url, int reloadCount, int width, int height) { 172 ScriptController::initializeThreading(); 173 174 // Setting this allows data: urls to load from a local file. 175 SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForAll); 176 177 // Create the fake JNIEnv and JavaVM 178 InitializeJavaVM(); 179 180 // The real function is private to libwebcore but we know what it does. 181 notifyHistoryItemChanged = historyItemChanged; 182 183 // Implement the shared timer callback 184 MyJavaSharedClient client; 185 JavaSharedClient::SetTimerClient(&client); 186 JavaSharedClient::SetCookieClient(&client); 187 188 // Create the page with all the various clients 189 ChromeClientAndroid* chrome = new ChromeClientAndroid; 190 EditorClientAndroid* editor = new EditorClientAndroid; 191 Page* page = new Page(chrome, 192 new ContextMenuClientAndroid, 193 editor, 194 new DragClientAndroid, 195 new InspectorClientAndroid, 196 0, // PluginHalterClient 197 0); // GeolocationControllerClient 198 editor->setPage(page); 199 200 // Create MyWebFrame that intercepts network requests 201 MyWebFrame* webFrame = new MyWebFrame(page); 202 webFrame->setUserAgent("Performance testing"); // needs to be non-empty 203 chrome->setWebFrame(webFrame); 204 // ChromeClientAndroid maintains the reference. 205 Release(webFrame); 206 207 // Create the Frame and the FrameLoaderClient 208 FrameLoaderClientAndroid* loader = new FrameLoaderClientAndroid(webFrame); 209 RefPtr<Frame> frame = Frame::create(page, NULL, loader); 210 loader->setFrame(frame.get()); 211 212 // Build our View system, resize it to the given dimensions and release our 213 // references. Note: We keep a referenec to frameView so we can layout and 214 // draw later without risk of it being deleted. 215 WebViewCore* webViewCore = new WebViewCore(JSC::Bindings::getJNIEnv(), 216 MY_JOBJECT, frame.get()); 217 RefPtr<FrameView> frameView = FrameView::create(frame.get()); 218 WebFrameView* webFrameView = new WebFrameView(frameView.get(), webViewCore); 219 frame->setView(frameView); 220 frameView->resize(width, height); 221 Release(webViewCore); 222 Release(webFrameView); 223 224 // Initialize the frame and turn of low-bandwidth display (it fails an 225 // assertion in the Cache code) 226 frame->init(); 227 frame->selection()->setFocused(true); 228 229 // Set all the default settings the Browser normally uses. 230 Settings* s = frame->settings(); 231 s->setLayoutAlgorithm(Settings::kLayoutNormal); // Normal layout for now 232 s->setStandardFontFamily("sans-serif"); 233 s->setFixedFontFamily("monospace"); 234 s->setSansSerifFontFamily("sans-serif"); 235 s->setSerifFontFamily("serif"); 236 s->setCursiveFontFamily("cursive"); 237 s->setFantasyFontFamily("fantasy"); 238 s->setMinimumFontSize(8); 239 s->setMinimumLogicalFontSize(8); 240 s->setDefaultFontSize(16); 241 s->setDefaultFixedFontSize(13); 242 s->setLoadsImagesAutomatically(true); 243 s->setJavaScriptEnabled(true); 244 s->setDefaultTextEncodingName("latin1"); 245 s->setPluginsEnabled(false); 246 s->setShrinksStandaloneImagesToFit(false); 247 s->setUseWideViewport(false); 248 249 // Finally, load the actual data 250 ResourceRequest req(url); 251 frame->loader()->load(req, false); 252 253 do { 254 // Layout the page and service the timer 255 frame->view()->layout(); 256 while (client.m_hasTimer) { 257 client.m_func(); 258 JavaSharedClient::ServiceFunctionPtrQueue(); 259 } 260 JavaSharedClient::ServiceFunctionPtrQueue(); 261 262 // Layout more if needed. 263 while (frame->view()->needsLayout()) 264 frame->view()->layout(); 265 JavaSharedClient::ServiceFunctionPtrQueue(); 266 267 if (reloadCount) 268 frame->loader()->reload(true); 269 } while (reloadCount--); 270 271 // Draw into an offscreen bitmap 272 SkBitmap bmp; 273 bmp.setConfig(SkBitmap::kARGB_8888_Config, width, height); 274 bmp.allocPixels(); 275 SkCanvas canvas(bmp); 276 PlatformGraphicsContext ctx(&canvas, NULL); 277 GraphicsContext gc(&ctx); 278 frame->view()->paintContents(&gc, IntRect(0, 0, width, height)); 279 280 // Write the bitmap to the sdcard 281 SkImageEncoder* enc = SkImageEncoder::Create(SkImageEncoder::kPNG_Type); 282 enc->encodeFile("/sdcard/webcore_test.png", bmp, 100); 283 delete enc; 284 285 // Tear down the world. 286 frame->loader()->detachFromParent(); 287 delete page; 288 } 289 290 } // namespace android 291