Chromium Code Reviews| Index: chrome/browser/android/chrome_web_contents_delegate_android.cc |
| diff --git a/chrome/browser/android/chrome_web_contents_delegate_android.cc b/chrome/browser/android/chrome_web_contents_delegate_android.cc |
| index 56163c408ff7c4d41117ee0ba4eda1190e25b525..11d78af271a0558dddae7613baf67b93d5f34255 100644 |
| --- a/chrome/browser/android/chrome_web_contents_delegate_android.cc |
| +++ b/chrome/browser/android/chrome_web_contents_delegate_android.cc |
| @@ -6,8 +6,18 @@ |
| #include "base/android/jni_android.h" |
| #include "chrome/browser/file_select_helper.h" |
| +#include "chrome/browser/ui/find_bar/find_match_rects_details.h" |
| +#include "chrome/browser/ui/find_bar/find_notification_details.h" |
| +#include "chrome/browser/ui/find_bar/find_tab_helper.h" |
| +#include "chrome/browser/ui/tab_contents/tab_contents.h" |
| +#include "chrome/common/chrome_notification_types.h" |
| +#include "content/public/browser/notification_details.h" |
| +#include "content/public/browser/notification_source.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/common/file_chooser_params.h" |
| +#include "jni/ChromeWebContentsDelegateAndroid_jni.h" |
| +#include "ui/gfx/rect.h" |
| +#include "ui/gfx/rect_f.h" |
| using base::android::AttachCurrentThread; |
| using base::android::GetClass; |
| @@ -15,6 +25,32 @@ using base::android::ScopedJavaLocalRef; |
| using content::FileChooserParams; |
| using content::WebContents; |
| +namespace { |
| + |
| +// Convenience method to create Android rects. |
| +// RectType should be either gfx::Rect or gfx::RectF. |
| +template <typename RectType> |
| +ScopedJavaLocalRef<jobject> CreateAndroidRect( |
| + JNIEnv* env, |
| + const ScopedJavaLocalRef<jclass>& clazz, |
| + const jmethodID& constructor, |
| + const RectType& rect) { |
| + |
| + ScopedJavaLocalRef<jobject> rect_object( |
| + env, |
| + env->NewObject(clazz.obj(), |
| + constructor, |
| + rect.x(), |
| + rect.y(), |
| + rect.right(), |
| + rect.bottom())); |
| + |
| + DCHECK(!rect_object.is_null()); |
| + return rect_object; |
| +} |
| + |
| +} // anonymous namespace |
| + |
| namespace chrome { |
| namespace android { |
| @@ -24,6 +60,12 @@ ChromeWebContentsDelegateAndroid::ChromeWebContentsDelegateAndroid(JNIEnv* env, |
| } |
| ChromeWebContentsDelegateAndroid::~ChromeWebContentsDelegateAndroid() { |
| + notification_registrar_.RemoveAll(); |
| +} |
| + |
| +// Register native methods. |
| +bool RegisterChromeWebContentsDelegateAndroid(JNIEnv* env) { |
| + return RegisterNativesImpl(env); |
| } |
| void ChromeWebContentsDelegateAndroid::RunFileChooser( |
| @@ -32,5 +74,192 @@ void ChromeWebContentsDelegateAndroid::RunFileChooser( |
| FileSelectHelper::RunFileChooser(web_contents, params); |
| } |
| +void ChromeWebContentsDelegateAndroid::CloseContents( |
| + WebContents* web_contents) { |
| + // Prevent dangling registrations assigned to closed web contents. |
| + if (notification_registrar_.IsRegistered(this, |
| + chrome::NOTIFICATION_FIND_RESULT_AVAILABLE, |
| + content::Source<WebContents>(web_contents))) { |
| + notification_registrar_.Remove(this, |
| + chrome::NOTIFICATION_FIND_RESULT_AVAILABLE, |
| + content::Source<WebContents>(web_contents)); |
| + } |
| + |
| + if (notification_registrar_.IsRegistered(this, |
| + chrome::NOTIFICATION_FIND_MATCH_RECTS_AVAILABLE, |
| + content::Source<WebContents>(web_contents))) { |
| + notification_registrar_.Remove(this, |
| + chrome::NOTIFICATION_FIND_MATCH_RECTS_AVAILABLE, |
| + content::Source<WebContents>(web_contents)); |
| + } |
| + |
| + WebContentsDelegateAndroid::CloseContents(web_contents); |
| +} |
| + |
| +void ChromeWebContentsDelegateAndroid::Observe( |
| + int type, |
| + const content::NotificationSource& source, |
| + const content::NotificationDetails& details) { |
| + switch (type) { |
| + case chrome::NOTIFICATION_FIND_RESULT_AVAILABLE: |
| + OnFindResultAvailable(content::Source<WebContents>(source).ptr(), |
|
jam
2012/09/04 16:39:09
nit: this indentation isn't according to style gui
Leandro Graciá Gil
2012/09/04 18:25:50
Done.
|
| + content::Details<FindNotificationDetails>(details).ptr()); |
| + break; |
| + case chrome::NOTIFICATION_FIND_MATCH_RECTS_AVAILABLE: |
| + OnFindMatchRectsAvailable(content::Source<WebContents>(source).ptr(), |
| + content::Details<FindMatchRectsDetails>(details).ptr()); |
| + break; |
| + default: |
| + NOTREACHED() << "Unexpected notification: " << type; |
| + break; |
| + } |
| +} |
| + |
| +void ChromeWebContentsDelegateAndroid::FindReply( |
| + WebContents* web_contents, |
| + int request_id, |
| + int number_of_matches, |
| + const gfx::Rect& selection_rect, |
| + int active_match_ordinal, |
| + bool final_update) { |
| + TabContents* tab_contents = TabContents::FromWebContents(web_contents); |
| + if (!tab_contents || !tab_contents->find_tab_helper()) |
|
jam
2012/09/04 16:39:09
will this condition really happen?
Leandro Graciá Gil
2012/09/04 18:25:50
Good catch. We actually removed some of these chec
|
| + return; |
| + |
| + if (!notification_registrar_.IsRegistered(this, |
| + chrome::NOTIFICATION_FIND_RESULT_AVAILABLE, |
| + content::Source<WebContents>(web_contents))) { |
| + notification_registrar_.Add(this, |
| + chrome::NOTIFICATION_FIND_RESULT_AVAILABLE, |
| + content::Source<WebContents>(web_contents)); |
| + } |
| + |
| + tab_contents->find_tab_helper()->HandleFindReply(request_id, |
| + number_of_matches, |
| + selection_rect, |
| + active_match_ordinal, |
| + final_update); |
| +} |
| + |
| +void ChromeWebContentsDelegateAndroid::OnFindResultAvailable( |
| + WebContents* web_contents, |
| + const FindNotificationDetails* find_result) { |
| + DCHECK(web_contents); |
|
jam
2012/09/04 16:39:09
please get rid of these dchecks. if they're null,
Leandro Graciá Gil
2012/09/04 18:25:50
Done.
|
| + DCHECK(find_result); |
| + |
| + JNIEnv* env = AttachCurrentThread(); |
| + ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env); |
| + if (obj.is_null()) |
| + return; |
| + |
| + // Create the selection rect. |
| + ScopedJavaLocalRef<jclass> rect_clazz = |
| + GetClass(env, "android/graphics/Rect"); |
| + |
| + jmethodID rect_constructor = |
| + GetMethodID(env, rect_clazz, "<init>", "(IIII)V"); |
| + |
| + ScopedJavaLocalRef<jobject> selection_rect = CreateAndroidRect( |
| + env, rect_clazz, rect_constructor, find_result->selection_rect()); |
| + |
| + // Create the details object. |
| + ScopedJavaLocalRef<jclass> details_clazz = |
| + GetClass(env, "org/chromium/chrome/browser/FindNotificationDetails"); |
| + |
| + jmethodID details_constructor = GetMethodID(env, details_clazz, "<init>", |
| + "(ILandroid/graphics/Rect;IZ)V"); |
| + |
| + ScopedJavaLocalRef<jobject> details_object( |
| + env, |
| + env->NewObject(details_clazz.obj(), |
| + details_constructor, |
| + find_result->number_of_matches(), |
| + selection_rect.obj(), |
| + find_result->active_match_ordinal(), |
| + find_result->final_update())); |
| + DCHECK(!details_object.is_null()); |
| + |
| + Java_ChromeWebContentsDelegateAndroid_onFindResultAvailable( |
| + env, |
| + obj.obj(), |
| + details_object.obj()); |
| +} |
| + |
| +void ChromeWebContentsDelegateAndroid::GetFindMatchRectsReply( |
| + WebContents* web_contents, |
| + int version, |
| + const std::vector<gfx::RectF>& rects, |
| + const gfx::RectF& active_rect) { |
| + TabContents* tab_contents = TabContents::FromWebContents(web_contents); |
| + if (!tab_contents || !tab_contents->find_tab_helper()) |
| + return; |
| + |
| + if (!notification_registrar_.IsRegistered(this, |
| + chrome::NOTIFICATION_FIND_MATCH_RECTS_AVAILABLE, |
| + content::Source<WebContents>(web_contents))) { |
| + notification_registrar_.Add(this, |
| + chrome::NOTIFICATION_FIND_MATCH_RECTS_AVAILABLE, |
| + content::Source<WebContents>(web_contents)); |
| + } |
| + |
| + tab_contents->find_tab_helper()->HandleGetFindMatchRectsReply( |
| + version, rects, active_rect); |
| +} |
| + |
| +void ChromeWebContentsDelegateAndroid::OnFindMatchRectsAvailable( |
| + WebContents* web_contents, |
| + const FindMatchRectsDetails* match_rects) { |
| + DCHECK(web_contents); |
| + DCHECK(match_rects); |
| + |
| + JNIEnv* env = AttachCurrentThread(); |
| + ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env); |
| + if (obj.is_null()) |
| + return; |
| + |
| + // Create the rects. |
| + ScopedJavaLocalRef<jclass> rect_clazz = |
| + GetClass(env, "android/graphics/RectF"); |
| + |
| + jmethodID rect_constructor = |
| + GetMethodID(env, rect_clazz, "<init>", "(FFFF)V"); |
| + |
| + ScopedJavaLocalRef<jobjectArray> rects(env, env->NewObjectArray( |
| + match_rects->rects().size(), rect_clazz.obj(), NULL)); |
| + |
| + for (size_t i = 0; i < match_rects->rects().size(); ++i) { |
| + env->SetObjectArrayElement( |
| + rects.obj(), i, |
| + CreateAndroidRect(env, |
| + rect_clazz, |
| + rect_constructor, |
| + match_rects->rects()[i]).obj()); |
| + } |
| + |
| + ScopedJavaLocalRef<jobject> active_rect = CreateAndroidRect( |
| + env, rect_clazz, rect_constructor, match_rects->active_rect()); |
| + |
| + // Create the details object. |
| + ScopedJavaLocalRef<jclass> details_clazz = |
| + GetClass(env, "org/chromium/chrome/browser/FindMatchRectsDetails"); |
| + |
| + jmethodID details_constructor = GetMethodID(env, details_clazz, "<init>", |
| + "(I[Landroid/graphics/RectF;Landroid/graphics/RectF;)V"); |
| + |
| + ScopedJavaLocalRef<jobject> details_object( |
| + env, |
| + env->NewObject(details_clazz.obj(), |
| + details_constructor, |
| + match_rects->version(), |
| + rects.obj(), |
| + active_rect.obj())); |
| + DCHECK(!details_object.is_null()); |
| + |
| + Java_ChromeWebContentsDelegateAndroid_onFindMatchRectsAvailable( |
| + env, |
| + obj.obj(), |
| + details_object.obj()); |
| +} |
| + |
| } // namespace android |
| } // namespace chrome |