forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Original author: amoylan@chromium.org Original cl: https://chromium-review.googlesource.com/c/chromium/src/+/706439 This CL adds the GeoLanguageProvider browser singleton as described in the design doc: https://docs.google.com/document/d/18WqVHz5F9vaUiE32E8Ge6QHmku2QSJKvlqB9JjnIM-g This interface provides a list of language codes corresponding to local languages based on the device's approximate geolocation derived from its public IP address, using the PublicIpAddressGeolocator service. IP geolocation updates are requested no more often than every 24 hours. This singleton is started up after Profile init in PreMainMessageLoopRun. The startup runs on a background task runner, connecting & subscribing to the IP geolocation service. Startup is gated on the Feature setting "GeoLanguage" which is false for now. Bug: 76915 Change-Id: I9af2b1375fabda3d029ca396043b9195acab7cf0 Reviewed-on: https://chromium-review.googlesource.com/807884 Commit-Queue: Renjie Liu <renjieliu@chromium.org> Reviewed-by: Miguel Casas <mcasas@chromium.org> Reviewed-by: Zhongyi Shi <zhongyi@chromium.org> Reviewed-by: Colin Blundell <blundell@chromium.org> Cr-Commit-Position: refs/heads/master@{#523709}
- Loading branch information
Renjie Liu
authored and
Commit Bot
committed
Dec 13, 2017
1 parent
e48a05c
commit 1aea053
Showing
6 changed files
with
475 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
include_rules = [ | ||
"+content/public/browser", | ||
"+device/geolocation/public/interfaces", | ||
"+net", | ||
"+services/device/public/interfaces", | ||
"+services/service_manager/public", | ||
] |
153 changes: 153 additions & 0 deletions
153
components/language/content/browser/geo_language_provider.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
// Copyright 2017 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 "components/language/content/browser/geo_language_provider.h" | ||
|
||
#include "base/memory/singleton.h" | ||
#include "base/task_scheduler/post_task.h" | ||
#include "base/time/time.h" | ||
#include "net/traffic_annotation/network_traffic_annotation.h" | ||
#include "services/device/public/interfaces/constants.mojom.h" | ||
#include "services/device/public/interfaces/public_ip_address_geolocation_provider.mojom.h" | ||
#include "services/service_manager/public/cpp/connector.h" | ||
|
||
namespace language { | ||
namespace { | ||
|
||
// Don't start requesting updates to IP-based approximation geolocation until | ||
// this long after receiving the last one. | ||
constexpr base::TimeDelta kMinUpdatePeriod = base::TimeDelta::FromDays(1); | ||
|
||
} // namespace | ||
|
||
GeoLanguageProvider::GeoLanguageProvider() | ||
: languages_(), | ||
creation_task_runner_(base::SequencedTaskRunnerHandle::Get()), | ||
background_task_runner_(base::CreateSequencedTaskRunnerWithTraits( | ||
{base::MayBlock(), base::TaskPriority::BACKGROUND, | ||
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) { | ||
// Constructor is not required to run on |background_task_runner_|: | ||
DETACH_FROM_SEQUENCE(background_sequence_checker_); | ||
} | ||
|
||
GeoLanguageProvider::GeoLanguageProvider( | ||
scoped_refptr<base::SequencedTaskRunner> background_task_runner) | ||
: languages_(), | ||
creation_task_runner_(base::SequencedTaskRunnerHandle::Get()), | ||
background_task_runner_(background_task_runner) { | ||
// Constructor is not required to run on |background_task_runner_|: | ||
DETACH_FROM_SEQUENCE(background_sequence_checker_); | ||
} | ||
|
||
GeoLanguageProvider::~GeoLanguageProvider() = default; | ||
|
||
/* static */ | ||
GeoLanguageProvider* GeoLanguageProvider::GetInstance() { | ||
return base::Singleton<GeoLanguageProvider, base::LeakySingletonTraits< | ||
GeoLanguageProvider>>::get(); | ||
} | ||
|
||
void GeoLanguageProvider::StartUp( | ||
std::unique_ptr<service_manager::Connector> service_manager_connector) { | ||
DCHECK_CALLED_ON_VALID_SEQUENCE(creation_sequence_checker_); | ||
|
||
service_manager_connector_ = std::move(service_manager_connector); | ||
// Continue startup in the background. | ||
background_task_runner_->PostTask( | ||
FROM_HERE, base::BindOnce(&GeoLanguageProvider::BackgroundStartUp, | ||
base::Unretained(this))); | ||
} | ||
|
||
std::vector<std::string> GeoLanguageProvider::CurrentGeoLanguages() const { | ||
DCHECK_CALLED_ON_VALID_SEQUENCE(creation_sequence_checker_); | ||
return languages_; | ||
} | ||
|
||
void GeoLanguageProvider::BackgroundStartUp() { | ||
// This binds background_sequence_checker_. | ||
DCHECK_CALLED_ON_VALID_SEQUENCE(background_sequence_checker_); | ||
|
||
// Initialize location->language lookup library. | ||
language_code_locator_ = std::make_unique<language::LanguageCodeLocator>(); | ||
|
||
// Make initial query. | ||
QueryNextPosition(); | ||
} | ||
|
||
void GeoLanguageProvider::BindIpGeolocationService() { | ||
DCHECK_CALLED_ON_VALID_SEQUENCE(background_sequence_checker_); | ||
DCHECK(!geolocation_provider_.is_bound()); | ||
|
||
// Bind a PublicIpAddressGeolocationProvider. | ||
device::mojom::PublicIpAddressGeolocationProviderPtr ip_geolocation_provider; | ||
service_manager_connector_->BindInterface( | ||
device::mojom::kServiceName, mojo::MakeRequest(&ip_geolocation_provider)); | ||
|
||
net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation = | ||
net::DefinePartialNetworkTrafficAnnotation("geo_language_provider", | ||
"network_location_request", | ||
R"( | ||
semantics { | ||
sender: "GeoLanguage Provider" | ||
} | ||
policy { | ||
setting: | ||
"Users can control this feature via the translation settings " | ||
"'Languages', 'Language', 'Offer to translate'." | ||
chrome_policy { | ||
DefaultGeolocationSetting { | ||
DefaultGeolocationSetting: 2 | ||
} | ||
} | ||
})"); | ||
|
||
// Use the PublicIpAddressGeolocationProvider to bind ip_geolocation_service_. | ||
ip_geolocation_provider->CreateGeolocation( | ||
static_cast<net::MutablePartialNetworkTrafficAnnotationTag>( | ||
partial_traffic_annotation), | ||
mojo::MakeRequest(&geolocation_provider_)); | ||
// No error handler required: If the connection is broken, QueryNextPosition | ||
// will bind it again. | ||
} | ||
|
||
void GeoLanguageProvider::QueryNextPosition() { | ||
DCHECK_CALLED_ON_VALID_SEQUENCE(background_sequence_checker_); | ||
|
||
if (geolocation_provider_.encountered_error()) | ||
geolocation_provider_.reset(); | ||
if (!geolocation_provider_.is_bound()) | ||
BindIpGeolocationService(); | ||
|
||
geolocation_provider_->QueryNextPosition(base::BindOnce( | ||
&GeoLanguageProvider::OnIpGeolocationResponse, base::Unretained(this))); | ||
} | ||
|
||
void GeoLanguageProvider::OnIpGeolocationResponse( | ||
device::mojom::GeopositionPtr geoposition) { | ||
DCHECK_CALLED_ON_VALID_SEQUENCE(background_sequence_checker_); | ||
|
||
const std::vector<std::string> languages = | ||
language_code_locator_->GetLanguageCode(geoposition->latitude, | ||
geoposition->longitude); | ||
|
||
// Update current languages on UI thread. | ||
creation_task_runner_->PostTask( | ||
FROM_HERE, base::BindOnce(&GeoLanguageProvider::SetGeoLanguages, | ||
base::Unretained(this), languages)); | ||
|
||
// Post a task to request a fresh lookup after |kMinUpdatePeriod|. | ||
background_task_runner_->PostDelayedTask( | ||
FROM_HERE, | ||
base::BindOnce(&GeoLanguageProvider::QueryNextPosition, | ||
base::Unretained(this)), | ||
kMinUpdatePeriod); | ||
} | ||
|
||
void GeoLanguageProvider::SetGeoLanguages( | ||
const std::vector<std::string>& languages) { | ||
DCHECK_CALLED_ON_VALID_SEQUENCE(creation_sequence_checker_); | ||
languages_ = languages; | ||
} | ||
|
||
} // namespace language |
114 changes: 114 additions & 0 deletions
114
components/language/content/browser/geo_language_provider.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// Copyright 2017 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 COMPONENTS_LANGUAGE_CONTENT_BROWSER_GEO_LANGUAGE_PROVIDER_H_ | ||
#define COMPONENTS_LANGUAGE_CONTENT_BROWSER_GEO_LANGUAGE_PROVIDER_H_ | ||
|
||
#include <string> | ||
|
||
#include "base/macros.h" | ||
#include "base/memory/ref_counted.h" | ||
#include "base/sequence_checker.h" | ||
#include "base/sequenced_task_runner.h" | ||
#include "components/language/content/browser/language_code_locator.h" | ||
#include "device/geolocation/public/interfaces/geolocation.mojom.h" | ||
|
||
namespace base { | ||
template <typename T> | ||
struct DefaultSingletonTraits; | ||
} | ||
|
||
namespace service_manager { | ||
class Connector; | ||
} | ||
|
||
namespace language { | ||
// GeoLanguageProvider is responsible for providing a "local" language derived | ||
// from the approximate geolocation of the device based only on its public IP | ||
// address. | ||
// * Singleton class. Access through GetInstance(). | ||
// * Sequencing: Must be created and used on the same sequence. | ||
class GeoLanguageProvider { | ||
public: | ||
static GeoLanguageProvider* GetInstance(); | ||
|
||
// Call this once near browser startup. Begins ongoing geo-language updates. | ||
// * Initializes location->language mapping in a low-priority background task. | ||
// * Until the first IP geolocation completes, CurrentGeoLanguages() will | ||
// return an empty list. | ||
// |service_manager_connector| should not yet be bound to a sequence, e.g., it | ||
// should be the result of invoking ServiceManagerConnect::Clone() on another | ||
// connector. | ||
void StartUp( | ||
std::unique_ptr<service_manager::Connector> service_manager_connector); | ||
|
||
// Returns the inferred ranked list of local languages based on the most | ||
// recently obtained approximate public-IP geolocation of the device. | ||
// * Returns a list of BCP-47 language codes. | ||
// * Returns an empty list in these cases: | ||
// - StartUp() not yet called | ||
// - Geolocation failed | ||
// - Geolocation pending | ||
// - Geolocation succeeded but no local language is mapped to that location | ||
std::vector<std::string> CurrentGeoLanguages() const; | ||
|
||
private: | ||
friend class GeoLanguageProviderTest; | ||
|
||
GeoLanguageProvider(); | ||
explicit GeoLanguageProvider( | ||
scoped_refptr<base::SequencedTaskRunner> background_task_runner); | ||
~GeoLanguageProvider(); | ||
friend struct base::DefaultSingletonTraits<GeoLanguageProvider>; | ||
|
||
// Performs actual work described in StartUp() above. | ||
void BackgroundStartUp(); | ||
|
||
// Binds |ip_geolocation_service_| using a service_manager::Connector. | ||
void BindIpGeolocationService(); | ||
|
||
// Requests the next available IP-based approximate geolocation from | ||
// |ip_geolocation_service_|, binding |ip_geolocation_service_| first if | ||
// necessary. | ||
void QueryNextPosition(); | ||
|
||
// Updates the list of BCP-47 language codes that will be returned by calls to | ||
// CurrentGeoLanguages(). | ||
// Must be called on the UI thread. | ||
void SetGeoLanguages(const std::vector<std::string>& languages); | ||
|
||
// Callback for updates from |ip_geolocation_service_|. | ||
void OnIpGeolocationResponse(device::mojom::GeopositionPtr geoposition); | ||
|
||
// List of BCP-47 language code inferred from public-IP geolocation. | ||
// May be empty. See comment on CurrentGeoLanguages() above. | ||
std::vector<std::string> languages_; | ||
|
||
// Service manager connector for use on background_task_runner_. | ||
std::unique_ptr<service_manager::Connector> service_manager_connector_; | ||
|
||
// Connection to the IP geolocation service. | ||
device::mojom::GeolocationPtr geolocation_provider_; | ||
|
||
// Location -> Language lookup library. | ||
std::unique_ptr<language::LanguageCodeLocator> language_code_locator_; | ||
|
||
// Runner for tasks that should run on the creation sequence. | ||
scoped_refptr<base::SequencedTaskRunner> creation_task_runner_; | ||
|
||
// Runner for low priority background tasks. | ||
scoped_refptr<base::SequencedTaskRunner> background_task_runner_; | ||
|
||
// Sequence checker for methods that must run on the creation sequence. | ||
SEQUENCE_CHECKER(creation_sequence_checker_); | ||
|
||
// Sequence checker for background_task_runner_. | ||
SEQUENCE_CHECKER(background_sequence_checker_); | ||
|
||
DISALLOW_COPY_AND_ASSIGN(GeoLanguageProvider); | ||
}; | ||
|
||
} // namespace language | ||
|
||
#endif // COMPONENTS_LANGUAGE_CONTENT_BROWSER_GEO_LANGUAGE_PROVIDER_H_ |
Oops, something went wrong.