1// Copyright (c) 2010 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 "chrome/browser/content_setting_bubble_model.h"
6
7#include "base/auto_reset.h"
8#include "base/command_line.h"
9#include "chrome/browser/content_settings/host_content_settings_map.h"
10#include "chrome/browser/profiles/profile.h"
11#include "chrome/browser/geolocation/geolocation_content_settings_map.h"
12#include "chrome/common/chrome_switches.h"
13#include "chrome/test/testing_profile.h"
14#include "content/browser/browser_thread.h"
15#include "content/browser/renderer_host/test_render_view_host.h"
16#include "content/browser/tab_contents/test_tab_contents.h"
17#include "testing/gtest/include/gtest/gtest.h"
18
19class ContentSettingBubbleModelTest : public RenderViewHostTestHarness {
20 protected:
21  ContentSettingBubbleModelTest()
22      : ui_thread_(BrowserThread::UI, MessageLoop::current()) {
23  }
24
25  void CheckGeolocationBubble(size_t expected_domains,
26                              bool expect_clear_link,
27                              bool expect_reload_hint) {
28    scoped_ptr<ContentSettingBubbleModel> content_setting_bubble_model(
29        ContentSettingBubbleModel::CreateContentSettingBubbleModel(
30           contents(), profile_.get(), CONTENT_SETTINGS_TYPE_GEOLOCATION));
31    const ContentSettingBubbleModel::BubbleContent& bubble_content =
32        content_setting_bubble_model->bubble_content();
33    EXPECT_TRUE(bubble_content.title.empty());
34    EXPECT_TRUE(bubble_content.radio_group.radio_items.empty());
35    EXPECT_TRUE(bubble_content.popup_items.empty());
36    EXPECT_EQ(expected_domains, bubble_content.domain_lists.size());
37    EXPECT_NE(expect_clear_link || expect_reload_hint,
38              bubble_content.custom_link.empty());
39    EXPECT_EQ(expect_clear_link, bubble_content.custom_link_enabled);
40    EXPECT_FALSE(bubble_content.manage_link.empty());
41  }
42
43  BrowserThread ui_thread_;
44};
45
46TEST_F(ContentSettingBubbleModelTest, ImageRadios) {
47  TabSpecificContentSettings* content_settings =
48      contents()->GetTabSpecificContentSettings();
49  content_settings->OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES,
50                                     std::string());
51
52  scoped_ptr<ContentSettingBubbleModel> content_setting_bubble_model(
53      ContentSettingBubbleModel::CreateContentSettingBubbleModel(
54         contents(), profile_.get(), CONTENT_SETTINGS_TYPE_IMAGES));
55  const ContentSettingBubbleModel::BubbleContent& bubble_content =
56      content_setting_bubble_model->bubble_content();
57  EXPECT_FALSE(bubble_content.title.empty());
58  EXPECT_EQ(2U, bubble_content.radio_group.radio_items.size());
59  EXPECT_EQ(0, bubble_content.radio_group.default_item);
60  EXPECT_TRUE(bubble_content.custom_link.empty());
61  EXPECT_FALSE(bubble_content.manage_link.empty());
62}
63
64TEST_F(ContentSettingBubbleModelTest, Cookies) {
65  TabSpecificContentSettings* content_settings =
66      contents()->GetTabSpecificContentSettings();
67  content_settings->OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES,
68                                     std::string());
69
70  scoped_ptr<ContentSettingBubbleModel> content_setting_bubble_model(
71      ContentSettingBubbleModel::CreateContentSettingBubbleModel(
72         contents(), profile_.get(), CONTENT_SETTINGS_TYPE_COOKIES));
73  const ContentSettingBubbleModel::BubbleContent& bubble_content =
74      content_setting_bubble_model->bubble_content();
75  EXPECT_FALSE(bubble_content.title.empty());
76  EXPECT_FALSE(bubble_content.radio_group.radio_items.empty());
77  EXPECT_FALSE(bubble_content.custom_link.empty());
78  EXPECT_TRUE(bubble_content.custom_link_enabled);
79  EXPECT_FALSE(bubble_content.manage_link.empty());
80}
81
82TEST_F(ContentSettingBubbleModelTest, Plugins) {
83  TabSpecificContentSettings* content_settings =
84      contents()->GetTabSpecificContentSettings();
85  content_settings->OnContentBlocked(CONTENT_SETTINGS_TYPE_PLUGINS,
86                                     std::string());
87
88  scoped_ptr<ContentSettingBubbleModel> content_setting_bubble_model(
89      ContentSettingBubbleModel::CreateContentSettingBubbleModel(
90         contents(), profile_.get(), CONTENT_SETTINGS_TYPE_PLUGINS));
91  const ContentSettingBubbleModel::BubbleContent& bubble_content =
92      content_setting_bubble_model->bubble_content();
93  EXPECT_FALSE(bubble_content.title.empty());
94  EXPECT_EQ(2U, bubble_content.radio_group.radio_items.size());
95  EXPECT_FALSE(bubble_content.custom_link.empty());
96  EXPECT_TRUE(bubble_content.custom_link_enabled);
97  EXPECT_FALSE(bubble_content.manage_link.empty());
98}
99
100TEST_F(ContentSettingBubbleModelTest, MultiplePlugins) {
101  CommandLine* cmd = CommandLine::ForCurrentProcess();
102  AutoReset<CommandLine> auto_reset(cmd, *cmd);
103  cmd->AppendSwitch(switches::kEnableResourceContentSettings);
104  cmd->AppendSwitch(switches::kEnableClickToPlay);
105
106  HostContentSettingsMap* map = profile_->GetHostContentSettingsMap();
107  std::string fooPlugin = "foo";
108  std::string barPlugin = "bar";
109  GURL url = contents()->GetURL();
110  map->AddExceptionForURL(url,
111                          CONTENT_SETTINGS_TYPE_PLUGINS,
112                          fooPlugin,
113                          CONTENT_SETTING_ALLOW);
114  map->AddExceptionForURL(url,
115                          CONTENT_SETTINGS_TYPE_PLUGINS,
116                          barPlugin,
117                          CONTENT_SETTING_ASK);
118
119  TabSpecificContentSettings* content_settings =
120      contents()->GetTabSpecificContentSettings();
121  content_settings->OnContentBlocked(CONTENT_SETTINGS_TYPE_PLUGINS,
122                                     fooPlugin);
123  content_settings->OnContentBlocked(CONTENT_SETTINGS_TYPE_PLUGINS,
124                                     barPlugin);
125
126  scoped_ptr<ContentSettingBubbleModel> content_setting_bubble_model(
127      ContentSettingBubbleModel::CreateContentSettingBubbleModel(
128         contents(), profile_.get(), CONTENT_SETTINGS_TYPE_PLUGINS));
129  const ContentSettingBubbleModel::BubbleContent& bubble_content =
130      content_setting_bubble_model->bubble_content();
131  EXPECT_EQ(2U, bubble_content.radio_group.radio_items.size());
132  EXPECT_EQ(1, bubble_content.radio_group.default_item);
133
134  content_setting_bubble_model->OnRadioClicked(0);
135  // Nothing should have changed.
136  EXPECT_EQ(CONTENT_SETTING_ALLOW,
137            map->GetContentSetting(url,
138                                   CONTENT_SETTINGS_TYPE_PLUGINS,
139                                   fooPlugin));
140  EXPECT_EQ(CONTENT_SETTING_ASK,
141            map->GetContentSetting(url,
142                                   CONTENT_SETTINGS_TYPE_PLUGINS,
143                                   barPlugin));
144
145  content_setting_bubble_model.reset();
146  // Both plug-ins should be click-to-play now.
147  EXPECT_EQ(CONTENT_SETTING_ALLOW,
148            map->GetContentSetting(url,
149                                   CONTENT_SETTINGS_TYPE_PLUGINS,
150                                   fooPlugin));
151  EXPECT_EQ(CONTENT_SETTING_ALLOW,
152            map->GetContentSetting(url,
153                                   CONTENT_SETTINGS_TYPE_PLUGINS,
154                                   barPlugin));
155}
156
157TEST_F(ContentSettingBubbleModelTest, Geolocation) {
158  const GURL page_url("http://toplevel.example/");
159  const GURL frame1_url("http://host1.example/");
160  const GURL frame2_url("http://host2.example:999/");
161
162  NavigateAndCommit(page_url);
163  TabSpecificContentSettings* content_settings =
164      contents()->GetTabSpecificContentSettings();
165
166  // One permitted frame, but not in the content map: requires reload.
167  content_settings->OnGeolocationPermissionSet(frame1_url, true);
168  CheckGeolocationBubble(1, false, true);
169
170  // Add it to the content map, should now have a clear link.
171  GeolocationContentSettingsMap* setting_map =
172      profile_->GetGeolocationContentSettingsMap();
173  setting_map->SetContentSetting(frame1_url, page_url, CONTENT_SETTING_ALLOW);
174  CheckGeolocationBubble(1, true, false);
175
176  // Change the default to allow: no message needed.
177  setting_map->SetDefaultContentSetting(CONTENT_SETTING_ALLOW);
178  CheckGeolocationBubble(1, false, false);
179
180  // Second frame denied, but not stored in the content map: requires reload.
181  content_settings->OnGeolocationPermissionSet(frame2_url, false);
182  CheckGeolocationBubble(2, false, true);
183
184  // Change the default to block: offer a clear link for the persisted frame 1.
185  setting_map->SetDefaultContentSetting(CONTENT_SETTING_BLOCK);
186  CheckGeolocationBubble(2, true, false);
187}
188
189TEST_F(ContentSettingBubbleModelTest, FileURL) {
190  std::string file_url("file:///tmp/test.html");
191  NavigateAndCommit(GURL(file_url));
192  scoped_ptr<ContentSettingBubbleModel> content_setting_bubble_model(
193      ContentSettingBubbleModel::CreateContentSettingBubbleModel(
194         contents(), profile_.get(), CONTENT_SETTINGS_TYPE_IMAGES));
195  std::string title =
196      content_setting_bubble_model->bubble_content().radio_group.radio_items[0];
197  ASSERT_NE(std::string::npos, title.find(file_url));
198}
199