diff options
-rw-r--r-- | chrome/browser/browser_prefs.cc | 2 | ||||
-rw-r--r-- | chrome/browser/geolocation/access_token_store.cc | 51 | ||||
-rw-r--r-- | chrome/browser/geolocation/access_token_store.h | 33 | ||||
-rw-r--r-- | chrome/browser/geolocation/geoposition.h | 7 | ||||
-rw-r--r-- | chrome/browser/geolocation/location_arbitrator.cc | 137 | ||||
-rw-r--r-- | chrome/browser/geolocation/location_arbitrator.h | 61 | ||||
-rw-r--r-- | chrome/browser/geolocation/location_provider.h | 18 | ||||
-rw-r--r-- | chrome/browser/geolocation/network_location_provider.cc | 3 | ||||
-rw-r--r-- | chrome/browser/geolocation/network_location_provider.h | 2 | ||||
-rw-r--r-- | chrome/browser/geolocation/network_location_provider_unittest.cc | 19 | ||||
-rw-r--r-- | chrome/browser/geolocation/network_location_request.h | 2 | ||||
-rwxr-xr-x | chrome/chrome_browser.gypi | 4 | ||||
-rw-r--r-- | chrome/common/pref_names.cc | 6 | ||||
-rw-r--r-- | chrome/common/pref_names.h | 2 |
14 files changed, 316 insertions, 31 deletions
diff --git a/chrome/browser/browser_prefs.cc b/chrome/browser/browser_prefs.cc index 3287168..61d6c9c 100644 --- a/chrome/browser/browser_prefs.cc +++ b/chrome/browser/browser_prefs.cc @@ -15,6 +15,7 @@ #include "chrome/browser/extensions/extensions_ui.h" #include "chrome/browser/external_protocol_handler.h" #include "chrome/browser/form_field_history_manager.h" +#include "chrome/browser/geolocation/access_token_store.h" #include "chrome/browser/google_url_tracker.h" #include "chrome/browser/host_content_settings_map.h" #include "chrome/browser/host_zoom_map.h" @@ -81,6 +82,7 @@ void RegisterLocalState(PrefService* local_state) { #if defined(OS_WIN) CookiePromptModalDialog::RegisterPrefs(local_state); #endif + AccessTokenStore::RegisterPrefs(local_state); } void RegisterUserPrefs(PrefService* user_prefs) { diff --git a/chrome/browser/geolocation/access_token_store.cc b/chrome/browser/geolocation/access_token_store.cc new file mode 100644 index 0000000..0055103 --- /dev/null +++ b/chrome/browser/geolocation/access_token_store.cc @@ -0,0 +1,51 @@ +// Copyright (c) 2010 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/geolocation/access_token_store.h" + +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/browser/browser_process.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/pref_service.h" +#include "googleurl/src/gurl.h" + +namespace { +// Implementation of the geolocation access token store using chrome's prefs +// store (local_state) to persist these tokens. +// TODO(joth): Calls APIs which probably can't be used from the thread that it +// will be run on; needs prefs access bounced via UI thread. +class ChromePrefsAccessTokenStore : public AccessTokenStore { + public: + // AccessTokenStore + virtual bool SetAccessToken(const GURL& url, + const string16& access_token) { + DictionaryValue* access_token_dictionary = + g_browser_process->local_state()->GetMutableDictionary( + prefs::kGeolocationAccessToken); + access_token_dictionary->SetWithoutPathExpansion( + UTF8ToWide(url.spec()), + Value::CreateStringValueFromUTF16(access_token)); + return true; + } + + virtual bool GetAccessToken(const GURL& url, string16* access_token) { + const DictionaryValue* access_token_dictionary = + g_browser_process->local_state()->GetDictionary( + prefs::kGeolocationAccessToken); + // Careful: The returned value could be NULL if the pref has never been set. + if (access_token_dictionary == NULL) + return false; + return access_token_dictionary->GetStringAsUTF16WithoutPathExpansion( + UTF8ToWide(url.spec()), access_token); + } +}; + +} // namespace + +void AccessTokenStore::RegisterPrefs(PrefService* prefs) { + prefs->RegisterDictionaryPref(prefs::kGeolocationAccessToken); +} + +AccessTokenStore* NewChromePrefsAccessTokenStore(); diff --git a/chrome/browser/geolocation/access_token_store.h b/chrome/browser/geolocation/access_token_store.h new file mode 100644 index 0000000..11733a4 --- /dev/null +++ b/chrome/browser/geolocation/access_token_store.h @@ -0,0 +1,33 @@ +// Copyright (c) 2010 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 CHROME_BROWSER_GEOLOCATION_ACCESS_TOKEN_STORE_H_ +#define CHROME_BROWSER_GEOLOCATION_ACCESS_TOKEN_STORE_H_ + +#include "base/ref_counted.h" +#include "base/string16.h" + +class GURL; +class PrefService; + +// Provides storage for the access token used in the network request. +// Provided to allow for mocking for testing, by decoupling deep browser +// dependencies (singleton prefs & threads) from the geolocaiton object. +class AccessTokenStore : public base::RefCounted<AccessTokenStore> { + public: + static void RegisterPrefs(PrefService* prefs); + + virtual bool SetAccessToken(const GURL& url, + const string16& access_token) = 0; + virtual bool GetAccessToken(const GURL& url, string16* access_token) = 0; + + protected: + friend class base::RefCounted<AccessTokenStore>; + virtual ~AccessTokenStore() {} +}; + +// Creates a new access token store backed by the global chome prefs. +AccessTokenStore* NewChromePrefsAccessTokenStore(); + +#endif // CHROME_BROWSER_GEOLOCATION_ACCESS_TOKEN_STORE_H_ diff --git a/chrome/browser/geolocation/geoposition.h b/chrome/browser/geolocation/geoposition.h index 31e5d55..7143638 100644 --- a/chrome/browser/geolocation/geoposition.h +++ b/chrome/browser/geolocation/geoposition.h @@ -20,11 +20,8 @@ struct Position { // values for all of them to allow us to provide the constants on the error // object. enum ErrorCode { - ERROR_CODE_NONE = -1, // Gears addition - ERROR_CODE_UNKNOWN_ERROR = 0, // Not used by Gears - ERROR_CODE_PERMISSION_DENIED = 1, // Not used by Gears - Geolocation - // methods throw an exception if - // permission has not been granted. + ERROR_CODE_NONE = 0, // Chrome addition + ERROR_CODE_PERMISSION_DENIED = 1, ERROR_CODE_POSITION_UNAVAILABLE = 2, ERROR_CODE_TIMEOUT = 3, }; diff --git a/chrome/browser/geolocation/location_arbitrator.cc b/chrome/browser/geolocation/location_arbitrator.cc new file mode 100644 index 0000000..e8f1863 --- /dev/null +++ b/chrome/browser/geolocation/location_arbitrator.cc @@ -0,0 +1,137 @@ +// Copyright (c) 2010 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/geolocation/location_arbitrator.h" + +#include <map> + +#include "base/logging.h" +#include "base/non_thread_safe.h" +#include "base/ref_counted.h" +#include "base/scoped_ptr.h" +#include "base/string_util.h" +#include "chrome/browser/net/url_request_context_getter.h" +#include "chrome/browser/geolocation/access_token_store.h" +#include "chrome/browser/geolocation/geoposition.h" +#include "chrome/browser/geolocation/location_provider.h" +#include "googleurl/src/gurl.h" + +namespace { + +const char* kDefaultNetworkProviderUrl = "https://www.google.com/loc/json"; + +class GeolocationArbitratorImpl + : public GeolocationArbitrator, + public LocationProviderBase::ListenerInterface, + public NonThreadSafe { + public: + GeolocationArbitratorImpl(AccessTokenStore* access_token_store, + URLRequestContextGetter* context_getter); + ~GeolocationArbitratorImpl(); + + // GeolocationArbitrator + virtual void AddObserver(Delegate* delegate, + const UpdateOptions& update_options); + virtual void RemoveObserver(Delegate* delegate); + virtual void SetUseMockProvider(bool use_mock); + + // ListenerInterface + virtual void LocationUpdateAvailable(LocationProviderBase* provider); + virtual void MovementDetected(LocationProviderBase* provider); + + private: + void CreateProviders(); + bool HasHighAccuracyObserver(); + + scoped_refptr<AccessTokenStore> access_token_store_; + scoped_refptr<URLRequestContextGetter> context_getter_; + + const GURL default_url_; + scoped_ptr<LocationProviderBase> provider_; + + typedef std::map<Delegate*, UpdateOptions> DelegateMap; + DelegateMap observers_; + bool use_mock_; +}; + +} // namespace + +GeolocationArbitrator* GeolocationArbitrator::New( + AccessTokenStore* access_token_store, + URLRequestContextGetter* context_getter) { + return new GeolocationArbitratorImpl(access_token_store, context_getter); +} + +GeolocationArbitratorImpl::GeolocationArbitratorImpl( + AccessTokenStore* access_token_store, + URLRequestContextGetter* context_getter) + : access_token_store_(access_token_store), context_getter_(context_getter), + default_url_(kDefaultNetworkProviderUrl), use_mock_(false) { + DCHECK(default_url_.is_valid()); +} + +GeolocationArbitratorImpl::~GeolocationArbitratorImpl() { + DCHECK(CalledOnValidThread()); +} + +void GeolocationArbitratorImpl::AddObserver( + Delegate* delegate, const UpdateOptions& update_options) { + DCHECK(CalledOnValidThread()); + observers_[delegate] = update_options; + CreateProviders(); +} + +void GeolocationArbitratorImpl::RemoveObserver(Delegate* delegate) { + DCHECK(CalledOnValidThread()); + observers_.erase(delegate); + if (observers_.empty()) { + // TODO(joth): Delayed callback to linger before destroying the provider. + provider_.reset(); + } +} + +void GeolocationArbitratorImpl::SetUseMockProvider(bool use_mock) { + DCHECK(CalledOnValidThread()); + DCHECK(provider_ == NULL); + use_mock_ = use_mock; +} + +void GeolocationArbitratorImpl::LocationUpdateAvailable( + LocationProviderBase* provider) { + DCHECK(CalledOnValidThread()); + DCHECK(provider); + Position position; + provider->GetPosition(&position); + // TODO(joth): Arbitrate. + for (DelegateMap::const_iterator it = observers_.begin(); + it != observers_.end(); ++it) { + it->first->OnLocationUpdate(position); + } +} + +void GeolocationArbitratorImpl::MovementDetected( + LocationProviderBase* provider) { + DCHECK(CalledOnValidThread()); +} + +void GeolocationArbitratorImpl::CreateProviders() { + DCHECK(CalledOnValidThread()); + DCHECK(!observers_.empty()); + if (provider_ == NULL) { + // TODO(joth): Check with GLS folks what hostname they'd like sent. + provider_.reset(NewNetworkLocationProvider(access_token_store_.get(), + context_getter_.get(), default_url_, ASCIIToUTF16("chromium.org"))); + } + // TODO(joth): Use high-accuracy to create conditionally create GPS provider. +} + +bool GeolocationArbitratorImpl::HasHighAccuracyObserver() { + DCHECK(CalledOnValidThread()); + for (DelegateMap::const_iterator it = observers_.begin(); + it != observers_.end(); ++it) { + if (it->second.use_high_accuracy) + return true; + } + return false; +} diff --git a/chrome/browser/geolocation/location_arbitrator.h b/chrome/browser/geolocation/location_arbitrator.h new file mode 100644 index 0000000..46ab448 --- /dev/null +++ b/chrome/browser/geolocation/location_arbitrator.h @@ -0,0 +1,61 @@ +// Copyright (c) 2010 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 CHROME_BROWSER_GEOLOCATION_LOCATION_ARBITRATOR_H_ +#define CHROME_BROWSER_GEOLOCATION_LOCATION_ARBITRATOR_H_ + +class AccessTokenStore; +class URLRequestContextGetter; +struct Position; + +// This is the main API to the geolocaiton subsystem. Typically the application +// will hold a single instance of this class, and can register multiple +// observers which will be notified of location updates. Underlying location +// provider(s) will only be enabled whilst there is at least one observer +// registered. +// This class is responsible for handling updates from multiple underlying +// providers and resolving them to a single 'best' location fix at any given +// moment. +class GeolocationArbitrator { + public: + // Creates and returns a new instance of the location arbitrator. + static GeolocationArbitrator* New(AccessTokenStore* access_token_store, + URLRequestContextGetter* context_getter); + + class Delegate { + public: + // This will be called whenever the 'best available' location is updated, + // or when an error is encountered meaning no location data will be + // available in the forseeable future. + virtual void OnLocationUpdate(const Position& position) = 0; + + protected: + virtual ~Delegate() {} + }; + struct UpdateOptions { + UpdateOptions() : use_high_accuracy(false) {} + bool use_high_accuracy; + }; + + virtual ~GeolocationArbitrator(); + + // Must be called from the same thread as the arbitrator was created on. + // The update options passed are used as a 'hint' for the provider preferences + // for this particular observer, however the delegate could receive callbacks + // for best available locations from any active provider whilst it is + // registerd. + // If an existing delegate is added a second time it's options are updated + // but only a single call to RemoveObserver() is required to remove it. + virtual void AddObserver(Delegate* delegate, + const UpdateOptions& update_options) = 0; + // Remove a previously registered observer. No-op if not previously registered + // via AddObserver() + virtual void RemoveObserver(Delegate* delegate) = 0; + + // TODO(joth): This is a stop-gap for testing; once we have decoupled + // provider factory we should extract mock creation from the arbitrator. + virtual void SetUseMockProvider(bool use_mock) = 0; +}; + +#endif // CHROME_BROWSER_GEOLOCATION_LOCATION_ARBITRATOR_H_ diff --git a/chrome/browser/geolocation/location_provider.h b/chrome/browser/geolocation/location_provider.h index eca5b57..e5e650f 100644 --- a/chrome/browser/geolocation/location_provider.h +++ b/chrome/browser/geolocation/location_provider.h @@ -17,26 +17,14 @@ #include "base/non_thread_safe.h" #include "base/string16.h" +class AccessTokenStore; class GURL; -struct Position; class URLRequestContextGetter; +struct Position; // The base class used by all location providers. class LocationProviderBase : public NonThreadSafe { public: - // Provides storage for the access token used in the network request. - // Normally the client (i.e. geolocation controller) implements this, but - // also allows mocking for testing. - class AccessTokenStore { - public: - virtual bool SetAccessToken(const GURL& url, - const string16& access_token) = 0; - virtual bool GetAccessToken(const GURL& url, string16* access_token) = 0; - - protected: - virtual ~AccessTokenStore() {} - }; - // Clients of the location provider must implement this interface. All call- // backs to this interface will happen in the context of the thread on which // the location provider was created. @@ -104,7 +92,7 @@ class LocationProviderBase : public NonThreadSafe { LocationProviderBase* NewMockLocationProvider(); LocationProviderBase* NewGpsLocationProvider(); LocationProviderBase* NewNetworkLocationProvider( - LocationProviderBase::AccessTokenStore* access_token_store, + AccessTokenStore* access_token_store, URLRequestContextGetter* context, const GURL& url, const string16& host_name); diff --git a/chrome/browser/geolocation/network_location_provider.cc b/chrome/browser/geolocation/network_location_provider.cc index f4d0455..932ff0e 100644 --- a/chrome/browser/geolocation/network_location_provider.cc +++ b/chrome/browser/geolocation/network_location_provider.cc @@ -5,6 +5,7 @@ #include "chrome/browser/geolocation/network_location_provider.h" #include "base/time.h" +#include "chrome/browser/geolocation/access_token_store.h" namespace { // The maximum period of time we'll wait for a complete set of device data @@ -103,7 +104,7 @@ class NetworkLocationProvider::PositionCache { // NetworkLocationProvider factory function LocationProviderBase* NewNetworkLocationProvider( - LocationProviderBase::AccessTokenStore* access_token_store, + AccessTokenStore* access_token_store, URLRequestContextGetter* context, const GURL& url, const string16& host_name) { diff --git a/chrome/browser/geolocation/network_location_provider.h b/chrome/browser/geolocation/network_location_provider.h index 94e5b5b..9dfe59ac 100644 --- a/chrome/browser/geolocation/network_location_provider.h +++ b/chrome/browser/geolocation/network_location_provider.h @@ -54,7 +54,7 @@ class NetworkLocationProvider bool server_error, const string16& access_token); - AccessTokenStore* access_token_store_; + scoped_refptr<AccessTokenStore> access_token_store_; // The device data providers, acquired via global factories. RadioDataProvider* radio_data_provider_; diff --git a/chrome/browser/geolocation/network_location_provider_unittest.cc b/chrome/browser/geolocation/network_location_provider_unittest.cc index 2a622e4..6a56c01 100644 --- a/chrome/browser/geolocation/network_location_provider_unittest.cc +++ b/chrome/browser/geolocation/network_location_provider_unittest.cc @@ -10,6 +10,7 @@ #include "base/scoped_ptr.h" #include "base/string_util.h" #include "base/values.h" +#include "chrome/browser/geolocation/access_token_store.h" #include "chrome/browser/net/test_url_fetcher_factory.h" #include "net/url_request/url_request_status.h" #include "testing/gtest/include/gtest/gtest.h" @@ -45,7 +46,7 @@ class MessageLoopQuitListener LocationProviderBase* movement_provider_; }; -class FakeAccessTokenStore : public LocationProviderBase::AccessTokenStore { +class FakeAccessTokenStore : public AccessTokenStore { public: FakeAccessTokenStore() : allow_set_(true) {} @@ -65,6 +66,9 @@ class FakeAccessTokenStore : public LocationProviderBase::AccessTokenStore { } bool allow_set_; std::map<GURL, string16> token_map_; + + private: + ~FakeAccessTokenStore() {} }; @@ -132,6 +136,7 @@ class GeolocationNetworkProviderTest : public testing::Test { public: virtual void SetUp() { URLFetcher::set_factory(&url_fetcher_factory_); + access_token_store_ = new FakeAccessTokenStore; } virtual void TearDown() { @@ -143,7 +148,7 @@ class GeolocationNetworkProviderTest : public testing::Test { LocationProviderBase* CreateProvider() { return NewNetworkLocationProvider( - &access_token_store_, + access_token_store_.get(), NULL, // No URLContextGetter needed, as using test urlfecther factory. test_server_url_, ASCIIToUTF16(kTestHost)); @@ -253,7 +258,7 @@ class GeolocationNetworkProviderTest : public testing::Test { const GURL test_server_url_; MessageLoop main_message_loop_; - FakeAccessTokenStore access_token_store_; + scoped_refptr<FakeAccessTokenStore> access_token_store_; TestURLFetcherFactory url_fetcher_factory_; }; @@ -315,9 +320,9 @@ TEST_F(GeolocationNetworkProviderTest, MultipleWifiScansComplete) { ResponseCookies(), kNoFixNetworkResponse); // This should have set the access token anyhow - EXPECT_EQ(1, static_cast<int>(access_token_store_.token_map_.size())); + EXPECT_EQ(1, static_cast<int>(access_token_store_->token_map_.size())); string16 token; - EXPECT_TRUE(access_token_store_.GetAccessToken(test_server_url_, &token)); + EXPECT_TRUE(access_token_store_->GetAccessToken(test_server_url_, &token)); EXPECT_EQ(REFERENCE_ACCESS_TOKEN, UTF16ToUTF8(token)); Position position; @@ -361,8 +366,8 @@ TEST_F(GeolocationNetworkProviderTest, MultipleWifiScansComplete) { EXPECT_TRUE(position.IsValidFix()); // Token should still be in the store. - EXPECT_EQ(1, static_cast<int>(access_token_store_.token_map_.size())); - EXPECT_TRUE(access_token_store_.GetAccessToken(test_server_url_, &token)); + EXPECT_EQ(1, static_cast<int>(access_token_store_->token_map_.size())); + EXPECT_TRUE(access_token_store_->GetAccessToken(test_server_url_, &token)); EXPECT_EQ(REFERENCE_ACCESS_TOKEN, UTF16ToUTF8(token)); // Wifi updated again, with one less AP. This is 'close enough' to the diff --git a/chrome/browser/geolocation/network_location_request.h b/chrome/browser/geolocation/network_location_request.h index 4bf77fc..da89cb1 100644 --- a/chrome/browser/geolocation/network_location_request.h +++ b/chrome/browser/geolocation/network_location_request.h @@ -12,9 +12,9 @@ #include "chrome/browser/net/url_fetcher.h" #include "googleurl/src/gurl.h" -struct Position; class URLRequestContextGetter; class URLFetcher; +struct Position; // Takes a set of device data and sends it to a server to get a position fix. // It performs formatting of the request and interpretation of the response. diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index a309975..2a1b00d 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -921,11 +921,15 @@ 'browser/form_field_history_manager.h', 'browser/gears_integration.cc', 'browser/gears_integration.h', + 'browser/geolocation/access_token_store.cc', + 'browser/geolocation/access_token_store.h', 'browser/geolocation/device_data_provider.h', 'browser/geolocation/empty_device_data_provider.cc', 'browser/geolocation/empty_device_data_provider.h', 'browser/geolocation/geoposition.cc', 'browser/geolocation/geoposition.h', + 'browser/geolocation/location_arbitrator.cc', + 'browser/geolocation/location_arbitrator.h', 'browser/geolocation/location_provider.cc', 'browser/geolocation/location_provider.h', 'browser/geolocation/location_provider_pool.cc', diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index a742996..74bc67e 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -20,7 +20,7 @@ const wchar_t kHomePage[] = L"homepage"; // it means the profile didn't exit cleanly. const wchar_t kSessionExitedCleanly[] = L"profile.exited_cleanly"; -// This is one of three integer values: +// An integer pref. Holds one of several values: // 0: (or empty) don't do anything special on startup. // 1: restore the last session. // 2: this was used to indicate a specific session should be restored. It is @@ -664,4 +664,8 @@ const wchar_t kWebAppCreateInAppsMenu[] = const wchar_t kWebAppCreateInQuickLaunchBar[] = L"browser.web_app.create_in_quick_launch_bar"; +// Dictionary that maps Geolocation network provider server URLs to +// corresponding access token. +const wchar_t kGeolocationAccessToken[] = L"geolocation.access_token"; + } // namespace prefs diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 6fecca6..145e5c1 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -247,6 +247,8 @@ extern const wchar_t kWebAppCreateOnDesktop[]; extern const wchar_t kWebAppCreateInAppsMenu[]; extern const wchar_t kWebAppCreateInQuickLaunchBar[]; +extern const wchar_t kGeolocationAccessToken[]; + } // namespace prefs #endif // CHROME_COMMON_PREF_NAMES_H_ |