OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // Implementation of the geolocation content settings map. Styled on | |
6 // HostContentSettingsMap however unlike that class, this one does not hold | |
7 // an additional in-memory copy of the settings as it does not need to support | |
8 // thread safe synchronous access to the settings; all geolocation permissions | |
9 // are read and written in the UI thread. (If in future this is no longer the | |
10 // case, refer to http://codereview.chromium.org/1525018 for a previous version | |
11 // with caching. Note that as we must observe the prefs store for settings | |
12 // changes, e.g. coming from the sync engine, the simplest design would be to | |
13 // always write-through changes straight to the prefs store, and rely on the | |
14 // notification observer to subsequently update any cached copy). | |
15 | |
16 #include "chrome/browser/geolocation/geolocation_content_settings_map.h" | |
17 | |
18 #include <string> | |
19 | |
20 #include "base/string_piece.h" | |
21 #include "base/utf_string_conversions.h" | |
22 #include "chrome/browser/content_settings/content_settings_details.h" | |
23 #include "chrome/browser/content_settings/content_settings_pattern.h" | |
24 #include "chrome/browser/content_settings/host_content_settings_map.h" | |
25 #include "chrome/browser/prefs/pref_service.h" | |
26 #include "chrome/browser/prefs/scoped_user_pref_update.h" | |
27 #include "chrome/browser/profiles/profile.h" | |
28 #include "chrome/common/chrome_notification_types.h" | |
29 #include "chrome/common/pref_names.h" | |
30 #include "chrome/common/url_constants.h" | |
31 #include "content/browser/browser_thread.h" | |
32 #include "content/common/notification_service.h" | |
33 #include "content/common/notification_source.h" | |
34 #include "net/base/dns_util.h" | |
35 #include "net/base/static_cookie_policy.h" | |
36 | |
37 GeolocationContentSettingsMap::GeolocationContentSettingsMap(Profile* profile) | |
38 : profile_(profile) { | |
39 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
40 prefs_registrar_.Init(profile_->GetPrefs()); | |
41 prefs_registrar_.Add(prefs::kGeolocationContentSettings, this); | |
42 notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, | |
43 Source<Profile>(profile_)); | |
44 notification_registrar_.Add( | |
45 this, | |
46 chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED, | |
47 Source<HostContentSettingsMap>(profile_->GetHostContentSettingsMap())); | |
48 } | |
49 | |
50 // static | |
51 void GeolocationContentSettingsMap::RegisterUserPrefs(PrefService* prefs) { | |
52 prefs->RegisterDictionaryPref(prefs::kGeolocationContentSettings, | |
53 PrefService::SYNCABLE_PREF); | |
54 } | |
55 | |
56 ContentSetting GeolocationContentSettingsMap::GetContentSetting( | |
57 const GURL& requesting_url, | |
58 const GURL& embedding_url) const { | |
59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
60 DCHECK(requesting_url.is_valid() && embedding_url.is_valid()); | |
61 GURL requesting_origin(requesting_url.GetOrigin()); | |
62 GURL embedding_origin(embedding_url.GetOrigin()); | |
63 DCHECK(requesting_origin.is_valid() && embedding_origin.is_valid()); | |
64 // If the profile is destroyed (and set to NULL) return CONTENT_SETTING_BLOCK. | |
65 if (!profile_) | |
66 return CONTENT_SETTING_BLOCK; | |
67 const DictionaryValue* all_settings_dictionary = | |
68 profile_->GetPrefs()->GetDictionary(prefs::kGeolocationContentSettings); | |
69 // Careful: The returned value could be NULL if the pref has never been set. | |
70 if (all_settings_dictionary != NULL) { | |
71 DictionaryValue* requesting_origin_settings; | |
72 if (all_settings_dictionary->GetDictionaryWithoutPathExpansion( | |
73 requesting_origin.spec(), &requesting_origin_settings)) { | |
74 int setting; | |
75 if (requesting_origin_settings->GetIntegerWithoutPathExpansion( | |
76 embedding_origin.spec(), &setting)) | |
77 return IntToContentSetting(setting); | |
78 // Check for any-embedder setting | |
79 if (requesting_origin != embedding_origin && | |
80 requesting_origin_settings->GetIntegerWithoutPathExpansion( | |
81 "", &setting)) | |
82 return IntToContentSetting(setting); | |
83 } | |
84 } | |
85 return profile_->GetHostContentSettingsMap()->GetDefaultContentSetting( | |
86 CONTENT_SETTINGS_TYPE_GEOLOCATION); | |
87 } | |
88 | |
89 GeolocationContentSettingsMap::AllOriginsSettings | |
90 GeolocationContentSettingsMap::GetAllOriginsSettings() const { | |
91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
92 AllOriginsSettings content_settings; | |
93 const DictionaryValue* all_settings_dictionary = | |
94 profile_->GetPrefs()->GetDictionary(prefs::kGeolocationContentSettings); | |
95 // Careful: The returned value could be NULL if the pref has never been set. | |
96 if (all_settings_dictionary != NULL) { | |
97 for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys()); | |
98 i != all_settings_dictionary->end_keys(); ++i) { | |
99 const std::string& origin(*i); | |
100 GURL origin_as_url(origin); | |
101 if (!origin_as_url.is_valid()) | |
102 continue; | |
103 DictionaryValue* requesting_origin_settings_dictionary = NULL; | |
104 bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion( | |
105 origin, &requesting_origin_settings_dictionary); | |
106 DCHECK(found); | |
107 if (!requesting_origin_settings_dictionary) | |
108 continue; | |
109 GetOneOriginSettingsFromDictionary( | |
110 requesting_origin_settings_dictionary, | |
111 &content_settings[origin_as_url]); | |
112 } | |
113 } | |
114 return content_settings; | |
115 } | |
116 | |
117 void GeolocationContentSettingsMap::SetContentSetting( | |
118 const GURL& requesting_url, | |
119 const GURL& embedding_url, | |
120 ContentSetting setting) { | |
121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
122 DCHECK(requesting_url.is_valid()); | |
123 DCHECK(embedding_url.is_valid() || embedding_url.is_empty()); | |
124 GURL requesting_origin(requesting_url.GetOrigin()); | |
125 GURL embedding_origin(embedding_url.GetOrigin()); | |
126 DCHECK(requesting_origin.is_valid()); | |
127 DCHECK(embedding_origin.is_valid() || embedding_url.is_empty()); | |
128 if (!profile_) | |
129 return; | |
130 PrefService* prefs = profile_->GetPrefs(); | |
131 | |
132 DictionaryPrefUpdate update(prefs, prefs::kGeolocationContentSettings); | |
133 DictionaryValue* all_settings_dictionary = update.Get(); | |
134 DictionaryValue* requesting_origin_settings_dictionary = NULL; | |
135 all_settings_dictionary->GetDictionaryWithoutPathExpansion( | |
136 requesting_origin.spec(), &requesting_origin_settings_dictionary); | |
137 if (setting == CONTENT_SETTING_DEFAULT) { | |
138 if (requesting_origin_settings_dictionary) { | |
139 requesting_origin_settings_dictionary->RemoveWithoutPathExpansion( | |
140 embedding_origin.spec(), NULL); | |
141 if (requesting_origin_settings_dictionary->empty()) | |
142 all_settings_dictionary->RemoveWithoutPathExpansion( | |
143 requesting_origin.spec(), NULL); | |
144 } | |
145 } else { | |
146 if (!requesting_origin_settings_dictionary) { | |
147 requesting_origin_settings_dictionary = new DictionaryValue; | |
148 all_settings_dictionary->SetWithoutPathExpansion( | |
149 requesting_origin.spec(), requesting_origin_settings_dictionary); | |
150 } | |
151 DCHECK(requesting_origin_settings_dictionary); | |
152 requesting_origin_settings_dictionary->SetWithoutPathExpansion( | |
153 embedding_origin.spec(), Value::CreateIntegerValue(setting)); | |
154 } | |
155 } | |
156 | |
157 void GeolocationContentSettingsMap::ResetToDefault() { | |
158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
159 if (!profile_) | |
160 return; | |
161 PrefService* prefs = profile_->GetPrefs(); | |
162 prefs->ClearPref(prefs::kGeolocationContentSettings); | |
163 profile_->GetHostContentSettingsMap()->SetDefaultContentSetting( | |
164 CONTENT_SETTINGS_TYPE_GEOLOCATION, CONTENT_SETTING_DEFAULT); | |
165 } | |
166 | |
167 void GeolocationContentSettingsMap::NotifyObservers( | |
168 const ContentSettingsDetails& details) { | |
169 NotificationService::current()->Notify( | |
170 chrome::NOTIFICATION_GEOLOCATION_SETTINGS_CHANGED, | |
171 Source<GeolocationContentSettingsMap>(this), | |
172 Details<const ContentSettingsDetails>(&details)); | |
173 } | |
174 | |
175 void GeolocationContentSettingsMap::Observe( | |
176 int type, | |
177 const NotificationSource& source, | |
178 const NotificationDetails& details) { | |
179 if (type == chrome::NOTIFICATION_PREF_CHANGED) { | |
180 } else if (type == chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED) { | |
181 const ContentSettingsType& content_type = | |
182 Details<ContentSettingsDetails>(details).ptr()->type(); | |
183 if (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION) { | |
184 ContentSettingsDetails details(ContentSettingsPattern(), | |
185 ContentSettingsPattern(), | |
186 CONTENT_SETTINGS_TYPE_DEFAULT, | |
187 std::string()); | |
188 NotifyObservers(details); | |
189 } | |
190 } else if (chrome::NOTIFICATION_PROFILE_DESTROYED == type) { | |
191 UnregisterObservers(); | |
192 } else { | |
193 NOTREACHED(); | |
194 } | |
195 } | |
196 | |
197 void GeolocationContentSettingsMap::UnregisterObservers() { | |
198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
199 if (!profile_) | |
200 return; | |
201 prefs_registrar_.RemoveAll(); | |
202 notification_registrar_.Remove(this, chrome::NOTIFICATION_PROFILE_DESTROYED, | |
203 Source<Profile>(profile_)); | |
204 profile_ = NULL; | |
205 } | |
206 | |
207 GeolocationContentSettingsMap::~GeolocationContentSettingsMap() { | |
208 UnregisterObservers(); | |
209 } | |
210 | |
211 // static | |
212 void GeolocationContentSettingsMap::GetOneOriginSettingsFromDictionary( | |
213 const DictionaryValue* dictionary, | |
214 OneOriginSettings* one_origin_settings) { | |
215 for (DictionaryValue::key_iterator i(dictionary->begin_keys()); | |
216 i != dictionary->end_keys(); ++i) { | |
217 const std::string& target(*i); | |
218 int setting = 0; | |
219 bool found = dictionary->GetIntegerWithoutPathExpansion(target, &setting); | |
220 DCHECK(found); | |
221 GURL target_url(target); | |
222 // An empty URL has a special meaning (wildcard), so only accept invalid | |
223 // URLs if the original version was empty (avoids treating corrupted prefs | |
224 // as the wildcard entry; see http://crbug.com/39685) | |
225 if (target_url.is_valid() || target.empty()) | |
226 (*one_origin_settings)[target_url] = IntToContentSetting(setting); | |
227 } | |
228 } | |
OLD | NEW |