• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/phone_number_detector.h"
6 
7 #include <algorithm>
8 
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "content/public/renderer/android_content_detection_prefixes.h"
12 #include "net/base/escape.h"
13 #include "third_party/libphonenumber/src/phonenumber_api.h"
14 #include "third_party/libphonenumber/src/phonenumbers/phonenumbermatch.h"
15 #include "third_party/libphonenumber/src/phonenumbers/phonenumbermatcher.h"
16 #include "third_party/libphonenumber/src/phonenumbers/region_code.h"
17 
18 using i18n::phonenumbers::PhoneNumberMatch;
19 using i18n::phonenumbers::PhoneNumberMatcher;
20 using i18n::phonenumbers::PhoneNumberUtil;
21 using i18n::phonenumbers::RegionCode;
22 
23 namespace {
24 
25 // Maximum number of characters to look around for phone number detection.
26 const size_t kMaximumTelephoneLength = 20;
27 
28 }  // anonymous namespace
29 
30 namespace content {
31 
PhoneNumberDetector()32 PhoneNumberDetector::PhoneNumberDetector()
33     : region_code_(RegionCode::GetUnknown()) {
34 }
35 
36 // Region should be empty or an ISO 3166-1 alpha-2 country code.
PhoneNumberDetector(const std::string & region)37 PhoneNumberDetector::PhoneNumberDetector(const std::string& region)
38     : region_code_(region.empty() ? RegionCode::GetUnknown()
39                                   : StringToUpperASCII(region)) {
40 }
41 
~PhoneNumberDetector()42 PhoneNumberDetector::~PhoneNumberDetector() {
43 }
44 
GetMaximumContentLength()45 size_t PhoneNumberDetector::GetMaximumContentLength() {
46   return kMaximumTelephoneLength;
47 }
48 
GetIntentURL(const std::string & content_text)49 GURL PhoneNumberDetector::GetIntentURL(const std::string& content_text) {
50   if (content_text.empty())
51     return GURL();
52 
53   return GURL(kPhoneNumberPrefix +
54       net::EscapeQueryParamValue(content_text, true));
55 }
56 
FindContent(const base::string16::const_iterator & begin,const base::string16::const_iterator & end,size_t * start_pos,size_t * end_pos,std::string * content_text)57 bool PhoneNumberDetector::FindContent(
58     const base::string16::const_iterator& begin,
59     const base::string16::const_iterator& end,
60     size_t* start_pos,
61     size_t* end_pos,
62     std::string* content_text) {
63   base::string16 utf16_input = base::string16(begin, end);
64   std::string utf8_input = base::UTF16ToUTF8(utf16_input);
65 
66   PhoneNumberMatcher matcher(utf8_input, region_code_);
67   if (matcher.HasNext()) {
68     PhoneNumberMatch match;
69     matcher.Next(&match);
70 
71     PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance();
72     phone_util->FormatNumberForMobileDialing(match.number(), region_code_,
73                                              false, /* with_formatting */
74                                              content_text);
75     // If the number can't be dialed from the current region, the formatted
76     // string will be empty.
77     if (content_text->empty())
78       return false;
79 
80     // Need to return start_pos and end_pos relative to a UTF16 encoding.
81     *start_pos =
82         base::UTF8ToUTF16(utf8_input.substr(0, match.start())).length();
83     *end_pos = *start_pos + base::UTF8ToUTF16(match.raw_string()).length();
84 
85     return true;
86   }
87 
88   return false;
89 }
90 
91 }  // namespace content
92