Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Unified Diff: chrome/browser/android/search_geolocation/search_geolocation_service.cc

Issue 2612993002: Make geolocation API and X-Geo header access consistent (Closed)
Patch Set: Fix test / merge error Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/android/search_geolocation/search_geolocation_service.cc
diff --git a/chrome/browser/android/search_geolocation/search_geolocation_service.cc b/chrome/browser/android/search_geolocation/search_geolocation_service.cc
new file mode 100644
index 0000000000000000000000000000000000000000..952dbc76e42a013ee3deb0aed66b87abf005d5e9
--- /dev/null
+++ b/chrome/browser/android/search_geolocation/search_geolocation_service.cc
@@ -0,0 +1,283 @@
+// 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 "chrome/browser/android/search_geolocation/search_geolocation_service.h"
+
+#include "base/feature_list.h"
+#include "base/values.h"
+#include "chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.h"
+#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
+#include "chrome/common/chrome_features.h"
+#include "chrome/common/pref_names.h"
+#include "components/content_settings/core/browser/content_settings_utils.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/content_settings/core/common/content_settings_types.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/prefs/pref_service.h"
+#include "components/search_engines/template_url.h"
+#include "components/search_engines/template_url_service.h"
+#include "url/gurl.h"
+#include "url/url_constants.h"
+
+namespace {
+
+const char kIsGoogleSearchEngineKey[] = "is_google_search_engine";
+const char kCCTLDKey[] = "cctld";
+const char kDSESettingKey[] = "dse_setting";
+
+} // namespace
+
+struct SearchGeolocationService::PrefValue {
+ bool is_google_search_engine = false;
+ url::Origin cctld;
+ bool setting = false;
+};
+
+// static
+SearchGeolocationService*
+SearchGeolocationService::Factory::GetForBrowserContext(
+ content::BrowserContext* context) {
+ return static_cast<SearchGeolocationService*>(GetInstance()
+ ->GetServiceForBrowserContext(context, true));
+}
+
+// static
+SearchGeolocationService::Factory*
+SearchGeolocationService::Factory::GetInstance() {
+ return base::Singleton<SearchGeolocationService::Factory>::get();
+}
+
+SearchGeolocationService::Factory::Factory()
+ : BrowserContextKeyedServiceFactory(
+ "SearchGeolocationService",
+ BrowserContextDependencyManager::GetInstance()) {
+ DependsOn(HostContentSettingsMapFactory::GetInstance());
+ DependsOn(TemplateURLServiceFactory::GetInstance());
+}
+
+SearchGeolocationService::Factory::~Factory() {}
+
+bool SearchGeolocationService::Factory::ServiceIsCreatedWithBrowserContext()
+ const {
+ return true;
+}
+
+KeyedService* SearchGeolocationService::Factory::BuildServiceInstanceFor(
+ content::BrowserContext* context) const {
+ return new SearchGeolocationService(Profile::FromBrowserContext(context));
+}
+
+// static
+void SearchGeolocationService::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterDictionaryPref(prefs::kGoogleDSEGeolocationSetting);
+}
+
+SearchGeolocationService::SearchGeolocationService(Profile* profile)
+ : profile_(profile),
+ pref_service_(profile_->GetPrefs()),
+ host_content_settings_map_(
+ HostContentSettingsMapFactory::GetForProfile(profile_)),
+ template_url_service_(
+ TemplateURLServiceFactory::GetForProfile(profile_)) {
+ if (!UseConsistentSearchGeolocation())
+ return;
+
+ template_url_service_->AddObserver(this);
+
+ InitializeDSEGeolocationSettingIfNeeded();
+
+ // Make sure the setting is valid now. It's possible that the setting has
+ // become invalid either by changes being made to enterprise policy, or while
+ // the flag to enable consistent search geolocation was off.
+ EnsureDSEGeolocationSettingIsValid();
+}
+
+bool SearchGeolocationService::UseDSEGeolocationSetting(
+ const url::Origin& requesting_origin) {
+ if (!UseConsistentSearchGeolocation())
+ return false;
+
+ if (profile_->IsOffTheRecord())
+ return false;
+
+ if (requesting_origin.scheme() != url::kHttpsScheme)
+ return false;
+
+ if (!requesting_origin.IsSameOriginWith(GetDSECCTLD()))
+ return false;
+
+ // If the content setting for the DSE CCTLD is controlled by policy, and is st
+ // to ASK, don't use the DSE geolocation setting.
+ if (!IsContentSettingUserSettable() &&
+ GetCurrentContentSetting() == CONTENT_SETTING_ASK) {
+ return false;
+ }
+
+ return true;
+}
+
+bool SearchGeolocationService::GetDSEGeolocationSetting() {
+ // Make sure the setting is valid, in case enterprise policy has changed.
+ // TODO(benwells): Check if enterprise policy can change while Chrome is
+ // running. If it can't this call is probably not needed.
+ EnsureDSEGeolocationSettingIsValid();
+
+ return GetDSEGeolocationPref().setting;
+}
+
+void SearchGeolocationService::SetDSEGeolocationSetting(bool setting) {
+ PrefValue pref = GetDSEGeolocationPref();
+ if (setting == pref.setting)
+ return;
+
+ // If the user cannot change their geolocation content setting (e.g. due to
+ // enterprise policy), they also can't change this preference so just bail
+ // out.
+ if (!IsContentSettingUserSettable())
+ return;
+
+ pref.setting = setting;
+ SetDSEGeolocationPref(pref);
+
+ ResetContentSetting();
+}
+
+void SearchGeolocationService::Shutdown() {
+ if (UseConsistentSearchGeolocation())
+ template_url_service_->RemoveObserver(this);
+}
+
+SearchGeolocationService::~SearchGeolocationService() {}
+
+void SearchGeolocationService::OnTemplateURLServiceChanged() {
+ bool is_now_google_search_engine = IsGoogleSearchEngine();
+ PrefValue pref = GetDSEGeolocationPref();
+ ContentSetting content_setting = GetCurrentContentSetting();
+
+ if (is_now_google_search_engine) {
+ if (content_setting == CONTENT_SETTING_BLOCK && pref.setting) {
+ pref.setting = false;
+ } else if (content_setting == CONTENT_SETTING_ALLOW && !pref.setting) {
+ ResetContentSetting();
+ }
+ }
+
+ if (is_now_google_search_engine && !pref.is_google_search_engine &&
+ pref.setting) {
+ SearchGeolocationDisclosureTabHelper::ResetDisclosure(profile_);
+ }
+
+ pref.is_google_search_engine = is_now_google_search_engine;
+ pref.cctld = GetDSECCTLD();
+ SetDSEGeolocationPref(pref);
+}
+
+void SearchGeolocationService::InitializeDSEGeolocationSettingIfNeeded() {
+ // Initialize the pref if it hasn't been initialized yet.
+ if (!pref_service_->HasPrefPath(prefs::kGoogleDSEGeolocationSetting)) {
+ ContentSetting content_setting = GetCurrentContentSetting();
+
+ PrefValue pref;
+ pref.is_google_search_engine = IsGoogleSearchEngine();
+ pref.cctld = GetDSECCTLD();
+ pref.setting = content_setting != CONTENT_SETTING_BLOCK;
+ SetDSEGeolocationPref(pref);
+
+ SearchGeolocationDisclosureTabHelper::ResetDisclosure(profile_);
+ }
+}
+
+void SearchGeolocationService::EnsureDSEGeolocationSettingIsValid() {
+ PrefValue pref = GetDSEGeolocationPref();
+ ContentSetting content_setting = GetCurrentContentSetting();
+ bool new_setting = pref.setting;
+
+ if (pref.setting && content_setting == CONTENT_SETTING_BLOCK) {
+ new_setting = false;
+ } else if (!pref.setting && content_setting == CONTENT_SETTING_ALLOW) {
+ new_setting = true;
+ }
+
+ if (pref.setting != new_setting) {
+ pref.setting = new_setting;
+ SetDSEGeolocationPref(pref);
+ }
+}
+
+bool SearchGeolocationService::IsGoogleSearchEngine() {
+ const TemplateURL* template_url =
+ template_url_service_->GetDefaultSearchProvider();
+ return template_url &&
+ template_url->HasGoogleBaseURLs(UIThreadSearchTermsData(profile_));
+}
+
+url::Origin SearchGeolocationService::GetDSECCTLD() {
+ if (!IsGoogleSearchEngine())
+ return url::Origin();
+
+ GURL origin_url(UIThreadSearchTermsData(profile_).GoogleBaseURLValue());
+ return url::Origin(origin_url);
+}
+
+SearchGeolocationService::PrefValue
+SearchGeolocationService::GetDSEGeolocationPref() {
+ const base::DictionaryValue* dict =
+ pref_service_->GetDictionary(prefs::kGoogleDSEGeolocationSetting);
+
+ PrefValue pref;
+ bool is_google_search_engine;
+ std::string cctld_string;
+ bool setting;
+ if (dict->GetBoolean(kIsGoogleSearchEngineKey, &is_google_search_engine) &&
+ dict->GetString(kCCTLDKey, &cctld_string) &&
+ dict->GetBoolean(kDSESettingKey, &setting)) {
+ pref.is_google_search_engine = is_google_search_engine;
+ pref.cctld = url::Origin(GURL(cctld_string));
+ pref.setting = setting;
+ }
+
+ return pref;
+}
+
+void SearchGeolocationService::SetDSEGeolocationPref(
+ const SearchGeolocationService::PrefValue& pref) {
+ base::DictionaryValue dict;
+ dict.SetBoolean(kIsGoogleSearchEngineKey, pref.is_google_search_engine);
+ dict.SetString(kCCTLDKey, pref.cctld.Serialize());
+ dict.SetBoolean(kDSESettingKey, pref.setting);
+ pref_service_->Set(prefs::kGoogleDSEGeolocationSetting, dict);
+}
+
+ContentSetting SearchGeolocationService::GetCurrentContentSetting() {
+ url::Origin origin = GetDSECCTLD();
+ return host_content_settings_map_->GetContentSetting(
+ origin.GetURL(), origin.GetURL(), CONTENT_SETTINGS_TYPE_GEOLOCATION,
+ std::string());
+}
+
+void SearchGeolocationService::ResetContentSetting() {
+ url::Origin origin = GetDSECCTLD();
+ host_content_settings_map_->SetContentSettingDefaultScope(
+ origin.GetURL(), origin.GetURL(), CONTENT_SETTINGS_TYPE_GEOLOCATION,
+ std::string(), CONTENT_SETTING_DEFAULT);
+}
+
+bool SearchGeolocationService::IsContentSettingUserSettable() {
+ content_settings::SettingInfo info;
+ url::Origin origin = GetDSECCTLD();
+ std::unique_ptr<base::Value> value =
+ host_content_settings_map_->GetWebsiteSetting(
+ origin.GetURL(), origin.GetURL(), CONTENT_SETTINGS_TYPE_GEOLOCATION,
+ std::string(), &info);
+ return info.source == content_settings::SETTING_SOURCE_USER;
+}
+
+bool SearchGeolocationService::UseConsistentSearchGeolocation() {
+ return base::FeatureList::IsEnabled(features::kConsistentOmniboxGeolocation);
+}

Powered by Google App Engine
This is Rietveld 408576698