Home | History | Annotate | Download | only in jni
      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 "DeviceMotionClientAndroid.h"
     35 #include "DeviceOrientationClientAndroid.h"
     36 #include "DragClientAndroid.h"
     37 #include "EditorClientAndroid.h"
     38 #include "FocusController.h"
     39 #include "Frame.h"
     40 #include "FrameLoader.h"
     41 #include "FrameLoaderClientAndroid.h"
     42 #include "FrameView.h"
     43 #include "GraphicsContext.h"
     44 #include "HistoryItem.h"
     45 #include "InspectorClientAndroid.h"
     46 #include "IntRect.h"
     47 #include "JavaSharedClient.h"
     48 #include "Page.h"
     49 #include "PlatformGraphicsContext.h"
     50 #include "ResourceRequest.h"
     51 #include "ScriptController.h"
     52 #include "SecurityOrigin.h"
     53 #include "SelectionController.h"
     54 #include "Settings.h"
     55 #include "SharedBuffer.h"
     56 #include "SkBitmap.h"
     57 #include "SkCanvas.h"
     58 #include "SkImageEncoder.h"
     59 #include "SubstituteData.h"
     60 #include "TimerClient.h"
     61 #include "TextEncoding.h"
     62 #include "WebCoreViewBridge.h"
     63 #include "WebFrameView.h"
     64 #include "WebViewCore.h"
     65 #include "benchmark/Intercept.h"
     66 #include "benchmark/MyJavaVM.h"
     67 
     68 #include <JNIUtility.h>
     69 #include <jni.h>
     70 #include <utils/Log.h>
     71 
     72 #define EXPORT __attribute__((visibility("default")))
     73 
     74 namespace android {
     75 
     76 extern int registerWebFrame(JNIEnv*);
     77 extern int registerJavaBridge(JNIEnv*);
     78 extern int registerJniUtil(JNIEnv*);
     79 extern int registerResourceLoader(JNIEnv*);
     80 extern int registerWebViewCore(JNIEnv*);
     81 extern int registerWebHistory(JNIEnv*);
     82 extern int registerWebIconDatabase(JNIEnv*);
     83 extern int registerWebSettings(JNIEnv*);
     84 extern int registerWebView(JNIEnv*);
     85 extern int registerViewStateSerializer(JNIEnv*);
     86 #if ENABLE(DATABASE)
     87 extern int registerWebStorage(JNIEnv*);
     88 #endif
     89 extern int registerGeolocationPermissions(JNIEnv*);
     90 extern int registerMockGeolocation(JNIEnv*);
     91 #if ENABLE(VIDEO)
     92 extern int registerMediaPlayerAudio(JNIEnv*);
     93 extern int registerMediaPlayerVideo(JNIEnv*);
     94 #endif
     95 extern int registerDeviceMotionAndOrientationManager(JNIEnv*);
     96 extern int registerCookieManager(JNIEnv*);
     97 #if USE(CHROME_NETWORK_STACK)
     98 extern int registerCacheManager(JNIEnv*);
     99 #endif
    100 
    101 }
    102 
    103 struct RegistrationMethod {
    104     const char* name;
    105     int (*func)(JNIEnv*);
    106 };
    107 
    108 static RegistrationMethod gWebCoreRegMethods[] = {
    109     { "JavaBridge", android::registerJavaBridge },
    110     { "JniUtil", android::registerJniUtil },
    111     { "WebFrame", android::registerWebFrame },
    112     { "WebCoreResourceLoader", android::registerResourceLoader },
    113     { "WebViewCore", android::registerWebViewCore },
    114     { "WebHistory", android::registerWebHistory },
    115     { "WebIconDatabase", android::registerWebIconDatabase },
    116     { "WebSettings", android::registerWebSettings },
    117 #if ENABLE(DATABASE)
    118     { "WebStorage", android::registerWebStorage },
    119 #endif
    120     { "WebView", android::registerWebView },
    121     { "ViewStateSerializer", android::registerViewStateSerializer },
    122     { "GeolocationPermissions", android::registerGeolocationPermissions },
    123     { "MockGeolocation", android::registerMockGeolocation },
    124 #if ENABLE(VIDEO)
    125     { "HTML5Audio", android::registerMediaPlayerAudio },
    126     { "HTML5VideoViewProxy", android::registerMediaPlayerVideo },
    127 #endif
    128     { "DeviceMotionAndOrientationManager", android::registerDeviceMotionAndOrientationManager },
    129     { "CookieManager", android::registerCookieManager },
    130 #if USE(CHROME_NETWORK_STACK)
    131     { "CacheManager", android::registerCacheManager },
    132 #endif
    133 };
    134 
    135 EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
    136 {
    137     // Save the JavaVM pointer for use globally.
    138     JSC::Bindings::setJavaVM(vm);
    139 
    140     JNIEnv* env = NULL;
    141     jint result = -1;
    142 
    143     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
    144         LOGE("GetEnv failed!");
    145         return result;
    146     }
    147     LOG_ASSERT(env, "Could not retrieve the env!");
    148 
    149     const RegistrationMethod* method = gWebCoreRegMethods;
    150     const RegistrationMethod* end = method + sizeof(gWebCoreRegMethods)/sizeof(RegistrationMethod);
    151     while (method != end) {
    152         if (method->func(env) < 0) {
    153             LOGE("%s registration failed!", method->name);
    154             return result;
    155         }
    156         method++;
    157     }
    158 
    159     // Initialize rand() function. The rand() function is used in
    160     // FileSystemAndroid to create a random temporary filename.
    161     srand(time(NULL));
    162 
    163     return JNI_VERSION_1_4;
    164 }
    165 
    166 class MyJavaSharedClient : public TimerClient, public CookieClient {
    167 public:
    168     MyJavaSharedClient() : m_hasTimer(false) {}
    169     virtual void setSharedTimer(long long timemillis) { m_hasTimer = true; }
    170     virtual void stopSharedTimer() { m_hasTimer = false; }
    171     virtual void setSharedTimerCallback(void (*f)()) { m_func = f; }
    172     virtual void signalServiceFuncPtrQueue() {}
    173 
    174     // Cookie methods that do nothing.
    175     virtual void setCookies(const KURL&, const String&) {}
    176     virtual String cookies(const KURL&) { return ""; }
    177     virtual bool cookiesEnabled() { return false; }
    178 
    179     bool m_hasTimer;
    180     void (*m_func)();
    181 };
    182 
    183 static void historyItemChanged(HistoryItem* i) {
    184     if (i->bridge())
    185         i->bridge()->updateHistoryItem(i);
    186 }
    187 
    188 namespace android {
    189 
    190 EXPORT void benchmark(const char* url, int reloadCount, int width, int height) {
    191     ScriptController::initializeThreading();
    192 
    193     // Setting this allows data: urls to load from a local file.
    194     SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForAll);
    195 
    196     // Create the fake JNIEnv and JavaVM
    197     InitializeJavaVM();
    198 
    199     // The real function is private to libwebcore but we know what it does.
    200     notifyHistoryItemChanged = historyItemChanged;
    201 
    202     // Implement the shared timer callback
    203     MyJavaSharedClient client;
    204     JavaSharedClient::SetTimerClient(&client);
    205     JavaSharedClient::SetCookieClient(&client);
    206 
    207     // Create the page with all the various clients
    208     ChromeClientAndroid* chrome = new ChromeClientAndroid;
    209     EditorClientAndroid* editor = new EditorClientAndroid;
    210     DeviceMotionClientAndroid* deviceMotion = new DeviceMotionClientAndroid;
    211     DeviceOrientationClientAndroid* deviceOrientation = new DeviceOrientationClientAndroid;
    212     WebCore::Page::PageClients pageClients;
    213     pageClients.chromeClient = chrome;
    214     pageClients.contextMenuClient = new ContextMenuClientAndroid;
    215     pageClients.editorClient = editor;
    216     pageClients.dragClient = new DragClientAndroid;
    217     pageClients.inspectorClient = new InspectorClientAndroid;
    218     pageClients.deviceMotionClient = deviceMotion;
    219     pageClients.deviceOrientationClient = deviceOrientation;
    220     WebCore::Page* page = new WebCore::Page(pageClients);
    221     editor->setPage(page);
    222 
    223     // Create MyWebFrame that intercepts network requests
    224     MyWebFrame* webFrame = new MyWebFrame(page);
    225     webFrame->setUserAgent("Performance testing"); // needs to be non-empty
    226     chrome->setWebFrame(webFrame);
    227     // ChromeClientAndroid maintains the reference.
    228     Release(webFrame);
    229 
    230     // Create the Frame and the FrameLoaderClient
    231     FrameLoaderClientAndroid* loader = new FrameLoaderClientAndroid(webFrame);
    232     RefPtr<Frame> frame = Frame::create(page, NULL, loader);
    233     loader->setFrame(frame.get());
    234 
    235     // Build our View system, resize it to the given dimensions and release our
    236     // references. Note: We keep a referenec to frameView so we can layout and
    237     // draw later without risk of it being deleted.
    238     WebViewCore* webViewCore = new WebViewCore(JSC::Bindings::getJNIEnv(),
    239             MY_JOBJECT, frame.get());
    240     RefPtr<FrameView> frameView = FrameView::create(frame.get());
    241     WebFrameView* webFrameView = new WebFrameView(frameView.get(), webViewCore);
    242     frame->setView(frameView);
    243     frameView->resize(width, height);
    244     Release(webViewCore);
    245     Release(webFrameView);
    246 
    247     // Initialize the frame and turn of low-bandwidth display (it fails an
    248     // assertion in the Cache code)
    249     frame->init();
    250     frame->selection()->setFocused(true);
    251     frame->page()->focusController()->setFocused(true);
    252 
    253     deviceMotion->setWebViewCore(webViewCore);
    254     deviceOrientation->setWebViewCore(webViewCore);
    255 
    256     // Set all the default settings the Browser normally uses.
    257     Settings* s = frame->settings();
    258 #ifdef ANDROID_LAYOUT
    259     s->setLayoutAlgorithm(Settings::kLayoutNormal); // Normal layout for now
    260 #endif
    261     s->setStandardFontFamily("sans-serif");
    262     s->setFixedFontFamily("monospace");
    263     s->setSansSerifFontFamily("sans-serif");
    264     s->setSerifFontFamily("serif");
    265     s->setCursiveFontFamily("cursive");
    266     s->setFantasyFontFamily("fantasy");
    267     s->setMinimumFontSize(8);
    268     s->setMinimumLogicalFontSize(8);
    269     s->setDefaultFontSize(16);
    270     s->setDefaultFixedFontSize(13);
    271     s->setLoadsImagesAutomatically(true);
    272     s->setJavaScriptEnabled(true);
    273     s->setDefaultTextEncodingName("latin1");
    274     s->setPluginsEnabled(false);
    275     s->setShrinksStandaloneImagesToFit(false);
    276 #ifdef ANDROID_LAYOUT
    277     s->setUseWideViewport(false);
    278 #endif
    279 
    280     // Finally, load the actual data
    281     ResourceRequest req(url);
    282     frame->loader()->load(req, false);
    283 
    284     do {
    285         // Layout the page and service the timer
    286         frame->view()->layout();
    287         while (client.m_hasTimer) {
    288             client.m_func();
    289             JavaSharedClient::ServiceFunctionPtrQueue();
    290         }
    291         JavaSharedClient::ServiceFunctionPtrQueue();
    292 
    293         // Layout more if needed.
    294         while (frame->view()->needsLayout())
    295             frame->view()->layout();
    296         JavaSharedClient::ServiceFunctionPtrQueue();
    297 
    298         if (reloadCount)
    299             frame->loader()->reload(true);
    300     } while (reloadCount--);
    301 
    302     // Draw into an offscreen bitmap
    303     SkBitmap bmp;
    304     bmp.setConfig(SkBitmap::kARGB_8888_Config, width, height);
    305     bmp.allocPixels();
    306     SkCanvas canvas(bmp);
    307     PlatformGraphicsContext ctx(&canvas);
    308     GraphicsContext gc(&ctx);
    309     frame->view()->paintContents(&gc, IntRect(0, 0, width, height));
    310 
    311     // Write the bitmap to the sdcard
    312     SkImageEncoder* enc = SkImageEncoder::Create(SkImageEncoder::kPNG_Type);
    313     enc->encodeFile("/sdcard/webcore_test.png", bmp, 100);
    314     delete enc;
    315 
    316     // Tear down the world.
    317     frame->loader()->detachFromParent();
    318     delete page;
    319 }
    320 
    321 }  // namespace android
    322