#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/file_chooser_params.h"
+#include "content/public/common/show_desktop_notification_params.h"
#include "jni/XWalkContentsClientBridge_jni.h"
#include "net/cert/x509_certificate.h"
+#include "third_party/skia/include/core/SkBitmap.h"
#include "url/gurl.h"
+#include "ui/gfx/android/java_bitmap.h"
+#include "ui/shell_dialogs/selected_file_info.h"
using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF16;
using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;
using content::BrowserThread;
+using content::FileChooserParams;
using content::RenderViewHost;
using content::WebContents;
namespace xwalk {
+namespace {
+
+void RunUpdateNotificationIconOnUIThread(
+ int notification_id,
+ int process_id,
+ int route_id,
+ const SkBitmap& icon) {
+ XWalkContentsClientBridgeBase* bridge =
+ XWalkContentsClientBridgeBase::FromRenderViewID(process_id, route_id);
+ if (bridge)
+ bridge->UpdateNotificationIcon(notification_id, icon);
+}
+
+} // namespace
+
XWalkContentsClientBridge::XWalkContentsClientBridge(JNIEnv* env, jobject obj)
: java_ref_(env, obj) {
DCHECK(obj);
Java_XWalkContentsClientBridge_setNativeContentsClientBridge(
- env, obj, reinterpret_cast<jint>(this));
+ env, obj, reinterpret_cast<intptr_t>(this));
}
XWalkContentsClientBridge::~XWalkContentsClientBridge() {
int cert_error,
net::X509Certificate* cert,
const GURL& request_url,
- const base::Callback<void(bool)>& callback,
+ const base::Callback<void(bool)>& callback, // NOLINT
bool* cancel_request) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
void XWalkContentsClientBridge::RunJavaScriptDialog(
content::JavaScriptMessageType message_type,
const GURL& origin_url,
- const string16& message_text,
- const string16& default_prompt_text,
+ const base::string16& message_text,
+ const base::string16& default_prompt_text,
const content::JavaScriptDialogManager::DialogClosedCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
JNIEnv* env = AttachCurrentThread();
void XWalkContentsClientBridge::RunBeforeUnloadDialog(
const GURL& origin_url,
- const string16& message_text,
+ const base::string16& message_text,
const content::JavaScriptDialogManager::DialogClosedCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
JNIEnv* env = AttachCurrentThread();
env, obj.obj(), handler.obj(), jhost.obj(), jrealm.obj());
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() ||
+ iter->second.size() != 3) {
+ return;
+ }
+ int notification_id = iter->second[0];
+ int process_id = iter->second[1];
+ int route_id = iter->second[2];
+ // 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,
+ process_id,
+ route_id,
+ 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());
+}
+
+void XWalkContentsClientBridge::ShowNotification(
+ const content::ShowDesktopNotificationHostMsgParams& params,
+ bool worker,
+ int process_id,
+ int route_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ JNIEnv* env = AttachCurrentThread();
+
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (obj.is_null())
+ return;
+
+ ScopedJavaLocalRef<jstring> jtitle(
+ ConvertUTF16ToJavaString(env, params.title));
+ ScopedJavaLocalRef<jstring> jbody(
+ ConvertUTF16ToJavaString(env, params.body));
+ ScopedJavaLocalRef<jstring> jreplace_id(
+ ConvertUTF16ToJavaString(env, params.replace_id));
+
+ Java_XWalkContentsClientBridge_showNotification(
+ env, obj.obj(), jtitle.obj(), jbody.obj(),
+ jreplace_id.obj(), params.notification_id,
+ process_id, route_id);
+
+ if (params.icon_url.is_valid()) {
+ RenderViewHost* rvh = RenderViewHost::FromID(process_id, route_id);
+ if (rvh) {
+ WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
+ if (web_contents) {
+ int download_request_id = web_contents->DownloadImage(
+ params.icon_url,
+ false,
+ 0,
+ base::Bind(
+ &XWalkContentsClientBridge::OnNotificationIconDownloaded,
+ base::Unretained(this)));
+ std::vector<int> ids;
+ ids.push_back(params.notification_id);
+ ids.push_back(process_id);
+ ids.push_back(route_id);
+ downloading_icon_notifications_[download_request_id] = ids;
+ }
+ }
+ }
+}
+
+void XWalkContentsClientBridge::CancelNotification(
+ int notification_id,
+ int process_id,
+ int route_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ JNIEnv* env = AttachCurrentThread();
+
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (obj.is_null())
+ return;
+
+ Java_XWalkContentsClientBridge_cancelNotification(
+ env, obj.obj(), notification_id,
+ process_id, route_id);
+}
+
void XWalkContentsClientBridge::ConfirmJsResult(JNIEnv* env,
jobject,
int id,
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
content::JavaScriptDialogManager::DialogClosedCallback* callback =
pending_js_dialog_callbacks_.Lookup(id);
- string16 prompt_text;
+ base::string16 prompt_text;
if (prompt) {
prompt_text = ConvertJavaStringToUTF16(env, prompt);
}
content::JavaScriptDialogManager::DialogClosedCallback* callback =
pending_js_dialog_callbacks_.Lookup(id);
if (callback)
- callback->Run(false, string16());
+ callback->Run(false, base::string16());
pending_js_dialog_callbacks_.Remove(id);
}
void XWalkContentsClientBridge::ExitFullscreen(
- JNIEnv*, jobject, jint j_web_contents) {
+ JNIEnv*, jobject, jlong j_web_contents) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
WebContents* web_contents = reinterpret_cast<WebContents*>(j_web_contents);
if (web_contents) {
}
}
+void XWalkContentsClientBridge::NotificationDisplayed(
+ JNIEnv*, jobject, int id, int process_id, int route_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ RenderViewHost* rvh = RenderViewHost::FromID(
+ process_id, route_id);
+ if (!rvh)
+ return;
+ rvh->DesktopNotificationPostDisplay(id);
+}
+
+void XWalkContentsClientBridge::NotificationError(
+ JNIEnv* env, jobject, int id, jstring error,
+ int process_id, int route_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ RenderViewHost* rvh = RenderViewHost::FromID(
+ process_id, route_id);
+ if (!rvh)
+ return;
+ base::string16 error_text;
+ if (error)
+ error_text = ConvertJavaStringToUTF16(env, error);
+ rvh->DesktopNotificationPostError(id, error_text);
+}
+
+void XWalkContentsClientBridge::NotificationClicked(
+ JNIEnv*, jobject, int id, int process_id, int route_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ RenderViewHost* rvh = RenderViewHost::FromID(
+ process_id, route_id);
+ if (!rvh)
+ return;
+ rvh->DesktopNotificationPostClick(id);
+}
+
+void XWalkContentsClientBridge::NotificationClosed(
+ JNIEnv*, jobject, int id, bool by_user,
+ int process_id, int route_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ RenderViewHost* rvh = RenderViewHost::FromID(
+ process_id, route_id);
+ if (!rvh)
+ return;
+ rvh->DesktopNotificationPostClose(id, by_user);
+}
+
+void XWalkContentsClientBridge::OnFilesSelected(
+ JNIEnv* env, jobject, int process_id, int render_id,
+ int mode, jstring filepath, jstring display_name) {
+ content::RenderViewHost* rvh =
+ content::RenderViewHost::FromID(process_id, render_id);
+ if (!rvh)
+ return;
+
+ std::string path = base::android::ConvertJavaStringToUTF8(env, filepath);
+ std::string file_name =
+ base::android::ConvertJavaStringToUTF8(env, display_name);
+ base::FilePath file_path = base::FilePath(path);
+ ui::SelectedFileInfo 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;
+ files.push_back(file_info);
+
+ rvh->FilesSelectedInChooser(
+ files, static_cast<content::FileChooserParams::Mode>(mode));
+}
+
+void XWalkContentsClientBridge::OnFilesNotSelected(
+ JNIEnv* env, jobject, int process_id, int render_id, int mode) {
+ content::RenderViewHost* rvh =
+ content::RenderViewHost::FromID(process_id, render_id);
+ if (!rvh)
+ return;
+
+ std::vector<ui::SelectedFileInfo> files;
+
+ rvh->FilesSelectedInChooser(
+ files, static_cast<content::FileChooserParams::Mode>(mode));
+}
+
bool RegisterXWalkContentsClientBridge(JNIEnv* env) {
return RegisterNativesImpl(env) >= 0;
}