| // 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 "content/renderer/android/content_detector.h" |
| |
| #include "base/logging.h" |
| #include "third_party/WebKit/public/platform/WebPoint.h" |
| #include "third_party/WebKit/public/web/WebHitTestResult.h" |
| #include "third_party/WebKit/public/web/WebSurroundingText.h" |
| |
| using blink::WebRange; |
| using blink::WebSurroundingText; |
| |
| namespace content { |
| |
| ContentDetector::Result::Result() : valid(false) {} |
| |
| ContentDetector::Result::Result(const blink::WebRange& content_boundaries, |
| const std::string& text, |
| const GURL& intent_url) |
| : valid(true), |
| content_boundaries(content_boundaries), |
| text(text), |
| intent_url(intent_url) { |
| } |
| |
| ContentDetector::Result::~Result() {} |
| |
| ContentDetector::Result ContentDetector::FindTappedContent( |
| const blink::WebHitTestResult& hit_test) { |
| if (hit_test.isNull()) |
| return Result(); |
| |
| std::string content_text; |
| blink::WebRange range = FindContentRange(hit_test, &content_text); |
| if (range.isNull()) |
| return Result(); |
| |
| GURL intent_url = GetIntentURL(content_text); |
| return Result(range, content_text, intent_url); |
| } |
| |
| WebRange ContentDetector::FindContentRange( |
| const blink::WebHitTestResult& hit_test, |
| std::string* content_text) { |
| // As the surrounding text extractor looks at maxLength/2 characters on |
| // either side of the hit point, we need to double max content length here. |
| WebSurroundingText surrounding_text; |
| surrounding_text.initialize(hit_test.node(), hit_test.localPoint(), |
| GetMaximumContentLength() * 2); |
| if (surrounding_text.isNull()) |
| return WebRange(); |
| |
| base::string16 content = surrounding_text.textContent(); |
| if (content.empty()) |
| return WebRange(); |
| |
| size_t selected_offset = surrounding_text.hitOffsetInTextContent(); |
| for (size_t start_offset = 0; start_offset < content.length();) { |
| size_t relative_start, relative_end; |
| if (!FindContent(content.begin() + start_offset, |
| content.end(), &relative_start, &relative_end, content_text)) { |
| break; |
| } else { |
| size_t content_start = start_offset + relative_start; |
| size_t content_end = start_offset + relative_end; |
| DCHECK(content_end <= content.length()); |
| |
| if (selected_offset >= content_start && selected_offset < content_end) { |
| WebRange range = surrounding_text.rangeFromContentOffsets( |
| content_start, content_end); |
| DCHECK(!range.isNull()); |
| return range; |
| } else { |
| start_offset += relative_end; |
| } |
| } |
| } |
| |
| return WebRange(); |
| } |
| |
| } // namespace content |