summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorleandrogracia@chromium.org <leandrogracia@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-25 13:22:08 +0000
committerleandrogracia@chromium.org <leandrogracia@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-25 13:22:08 +0000
commit975b42b0b184f93093dbb6067fb87b916e473939 (patch)
tree1f64091a2433837cb53af06b331a9329d132d010
parentb63fee8fed5490ac646d0249a3e4110620834379 (diff)
downloadchromium_src-975b42b0b184f93093dbb6067fb87b916e473939.zip
chromium_src-975b42b0b184f93093dbb6067fb87b916e473939.tar.gz
chromium_src-975b42b0b184f93093dbb6067fb87b916e473939.tar.bz2
[Android] Introduce phone number detection.
For more context see: https://chromiumcodereview.appspot.com/10187020/ BUG=125390 TEST=phone_number_detector_unittest.cc Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=139019 Review URL: https://chromiumcodereview.appspot.com/10440021 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@139026 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/content_renderer.gypi7
-rw-r--r--content/content_tests.gypi1
-rw-r--r--content/renderer/android/DEPS3
-rw-r--r--content/renderer/android/phone_number_detector.cc90
-rw-r--r--content/renderer/android/phone_number_detector.h41
-rw-r--r--content/renderer/android/phone_number_detector_unittest.cc74
-rw-r--r--third_party/libphonenumber/libphonenumber.gyp1
7 files changed, 217 insertions, 0 deletions
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index b1a13de..74c7719 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -46,6 +46,8 @@
'renderer/android/content_detector.h',
'renderer/android/email_detector.cc',
'renderer/android/email_detector.h',
+ 'renderer/android/phone_number_detector.cc',
+ 'renderer/android/phone_number_detector.h',
'renderer/active_notification_tracker.cc',
'renderer/active_notification_tracker.h',
'renderer/device_orientation_dispatcher.cc',
@@ -268,6 +270,11 @@
'../base/allocator/allocator.gyp:allocator',
],
}],
+ ['OS=="android"', {
+ 'dependencies': [
+ '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber',
+ ],
+ }],
# TODO(jrg): remove the OS=="android" section?
# http://crbug.com/113172
# Understand better how media_stream_ is tied into Chromium.
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 65250f7..224c4f4 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -286,6 +286,7 @@
'renderer/active_notification_tracker_unittest.cc',
'renderer/android/address_detector_unittest.cc',
'renderer/android/email_detector_unittest.cc',
+ 'renderer/android/phone_number_detector_unittest.cc',
'renderer/gpu/input_event_filter_unittest.cc',
'renderer/media/audio_message_filter_unittest.cc',
'renderer/media/capture_video_decoder_unittest.cc',
diff --git a/content/renderer/android/DEPS b/content/renderer/android/DEPS
new file mode 100644
index 0000000..bec0ab9
--- /dev/null
+++ b/content/renderer/android/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+third_party/libphonenumber", # For phone number detection.
+]
diff --git a/content/renderer/android/phone_number_detector.cc b/content/renderer/android/phone_number_detector.cc
new file mode 100644
index 0000000..30e0111
--- /dev/null
+++ b/content/renderer/android/phone_number_detector.cc
@@ -0,0 +1,90 @@
+// 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/phone_number_detector.h"
+
+#include <algorithm>
+
+#include "base/utf_string_conversions.h"
+#include "net/base/escape.h"
+#include "third_party/libphonenumber/src/phonenumber_api.h"
+#include "third_party/libphonenumber/src/phonenumbers/phonenumbermatch.h"
+#include "third_party/libphonenumber/src/phonenumbers/phonenumbermatcher.h"
+#include "third_party/libphonenumber/src/phonenumbers/region_code.h"
+
+using i18n::phonenumbers::PhoneNumberMatch;
+using i18n::phonenumbers::PhoneNumberMatcher;
+using i18n::phonenumbers::PhoneNumberUtil;
+using i18n::phonenumbers::RegionCode;
+
+namespace {
+
+// Maximum number of characters to look around for phone number detection.
+const size_t kMaximumTelephoneLength = 20;
+
+// Prefix used for telephone number intent URIs.
+const char kPhoneNumberSchemaPrefix[] = "tel:";
+
+} // anonymous namespace
+
+namespace content {
+
+PhoneNumberDetector::PhoneNumberDetector()
+ : region_code_(RegionCode::GetUnknown()) {
+}
+
+// Region should be empty or an ISO 3166-1 alpha-2 country code.
+PhoneNumberDetector::PhoneNumberDetector(const std::string& region)
+ : region_code_(region.empty() ? RegionCode::GetUnknown()
+ : StringToUpperASCII(region)) {
+}
+
+PhoneNumberDetector::~PhoneNumberDetector() {
+}
+
+size_t PhoneNumberDetector::GetMaximumContentLength() {
+ return kMaximumTelephoneLength;
+}
+
+GURL PhoneNumberDetector::GetIntentURL(const std::string& content_text) {
+ if (content_text.empty())
+ return GURL();
+
+ return GURL(kPhoneNumberSchemaPrefix +
+ net::EscapeQueryParamValue(content_text, true));
+}
+
+bool PhoneNumberDetector::FindContent(const string16::const_iterator& begin,
+ const string16::const_iterator& end,
+ size_t* start_pos,
+ size_t* end_pos,
+ std::string* content_text) {
+ string16 utf16_input = string16(begin, end);
+ std::string utf8_input = UTF16ToUTF8(utf16_input);
+
+ PhoneNumberMatcher matcher(utf8_input, region_code_);
+ if (matcher.HasNext()) {
+ PhoneNumberMatch match;
+ matcher.Next(&match);
+
+ PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance();
+ phone_util->FormatNumberForMobileDialing(match.number(), region_code_,
+ false, /* with_formatting */
+ content_text);
+ // If the number can't be dialed from the current region, the formatted
+ // string will be empty.
+ if (content_text->empty())
+ return false;
+
+ // Need to return start_pos and end_pos relative to a UTF16 encoding.
+ *start_pos = UTF8ToUTF16(utf8_input.substr(0, match.start())).length();
+ *end_pos = *start_pos + UTF8ToUTF16(match.raw_string()).length();
+
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace content
diff --git a/content/renderer/android/phone_number_detector.h b/content/renderer/android/phone_number_detector.h
new file mode 100644
index 0000000..fd13639
--- /dev/null
+++ b/content/renderer/android/phone_number_detector.h
@@ -0,0 +1,41 @@
+// 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.
+
+#ifndef CONTENT_RENDERER_ANDROID_PHONE_NUMBER_DETECTOR_H_
+#define CONTENT_RENDERER_ANDROID_PHONE_NUMBER_DETECTOR_H_
+#pragma once
+
+#include "content/renderer/android/content_detector.h"
+
+class PhoneNumberDetectorTest;
+
+namespace content {
+
+// Finds a telephone number in the given content text string.
+class PhoneNumberDetector : public ContentDetector {
+ public:
+ PhoneNumberDetector();
+ explicit PhoneNumberDetector(const std::string& region);
+ virtual ~PhoneNumberDetector();
+
+ private:
+ friend class ::PhoneNumberDetectorTest;
+
+ // Implementation of ContentDetector.
+ virtual bool FindContent(const string16::const_iterator& begin,
+ const string16::const_iterator& end,
+ size_t* start_pos,
+ size_t* end_pos,
+ std::string* content_text) OVERRIDE;
+ virtual GURL GetIntentURL(const std::string& content_text) OVERRIDE;
+ virtual size_t GetMaximumContentLength() OVERRIDE;
+
+ const std::string region_code_;
+
+ DISALLOW_COPY_AND_ASSIGN(PhoneNumberDetector);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_ANDROID_PHONE_NUMBER_DETECTOR_H_
diff --git a/content/renderer/android/phone_number_detector_unittest.cc b/content/renderer/android/phone_number_detector_unittest.cc
new file mode 100644
index 0000000..a0a01f1
--- /dev/null
+++ b/content/renderer/android/phone_number_detector_unittest.cc
@@ -0,0 +1,74 @@
+// 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/phone_number_detector.h"
+
+#include "base/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using content::PhoneNumberDetector;
+
+class PhoneNumberDetectorTest : public testing::Test {
+ public:
+ static std::string FindNumber(const std::string& content,
+ const std::string& region) {
+ string16 content_16 = UTF8ToUTF16(content);
+ string16 result_16;
+ size_t start, end;
+ PhoneNumberDetector detector(region);
+ std::string content_text;
+ if (detector.FindContent(content_16.begin(), content_16.end(),
+ &start, &end, &content_text))
+ result_16 = content_16.substr(start, end - start);
+ return UTF16ToUTF8(result_16);
+ }
+
+ static std::string FindAndFormatNumber(const std::string& content,
+ const std::string& region) {
+ string16 content_16 = UTF8ToUTF16(content);
+ string16 result_16;
+ size_t start, end;
+ PhoneNumberDetector detector(region);
+ std::string content_text;
+ detector.FindContent(content_16.begin(), content_16.end(),
+ &start, &end, &content_text);
+ return content_text;
+ }
+};
+
+TEST_F(PhoneNumberDetectorTest, FindNumber) {
+ // Tests cases with valid home numbers.
+ EXPECT_EQ("617-426-3000", FindNumber("hello 617-426-3000 blah", "us"));
+ EXPECT_EQ("", FindNumber("hello 617-426-3000 blah", "gb"));
+ EXPECT_EQ("020-7617-4426", FindNumber("<div>020-7617-4426</div>", "gb"));
+ EXPECT_EQ("", FindNumber("<div>020-7617-4426</div>", "fr"));
+ EXPECT_EQ("02.38.96.68.88", FindNumber("Tel:02.38.96.68.88", "fr"));
+ EXPECT_EQ("", FindNumber("Tel:02.38.96.68.88", "gb"));
+ EXPECT_EQ("1-800-866-2453",
+ FindNumber("You can call this number:1-800-866-2453 for more "
+ "information", "us"));
+ EXPECT_EQ("+1 203-925-4602", FindNumber("+1 203-925-4602", "us"));
+}
+
+TEST_F(PhoneNumberDetectorTest, FindAndFormatNumber) {
+ EXPECT_EQ("+16174263000",
+ FindAndFormatNumber("hello 617-426-3000 blah", "us"));
+ EXPECT_EQ("", FindAndFormatNumber("hello 617-426-3000 blah", "gb"));
+ EXPECT_EQ("+442076174426",
+ FindAndFormatNumber("<div>020-7617-4426</div>", "gb"));
+ EXPECT_EQ("", FindAndFormatNumber("<div>020-7617-4426</div>", "fr"));
+ EXPECT_EQ("+33238966888", FindAndFormatNumber("Tel:02.38.96.68.88", "fr"));
+ EXPECT_EQ("+18008662453",
+ FindAndFormatNumber("You can call this number:1-800-866-2453 for"
+ "more information", "us"));
+ EXPECT_EQ("+12039254602", FindAndFormatNumber("+1 203-925-4602", "us"));
+
+ // "+1 (650) 333-6000" using fullwidth UTF-8 characters.
+ EXPECT_EQ("+16503336000", FindAndFormatNumber(
+ "\xEF\xBC\x8B\xEF\xBC\x91\xE3\x80\x80\xEF\xBC\x88"
+ "\xEF\xBC\x96\xEF\xBC\x95\xEF\xBC\x90\xEF\xBC\x89"
+ "\xE3\x80\x80\xEF\xBC\x93\xEF\xBC\x93\xEF\xBC\x93"
+ "\xE3\x83\xBC\xEF\xBC\x96\xEF\xBC\x90\xEF\xBC\x90"
+ "\xEF\xBC\x90", "us"));
+}
diff --git a/third_party/libphonenumber/libphonenumber.gyp b/third_party/libphonenumber/libphonenumber.gyp
index 16f21dc..0741fd9 100644
--- a/third_party/libphonenumber/libphonenumber.gyp
+++ b/third_party/libphonenumber/libphonenumber.gyp
@@ -58,6 +58,7 @@
'direct_dependent_settings': {
'include_dirs': [
'<(SHARED_INTERMEDIATE_DIR)/protoc_out/third_party/libphonenumber',
+ 'src',
],
},
'variables': {