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 "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(JNIEnv*);
     86 #endif
     87 
     88 }
     89 
     90 struct RegistrationMethod {
     91     const char* name;
     92     int (*func)(JNIEnv*);
     93 };
     94 
     95 static RegistrationMethod gWebCoreRegMethods[] = {
     96     { "JavaBridge", android::register_javabridge },
     97     { "WebFrame", android::register_webframe },
     98     { "WebCoreResourceLoader", android::register_resource_loader },
     99     { "WebViewCore", android::register_webviewcore },
    100     { "WebHistory", android::register_webhistory },
    101     { "WebIconDatabase", android::register_webicondatabase },
    102     { "WebSettings", android::register_websettings },
    103 #if ENABLE(DATABASE)
    104     { "WebStorage", android::register_webstorage },
    105 #endif
    106     { "WebView", android::register_webview },
    107     { "GeolocationPermissions", android::register_geolocation_permissions },
    108     { "MockGeolocation", android::register_mock_geolocation },
    109 #if ENABLE(VIDEO)
    110     { "HTML5VideoViewProxy", android::register_mediaplayer },
    111 #endif
    112 };
    113 
    114 EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
    115 {
    116     // Save the JavaVM pointer for use globally.
    117     JSC::Bindings::setJavaVM(vm);
    118 
    119     JNIEnv* env = NULL;
    120     jint result = -1;
    121 
    122     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
    123         LOGE("GetEnv failed!");
    124         return result;
    125     }
    126     LOG_ASSERT(env, "Could not retrieve the env!");
    127 
    128     const RegistrationMethod* method = gWebCoreRegMethods;
    129     const RegistrationMethod* end = method + sizeof(gWebCoreRegMethods)/sizeof(RegistrationMethod);
    130     while (method != end) {
    131         if (method->func(env) < 0) {
    132             LOGE("%s registration failed!", method->name);
    133             return result;
    134         }
    135         method++;
    136     }
    137 
    138     // Initialize rand() function. The rand() function is used in
    139     // FileSystemAndroid to create a random temporary filename.
    140     srand(time(NULL));
    141 
    142     return JNI_VERSION_1_4;
    143 }
    144 
    145 class MyJavaSharedClient : public TimerClient, public CookieClient {
    146 public:
    147     MyJavaSharedClient() : m_hasTimer(false) {}
    148     virtual void setSharedTimer(long long timemillis) { m_hasTimer = true; }
    149     virtual void stopSharedTimer() { m_hasTimer = false; }
    150     virtual void setSharedTimerCallback(void (*f)()) { m_func = f; }
    151     virtual void signalServiceFuncPtrQueue() {}
    152 
    153     // Cookie methods that do nothing.
    154     virtual void setCookies(const KURL&, const String&) {}
    155     virtual String cookies(const KURL&) { return ""; }
    156     virtual bool cookiesEnabled() { return false; }
    157 
    158     bool m_hasTimer;
    159     void (*m_func)();
    160 };
    161 
    162 static void historyItemChanged(HistoryItem* i) {
    163     if (i->bridge())
    164         i->bridge()->updateHistoryItem(i);
    165 }
    166 
    167 namespace android {
    168 
    169 EXPORT void benchmark(const char* url, int reloadCount, int width, int height) {
    170     ScriptController::initializeThreading();
    171 
    172     // Setting this allows data: urls to load from a local file.
    173     SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForAll);
    174 
    175     // Create the fake JNIEnv and JavaVM
    176     InitializeJavaVM();
    177 
    178     // The real function is private to libwebcore but we know what it does.
    179     notifyHistoryItemChanged = historyItemChanged;
    180 
    181     // Implement the shared timer callback
    182     MyJavaSharedClient client;
    183     JavaSharedClient::SetTimerClient(&client);
    184     JavaSharedClient::SetCookieClient(&client);
    185 
    186     // Create the page with all the various clients
    187     ChromeClientAndroid* chrome = new ChromeClientAndroid;
    188     EditorClientAndroid* editor = new EditorClientAndroid;
    189     Page* page = new Page(chrome,
    190                           new ContextMenuClientAndroid,
    191                           editor,
    192                           new DragClientAndroid,
    193                           new InspectorClientAndroid,
    194                           0, // PluginHalterClient
    195                           0); // GeolocationControllerClient
    196     editor->setPage(page);
    197 
    198     // Create MyWebFrame that intercepts network requests
    199     MyWebFrame* webFrame = new MyWebFrame(page);
    200     webFrame->setUserAgent("Performance testing"); // needs to be non-empty
    201     chrome->setWebFrame(webFrame);
    202     // ChromeClientAndroid maintains the reference.
    203     Release(webFrame);
    204 
    205     // Create the Frame and the FrameLoaderClient
    206     FrameLoaderClientAndroid* loader = new FrameLoaderClientAndroid(webFrame);
    207     RefPtr<Frame> frame = Frame::create(page, NULL, loader);
    208     loader->setFrame(frame.get());
    209 
    210     // Build our View system, resize it to the given dimensions and release our
    211     // references. Note: We keep a referenec to frameView so we can layout and
    212     // draw later without risk of it being deleted.
    213     WebViewCore* webViewCore = new WebViewCore(JSC::Bindings::getJNIEnv(),
    214             MY_JOBJECT, frame.get());
    215     RefPtr<FrameView> frameView = FrameView::create(frame.get());
    216     WebFrameView* webFrameView = new WebFrameView(frameView.get(), webViewCore);
    217     frame->setView(frameView);
    218     frameView->resize(width, height);
    219     Release(webViewCore);
    220     Release(webFrameView);
    221 
    222     // Initialize the frame and turn of low-bandwidth display (it fails an
    223     // assertion in the Cache code)
    224     frame->init();
    225     frame->selection()->setFocused(true);
    226 
    227     // Set all the default settings the Browser normally uses.
    228     Settings* s = frame->settings();
    229     s->setLayoutAlgorithm(Settings::kLayoutNormal); // Normal layout for now
    230     s->setStandardFontFamily("sans-serif");
    231     s->setFixedFontFamily("monospace");
    232     s->setSansSerifFontFamily("sans-serif");
    233     s->setSerifFontFamily("serif");
    234     s->setCursiveFontFamily("cursive");
    235     s->setFantasyFontFamily("fantasy");
    236     s->setMinimumFontSize(8);
    237     s->setMinimumLogicalFontSize(8);
    238     s->setDefaultFontSize(16);
    239     s->setDefaultFixedFontSize(13);
    240     s->setLoadsImagesAutomatically(true);
    241     s->setJavaScriptEnabled(true);
    242     s->setDefaultTextEncodingName("latin1");
    243     s->setPluginsEnabled(false);
    244     s->setShrinksStandaloneImagesToFit(false);
    245     s->setUseWideViewport(false);
    246 
    247     // Finally, load the actual data
    248     ResourceRequest req(url);
    249     frame->loader()->load(req, false);
    250 
    251     do {
    252         // Layout the page and service the timer
    253         frame->view()->layout();
    254         while (client.m_hasTimer) {
    255             client.m_func();
    256             JavaSharedClient::ServiceFunctionPtrQueue();
    257         }
    258         JavaSharedClient::ServiceFunctionPtrQueue();
    259 
    260         // Layout more if needed.
    261         while (frame->view()->needsLayout())
    262             frame->view()->layout();
    263         JavaSharedClient::ServiceFunctionPtrQueue();
    264 
    265         if (reloadCount)
    266             frame->loader()->reload(true);
    267     } while (reloadCount--);
    268 
    269     // Draw into an offscreen bitmap
    270     SkBitmap bmp;
    271     bmp.setConfig(SkBitmap::kARGB_8888_Config, width, height);
    272     bmp.allocPixels();
    273     SkCanvas canvas(bmp);
    274     PlatformGraphicsContext ctx(&canvas, NULL);
    275     GraphicsContext gc(&ctx);
    276     frame->view()->paintContents(&gc, IntRect(0, 0, width, height));
    277 
    278     // Write the bitmap to the sdcard
    279     SkImageEncoder* enc = SkImageEncoder::Create(SkImageEncoder::kPNG_Type);
    280     enc->encodeFile("/sdcard/webcore_test.png", bmp, 100);
    281     delete enc;
    282 
    283     // Tear down the world.
    284     frame->loader()->detachFromParent();
    285     delete page;
    286 }
    287 
    288 }  // namespace android
    289