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/common/extensions/extension.h"
11 #include "chrome/common/extensions/extension_builder.h"
12 #include "chrome/renderer/searchbox/search_bouncer.h"
13 #include "content/public/common/webplugininfo.h"
14 #include "extensions/common/manifest_constants.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/WebKit/public/platform/WebString.h"
17 #include "third_party/WebKit/public/platform/WebVector.h"
18 #include "third_party/WebKit/public/web/WebPluginParams.h"
21 using WebKit::WebPluginParams;
22 using WebKit::WebString;
23 using WebKit::WebVector;
24 using chrome::ChromeContentRendererClient;
25 using content::WebPluginInfo;
26 using content::WebPluginMimeType;
31 const bool kNaClRestricted = false;
32 const bool kNaClUnrestricted = true;
33 const bool kExtensionRestricted = false;
34 const bool kExtensionUnrestricted = true;
35 const bool kExtensionNotFromWebStore = false;
36 const bool kExtensionFromWebStore = true;
37 const bool kNotHostedApp = false;
38 const bool kHostedApp = true;
40 const char kExtensionUrl[] = "chrome-extension://extension_id/background.html";
42 const char kPhotosAppURL1[] = "https://foo.plus.google.com";
43 const char kPhotosAppURL2[] = "https://foo.plus.sandbox.google.com";
44 const char kPhotosManifestURL1[] = "https://ssl.gstatic.com/s2/oz/nacl/foo";
45 const char kPhotosManifestURL2[] = "https://ssl.gstatic.com/photos/nacl/foo";
47 const char kChatAppURL1[] = "https://foo.talkgadget.google.com";
48 const char kChatAppURL2[] = "https://foo.talk.google.com";
49 const char kChatManifestURL[] = "https://ssl.gstatic.com/chat/apps/fx";
51 bool AllowsDevInterfaces(const WebPluginParams& params) {
52 for (size_t i = 0; i < params.attributeNames.size(); ++i) {
53 if (params.attributeNames[i] == WebString::fromUTF8("@dev"))
59 void AddFakeDevAttribute(WebPluginParams* params) {
60 WebVector<WebString> names(static_cast<size_t>(1));
61 WebVector<WebString> values(static_cast<size_t>(1));
62 names[0] = WebString::fromUTF8("@dev");
63 values[0] = WebString();
64 params->attributeNames.swap(names);
65 params->attributeValues.swap(values);
68 void AddContentTypeHandler(content::WebPluginInfo* info,
69 const char* mime_type,
70 const char* manifest_url) {
71 content::WebPluginMimeType mime_type_info;
72 mime_type_info.mime_type = mime_type;
73 mime_type_info.additional_param_names.push_back(UTF8ToUTF16("nacl"));
74 mime_type_info.additional_param_values.push_back(
75 UTF8ToUTF16(manifest_url));
76 info->mime_types.push_back(mime_type_info);
80 typedef testing::Test ChromeContentRendererClientTest;
83 scoped_refptr<const extensions::Extension> CreateTestExtension(
84 bool is_unrestricted, bool is_from_webstore, bool is_hosted_app,
85 const std::string& app_url) {
86 extensions::Manifest::Location location = is_unrestricted ?
87 extensions::Manifest::UNPACKED :
88 extensions::Manifest::INTERNAL;
89 int flags = is_from_webstore ?
90 extensions::Extension::FROM_WEBSTORE:
91 extensions::Extension::NO_FLAGS;
93 base::DictionaryValue manifest;
94 manifest.SetString("name", "NaCl Extension");
95 manifest.SetString("version", "1");
96 manifest.SetInteger("manifest_version", 2);
98 base::ListValue* url_list = new base::ListValue();
99 url_list->Append(base::Value::CreateStringValue(app_url));
100 manifest.Set(extensions::manifest_keys::kWebURLs, url_list);
101 manifest.SetString(extensions::manifest_keys::kLaunchWebURL, app_url);
104 return extensions::Extension::Create(base::FilePath(), location, manifest,
108 scoped_refptr<const extensions::Extension> CreateExtension(
109 bool is_unrestricted, bool is_from_webstore) {
110 return CreateTestExtension(
111 is_unrestricted, is_from_webstore, kNotHostedApp, std::string());
114 scoped_refptr<const extensions::Extension> CreateHostedApp(
115 bool is_unrestricted, bool is_from_webstore, const std::string& app_url) {
116 return CreateTestExtension(is_unrestricted, is_from_webstore, kHostedApp,
120 TEST_F(ChromeContentRendererClientTest, NaClRestriction) {
121 // Unknown content types have no NaCl module.
125 ChromeContentRendererClient::GetNaClContentHandlerURL(
126 "application/x-foo", info));
128 // Known content types have a NaCl module.
131 AddContentTypeHandler(&info, "application/x-foo", "www.foo.com");
132 EXPECT_EQ(GURL("www.foo.com"),
133 ChromeContentRendererClient::GetNaClContentHandlerURL(
134 "application/x-foo", info));
136 // --enable-nacl allows all NaCl apps, with 'dev' interfaces.
138 WebPluginParams params;
139 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
143 CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
145 EXPECT_TRUE(AllowsDevInterfaces(params));
147 // Unrestricted extensions are allowed without --enable-nacl, with 'dev'
148 // interfaces if called from an extension url.
150 WebPluginParams params;
151 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
155 CreateExtension(kExtensionUnrestricted, kExtensionNotFromWebStore)
158 EXPECT_TRUE(AllowsDevInterfaces(params));
160 // CWS extensions are allowed without --enable-nacl, without 'dev'
161 // interfaces if called from an extension url.
163 WebPluginParams params;
164 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
168 CreateExtension(kExtensionRestricted, kExtensionFromWebStore).get(),
170 EXPECT_FALSE(AllowsDevInterfaces(params));
172 // CWS extensions can't get 'dev' interfaces with --enable-nacl.
174 WebPluginParams params;
175 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
179 CreateExtension(kExtensionRestricted, kExtensionFromWebStore).get(),
181 EXPECT_FALSE(AllowsDevInterfaces(params));
183 // CWS extensions can't get 'dev' interfaces by injecting a fake
186 WebPluginParams params;
187 AddFakeDevAttribute(¶ms);
188 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
192 CreateExtension(kExtensionRestricted, kExtensionFromWebStore).get(),
194 EXPECT_FALSE(AllowsDevInterfaces(params));
196 // The NaCl PDF extension is allowed without --enable-nacl, with 'dev'
197 // interfaces, from all URLs.
199 WebPluginParams params;
200 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
201 GURL("chrome-extension://acadkphlmlegjaadjagenfimbpphcgnh"),
204 CreateExtension(kExtensionRestricted, kExtensionFromWebStore).get(),
206 EXPECT_TRUE(AllowsDevInterfaces(params));
208 // Whitelisted URLs are allowed without --enable-nacl, without 'dev'
209 // interfaces. There is a whitelist for the app URL and the manifest URL.
211 WebPluginParams params;
212 // Whitelisted Photos app is allowed (two app URLs, two manifest URLs)
213 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
214 GURL(kPhotosManifestURL1),
215 GURL(kPhotosAppURL1),
217 CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
219 EXPECT_FALSE(AllowsDevInterfaces(params));
220 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
221 GURL(kPhotosManifestURL1),
222 GURL(kPhotosAppURL2),
224 CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
226 EXPECT_FALSE(AllowsDevInterfaces(params));
227 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
228 GURL(kPhotosManifestURL2),
229 GURL(kPhotosAppURL1),
231 CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
233 EXPECT_FALSE(AllowsDevInterfaces(params));
234 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
235 GURL(kPhotosManifestURL2),
236 GURL(kPhotosAppURL2),
238 CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
240 EXPECT_FALSE(AllowsDevInterfaces(params));
241 // Whitelisted Chat app is allowed.
242 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
243 GURL(kChatManifestURL),
246 CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
248 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
249 GURL(kChatManifestURL),
252 CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
255 // Whitelisted manifest URL, bad app URLs, NOT allowed.
256 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
257 GURL(kPhotosManifestURL1),
258 GURL("http://plus.google.com/foo"), // http scheme
260 CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
262 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
263 GURL(kPhotosManifestURL1),
264 GURL("http://plus.sandbox.google.com/foo"), // http scheme
266 CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
268 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
269 GURL(kPhotosManifestURL1),
270 GURL("https://plus.google.evil.com/foo"), // bad host
272 CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
274 // Whitelisted app URL, bad manifest URL, NOT allowed.
275 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
276 GURL("http://ssl.gstatic.com/s2/oz/nacl/foo"), // http scheme
277 GURL(kPhotosAppURL1),
279 CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
281 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
282 GURL("https://ssl.gstatic.evil.com/s2/oz/nacl/foo"), // bad host
283 GURL(kPhotosAppURL1),
285 CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
287 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
288 GURL("https://ssl.gstatic.com/wrong/s2/oz/nacl/foo"), // bad path
289 GURL(kPhotosAppURL1),
291 CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
294 // Whitelisted URLs can't get 'dev' interfaces with --enable-nacl.
296 WebPluginParams params;
297 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
298 GURL(kPhotosManifestURL1),
299 GURL(kPhotosAppURL1),
301 CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
303 EXPECT_FALSE(AllowsDevInterfaces(params));
305 // Whitelisted URLs can't get 'dev' interfaces by injecting a fake
308 WebPluginParams params;
309 AddFakeDevAttribute(¶ms);
310 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
311 GURL(kPhotosManifestURL1),
312 GURL(kPhotosAppURL1),
314 CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
316 EXPECT_FALSE(AllowsDevInterfaces(params));
318 // Non-whitelisted URLs are blocked without --enable-nacl.
320 WebPluginParams params;
321 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
323 GURL("https://plus.google.com.evil.com/foo1"),
325 CreateExtension(kExtensionRestricted, kExtensionNotFromWebStore).get(),
327 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
329 GURL("https://plus.google.com.evil.com/foo2"),
331 CreateExtension(kExtensionRestricted, kExtensionFromWebStore).get(),
333 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
335 GURL("https://talkgadget.google.com.evil.com/foo3"),
337 CreateExtension(kExtensionUnrestricted, kExtensionNotFromWebStore)
340 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
342 GURL("https://talkgadget.google.com.evil.com/foo4"),
344 CreateExtension(kExtensionUnrestricted, kExtensionFromWebStore).get(),
347 // Non chrome-extension:// URLs belonging to hosted apps are allowed.
349 WebPluginParams params;
350 EXPECT_TRUE(ChromeContentRendererClient::IsNaClAllowed(
352 GURL("http://example.com/test.html"),
354 CreateHostedApp(kExtensionRestricted,
355 kExtensionNotFromWebStore,
356 "http://example.com/").get(),
358 EXPECT_FALSE(ChromeContentRendererClient::IsNaClAllowed(
360 GURL("http://example.evil.com/test.html"),
362 CreateHostedApp(kExtensionRestricted,
363 kExtensionNotFromWebStore,
364 "http://example.com/").get(),
369 TEST_F(ChromeContentRendererClientTest, AllowPepperMediaStreamAPI) {
370 ChromeContentRendererClient test;
371 #if !defined(OS_ANDROID)
372 EXPECT_TRUE(test.AllowPepperMediaStreamAPI(GURL(kChatAppURL1)));
373 EXPECT_TRUE(test.AllowPepperMediaStreamAPI(GURL(kChatAppURL2)));
375 EXPECT_FALSE(test.AllowPepperMediaStreamAPI(GURL(kChatAppURL1)));
376 EXPECT_FALSE(test.AllowPepperMediaStreamAPI(GURL(kChatAppURL2)));
378 EXPECT_FALSE(test.AllowPepperMediaStreamAPI(
379 GURL("http://talkgadget.google.com")));
380 EXPECT_FALSE(test.AllowPepperMediaStreamAPI(
381 GURL("https://talkgadget.evil.com")));
384 TEST_F(ChromeContentRendererClientTest, ShouldSuppressErrorPage) {
385 ChromeContentRendererClient client;
386 client.search_bouncer_.reset(new SearchBouncer);
387 client.search_bouncer_->OnSetSearchURLs(
388 std::vector<GURL>(), GURL("http://example.com/n"));
389 EXPECT_FALSE(client.ShouldSuppressErrorPage(GURL("http://example.com")));
390 EXPECT_TRUE(client.ShouldSuppressErrorPage(GURL("http://example.com/n")));
393 } // namespace chrome