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 kExtensionNotFromWebStore
= false;
42 const bool kExtensionFromWebStore
= true;
45 #if defined(ENABLE_EXTENSIONS)
46 const bool kNotHostedApp
= false;
47 const bool kHostedApp
= true;
50 #if !defined(DISABLE_NACL)
51 const char kExtensionUrl
[] = "chrome-extension://extension_id/background.html";
53 const char kPhotosAppURL1
[] = "https://foo.plus.google.com";
54 const char kPhotosAppURL2
[] = "https://foo.plus.sandbox.google.com";
55 const char kPhotosManifestURL1
[] = "https://ssl.gstatic.com/s2/oz/nacl/foo";
56 const char kPhotosManifestURL2
[] = "https://ssl.gstatic.com/photos/nacl/foo";
57 const char kChatManifestFS1
[] =
58 "filesystem:https://foo.talkgadget.google.com/foo";
59 const char kChatManifestFS2
[] = "filesystem:https://foo.plus.google.com/foo";
60 const char kChatManifestFS3
[] =
61 "filesystem:https://foo.plus.sandbox.google.com/foo";
64 const char kChatAppURL1
[] = "https://foo.talkgadget.google.com/hangouts/foo";
65 const char kChatAppURL2
[] = "https://foo.plus.google.com/hangouts/foo";
66 const char kChatAppURL3
[] = "https://foo.plus.sandbox.google.com/hangouts/foo";
68 #if !defined(DISABLE_NACL)
69 bool AllowsDevInterfaces(const WebPluginParams
& params
) {
70 for (size_t i
= 0; i
< params
.attributeNames
.size(); ++i
) {
71 if (params
.attributeNames
[i
] == WebString::fromUTF8("@dev"))
77 void AddFakeDevAttribute(WebPluginParams
* params
) {
78 WebVector
<WebString
> names(static_cast<size_t>(1));
79 WebVector
<WebString
> values(static_cast<size_t>(1));
80 names
[0] = WebString::fromUTF8("@dev");
81 values
[0] = WebString();
82 params
->attributeNames
.swap(names
);
83 params
->attributeValues
.swap(values
);
87 void AddContentTypeHandler(content::WebPluginInfo
* info
,
88 const char* mime_type
,
89 const char* manifest_url
) {
90 content::WebPluginMimeType mime_type_info
;
91 mime_type_info
.mime_type
= mime_type
;
92 mime_type_info
.additional_param_names
.push_back(base::UTF8ToUTF16("nacl"));
93 mime_type_info
.additional_param_values
.push_back(
94 base::UTF8ToUTF16(manifest_url
));
95 info
->mime_types
.push_back(mime_type_info
);
100 typedef testing::Test ChromeContentRendererClientTest
;
103 #if defined(ENABLE_EXTENSIONS)
104 scoped_refptr
<const extensions::Extension
> CreateTestExtension(
105 extensions::Manifest::Location location
, bool is_from_webstore
,
106 bool is_hosted_app
, const std::string
& app_url
) {
107 int flags
= is_from_webstore
?
108 extensions::Extension::FROM_WEBSTORE
:
109 extensions::Extension::NO_FLAGS
;
111 base::DictionaryValue manifest
;
112 manifest
.SetString("name", "NaCl Extension");
113 manifest
.SetString("version", "1");
114 manifest
.SetInteger("manifest_version", 2);
116 base::ListValue
* url_list
= new base::ListValue();
117 url_list
->Append(new base::StringValue(app_url
));
118 manifest
.Set(extensions::manifest_keys::kWebURLs
, url_list
);
119 manifest
.SetString(extensions::manifest_keys::kLaunchWebURL
, app_url
);
122 return extensions::Extension::Create(base::FilePath(), location
, manifest
,
126 scoped_refptr
<const extensions::Extension
> CreateExtension(
127 bool is_from_webstore
) {
128 return CreateTestExtension(
129 extensions::Manifest::INTERNAL
, is_from_webstore
, kNotHostedApp
,
133 scoped_refptr
<const extensions::Extension
> CreateExtensionWithLocation(
134 extensions::Manifest::Location location
, bool is_from_webstore
) {
135 return CreateTestExtension(
136 location
, is_from_webstore
, kNotHostedApp
, std::string());
139 scoped_refptr
<const extensions::Extension
> CreateHostedApp(
140 bool is_from_webstore
, const std::string
& app_url
) {
141 return CreateTestExtension(extensions::Manifest::INTERNAL
,
146 #endif // defined(ENABLE_EXTENSIONS)
148 TEST_F(ChromeContentRendererClientTest
, NaClRestriction
) {
149 // Unknown content types have no NaCl module.
153 ChromeContentRendererClient::GetNaClContentHandlerURL(
154 "application/x-foo", info
));
156 // Known content types have a NaCl module.
159 AddContentTypeHandler(&info
, "application/x-foo", "www.foo.com");
160 EXPECT_EQ(GURL("www.foo.com"),
161 ChromeContentRendererClient::GetNaClContentHandlerURL(
162 "application/x-foo", info
));
164 #if !defined(DISABLE_NACL)
165 // --enable-nacl allows all NaCl apps, with 'dev' interfaces.
167 WebPluginParams params
;
168 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
172 CreateExtension(kExtensionNotFromWebStore
).get(),
174 EXPECT_TRUE(AllowsDevInterfaces(params
));
176 // Unpacked extensions are allowed without --enable-nacl, with
179 WebPluginParams params
;
180 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
184 CreateExtensionWithLocation(extensions::Manifest::UNPACKED
,
185 kExtensionNotFromWebStore
).get(),
187 EXPECT_TRUE(AllowsDevInterfaces(params
));
189 // Component extensions are allowed without --enable-nacl, with
192 WebPluginParams params
;
193 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
197 CreateExtensionWithLocation(extensions::Manifest::COMPONENT
,
198 kExtensionNotFromWebStore
).get(),
200 EXPECT_TRUE(AllowsDevInterfaces(params
));
203 WebPluginParams params
;
204 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
208 CreateExtensionWithLocation(extensions::Manifest::EXTERNAL_COMPONENT
,
209 kExtensionNotFromWebStore
).get(),
211 EXPECT_TRUE(AllowsDevInterfaces(params
));
213 // Extensions that are force installed by policy are allowed without
214 // --enable-nacl, without 'dev' interfaces.
216 WebPluginParams params
;
217 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
221 CreateExtensionWithLocation(extensions::Manifest::EXTERNAL_POLICY
,
222 kExtensionNotFromWebStore
).get(),
224 EXPECT_FALSE(AllowsDevInterfaces(params
));
225 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
229 CreateExtensionWithLocation(
230 extensions::Manifest::EXTERNAL_POLICY_DOWNLOAD
,
231 kExtensionNotFromWebStore
).get(),
233 EXPECT_FALSE(AllowsDevInterfaces(params
));
235 // CWS extensions are allowed without --enable-nacl, without 'dev'
236 // interfaces if called from an extension url.
238 WebPluginParams params
;
239 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
243 CreateExtension(kExtensionFromWebStore
).get(),
245 EXPECT_FALSE(AllowsDevInterfaces(params
));
247 // CWS extensions can't get 'dev' interfaces with --enable-nacl.
249 WebPluginParams params
;
250 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
254 CreateExtension(kExtensionFromWebStore
).get(),
256 EXPECT_FALSE(AllowsDevInterfaces(params
));
258 // CWS extensions can't get 'dev' interfaces by injecting a fake
261 WebPluginParams params
;
262 AddFakeDevAttribute(¶ms
);
263 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
267 CreateExtension(kExtensionFromWebStore
).get(),
269 EXPECT_FALSE(AllowsDevInterfaces(params
));
272 // Whitelisted URLs are allowed without --enable-nacl, without 'dev'
273 // interfaces. There is a whitelist for the app URL and the manifest URL.
275 WebPluginParams params
;
276 // Whitelisted Photos app is allowed (two app URLs, two manifest URLs)
277 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
278 GURL(kPhotosManifestURL1
),
279 GURL(kPhotosAppURL1
),
283 EXPECT_FALSE(AllowsDevInterfaces(params
));
284 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
285 GURL(kPhotosManifestURL1
),
286 GURL(kPhotosAppURL2
),
290 EXPECT_FALSE(AllowsDevInterfaces(params
));
291 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
292 GURL(kPhotosManifestURL2
),
293 GURL(kPhotosAppURL1
),
297 EXPECT_FALSE(AllowsDevInterfaces(params
));
298 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
299 GURL(kPhotosManifestURL2
),
300 GURL(kPhotosAppURL2
),
304 EXPECT_FALSE(AllowsDevInterfaces(params
));
305 // Whitelisted Chat app is allowed.
306 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
307 GURL(kChatManifestFS1
),
312 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
313 GURL(kChatManifestFS2
),
318 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
319 GURL(kChatManifestFS3
),
325 // Whitelisted manifest URL, bad app URLs, NOT allowed.
326 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
327 GURL(kPhotosManifestURL1
),
328 GURL("http://plus.google.com/foo"), // http scheme
332 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
333 GURL(kPhotosManifestURL1
),
334 GURL("http://plus.sandbox.google.com/foo"), // http scheme
338 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
339 GURL(kPhotosManifestURL1
),
340 GURL("https://plus.google.evil.com/foo"), // bad host
344 // Whitelisted app URL, bad manifest URL, NOT allowed.
345 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
346 GURL("http://ssl.gstatic.com/s2/oz/nacl/foo"), // http scheme
347 GURL(kPhotosAppURL1
),
351 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
352 GURL("https://ssl.gstatic.evil.com/s2/oz/nacl/foo"), // bad host
353 GURL(kPhotosAppURL1
),
357 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
358 GURL("https://ssl.gstatic.com/wrong/s2/oz/nacl/foo"), // bad path
359 GURL(kPhotosAppURL1
),
364 // Whitelisted URLs can't get 'dev' interfaces with --enable-nacl.
366 WebPluginParams params
;
367 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
368 GURL(kPhotosManifestURL1
),
369 GURL(kPhotosAppURL1
),
373 EXPECT_FALSE(AllowsDevInterfaces(params
));
375 // Whitelisted URLs can't get 'dev' interfaces by injecting a fake
378 WebPluginParams params
;
379 AddFakeDevAttribute(¶ms
);
380 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
381 GURL(kPhotosManifestURL1
),
382 GURL(kPhotosAppURL1
),
386 EXPECT_FALSE(AllowsDevInterfaces(params
));
388 // Non-whitelisted URLs are blocked without --enable-nacl.
390 WebPluginParams params
;
391 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
393 GURL("https://plus.google.com.evil.com/foo1"),
398 // Non chrome-extension:// URLs belonging to hosted apps are allowed for
399 // webstore installed hosted apps.
401 WebPluginParams params
;
402 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
404 GURL("http://example.com/test.html"),
406 CreateHostedApp(kExtensionFromWebStore
,
407 "http://example.com/").get(),
409 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
411 GURL("http://example.com/test.html"),
413 CreateHostedApp(kExtensionNotFromWebStore
,
414 "http://example.com/").get(),
416 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
418 GURL("http://example.evil.com/test.html"),
420 CreateHostedApp(kExtensionNotFromWebStore
,
421 "http://example.com/").get(),
424 #endif // !defined(DISABLE_NACL)
427 TEST_F(ChromeContentRendererClientTest
, AllowPepperMediaStreamAPI
) {
428 ChromeContentRendererClient test
;
429 #if !defined(OS_ANDROID)
430 EXPECT_TRUE(test
.AllowPepperMediaStreamAPI(GURL(kChatAppURL1
)));
431 EXPECT_TRUE(test
.AllowPepperMediaStreamAPI(GURL(kChatAppURL2
)));
432 EXPECT_TRUE(test
.AllowPepperMediaStreamAPI(GURL(kChatAppURL3
)));
434 EXPECT_FALSE(test
.AllowPepperMediaStreamAPI(GURL(kChatAppURL1
)));
435 EXPECT_FALSE(test
.AllowPepperMediaStreamAPI(GURL(kChatAppURL2
)));
436 EXPECT_FALSE(test
.AllowPepperMediaStreamAPI(GURL(kChatAppURL3
)));
438 EXPECT_FALSE(test
.AllowPepperMediaStreamAPI(
439 GURL("http://talkgadget.google.com/hangouts/foo")));
440 EXPECT_FALSE(test
.AllowPepperMediaStreamAPI(
441 GURL("https://talkgadget.evil.com/hangouts/foo")));
444 TEST_F(ChromeContentRendererClientTest
, ShouldSuppressErrorPage
) {
445 ChromeContentRendererClient client
;
446 SearchBouncer::GetInstance()->OnSetSearchURLs(
447 std::vector
<GURL
>(), GURL("http://example.com/n"));
448 EXPECT_FALSE(client
.ShouldSuppressErrorPage(nullptr,
449 GURL("http://example.com")));
450 EXPECT_TRUE(client
.ShouldSuppressErrorPage(nullptr,
451 GURL("http://example.com/n")));
452 SearchBouncer::GetInstance()->OnSetSearchURLs(
453 std::vector
<GURL
>(), GURL::EmptyGURL());