Prevent guest views from issuing a search for empty text.
Do the same for Android webview. Set up roadblocks along the way to prevent this from happening again. BUG=535086 Review URL: https://codereview.chromium.org/1365563003 Cr-Commit-Position: refs/heads/master@{#359419}
This commit is contained in:
android_webview/browser
chrome/test/data/extensions/platform_apps/web_view/shim
content
extensions
pdf
ppapi/cpp/private
@ -18,14 +18,12 @@ namespace android_webview {
|
||||
|
||||
FindHelper::FindHelper(WebContents* web_contents)
|
||||
: WebContentsObserver(web_contents),
|
||||
listener_(NULL),
|
||||
listener_(nullptr),
|
||||
async_find_started_(false),
|
||||
sync_find_started_(false),
|
||||
find_request_id_counter_(0),
|
||||
current_request_id_(0),
|
||||
last_match_count_(-1),
|
||||
last_active_ordinal_(-1),
|
||||
weak_factory_(this) {
|
||||
last_active_ordinal_(-1) {
|
||||
}
|
||||
|
||||
FindHelper::~FindHelper() {
|
||||
@ -39,32 +37,36 @@ void FindHelper::FindAllAsync(const base::string16& search_string) {
|
||||
// Stop any ongoing asynchronous request.
|
||||
web_contents()->StopFinding(content::STOP_FIND_ACTION_KEEP_SELECTION);
|
||||
|
||||
sync_find_started_ = false;
|
||||
async_find_started_ = true;
|
||||
|
||||
StartNewRequest(search_string);
|
||||
|
||||
if (MaybeHandleEmptySearch(search_string))
|
||||
return;
|
||||
|
||||
WebFindOptions options;
|
||||
options.forward = true;
|
||||
options.matchCase = false;
|
||||
options.findNext = false;
|
||||
|
||||
StartNewRequest(search_string);
|
||||
web_contents()->Find(current_request_id_, search_string, options);
|
||||
}
|
||||
|
||||
void FindHelper::HandleFindReply(int request_id,
|
||||
int match_count,
|
||||
int active_ordinal,
|
||||
bool finished) {
|
||||
if ((!async_find_started_ && !sync_find_started_) ||
|
||||
request_id != current_request_id_) {
|
||||
int match_count,
|
||||
int active_ordinal,
|
||||
bool finished) {
|
||||
if (!async_find_started_ || request_id != current_request_id_)
|
||||
return;
|
||||
}
|
||||
|
||||
NotifyResults(active_ordinal, match_count, finished);
|
||||
}
|
||||
|
||||
void FindHelper::FindNext(bool forward) {
|
||||
if (!sync_find_started_ && !async_find_started_)
|
||||
if (!async_find_started_)
|
||||
return;
|
||||
|
||||
if (MaybeHandleEmptySearch(last_search_string_))
|
||||
return;
|
||||
|
||||
WebFindOptions options;
|
||||
@ -78,13 +80,21 @@ void FindHelper::FindNext(bool forward) {
|
||||
void FindHelper::ClearMatches() {
|
||||
web_contents()->StopFinding(content::STOP_FIND_ACTION_CLEAR_SELECTION);
|
||||
|
||||
sync_find_started_ = false;
|
||||
async_find_started_ = false;
|
||||
last_search_string_.clear();
|
||||
last_match_count_ = -1;
|
||||
last_active_ordinal_ = -1;
|
||||
}
|
||||
|
||||
bool FindHelper::MaybeHandleEmptySearch(const base::string16& search_string) {
|
||||
if (!search_string.empty())
|
||||
return false;
|
||||
|
||||
web_contents()->StopFinding(content::STOP_FIND_ACTION_CLEAR_SELECTION);
|
||||
NotifyResults(0, 0, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void FindHelper::StartNewRequest(const base::string16& search_string) {
|
||||
current_request_id_ = find_request_id_counter_++;
|
||||
last_search_string_ = search_string;
|
||||
@ -93,9 +103,9 @@ void FindHelper::StartNewRequest(const base::string16& search_string) {
|
||||
}
|
||||
|
||||
void FindHelper::NotifyResults(int active_ordinal,
|
||||
int match_count,
|
||||
bool finished) {
|
||||
// Match count or ordinal values set to -1 refer to the received replies.
|
||||
int match_count,
|
||||
bool finished) {
|
||||
// Match count or ordinal values set to -1 refer to received replies.
|
||||
if (match_count == -1)
|
||||
match_count = last_match_count_;
|
||||
else
|
||||
|
@ -5,7 +5,6 @@
|
||||
#ifndef ANDROID_WEBVIEW_BROWSER_FIND_HELPER_H_
|
||||
#define ANDROID_WEBVIEW_BROWSER_FIND_HELPER_H_
|
||||
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
|
||||
namespace android_webview {
|
||||
@ -28,7 +27,7 @@ class FindHelper : public content::WebContentsObserver {
|
||||
~FindHelper() override;
|
||||
|
||||
// Sets the listener to receive find result updates.
|
||||
// Does not own the listener and must set to NULL when invalid.
|
||||
// Does not own the listener and must set to nullptr when invalid.
|
||||
void SetListener(Listener* listener);
|
||||
|
||||
// Asynchronous API.
|
||||
@ -44,6 +43,7 @@ class FindHelper : public content::WebContentsObserver {
|
||||
|
||||
private:
|
||||
void StartNewRequest(const base::string16& search_string);
|
||||
bool MaybeHandleEmptySearch(const base::string16& search_string);
|
||||
void NotifyResults(int active_ordinal, int match_count, bool finished);
|
||||
|
||||
// Listener results are reported to.
|
||||
@ -51,7 +51,6 @@ class FindHelper : public content::WebContentsObserver {
|
||||
|
||||
// Used to check the validity of FindNext operations.
|
||||
bool async_find_started_;
|
||||
bool sync_find_started_;
|
||||
|
||||
// Used to provide different ids to each request and for result
|
||||
// verification in asynchronous calls.
|
||||
@ -63,9 +62,6 @@ class FindHelper : public content::WebContentsObserver {
|
||||
int last_match_count_;
|
||||
int last_active_ordinal_;
|
||||
|
||||
// Used to post synchronous result notifications to ourselves.
|
||||
base::WeakPtrFactory<FindHelper> weak_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(FindHelper);
|
||||
};
|
||||
|
||||
|
@ -2477,13 +2477,22 @@ function testFindAPI() {
|
||||
|
||||
var loadstopListener2 = function(e) {
|
||||
embedder.test.assertEq(webview.src, "about:blank");
|
||||
embedder.test.succeed();
|
||||
// Test find results when looking for nothing.
|
||||
webview.find("", {}, function(results) {
|
||||
embedder.test.assertEq(results.numberOfMatches, 0);
|
||||
embedder.test.assertEq(results.activeMatchOrdinal, 0);
|
||||
embedder.test.assertEq(results.selectionRect.left, 0);
|
||||
embedder.test.assertEq(results.selectionRect.top, 0);
|
||||
embedder.test.assertEq(results.selectionRect.width, 0);
|
||||
embedder.test.assertEq(results.selectionRect.height, 0);
|
||||
|
||||
embedder.test.succeed();
|
||||
});
|
||||
}
|
||||
|
||||
var loadstopListener1 = function(e) {
|
||||
// Test find results.
|
||||
webview.find("dog", {}, function(results) {
|
||||
callbackTest = true;
|
||||
embedder.test.assertEq(results.numberOfMatches, 100);
|
||||
embedder.test.assertTrue(results.selectionRect.width > 0);
|
||||
embedder.test.assertTrue(results.selectionRect.height > 0);
|
||||
|
@ -2774,6 +2774,12 @@ bool WebContentsImpl::IsSubframe() const {
|
||||
void WebContentsImpl::Find(int request_id,
|
||||
const base::string16& search_text,
|
||||
const blink::WebFindOptions& options) {
|
||||
// Cowardly refuse to search for no text.
|
||||
if (search_text.empty()) {
|
||||
NOTREACHED();
|
||||
return;
|
||||
}
|
||||
|
||||
// See if a top level browser plugin handles the find request first.
|
||||
if (browser_plugin_embedder_ &&
|
||||
browser_plugin_embedder_->Find(request_id, search_text, options)) {
|
||||
|
@ -640,7 +640,7 @@ class WebContents : public PageNavigator,
|
||||
// removed since we can then embed iframes in different processes.
|
||||
virtual bool IsSubframe() const = 0;
|
||||
|
||||
// Finds text on a page.
|
||||
// Finds text on a page. |search_text| should not be empty.
|
||||
virtual void Find(int request_id,
|
||||
const base::string16& search_text,
|
||||
const blink::WebFindOptions& options) = 0;
|
||||
|
@ -364,7 +364,6 @@ static bool DeviceScaleEnsuresTextQuality(float device_scale_factor) {
|
||||
// devices main thread antialiasing is a heavy burden.
|
||||
return device_scale_factor >= 1.5f;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static bool PreferCompositingToLCDText(CompositorDependencies* compositor_deps,
|
||||
@ -672,7 +671,7 @@ void RenderViewImpl::Initialize(const ViewMsg_New_Params& params,
|
||||
if (opener_view_routing_id != MSG_ROUTING_NONE && was_created_by_renderer)
|
||||
opener_id_ = opener_view_routing_id;
|
||||
|
||||
display_mode_= params.initial_size.display_mode;
|
||||
display_mode_ = params.initial_size.display_mode;
|
||||
|
||||
// Ensure we start with a valid next_page_id_ from the browser.
|
||||
DCHECK_GE(next_page_id_, 0);
|
||||
@ -2269,6 +2268,8 @@ blink::WebPlugin* RenderViewImpl::GetWebPluginForFind() {
|
||||
void RenderViewImpl::OnFind(int request_id,
|
||||
const base::string16& search_text,
|
||||
const WebFindOptions& options) {
|
||||
DCHECK(!search_text.empty());
|
||||
|
||||
WebFrame* main_frame = webview()->mainFrame();
|
||||
blink::WebPlugin* plugin = GetWebPluginForFind();
|
||||
// Check if the plugin still exists in the document.
|
||||
@ -3042,7 +3043,7 @@ void RenderViewImpl::OnWasHidden() {
|
||||
(*plugin_it)->SetContainerVisibility(false);
|
||||
}
|
||||
#endif // OS_MACOSX
|
||||
#endif // ENABLE_PLUGINS
|
||||
#endif // ENABLE_PLUGINS
|
||||
}
|
||||
|
||||
void RenderViewImpl::OnWasShown(bool needs_repainting,
|
||||
|
@ -132,6 +132,13 @@ void WebViewFindHelper::Find(
|
||||
if (!full_options->findNext)
|
||||
current_find_session_ = insert_result.first->second;
|
||||
|
||||
// Handle the empty |search_text| case internally.
|
||||
if (search_text.empty()) {
|
||||
guest_web_contents->StopFinding(content::STOP_FIND_ACTION_CLEAR_SELECTION);
|
||||
FindReply(current_find_request_id_, 0, gfx::Rect(), 0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
guest_web_contents->Find(current_find_request_id_,
|
||||
search_text, *full_options);
|
||||
}
|
||||
|
@ -739,13 +739,22 @@ function testFindAPI() {
|
||||
|
||||
var loadstopListener2 = function(e) {
|
||||
embedder.test.assertEq(webview.src, "about:blank");
|
||||
embedder.test.succeed();
|
||||
// Test find results when looking for nothing.
|
||||
webview.find("", {}, function(results) {
|
||||
embedder.test.assertEq(results.numberOfMatches, 0);
|
||||
embedder.test.assertEq(results.activeMatchOrdinal, 0);
|
||||
embedder.test.assertEq(results.selectionRect.left, 0);
|
||||
embedder.test.assertEq(results.selectionRect.top, 0);
|
||||
embedder.test.assertEq(results.selectionRect.width, 0);
|
||||
embedder.test.assertEq(results.selectionRect.height, 0);
|
||||
|
||||
embedder.test.succeed();
|
||||
});
|
||||
}
|
||||
|
||||
var loadstopListener1 = function(e) {
|
||||
// Test find results.
|
||||
webview.find("dog", {}, function(results) {
|
||||
callbackTest = true;
|
||||
embedder.test.assertEq(results.numberOfMatches, 100);
|
||||
embedder.test.assertTrue(results.selectionRect.width > 0);
|
||||
embedder.test.assertTrue(results.selectionRect.height > 0);
|
||||
|
@ -664,8 +664,8 @@ bool OutOfProcessInstance::IsPrintScalingDisabled() {
|
||||
}
|
||||
|
||||
bool OutOfProcessInstance::StartFind(const std::string& text,
|
||||
bool case_sensitive) {
|
||||
engine_->StartFind(text.c_str(), case_sensitive);
|
||||
bool case_sensitive) {
|
||||
engine_->StartFind(text, case_sensitive);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ class PDFEngine {
|
||||
uint32_t page_range_count,
|
||||
const PP_PrintSettings_Dev& print_settings) = 0;
|
||||
virtual void PrintEnd() = 0;
|
||||
virtual void StartFind(const char* text, bool case_sensitive) = 0;
|
||||
virtual void StartFind(const std::string& text, bool case_sensitive) = 0;
|
||||
virtual bool SelectFindResult(bool forward) = 0;
|
||||
virtual void StopFind() = 0;
|
||||
virtual void ZoomUpdated(double new_zoom_level) = 0;
|
||||
|
@ -1232,7 +1232,7 @@ void PDFiumEngine::UnsupportedFeature(int type) {
|
||||
}
|
||||
|
||||
void PDFiumEngine::ContinueFind(int32_t result) {
|
||||
StartFind(current_find_text_.c_str(), !!result);
|
||||
StartFind(current_find_text_, result != 0);
|
||||
}
|
||||
|
||||
bool PDFiumEngine::HandleEvent(const pp::InputEvent& event) {
|
||||
@ -1909,16 +1909,20 @@ bool PDFiumEngine::OnChar(const pp::KeyboardInputEvent& event) {
|
||||
event.GetModifiers());
|
||||
}
|
||||
|
||||
void PDFiumEngine::StartFind(const char* text, bool case_sensitive) {
|
||||
// We can get a call to StartFind before we have any page information (i.e.
|
||||
void PDFiumEngine::StartFind(const std::string& text, bool case_sensitive) {
|
||||
// If the caller asks StartFind() to search for no text, then this is an
|
||||
// error on the part of the caller. The PPAPI Find_Private interface
|
||||
// guarantees it is not empty, so this should never happen.
|
||||
DCHECK(!text.empty());
|
||||
|
||||
// If StartFind() gets called before we have any page information (i.e.
|
||||
// before the first call to LoadDocument has happened). Handle this case.
|
||||
if (pages_.empty())
|
||||
return;
|
||||
|
||||
bool first_search = false;
|
||||
bool first_search = (current_find_text_ != text);
|
||||
int character_to_start_searching_from = 0;
|
||||
if (current_find_text_ != text) { // First time we search for this text.
|
||||
first_search = true;
|
||||
if (first_search) {
|
||||
std::vector<PDFiumRange> old_selection = selection_;
|
||||
StopFind();
|
||||
current_find_text_ = text;
|
||||
@ -3432,7 +3436,7 @@ void PDFiumEngine::RotateInternal() {
|
||||
if (!current_find_text.empty()) {
|
||||
// Clear the UI.
|
||||
client_->NotifyNumberOfFindResultsChanged(0, false);
|
||||
StartFind(current_find_text.c_str(), false);
|
||||
StartFind(current_find_text, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ class PDFiumEngine : public PDFEngine,
|
||||
uint32_t page_range_count,
|
||||
const PP_PrintSettings_Dev& print_settings);
|
||||
virtual void PrintEnd();
|
||||
virtual void StartFind(const char* text, bool case_sensitive);
|
||||
virtual void StartFind(const std::string& text, bool case_sensitive);
|
||||
virtual bool SelectFindResult(bool forward);
|
||||
virtual void StopFind();
|
||||
virtual void ZoomUpdated(double new_zoom_level);
|
||||
|
@ -26,6 +26,10 @@ PP_Bool StartFind(PP_Instance instance,
|
||||
void* object = Instance::GetPerInstanceObject(instance, kPPPFindInterface);
|
||||
if (!object)
|
||||
return PP_FALSE;
|
||||
if (!text || text[0] == '\0') {
|
||||
PP_NOTREACHED();
|
||||
return PP_FALSE;
|
||||
}
|
||||
bool return_value = static_cast<Find_Private*>(object)->StartFind(
|
||||
text, PP_ToBool(case_sensitive));
|
||||
return PP_FromBool(return_value);
|
||||
|
Reference in New Issue
Block a user