Chromium Code Reviews| Index: content/renderer/render_view_impl.cc |
| diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc |
| index 224cb16f4c42e163a00131e049cb9bfa46244295..8e415c5ba48068bd93f52c327d20d2c4b8662112 100644 |
| --- a/content/renderer/render_view_impl.cc |
| +++ b/content/renderer/render_view_impl.cc |
| @@ -612,6 +612,7 @@ RenderViewImpl::RenderViewImpl( |
| mouse_lock_dispatcher_(NULL), |
| #if defined(OS_ANDROID) |
| expected_content_intent_id_(0), |
| + synchronous_find_active_match_ordinal_(-1), |
| #endif |
| session_storage_namespace_id_(session_storage_namespace_id), |
| handling_select_range_(false), |
| @@ -1054,6 +1055,9 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) { |
| IPC_MESSAGE_HANDLER(JavaBridgeMsg_Init, OnJavaBridgeInit) |
| IPC_MESSAGE_HANDLER(ViewMsg_SetAccessibilityMode, OnSetAccessibilityMode) |
| IPC_MESSAGE_HANDLER(ViewMsg_UpdateFrameTree, OnUpdatedFrameTree) |
| +#if defined(OS_ANDROID) |
| + IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewMsg_SynchronousFind, OnSynchronousFind) |
|
jam
2012/09/19 16:55:43
nit: put all the android if-def'd handlers togethe
Leandro Graciá Gil
2012/09/19 18:08:59
Done.
|
| +#endif |
| // Have the super handle all other messages. |
| IPC_MESSAGE_UNHANDLED(handled = RenderWidget::OnMessageReceived(message)) |
| @@ -3894,30 +3898,66 @@ void RenderViewImpl::hasTouchEventHandlers(bool has_handlers) { |
| Send(new ViewHostMsg_HasTouchEventHandlers(routing_id_, has_handlers)); |
| } |
|
jam
2012/09/19 16:55:43
the moving of functions around made this file hard
Leandro Graciá Gil
2012/09/19 18:08:59
Done.
|
| -void RenderViewImpl::reportFindInPageMatchCount(int request_id, int count, |
| +void RenderViewImpl::SendFindReply(int request_id, |
| + int match_count, |
| + int ordinal, |
| + const WebRect& selection_rect, |
| + bool final_status_update) { |
| +#if defined(OS_ANDROID) |
| + // Check if this is a synchronous find request. |
| + if (synchronous_find_pending_message_.get()) { |
| + if (final_status_update) { |
| + ViewMsg_SynchronousFind::WriteReplyParams( |
| + synchronous_find_pending_message_.get(), |
| + match_count, |
| + match_count ? synchronous_find_active_match_ordinal_ : 0); |
| + Send(synchronous_find_pending_message_.release()); |
| + } |
| + return; |
| + } |
| +#endif |
| + |
| + // Send the search result over to the browser process. |
| + Send(new ViewHostMsg_Find_Reply(routing_id_, |
| + request_id, |
| + match_count, |
| + selection_rect, |
| + ordinal, |
| + final_status_update)); |
| +} |
| + |
| +void RenderViewImpl::reportFindInPageMatchCount(int request_id, |
| + int count, |
| bool final_update) { |
| int active_match_ordinal = -1; // -1 = don't update active match ordinal |
| if (!count) |
| active_match_ordinal = 0; |
| - Send(new ViewHostMsg_Find_Reply(routing_id_, |
| - request_id, |
| - count, |
| - gfx::Rect(), |
| - active_match_ordinal, |
| - final_update)); |
| + // Send the search result over to the browser process. |
| + SendFindReply(request_id, |
| + count, |
| + active_match_ordinal, |
| + gfx::Rect(), |
| + final_update); |
| } |
| void RenderViewImpl::reportFindInPageSelection(int request_id, |
| int active_match_ordinal, |
| const WebRect& selection_rect) { |
| - // Send the search result over to the browser process. |
| - Send(new ViewHostMsg_Find_Reply(routing_id_, |
| - request_id, |
| - -1, |
| - selection_rect, |
| - active_match_ordinal, |
| - false)); |
| +#if defined(OS_ANDROID) |
| + // If this was a SynchronousFind request, we need to remember the ordinal |
| + // value here for replying when reportFindInPageMatchCount is called. |
| + if (synchronous_find_pending_message_.get()) { |
| + synchronous_find_active_match_ordinal_ = active_match_ordinal; |
| + return; |
| + } |
| +#endif |
| + |
| + SendFindReply(request_id, |
| + -1, /* number_of_matches */ |
| + active_match_ordinal, |
| + selection_rect, |
| + false /* final_update */); |
| } |
| void RenderViewImpl::openFileSystem( |
| @@ -4376,6 +4416,40 @@ void RenderViewImpl::PlayerGone(WebKit::WebMediaPlayer* player) { |
| DidPause(player); |
| } |
| +void RenderViewImpl::StopFinding(content::StopFindAction action) { |
| + WebView* view = webview(); |
| + if (!view) |
| + return; |
| + |
| + WebDocument doc = view->mainFrame()->document(); |
| + if (doc.isPluginDocument() && GetWebPluginFromPluginDocument()) { |
| + GetWebPluginFromPluginDocument()->stopFind(); |
| + return; |
| + } |
| + |
| + bool clear_selection = action == content::STOP_FIND_ACTION_CLEAR_SELECTION; |
| + if (clear_selection) |
| + view->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect")); |
| + |
| + WebFrame* frame = view->mainFrame(); |
| + while (frame) { |
| + frame->stopFinding(clear_selection); |
| + frame = frame->traverseNext(false); |
| + } |
| + |
| + if (action == content::STOP_FIND_ACTION_ACTIVATE_SELECTION) { |
| + WebFrame* focused_frame = view->focusedFrame(); |
| + if (focused_frame) { |
| + WebDocument doc = focused_frame->document(); |
| + if (!doc.isNull()) { |
| + WebNode node = doc.focusedNode(); |
| + if (!node.isNull()) |
| + node.simulateClick(); |
| + } |
| + } |
| + } |
| +} |
| + |
| void RenderViewImpl::SyncNavigationState() { |
| if (!webview()) |
| return; |
| @@ -4440,93 +4514,8 @@ void RenderViewImpl::SyncSelectionIfRequired() { |
| } |
| } |
| -GURL RenderViewImpl::GetAlternateErrorPageURL(const GURL& failed_url, |
| - ErrorPageType error_type) { |
| - if (failed_url.SchemeIsSecure()) { |
| - // If the URL that failed was secure, then the embedding web page was not |
| - // expecting a network attacker to be able to manipulate its contents. As |
| - // we fetch alternate error pages over HTTP, we would be allowing a network |
| - // attacker to manipulate the contents of the response if we tried to use |
| - // the link doctor here. |
| - return GURL(); |
| - } |
| - |
| - // Grab the base URL from the browser process. |
| - if (!alternate_error_page_url_.is_valid()) |
| - return GURL(); |
| - |
| - // Strip query params from the failed URL. |
| - GURL::Replacements remove_params; |
| - remove_params.ClearUsername(); |
| - remove_params.ClearPassword(); |
| - remove_params.ClearQuery(); |
| - remove_params.ClearRef(); |
| - const GURL url_to_send = failed_url.ReplaceComponents(remove_params); |
| - std::string spec_to_send = url_to_send.spec(); |
| - // Notify link doctor of the url truncation by sending of "?" at the end. |
| - if (failed_url.has_query()) |
| - spec_to_send.append("?"); |
| - |
| - // Construct the query params to send to link doctor. |
| - std::string params(alternate_error_page_url_.query()); |
| - params.append("&url="); |
| - params.append(net::EscapeQueryParamValue(spec_to_send, true)); |
| - params.append("&sourceid=chrome"); |
| - params.append("&error="); |
| - switch (error_type) { |
| - case DNS_ERROR: |
| - params.append("dnserror"); |
| - break; |
| - |
| - case HTTP_404: |
| - params.append("http404"); |
| - break; |
| - |
| - case CONNECTION_ERROR: |
| - params.append("connectionfailure"); |
| - break; |
| - |
| - default: |
| - NOTREACHED() << "unknown ErrorPageType"; |
| - } |
| - |
| - // OK, build the final url to return. |
| - GURL::Replacements link_doctor_params; |
| - link_doctor_params.SetQueryStr(params); |
| - GURL url = alternate_error_page_url_.ReplaceComponents(link_doctor_params); |
| - return url; |
| -} |
| - |
| -GURL RenderViewImpl::GetOpenerUrl() const { |
| - if (opener_id_ == MSG_ROUTING_NONE || opener_suppressed_) |
| - return GURL(); |
| - else |
| - return creator_url_; |
| -} |
| - |
| -GURL RenderViewImpl::GetLoadingUrl(WebKit::WebFrame* frame) const { |
| - WebDataSource* ds = frame->dataSource(); |
| - if (ds->hasUnreachableURL()) |
| - return ds->unreachableURL(); |
| - |
| - const WebURLRequest& request = ds->request(); |
| - return request.url(); |
| -} |
| - |
| -WebUIBindings* RenderViewImpl::GetWebUIBindings() { |
| - if (!web_ui_bindings_.get()) { |
| - web_ui_bindings_.reset(new WebUIBindings( |
| - static_cast<content::RenderView*>(this), routing_id_)); |
| - } |
| - return web_ui_bindings_.get(); |
| -} |
| - |
| -WebKit::WebPlugin* RenderViewImpl::GetWebPluginFromPluginDocument() { |
| - return webview()->mainFrame()->document().to<WebPluginDocument>().plugin(); |
| -} |
| - |
| -void RenderViewImpl::OnFind(int request_id, const string16& search_text, |
| - const WebFindOptions& options) { |
| +void RenderViewImpl::Find(int request_id, const string16& search_text, |
| + const WebFindOptions& options) { |
| WebFrame* main_frame = webview()->mainFrame(); |
| // Check if the plugin still exists in the document. |
| @@ -4536,16 +4525,10 @@ void RenderViewImpl::OnFind(int request_id, const string16& search_text, |
| // Just navigate back/forward. |
| GetWebPluginFromPluginDocument()->selectFindResult(options.forward); |
| } else { |
| - if (GetWebPluginFromPluginDocument()->startFind( |
| + if (!GetWebPluginFromPluginDocument()->startFind( |
| search_text, options.matchCase, request_id)) { |
| - } else { |
| // Send "no results". |
| - Send(new ViewHostMsg_Find_Reply(routing_id_, |
| - request_id, |
| - 0, |
| - gfx::Rect(), |
| - 0, |
| - true)); |
| + SendFindReply(request_id, 0, 0, gfx::Rect(), true); |
| } |
| } |
| return; |
| @@ -4618,13 +4601,8 @@ void RenderViewImpl::OnFind(int request_id, const string16& search_text, |
| // Otherwise the scoping effort will send more results. |
| bool final_status_update = !result; |
| - // Send the search result over to the browser process. |
| - Send(new ViewHostMsg_Find_Reply(routing_id_, |
| - request_id, |
| - match_count, |
| - selection_rect, |
| - ordinal, |
| - final_status_update)); |
| + SendFindReply(request_id, match_count, ordinal, selection_rect, |
| + final_status_update); |
| // Scoping effort begins, starting with the mainframe. |
| search_frame = main_frame; |
| @@ -4653,41 +4631,133 @@ void RenderViewImpl::OnFind(int request_id, const string16& search_text, |
| } |
| } |
| -void RenderViewImpl::OnStopFinding(content::StopFindAction action) { |
| - WebView* view = webview(); |
| - if (!view) |
| - return; |
| - |
| - WebDocument doc = view->mainFrame()->document(); |
| - if (doc.isPluginDocument() && GetWebPluginFromPluginDocument()) { |
| - GetWebPluginFromPluginDocument()->stopFind(); |
| - return; |
| +GURL RenderViewImpl::GetAlternateErrorPageURL(const GURL& failed_url, |
| + ErrorPageType error_type) { |
| + if (failed_url.SchemeIsSecure()) { |
| + // If the URL that failed was secure, then the embedding web page was not |
| + // expecting a network attacker to be able to manipulate its contents. As |
| + // we fetch alternate error pages over HTTP, we would be allowing a network |
| + // attacker to manipulate the contents of the response if we tried to use |
| + // the link doctor here. |
| + return GURL(); |
| } |
| - bool clear_selection = action == content::STOP_FIND_ACTION_CLEAR_SELECTION; |
| - if (clear_selection) |
| - view->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect")); |
| + // Grab the base URL from the browser process. |
| + if (!alternate_error_page_url_.is_valid()) |
| + return GURL(); |
| - WebFrame* frame = view->mainFrame(); |
| - while (frame) { |
| - frame->stopFinding(clear_selection); |
| - frame = frame->traverseNext(false); |
| + // Strip query params from the failed URL. |
| + GURL::Replacements remove_params; |
| + remove_params.ClearUsername(); |
| + remove_params.ClearPassword(); |
| + remove_params.ClearQuery(); |
| + remove_params.ClearRef(); |
| + const GURL url_to_send = failed_url.ReplaceComponents(remove_params); |
| + std::string spec_to_send = url_to_send.spec(); |
| + // Notify link doctor of the url truncation by sending of "?" at the end. |
| + if (failed_url.has_query()) |
| + spec_to_send.append("?"); |
| + |
| + // Construct the query params to send to link doctor. |
| + std::string params(alternate_error_page_url_.query()); |
| + params.append("&url="); |
| + params.append(net::EscapeQueryParamValue(spec_to_send, true)); |
| + params.append("&sourceid=chrome"); |
| + params.append("&error="); |
| + switch (error_type) { |
| + case DNS_ERROR: |
| + params.append("dnserror"); |
| + break; |
| + |
| + case HTTP_404: |
| + params.append("http404"); |
| + break; |
| + |
| + case CONNECTION_ERROR: |
| + params.append("connectionfailure"); |
| + break; |
| + |
| + default: |
| + NOTREACHED() << "unknown ErrorPageType"; |
| } |
| - if (action == content::STOP_FIND_ACTION_ACTIVATE_SELECTION) { |
| - WebFrame* focused_frame = view->focusedFrame(); |
| - if (focused_frame) { |
| - WebDocument doc = focused_frame->document(); |
| - if (!doc.isNull()) { |
| - WebNode node = doc.focusedNode(); |
| - if (!node.isNull()) |
| - node.simulateClick(); |
| - } |
| - } |
| + // OK, build the final url to return. |
| + GURL::Replacements link_doctor_params; |
| + link_doctor_params.SetQueryStr(params); |
| + GURL url = alternate_error_page_url_.ReplaceComponents(link_doctor_params); |
| + return url; |
| +} |
| + |
| +GURL RenderViewImpl::GetOpenerUrl() const { |
| + if (opener_id_ == MSG_ROUTING_NONE || opener_suppressed_) |
| + return GURL(); |
| + else |
| + return creator_url_; |
| +} |
| + |
| +GURL RenderViewImpl::GetLoadingUrl(WebKit::WebFrame* frame) const { |
| + WebDataSource* ds = frame->dataSource(); |
| + if (ds->hasUnreachableURL()) |
| + return ds->unreachableURL(); |
| + |
| + const WebURLRequest& request = ds->request(); |
| + return request.url(); |
| +} |
| + |
| +WebUIBindings* RenderViewImpl::GetWebUIBindings() { |
| + if (!web_ui_bindings_.get()) { |
| + web_ui_bindings_.reset(new WebUIBindings( |
| + static_cast<content::RenderView*>(this), routing_id_)); |
| } |
| + return web_ui_bindings_.get(); |
| +} |
| + |
| +WebKit::WebPlugin* RenderViewImpl::GetWebPluginFromPluginDocument() { |
| + return webview()->mainFrame()->document().to<WebPluginDocument>().plugin(); |
| +} |
| + |
| +void RenderViewImpl::OnFind(int request_id, const string16& search_text, |
| + const WebFindOptions& options) { |
| +#if defined(OS_ANDROID) |
| + // Make sure any asynchronous messages do not disrupt an ongoing synchronous |
| + // find request as it might lead to deadlocks. Also, these should be safe to |
| + // ignore since they would belong to a previous find request. |
| + if (synchronous_find_pending_message_.get()) |
| + return; |
| +#endif |
| + Find(request_id, search_text, options); |
| +} |
| + |
| +void RenderViewImpl::OnStopFinding(content::StopFindAction action) { |
| +#if defined(OS_ANDROID) |
| + // Make sure any asynchronous messages do not disrupt an ongoing synchronous |
| + // find request as it might lead to deadlocks. Also, these should be safe to |
| + // ignore since they would belong to a previous find request. |
| + if (synchronous_find_pending_message_.get()) |
| + return; |
| +#endif |
| + |
| + StopFinding(action); |
| } |
| #if defined(OS_ANDROID) |
| +void RenderViewImpl::OnSynchronousFind(int request_id, |
| + const string16& search_string, |
| + const WebFindOptions& options, |
| + IPC::Message* reply_msg) { |
| + // It is impossible for simultaneous blocking finds to occur. |
| + DCHECK(!synchronous_find_pending_message_.get()); |
|
jam
2012/09/19 16:55:43
nit: make this a CHECK instead?
Leandro Graciá Gil
2012/09/19 18:08:59
Done.
|
| + synchronous_find_pending_message_.reset(reply_msg); |
| + |
| + // Find next should be asynchronous in order to minimize blocking |
| + // the UI thread as much as possible. |
| + DCHECK(!options.findNext); |
| + StopFinding(content::STOP_FIND_ACTION_KEEP_SELECTION); |
| + synchronous_find_active_match_ordinal_ = -1; |
| + |
| + Find(request_id, search_string, options); |
| +} |
| + |
| void RenderViewImpl::OnActivateNearestFindResult(int request_id, |
| float x, float y) { |
| if (!webview()) |
| @@ -4705,12 +4775,11 @@ void RenderViewImpl::OnActivateNearestFindResult(int request_id, |
| return; |
| } |
| - Send(new ViewHostMsg_Find_Reply(routing_id_, |
| - request_id, |
| - -1 /* number_of_matches */, |
| - selection_rect, |
| - ordinal, |
| - true /* final_update */)); |
| + SendFindReply(request_id, |
| + -1 /* number_of_matches */, |
| + ordinal, |
| + selection_rect, |
| + true /* final_update */); |
| } |
| void RenderViewImpl::OnFindMatchRects(int current_version) { |