blob: 024da785abb4e9f6dfc75c095cc1eb47c03f2790 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "android_webview/native/aw_contents.h"
#include "android_webview/browser/renderer_host/aw_render_view_host_ext.h"
#include "android_webview/native/aw_browser_dependency_factory.h"
#include "android_webview/native/aw_contents_container.h"
#include "android_webview/native/aw_web_contents_delegate.h"
#include "android_webview/native/aw_contents_io_thread_client.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/supports_user_data.h"
#include "content/public/browser/android/content_view_core.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "jni/AwContents_jni.h"
using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF16;
using base::android::ConvertJavaStringToUTF8;
using base::android::ConvertUTF16ToJavaString;
using base::android::ConvertUTF8ToJavaString;
using base::android::JavaRef;
using base::android::ScopedJavaGlobalRef;
using base::android::ScopedJavaLocalRef;
using content::BrowserThread;
using content::ContentViewCore;
using content::WebContents;
namespace android_webview {
namespace {
const void* kAwContentsUserDataKey = &kAwContentsUserDataKey;
class AwContentsUserData : public base::SupportsUserData::Data {
public:
AwContentsUserData(AwContents* ptr) : contents_(ptr) {}
static AwContents* GetContents(WebContents* web_contents) {
if (!web_contents)
return NULL;
AwContentsUserData* data = reinterpret_cast<AwContentsUserData*>(
web_contents->GetUserData(kAwContentsUserDataKey));
return data ? data->contents_ : NULL;
}
private:
AwContents* contents_;
};
} // namespace
// static
AwContents* AwContents::FromWebContents(WebContents* web_contents) {
return AwContentsUserData::GetContents(web_contents);
}
AwContents::AwContents(JNIEnv* env,
jobject obj,
jobject web_contents_delegate,
bool private_browsing)
: java_ref_(env, obj),
web_contents_delegate_(
new AwWebContentsDelegate(env, web_contents_delegate)) {
android_webview::AwBrowserDependencyFactory* dependency_factory =
android_webview::AwBrowserDependencyFactory::GetInstance();
WebContents* web_contents =
dependency_factory->CreateWebContents(private_browsing);
DCHECK(!AwContents::FromWebContents(web_contents));
web_contents->SetUserData(kAwContentsUserDataKey,
new AwContentsUserData(this));
contents_container_.reset(dependency_factory->CreateContentsContainer(
web_contents));
web_contents->SetDelegate(web_contents_delegate_.get());
render_view_host_ext_.reset(new AwRenderViewHostExt(web_contents));
}
AwContents::~AwContents() {
WebContents* web_contents = contents_container_->GetWebContents();
DCHECK(AwContents::FromWebContents(web_contents) == this);
web_contents->RemoveUserData(kAwContentsUserDataKey);
if (find_helper_.get())
find_helper_->SetListener(NULL);
}
jint AwContents::GetWebContents(JNIEnv* env, jobject obj) {
return reinterpret_cast<jint>(contents_container_->GetWebContents());
}
void AwContents::Destroy(JNIEnv* env, jobject obj) {
delete this;
}
namespace {
// |message| is passed as base::Owned, so it will automatically be deleted
// when the callback goes out of scope.
void DocumentHasImagesCallback(ScopedJavaGlobalRef<jobject>* message,
bool has_images) {
Java_AwContents_onDocumentHasImagesResponse(AttachCurrentThread(),
has_images,
message->obj());
}
} // namespace
void AwContents::DocumentHasImages(JNIEnv* env, jobject obj, jobject message) {
ScopedJavaGlobalRef<jobject>* j_message = new ScopedJavaGlobalRef<jobject>();
j_message->Reset(env, message);
render_view_host_ext_->DocumentHasImages(
base::Bind(&DocumentHasImagesCallback, base::Owned(j_message)));
}
namespace {
void GenerateMHTMLCallback(ScopedJavaGlobalRef<jobject>* callback,
const FilePath& path, int64 size) {
JNIEnv* env = AttachCurrentThread();
// Android files are UTF8, so the path conversion below is safe.
Java_AwContents_generateMHTMLCallback(
env,
ConvertUTF8ToJavaString(env, path.AsUTF8Unsafe()).obj(),
size, callback->obj());
}
} // namespace
void AwContents::GenerateMHTML(JNIEnv* env, jobject obj,
jstring jpath, jobject callback) {
ScopedJavaGlobalRef<jobject>* j_callback = new ScopedJavaGlobalRef<jobject>();
j_callback->Reset(env, callback);
contents_container_->GetWebContents()->GenerateMHTML(
FilePath(ConvertJavaStringToUTF8(env, jpath)),
base::Bind(&GenerateMHTMLCallback, base::Owned(j_callback)));
}
void AwContents::RunJavaScriptDialog(
content::JavaScriptMessageType message_type,
const GURL& origin_url,
const string16& message_text,
const string16& default_prompt_text,
const ScopedJavaLocalRef<jobject>& js_result) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return;
ScopedJavaLocalRef<jstring> jurl(ConvertUTF8ToJavaString(
env, origin_url.spec()));
ScopedJavaLocalRef<jstring> jmessage(ConvertUTF16ToJavaString(
env, message_text));
switch (message_type) {
case content::JAVASCRIPT_MESSAGE_TYPE_ALERT:
Java_AwContents_handleJsAlert(
env, obj.obj(), jurl.obj(), jmessage.obj(), js_result.obj());
break;
case content::JAVASCRIPT_MESSAGE_TYPE_CONFIRM:
Java_AwContents_handleJsConfirm(
env, obj.obj(), jurl.obj(), jmessage.obj(), js_result.obj());
break;
case content::JAVASCRIPT_MESSAGE_TYPE_PROMPT: {
ScopedJavaLocalRef<jstring> jdefault_value(
ConvertUTF16ToJavaString(env, default_prompt_text));
Java_AwContents_handleJsPrompt(
env, obj.obj(), jurl.obj(), jmessage.obj(),
jdefault_value.obj(), js_result.obj());
break;
}
default:
NOTREACHED();
}
}
void AwContents::RunBeforeUnloadDialog(
const GURL& origin_url,
const string16& message_text,
const ScopedJavaLocalRef<jobject>& js_result) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return;
ScopedJavaLocalRef<jstring> jurl(ConvertUTF8ToJavaString(
env, origin_url.spec()));
ScopedJavaLocalRef<jstring> jmessage(ConvertUTF16ToJavaString(
env, message_text));
Java_AwContents_handleJsBeforeUnload(
env, obj.obj(), jurl.obj(), jmessage.obj(), js_result.obj());
}
void AwContents::onReceivedHttpAuthRequest(
const JavaRef<jobject>& handler,
const std::string& host,
const std::string& realm) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jstring> jhost = ConvertUTF8ToJavaString(env, host);
ScopedJavaLocalRef<jstring> jrealm = ConvertUTF8ToJavaString(env, realm);
Java_AwContents_onReceivedHttpAuthRequest(env, java_ref_.get(env).obj(),
handler.obj(), jhost.obj(),
jrealm.obj());
}
void AwContents::SetIoThreadClient(JNIEnv* env, jobject obj, jobject client) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
content::WebContents* web_contents = contents_container_->GetWebContents();
AwContentsIoThreadClient::Associate(
web_contents, ScopedJavaLocalRef<jobject>(env, client));
}
static jint Init(JNIEnv* env,
jobject obj,
jobject web_contents_delegate,
jboolean private_browsing) {
AwContents* tab = new AwContents(env, obj, web_contents_delegate,
private_browsing);
return reinterpret_cast<jint>(tab);
}
bool RegisterAwContents(JNIEnv* env) {
return RegisterNativesImpl(env) >= 0;
}
jint AwContents::FindAllSync(JNIEnv* env, jobject obj, jstring search_string) {
return GetFindHelper()->FindAllSync(
ConvertJavaStringToUTF16(env, search_string));
}
void AwContents::FindAllAsync(JNIEnv* env, jobject obj, jstring search_string) {
GetFindHelper()->FindAllAsync(ConvertJavaStringToUTF16(env, search_string));
}
void AwContents::FindNext(JNIEnv* env, jobject obj, jboolean forward) {
GetFindHelper()->FindNext(forward);
}
void AwContents::ClearMatches(JNIEnv* env, jobject obj) {
GetFindHelper()->ClearMatches();
}
FindHelper* AwContents::GetFindHelper() {
if (!find_helper_.get()) {
WebContents* web_contents = contents_container_->GetWebContents();
find_helper_.reset(new FindHelper(web_contents));
find_helper_->SetListener(this);
}
return find_helper_.get();
}
void AwContents::OnFindResultReceived(int active_ordinal,
int match_count,
bool finished) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return;
Java_AwContents_onFindResultReceived(
env, obj.obj(), active_ordinal, match_count, finished);
}
} // namespace android_webview