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.
5 #include "chrome/renderer/chrome_content_renderer_client.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/renderer/searchbox/search_bouncer.h"
11 #include "content/public/common/webplugininfo.h"
12 #include "testing/gtest/include/gtest/gtest.h"
15 #if defined(ENABLE_EXTENSIONS)
16 #include "extensions/common/extension.h"
17 #include "extensions/common/extension_builder.h"
18 #include "extensions/common/manifest_constants.h"
21 #if !defined(DISABLE_NACL)
22 #include "third_party/WebKit/public/platform/WebString.h"
23 #include "third_party/WebKit/public/platform/WebVector.h"
24 #include "third_party/WebKit/public/web/WebPluginParams.h"
27 #if !defined(DISABLE_NACL)
28 using blink::WebPluginParams
;
29 using blink::WebString
;
30 using blink::WebVector
;
33 using content::WebPluginInfo
;
34 using content::WebPluginMimeType
;
38 #if !defined(DISABLE_NACL)
39 const bool kNaClRestricted
= false;
40 const bool kNaClUnrestricted
= true;
41 const bool kExtensionRestricted
= false;
42 const bool kExtensionUnrestricted
= true;
43 const bool kExtensionNotFromWebStore
= false;
44 const bool kExtensionFromWebStore
= true;
47 #if defined(ENABLE_EXTENSIONS)
48 const bool kNotHostedApp
= false;
49 const bool kHostedApp
= true;
52 #if !defined(DISABLE_NACL)
53 const char kExtensionUrl
[] = "chrome-extension://extension_id/background.html";
55 const char kPhotosAppURL1
[] = "https://foo.plus.google.com";
56 const char kPhotosAppURL2
[] = "https://foo.plus.sandbox.google.com";
57 const char kPhotosManifestURL1
[] = "https://ssl.gstatic.com/s2/oz/nacl/foo";
58 const char kPhotosManifestURL2
[] = "https://ssl.gstatic.com/photos/nacl/foo";
59 const char kChatManifestFS1
[] =
60 "filesystem:https://foo.talkgadget.google.com/foo";
61 const char kChatManifestFS2
[] = "filesystem:https://foo.plus.google.com/foo";
62 const char kChatManifestFS3
[] =
63 "filesystem:https://foo.plus.sandbox.google.com/foo";
66 const char kChatAppURL1
[] = "https://foo.talkgadget.google.com/hangouts/foo";
67 const char kChatAppURL2
[] = "https://foo.plus.google.com/hangouts/foo";
68 const char kChatAppURL3
[] = "https://foo.plus.sandbox.google.com/hangouts/foo";
70 #if !defined(DISABLE_NACL)
71 bool AllowsDevInterfaces(const WebPluginParams
& params
) {
72 for (size_t i
= 0; i
< params
.attributeNames
.size(); ++i
) {
73 if (params
.attributeNames
[i
] == WebString::fromUTF8("@dev"))
79 void AddFakeDevAttribute(WebPluginParams
* params
) {
80 WebVector
<WebString
> names(static_cast<size_t>(1));
81 WebVector
<WebString
> values(static_cast<size_t>(1));
82 names
[0] = WebString::fromUTF8("@dev");
83 values
[0] = WebString();
84 params
->attributeNames
.swap(names
);
85 params
->attributeValues
.swap(values
);
89 void AddContentTypeHandler(content::WebPluginInfo
* info
,
90 const char* mime_type
,
91 const char* manifest_url
) {
92 content::WebPluginMimeType mime_type_info
;
93 mime_type_info
.mime_type
= mime_type
;
94 mime_type_info
.additional_param_names
.push_back(base::UTF8ToUTF16("nacl"));
95 mime_type_info
.additional_param_values
.push_back(
96 base::UTF8ToUTF16(manifest_url
));
97 info
->mime_types
.push_back(mime_type_info
);
102 typedef testing::Test ChromeContentRendererClientTest
;
105 #if defined(ENABLE_EXTENSIONS)
106 scoped_refptr
<const extensions::Extension
> CreateTestExtension(
107 bool is_unrestricted
, bool is_from_webstore
, bool is_hosted_app
,
108 const std::string
& app_url
) {
109 extensions::Manifest::Location location
= is_unrestricted
?
110 extensions::Manifest::UNPACKED
:
111 extensions::Manifest::INTERNAL
;
112 int flags
= is_from_webstore
?
113 extensions::Extension::FROM_WEBSTORE
:
114 extensions::Extension::NO_FLAGS
;
116 base::DictionaryValue manifest
;
117 manifest
.SetString("name", "NaCl Extension");
118 manifest
.SetString("version", "1");
119 manifest
.SetInteger("manifest_version", 2);
121 base::ListValue
* url_list
= new base::ListValue();
122 url_list
->Append(new base::StringValue(app_url
));
123 manifest
.Set(extensions::manifest_keys::kWebURLs
, url_list
);
124 manifest
.SetString(extensions::manifest_keys::kLaunchWebURL
, app_url
);
127 return extensions::Extension::Create(base::FilePath(), location
, manifest
,
131 scoped_refptr
<const extensions::Extension
> CreateExtension(
132 bool is_unrestricted
, bool is_from_webstore
) {
133 return CreateTestExtension(
134 is_unrestricted
, is_from_webstore
, kNotHostedApp
, std::string());
137 scoped_refptr
<const extensions::Extension
> CreateHostedApp(
138 bool is_unrestricted
, bool is_from_webstore
, const std::string
& app_url
) {
139 return CreateTestExtension(is_unrestricted
, is_from_webstore
, kHostedApp
,
142 #endif // defined(ENABLE_EXTENSIONS)
144 TEST_F(ChromeContentRendererClientTest
, NaClRestriction
) {
145 // Unknown content types have no NaCl module.
149 ChromeContentRendererClient::GetNaClContentHandlerURL(
150 "application/x-foo", info
));
152 // Known content types have a NaCl module.
155 AddContentTypeHandler(&info
, "application/x-foo", "www.foo.com");
156 EXPECT_EQ(GURL("www.foo.com"),
157 ChromeContentRendererClient::GetNaClContentHandlerURL(
158 "application/x-foo", info
));
160 #if !defined(DISABLE_NACL)
161 // --enable-nacl allows all NaCl apps, with 'dev' interfaces.
163 WebPluginParams params
;
164 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
168 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
170 EXPECT_TRUE(AllowsDevInterfaces(params
));
172 // Unrestricted extensions are allowed without --enable-nacl, with 'dev'
173 // interfaces if called from an extension url.
175 WebPluginParams params
;
176 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
180 CreateExtension(kExtensionUnrestricted
, kExtensionNotFromWebStore
)
183 EXPECT_TRUE(AllowsDevInterfaces(params
));
185 // CWS extensions are allowed without --enable-nacl, without 'dev'
186 // interfaces if called from an extension url.
188 WebPluginParams params
;
189 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
193 CreateExtension(kExtensionRestricted
, kExtensionFromWebStore
).get(),
195 EXPECT_FALSE(AllowsDevInterfaces(params
));
197 // CWS extensions can't get 'dev' interfaces with --enable-nacl.
199 WebPluginParams params
;
200 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
204 CreateExtension(kExtensionRestricted
, kExtensionFromWebStore
).get(),
206 EXPECT_FALSE(AllowsDevInterfaces(params
));
208 // CWS extensions can't get 'dev' interfaces by injecting a fake
211 WebPluginParams params
;
212 AddFakeDevAttribute(¶ms
);
213 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
217 CreateExtension(kExtensionRestricted
, kExtensionFromWebStore
).get(),
219 EXPECT_FALSE(AllowsDevInterfaces(params
));
221 // The NaCl PDF extension is allowed without --enable-nacl, with 'dev'
222 // interfaces, from all URLs.
224 WebPluginParams params
;
225 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
226 GURL("chrome-extension://acadkphlmlegjaadjagenfimbpphcgnh"),
229 CreateExtension(kExtensionRestricted
, kExtensionFromWebStore
).get(),
231 EXPECT_TRUE(AllowsDevInterfaces(params
));
233 // Whitelisted URLs are allowed without --enable-nacl, without 'dev'
234 // interfaces. There is a whitelist for the app URL and the manifest URL.
236 WebPluginParams params
;
237 // Whitelisted Photos app is allowed (two app URLs, two manifest URLs)
238 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
239 GURL(kPhotosManifestURL1
),
240 GURL(kPhotosAppURL1
),
242 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
244 EXPECT_FALSE(AllowsDevInterfaces(params
));
245 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
246 GURL(kPhotosManifestURL1
),
247 GURL(kPhotosAppURL2
),
249 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
251 EXPECT_FALSE(AllowsDevInterfaces(params
));
252 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
253 GURL(kPhotosManifestURL2
),
254 GURL(kPhotosAppURL1
),
256 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
258 EXPECT_FALSE(AllowsDevInterfaces(params
));
259 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
260 GURL(kPhotosManifestURL2
),
261 GURL(kPhotosAppURL2
),
263 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
265 EXPECT_FALSE(AllowsDevInterfaces(params
));
266 // Whitelisted Chat app is allowed.
267 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
268 GURL(kChatManifestFS1
),
271 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
273 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
274 GURL(kChatManifestFS2
),
277 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
279 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
280 GURL(kChatManifestFS3
),
283 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
286 // Whitelisted manifest URL, bad app URLs, NOT allowed.
287 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
288 GURL(kPhotosManifestURL1
),
289 GURL("http://plus.google.com/foo"), // http scheme
291 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
293 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
294 GURL(kPhotosManifestURL1
),
295 GURL("http://plus.sandbox.google.com/foo"), // http scheme
297 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
299 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
300 GURL(kPhotosManifestURL1
),
301 GURL("https://plus.google.evil.com/foo"), // bad host
303 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
305 // Whitelisted app URL, bad manifest URL, NOT allowed.
306 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
307 GURL("http://ssl.gstatic.com/s2/oz/nacl/foo"), // http scheme
308 GURL(kPhotosAppURL1
),
310 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
312 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
313 GURL("https://ssl.gstatic.evil.com/s2/oz/nacl/foo"), // bad host
314 GURL(kPhotosAppURL1
),
316 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
318 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
319 GURL("https://ssl.gstatic.com/wrong/s2/oz/nacl/foo"), // bad path
320 GURL(kPhotosAppURL1
),
322 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
325 // Whitelisted URLs can't get 'dev' interfaces with --enable-nacl.
327 WebPluginParams params
;
328 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
329 GURL(kPhotosManifestURL1
),
330 GURL(kPhotosAppURL1
),
332 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
334 EXPECT_FALSE(AllowsDevInterfaces(params
));
336 // Whitelisted URLs can't get 'dev' interfaces by injecting a fake
339 WebPluginParams params
;
340 AddFakeDevAttribute(¶ms
);
341 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
342 GURL(kPhotosManifestURL1
),
343 GURL(kPhotosAppURL1
),
345 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
347 EXPECT_FALSE(AllowsDevInterfaces(params
));
349 // Non-whitelisted URLs are blocked without --enable-nacl.
351 WebPluginParams params
;
352 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
354 GURL("https://plus.google.com.evil.com/foo1"),
356 CreateExtension(kExtensionRestricted
, kExtensionNotFromWebStore
).get(),
358 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
360 GURL("https://plus.google.com.evil.com/foo2"),
362 CreateExtension(kExtensionRestricted
, kExtensionFromWebStore
).get(),
364 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
366 GURL("https://talkgadget.google.com.evil.com/foo3"),
368 CreateExtension(kExtensionUnrestricted
, kExtensionNotFromWebStore
)
371 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
373 GURL("https://talkgadget.google.com.evil.com/foo4"),
375 CreateExtension(kExtensionUnrestricted
, kExtensionFromWebStore
).get(),
378 // Non chrome-extension:// URLs belonging to hosted apps are allowed.
380 WebPluginParams params
;
381 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
383 GURL("http://example.com/test.html"),
385 CreateHostedApp(kExtensionRestricted
,
386 kExtensionNotFromWebStore
,
387 "http://example.com/").get(),
389 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
391 GURL("http://example.evil.com/test.html"),
393 CreateHostedApp(kExtensionRestricted
,
394 kExtensionNotFromWebStore
,
395 "http://example.com/").get(),
398 #endif // !defined(DISABLE_NACL)
401 TEST_F(ChromeContentRendererClientTest
, AllowPepperMediaStreamAPI
) {
402 ChromeContentRendererClient test
;
403 #if !defined(OS_ANDROID)
404 EXPECT_TRUE(test
.AllowPepperMediaStreamAPI(GURL(kChatAppURL1
)));
405 EXPECT_TRUE(test
.AllowPepperMediaStreamAPI(GURL(kChatAppURL2
)));
406 EXPECT_TRUE(test
.AllowPepperMediaStreamAPI(GURL(kChatAppURL3
)));
408 EXPECT_FALSE(test
.AllowPepperMediaStreamAPI(GURL(kChatAppURL1
)));
409 EXPECT_FALSE(test
.AllowPepperMediaStreamAPI(GURL(kChatAppURL2
)));
410 EXPECT_FALSE(test
.AllowPepperMediaStreamAPI(GURL(kChatAppURL3
)));
412 EXPECT_FALSE(test
.AllowPepperMediaStreamAPI(
413 GURL("http://talkgadget.google.com/hangouts/foo")));
414 EXPECT_FALSE(test
.AllowPepperMediaStreamAPI(
415 GURL("https://talkgadget.evil.com/hangouts/foo")));
418 TEST_F(ChromeContentRendererClientTest
, ShouldSuppressErrorPage
) {
419 ChromeContentRendererClient client
;
420 client
.search_bouncer_
.reset(new SearchBouncer
);
421 client
.search_bouncer_
->OnSetSearchURLs(
422 std::vector
<GURL
>(), GURL("http://example.com/n"));
423 EXPECT_FALSE(client
.ShouldSuppressErrorPage(NULL
,
424 GURL("http://example.com")));
425 EXPECT_TRUE(client
.ShouldSuppressErrorPage(NULL
,
426 GURL("http://example.com/n")));