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#include "base/message_loop.h"
6#include "chrome/browser/content_settings/content_settings_details.h"
7#include "chrome/browser/geolocation/geolocation_content_settings_map.h"
8#include "chrome/browser/prefs/pref_service.h"
9#include "chrome/browser/prefs/scoped_user_pref_update.h"
10#include "chrome/common/pref_names.h"
11#include "chrome/test/testing_profile.h"
12#include "content/browser/browser_thread.h"
13#include "content/common/notification_registrar.h"
14#include "content/common/notification_service.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17
18namespace {
19
20class StubSettingsObserver : public NotificationObserver {
21 public:
22  StubSettingsObserver() : last_notifier(NULL), counter(0) {
23    registrar_.Add(this, NotificationType::GEOLOCATION_SETTINGS_CHANGED,
24                   NotificationService::AllSources());
25  }
26
27  virtual void Observe(NotificationType type,
28                       const NotificationSource& source,
29                       const NotificationDetails& details) {
30    ++counter;
31    Source<GeolocationContentSettingsMap> content_settings(source);
32    Details<ContentSettingsDetails> settings_details(details);
33    last_notifier = content_settings.ptr();
34    last_pattern = settings_details.ptr()->pattern();
35    last_update_all = settings_details.ptr()->update_all();
36    last_update_all_types = settings_details.ptr()->update_all_types();
37    last_type = settings_details.ptr()->type();
38    // This checks that calling a Get function from an observer doesn't
39    // deadlock.
40    last_notifier->GetContentSetting(GURL("http://random-hostname.com/"),
41                                     GURL("http://foo.random-hostname.com/"));
42  }
43
44  GeolocationContentSettingsMap* last_notifier;
45  ContentSettingsPattern last_pattern;
46  bool last_update_all;
47  bool last_update_all_types;
48  int counter;
49  ContentSettingsType last_type;
50
51 private:
52  NotificationRegistrar registrar_;
53};
54
55class GeolocationContentSettingsMapTests : public testing::Test {
56 public:
57  GeolocationContentSettingsMapTests()
58    : ui_thread_(BrowserThread::UI, &message_loop_) {
59  }
60
61 protected:
62  MessageLoop message_loop_;
63  BrowserThread ui_thread_;
64};
65
66TEST_F(GeolocationContentSettingsMapTests, DefaultValues) {
67  TestingProfile profile;
68  GeolocationContentSettingsMap* map =
69      profile.GetGeolocationContentSettingsMap();
70
71  // Check setting defaults.
72  EXPECT_EQ(CONTENT_SETTING_ASK, map->GetDefaultContentSetting());
73  map->SetDefaultContentSetting(CONTENT_SETTING_BLOCK);
74  EXPECT_EQ(CONTENT_SETTING_BLOCK, map->GetDefaultContentSetting());
75}
76
77TEST_F(GeolocationContentSettingsMapTests, Embedder) {
78  TestingProfile profile;
79  GeolocationContentSettingsMap* map =
80      profile.GetGeolocationContentSettingsMap();
81  GURL top_level("http://www.toplevel0.com/foo/bar");
82  EXPECT_EQ(CONTENT_SETTING_ASK, map->GetContentSetting(top_level, top_level));
83  // Now set the permission for requester_0.
84  map->SetContentSetting(top_level, top_level, CONTENT_SETTING_ALLOW);
85  EXPECT_EQ(CONTENT_SETTING_ALLOW,
86            map->GetContentSetting(top_level, top_level));
87
88  GURL requester_0("http://www.frame0.com/foo/bar");
89  EXPECT_EQ(CONTENT_SETTING_ASK,
90            map->GetContentSetting(requester_0, top_level));
91  // Now set the permission for only requester_1.
92  map->SetContentSetting(requester_0, top_level, CONTENT_SETTING_ALLOW);
93  EXPECT_EQ(CONTENT_SETTING_ALLOW,
94            map->GetContentSetting(top_level, top_level));
95  EXPECT_EQ(CONTENT_SETTING_ALLOW,
96            map->GetContentSetting(requester_0, top_level));
97  // Block only requester_1.
98  map->SetContentSetting(requester_0, top_level, CONTENT_SETTING_BLOCK);
99  EXPECT_EQ(CONTENT_SETTING_BLOCK,
100            map->GetContentSetting(requester_0, top_level));
101  EXPECT_EQ(CONTENT_SETTING_ALLOW,
102            map->GetContentSetting(top_level, top_level));
103}
104
105TEST_F(GeolocationContentSettingsMapTests, MultipleEmbeddersAndOrigins) {
106  TestingProfile profile;
107  GeolocationContentSettingsMap* map =
108      profile.GetGeolocationContentSettingsMap();
109  GURL requester_0("http://www.iframe0.com/foo/bar");
110  GURL requester_1("http://www.iframe1.co.uk/bar/foo");
111  GURL embedder_0("http://www.toplevel0.com/foo/bar");
112  EXPECT_EQ(CONTENT_SETTING_ASK,
113            map->GetContentSetting(requester_0, embedder_0));
114  EXPECT_EQ(CONTENT_SETTING_ASK,
115            map->GetContentSetting(requester_1, embedder_0));
116  // Now set the permission for only one origin.
117  map->SetContentSetting(requester_0, embedder_0, CONTENT_SETTING_ALLOW);
118  EXPECT_EQ(CONTENT_SETTING_ALLOW,
119            map->GetContentSetting(requester_0, embedder_0));
120  EXPECT_EQ(CONTENT_SETTING_ASK,
121            map->GetContentSetting(requester_1, embedder_0));
122  // Set the permission for the other origin.
123  map->SetContentSetting(requester_1, embedder_0, CONTENT_SETTING_ALLOW);
124  EXPECT_EQ(CONTENT_SETTING_ALLOW,
125            map->GetContentSetting(requester_1, embedder_0));
126  // Check they're not allowed on a different embedder.
127  GURL embedder_1("http://www.toplevel1.com/foo/bar");
128  EXPECT_EQ(CONTENT_SETTING_ASK,
129            map->GetContentSetting(requester_0, embedder_1));
130  EXPECT_EQ(CONTENT_SETTING_ASK,
131            map->GetContentSetting(requester_1, embedder_1));
132  // Check all settings are valid.
133  GeolocationContentSettingsMap::AllOriginsSettings content_settings(
134      map->GetAllOriginsSettings());
135  EXPECT_EQ(0U, content_settings.count(requester_0));
136  EXPECT_EQ(1U, content_settings.count(requester_0.GetOrigin()));
137  GeolocationContentSettingsMap::OneOriginSettings one_origin_settings(
138      content_settings[requester_0.GetOrigin()]);
139  EXPECT_EQ(CONTENT_SETTING_ALLOW, one_origin_settings[embedder_0.GetOrigin()]);
140
141  EXPECT_EQ(0U, content_settings.count(requester_1));
142  EXPECT_EQ(1U, content_settings.count(requester_1.GetOrigin()));
143  one_origin_settings = content_settings[requester_1.GetOrigin()];
144  EXPECT_EQ(CONTENT_SETTING_ALLOW, one_origin_settings[embedder_0.GetOrigin()]);
145  // Block requester_1 on the first embedder and add it to the second.
146  map->SetContentSetting(requester_1, embedder_0, CONTENT_SETTING_BLOCK);
147  map->SetContentSetting(requester_1, embedder_1, CONTENT_SETTING_ALLOW);
148  EXPECT_EQ(CONTENT_SETTING_BLOCK,
149            map->GetContentSetting(requester_1, embedder_0));
150  EXPECT_EQ(CONTENT_SETTING_ALLOW,
151            map->GetContentSetting(requester_1, embedder_1));
152}
153
154TEST_F(GeolocationContentSettingsMapTests, SetContentSettingDefault) {
155  TestingProfile profile;
156  GeolocationContentSettingsMap* map =
157      profile.GetGeolocationContentSettingsMap();
158  GURL top_level("http://www.toplevel0.com/foo/bar");
159  map->SetContentSetting(top_level, top_level, CONTENT_SETTING_ALLOW);
160  EXPECT_EQ(CONTENT_SETTING_ALLOW,
161            map->GetContentSetting(top_level, top_level));
162  // Set to CONTENT_SETTING_DEFAULT and check the actual value has changed.
163  map->SetContentSetting(top_level, top_level, CONTENT_SETTING_DEFAULT);
164  EXPECT_EQ(CONTENT_SETTING_ASK, map->GetContentSetting(top_level, top_level));
165}
166
167TEST_F(GeolocationContentSettingsMapTests, Reset) {
168  TestingProfile profile;
169  GeolocationContentSettingsMap* map =
170      profile.GetGeolocationContentSettingsMap();
171  GURL requester_0("http://www.iframe0.com/foo/bar");
172  GURL embedder_0("http://www.toplevel0.com/foo/bar");
173  map->SetContentSetting(requester_0, embedder_0, CONTENT_SETTING_ALLOW);
174  EXPECT_EQ(CONTENT_SETTING_ALLOW,
175            map->GetContentSetting(requester_0, embedder_0));
176  GeolocationContentSettingsMap::AllOriginsSettings content_settings(
177      map->GetAllOriginsSettings());
178  EXPECT_EQ(1U, content_settings.size());
179
180  // Set to CONTENT_SETTING_DEFAULT and check the actual value has changed.
181  map->SetContentSetting(requester_0, embedder_0, CONTENT_SETTING_DEFAULT);
182  EXPECT_EQ(CONTENT_SETTING_ASK,
183            map->GetContentSetting(requester_0, embedder_0));
184  content_settings = map->GetAllOriginsSettings();
185  EXPECT_TRUE(content_settings.empty());
186}
187
188TEST_F(GeolocationContentSettingsMapTests, ClearsWhenSettingBackToDefault) {
189  TestingProfile profile;
190  GeolocationContentSettingsMap* map =
191      profile.GetGeolocationContentSettingsMap();
192  GURL requester_0("http://www.iframe0.com/foo/bar");
193  GURL requester_1("http://www.iframe1.com/foo/bar");
194  GURL embedder_0("http://www.toplevel0.com/foo/bar");
195  map->SetContentSetting(requester_0, embedder_0, CONTENT_SETTING_ALLOW);
196  EXPECT_EQ(CONTENT_SETTING_ALLOW,
197            map->GetContentSetting(requester_0, embedder_0));
198  GeolocationContentSettingsMap::AllOriginsSettings content_settings(
199      map->GetAllOriginsSettings());
200  EXPECT_EQ(1U, content_settings.size());
201
202  map->SetContentSetting(requester_1, embedder_0, CONTENT_SETTING_ALLOW);
203  EXPECT_EQ(CONTENT_SETTING_ALLOW,
204            map->GetContentSetting(requester_1, embedder_0));
205  content_settings = map->GetAllOriginsSettings();
206  EXPECT_EQ(2U, content_settings.size());
207  EXPECT_EQ(1U, content_settings[requester_0.GetOrigin()].size());
208  EXPECT_EQ(1U, content_settings[requester_1.GetOrigin()].size());
209
210  // Set to default.
211  map->SetContentSetting(requester_0, embedder_0, CONTENT_SETTING_DEFAULT);
212  content_settings = map->GetAllOriginsSettings();
213  EXPECT_EQ(1U, content_settings.size());
214
215  map->SetContentSetting(requester_1, embedder_0, CONTENT_SETTING_DEFAULT);
216  content_settings = map->GetAllOriginsSettings();
217  EXPECT_TRUE(content_settings.empty());
218}
219
220TEST_F(GeolocationContentSettingsMapTests, WildCardForEmptyEmbedder) {
221  TestingProfile profile;
222  GeolocationContentSettingsMap* map =
223      profile.GetGeolocationContentSettingsMap();
224  GURL requester_0("http://www.iframe0.com/foo/bar");
225  GURL embedder_0("http://www.toplevel0.com/foo/bar");
226  GURL embedder_1("http://www.toplevel1.com/foo/bar");
227  GURL empty_url;
228  map->SetContentSetting(requester_0, embedder_0, CONTENT_SETTING_BLOCK);
229  map->SetContentSetting(requester_0, empty_url, CONTENT_SETTING_ALLOW);
230  EXPECT_EQ(CONTENT_SETTING_BLOCK,
231            map->GetContentSetting(requester_0, embedder_0));
232  EXPECT_EQ(CONTENT_SETTING_ALLOW,
233            map->GetContentSetting(requester_0, embedder_1));
234  EXPECT_EQ(CONTENT_SETTING_ASK,
235            map->GetContentSetting(requester_0, requester_0));
236
237  // Change the wildcard behavior.
238  map->SetContentSetting(requester_0, embedder_0, CONTENT_SETTING_ALLOW);
239  map->SetContentSetting(requester_0, empty_url, CONTENT_SETTING_BLOCK);
240  map->SetDefaultContentSetting(CONTENT_SETTING_ALLOW);
241  EXPECT_EQ(CONTENT_SETTING_ALLOW,
242            map->GetContentSetting(requester_0, embedder_0));
243  EXPECT_EQ(CONTENT_SETTING_BLOCK,
244            map->GetContentSetting(requester_0, embedder_1));
245  EXPECT_EQ(CONTENT_SETTING_ALLOW,
246            map->GetContentSetting(requester_0, requester_0));
247}
248
249TEST_F(GeolocationContentSettingsMapTests, IgnoreInvalidURLsInPrefs) {
250  TestingProfile profile;
251  {
252    DictionaryPrefUpdate update(profile.GetPrefs(),
253                                prefs::kGeolocationContentSettings);
254    DictionaryValue* all_settings_dictionary = update.Get();
255    // For simplicity, use the overloads that do path expansion. As '.' is the
256    // path separator, we can't have dotted hostnames (which is fine).
257    all_settings_dictionary->SetInteger("http://a/.http://b/",
258                                        CONTENT_SETTING_ALLOW);
259    all_settings_dictionary->SetInteger("bad_requester.http://b/",
260                                        CONTENT_SETTING_ALLOW);
261    all_settings_dictionary->SetInteger("http://a/.bad-embedder",
262                                        CONTENT_SETTING_ALLOW);
263  }
264
265  GeolocationContentSettingsMap* map =
266      profile.GetGeolocationContentSettingsMap();
267  EXPECT_EQ(CONTENT_SETTING_ASK, map->GetDefaultContentSetting());
268
269  // Check the valid entry was read OK.
270  EXPECT_EQ(CONTENT_SETTING_ALLOW,
271            map->GetContentSetting(GURL("http://a/"), GURL("http://b/")));
272  // But everything else should be according to the default.
273  EXPECT_EQ(CONTENT_SETTING_ASK,
274            map->GetContentSetting(GURL("http://a/"),
275            GURL("http://bad-embedder")));
276  EXPECT_EQ(CONTENT_SETTING_ASK,
277            map->GetContentSetting(GURL("http://a/"),
278            GURL("http://example.com")));
279  EXPECT_EQ(CONTENT_SETTING_ASK,
280            map->GetContentSetting(GURL("http://bad_requester/"),
281            GURL("http://b/")));
282}
283
284TEST_F(GeolocationContentSettingsMapTests, Observe) {
285  TestingProfile profile;
286  GeolocationContentSettingsMap* map =
287      profile.GetGeolocationContentSettingsMap();
288  StubSettingsObserver observer;
289
290  EXPECT_EQ(CONTENT_SETTING_ASK, map->GetDefaultContentSetting());
291
292  // Test if a CONTENT_SETTING_CHANGE notification is sent after the geolocation
293  // default content setting was changed through calling the
294  // SetDefaultContentSetting method.
295  map->SetDefaultContentSetting(CONTENT_SETTING_BLOCK);
296  EXPECT_EQ(map, observer.last_notifier);
297  EXPECT_EQ(CONTENT_SETTINGS_TYPE_DEFAULT, observer.last_type);
298  EXPECT_EQ(1, observer.counter);
299
300
301  // Test if a CONTENT_SETTING_CHANGE notification is sent after the preference
302  // GeolocationDefaultContentSetting was changed.
303  PrefService* prefs = profile.GetPrefs();
304  prefs->SetInteger(prefs::kGeolocationDefaultContentSetting,
305                    CONTENT_SETTING_ALLOW);
306  EXPECT_EQ(2, observer.counter);
307  EXPECT_EQ(map, observer.last_notifier);
308  EXPECT_EQ(CONTENT_SETTINGS_TYPE_DEFAULT, observer.last_type);
309  EXPECT_EQ(CONTENT_SETTING_ALLOW, map->GetDefaultContentSetting());
310}
311
312}  // namespace
313