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
18using i18n::phonenumbers::PhoneNumberMatch;
19using i18n::phonenumbers::PhoneNumberMatcher;
20using i18n::phonenumbers::PhoneNumberUtil;
21using i18n::phonenumbers::RegionCode;
22
23namespace {
24
25// Maximum number of characters to look around for phone number detection.
26const size_t kMaximumTelephoneLength = 20;
27
28}  // anonymous namespace
29
30namespace content {
31
32PhoneNumberDetector::PhoneNumberDetector()
33    : region_code_(RegionCode::GetUnknown()) {
34}
35
36// Region should be empty or an ISO 3166-1 alpha-2 country code.
37PhoneNumberDetector::PhoneNumberDetector(const std::string& region)
38    : region_code_(region.empty() ? RegionCode::GetUnknown()
39                                  : StringToUpperASCII(region)) {
40}
41
42PhoneNumberDetector::~PhoneNumberDetector() {
43}
44
45size_t PhoneNumberDetector::GetMaximumContentLength() {
46  return kMaximumTelephoneLength;
47}
48
49GURL 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
57bool 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