diff options
author | pkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-19 01:52:45 +0000 |
---|---|---|
committer | pkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-19 01:52:45 +0000 |
commit | aee541ebc97e1ff2c8bb43e4375913f582931d40 (patch) | |
tree | 49e6735353739bef26d1e960738470247ffa0dc8 | |
parent | 470ad82d83b7773ed5c791a1f3b612087b980eee (diff) | |
download | chromium_src-aee541ebc97e1ff2c8bb43e4375913f582931d40.zip chromium_src-aee541ebc97e1ff2c8bb43e4375913f582931d40.tar.gz chromium_src-aee541ebc97e1ff2c8bb43e4375913f582931d40.tar.bz2 |
Add GeolocationContentSettingsMap, a geolocation-specific variant of HostContentSettingsMap.
This was originally written by bulach and posted at http://codereview.chromium.org/1033004 ; modified and landed by me.
BUG=37206
TEST=Tested by unittests
TBR=bulach,joth
Review URL: http://codereview.chromium.org/1084005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42064 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/browser_prefs.cc | 2 | ||||
-rwxr-xr-x | chrome/browser/geolocation/geolocation_content_settings_map.cc | 203 | ||||
-rwxr-xr-x | chrome/browser/geolocation/geolocation_content_settings_map.h | 121 | ||||
-rwxr-xr-x | chrome/browser/geolocation/geolocation_content_settings_map_unittest.cc | 231 | ||||
-rw-r--r-- | chrome/browser/host_content_settings_map.cc | 2 | ||||
-rw-r--r-- | chrome/browser/profile.cc | 11 | ||||
-rw-r--r-- | chrome/browser/profile.h | 7 | ||||
-rwxr-xr-x | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/chrome_common.gypi | 5 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | chrome/common/content_settings.cc | 11 | ||||
-rw-r--r-- | chrome/common/content_settings.h | 4 | ||||
-rw-r--r-- | chrome/common/pref_names.cc | 7 | ||||
-rw-r--r-- | chrome/common/pref_names.h | 2 | ||||
-rw-r--r-- | chrome/test/testing_profile.h | 10 |
15 files changed, 616 insertions, 3 deletions
diff --git a/chrome/browser/browser_prefs.cc b/chrome/browser/browser_prefs.cc index 85eac53..187201a 100644 --- a/chrome/browser/browser_prefs.cc +++ b/chrome/browser/browser_prefs.cc @@ -16,6 +16,7 @@ #include "chrome/browser/extensions/extension_prefs.h" #include "chrome/browser/extensions/extensions_ui.h" #include "chrome/browser/external_protocol_handler.h" +#include "chrome/browser/geolocation/geolocation_content_settings_map.h" #include "chrome/browser/geolocation/geolocation_prefs.h" #include "chrome/browser/google_url_tracker.h" #include "chrome/browser/host_content_settings_map.h" @@ -102,6 +103,7 @@ void RegisterUserPrefs(PrefService* user_prefs) { Blacklist::RegisterUserPrefs(user_prefs); PinnedTabCodec::RegisterUserPrefs(user_prefs); ExtensionPrefs::RegisterUserPrefs(user_prefs); + GeolocationContentSettingsMap::RegisterUserPrefs(user_prefs); #if defined(TOOLKIT_VIEWS) BrowserActionsContainer::RegisterUserPrefs(user_prefs); #elif defined(TOOLKIT_GTK) diff --git a/chrome/browser/geolocation/geolocation_content_settings_map.cc b/chrome/browser/geolocation/geolocation_content_settings_map.cc new file mode 100755 index 0000000..3f88fb2 --- /dev/null +++ b/chrome/browser/geolocation/geolocation_content_settings_map.cc @@ -0,0 +1,203 @@ +// 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/geolocation_content_settings_map.h" + +#include "base/utf_string_conversions.h" +#include "chrome/browser/chrome_thread.h" +#include "chrome/browser/pref_service.h" +#include "chrome/browser/profile.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/notification_type.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/url_constants.h" +#include "net/base/dns_util.h" +#include "net/base/static_cookie_policy.h" + +// static +const ContentSetting + GeolocationContentSettingsMap::kDefaultSetting = CONTENT_SETTING_ASK; + +GeolocationContentSettingsMap::GeolocationContentSettingsMap(Profile* profile) + : profile_(profile) { + PrefService* prefs = profile_->GetPrefs(); + + // Read global defaults. + default_content_setting_ = IntToContentSetting( + prefs->GetInteger(prefs::kGeolocationDefaultContentSetting)); + if (default_content_setting_ == CONTENT_SETTING_DEFAULT) + default_content_setting_ = kDefaultSetting; + + // Read exceptions. + const DictionaryValue* all_settings_dictionary = + prefs->GetDictionary(prefs::kGeolocationContentSettings); + // Careful: The returned value could be NULL if the pref has never been set. + if (all_settings_dictionary != NULL) { + for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys()); + i != all_settings_dictionary->end_keys(); ++i) { + const std::wstring& wide_origin(*i); + DictionaryValue* requesting_origin_settings_dictionary = NULL; + bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion( + wide_origin, &requesting_origin_settings_dictionary); + DCHECK(found); + OneOriginSettings* requesting_origin_settings = + &content_settings_[GURL(WideToUTF8(wide_origin))]; + GetOneOriginSettingsFromDictionary(requesting_origin_settings_dictionary, + requesting_origin_settings); + } + } +} + +// static +void GeolocationContentSettingsMap::RegisterUserPrefs(PrefService* prefs) { + prefs->RegisterIntegerPref(prefs::kGeolocationDefaultContentSetting, + CONTENT_SETTING_ASK); + prefs->RegisterDictionaryPref(prefs::kGeolocationContentSettings); +} + +ContentSetting GeolocationContentSettingsMap::GetDefaultContentSetting() const { + AutoLock auto_lock(lock_); + return default_content_setting_; +} + +ContentSetting GeolocationContentSettingsMap::GetContentSetting( + const GURL& requesting_url, + const GURL& embedding_url) const { + DCHECK(requesting_url.is_valid() && embedding_url.is_valid()); + GURL requesting_origin(requesting_url.GetOrigin()); + GURL embedding_origin(embedding_url.GetOrigin()); + DCHECK(requesting_origin.is_valid() && embedding_origin.is_valid()); + AutoLock auto_lock(lock_); + AllOriginsSettings::const_iterator i(content_settings_.find( + requesting_origin)); + if (i != content_settings_.end()) { + OneOriginSettings::const_iterator j(i->second.find(embedding_origin)); + if (j != i->second.end()) + return j->second; + if (requesting_origin != embedding_origin) { + OneOriginSettings::const_iterator any_embedder(i->second.find(GURL())); + if (any_embedder != i->second.end()) + return any_embedder->second; + } + } + return default_content_setting_; +} + +GeolocationContentSettingsMap::AllOriginsSettings + GeolocationContentSettingsMap::GetAllOriginsSettings() const { + AutoLock auto_lock(lock_); + return content_settings_; +} + +void GeolocationContentSettingsMap::SetDefaultContentSetting( + ContentSetting setting) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); + { + AutoLock auto_lock(lock_); + default_content_setting_ = + (setting == CONTENT_SETTING_DEFAULT) ? kDefaultSetting : setting; + } + profile_->GetPrefs()->SetInteger(prefs::kGeolocationDefaultContentSetting, + default_content_setting_); +} + +void GeolocationContentSettingsMap::SetContentSetting( + const GURL& requesting_url, + const GURL& embedding_url, + ContentSetting setting) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); + DCHECK(requesting_url.is_valid() && + (embedding_url.is_valid() || embedding_url.is_empty())); + GURL requesting_origin(requesting_url.GetOrigin()); + GURL embedding_origin(embedding_url.GetOrigin()); + DCHECK(requesting_origin.is_valid() && + (embedding_origin.is_valid() || embedding_url.is_empty())); + std::wstring wide_requesting_origin(UTF8ToWide(requesting_origin.spec())); + std::wstring wide_embedding_origin(UTF8ToWide(embedding_origin.spec())); + DictionaryValue* all_settings_dictionary = + profile_->GetPrefs()->GetMutableDictionary( + prefs::kGeolocationContentSettings); + + AutoLock auto_lock(lock_); + DictionaryValue* requesting_origin_settings_dictionary; + all_settings_dictionary->GetDictionaryWithoutPathExpansion( + wide_requesting_origin, &requesting_origin_settings_dictionary); + if (setting == CONTENT_SETTING_DEFAULT) { + if (!content_settings_.count(requesting_origin) || + !content_settings_[requesting_origin].count(embedding_origin)) + return; + if (content_settings_[requesting_origin].size() == 1) { + all_settings_dictionary->RemoveWithoutPathExpansion( + wide_requesting_origin, NULL); + content_settings_.erase(requesting_origin); + return; + } + requesting_origin_settings_dictionary->RemoveWithoutPathExpansion( + wide_embedding_origin, NULL); + content_settings_[requesting_origin].erase(embedding_origin); + return; + } + + if (!content_settings_.count(requesting_origin)) { + requesting_origin_settings_dictionary = new DictionaryValue; + all_settings_dictionary->SetWithoutPathExpansion( + wide_requesting_origin, requesting_origin_settings_dictionary); + } + content_settings_[requesting_origin][embedding_origin] = setting; + DCHECK(requesting_origin_settings_dictionary); + requesting_origin_settings_dictionary->SetWithoutPathExpansion( + wide_embedding_origin, Value::CreateIntegerValue(setting)); +} + +void GeolocationContentSettingsMap::ClearOneRequestingOrigin( + const GURL& requesting_origin) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); + DCHECK(requesting_origin.is_valid()); + + { + AutoLock auto_lock(lock_); + AllOriginsSettings::iterator i(content_settings_.find(requesting_origin)); + if (i == content_settings_.end()) + return; + content_settings_.erase(i); + } + + DictionaryValue* all_settings_dictionary = + profile_->GetPrefs()->GetMutableDictionary( + prefs::kGeolocationContentSettings); + all_settings_dictionary->RemoveWithoutPathExpansion( + UTF8ToWide(requesting_origin.spec()), NULL); +} + +void GeolocationContentSettingsMap::ResetToDefault() { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); + + { + AutoLock auto_lock(lock_); + default_content_setting_ = kDefaultSetting; + content_settings_.clear(); + } + + PrefService* prefs = profile_->GetPrefs(); + prefs->ClearPref(prefs::kGeolocationDefaultContentSetting); + prefs->ClearPref(prefs::kGeolocationContentSettings); +} + +GeolocationContentSettingsMap::~GeolocationContentSettingsMap() { +} + +// static +void GeolocationContentSettingsMap::GetOneOriginSettingsFromDictionary( + const DictionaryValue* dictionary, + OneOriginSettings* one_origin_settings) { + for (DictionaryValue::key_iterator i(dictionary->begin_keys()); + i != dictionary->end_keys(); ++i) { + const std::wstring& target(*i); + int setting = kDefaultSetting; + bool found = dictionary->GetIntegerWithoutPathExpansion(target, &setting); + DCHECK(found); + (*one_origin_settings)[GURL(WideToUTF8(target))] = + IntToContentSetting(setting); + } +} diff --git a/chrome/browser/geolocation/geolocation_content_settings_map.h b/chrome/browser/geolocation/geolocation_content_settings_map.h new file mode 100755 index 0000000..df9d953 --- /dev/null +++ b/chrome/browser/geolocation/geolocation_content_settings_map.h @@ -0,0 +1,121 @@ +// 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. + +// Maps [requesting_origin, embedder] to content settings. Written on the UI +// thread and read on any thread. One instance per profile. This is based on +// HostContentSettingsMap but differs significantly in two aspects: +// - It maps [requesting_origin.GetOrigin(), embedder.GetOrigin()] => setting +// rather than host => setting. +// - It manages only Geolocation. + +#ifndef CHROME_BROWSER_GEOLOCATION_GEOLOCATION_CONTENT_SETTINGS_MAP_H_ +#define CHROME_BROWSER_GEOLOCATION_GEOLOCATION_CONTENT_SETTINGS_MAP_H_ + +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include "base/basictypes.h" +#include "base/lock.h" +#include "base/ref_counted.h" +#include "chrome/common/content_settings.h" +#include "googleurl/src/gurl.h" + +class DictionaryValue; +class PrefService; +class Profile; + +class GeolocationContentSettingsMap + : public base::RefCountedThreadSafe<GeolocationContentSettingsMap> { + public: + typedef std::map<GURL, ContentSetting> OneOriginSettings; + typedef std::map<GURL, OneOriginSettings> AllOriginsSettings; + + explicit GeolocationContentSettingsMap(Profile* profile); + + static void RegisterUserPrefs(PrefService* prefs); + + // Returns the default setting. + // + // This may be called on any thread. + ContentSetting GetDefaultContentSetting() const; + + // Returns a single ContentSetting which applies to the given |requesting_url| + // when embedded in a top-level page from |embedding_url|. To determine the + // setting for a top-level page, as opposed to a frame embedded in a page, + // pass the page's URL for both arguments. + // + // This may be called on any thread. Both arguments should be valid GURLs. + ContentSetting GetContentSetting(const GURL& requesting_url, + const GURL& embedding_url) const; + + // Returns the settings for all origins with any non-default settings. + // + // This may be called on any thread. + AllOriginsSettings GetAllOriginsSettings() const; + + // Sets the default setting. + // + // This should only be called on the UI thread. + void SetDefaultContentSetting(ContentSetting setting); + + // Sets the content setting for a particular (requesting origin, embedding + // origin) pair. If the embedding origin is the same as the requesting + // origin, this represents the setting used when the requesting origin is + // itself the top-level page. If |embedder| is the empty GURL, |setting| + // becomes the default setting for the requesting origin when embedded on any + // page that does not have an explicit setting. Passing + // CONTENT_SETTING_DEFAULT for |setting| effectively removes that setting and + // allows future requests to return the all-embedders or global defaults (as + // applicable). + // + // This should only be called on the UI thread. |requesting_url| should be + // a valid GURL, and |embedding_url| should be valid or empty. + void SetContentSetting(const GURL& requesting_url, + const GURL& embedding_url, + ContentSetting setting); + + // Clears all settings for |requesting_origin|. Note: Unlike in the functions + // above, this is expected to be an origin, not some URL of which we'll take + // the origin; this is to prevent ambiguity where callers could think they're + // clearing something wider or narrower than they really are. + // + // This should only be called on the UI thread. |requesting_origin| should be + // a valid GURL. + void ClearOneRequestingOrigin(const GURL& requesting_origin); + + // Resets all settings. + // + // This should only be called on the UI thread. + void ResetToDefault(); + + private: + friend class base::RefCountedThreadSafe<GeolocationContentSettingsMap>; + + // The default setting. + static const ContentSetting kDefaultSetting; + + ~GeolocationContentSettingsMap(); + + // Sets the fields of |one_origin_settings| based on the values in + // |dictionary|. + static void GetOneOriginSettingsFromDictionary( + const DictionaryValue* dictionary, + OneOriginSettings* one_origin_settings); + + // The profile we're associated with. + Profile* profile_; + + // Copies of the pref data, so that we can read it on the IO thread. + ContentSetting default_content_setting_; + AllOriginsSettings content_settings_; + + // Used around accesses to the settings objects to guarantee thread safety. + mutable Lock lock_; + + DISALLOW_COPY_AND_ASSIGN(GeolocationContentSettingsMap); +}; + +#endif // CHROME_BROWSER_GEOLOCATION_GEOLOCATION_CONTENT_SETTINGS_MAP_H_ diff --git a/chrome/browser/geolocation/geolocation_content_settings_map_unittest.cc b/chrome/browser/geolocation/geolocation_content_settings_map_unittest.cc new file mode 100755 index 0000000..4219c6d --- /dev/null +++ b/chrome/browser/geolocation/geolocation_content_settings_map_unittest.cc @@ -0,0 +1,231 @@ +// 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/geolocation_content_settings_map.h" + +#include "chrome/test/testing_profile.h" +#include "testing/gtest/include/gtest/gtest.h" + + +namespace { + +class GeolocationContentSettingsMapTests : public testing::Test { + public: + GeolocationContentSettingsMapTests() + : ui_thread_(ChromeThread::UI, &message_loop_) { + } + + protected: + MessageLoop message_loop_; + ChromeThread ui_thread_; +}; + +TEST_F(GeolocationContentSettingsMapTests, DefaultValues) { + TestingProfile profile; + GeolocationContentSettingsMap* map = + profile.GetGeolocationContentSettingsMap(); + + // Check setting defaults. + EXPECT_EQ(CONTENT_SETTING_ASK, map->GetDefaultContentSetting()); + map->SetDefaultContentSetting(CONTENT_SETTING_BLOCK); + EXPECT_EQ(CONTENT_SETTING_BLOCK, map->GetDefaultContentSetting()); +} + +TEST_F(GeolocationContentSettingsMapTests, Embedder) { + TestingProfile profile; + GeolocationContentSettingsMap* map = + profile.GetGeolocationContentSettingsMap(); + GURL top_level("http://www.toplevel0.com/foo/bar"); + EXPECT_EQ(CONTENT_SETTING_ASK, map->GetContentSetting(top_level, top_level)); + // Now set the permission for requester_0. + map->SetContentSetting(top_level, top_level, CONTENT_SETTING_ALLOW); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(top_level, top_level)); + + GURL requester_0("http://www.frame0.com/foo/bar"); + EXPECT_EQ(CONTENT_SETTING_ASK, + map->GetContentSetting(requester_0, top_level)); + // Now set the permission for only requester_1. + map->SetContentSetting(requester_0, top_level, CONTENT_SETTING_ALLOW); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(top_level, top_level)); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(requester_0, top_level)); + // Block only requester_1. + map->SetContentSetting(requester_0, top_level, CONTENT_SETTING_BLOCK); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + map->GetContentSetting(requester_0, top_level)); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(top_level, top_level)); +} + +TEST_F(GeolocationContentSettingsMapTests, MultipleEmbeddersAndOrigins) { + TestingProfile profile; + GeolocationContentSettingsMap* map = + profile.GetGeolocationContentSettingsMap(); + GURL requester_0("http://www.iframe0.com/foo/bar"); + GURL requester_1("http://www.iframe1.co.uk/bar/foo"); + GURL embedder_0("http://www.toplevel0.com/foo/bar"); + EXPECT_EQ(CONTENT_SETTING_ASK, + map->GetContentSetting(requester_0, embedder_0)); + EXPECT_EQ(CONTENT_SETTING_ASK, + map->GetContentSetting(requester_1, embedder_0)); + // Now set the permission for only one origin. + map->SetContentSetting(requester_0, embedder_0, CONTENT_SETTING_ALLOW); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(requester_0, embedder_0)); + EXPECT_EQ(CONTENT_SETTING_ASK, + map->GetContentSetting(requester_1, embedder_0)); + // Set the permission for the other origin. + map->SetContentSetting(requester_1, embedder_0, CONTENT_SETTING_ALLOW); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(requester_1, embedder_0)); + // Check they're not allowed on a different embedder. + GURL embedder_1("http://www.toplevel1.com/foo/bar"); + EXPECT_EQ(CONTENT_SETTING_ASK, + map->GetContentSetting(requester_0, embedder_1)); + EXPECT_EQ(CONTENT_SETTING_ASK, + map->GetContentSetting(requester_1, embedder_1)); + // Check all settings are valid. + GeolocationContentSettingsMap::AllOriginsSettings content_settings( + map->GetAllOriginsSettings()); + EXPECT_EQ(0U, content_settings.count(requester_0)); + EXPECT_EQ(1U, content_settings.count(requester_0.GetOrigin())); + GeolocationContentSettingsMap::OneOriginSettings one_origin_settings( + content_settings[requester_0.GetOrigin()]); + EXPECT_EQ(CONTENT_SETTING_ALLOW, one_origin_settings[embedder_0.GetOrigin()]); + + EXPECT_EQ(0U, content_settings.count(requester_1)); + EXPECT_EQ(1U, content_settings.count(requester_1.GetOrigin())); + one_origin_settings = content_settings[requester_1.GetOrigin()]; + EXPECT_EQ(CONTENT_SETTING_ALLOW, one_origin_settings[embedder_0.GetOrigin()]); + // Block requester_1 on the first embedder and add it to the second. + map->SetContentSetting(requester_1, embedder_0, CONTENT_SETTING_BLOCK); + map->SetContentSetting(requester_1, embedder_1, CONTENT_SETTING_ALLOW); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + map->GetContentSetting(requester_1, embedder_0)); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(requester_1, embedder_1)); +} + +TEST_F(GeolocationContentSettingsMapTests, SetContentSettingDefault) { + TestingProfile profile; + GeolocationContentSettingsMap* map = + profile.GetGeolocationContentSettingsMap(); + GURL top_level("http://www.toplevel0.com/foo/bar"); + map->SetContentSetting(top_level, top_level, CONTENT_SETTING_ALLOW); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(top_level, top_level)); + // Set to CONTENT_SETTING_DEFAULT and check the actual value has changed. + map->SetContentSetting(top_level, top_level, CONTENT_SETTING_DEFAULT); + EXPECT_EQ(CONTENT_SETTING_ASK, map->GetContentSetting(top_level, top_level)); +} + +TEST_F(GeolocationContentSettingsMapTests, ClearOneOrigin) { + TestingProfile profile; + GeolocationContentSettingsMap* map = + profile.GetGeolocationContentSettingsMap(); + GURL requester_0("http://www.iframe0.com/foo/bar"); + GURL requester_1("http://www.iframe1.com/foo/bar"); + GURL embedder_0("http://www.toplevel0.com/foo/bar"); + map->SetContentSetting(requester_0, embedder_0, CONTENT_SETTING_ALLOW); + map->SetContentSetting(requester_1, embedder_0, CONTENT_SETTING_ALLOW); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(requester_0, embedder_0)); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(requester_1, embedder_0)); + + map->ClearOneRequestingOrigin(requester_0.GetOrigin()); + EXPECT_EQ(CONTENT_SETTING_ASK, + map->GetContentSetting(requester_0, embedder_0)); + + // Passing a non-origin shouldn't do anything. + map->ClearOneRequestingOrigin(requester_1); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(requester_1, embedder_0)); +} + +TEST_F(GeolocationContentSettingsMapTests, Reset) { + TestingProfile profile; + GeolocationContentSettingsMap* map = + profile.GetGeolocationContentSettingsMap(); + GURL requester_0("http://www.iframe0.com/foo/bar"); + GURL embedder_0("http://www.toplevel0.com/foo/bar"); + map->SetContentSetting(requester_0, embedder_0, CONTENT_SETTING_ALLOW); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(requester_0, embedder_0)); + GeolocationContentSettingsMap::AllOriginsSettings content_settings( + map->GetAllOriginsSettings()); + EXPECT_EQ(1U, content_settings.size()); + + // Set to CONTENT_SETTING_DEFAULT and check the actual value has changed. + map->SetContentSetting(requester_0, embedder_0, CONTENT_SETTING_DEFAULT); + EXPECT_EQ(CONTENT_SETTING_ASK, + map->GetContentSetting(requester_0, embedder_0)); + content_settings = map->GetAllOriginsSettings(); + EXPECT_TRUE(content_settings.empty()); +} + +TEST_F(GeolocationContentSettingsMapTests, ClearsWhenSettingBackToDefault) { + TestingProfile profile; + GeolocationContentSettingsMap* map = + profile.GetGeolocationContentSettingsMap(); + GURL requester_0("http://www.iframe0.com/foo/bar"); + GURL requester_1("http://www.iframe1.com/foo/bar"); + GURL embedder_0("http://www.toplevel0.com/foo/bar"); + map->SetContentSetting(requester_0, embedder_0, CONTENT_SETTING_ALLOW); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(requester_0, embedder_0)); + GeolocationContentSettingsMap::AllOriginsSettings content_settings( + map->GetAllOriginsSettings()); + EXPECT_EQ(1U, content_settings.size()); + + map->SetContentSetting(requester_1, embedder_0, CONTENT_SETTING_ALLOW); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(requester_1, embedder_0)); + content_settings = map->GetAllOriginsSettings(); + EXPECT_EQ(2U, content_settings.size()); + EXPECT_EQ(1U, content_settings[requester_0.GetOrigin()].size()); + EXPECT_EQ(1U, content_settings[requester_1.GetOrigin()].size()); + + // Set to default. + map->SetContentSetting(requester_0, embedder_0, CONTENT_SETTING_DEFAULT); + content_settings = map->GetAllOriginsSettings(); + EXPECT_EQ(1U, content_settings.size()); + + map->SetContentSetting(requester_1, embedder_0, CONTENT_SETTING_DEFAULT); + content_settings = map->GetAllOriginsSettings(); + EXPECT_TRUE(content_settings.empty()); +} + +TEST_F(GeolocationContentSettingsMapTests, WildCardForEmptyEmbedder) { + TestingProfile profile; + GeolocationContentSettingsMap* map = + profile.GetGeolocationContentSettingsMap(); + GURL requester_0("http://www.iframe0.com/foo/bar"); + GURL embedder_0("http://www.toplevel0.com/foo/bar"); + GURL embedder_1("http://www.toplevel1.com/foo/bar"); + GURL empty_url; + map->SetContentSetting(requester_0, embedder_0, CONTENT_SETTING_BLOCK); + map->SetContentSetting(requester_0, empty_url, CONTENT_SETTING_ALLOW); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + map->GetContentSetting(requester_0, embedder_0)); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(requester_0, embedder_1)); + EXPECT_EQ(CONTENT_SETTING_ASK, + map->GetContentSetting(requester_0, requester_0)); + + // Change the wildcard behavior. + map->SetContentSetting(requester_0, embedder_0, CONTENT_SETTING_ALLOW); + map->SetContentSetting(requester_0, empty_url, CONTENT_SETTING_BLOCK); + map->SetDefaultContentSetting(CONTENT_SETTING_ALLOW); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(requester_0, embedder_0)); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + map->GetContentSetting(requester_0, embedder_1)); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(requester_0, requester_0)); +} + +} // namespace diff --git a/chrome/browser/host_content_settings_map.cc b/chrome/browser/host_content_settings_map.cc index 811836a..2508f6cc 100644 --- a/chrome/browser/host_content_settings_map.cc +++ b/chrome/browser/host_content_settings_map.cc @@ -352,7 +352,7 @@ void HostContentSettingsMap::GetSettingsFromDictionary( DCHECK(found); for (size_t type = 0; type < arraysize(kTypeNames); ++type) { if (std::wstring(kTypeNames[type]) == content_type) { - settings->settings[type] = static_cast<ContentSetting>(setting); + settings->settings[type] = IntToContentSetting(setting); break; } } diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc index c94b38c..802ad29 100644 --- a/chrome/browser/profile.cc +++ b/chrome/browser/profile.cc @@ -28,6 +28,7 @@ #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/extensions/user_script_master.h" #include "chrome/browser/favicon_service.h" +#include "chrome/browser/geolocation/geolocation_content_settings_map.h" #include "chrome/browser/spellcheck_host.h" #include "chrome/browser/transport_security_persister.h" #include "chrome/browser/history/history.h" @@ -408,6 +409,10 @@ class OffTheRecordProfileImpl : public Profile, return profile_->GetHostZoomMap(); } + virtual GeolocationContentSettingsMap* GetGeolocationContentSettingsMap() { + return profile_->GetGeolocationContentSettingsMap(); + } + virtual Blacklist* GetPrivacyBlacklist() { return profile_->GetPrivacyBlacklist(); } @@ -987,6 +992,12 @@ HostZoomMap* ProfileImpl::GetHostZoomMap() { return host_zoom_map_.get(); } +GeolocationContentSettingsMap* ProfileImpl::GetGeolocationContentSettingsMap() { + if (!geolocation_content_settings_map_.get()) + geolocation_content_settings_map_ = new GeolocationContentSettingsMap(this); + return geolocation_content_settings_map_.get(); +} + Blacklist* ProfileImpl::GetPrivacyBlacklist() { if (!CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnablePrivacyBlacklists)) diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h index de6ed47..9db5374 100644 --- a/chrome/browser/profile.h +++ b/chrome/browser/profile.h @@ -42,6 +42,7 @@ class ExtensionProcessManager; class ExtensionMessageService; class ExtensionsService; class FaviconService; +class GeolocationContentSettingsMap; class HistoryService; class HostContentSettingsMap; class HostZoomMap; @@ -298,6 +299,9 @@ class Profile { // Returns the Hostname <-> Zoom Level map for this profile. virtual HostZoomMap* GetHostZoomMap() = 0; + // Returns the geolocation settings map for this profile. + virtual GeolocationContentSettingsMap* GetGeolocationContentSettingsMap() = 0; + // Returns the Privacy Blacklist for this profile. virtual Blacklist* GetPrivacyBlacklist() = 0; @@ -471,6 +475,7 @@ class ProfileImpl : public Profile, virtual net::SSLConfigService* GetSSLConfigService(); virtual HostContentSettingsMap* GetHostContentSettingsMap(); virtual HostZoomMap* GetHostZoomMap(); + virtual GeolocationContentSettingsMap* GetGeolocationContentSettingsMap(); virtual Blacklist* GetPrivacyBlacklist(); virtual UserStyleSheetWatcher* GetUserStyleSheetWatcher(); virtual SessionService* GetSessionService(); @@ -558,6 +563,8 @@ class ProfileImpl : public Profile, scoped_refptr<HostContentSettingsMap> host_content_settings_map_; scoped_refptr<HostZoomMap> host_zoom_map_; + scoped_refptr<GeolocationContentSettingsMap> + geolocation_content_settings_map_; scoped_refptr<Blacklist> privacy_blacklist_; scoped_refptr<UserStyleSheetWatcher> user_style_sheet_watcher_; scoped_refptr<DownloadManager> download_manager_; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 730914a..a6f0e91 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1054,6 +1054,8 @@ 'browser/geolocation/geolocation_permission_context.h', 'browser/geolocation/geolocation_prefs.cc', 'browser/geolocation/geolocation_prefs.h', + 'browser/geolocation/geolocation_content_settings_map.cc', + 'browser/geolocation/geolocation_content_settings_map.h', 'browser/geolocation/location_arbitrator.cc', 'browser/geolocation/location_arbitrator.h', 'browser/geolocation/location_provider.cc', diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index 4fb4c85..6a935e6 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi @@ -42,6 +42,9 @@ 'common/chrome_counters.h', 'common/common_param_traits.cc', 'common/common_param_traits.h', + 'common/content_settings.cc', + 'common/content_settings.h', + 'common/content_settings_types.h', 'common/debug_flags.cc', 'common/debug_flags.h', 'common/devtools_messages.h', @@ -196,8 +199,6 @@ 'common/command_buffer_messages.h', 'common/command_buffer_messages_internal.h', 'common/common_glue.cc', - 'common/content_settings.h' - 'common/content_settings_types.h', 'common/css_colors.h', 'common/db_message_filter.cc', 'common/db_message_filter.h', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index a465999..25e7e7c 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -752,6 +752,7 @@ 'browser/file_watcher_unittest.cc', 'browser/find_backend_unittest.cc', 'browser/geolocation/fake_access_token_store.h', + 'browser/geolocation/geolocation_content_settings_map_unittest.cc', 'browser/geolocation/location_arbitrator_unittest.cc', 'browser/geolocation/network_location_provider_unittest.cc', 'browser/geolocation/wifi_data_provider_common_unittest.cc', diff --git a/chrome/common/content_settings.cc b/chrome/common/content_settings.cc new file mode 100644 index 0000000..89eaa59 --- /dev/null +++ b/chrome/common/content_settings.cc @@ -0,0 +1,11 @@ +// 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/common/content_settings.h" + +ContentSetting IntToContentSetting(int content_setting) { + return ((content_setting < 0) || + (content_setting >= CONTENT_SETTING_NUM_SETTINGS)) ? + CONTENT_SETTING_DEFAULT : static_cast<ContentSetting>(content_setting); +} diff --git a/chrome/common/content_settings.h b/chrome/common/content_settings.h index 63af52e..b077be2 100644 --- a/chrome/common/content_settings.h +++ b/chrome/common/content_settings.h @@ -17,6 +17,10 @@ enum ContentSetting { CONTENT_SETTING_NUM_SETTINGS }; +// Range-checked conversion of an int to a ContentSetting, for use when reading +// prefs off disk. +ContentSetting IntToContentSetting(int content_setting); + // Aggregates the permissions for the different content types. struct ContentSettings { ContentSettings() { diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 24f5f67c..62486e3 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -351,6 +351,13 @@ const wchar_t kEnableTranslate[] = L"translate.enabled"; const wchar_t kPinnedTabs[] = L"pinned_tabs"; +// Integer containing the default Geolocation content setting. +const wchar_t kGeolocationDefaultContentSetting[] = + L"geolocation.default_content_setting"; + +// Dictionary that maps [frame, toplevel] to their Geolocation content setting. +const wchar_t kGeolocationContentSettings[] = L"geolocation.content_settings"; + // *************** LOCAL STATE *************** // These are attached to the machine/installation diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 1e0006f..a8b2de9 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -253,6 +253,8 @@ extern const wchar_t kWebAppCreateInAppsMenu[]; extern const wchar_t kWebAppCreateInQuickLaunchBar[]; extern const wchar_t kGeolocationAccessToken[]; +extern const wchar_t kGeolocationDefaultContentSetting[]; +extern const wchar_t kGeolocationContentSettings[]; } // namespace prefs diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h index 82535c5..08e02b7 100644 --- a/chrome/test/testing_profile.h +++ b/chrome/test/testing_profile.h @@ -12,6 +12,7 @@ #include "chrome/browser/browser_prefs.h" #include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/favicon_service.h" +#include "chrome/browser/geolocation/geolocation_content_settings_map.h" #include "chrome/browser/host_content_settings_map.h" #include "chrome/browser/history/history.h" #include "chrome/browser/in_process_webkit/webkit_context.h" @@ -190,6 +191,13 @@ class TestingProfile : public Profile { host_content_settings_map_ = new HostContentSettingsMap(this); return host_content_settings_map_.get(); } + virtual GeolocationContentSettingsMap* GetGeolocationContentSettingsMap() { + if (!geolocation_content_settings_map_.get()) { + geolocation_content_settings_map_ = + new GeolocationContentSettingsMap(this); + } + return geolocation_content_settings_map_.get(); + } virtual HostZoomMap* GetHostZoomMap() { return NULL; } void set_session_service(SessionService* session_service); virtual SessionService* GetSessionService() { return session_service_.get(); } @@ -315,6 +323,8 @@ class TestingProfile : public Profile { scoped_refptr<WebKitContext> webkit_context_; scoped_refptr<HostContentSettingsMap> host_content_settings_map_; + scoped_refptr<GeolocationContentSettingsMap> + geolocation_content_settings_map_; }; // A profile that derives from another profile. This does not actually |