#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/callback.h"
+#include "base/containers/scoped_ptr_hash_map.h"
#include "base/guid.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/desktop_notification_delegate.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/file_chooser_file_info.h"
#include "content/public/common/file_chooser_params.h"
#include "content/public/common/show_desktop_notification_params.h"
#include "jni/XWalkContentsClientBridge_jni.h"
using base::android::ConvertUTF16ToJavaString;
using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;
+using base::ScopedPtrHashMap;
using content::BrowserThread;
using content::FileChooserParams;
using content::RenderViewHost;
namespace {
-void RunUpdateNotificationIconOnUIThread(
- int notification_id,
- content::RenderFrameHost* render_frame_host,
- const SkBitmap& icon) {
- XWalkContentsClientBridgeBase* bridge =
- XWalkContentsClientBridgeBase::FromRenderFrameHost(render_frame_host);
- if (bridge)
- bridge->UpdateNotificationIcon(notification_id, icon);
-}
+int g_next_notification_id_ = 1;
+
+ScopedPtrHashMap<int, content::DesktopNotificationDelegate> g_notification_map_;
} // namespace
-static IDMap<content::DesktopNotificationDelegate> notifications_;
-XWalkContentsClientBridge::XWalkContentsClientBridge(JNIEnv* env, jobject obj)
- : java_ref_(env, obj) {
+XWalkContentsClientBridge::XWalkContentsClientBridge(
+ JNIEnv* env, jobject obj,
+ content::WebContents* web_contents)
+ : java_ref_(env, obj),
+ icon_helper_(new XWalkIconHelper(web_contents)) {
DCHECK(obj);
Java_XWalkContentsClientBridge_setNativeContentsClientBridge(
env, obj, reinterpret_cast<intptr_t>(this));
+ icon_helper_->SetListener(this);
}
XWalkContentsClientBridge::~XWalkContentsClientBridge() {
return;
std::string der_string;
- net::X509Certificate::GetDEREncoded(cert->os_cert_handle(), &der_string);
+ if (!net::X509Certificate::GetDEREncoded(cert->os_cert_handle(),
+ &der_string))
+ return;
ScopedJavaLocalRef<jbyteArray> jcert = base::android::ToJavaByteArray(
env,
reinterpret_cast<const uint8*>(der_string.data()),
return true;
}
-void XWalkContentsClientBridge::OnNotificationIconDownloaded(
- int id,
- int http_status_code,
- const GURL& icon_url,
- const std::vector<SkBitmap>& bitmaps,
- const std::vector<gfx::Size>& original_bitmap_sizes) {
- if (bitmaps.empty() && http_status_code == 404) {
- LOG(WARNING) << "Failed to download notification icon from "
- << icon_url.spec();
- } else {
- NotificationDownloadRequestIdMap::iterator iter =
- downloading_icon_notifications_.find(id);
- if (iter == downloading_icon_notifications_.end())
- return;
-
- int notification_id = iter->second.first;
- content::RenderFrameHost* render_frame_host = iter->second.second;
- // This will lead to a second call of ShowNotification for the
- // same notification id to update the icon. On Android, when
- // the notification which is already shown is fired again, it will
- // silently update the content only.
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&RunUpdateNotificationIconOnUIThread,
- notification_id,
- render_frame_host,
- bitmaps[0]));
- }
- downloading_icon_notifications_.erase(id);
-}
-
-void XWalkContentsClientBridge::UpdateNotificationIcon(
- int notification_id, const SkBitmap& icon) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- JNIEnv* env = AttachCurrentThread();
-
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
- if (obj.is_null())
- return;
-
- ScopedJavaLocalRef<jobject> jicon = gfx::ConvertToJavaBitmap(&icon);
- Java_XWalkContentsClientBridge_updateNotificationIcon(
- env, obj.obj(), notification_id, jicon.obj());
-}
-
static void CancelNotification(
- JavaObjectWeakGlobalRef java_ref,
- int notification_id, content::DesktopNotificationDelegate* delegate) {
+ JavaObjectWeakGlobalRef java_ref, int notification_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref.get(env);
return;
Java_XWalkContentsClientBridge_cancelNotification(
- env, obj.obj(), notification_id, reinterpret_cast<intptr_t>(delegate));
+ env, obj.obj(), notification_id);
}
void XWalkContentsClientBridge::ShowNotification(
const content::ShowDesktopNotificationHostMsgParams& params,
- content::RenderFrameHost* render_frame_host,
- content::DesktopNotificationDelegate* delegate,
+ scoped_ptr<content::DesktopNotificationDelegate> delegate,
base::Closure* cancel_callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
JNIEnv* env = AttachCurrentThread();
ConvertUTF16ToJavaString(env, params.body));
ScopedJavaLocalRef<jstring> jreplace_id(
ConvertUTF16ToJavaString(env, params.replace_id));
+ ScopedJavaLocalRef<jobject> jicon = gfx::ConvertToJavaBitmap(¶ms.icon);
- int notification_id = notifications_.Add(delegate);
+ int notification_id = g_next_notification_id_++;
+ g_notification_map_.set(notification_id, delegate.Pass());
Java_XWalkContentsClientBridge_showNotification(
env, obj.obj(), jtitle.obj(), jbody.obj(),
- jreplace_id.obj(), notification_id,
- reinterpret_cast<intptr_t>(delegate));
+ jreplace_id.obj(), jicon.obj(), notification_id);
if (cancel_callback)
- *cancel_callback =
- base::Bind(&CancelNotification, java_ref_, notification_id, delegate);
-
- if (params.icon_url.is_valid()) {
- WebContents* web_contents =
- WebContents::FromRenderFrameHost(render_frame_host);
- if (web_contents) {
- int download_request_id = web_contents->DownloadImage(
- params.icon_url,
- false,
- 0,
- base::Bind(
- &XWalkContentsClientBridge::OnNotificationIconDownloaded,
- base::Unretained(this)));
- NotificationDownloadRequestInfos info =
- std::make_pair(notification_id, render_frame_host);
- downloading_icon_notifications_[download_request_id] = info;
- }
- }
+ *cancel_callback = base::Bind(
+ &CancelNotification, java_ref_, notification_id);
}
void XWalkContentsClientBridge::OnWebLayoutPageScaleFactorChanged(
}
void XWalkContentsClientBridge::NotificationDisplayed(
- JNIEnv*, jobject, jlong delegate) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- content::DesktopNotificationDelegate* notification_delegate =
- reinterpret_cast<content::DesktopNotificationDelegate*> (delegate);
- notification_delegate->NotificationDisplayed();
-}
-
-void XWalkContentsClientBridge::NotificationError(
- JNIEnv* env, jobject, jlong delegate) {
+ JNIEnv*, jobject, jint notification_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
content::DesktopNotificationDelegate* notification_delegate =
- reinterpret_cast<content::DesktopNotificationDelegate*> (delegate);
- notification_delegate->NotificationError();
+ g_notification_map_.get(notification_id);
+ if (notification_delegate)
+ notification_delegate->NotificationDisplayed();
}
void XWalkContentsClientBridge::NotificationClicked(
- JNIEnv*, jobject, jint id, jlong delegate) {
+ JNIEnv*, jobject, jint id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- notifications_.Remove(id);
- content::DesktopNotificationDelegate* notification_delegate =
- reinterpret_cast<content::DesktopNotificationDelegate*> (delegate);
- notification_delegate->NotificationClick();
+ scoped_ptr<content::DesktopNotificationDelegate> notification_delegate =
+ g_notification_map_.take_and_erase(id);
+ if (notification_delegate.get())
+ notification_delegate->NotificationClick();
}
void XWalkContentsClientBridge::NotificationClosed(
- JNIEnv*, jobject, jint id, bool by_user, jlong delegate) {
+ JNIEnv*, jobject, jint id, bool by_user) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- notifications_.Remove(id);
- content::DesktopNotificationDelegate* notification_delegate =
- reinterpret_cast<content::DesktopNotificationDelegate*> (delegate);
- notification_delegate->NotificationClosed(by_user);
+ scoped_ptr<content::DesktopNotificationDelegate> notification_delegate =
+ g_notification_map_.take_and_erase(id);
+ if (notification_delegate.get())
+ notification_delegate->NotificationClosed(by_user);
}
void XWalkContentsClientBridge::OnFilesSelected(
std::string file_name =
base::android::ConvertJavaStringToUTF8(env, display_name);
base::FilePath file_path = base::FilePath(path);
- ui::SelectedFileInfo file_info;
+ content::FileChooserFileInfo file_info;
file_info.file_path = file_path;
- file_info.local_path = file_path;
if (!file_name.empty())
file_info.display_name = file_name;
- std::vector<ui::SelectedFileInfo> files;
+ std::vector<content::FileChooserFileInfo> files;
files.push_back(file_info);
rvh->FilesSelectedInChooser(
if (!rvh)
return;
- std::vector<ui::SelectedFileInfo> files;
+ std::vector<content::FileChooserFileInfo> files;
rvh->FilesSelectedInChooser(
files, static_cast<content::FileChooserParams::Mode>(mode));
}
+void XWalkContentsClientBridge::DownloadIcon(JNIEnv* env,
+ jobject obj,
+ jstring url) {
+ std::string url_str = base::android::ConvertJavaStringToUTF8(env, url);
+ icon_helper_->DownloadIcon(GURL(url_str));
+}
+
+void XWalkContentsClientBridge::OnIconAvailable(const GURL& icon_url) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+
+ ScopedJavaLocalRef<jstring> jurl(
+ ConvertUTF8ToJavaString(env, icon_url.spec()));
+
+ Java_XWalkContentsClientBridge_onIconAvailable(env, obj.obj(), jurl.obj());
+}
+
+void XWalkContentsClientBridge::OnReceivedIcon(const GURL& icon_url,
+ const SkBitmap& bitmap) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+
+ ScopedJavaLocalRef<jstring> jurl(
+ ConvertUTF8ToJavaString(env, icon_url.spec()));
+ ScopedJavaLocalRef<jobject> jicon = gfx::ConvertToJavaBitmap(&bitmap);
+
+ Java_XWalkContentsClientBridge_onReceivedIcon(
+ env, obj.obj(), jurl.obj(), jicon.obj());
+}
+
bool RegisterXWalkContentsClientBridge(JNIEnv* env) {
- return RegisterNativesImpl(env) >= 0;
+ return RegisterNativesImpl(env);
}
} // namespace xwalk