diff options
author | leandrogracia@chromium.org <leandrogracia@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-05 03:46:31 +0000 |
---|---|---|
committer | leandrogracia@chromium.org <leandrogracia@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-05 03:46:31 +0000 |
commit | 59363fc9eb86572b33961caffa9ea11da23d78de (patch) | |
tree | 2ccd23b566f9b630e8b42d8d7c6704cfcbb9f546 /chrome | |
parent | a20a5f4e9a157e484243ac47118345e646cd9f41 (diff) | |
download | chromium_src-59363fc9eb86572b33961caffa9ea11da23d78de.zip chromium_src-59363fc9eb86572b33961caffa9ea11da23d78de.tar.gz chromium_src-59363fc9eb86572b33961caffa9ea11da23d78de.tar.bz2 |
Upstream the Android port find-in-page feature.
This patch provides the find-in-page Chromium code for the Android port.
Further code implementing the feature for Android WebView will be added later in a different patch.
Unlike the previous approach (CL 10699024) this patch uses the FindTabHelper class as Desktop Chrome does, introducing its new required APIs there. It also introduces FindMatchRects in a way symmetrical to the current Find/FindReply implementation in order to simplify any possible future adoption of this API by other platforms.
BUG=136762
Review URL: https://chromiumcodereview.appspot.com/10905058
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@154893 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
12 files changed, 415 insertions, 1 deletions
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeWebContentsDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeWebContentsDelegateAndroid.java index 73317b1..3e7a58a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeWebContentsDelegateAndroid.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeWebContentsDelegateAndroid.java @@ -4,6 +4,7 @@ package org.chromium.chrome.browser; +import org.chromium.base.CalledByNative; import org.chromium.chrome.browser.component.web_contents_delegate_android.WebContentsDelegateAndroid; /** @@ -13,4 +14,12 @@ import org.chromium.chrome.browser.component.web_contents_delegate_android.WebCo * These methods belong to the Chromium Android port but not to WebView. */ public class ChromeWebContentsDelegateAndroid extends WebContentsDelegateAndroid { + + @CalledByNative + public void onFindResultAvailable(FindNotificationDetails result) { + } + + @CalledByNative + public void onFindMatchRectsAvailable(FindMatchRectsDetails result) { + } } diff --git a/chrome/android/java/src/org/chromium/chrome/browser/FindMatchRectsDetails.java b/chrome/android/java/src/org/chromium/chrome/browser/FindMatchRectsDetails.java new file mode 100644 index 0000000..a0575d3 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/FindMatchRectsDetails.java @@ -0,0 +1,28 @@ +// 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. + +package org.chromium.chrome.browser; + +import android.graphics.RectF; + +/** + * Java equivalent to the C++ FindMatchRectsDetails class + * defined in chrome/browser/ui/find_bar/find_match_rects_details.h + */ +public class FindMatchRectsDetails { + /** Version of the the rects in this result. */ + public final int version; + + /** Rects of the find matches in find-in-page coordinates. */ + public final RectF[] rects; + + /** Rect of the active match in find-in-page coordinates. */ + public final RectF activeRect; + + public FindMatchRectsDetails(int version, RectF[] rects, RectF activeRect) { + this.version = version; + this.rects = rects; + this.activeRect = activeRect; + } +} diff --git a/chrome/android/java/src/org/chromium/chrome/browser/FindNotificationDetails.java b/chrome/android/java/src/org/chromium/chrome/browser/FindNotificationDetails.java new file mode 100644 index 0000000..ed8058e --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/FindNotificationDetails.java @@ -0,0 +1,40 @@ +// 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. + +package org.chromium.chrome.browser; + +import android.graphics.Rect; + +/** + * Java equivalent to the C++ FindNotificationDetails class + * defined in chrome/browser/ui/find_bar/find_notification_details.h + */ +public class FindNotificationDetails { + /** How many matches were found. */ + public final int numberOfMatches; + + /** Where selection occurred (in renderer window coordinates). */ + public final Rect rendererSelectionRect; + + /** + * The ordinal of the currently selected match. + * + * Might be -1 even with matches in rare edge cases where the active match + * has been removed from DOM by the time the active ordinals are processed. + * This indicates we failed to locate and highlight the active match. + */ + public final int activeMatchOrdinal; + + /** Whether this is the last Find Result update for the request. */ + public final boolean finalUpdate; + + public FindNotificationDetails( + int numberOfMatches, Rect rendererSelectionRect, + int activeMatchOrdinal, boolean finalUpdate) { + this.numberOfMatches = numberOfMatches; + this.rendererSelectionRect = rendererSelectionRect; + this.activeMatchOrdinal = activeMatchOrdinal; + this.finalUpdate = finalUpdate; + } +} diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc index a768c22..7f1ccaf 100644 --- a/chrome/browser/android/chrome_jni_registrar.cc +++ b/chrome/browser/android/chrome_jni_registrar.cc @@ -6,6 +6,7 @@ #include "base/android/jni_android.h" #include "base/android/jni_registrar.h" +#include "chrome/browser/android/chrome_web_contents_delegate_android.h" #include "chrome/browser/android/content_view_util.h" #include "chrome/browser/android/intent_helper.h" #include "chrome/browser/android/process_utils.h" @@ -17,6 +18,8 @@ namespace chrome { namespace android { static base::android::RegistrationMethod kChromeRegisteredMethods[] = { + { "ChromeWebContentsDelegateAndroid", + RegisterChromeWebContentsDelegateAndroid }, { "ContentViewUtil", RegisterContentViewUtil }, { "IntentHelper", RegisterIntentHelper }, { "JavascriptAppModalDialog", diff --git a/chrome/browser/android/chrome_web_contents_delegate_android.cc b/chrome/browser/android/chrome_web_contents_delegate_android.cc index 56163c4..84d2685 100644 --- a/chrome/browser/android/chrome_web_contents_delegate_android.cc +++ b/chrome/browser/android/chrome_web_contents_delegate_android.cc @@ -6,8 +6,19 @@ #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_service.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 +26,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 +61,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 +75,159 @@ 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)); + } + + 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(), + content::Details<FindNotificationDetails>(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) { + 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)); + } + + TabContents* tab_contents = TabContents::FromWebContents(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) { + 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::FindMatchRectsReply( + WebContents* web_contents, + int version, + const std::vector<gfx::RectF>& rects, + const gfx::RectF& active_rect) { + FindMatchRectsDetails match_rects(version, rects, active_rect); + content::NotificationService::current()->Notify( + chrome::NOTIFICATION_FIND_MATCH_RECTS_AVAILABLE, + content::Source<WebContents>(web_contents), + content::Details<FindMatchRectsDetails>(&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> jrects(env, env->NewObjectArray( + match_rects.rects().size(), rect_clazz.obj(), NULL)); + + for (size_t i = 0; i < match_rects.rects().size(); ++i) { + env->SetObjectArrayElement( + jrects.obj(), i, + CreateAndroidRect(env, + rect_clazz, + rect_constructor, + match_rects.rects()[i]).obj()); + } + + ScopedJavaLocalRef<jobject> jactive_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(), + jrects.obj(), + jactive_rect.obj())); + DCHECK(!details_object.is_null()); + + Java_ChromeWebContentsDelegateAndroid_onFindMatchRectsAvailable( + env, + obj.obj(), + details_object.obj()); +} + } // namespace android } // namespace chrome diff --git a/chrome/browser/android/chrome_web_contents_delegate_android.h b/chrome/browser/android/chrome_web_contents_delegate_android.h index beba28f..dea38f8 100644 --- a/chrome/browser/android/chrome_web_contents_delegate_android.h +++ b/chrome/browser/android/chrome_web_contents_delegate_android.h @@ -8,12 +8,21 @@ #include <jni.h> #include "chrome/browser/component/web_contents_delegate_android/web_contents_delegate_android.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" + +class FindNotificationDetails; namespace content { struct FileChooserParams; class WebContents; } +namespace gfx { +class Rect; +class RectF; +} + namespace chrome { namespace android { @@ -21,7 +30,8 @@ namespace android { // Should contain any WebContentsDelegate implementations required by // the Chromium Android port but not to be shared with WebView. class ChromeWebContentsDelegateAndroid - : public web_contents_delegate_android::WebContentsDelegateAndroid { + : public web_contents_delegate_android::WebContentsDelegateAndroid, + public content::NotificationObserver { public: ChromeWebContentsDelegateAndroid(JNIEnv* env, jobject obj); virtual ~ChromeWebContentsDelegateAndroid(); @@ -29,8 +39,33 @@ class ChromeWebContentsDelegateAndroid virtual void RunFileChooser(content::WebContents* web_contents, const content::FileChooserParams& params) OVERRIDE; + virtual void CloseContents(content::WebContents* web_contents) OVERRIDE; + virtual void FindReply(content::WebContents* web_contents, + int request_id, + int number_of_matches, + const gfx::Rect& selection_rect, + int active_match_ordinal, + bool final_update) OVERRIDE; + virtual void FindMatchRectsReply(content::WebContents* web_contents, + int version, + const std::vector<gfx::RectF>& rects, + const gfx::RectF& active_rect) OVERRIDE; + + private: + // NotificationObserver implementation. + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; + + void OnFindResultAvailable(content::WebContents* web_contents, + const FindNotificationDetails* find_result); + + content::NotificationRegistrar notification_registrar_; }; +// Register the native methods through JNI. +bool RegisterChromeWebContentsDelegateAndroid(JNIEnv* env); + } // namespace android } // namespace chrome diff --git a/chrome/browser/ui/find_bar/find_match_rects_details.cc b/chrome/browser/ui/find_bar/find_match_rects_details.cc new file mode 100644 index 0000000..7e8e9da --- /dev/null +++ b/chrome/browser/ui/find_bar/find_match_rects_details.cc @@ -0,0 +1,21 @@ +// 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 "chrome/browser/ui/find_bar/find_match_rects_details.h" + +FindMatchRectsDetails::FindMatchRectsDetails() + : version_(-1) { +} + +FindMatchRectsDetails::FindMatchRectsDetails( + int version, + const std::vector<gfx::RectF>& rects, + const gfx::RectF& active_rect) + : version_(version), + rects_(rects), + active_rect_(active_rect) { +} + +FindMatchRectsDetails::~FindMatchRectsDetails() { +} diff --git a/chrome/browser/ui/find_bar/find_match_rects_details.h b/chrome/browser/ui/find_bar/find_match_rects_details.h new file mode 100644 index 0000000..98c0380 --- /dev/null +++ b/chrome/browser/ui/find_bar/find_match_rects_details.h @@ -0,0 +1,41 @@ +// 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. + +#ifndef CHROME_BROWSER_UI_FIND_BAR_FIND_MATCH_RECTS_DETAILS_H_ +#define CHROME_BROWSER_UI_FIND_BAR_FIND_MATCH_RECTS_DETAILS_H_ + +#include <vector> + +#include "base/basictypes.h" +#include "ui/gfx/rect_f.h" + +// Holds the result details of a RequestFindMatchRects reply. +class FindMatchRectsDetails { + public: + FindMatchRectsDetails(); + + FindMatchRectsDetails(int version, + const std::vector<gfx::RectF>& rects, + const gfx::RectF& active_rect); + + ~FindMatchRectsDetails(); + + int version() const { return version_; } + + const std::vector<gfx::RectF>& rects() const { return rects_; } + + const gfx::RectF& active_rect() const { return active_rect_; } + + private: + // The version of the rects in this structure. + int version_; + + // The rects of the find matches in find-in-page coordinates. + std::vector<gfx::RectF> rects_; + + // The rect of the active find match in find-in-page coordinates. + gfx::RectF active_rect_; +}; + +#endif // CHROME_BROWSER_UI_FIND_BAR_FIND_MATCH_RECTS_DETAILS_H_ diff --git a/chrome/browser/ui/find_bar/find_tab_helper.cc b/chrome/browser/ui/find_bar/find_tab_helper.cc index 7b9dee1..d3b5591 100644 --- a/chrome/browser/ui/find_bar/find_tab_helper.cc +++ b/chrome/browser/ui/find_bar/find_tab_helper.cc @@ -15,6 +15,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/common/stop_find_action.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFindOptions.h" +#include "ui/gfx/rect_f.h" using WebKit::WebFindOptions; using content::WebContents; @@ -124,6 +125,20 @@ void FindTabHelper::StopFinding( web_contents()->GetRenderViewHost()->StopFinding(action); } +#if defined(OS_ANDROID) +void FindTabHelper::ActivateNearestFindResult(float x, float y) { + if (!find_op_aborted_ && !find_text_.empty()) { + web_contents()->GetRenderViewHost()->ActivateNearestFindResult( + current_find_request_id_, x, y); + } +} + +void FindTabHelper::RequestFindMatchRects(int current_version) { + if (!find_op_aborted_ && !find_text_.empty()) + web_contents()->GetRenderViewHost()->RequestFindMatchRects(current_version); +} +#endif + void FindTabHelper::HandleFindReply(int request_id, int number_of_matches, const gfx::Rect& selection_rect, diff --git a/chrome/browser/ui/find_bar/find_tab_helper.h b/chrome/browser/ui/find_bar/find_tab_helper.h index be11ed9..db31cd9 100644 --- a/chrome/browser/ui/find_bar/find_tab_helper.h +++ b/chrome/browser/ui/find_bar/find_tab_helper.h @@ -9,6 +9,10 @@ #include "chrome/browser/ui/find_bar/find_notification_details.h" #include "content/public/browser/web_contents_observer.h" +namespace gfx { +class RectF; +} + // Per-tab find manager. Handles dealing with the life cycle of find sessions. class FindTabHelper : public content::WebContentsObserver { public: @@ -57,6 +61,15 @@ class FindTabHelper : public content::WebContentsObserver { return last_search_result_; } +#if defined(OS_ANDROID) + // Selects and zooms to the find result nearest to the point (x,y) + // defined in find-in-page coordinates. + void ActivateNearestFindResult(float x, float y); + + // Asks the renderer to send the rects of the current find matches. + void RequestFindMatchRects(int current_version); +#endif + void HandleFindReply(int request_id, int number_of_matches, const gfx::Rect& selection_rect, diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index f284d08..beda654 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -4456,6 +4456,8 @@ 'chrome_browser_jni_headers', ], 'sources': [ + 'browser/ui/find_bar/find_match_rects_details.cc', + 'browser/ui/find_bar/find_match_rects_details.h', 'browser/ui/webui/ntp/android/bookmarks_handler.cc', 'browser/ui/webui/ntp/android/bookmarks_handler.h', 'browser/ui/webui/ntp/android/context_menu_handler.cc', @@ -5052,6 +5054,7 @@ 'sources': [ 'android/java/src/org/chromium/chrome/browser/AndroidProtocolAdapter.java', 'android/java/src/org/chromium/chrome/browser/ChromeHttpAuthHandler.java', + 'android/java/src/org/chromium/chrome/browser/ChromeWebContentsDelegateAndroid.java', 'android/java/src/org/chromium/chrome/browser/ContentViewUtil.java', 'android/java/src/org/chromium/chrome/browser/IntentHelper.java', 'android/java/src/org/chromium/chrome/browser/JavascriptAppModalDialog.java', diff --git a/chrome/common/chrome_notification_types.h b/chrome/common/chrome_notification_types.h index 0366704..103edcf 100644 --- a/chrome/common/chrome_notification_types.h +++ b/chrome/common/chrome_notification_types.h @@ -5,6 +5,7 @@ #ifndef CHROME_COMMON_CHROME_NOTIFICATION_TYPES_H_ #define CHROME_COMMON_CHROME_NOTIFICATION_TYPES_H_ +#include "build/build_config.h" #include "content/public/browser/notification_types.h" namespace chrome { @@ -198,6 +199,14 @@ enum NotificationType { // match was found or not found. NOTIFICATION_FIND_RESULT_AVAILABLE, +#if defined(OS_ANDROID) + // This notification is sent when the match rects of a find-in-page search + // are available. The source is a Source<WebContents>. Details encompass a + // FindMatchRectsDetails object that contains the result version and the + // rects information. + NOTIFICATION_FIND_MATCH_RECTS_AVAILABLE, +#endif + // BackgroundContents ------------------------------------------------------ // A new background contents was opened by script. The source is the parent |