blob: 616526b203ff0d37a9c68eafc1666f78d06a433b [file] [log] [blame]
/*
* Copyright 2009, The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define LOG_TAG "webcoreglue"
#include "config.h"
#include "BackForwardList.h"
#include "ChromeClientAndroid.h"
#include "ContextMenuClientAndroid.h"
#include "CookieClient.h"
#include "DragClientAndroid.h"
#include "EditorClientAndroid.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameLoaderClientAndroid.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "HistoryItem.h"
#include "InspectorClientAndroid.h"
#include "IntRect.h"
#include "JavaSharedClient.h"
#include "jni_utility.h"
#include "Page.h"
#include "PlatformGraphicsContext.h"
#include "ResourceRequest.h"
#include "ScriptController.h"
#include "SecurityOrigin.h"
#include "SelectionController.h"
#include "Settings.h"
#include "SharedBuffer.h"
#include "SubstituteData.h"
#include "TimerClient.h"
#include "TextEncoding.h"
#include "WebCoreViewBridge.h"
#include "WebFrameView.h"
#include "WebViewCore.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkImageEncoder.h"
#include "benchmark/Intercept.h"
#include "benchmark/MyJavaVM.h"
#include "jni_utility.h"
#include <jni.h>
#include <utils/Log.h>
namespace android {
extern int register_webframe(JNIEnv*);
extern int register_javabridge(JNIEnv*);
extern int register_resource_loader(JNIEnv*);
extern int register_webviewcore(JNIEnv*);
extern int register_webhistory(JNIEnv*);
extern int register_webicondatabase(JNIEnv*);
extern int register_websettings(JNIEnv*);
extern int register_webview(JNIEnv*);
extern int register_webcorejni(JNIEnv*);
#if ENABLE(DATABASE)
extern int register_webstorage(JNIEnv*);
#endif
extern int register_geolocation_permissions(JNIEnv*);
extern int register_mock_geolocation(JNIEnv*);
#if ENABLE(VIDEO)
extern int register_mediaplayer(JNIEnv*);
#endif
}
struct RegistrationMethod {
const char* name;
int (*func)(JNIEnv*);
};
static RegistrationMethod gWebCoreRegMethods[] = {
{ "JavaBridge", android::register_javabridge },
{ "WebFrame", android::register_webframe },
{ "WebCoreResourceLoader", android::register_resource_loader },
{ "WebCoreJni", android::register_webcorejni },
{ "WebViewCore", android::register_webviewcore },
{ "WebHistory", android::register_webhistory },
{ "WebIconDatabase", android::register_webicondatabase },
{ "WebSettings", android::register_websettings },
#if ENABLE(DATABASE)
{ "WebStorage", android::register_webstorage },
#endif
{ "WebView", android::register_webview },
{ "GeolocationPermissions", android::register_geolocation_permissions },
{ "MockGeolocation", android::register_mock_geolocation },
#if ENABLE(VIDEO)
{ "HTML5VideoViewProxy", android::register_mediaplayer },
#endif
};
EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
// Save the JavaVM pointer for use globally.
JSC::Bindings::setJavaVM(vm);
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
LOGE("GetEnv failed!");
return result;
}
LOG_ASSERT(env, "Could not retrieve the env!");
const RegistrationMethod* method = gWebCoreRegMethods;
const RegistrationMethod* end = method + sizeof(gWebCoreRegMethods)/sizeof(RegistrationMethod);
while (method != end) {
if (method->func(env) < 0) {
LOGE("%s registration failed!", method->name);
return result;
}
method++;
}
// Initialize rand() function. The rand() function is used in
// FileSystemAndroid to create a random temporary filename.
srand(time(NULL));
return JNI_VERSION_1_4;
}
class MyJavaSharedClient : public TimerClient, public CookieClient {
public:
MyJavaSharedClient() : m_hasTimer(false) {}
virtual void setSharedTimer(long long timemillis) { m_hasTimer = true; }
virtual void stopSharedTimer() { m_hasTimer = false; }
virtual void setSharedTimerCallback(void (*f)()) { m_func = f; }
virtual void signalServiceFuncPtrQueue() {}
// Cookie methods that do nothing.
virtual void setCookies(const KURL&, const String&) {}
virtual String cookies(const KURL&) { return ""; }
virtual bool cookiesEnabled() { return false; }
bool m_hasTimer;
void (*m_func)();
};
static void historyItemChanged(HistoryItem* i) {
if (i->bridge())
i->bridge()->updateHistoryItem(i);
}
namespace android {
EXPORT void benchmark(const char* url, int reloadCount, int width, int height) {
ScriptController::initializeThreading();
// Setting this allows data: urls to load from a local file.
SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForAll);
// Create the fake JNIEnv and JavaVM
InitializeJavaVM();
// The real function is private to libwebcore but we know what it does.
notifyHistoryItemChanged = historyItemChanged;
// Implement the shared timer callback
MyJavaSharedClient client;
JavaSharedClient::SetTimerClient(&client);
JavaSharedClient::SetCookieClient(&client);
// Create the page with all the various clients
ChromeClientAndroid* chrome = new ChromeClientAndroid;
EditorClientAndroid* editor = new EditorClientAndroid;
Page* page = new Page(chrome, new ContextMenuClientAndroid, editor,
new DragClientAndroid, new InspectorClientAndroid, NULL);
editor->setPage(page);
// Create MyWebFrame that intercepts network requests
MyWebFrame* webFrame = new MyWebFrame(page);
webFrame->setUserAgent("Performance testing"); // needs to be non-empty
chrome->setWebFrame(webFrame);
// ChromeClientAndroid maintains the reference.
Release(webFrame);
// Create the Frame and the FrameLoaderClient
FrameLoaderClientAndroid* loader = new FrameLoaderClientAndroid(webFrame);
RefPtr<Frame> frame = Frame::create(page, NULL, loader);
loader->setFrame(frame.get());
// Build our View system, resize it to the given dimensions and release our
// references. Note: We keep a referenec to frameView so we can layout and
// draw later without risk of it being deleted.
WebViewCore* webViewCore = new WebViewCore(JSC::Bindings::getJNIEnv(),
MY_JOBJECT, frame.get());
RefPtr<FrameView> frameView = FrameView::create(frame.get());
WebFrameView* webFrameView = new WebFrameView(frameView.get(), webViewCore);
frame->setView(frameView);
frameView->resize(width, height);
Release(webViewCore);
Release(webFrameView);
// Initialize the frame and turn of low-bandwidth display (it fails an
// assertion in the Cache code)
frame->init();
frame->selection()->setFocused(true);
// Set all the default settings the Browser normally uses.
Settings* s = frame->settings();
s->setLayoutAlgorithm(Settings::kLayoutNormal); // Normal layout for now
s->setStandardFontFamily("sans-serif");
s->setFixedFontFamily("monospace");
s->setSansSerifFontFamily("sans-serif");
s->setSerifFontFamily("serif");
s->setCursiveFontFamily("cursive");
s->setFantasyFontFamily("fantasy");
s->setMinimumFontSize(8);
s->setMinimumLogicalFontSize(8);
s->setDefaultFontSize(16);
s->setDefaultFixedFontSize(13);
s->setLoadsImagesAutomatically(true);
s->setJavaScriptEnabled(true);
s->setDefaultTextEncodingName("latin1");
s->setPluginsEnabled(false);
s->setShrinksStandaloneImagesToFit(false);
s->setUseWideViewport(false);
// Finally, load the actual data
ResourceRequest req(url);
frame->loader()->load(req, false);
do {
// Layout the page and service the timer
frameView->layout();
while (client.m_hasTimer) {
client.m_func();
JavaSharedClient::ServiceFunctionPtrQueue();
}
JavaSharedClient::ServiceFunctionPtrQueue();
// Layout more if needed.
while (frameView->needsLayout())
frameView->layout();
JavaSharedClient::ServiceFunctionPtrQueue();
if (reloadCount)
frame->loader()->reload(true);
} while (reloadCount--);
// Draw into an offscreen bitmap
SkBitmap bmp;
bmp.setConfig(SkBitmap::kARGB_8888_Config, width, height);
bmp.allocPixels();
SkCanvas canvas(bmp);
PlatformGraphicsContext ctx(&canvas, NULL);
GraphicsContext gc(&ctx);
frameView->paintContents(&gc, IntRect(0, 0, width, height));
// Write the bitmap to the sdcard
SkImageEncoder* enc = SkImageEncoder::Create(SkImageEncoder::kPNG_Type);
enc->encodeFile("/sdcard/webcore_test.png", bmp, 100);
delete enc;
// Tear down the world.
frame->loader()->detachFromParent();
delete page;
}
} // namespace android