Index: components/html_viewer/html_frame.cc |
diff --git a/components/html_viewer/html_frame.cc b/components/html_viewer/html_frame.cc |
index edaed4f2c63cd875ffa769a50c1c4d5da377ba7f..73c1d87a8e8a421c86bf93b4472efbdd2b8bdb00 100644 |
--- a/components/html_viewer/html_frame.cc |
+++ b/components/html_viewer/html_frame.cc |
@@ -49,6 +49,7 @@ |
#include "third_party/WebKit/public/web/WebConsoleMessage.h" |
#include "third_party/WebKit/public/web/WebDocument.h" |
#include "third_party/WebKit/public/web/WebElement.h" |
+#include "third_party/WebKit/public/web/WebFindOptions.h" |
#include "third_party/WebKit/public/web/WebInputEvent.h" |
#include "third_party/WebKit/public/web/WebKit.h" |
#include "third_party/WebKit/public/web/WebLocalFrame.h" |
@@ -238,6 +239,14 @@ blink::WebView* HTMLFrame::web_view() { |
: nullptr; |
} |
+blink::WebView* HTMLFrame::web_view() const { |
+ blink::WebWidget* web_widget = |
+ html_widget_ ? html_widget_->GetWidget() : nullptr; |
+ return web_widget && web_widget->isWebView() |
+ ? static_cast<blink::WebView*>(web_widget) |
+ : nullptr; |
+} |
+ |
blink::WebWidget* HTMLFrame::GetWebWidget() { |
return html_widget_ ? html_widget_->GetWidget() : nullptr; |
} |
@@ -466,6 +475,18 @@ void HTMLFrame::didReceiveTitle(blink::WebLocalFrame* frame, |
server_->TitleChanged(formatted); |
} |
+void HTMLFrame::reportFindInPageMatchCount(int identifier, |
+ int count, |
+ bool finalUpdate) { |
+ server_->ReportFindInPageMatchCount(identifier, count, finalUpdate); |
+} |
+ |
+void HTMLFrame::reportFindInPageSelection(int identifier, |
+ int activeMatchOrdinal, |
+ const blink::WebRect& selection) { |
+ server_->ReportFindInPageSelection(identifier, activeMatchOrdinal); |
+} |
+ |
void HTMLFrame::Bind( |
web_view::mojom::FramePtr frame, |
mojo::InterfaceRequest<web_view::mojom::FrameClient> frame_client_request) { |
@@ -617,6 +638,19 @@ void HTMLFrame::SwapDelegate(HTMLFrameDelegate* delegate) { |
delegate->OnSwap(this, old_delegate); |
} |
+blink::WebElement HTMLFrame::GetFocusedElement() const { |
+ if (!web_view()) |
+ return blink::WebElement(); |
+ blink::WebFrame* focused_frame = web_view()->focusedFrame(); |
+ if (focused_frame) { |
+ blink::WebDocument doc = focused_frame->document(); |
+ if (!doc.isNull()) |
+ return doc.focusedElement(); |
+ } |
+ |
+ return blink::WebElement(); |
+} |
+ |
HTMLFrame* HTMLFrame::FindFrameWithWebFrame(blink::WebFrame* web_frame) { |
if (web_frame_ == web_frame) |
return this; |
@@ -806,6 +840,129 @@ void HTMLFrame::OnDispatchFrameLoadEvent(uint32_t frame_id) { |
frame->web_frame_->toWebRemoteFrame()->DispatchLoadEventForFrameOwner(); |
} |
+void HTMLFrame::OnFind(int32 request_id, const mojo::String& search_text) { |
Elliot Glaysher
2015/09/28 21:22:57
This and GetFocusedElement() were copied almost ve
|
+ blink::WebFrame* main_frame = web_view()->mainFrame(); |
+ blink::WebFrame* frame_after_main = main_frame->traverseNext(true); |
+ blink::WebFrame* focused_frame = web_view()->focusedFrame(); |
+ blink::WebFrame* search_frame = |
+ focused_frame; // start searching focused frame. |
+ |
+ bool multi_frame = (frame_after_main != main_frame); |
+ |
+ blink::WebFindOptions options; |
+ |
+ // If we have multiple frames, we don't want to wrap the search within the |
+ // frame, so we check here if we only have main_frame in the chain. |
+ bool wrap_within_frame = !multi_frame; |
+ |
+ blink::WebRect selection_rect; |
+ bool result = false; |
+ |
+ // If something is selected when we start searching it means we cannot just |
+ // increment the current match ordinal; we need to re-generate it. |
+ blink::WebRange current_selection = focused_frame->selectionRange(); |
+ |
+ do { |
+ result = search_frame->find(request_id, search_text.To<blink::WebString>(), |
+ options, wrap_within_frame, &selection_rect); |
+ |
+ if (!result) { |
+ // don't leave text selected as you move to the next frame. |
+ search_frame->executeCommand(blink::WebString::fromUTF8("Unselect"), |
+ GetFocusedElement()); |
+ |
+ // Find the next frame, but skip the invisible ones. |
+ do { |
+ // What is the next frame to search? (we might be going backwards). Note |
+ // that we specify wrap=true so that search_frame never becomes NULL. |
+ search_frame = options.forward ? search_frame->traverseNext(true) |
+ : search_frame->traversePrevious(true); |
+ } while (!search_frame->hasVisibleContent() && |
+ search_frame != focused_frame); |
+ |
+ // Make sure selection doesn't affect the search operation in new frame. |
+ search_frame->executeCommand(blink::WebString::fromUTF8("Unselect"), |
+ GetFocusedElement()); |
+ |
+ // If we have multiple frames and we have wrapped back around to the |
+ // focused frame, we need to search it once more allowing wrap within |
+ // the frame, otherwise it will report 'no match' if the focused frame has |
+ // reported matches, but no frames after the focused_frame contain a |
+ // match for the search word(s). |
+ if (multi_frame && search_frame == focused_frame) { |
+ result = |
+ search_frame->find(request_id, search_text.To<blink::WebString>(), |
+ options, true, // Force wrapping. |
+ &selection_rect); |
+ } |
+ } |
+ |
+ web_view()->setFocusedFrame(search_frame); |
+ } while (!result && search_frame != focused_frame); |
+ |
+ if (options.findNext && current_selection.isNull()) { |
+ // Force the main_frame to report the actual count. |
+ main_frame->increaseMatchCount(0, request_id); |
+ } else { |
+ // If nothing is found, set result to "0 of 0", otherwise, set it to |
+ // "-1 of 1" to indicate that we found at least one item, but we don't know |
+ // yet what is active. |
+ int ordinal = result ? -1 : 0; // -1 here means, we might know more later. |
+ int match_count = result ? 1 : 0; // 1 here means possibly more coming. |
+ |
+ // If we find no matches then this will be our last status update. |
+ // Otherwise the scoping effort will send more results. |
+ bool final_status_update = !result; |
+ |
+ server_->ReportFindInPageSelection(request_id, ordinal); |
+ server_->ReportFindInPageMatchCount(request_id, match_count, |
+ final_status_update); |
+ |
+ // Scoping effort begins, starting with the mainframe. |
+ search_frame = main_frame; |
+ |
+ main_frame->resetMatchCount(); |
+ |
+ do { |
+ // Cancel all old scoping requests before starting a new one. |
+ search_frame->cancelPendingScopingEffort(); |
+ |
+ // We don't start another scoping effort unless at least one match has |
+ // been found. |
+ if (result) { |
+ // Start new scoping request. If the scoping function determines that it |
+ // needs to scope, it will defer until later. |
+ search_frame->scopeStringMatches( |
+ request_id, search_text.To<blink::WebString>(), options, |
+ true); // reset the tickmarks |
+ } |
+ |
+ // Iterate to the next frame. The frame will not necessarily scope, for |
+ // example if it is not visible. |
+ search_frame = search_frame->traverseNext(true); |
+ } while (search_frame != main_frame); |
+ } |
+} |
+ |
+void HTMLFrame::OnStopFinding() { |
+ blink::WebView* view = web_view(); |
+ if (!view) |
+ return; |
+ |
+ // TODO(erg): content has a whole concept about different actions that can be |
+ // done during a stop find. We aren't handling these at all. |
+ bool clear_selection = true; |
+ |
+ view->focusedFrame()->executeCommand(blink::WebString::fromUTF8("Unselect"), |
+ GetFocusedElement()); |
+ |
+ blink::WebFrame* frame = view->mainFrame(); |
+ while (frame) { |
+ frame->stopFinding(clear_selection); |
+ frame = frame->traverseNext(false); |
+ } |
+} |
+ |
void HTMLFrame::frameDetached(blink::WebRemoteFrameClient::DetachType type) { |
if (type == blink::WebRemoteFrameClient::DetachType::Swap) { |
web_frame_->close(); |