1 // Copyright (c) 2012 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/common/content_settings.h"
6 #include "chrome/common/render_messages.h"
7 #include "chrome/renderer/content_settings_observer.h"
8 #include "chrome/test/base/chrome_render_view_test.h"
9 #include "content/public/renderer/render_view.h"
10 #include "ipc/ipc_message_macros.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/WebKit/public/web/WebView.h"
14
15 using testing::_;
16 using testing::DeleteArg;
17
18 namespace {
19
20 class MockContentSettingsObserver : public ContentSettingsObserver {
21 public:
22 explicit MockContentSettingsObserver(content::RenderView* render_view);
23
24 virtual bool Send(IPC::Message* message);
25
26 MOCK_METHOD1(OnContentBlocked,
27 void(ContentSettingsType));
28
29 MOCK_METHOD5(OnAllowDOMStorage,
30 void(int, const GURL&, const GURL&, bool, IPC::Message*));
31 GURL image_url_;
32 std::string image_origin_;
33 };
34
MockContentSettingsObserver(content::RenderView * render_view)35 MockContentSettingsObserver::MockContentSettingsObserver(
36 content::RenderView* render_view)
37 : ContentSettingsObserver(render_view, NULL),
38 image_url_("http://www.foo.com/image.jpg"),
39 image_origin_("http://www.foo.com") {
40 }
41
Send(IPC::Message * message)42 bool MockContentSettingsObserver::Send(IPC::Message* message) {
43 IPC_BEGIN_MESSAGE_MAP(MockContentSettingsObserver, *message)
44 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_ContentBlocked, OnContentBlocked)
45 IPC_MESSAGE_HANDLER_DELAY_REPLY(ChromeViewHostMsg_AllowDOMStorage,
46 OnAllowDOMStorage)
47 IPC_MESSAGE_UNHANDLED(ADD_FAILURE())
48 IPC_END_MESSAGE_MAP()
49
50 // Our super class deletes the message.
51 return RenderViewObserver::Send(message);
52 }
53
54 } // namespace
55
TEST_F(ChromeRenderViewTest,DidBlockContentType)56 TEST_F(ChromeRenderViewTest, DidBlockContentType) {
57 MockContentSettingsObserver observer(view_);
58 EXPECT_CALL(observer,
59 OnContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES));
60 observer.DidBlockContentType(CONTENT_SETTINGS_TYPE_COOKIES);
61
62 // Blocking the same content type a second time shouldn't send a notification.
63 observer.DidBlockContentType(CONTENT_SETTINGS_TYPE_COOKIES);
64 ::testing::Mock::VerifyAndClearExpectations(&observer);
65 }
66
67 // Tests that multiple invokations of AllowDOMStorage result in a single IPC.
68 // Fails due to http://crbug.com/104300
TEST_F(ChromeRenderViewTest,DISABLED_AllowDOMStorage)69 TEST_F(ChromeRenderViewTest, DISABLED_AllowDOMStorage) {
70 // Load some HTML, so we have a valid security origin.
71 LoadHTML("<html></html>");
72 MockContentSettingsObserver observer(view_);
73 ON_CALL(observer,
74 OnAllowDOMStorage(_, _, _, _, _)).WillByDefault(DeleteArg<4>());
75 EXPECT_CALL(observer,
76 OnAllowDOMStorage(_, _, _, _, _));
77 observer.allowStorage(view_->GetWebView()->focusedFrame(), true);
78
79 // Accessing localStorage from the same origin again shouldn't result in a
80 // new IPC.
81 observer.allowStorage(view_->GetWebView()->focusedFrame(), true);
82 ::testing::Mock::VerifyAndClearExpectations(&observer);
83 }
84
85 // Regression test for http://crbug.com/35011
TEST_F(ChromeRenderViewTest,JSBlockSentAfterPageLoad)86 TEST_F(ChromeRenderViewTest, JSBlockSentAfterPageLoad) {
87 // 1. Load page with JS.
88 std::string html = "<html>"
89 "<head>"
90 "<script>document.createElement('div');</script>"
91 "</head>"
92 "<body>"
93 "</body>"
94 "</html>";
95 render_thread_->sink().ClearMessages();
96 LoadHTML(html.c_str());
97
98 // 2. Block JavaScript.
99 RendererContentSettingRules content_setting_rules;
100 ContentSettingsForOneType& script_setting_rules =
101 content_setting_rules.script_rules;
102 script_setting_rules.push_back(
103 ContentSettingPatternSource(ContentSettingsPattern::Wildcard(),
104 ContentSettingsPattern::Wildcard(),
105 CONTENT_SETTING_BLOCK,
106 std::string(),
107 false));
108 ContentSettingsObserver* observer = ContentSettingsObserver::Get(view_);
109 observer->SetContentSettingRules(&content_setting_rules);
110
111 // Make sure no pending messages are in the queue.
112 ProcessPendingMessages();
113 render_thread_->sink().ClearMessages();
114
115 // 3. Reload page.
116 std::string url_str = "data:text/html;charset=utf-8,";
117 url_str.append(html);
118 GURL url(url_str);
119 Reload(url);
120 ProcessPendingMessages();
121
122 // 4. Verify that the notification that javascript was blocked is sent after
123 // the navigation notifiction is sent.
124 int navigation_index = -1;
125 int block_index = -1;
126 for (size_t i = 0; i < render_thread_->sink().message_count(); ++i) {
127 const IPC::Message* msg = render_thread_->sink().GetMessageAt(i);
128 if (msg->type() == GetNavigationIPCType())
129 navigation_index = i;
130 if (msg->type() == ChromeViewHostMsg_ContentBlocked::ID)
131 block_index = i;
132 }
133 EXPECT_NE(-1, navigation_index);
134 EXPECT_NE(-1, block_index);
135 EXPECT_LT(navigation_index, block_index);
136 }
137
TEST_F(ChromeRenderViewTest,PluginsTemporarilyAllowed)138 TEST_F(ChromeRenderViewTest, PluginsTemporarilyAllowed) {
139 // Load some HTML.
140 LoadHTML("<html>Foo</html>");
141
142 std::string foo_plugin = "foo";
143 std::string bar_plugin = "bar";
144
145 ContentSettingsObserver* observer = ContentSettingsObserver::Get(view_);
146 EXPECT_FALSE(observer->IsPluginTemporarilyAllowed(foo_plugin));
147
148 // Temporarily allow the "foo" plugin.
149 OnMessageReceived(ChromeViewMsg_LoadBlockedPlugins(MSG_ROUTING_NONE,
150 foo_plugin));
151 EXPECT_TRUE(observer->IsPluginTemporarilyAllowed(foo_plugin));
152 EXPECT_FALSE(observer->IsPluginTemporarilyAllowed(bar_plugin));
153
154 // Simulate a navigation within the page.
155 DidNavigateWithinPage(GetMainFrame(), true);
156 EXPECT_TRUE(observer->IsPluginTemporarilyAllowed(foo_plugin));
157 EXPECT_FALSE(observer->IsPluginTemporarilyAllowed(bar_plugin));
158
159 // Navigate to a different page.
160 LoadHTML("<html>Bar</html>");
161 EXPECT_FALSE(observer->IsPluginTemporarilyAllowed(foo_plugin));
162 EXPECT_FALSE(observer->IsPluginTemporarilyAllowed(bar_plugin));
163
164 // Temporarily allow all plugins.
165 OnMessageReceived(ChromeViewMsg_LoadBlockedPlugins(MSG_ROUTING_NONE,
166 std::string()));
167 EXPECT_TRUE(observer->IsPluginTemporarilyAllowed(foo_plugin));
168 EXPECT_TRUE(observer->IsPluginTemporarilyAllowed(bar_plugin));
169 }
170
TEST_F(ChromeRenderViewTest,ImagesBlockedByDefault)171 TEST_F(ChromeRenderViewTest, ImagesBlockedByDefault) {
172 MockContentSettingsObserver mock_observer(view_);
173
174 // Load some HTML.
175 LoadHTML("<html>Foo</html>");
176
177 // Set the default image blocking setting.
178 RendererContentSettingRules content_setting_rules;
179 ContentSettingsForOneType& image_setting_rules =
180 content_setting_rules.image_rules;
181 image_setting_rules.push_back(
182 ContentSettingPatternSource(ContentSettingsPattern::Wildcard(),
183 ContentSettingsPattern::Wildcard(),
184 CONTENT_SETTING_BLOCK,
185 std::string(),
186 false));
187
188 ContentSettingsObserver* observer = ContentSettingsObserver::Get(view_);
189 observer->SetContentSettingRules(&content_setting_rules);
190 EXPECT_CALL(mock_observer,
191 OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES));
192 EXPECT_FALSE(observer->allowImage(GetMainFrame(),
193 true, mock_observer.image_url_));
194 ::testing::Mock::VerifyAndClearExpectations(&observer);
195
196 // Create an exception which allows the image.
197 image_setting_rules.insert(
198 image_setting_rules.begin(),
199 ContentSettingPatternSource(
200 ContentSettingsPattern::Wildcard(),
201 ContentSettingsPattern::FromString(mock_observer.image_origin_),
202 CONTENT_SETTING_ALLOW,
203 std::string(),
204 false));
205
206 EXPECT_CALL(
207 mock_observer,
208 OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES)).Times(0);
209 EXPECT_TRUE(observer->allowImage(GetMainFrame(), true,
210 mock_observer.image_url_));
211 ::testing::Mock::VerifyAndClearExpectations(&observer);
212 }
213
TEST_F(ChromeRenderViewTest,ImagesAllowedByDefault)214 TEST_F(ChromeRenderViewTest, ImagesAllowedByDefault) {
215 MockContentSettingsObserver mock_observer(view_);
216
217 // Load some HTML.
218 LoadHTML("<html>Foo</html>");
219
220 // Set the default image blocking setting.
221 RendererContentSettingRules content_setting_rules;
222 ContentSettingsForOneType& image_setting_rules =
223 content_setting_rules.image_rules;
224 image_setting_rules.push_back(
225 ContentSettingPatternSource(ContentSettingsPattern::Wildcard(),
226 ContentSettingsPattern::Wildcard(),
227 CONTENT_SETTING_ALLOW,
228 std::string(),
229 false));
230
231 ContentSettingsObserver* observer = ContentSettingsObserver::Get(view_);
232 observer->SetContentSettingRules(&content_setting_rules);
233 EXPECT_CALL(
234 mock_observer,
235 OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES)).Times(0);
236 EXPECT_TRUE(observer->allowImage(GetMainFrame(), true,
237 mock_observer.image_url_));
238 ::testing::Mock::VerifyAndClearExpectations(&observer);
239
240 // Create an exception which blocks the image.
241 image_setting_rules.insert(
242 image_setting_rules.begin(),
243 ContentSettingPatternSource(
244 ContentSettingsPattern::Wildcard(),
245 ContentSettingsPattern::FromString(mock_observer.image_origin_),
246 CONTENT_SETTING_BLOCK,
247 std::string(),
248 false));
249 EXPECT_CALL(mock_observer,
250 OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES));
251 EXPECT_FALSE(observer->allowImage(GetMainFrame(),
252 true, mock_observer.image_url_));
253 ::testing::Mock::VerifyAndClearExpectations(&observer);
254 }
255
TEST_F(ChromeRenderViewTest,ContentSettingsBlockScripts)256 TEST_F(ChromeRenderViewTest, ContentSettingsBlockScripts) {
257 // Set the content settings for scripts.
258 RendererContentSettingRules content_setting_rules;
259 ContentSettingsForOneType& script_setting_rules =
260 content_setting_rules.script_rules;
261 script_setting_rules.push_back(
262 ContentSettingPatternSource(ContentSettingsPattern::Wildcard(),
263 ContentSettingsPattern::Wildcard(),
264 CONTENT_SETTING_BLOCK,
265 std::string(),
266 false));
267
268 ContentSettingsObserver* observer = ContentSettingsObserver::Get(view_);
269 observer->SetContentSettingRules(&content_setting_rules);
270
271 // Load a page which contains a script.
272 std::string html = "<html>"
273 "<head>"
274 "<script src='data:foo'></script>"
275 "</head>"
276 "<body>"
277 "</body>"
278 "</html>";
279 LoadHTML(html.c_str());
280
281 // Verify that the script was blocked.
282 bool was_blocked = false;
283 for (size_t i = 0; i < render_thread_->sink().message_count(); ++i) {
284 const IPC::Message* msg = render_thread_->sink().GetMessageAt(i);
285 if (msg->type() == ChromeViewHostMsg_ContentBlocked::ID)
286 was_blocked = true;
287 }
288 EXPECT_TRUE(was_blocked);
289 }
290
TEST_F(ChromeRenderViewTest,ContentSettingsAllowScripts)291 TEST_F(ChromeRenderViewTest, ContentSettingsAllowScripts) {
292 // Set the content settings for scripts.
293 RendererContentSettingRules content_setting_rules;
294 ContentSettingsForOneType& script_setting_rules =
295 content_setting_rules.script_rules;
296 script_setting_rules.push_back(
297 ContentSettingPatternSource(ContentSettingsPattern::Wildcard(),
298 ContentSettingsPattern::Wildcard(),
299 CONTENT_SETTING_ALLOW,
300 std::string(),
301 false));
302
303 ContentSettingsObserver* observer = ContentSettingsObserver::Get(view_);
304 observer->SetContentSettingRules(&content_setting_rules);
305
306 // Load a page which contains a script.
307 std::string html = "<html>"
308 "<head>"
309 "<script src='data:foo'></script>"
310 "</head>"
311 "<body>"
312 "</body>"
313 "</html>";
314 LoadHTML(html.c_str());
315
316 // Verify that the script was not blocked.
317 bool was_blocked = false;
318 for (size_t i = 0; i < render_thread_->sink().message_count(); ++i) {
319 const IPC::Message* msg = render_thread_->sink().GetMessageAt(i);
320 if (msg->type() == ChromeViewHostMsg_ContentBlocked::ID)
321 was_blocked = true;
322 }
323 EXPECT_FALSE(was_blocked);
324 }
325
TEST_F(ChromeRenderViewTest,ContentSettingsInterstitialPages)326 TEST_F(ChromeRenderViewTest, ContentSettingsInterstitialPages) {
327 MockContentSettingsObserver mock_observer(view_);
328 // Block scripts.
329 RendererContentSettingRules content_setting_rules;
330 ContentSettingsForOneType& script_setting_rules =
331 content_setting_rules.script_rules;
332 script_setting_rules.push_back(
333 ContentSettingPatternSource(ContentSettingsPattern::Wildcard(),
334 ContentSettingsPattern::Wildcard(),
335 CONTENT_SETTING_BLOCK,
336 std::string(),
337 false));
338 // Block images.
339 ContentSettingsForOneType& image_setting_rules =
340 content_setting_rules.image_rules;
341 image_setting_rules.push_back(
342 ContentSettingPatternSource(ContentSettingsPattern::Wildcard(),
343 ContentSettingsPattern::Wildcard(),
344 CONTENT_SETTING_BLOCK,
345 std::string(),
346 false));
347
348 ContentSettingsObserver* observer = ContentSettingsObserver::Get(view_);
349 observer->SetContentSettingRules(&content_setting_rules);
350 observer->OnSetAsInterstitial();
351
352 // Load a page which contains a script.
353 std::string html = "<html>"
354 "<head>"
355 "<script src='data:foo'></script>"
356 "</head>"
357 "<body>"
358 "</body>"
359 "</html>";
360 LoadHTML(html.c_str());
361
362 // Verify that the script was allowed.
363 bool was_blocked = false;
364 for (size_t i = 0; i < render_thread_->sink().message_count(); ++i) {
365 const IPC::Message* msg = render_thread_->sink().GetMessageAt(i);
366 if (msg->type() == ChromeViewHostMsg_ContentBlocked::ID)
367 was_blocked = true;
368 }
369 EXPECT_FALSE(was_blocked);
370
371 // Verify that images are allowed.
372 EXPECT_CALL(
373 mock_observer,
374 OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES)).Times(0);
375 EXPECT_TRUE(observer->allowImage(GetMainFrame(), true,
376 mock_observer.image_url_));
377 ::testing::Mock::VerifyAndClearExpectations(&observer);
378 }
379