Chromium Code Reviews| 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(); |