1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/renderer/android/content_detector.h" 6 7 #include "base/logging.h" 8 #include "third_party/WebKit/public/platform/WebPoint.h" 9 #include "third_party/WebKit/public/web/WebHitTestResult.h" 10 #include "third_party/WebKit/public/web/WebSurroundingText.h" 11 12 using blink::WebRange; 13 using blink::WebSurroundingText; 14 15 namespace content { 16 17 ContentDetector::Result::Result() : valid(false) {} 18 19 ContentDetector::Result::Result(const blink::WebRange& content_boundaries, 20 const std::string& text, 21 const GURL& intent_url) 22 : valid(true), 23 content_boundaries(content_boundaries), 24 text(text), 25 intent_url(intent_url) { 26 } 27 28 ContentDetector::Result::~Result() {} 29 30 ContentDetector::Result ContentDetector::FindTappedContent( 31 const blink::WebHitTestResult& hit_test) { 32 if (hit_test.isNull()) 33 return Result(); 34 35 std::string content_text; 36 blink::WebRange range = FindContentRange(hit_test, &content_text); 37 if (range.isNull()) 38 return Result(); 39 40 GURL intent_url = GetIntentURL(content_text); 41 return Result(range, content_text, intent_url); 42 } 43 44 WebRange ContentDetector::FindContentRange( 45 const blink::WebHitTestResult& hit_test, 46 std::string* content_text) { 47 // As the surrounding text extractor looks at maxLength/2 characters on 48 // either side of the hit point, we need to double max content length here. 49 WebSurroundingText surrounding_text; 50 surrounding_text.initialize(hit_test.node(), hit_test.localPoint(), 51 GetMaximumContentLength() * 2); 52 if (surrounding_text.isNull()) 53 return WebRange(); 54 55 base::string16 content = surrounding_text.textContent(); 56 if (content.empty()) 57 return WebRange(); 58 59 size_t selected_offset = surrounding_text.hitOffsetInTextContent(); 60 for (size_t start_offset = 0; start_offset < content.length();) { 61 size_t relative_start, relative_end; 62 if (!FindContent(content.begin() + start_offset, 63 content.end(), &relative_start, &relative_end, content_text)) { 64 break; 65 } else { 66 size_t content_start = start_offset + relative_start; 67 size_t content_end = start_offset + relative_end; 68 DCHECK(content_end <= content.length()); 69 70 if (selected_offset >= content_start && selected_offset < content_end) { 71 WebRange range = surrounding_text.rangeFromContentOffsets( 72 content_start, content_end); 73 DCHECK(!range.isNull()); 74 return range; 75 } else { 76 start_offset += relative_end; 77 } 78 } 79 } 80 81 return WebRange(); 82 } 83 84 } // namespace content 85